From 10908612878a66f56c8bc8fd967c00e14b1a2936 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Fri, 19 Jan 2024 13:00:53 -0800 Subject: [PATCH 01/45] clock app update to radix --- clock_radix/.gitignore | 5 + clock_radix/assets/favicon.ico | Bin 0 -> 4286 bytes clock_radix/clock_radix/__init__.py | 0 clock_radix/clock_radix/clock_radix.py | 225 +++++++++++++++++++++++++ clock_radix/requirements.txt | 2 + clock_radix/rxconfig.py | 5 + 6 files changed, 237 insertions(+) create mode 100644 clock_radix/.gitignore create mode 100644 clock_radix/assets/favicon.ico create mode 100644 clock_radix/clock_radix/__init__.py create mode 100644 clock_radix/clock_radix/clock_radix.py create mode 100644 clock_radix/requirements.txt create mode 100644 clock_radix/rxconfig.py diff --git a/clock_radix/.gitignore b/clock_radix/.gitignore new file mode 100644 index 00000000..f6711845 --- /dev/null +++ b/clock_radix/.gitignore @@ -0,0 +1,5 @@ +*.db +*.py[cod] +.web +__pycache__/ +reflex.db \ No newline at end of file diff --git a/clock_radix/assets/favicon.ico b/clock_radix/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..166ae995eaa63fc96771410a758282dc30e925cf GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 0 HcmV?d00001 diff --git a/clock_radix/clock_radix/__init__.py b/clock_radix/clock_radix/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/clock_radix/clock_radix/clock_radix.py b/clock_radix/clock_radix/clock_radix.py new file mode 100644 index 00000000..d80c3beb --- /dev/null +++ b/clock_radix/clock_radix/clock_radix.py @@ -0,0 +1,225 @@ +"""A Reflex example of a analog clock in Radix.""" + +import asyncio +from datetime import datetime, timezone +from typing import Any + +import reflex as rx +from reflex.components.radix.themes import theme +import reflex.components.radix.themes as rdxt + +import pytz + + + +# The supported time zones. +TIMEZONES = [ + "Asia/Tokyo", + "Australia/Sydney", + "Europe/London", + "Europe/Paris", + "Europe/Moscow", + "US/Pacific", + "US/Eastern", +] +DEFAULT_ZONE = TIMEZONES[-2] + + +def rotate(degrees: int) -> str: + """CSS to rotate a clock hand. + + Args: + degrees: The degrees to rotate the clock hand. + + Returns: + The CSS to rotate the clock hand. + """ + return f"rotate({degrees}deg)" + + +class State(rx.State): + """The app state.""" + + # The time zone to display the clock in. + zone: str = rx.Cookie(DEFAULT_ZONE) + + # Whether the clock is running. + running: bool = False + + # The last updated timestamp + _now: datetime = datetime.fromtimestamp(0) + + @rx.cached_var + def valid_zone(self) -> str: + """Get the current time zone. + + Returns: + The current time zone. + """ + try: + pytz.timezone(self.zone) + except Exception: + return DEFAULT_ZONE + return self.zone + + @rx.cached_var + def time_info(self) -> dict[str, Any]: + """Get the current time info. + + This can also be done as several computed vars, but this is more concise. + + Returns: + A dictionary of the current time info. + """ + now = self._now.astimezone(pytz.timezone(self.valid_zone)) + return { + "hour": now.hour if now.hour <= 12 else now.hour % 12, + "minute": now.minute, + "second": now.second, + "meridiem": "AM" if now.hour < 12 else "PM", + "minute_display": f"{now.minute:02}", + "second_display": f"{now.second:02}", + "hour_rotation": rotate(now.hour * 30 - 90), + "minute_rotation": rotate(now.minute * 0.0167 * 360 - 90), + "second_rotation": rotate(now.second * 0.0167 * 360 - 90), + } + + def on_load(self): + """Switch the clock off when the page refreshes.""" + self.running = False + self.refresh() + + def refresh(self): + """Refresh the clock.""" + self._now = datetime.now(timezone.utc) + + @rx.background + async def tick(self): + """Update the clock every second.""" + while self.running: + async with self: + self.refresh() + + # Sleep for a second. + await asyncio.sleep(1) + + def flip_switch(self, running: bool): + """Start or stop the clock. + + Args: + running: Whether the clock should be running. + """ + # Set the switch state. + self.running = running + + # Start the clock if the switch is on. + if self.running: + return State.tick + + + +def clock_hand(rotation: str, color: str, length: str) -> rx.Component: + """Create a clock hand. + + Args: + rotation: The rotation of the clock hand. + color: The color of the clock hand. + length: The length of the clock hand. + + Returns: + A clock hand component. + """ + # rx.divider before + return rdxt.separator( + transform=rotation, + width=f"{length}em", + position="absolute", + border_style="solid", + border_width="4px", + border_image=f"linear-gradient(to right, rgb(250,250,250) 50%, {color} 100%) 0 0 100% 0", + z_index=0, + ) + + + +def analog_clock() -> rx.Component: + """Create the analog clock.""" + return rx.circle( + # The inner circle. + rx.circle( + width="1em", + height="1em", + border_width="thick", + border_color="#43464B", + z_index=1, + ), + # The clock hands. + clock_hand(State.time_info["hour_rotation"], "black", "16"), + clock_hand(State.time_info["minute_rotation"], "red", "18"), + clock_hand(State.time_info["second_rotation"], "blue", "19"), + border_width="thick", + border_color="#43464B", + width="25em", + height="25em", + bg="rgb(250,250,250)", + box_shadow="dark-lg", + ) + + +def digital_clock() -> rx.Component: + """Create the digital clock.""" + return rx.hstack( + rdxt.heading(State.time_info["hour"], size="8"), + rdxt.heading(":", size="8"), + rdxt.heading(State.time_info["minute_display"], size="8"), + rdxt.heading(":", size="8"), + rdxt.heading(State.time_info["second_display"], size="8"), + rdxt.heading(State.time_info["meridiem"], size="8"), + border_width="medium", + border_color="#43464B", + border_radius="2em", + padding_x="2em", + bg="white", + color="#333", + ) + + +def timezone_select() -> rx.Component: + """Create the timezone select.""" + return rdxt.select( + TIMEZONES, + placeholder="Select a time zone.", + on_value_change=State.set_zone, + value=State.valid_zone, + bg="#white", + width="100%", + size="3", + ) + + +def index(): + """The main view.""" + return rx.center( + rx.vstack( + analog_clock(), + rx.hstack( + digital_clock(), + rdxt.switch(is_checked=State.running, on_checked_change=State.flip_switch), + ), + timezone_select(), + padding="5em", + border_width="medium", + border_color="#43464B", + border_radius="25px", + bg="#ededed", + #bg=accent_color, + text_align="center", + ), + padding="5em", + ) + + + + +app = rx.App(theme=theme(appearance="light", has_background=True, radius="large", accent_color="amber", gray_color="sand",)) +app.add_page(index, title="Clock", on_load=State.on_load) \ No newline at end of file diff --git a/clock_radix/requirements.txt b/clock_radix/requirements.txt new file mode 100644 index 00000000..009fa0e2 --- /dev/null +++ b/clock_radix/requirements.txt @@ -0,0 +1,2 @@ +reflex>=0.3.7 +pytz==2022.7.1 diff --git a/clock_radix/rxconfig.py b/clock_radix/rxconfig.py new file mode 100644 index 00000000..b90ba40b --- /dev/null +++ b/clock_radix/rxconfig.py @@ -0,0 +1,5 @@ +import reflex as rx + +config = rx.Config( + app_name="clock_radix", +) \ No newline at end of file From 278da6da2c6279a3101ed36ac2c8aae8f62f7225 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Fri, 19 Jan 2024 14:18:02 -0800 Subject: [PATCH 02/45] converting nba app to radix --- nba_radix/.gitignore | 4 + nba_radix/assets/favicon.ico | Bin 0 -> 4286 bytes nba_radix/assets/nba.png | Bin 0 -> 14901 bytes nba_radix/nba_radix/__init__.py | 0 nba_radix/nba_radix/helpers.py | 39 ++++++++ nba_radix/nba_radix/nba_radix.py | 150 +++++++++++++++++++++++++++++++ nba_radix/requirements.txt | 1 + nba_radix/rxconfig.py | 5 ++ 8 files changed, 199 insertions(+) create mode 100644 nba_radix/.gitignore create mode 100644 nba_radix/assets/favicon.ico create mode 100644 nba_radix/assets/nba.png create mode 100644 nba_radix/nba_radix/__init__.py create mode 100644 nba_radix/nba_radix/helpers.py create mode 100644 nba_radix/nba_radix/nba_radix.py create mode 100644 nba_radix/requirements.txt create mode 100644 nba_radix/rxconfig.py diff --git a/nba_radix/.gitignore b/nba_radix/.gitignore new file mode 100644 index 00000000..eab0d4b0 --- /dev/null +++ b/nba_radix/.gitignore @@ -0,0 +1,4 @@ +*.db +*.py[cod] +.web +__pycache__/ \ No newline at end of file diff --git a/nba_radix/assets/favicon.ico b/nba_radix/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..166ae995eaa63fc96771410a758282dc30e925cf GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 0 HcmV?d00001 diff --git a/nba_radix/assets/nba.png b/nba_radix/assets/nba.png new file mode 100644 index 0000000000000000000000000000000000000000..004b4ec6859860b63235d4e8eac699a74760bbdd GIT binary patch literal 14901 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 literal 0 HcmV?d00001 diff --git a/nba_radix/nba_radix/__init__.py b/nba_radix/nba_radix/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/nba_radix/nba_radix/helpers.py b/nba_radix/nba_radix/helpers.py new file mode 100644 index 00000000..e3076823 --- /dev/null +++ b/nba_radix/nba_radix/helpers.py @@ -0,0 +1,39 @@ +import reflex as rx +import reflex.components.radix.themes as rdxt + +def navbar(): + return rdxt.box( + rx.hstack( + rx.hstack( + rx.image(src="/nba.png", width="50px"), + rdxt.heading("NBA Data", size="8"), + rdxt.flex( + rdxt.badge("2015-2016 Season"), + ), + ), + rdxt.dropdownmenu_root( + rdxt.dropdownmenu_trigger( + rdxt.button("Menu", color="white", size="3", radius="medium", px=4, py=2), + ), + rdxt.dropdownmenu_content( + rdxt.link(rdxt.dropdownmenu_item("Graph"), href="/"), + rdxt.dropdownmenu_separator(), + rdxt.link( + rdxt.dropdownmenu_item( + rx.hstack(rdxt.text("20Dataset"), rdxt.icon(tag="download")) + ), + href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", + ), + ), + ), + justify="space-between", + border_bottom="0.2em solid #F0F0F0", + padding_x="2em", + padding_y="1em", + bg="rgba(255,255,255, 0.97)", + ), + position="fixed", + width="100%", + top="0px", + z_index="500", + ) \ No newline at end of file diff --git a/nba_radix/nba_radix/nba_radix.py b/nba_radix/nba_radix/nba_radix.py new file mode 100644 index 00000000..327e8567 --- /dev/null +++ b/nba_radix/nba_radix/nba_radix.py @@ -0,0 +1,150 @@ +"""Welcome to Reflex! This file outlines the steps to create a basic app.""" +import reflex as rx +import pandas as pd +import plotly.express as px +import plotly.graph_objects as go +from .helpers import navbar +from reflex.components.radix.themes import theme +import reflex.components.radix.themes as rdxt + +nba_overview = "https://media.geeksforgeeks.org/wp-content/uploads/nba.csv" +nba_data = pd.read_csv(nba_overview) +college = sorted(nba_data["College"].unique().astype(str)) + + +class State(rx.State): + """The app state.""" + + # Filters to apply to the data. + position: str + college: str + age: tuple[int, int] = (18, 50) + salary: tuple[int, int] = (0, 25000000) + + @rx.var + def df(self) -> pd.DataFrame: + """The data.""" + nba = nba_data[ + (nba_data["Age"] > int(self.age[0])) + & (nba_data["Age"] < int(self.age[1])) + & (nba_data["Salary"] > int(self.salary[0])) + & (nba_data["Salary"] < int(self.salary[1])) + ] + + if self.college and self.college != "All": + nba = nba[nba["College"] == self.college] + + if self.position and self.position != "All": + nba = nba[nba["Position"] == self.position] + + if nba.empty: + return pd.DataFrame() + else: + return nba.fillna("") + + @rx.var + def scat_fig(self) -> go.Figure: + """The scatter figure.""" + nba = self.df + + if nba.empty: + return go.Figure() + else: + return px.scatter( + nba, + x="Age", + y="Salary", + title="NBA Age/Salary plot", + color=nba["Position"], + hover_data=["Name"], + symbol=nba["Position"], + trendline="lowess", + trendline_scope="overall", + ) + + @rx.var + def hist_fig(self) -> go.Figure: + """The histogram figure.""" + nba = self.df + + if nba.empty: + return go.Figure() + else: + return px.histogram( + nba, x="Age", y="Salary", title="Age/Salary Distribution" + ) + + +def selection(): + return rx.vstack( + rx.hstack( + rx.vstack( + rdxt.select( + ["C", "PF", "SF", "PG", "SG"], + placeholder="Select a position. (All)", + on_value_change=State.set_position, + size="3", + ), + rdxt.select( + college, + placeholder="Select a college. (All)", + on_value_change=State.set_college, + size="3", + ), + ), + rx.vstack( + rx.vstack( + rx.hstack( + rdxt.badge("Min Age: ", State.age[0]), + rdxt.separator(orientation="vertical"), + rdxt.badge("Max Age: ", State.age[1]), + ), + rdxt.slider(default_value=[18, 50], min=18, max=50, on_value_commit=State.set_age,), + align_items="left", + width="100%", + ), + rx.vstack( + rx.hstack( + rdxt.badge("Min Sal: ", State.salary[0] // 1000000, "M"), + rdxt.separator(orientation="vertical"), + rdxt.badge("Max Sal: ", State.salary[1] // 1000000, "M"), + ), + rdxt.slider( + default_value=[0, 25000000], min=0, max=25000000, on_value_commit=State.set_salary, + ), + align_items="left", + width="100%", + ), + ), + spacing="1em", + ), + width="100%", + ) + + +def index(): + """The main view.""" + return rx.center( + rx.vstack( + navbar(), + selection(), + rdxt.separator(width="100%"), + rx.plotly(data=State.scat_fig, layout={"width": "1000", "height": "600"}), + rx.plotly(data=State.hist_fig, layout={"width": "1000", "height": "600"}), + rx.data_table( + data=nba_data, + pagination=True, + search=True, + sort=True, + resizable=True, + ), + rdxt.separator(width="100%"), + padding_top="6em", + width="100%", + ) + ) + + + +app = rx.App(theme=theme(appearance="light", has_background=True, radius="large", accent_color="amber", gray_color="sand",)) +app.add_page(index, title="NBA App") \ No newline at end of file diff --git a/nba_radix/requirements.txt b/nba_radix/requirements.txt new file mode 100644 index 00000000..9520ecbd --- /dev/null +++ b/nba_radix/requirements.txt @@ -0,0 +1 @@ +reflex==0.3.7 diff --git a/nba_radix/rxconfig.py b/nba_radix/rxconfig.py new file mode 100644 index 00000000..919ea29a --- /dev/null +++ b/nba_radix/rxconfig.py @@ -0,0 +1,5 @@ +import reflex as rx + +config = rx.Config( + app_name="nba_radix", +) \ No newline at end of file From ecf9e3ffd5d4e01b58244714b42c12f56972e019 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Mon, 22 Jan 2024 16:57:00 -0800 Subject: [PATCH 03/45] update dependencies --- nba_radix/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nba_radix/requirements.txt b/nba_radix/requirements.txt index 9520ecbd..fba2e31a 100644 --- a/nba_radix/requirements.txt +++ b/nba_radix/requirements.txt @@ -1 +1 @@ -reflex==0.3.7 +reflex>=0.3.7 From a2e8b53410ca2225bcd98605cb1041afc56b4639 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Mon, 22 Jan 2024 17:01:38 -0800 Subject: [PATCH 04/45] minor clock change --- clock_radix/clock_radix/clock_radix.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clock_radix/clock_radix/clock_radix.py b/clock_radix/clock_radix/clock_radix.py index d80c3beb..7d4e52b4 100644 --- a/clock_radix/clock_radix/clock_radix.py +++ b/clock_radix/clock_radix/clock_radix.py @@ -129,8 +129,7 @@ def clock_hand(rotation: str, color: str, length: str) -> rx.Component: Returns: A clock hand component. """ - # rx.divider before - return rdxt.separator( + return rx.divider( transform=rotation, width=f"{length}em", position="absolute", From 69f47c85810a7b5342c0790dff74682e767c0fc1 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Fri, 26 Jan 2024 12:03:36 -0800 Subject: [PATCH 05/45] update for integration testing --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index c6ee2c1d..85120c85 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,6 +1,6 @@ name: app-harness env: - REFLEX_VERSION: "==0.3.8" + REFLEX_VERSION: "==0.3.9" TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index f1176103..53503b36 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,6 +1,6 @@ name: check-export env: - REFLEX_VERSION: "==0.3.8" + REFLEX_VERSION: "==0.3.9" TELEMETRY_ENABLED: false on: push: From 65b5ca718e56c596e6dc12c4de0c2f8dbf6905a5 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Fri, 26 Jan 2024 12:06:42 -0800 Subject: [PATCH 06/45] update for integration testing --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index c6ee2c1d..85120c85 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,6 +1,6 @@ name: app-harness env: - REFLEX_VERSION: "==0.3.8" + REFLEX_VERSION: "==0.3.9" TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index f1176103..53503b36 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,6 +1,6 @@ name: check-export env: - REFLEX_VERSION: "==0.3.8" + REFLEX_VERSION: "==0.3.9" TELEMETRY_ENABLED: false on: push: From 6a471d0f699a747a42130bc517fe3f23761d04cb Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Fri, 26 Jan 2024 12:12:40 -0800 Subject: [PATCH 07/45] update requirements.txt --- nba_radix/requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nba_radix/requirements.txt b/nba_radix/requirements.txt index fba2e31a..60b93853 100644 --- a/nba_radix/requirements.txt +++ b/nba_radix/requirements.txt @@ -1 +1,3 @@ -reflex>=0.3.7 +reflex>=0.3.8 +pandas>=2.2.0 +plotly>=5.18.0 From 81262c5465577dac341a42dd51a3c40077f8435b Mon Sep 17 00:00:00 2001 From: Jackie Tung Date: Mon, 5 Feb 2024 11:21:29 -0800 Subject: [PATCH 08/45] basic crud --- basic_crud/basic_crud/basic_crud.py | 66 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/basic_crud/basic_crud/basic_crud.py b/basic_crud/basic_crud/basic_crud.py index b77b2acb..fc14cd56 100644 --- a/basic_crud/basic_crud/basic_crud.py +++ b/basic_crud/basic_crud/basic_crud.py @@ -107,32 +107,32 @@ async def send_query(self): def data_display(): - return rx.chakra.vstack( - rx.chakra.heading(State.total, " products found"), + return rx.vstack( + rx.heading(State.total, " products found"), rx.foreach(State.products, render_product), - rx.chakra.spacer(), + rx.spacer(), width="30vw", height="100%", ) def render_product(product: Product): - return rx.chakra.hstack( - rx.chakra.image(src=product.image, height="100%", width="3vw"), - rx.chakra.text(f"({product.code}) {product.label}", width="10vw"), - rx.chakra.vstack( - rx.chakra.text("Stock:", product.quantity), - rx.chakra.text("Category:", product.category), + return rx.hstack( + rx.image(src=product.image, height="100%", width="3vw"), + rx.text(f"({product.code}) {product.label}", width="10vw"), + rx.vstack( + rx.text("Stock:", product.quantity), + rx.text("Category:", product.category), spacing="0", width="7vw", ), - rx.chakra.vstack( - rx.chakra.text("Seller:", product.seller), - rx.chakra.text("Sender:", product.sender), + rx.vstack( + rx.text("Seller:", product.seller), + rx.text("Sender:", product.sender), spacing="0", width="7vw", ), - rx.chakra.spacer(), + rx.spacer(), border="solid black 1px", spcaing="5", width="100%", @@ -140,32 +140,32 @@ def render_product(product: Product): def query_form(): - return rx.chakra.vstack( - rx.chakra.hstack( - rx.chakra.text("Query:"), - rx.chakra.select( + return rx.vstack( + rx.hstack( + rx.text("Query:"), + rx.select( ["GET", "POST", "PUT", "DELETE"], on_change=QueryState.update_method, ), - rx.chakra.input( + rx.input( value=QueryState.url_query, on_change=QueryState.set_url_query, width="30vw", ), ), - rx.chakra.text("Body:"), - rx.chakra.text_area( - value=QueryState.body, height="30vh", on_change=QueryState.set_body + rx.text("Body:"), + rx.text_area( + value=QueryState.body, height="20vh", width="20vh", on_change=QueryState.set_body ), - rx.chakra.hstack( - rx.chakra.button("Clear", on_click=QueryState.clear_query), - rx.chakra.button("Send", on_click=QueryState.send_query), + rx.hstack( + rx.button("Clear", on_click=QueryState.clear_query), + rx.button("Send", on_click=QueryState.send_query), ), - rx.chakra.divider(orientation="horizontal", border="solid black 1px", width="100%"), - rx.chakra.hstack( - rx.chakra.text("Status: ", QueryState.response_code), rx.chakra.spacer(), width="100%" + rx.separator(orientation="horizontal", border="solid black 1px", width="100%"), + rx.hstack( + rx.text("Status: ", QueryState.response_code), rx.spacer(), width="100%" ), - rx.chakra.container( + rx.container( rx.markdown( QueryState.f_response, language="json", @@ -178,13 +178,13 @@ def query_form(): def index() -> rx.Component: - return rx.chakra.hstack( - rx.chakra.spacer(), + return rx.hstack( + rx.spacer(), data_display(), - rx.chakra.spacer(), - rx.chakra.divider(orientation="vertical", border="solid black 1px"), + rx.spacer(), + rx.separator(orientation="vertical", border="solid black 1px"), query_form(), - rx.chakra.spacer(), + rx.spacer(), height="100vh", width="100vw", spacing="0", From e722e934e0d57d69fd8617d8b794eef5a325f2b3 Mon Sep 17 00:00:00 2001 From: Jackie Tung Date: Mon, 5 Feb 2024 13:29:13 -0800 Subject: [PATCH 09/45] todo, snake game --- counter/counter/counter.py | 17 +++++----- snakegame/snakegame/snakegame.py | 39 ++++++++++++----------- todo/todo/todo.py | 53 ++++++++++---------------------- 3 files changed, 43 insertions(+), 66 deletions(-) diff --git a/counter/counter/counter.py b/counter/counter/counter.py index 376ad14a..aaec592d 100644 --- a/counter/counter/counter.py +++ b/counter/counter/counter.py @@ -23,23 +23,20 @@ def random(self): def index(): """The main view.""" - return rx.chakra.center( - rx.chakra.vstack( - rx.chakra.heading(State.count), - rx.chakra.hstack( - rx.chakra.button("Decrement", on_click=State.decrement, color_scheme="red"), - rx.chakra.button( + return rx.center( + rx.vstack( + rx.heading(State.count), + rx.hstack( + rx.button("Decrement", on_click=State.decrement, color_scheme="red"), + rx.button( "Randomize", on_click=State.random, background_image="linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(0,176,34,1) 100%)", color="white", ), - rx.chakra.button("Increment", on_click=State.increment, color_scheme="green"), + rx.button("Increment", on_click=State.increment, color_scheme="green"), ), padding="1em", - bg="#ededed", - border_radius="1em", - box_shadow="lg", ), padding_y="5em", font_size="2em", diff --git a/snakegame/snakegame/snakegame.py b/snakegame/snakegame/snakegame.py index ba9cfa17..58e04ac9 100644 --- a/snakegame/snakegame/snakegame.py +++ b/snakegame/snakegame/snakegame.py @@ -236,14 +236,14 @@ def render(self) -> str: def colored_box(color, index): """One square of the game grid.""" - return rx.chakra.box(bg=color, width="1em", height="1em", border="1px solid white") + return rx.box(background_color=color, width="1em", height="1em", border="1px solid white") def stat_box(label, value): """One of the score, magic, or rate boxes.""" - return rx.chakra.vstack( - rx.chakra.heading(label, font_size="1em"), - rx.chakra.heading(value, font_size="2em"), + return rx.vstack( + rx.heading(label, font_size="1em"), + rx.heading(value, font_size="2em"), bg_color="yellow", border_width="1px", padding_left="1em", @@ -253,7 +253,7 @@ def stat_box(label, value): def control_button(label, on_click): """One of the arrow buttons for touch/mouse control.""" - return rx.chakra.button( + return rx.button( label, on_click=on_click, color_scheme="red", @@ -264,9 +264,8 @@ def control_button(label, on_click): def padding_button(): """A button that is used for padding in the controls panel.""" - return rx.chakra.button( + return rx.button( "○", - color_scheme="none", border_radius="1em", font_size="2em", ) @@ -274,19 +273,19 @@ def padding_button(): def controls_panel(): """The controls panel of arrow buttons.""" - return rx.chakra.hstack( + return rx.hstack( GlobalKeyWatcher.create( keys=["ArrowUp", "ArrowLeft", "ArrowRight", "ArrowDown", ",", "."], on_key_down=State.handle_key, ), - rx.chakra.vstack( + rx.vstack( padding_button(), control_button( "←", on_click=State.arrow_left, ), ), - rx.chakra.vstack( + rx.vstack( control_button( "↑", on_click=State.arrow_up, @@ -296,7 +295,7 @@ def controls_panel(): on_click=State.arrow_down, ), ), - rx.chakra.vstack( + rx.vstack( padding_button(), control_button( "→", @@ -307,36 +306,36 @@ def controls_panel(): def index(): - return rx.chakra.vstack( - rx.chakra.hstack( - rx.chakra.button( + return rx.vstack( + rx.hstack( + rx.button( "PAUSE", on_click=State.pause, color_scheme="blue", border_radius="1em", ), - rx.chakra.button( + rx.button( "RUN", on_click=State.play, color_scheme="green", border_radius="1em", ), - rx.chakra.switch(is_checked=State.running, on_change=State.flip_switch), + rx.switch(checked=State.running, on_change=State.flip_switch), ), - rx.chakra.hstack( + rx.hstack( stat_box("RATE", State.rate), stat_box("SCORE", State.score), stat_box("MAGIC", State.magic), ), # Usage of foreach, please refer https://reflex.app/docs/library/layout/foreach - rx.chakra.responsive_grid( + rx.grid( rx.foreach( State.cells, lambda color, idx: colored_box(color, idx), ), - columns=[N], + columns=f"{N}", ), - rx.cond(State.died, rx.chakra.heading("Game Over 🐍")), + rx.cond(State.died, rx.heading("Game Over 🐍")), controls_panel(), padding_top="3%", ) diff --git a/todo/todo/todo.py b/todo/todo/todo.py index 2c9dd67f..59b142a6 100644 --- a/todo/todo/todo.py +++ b/todo/todo/todo.py @@ -10,26 +10,12 @@ class State(rx.State): # The new item to add to the todo list. new_item: str - # whether an item entered is valid - invalid_item: bool = False - - def add_item(self, form_data: dict[str, str]): - """Add a new item to the todo list. - - Args: - form_data: The data from the form. - """ - # Add the new item to the list. - new_item = form_data.pop("new_item") - if not new_item: - self.invalid_item = True - return - - self.items.append(new_item) - # set the invalid status to False. - self.invalid_item = False - # Clear the value of the input. - return rx.set_value("new_item", "") + def add_item(self): + """Add a new item to the todo list.""" + if self.new_item: + self.items.append(self.new_item) + # Clear the value of the input. + self.new_item = "" def finish_item(self, item: str): """Finish an item in the todo list. @@ -52,16 +38,16 @@ def todo_item(item: rx.Var[str]) -> rx.Component: A single rendered todo list item. """ return rx.chakra.list_item( - rx.chakra.hstack( + rx.hstack( # A button to finish the item. - rx.chakra.button( + rx.button( on_click=lambda: State.finish_item(item), height="1.5em", background_color="white", border="1px solid blue", ), # The item text. - rx.chakra.text(item, font_size="1.25em"), + rx.text(item, font_size="1.25em"), ) ) @@ -87,19 +73,14 @@ def new_item() -> rx.Component: Returns: A form to add a new item to the todo list. """ - return rx.chakra.form( - # Pressing enter will submit the form. - rx.chakra.input( + return rx.hstack(rx.input( id="new_item", placeholder="Add a todo...", bg="white", - is_invalid=State.invalid_item, - ), - # Clicking the button will also submit the form. - rx.chakra.center( - rx.chakra.button("Add", type_="submit", bg="white"), + on_change=State.set_new_item, + value=State.new_item, ), - on_submit=State.add_item, + rx.button("Add", bg="white", on_click=State.add_item, margin_left="1em"), ) @@ -109,11 +90,11 @@ def index() -> rx.Component: Returns: The index page of the todo app. """ - return rx.chakra.container( - rx.chakra.vstack( - rx.chakra.heading("Todos"), + return rx.container( + rx.vstack( + rx.heading("Todos"), new_item(), - rx.chakra.divider(), + rx.separator(), todo_list(), bg="#ededed", margin="5em", From b93c4f381a2521c5d1f43df7813169775b82bae1 Mon Sep 17 00:00:00 2001 From: Jackie Tung Date: Mon, 5 Feb 2024 13:44:39 -0800 Subject: [PATCH 10/45] github stats --- github-stats/github_stats/github_stats.py | 47 +++++++++-------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/github-stats/github_stats/github_stats.py b/github-stats/github_stats/github_stats.py index db868662..5c1791d0 100644 --- a/github-stats/github_stats/github_stats.py +++ b/github-stats/github_stats/github_stats.py @@ -23,6 +23,7 @@ class State(rx.State): fetching: bool = False selected_users_json: str = rx.LocalStorage() user_stats_json: str = rx.LocalStorage() + username: str def on_load(self): if self.selected_users_json: @@ -88,16 +89,12 @@ def remove_user(self, user: str): self._save_selected_users() self._remove_data_for_deselected_users() - def add_user(self, user: str): - self.selected_users.append(user) - self._save_selected_users() - return State.fetch_missing_stats - - def handle_form(self, form_data: dict): - username = form_data.get("username") - if username and username not in self.selected_users: - yield State.add_user(username) - yield rx.set_value("username", "") + def add_user(self): + if self.username and self.username not in self.selected_users: + self.selected_users.append(self.username) + self.username = "" + self._save_selected_users() + return State.fetch_missing_stats @rx.cached_var def data_pretty(self) -> str: @@ -107,16 +104,16 @@ def data_pretty(self) -> str: def index() -> rx.Component: return rx.fragment( rx.chakra.color_mode_button(rx.chakra.color_mode_icon(), float="right"), - rx.chakra.vstack( - rx.chakra.heading("Github Stats", font_size="2em"), - rx.chakra.flex( + rx.vstack( + rx.heading("Github Stats", font_size="2em"), + rx.flex( rx.foreach( State.selected_users, - lambda user: rx.chakra.box( + lambda user: rx.box( user, - rx.chakra.button( + rx.button( "X", - size="xs", + size="1", on_click=State.remove_user(user), margin_left="5px", ), @@ -130,19 +127,13 @@ def index() -> rx.Component: ), rx.cond( State.fetching, - rx.chakra.vstack( - rx.chakra.text("Fetching Data..."), - rx.chakra.progress(is_indeterminate=True, width="50vw"), - ), - ), - rx.chakra.form( - rx.chakra.hstack( - rx.chakra.input(placeholder="Github Username", id="username"), - rx.chakra.button("Get Stats", type_="submit"), + rx.vstack( + rx.text("Fetching Data..."), ), - on_submit=State.handle_form, ), - rx.chakra.box( + rx.input(placeholder="Github Username", id="username", value=State.username, on_change=State.set_username), + rx.button("Get Stats", on_click=State.add_user), + rx.box( rx.recharts.bar_chart( rx.recharts.graphing_tooltip(cursor=False), rx.recharts.bar( @@ -166,7 +157,7 @@ def index() -> rx.Component: width="100%", height="15em", ), - rx.chakra.text_area( + rx.text_area( value=State.data_pretty, ), ), From 98703da7b11e7e7f235a5756eb7fc91e721cc5bd Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 6 Feb 2024 10:53:57 -0800 Subject: [PATCH 11/45] convert to new name space --- clock_radix/clock_radix/clock_radix.py | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/clock_radix/clock_radix/clock_radix.py b/clock_radix/clock_radix/clock_radix.py index 7d4e52b4..29dc5b1f 100644 --- a/clock_radix/clock_radix/clock_radix.py +++ b/clock_radix/clock_radix/clock_radix.py @@ -6,7 +6,7 @@ import reflex as rx from reflex.components.radix.themes import theme -import reflex.components.radix.themes as rdxt +# import reflex.components.radix.themes as rdxt import pytz @@ -129,7 +129,7 @@ def clock_hand(rotation: str, color: str, length: str) -> rx.Component: Returns: A clock hand component. """ - return rx.divider( + return rx.chakra.divider( transform=rotation, width=f"{length}em", position="absolute", @@ -143,9 +143,9 @@ def clock_hand(rotation: str, color: str, length: str) -> rx.Component: def analog_clock() -> rx.Component: """Create the analog clock.""" - return rx.circle( + return rx.chakra.circle( # The inner circle. - rx.circle( + rx.chakra.circle( width="1em", height="1em", border_width="thick", @@ -168,29 +168,29 @@ def analog_clock() -> rx.Component: def digital_clock() -> rx.Component: """Create the digital clock.""" return rx.hstack( - rdxt.heading(State.time_info["hour"], size="8"), - rdxt.heading(":", size="8"), - rdxt.heading(State.time_info["minute_display"], size="8"), - rdxt.heading(":", size="8"), - rdxt.heading(State.time_info["second_display"], size="8"), - rdxt.heading(State.time_info["meridiem"], size="8"), + rx.heading(State.time_info["hour"], size="8"), + rx.heading(":", size="8"), + rx.heading(State.time_info["minute_display"], size="8"), + rx.heading(":", size="8"), + rx.heading(State.time_info["second_display"], size="8"), + rx.heading(State.time_info["meridiem"], size="8"), border_width="medium", border_color="#43464B", border_radius="2em", - padding_x="2em", - bg="white", + padding_inline_start="2em", + padding_inline_end="2em", + background="white", color="#333", ) def timezone_select() -> rx.Component: """Create the timezone select.""" - return rdxt.select( + return rx.select( TIMEZONES, placeholder="Select a time zone.", - on_value_change=State.set_zone, + on_change=State.set_zone, value=State.valid_zone, - bg="#white", width="100%", size="3", ) @@ -203,14 +203,14 @@ def index(): analog_clock(), rx.hstack( digital_clock(), - rdxt.switch(is_checked=State.running, on_checked_change=State.flip_switch), + rx.switch(is_checked=State.running, on_change=State.flip_switch), ), timezone_select(), padding="5em", border_width="medium", border_color="#43464B", border_radius="25px", - bg="#ededed", + background="#ededed", #bg=accent_color, text_align="center", ), From 226488986feac9b8b52949dd7518933d555ec187 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 6 Feb 2024 11:14:26 -0800 Subject: [PATCH 12/45] convert to new radix namespace --- nba_radix/nba_radix/helpers.py | 33 ++++++++++++++++---------------- nba_radix/nba_radix/nba_radix.py | 29 ++++++++++++++-------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/nba_radix/nba_radix/helpers.py b/nba_radix/nba_radix/helpers.py index e3076823..86c06a13 100644 --- a/nba_radix/nba_radix/helpers.py +++ b/nba_radix/nba_radix/helpers.py @@ -1,26 +1,25 @@ import reflex as rx -import reflex.components.radix.themes as rdxt def navbar(): - return rdxt.box( + return rx.box( rx.hstack( rx.hstack( rx.image(src="/nba.png", width="50px"), - rdxt.heading("NBA Data", size="8"), - rdxt.flex( - rdxt.badge("2015-2016 Season"), + rx.heading("NBA Data", size="8"), + rx.flex( + rx.badge("2015-2016 Season"), ), ), - rdxt.dropdownmenu_root( - rdxt.dropdownmenu_trigger( - rdxt.button("Menu", color="white", size="3", radius="medium", px=4, py=2), + rx.dropdown_menu.root( + rx.dropdown_menu.trigger( + rx.button("Menu", color="white", size="3", radius="medium", px=4, py=2), ), - rdxt.dropdownmenu_content( - rdxt.link(rdxt.dropdownmenu_item("Graph"), href="/"), - rdxt.dropdownmenu_separator(), - rdxt.link( - rdxt.dropdownmenu_item( - rx.hstack(rdxt.text("20Dataset"), rdxt.icon(tag="download")) + rx.dropdown_menu.content( + rx.link(rx.dropdown_menu.item("Graph"), href="/"), + rx.dropdown_menu.separator(), + rx.link( + rx.dropdown_menu.item( + rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")) ), href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), @@ -28,8 +27,10 @@ def navbar(): ), justify="space-between", border_bottom="0.2em solid #F0F0F0", - padding_x="2em", - padding_y="1em", + padding_inline_start="2em", + padding_inline_end="2em", + padding_top="1em", + padding_bottom="1em", bg="rgba(255,255,255, 0.97)", ), position="fixed", diff --git a/nba_radix/nba_radix/nba_radix.py b/nba_radix/nba_radix/nba_radix.py index 327e8567..b8ff17a6 100644 --- a/nba_radix/nba_radix/nba_radix.py +++ b/nba_radix/nba_radix/nba_radix.py @@ -5,7 +5,6 @@ import plotly.graph_objects as go from .helpers import navbar from reflex.components.radix.themes import theme -import reflex.components.radix.themes as rdxt nba_overview = "https://media.geeksforgeeks.org/wp-content/uploads/nba.csv" nba_data = pd.read_csv(nba_overview) @@ -79,37 +78,37 @@ def selection(): return rx.vstack( rx.hstack( rx.vstack( - rdxt.select( + rx.select( ["C", "PF", "SF", "PG", "SG"], placeholder="Select a position. (All)", - on_value_change=State.set_position, + on_change=State.set_position, size="3", ), - rdxt.select( + rx.select( college, placeholder="Select a college. (All)", - on_value_change=State.set_college, + on_change=State.set_college, size="3", ), ), rx.vstack( rx.vstack( rx.hstack( - rdxt.badge("Min Age: ", State.age[0]), - rdxt.separator(orientation="vertical"), - rdxt.badge("Max Age: ", State.age[1]), + rx.badge("Min Age: ", State.age[0]), + rx.separator(orientation="vertical"), + rx.badge("Max Age: ", State.age[1]), ), - rdxt.slider(default_value=[18, 50], min=18, max=50, on_value_commit=State.set_age,), + rx.slider(default_value=[18, 50], min=18, max=50, on_value_commit=State.set_age,), align_items="left", width="100%", ), rx.vstack( rx.hstack( - rdxt.badge("Min Sal: ", State.salary[0] // 1000000, "M"), - rdxt.separator(orientation="vertical"), - rdxt.badge("Max Sal: ", State.salary[1] // 1000000, "M"), + rx.badge("Min Sal: ", State.salary[0] // 1000000, "M"), + rx.separator(orientation="vertical"), + rx.badge("Max Sal: ", State.salary[1] // 1000000, "M"), ), - rdxt.slider( + rx.slider( default_value=[0, 25000000], min=0, max=25000000, on_value_commit=State.set_salary, ), align_items="left", @@ -128,7 +127,7 @@ def index(): rx.vstack( navbar(), selection(), - rdxt.separator(width="100%"), + rx.separator(width="100%"), rx.plotly(data=State.scat_fig, layout={"width": "1000", "height": "600"}), rx.plotly(data=State.hist_fig, layout={"width": "1000", "height": "600"}), rx.data_table( @@ -138,7 +137,7 @@ def index(): sort=True, resizable=True, ), - rdxt.separator(width="100%"), + rx.separator(width="100%"), padding_top="6em", width="100%", ) From f00f7965e46787c46080bdef5977cba5607caada Mon Sep 17 00:00:00 2001 From: Jackie Tung Date: Wed, 7 Feb 2024 14:38:05 -0800 Subject: [PATCH 13/45] color mode yay! --- github-stats/github_stats/github_stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github-stats/github_stats/github_stats.py b/github-stats/github_stats/github_stats.py index 5c1791d0..dc211c2e 100644 --- a/github-stats/github_stats/github_stats.py +++ b/github-stats/github_stats/github_stats.py @@ -103,7 +103,7 @@ def data_pretty(self) -> str: def index() -> rx.Component: return rx.fragment( - rx.chakra.color_mode_button(rx.chakra.color_mode_icon(), float="right"), + rx.color_mode.button(rx.color_mode.icon(), float="right"), rx.vstack( rx.heading("Github Stats", font_size="2em"), rx.flex( From f36dddfeaf52fb383efe9fb7ae30a4181e0888a1 Mon Sep 17 00:00:00 2001 From: Jackie Tung Date: Wed, 7 Feb 2024 14:45:46 -0800 Subject: [PATCH 14/45] list / items yay --- todo/todo/todo.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/todo/todo/todo.py b/todo/todo/todo.py index 59b142a6..34904580 100644 --- a/todo/todo/todo.py +++ b/todo/todo/todo.py @@ -37,18 +37,14 @@ def todo_item(item: rx.Var[str]) -> rx.Component: Returns: A single rendered todo list item. """ - return rx.chakra.list_item( - rx.hstack( - # A button to finish the item. - rx.button( - on_click=lambda: State.finish_item(item), - height="1.5em", - background_color="white", - border="1px solid blue", - ), - # The item text. - rx.text(item, font_size="1.25em"), - ) + return rx.list_item( + # A button to finish the item. + rx.button("✓", + on_click=lambda: State.finish_item(item), + margin="0 1em 1em 0" + ), + # The item text. + rx.text(item), ) @@ -58,7 +54,7 @@ def todo_list() -> rx.Component: Returns: The rendered todo list. """ - return rx.chakra.ordered_list( + return rx.ordered_list( # rx.foreach is necessary to iterate over state vars. # see: https://reflex.dev/docs/library/layout/foreach rx.foreach(State.items, lambda item: todo_item(item)), @@ -74,13 +70,13 @@ def new_item() -> rx.Component: A form to add a new item to the todo list. """ return rx.hstack(rx.input( - id="new_item", - placeholder="Add a todo...", - bg="white", - on_change=State.set_new_item, - value=State.new_item, - ), - rx.button("Add", bg="white", on_click=State.add_item, margin_left="1em"), + id="new_item", + placeholder="Add a todo...", + bg="white", + on_change=State.set_new_item, + value=State.new_item, + ), + rx.button("Add", on_click=State.add_item), ) From 86fd8474204e16ad78febcd77add08253848d803 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:20:08 -0800 Subject: [PATCH 15/45] move old apps to chakra folder --- {basic_crud => chakra_apps/basic_crud}/.gitignore | 0 {basic_crud => chakra_apps/basic_crud}/README.md | 0 .../basic_crud}/assets/favicon.ico | Bin .../basic_crud}/basic_crud/__init__.py | 0 .../basic_crud}/basic_crud/api.py | 0 .../basic_crud}/basic_crud/basic_crud.py | 0 .../basic_crud}/basic_crud/model.py | 0 .../basic_crud}/basic_crud/test.http | 0 .../basic_crud}/requirements.txt | 0 {basic_crud => chakra_apps/basic_crud}/rxconfig.py | 0 {chatroom => chakra_apps/chatroom}/.gitignore | 0 {chatroom => chakra_apps/chatroom}/README.md | 0 .../chatroom}/assets/favicon.ico | Bin .../chatroom}/assets/screenshot.png | Bin .../chatroom}/chatroom/__init__.py | 0 .../chatroom}/chatroom/chatroom.py | 0 {chatroom => chakra_apps/chatroom}/requirements.txt | 0 {chatroom => chakra_apps/chatroom}/rxconfig.py | 0 {clock => chakra_apps/clock}/.gitignore | 0 {clock => chakra_apps/clock}/assets/favicon.ico | Bin {clock => chakra_apps/clock}/clock/__init__.py | 0 {clock => chakra_apps/clock}/clock/clock.py | 0 {clock => chakra_apps/clock}/requirements.txt | 0 {clock => chakra_apps/clock}/rxconfig.py | 0 {counter => chakra_apps/counter}/.gitignore | 0 {counter => chakra_apps/counter}/assets/favicon.ico | Bin .../counter}/counter/__init__.py | 0 {counter => chakra_apps/counter}/counter/counter.py | 0 .../counter}/requirements-dev.txt | 0 {counter => chakra_apps/counter}/requirements.txt | 0 {counter => chakra_apps/counter}/rxconfig.py | 0 .../counter}/tests/test_counter.py | 0 {crm => chakra_apps/crm}/.gitignore | 0 {crm => chakra_apps/crm}/README.md | 0 {crm => chakra_apps/crm}/assets/favicon.ico | Bin {crm => chakra_apps/crm}/crm/__init__.py | 0 {crm => chakra_apps/crm}/crm/components/__init__.py | 0 {crm => chakra_apps/crm}/crm/components/crm.py | 0 {crm => chakra_apps/crm}/crm/components/navbar.py | 0 {crm => chakra_apps/crm}/crm/crm.py | 0 {crm => chakra_apps/crm}/crm/pages/__init__.py | 0 {crm => chakra_apps/crm}/crm/pages/index.py | 0 {crm => chakra_apps/crm}/crm/pages/login.py | 0 {crm => chakra_apps/crm}/crm/state/__init__.py | 0 {crm => chakra_apps/crm}/crm/state/login.py | 0 {crm => chakra_apps/crm}/crm/state/models.py | 0 {crm => chakra_apps/crm}/crm/state/state.py | 0 {crm => chakra_apps/crm}/requirements.txt | 0 {crm => chakra_apps/crm}/rxconfig.py | 0 {dalle => chakra_apps/dalle}/.gitignore | 0 {dalle => chakra_apps/dalle}/assets/favicon.ico | Bin {dalle => chakra_apps/dalle}/dalle/__init__.py | 0 {dalle => chakra_apps/dalle}/dalle/dalle.py | 0 {dalle => chakra_apps/dalle}/requirements.txt | 0 {dalle => chakra_apps/dalle}/rxconfig.py | 0 .../datatable_tutorial}/.gitignore | 0 .../datatable_tutorial}/assets/favicon.ico | Bin .../datatable_tutorial/__init__.py | 0 .../datatable_tutorial/datatable_tutorial.py | 0 .../datatable_tutorial}/requirements.txt | 0 .../datatable_tutorial}/rxconfig.py | 0 {ecommerce => chakra_apps/ecommerce}/.gitignore | 0 .../ecommerce}/assets/favicon.ico | Bin .../ecommerce}/ecommerce/__init__.py | 0 .../ecommerce}/ecommerce/ecommerce.py | 0 {ecommerce => chakra_apps/ecommerce}/products.json | 0 .../ecommerce}/requirements.txt | 0 {ecommerce => chakra_apps/ecommerce}/rxconfig.py | 0 {fragments => chakra_apps/fragments}/.gitignore | 0 .../fragments}/assets/favicon.ico | Bin .../fragments}/fragments/__init__.py | 0 .../fragments}/fragments/fragments.py | 0 .../fragments}/requirements.txt | 0 {fragments => chakra_apps/fragments}/rxconfig.py | 0 .../github-stats}/.gitignore | 0 .../github-stats}/assets/favicon.ico | Bin .../github-stats}/github_stats/__init__.py | 0 .../github-stats}/github_stats/fetchers.py | 0 .../github-stats}/github_stats/github_stats.py | 0 .../github-stats}/requirements.txt | 0 .../github-stats}/rxconfig.py | 0 {google_auth => chakra_apps/google_auth}/README.md | 0 .../google_auth}/assets/favicon.ico | Bin .../google_auth}/google_auth/__init__.py | 0 .../google_auth}/google_auth/google_auth.py | 0 .../google_auth}/google_auth/react_oauth_google.py | 0 .../google_auth}/requirements.txt | 0 .../google_auth}/rxconfig.py | 0 {gpt => chakra_apps/gpt}/.gitignore | 0 {gpt => chakra_apps/gpt}/assets/favicon.ico | Bin {gpt => chakra_apps/gpt}/gpt/__init__.py | 0 {gpt => chakra_apps/gpt}/gpt/gpt.py | 0 {gpt => chakra_apps/gpt}/gpt/helpers.py | 0 {gpt => chakra_apps/gpt}/requirements.txt | 0 {gpt => chakra_apps/gpt}/rxconfig.py | 0 {local_auth => chakra_apps/local_auth}/.gitignore | 0 {local_auth => chakra_apps/local_auth}/README.md | 0 {local_auth => chakra_apps/local_auth}/alembic.ini | 0 .../local_auth}/alembic/README | 0 .../local_auth}/alembic/env.py | 0 .../local_auth}/alembic/script.py.mako | 0 .../local_auth}/alembic/versions/e50402348eab_.py | 0 .../local_auth}/assets/favicon.ico | Bin .../local_auth}/local_auth/__init__.py | 0 .../local_auth}/local_auth/auth_session.py | 0 .../local_auth}/local_auth/base_state.py | 0 .../local_auth}/local_auth/local_auth.py | 0 .../local_auth}/local_auth/login.py | 0 .../local_auth}/local_auth/registration.py | 0 .../local_auth}/local_auth/user.py | 0 .../local_auth}/requirements.txt | 0 {local_auth => chakra_apps/local_auth}/rxconfig.py | 0 .../lorem-stream}/.gitignore | 0 .../lorem-stream}/README.md | 0 .../lorem-stream}/assets/favicon.ico | Bin .../lorem-stream}/lorem_stream/__init__.py | 0 .../lorem-stream}/lorem_stream/lorem_stream.py | 0 .../lorem-stream}/requirements.txt | 0 .../lorem-stream}/rxconfig.py | 0 {nba => chakra_apps/nba}/.gitignore | 0 {nba => chakra_apps/nba}/README.md | 0 {nba => chakra_apps/nba}/assets/favicon.ico | Bin {nba => chakra_apps/nba}/assets/nba.png | Bin {nba => chakra_apps/nba}/nba/__init__.py | 0 {nba => chakra_apps/nba}/nba/helpers.py | 0 {nba => chakra_apps/nba}/nba/nba.py | 0 {nba => chakra_apps/nba}/requirements.txt | 0 {nba => chakra_apps/nba}/rxconfig.py | 0 {qr-scanner => chakra_apps/qr-scanner}/.gitignore | 0 {qr-scanner => chakra_apps/qr-scanner}/README.md | 0 .../qr-scanner}/assets/favicon.ico | Bin .../qr-scanner}/qr_scanner/__init__.py | 0 .../qr-scanner}/qr_scanner/component.py | 0 .../qr-scanner}/qr_scanner/qr_scanner.py | 0 .../qr-scanner}/requirements.txt | 0 {qr-scanner => chakra_apps/qr-scanner}/rxconfig.py | 0 {quiz => chakra_apps/quiz}/.gitignore | 0 {quiz => chakra_apps/quiz}/assets/favicon.ico | Bin {quiz => chakra_apps/quiz}/quiz/__init__.py | 0 {quiz => chakra_apps/quiz}/quiz/quiz.py | 0 {quiz => chakra_apps/quiz}/quiz/results.py | 0 {quiz => chakra_apps/quiz}/requirements.txt | 0 {quiz => chakra_apps/quiz}/rxconfig.py | 0 .../random-number-range}/.gitignore | 0 .../random-number-range}/assets/favicon.ico | Bin .../random_number_range/__init__.py | 0 .../random_number_range/random_number_range.py | 0 .../random-number-range}/requirements.txt | 0 .../random-number-range}/rxconfig.py | 0 {sales => chakra_apps/sales}/.gitignore | 0 {sales => chakra_apps/sales}/assets/favicon.ico | Bin {sales => chakra_apps/sales}/assets/pynecone.ico | Bin {sales => chakra_apps/sales}/requirements.txt | 0 {sales => chakra_apps/sales}/rxconfig.py | 0 {sales => chakra_apps/sales}/sales/__init__.py | 0 {sales => chakra_apps/sales}/sales/models.py | 0 {sales => chakra_apps/sales}/sales/sales.py | 0 {snakegame => chakra_apps/snakegame}/.gitignore | 0 .../snakegame}/assets/favicon.ico | Bin .../snakegame}/requirements.txt | 0 {snakegame => chakra_apps/snakegame}/rxconfig.py | 0 .../snakegame}/snakegame/__init__.py | 0 .../snakegame}/snakegame/snakegame.py | 0 .../stable_diffusion}/.gitignore | 0 .../stable_diffusion}/README.md | 0 .../stable_diffusion}/assets/favicon.ico | Bin .../stable_diffusion}/docs/stable_diffusion.gif | Bin .../stable_diffusion}/linux_requirements.txt | 0 .../stable_diffusion}/mac_requirements.txt | 0 .../stable_diffusion}/requirements.txt | 0 .../stable_diffusion}/rxconfig.py | 0 .../stable_diffusion}/stable_diffusion/__init__.py | 0 .../stable_diffusion/img2img_linux.py | 0 .../stable_diffusion/img2img_mac.py | 0 .../stable_diffusion/img2img_mac_cpu_only.py | 0 .../stable_diffusion/stable_diffusion.py | 0 .../stable_diffusion}/stable_diffusion/styles.py | 0 {tailwind => chakra_apps/tailwind}/.gitignore | 0 .../tailwind}/assets/favicon.ico | Bin .../tailwind}/assets/tailwind.png | Bin {tailwind => chakra_apps/tailwind}/requirements.txt | 0 {tailwind => chakra_apps/tailwind}/rxconfig.py | 0 .../tailwind}/tailwind/__init__.py | 0 .../tailwind}/tailwind/tailwind.py | 0 {todo => chakra_apps/todo}/.gitignore | 0 {todo => chakra_apps/todo}/assets/favicon.ico | Bin {todo => chakra_apps/todo}/requirements.txt | 0 {todo => chakra_apps/todo}/rxconfig.py | 0 {todo => chakra_apps/todo}/todo/__init__.py | 0 {todo => chakra_apps/todo}/todo/todo.py | 0 {translator => chakra_apps/translator}/.gitignore | 0 .../translator}/assets/favicon.ico | Bin .../translator}/requirements.txt | 0 {translator => chakra_apps/translator}/rxconfig.py | 0 .../translator}/translator/__init__.py | 0 .../translator}/translator/langs.py | 0 .../translator}/translator/translator.py | 0 {traversal => chakra_apps/traversal}/.gitignore | 0 .../traversal}/assets/favicon.ico | Bin .../traversal}/requirements.txt | 0 {traversal => chakra_apps/traversal}/rxconfig.py | 0 .../traversal}/traversal/__init__.py | 0 .../traversal}/traversal/traversal.py | 0 {twitter => chakra_apps/twitter}/.gitignore | 0 {twitter => chakra_apps/twitter}/README.md | 0 {twitter => chakra_apps/twitter}/assets/bg.svg | 0 {twitter => chakra_apps/twitter}/assets/favicon.ico | Bin {twitter => chakra_apps/twitter}/assets/signup.svg | 0 {twitter => chakra_apps/twitter}/requirements.txt | 0 {twitter => chakra_apps/twitter}/rxconfig.py | 0 .../twitter}/twitter/__init__.py | 0 .../twitter}/twitter/components/__init__.py | 0 .../twitter}/twitter/components/container.py | 0 .../twitter}/twitter/layouts/__init__.py | 0 .../twitter}/twitter/layouts/auth.py | 0 .../twitter}/twitter/pages/__init__.py | 0 .../twitter}/twitter/pages/home.py | 0 .../twitter}/twitter/pages/login.py | 0 .../twitter}/twitter/pages/signup.py | 0 .../twitter}/twitter/state/auth.py | 0 .../twitter}/twitter/state/base.py | 0 .../twitter}/twitter/state/home.py | 0 {twitter => chakra_apps/twitter}/twitter/twitter.py | 0 {upload => chakra_apps/upload}/.gitignore | 0 {upload => chakra_apps/upload}/assets/favicon.ico | Bin {upload => chakra_apps/upload}/requirements.txt | 0 {upload => chakra_apps/upload}/rxconfig.py | 0 {upload => chakra_apps/upload}/upload/__init__.py | 0 {upload => chakra_apps/upload}/upload/upload.py | 0 229 files changed, 0 insertions(+), 0 deletions(-) rename {basic_crud => chakra_apps/basic_crud}/.gitignore (100%) rename {basic_crud => chakra_apps/basic_crud}/README.md (100%) rename {basic_crud => chakra_apps/basic_crud}/assets/favicon.ico (100%) rename {basic_crud => chakra_apps/basic_crud}/basic_crud/__init__.py (100%) rename {basic_crud => chakra_apps/basic_crud}/basic_crud/api.py (100%) rename {basic_crud => chakra_apps/basic_crud}/basic_crud/basic_crud.py (100%) rename {basic_crud => chakra_apps/basic_crud}/basic_crud/model.py (100%) rename {basic_crud => chakra_apps/basic_crud}/basic_crud/test.http (100%) rename {basic_crud => chakra_apps/basic_crud}/requirements.txt (100%) rename {basic_crud => chakra_apps/basic_crud}/rxconfig.py (100%) rename {chatroom => chakra_apps/chatroom}/.gitignore (100%) rename {chatroom => chakra_apps/chatroom}/README.md (100%) rename {chatroom => chakra_apps/chatroom}/assets/favicon.ico (100%) rename {chatroom => chakra_apps/chatroom}/assets/screenshot.png (100%) rename {chatroom => chakra_apps/chatroom}/chatroom/__init__.py (100%) rename {chatroom => chakra_apps/chatroom}/chatroom/chatroom.py (100%) rename {chatroom => chakra_apps/chatroom}/requirements.txt (100%) rename {chatroom => chakra_apps/chatroom}/rxconfig.py (100%) rename {clock => chakra_apps/clock}/.gitignore (100%) rename {clock => chakra_apps/clock}/assets/favicon.ico (100%) rename {clock => chakra_apps/clock}/clock/__init__.py (100%) rename {clock => chakra_apps/clock}/clock/clock.py (100%) rename {clock => chakra_apps/clock}/requirements.txt (100%) rename {clock => chakra_apps/clock}/rxconfig.py (100%) rename {counter => chakra_apps/counter}/.gitignore (100%) rename {counter => chakra_apps/counter}/assets/favicon.ico (100%) rename {counter => chakra_apps/counter}/counter/__init__.py (100%) rename {counter => chakra_apps/counter}/counter/counter.py (100%) rename {counter => chakra_apps/counter}/requirements-dev.txt (100%) rename {counter => chakra_apps/counter}/requirements.txt (100%) rename {counter => chakra_apps/counter}/rxconfig.py (100%) rename {counter => chakra_apps/counter}/tests/test_counter.py (100%) rename {crm => chakra_apps/crm}/.gitignore (100%) rename {crm => chakra_apps/crm}/README.md (100%) rename {crm => chakra_apps/crm}/assets/favicon.ico (100%) rename {crm => chakra_apps/crm}/crm/__init__.py (100%) rename {crm => chakra_apps/crm}/crm/components/__init__.py (100%) rename {crm => chakra_apps/crm}/crm/components/crm.py (100%) rename {crm => chakra_apps/crm}/crm/components/navbar.py (100%) rename {crm => chakra_apps/crm}/crm/crm.py (100%) rename {crm => chakra_apps/crm}/crm/pages/__init__.py (100%) rename {crm => chakra_apps/crm}/crm/pages/index.py (100%) rename {crm => chakra_apps/crm}/crm/pages/login.py (100%) rename {crm => chakra_apps/crm}/crm/state/__init__.py (100%) rename {crm => chakra_apps/crm}/crm/state/login.py (100%) rename {crm => chakra_apps/crm}/crm/state/models.py (100%) rename {crm => chakra_apps/crm}/crm/state/state.py (100%) rename {crm => chakra_apps/crm}/requirements.txt (100%) rename {crm => chakra_apps/crm}/rxconfig.py (100%) rename {dalle => chakra_apps/dalle}/.gitignore (100%) rename {dalle => chakra_apps/dalle}/assets/favicon.ico (100%) rename {dalle => chakra_apps/dalle}/dalle/__init__.py (100%) rename {dalle => chakra_apps/dalle}/dalle/dalle.py (100%) rename {dalle => chakra_apps/dalle}/requirements.txt (100%) rename {dalle => chakra_apps/dalle}/rxconfig.py (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/.gitignore (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/assets/favicon.ico (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/datatable_tutorial/__init__.py (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/datatable_tutorial/datatable_tutorial.py (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/requirements.txt (100%) rename {datatable_tutorial => chakra_apps/datatable_tutorial}/rxconfig.py (100%) rename {ecommerce => chakra_apps/ecommerce}/.gitignore (100%) rename {ecommerce => chakra_apps/ecommerce}/assets/favicon.ico (100%) rename {ecommerce => chakra_apps/ecommerce}/ecommerce/__init__.py (100%) rename {ecommerce => chakra_apps/ecommerce}/ecommerce/ecommerce.py (100%) rename {ecommerce => chakra_apps/ecommerce}/products.json (100%) rename {ecommerce => chakra_apps/ecommerce}/requirements.txt (100%) rename {ecommerce => chakra_apps/ecommerce}/rxconfig.py (100%) rename {fragments => chakra_apps/fragments}/.gitignore (100%) rename {fragments => chakra_apps/fragments}/assets/favicon.ico (100%) rename {fragments => chakra_apps/fragments}/fragments/__init__.py (100%) rename {fragments => chakra_apps/fragments}/fragments/fragments.py (100%) rename {fragments => chakra_apps/fragments}/requirements.txt (100%) rename {fragments => chakra_apps/fragments}/rxconfig.py (100%) rename {github-stats => chakra_apps/github-stats}/.gitignore (100%) rename {github-stats => chakra_apps/github-stats}/assets/favicon.ico (100%) rename {github-stats => chakra_apps/github-stats}/github_stats/__init__.py (100%) rename {github-stats => chakra_apps/github-stats}/github_stats/fetchers.py (100%) rename {github-stats => chakra_apps/github-stats}/github_stats/github_stats.py (100%) rename {github-stats => chakra_apps/github-stats}/requirements.txt (100%) rename {github-stats => chakra_apps/github-stats}/rxconfig.py (100%) rename {google_auth => chakra_apps/google_auth}/README.md (100%) rename {google_auth => chakra_apps/google_auth}/assets/favicon.ico (100%) rename {google_auth => chakra_apps/google_auth}/google_auth/__init__.py (100%) rename {google_auth => chakra_apps/google_auth}/google_auth/google_auth.py (100%) rename {google_auth => chakra_apps/google_auth}/google_auth/react_oauth_google.py (100%) rename {google_auth => chakra_apps/google_auth}/requirements.txt (100%) rename {google_auth => chakra_apps/google_auth}/rxconfig.py (100%) rename {gpt => chakra_apps/gpt}/.gitignore (100%) rename {gpt => chakra_apps/gpt}/assets/favicon.ico (100%) rename {gpt => chakra_apps/gpt}/gpt/__init__.py (100%) rename {gpt => chakra_apps/gpt}/gpt/gpt.py (100%) rename {gpt => chakra_apps/gpt}/gpt/helpers.py (100%) rename {gpt => chakra_apps/gpt}/requirements.txt (100%) rename {gpt => chakra_apps/gpt}/rxconfig.py (100%) rename {local_auth => chakra_apps/local_auth}/.gitignore (100%) rename {local_auth => chakra_apps/local_auth}/README.md (100%) rename {local_auth => chakra_apps/local_auth}/alembic.ini (100%) rename {local_auth => chakra_apps/local_auth}/alembic/README (100%) rename {local_auth => chakra_apps/local_auth}/alembic/env.py (100%) rename {local_auth => chakra_apps/local_auth}/alembic/script.py.mako (100%) rename {local_auth => chakra_apps/local_auth}/alembic/versions/e50402348eab_.py (100%) rename {local_auth => chakra_apps/local_auth}/assets/favicon.ico (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/__init__.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/auth_session.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/base_state.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/local_auth.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/login.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/registration.py (100%) rename {local_auth => chakra_apps/local_auth}/local_auth/user.py (100%) rename {local_auth => chakra_apps/local_auth}/requirements.txt (100%) rename {local_auth => chakra_apps/local_auth}/rxconfig.py (100%) rename {lorem-stream => chakra_apps/lorem-stream}/.gitignore (100%) rename {lorem-stream => chakra_apps/lorem-stream}/README.md (100%) rename {lorem-stream => chakra_apps/lorem-stream}/assets/favicon.ico (100%) rename {lorem-stream => chakra_apps/lorem-stream}/lorem_stream/__init__.py (100%) rename {lorem-stream => chakra_apps/lorem-stream}/lorem_stream/lorem_stream.py (100%) rename {lorem-stream => chakra_apps/lorem-stream}/requirements.txt (100%) rename {lorem-stream => chakra_apps/lorem-stream}/rxconfig.py (100%) rename {nba => chakra_apps/nba}/.gitignore (100%) rename {nba => chakra_apps/nba}/README.md (100%) rename {nba => chakra_apps/nba}/assets/favicon.ico (100%) rename {nba => chakra_apps/nba}/assets/nba.png (100%) rename {nba => chakra_apps/nba}/nba/__init__.py (100%) rename {nba => chakra_apps/nba}/nba/helpers.py (100%) rename {nba => chakra_apps/nba}/nba/nba.py (100%) rename {nba => chakra_apps/nba}/requirements.txt (100%) rename {nba => chakra_apps/nba}/rxconfig.py (100%) rename {qr-scanner => chakra_apps/qr-scanner}/.gitignore (100%) rename {qr-scanner => chakra_apps/qr-scanner}/README.md (100%) rename {qr-scanner => chakra_apps/qr-scanner}/assets/favicon.ico (100%) rename {qr-scanner => chakra_apps/qr-scanner}/qr_scanner/__init__.py (100%) rename {qr-scanner => chakra_apps/qr-scanner}/qr_scanner/component.py (100%) rename {qr-scanner => chakra_apps/qr-scanner}/qr_scanner/qr_scanner.py (100%) rename {qr-scanner => chakra_apps/qr-scanner}/requirements.txt (100%) rename {qr-scanner => chakra_apps/qr-scanner}/rxconfig.py (100%) rename {quiz => chakra_apps/quiz}/.gitignore (100%) rename {quiz => chakra_apps/quiz}/assets/favicon.ico (100%) rename {quiz => chakra_apps/quiz}/quiz/__init__.py (100%) rename {quiz => chakra_apps/quiz}/quiz/quiz.py (100%) rename {quiz => chakra_apps/quiz}/quiz/results.py (100%) rename {quiz => chakra_apps/quiz}/requirements.txt (100%) rename {quiz => chakra_apps/quiz}/rxconfig.py (100%) rename {random-number-range => chakra_apps/random-number-range}/.gitignore (100%) rename {random-number-range => chakra_apps/random-number-range}/assets/favicon.ico (100%) rename {random-number-range => chakra_apps/random-number-range}/random_number_range/__init__.py (100%) rename {random-number-range => chakra_apps/random-number-range}/random_number_range/random_number_range.py (100%) rename {random-number-range => chakra_apps/random-number-range}/requirements.txt (100%) rename {random-number-range => chakra_apps/random-number-range}/rxconfig.py (100%) rename {sales => chakra_apps/sales}/.gitignore (100%) rename {sales => chakra_apps/sales}/assets/favicon.ico (100%) rename {sales => chakra_apps/sales}/assets/pynecone.ico (100%) rename {sales => chakra_apps/sales}/requirements.txt (100%) rename {sales => chakra_apps/sales}/rxconfig.py (100%) rename {sales => chakra_apps/sales}/sales/__init__.py (100%) rename {sales => chakra_apps/sales}/sales/models.py (100%) rename {sales => chakra_apps/sales}/sales/sales.py (100%) rename {snakegame => chakra_apps/snakegame}/.gitignore (100%) rename {snakegame => chakra_apps/snakegame}/assets/favicon.ico (100%) rename {snakegame => chakra_apps/snakegame}/requirements.txt (100%) rename {snakegame => chakra_apps/snakegame}/rxconfig.py (100%) rename {snakegame => chakra_apps/snakegame}/snakegame/__init__.py (100%) rename {snakegame => chakra_apps/snakegame}/snakegame/snakegame.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/.gitignore (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/README.md (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/assets/favicon.ico (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/docs/stable_diffusion.gif (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/linux_requirements.txt (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/mac_requirements.txt (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/requirements.txt (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/rxconfig.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/__init__.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/img2img_linux.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/img2img_mac.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/img2img_mac_cpu_only.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/stable_diffusion.py (100%) rename {stable_diffusion => chakra_apps/stable_diffusion}/stable_diffusion/styles.py (100%) rename {tailwind => chakra_apps/tailwind}/.gitignore (100%) rename {tailwind => chakra_apps/tailwind}/assets/favicon.ico (100%) rename {tailwind => chakra_apps/tailwind}/assets/tailwind.png (100%) rename {tailwind => chakra_apps/tailwind}/requirements.txt (100%) rename {tailwind => chakra_apps/tailwind}/rxconfig.py (100%) rename {tailwind => chakra_apps/tailwind}/tailwind/__init__.py (100%) rename {tailwind => chakra_apps/tailwind}/tailwind/tailwind.py (100%) rename {todo => chakra_apps/todo}/.gitignore (100%) rename {todo => chakra_apps/todo}/assets/favicon.ico (100%) rename {todo => chakra_apps/todo}/requirements.txt (100%) rename {todo => chakra_apps/todo}/rxconfig.py (100%) rename {todo => chakra_apps/todo}/todo/__init__.py (100%) rename {todo => chakra_apps/todo}/todo/todo.py (100%) rename {translator => chakra_apps/translator}/.gitignore (100%) rename {translator => chakra_apps/translator}/assets/favicon.ico (100%) rename {translator => chakra_apps/translator}/requirements.txt (100%) rename {translator => chakra_apps/translator}/rxconfig.py (100%) rename {translator => chakra_apps/translator}/translator/__init__.py (100%) rename {translator => chakra_apps/translator}/translator/langs.py (100%) rename {translator => chakra_apps/translator}/translator/translator.py (100%) rename {traversal => chakra_apps/traversal}/.gitignore (100%) rename {traversal => chakra_apps/traversal}/assets/favicon.ico (100%) rename {traversal => chakra_apps/traversal}/requirements.txt (100%) rename {traversal => chakra_apps/traversal}/rxconfig.py (100%) rename {traversal => chakra_apps/traversal}/traversal/__init__.py (100%) rename {traversal => chakra_apps/traversal}/traversal/traversal.py (100%) rename {twitter => chakra_apps/twitter}/.gitignore (100%) rename {twitter => chakra_apps/twitter}/README.md (100%) rename {twitter => chakra_apps/twitter}/assets/bg.svg (100%) rename {twitter => chakra_apps/twitter}/assets/favicon.ico (100%) rename {twitter => chakra_apps/twitter}/assets/signup.svg (100%) rename {twitter => chakra_apps/twitter}/requirements.txt (100%) rename {twitter => chakra_apps/twitter}/rxconfig.py (100%) rename {twitter => chakra_apps/twitter}/twitter/__init__.py (100%) rename {twitter => chakra_apps/twitter}/twitter/components/__init__.py (100%) rename {twitter => chakra_apps/twitter}/twitter/components/container.py (100%) rename {twitter => chakra_apps/twitter}/twitter/layouts/__init__.py (100%) rename {twitter => chakra_apps/twitter}/twitter/layouts/auth.py (100%) rename {twitter => chakra_apps/twitter}/twitter/pages/__init__.py (100%) rename {twitter => chakra_apps/twitter}/twitter/pages/home.py (100%) rename {twitter => chakra_apps/twitter}/twitter/pages/login.py (100%) rename {twitter => chakra_apps/twitter}/twitter/pages/signup.py (100%) rename {twitter => chakra_apps/twitter}/twitter/state/auth.py (100%) rename {twitter => chakra_apps/twitter}/twitter/state/base.py (100%) rename {twitter => chakra_apps/twitter}/twitter/state/home.py (100%) rename {twitter => chakra_apps/twitter}/twitter/twitter.py (100%) rename {upload => chakra_apps/upload}/.gitignore (100%) rename {upload => chakra_apps/upload}/assets/favicon.ico (100%) rename {upload => chakra_apps/upload}/requirements.txt (100%) rename {upload => chakra_apps/upload}/rxconfig.py (100%) rename {upload => chakra_apps/upload}/upload/__init__.py (100%) rename {upload => chakra_apps/upload}/upload/upload.py (100%) diff --git a/basic_crud/.gitignore b/chakra_apps/basic_crud/.gitignore similarity index 100% rename from basic_crud/.gitignore rename to chakra_apps/basic_crud/.gitignore diff --git a/basic_crud/README.md b/chakra_apps/basic_crud/README.md similarity index 100% rename from basic_crud/README.md rename to chakra_apps/basic_crud/README.md diff --git a/basic_crud/assets/favicon.ico b/chakra_apps/basic_crud/assets/favicon.ico similarity index 100% rename from basic_crud/assets/favicon.ico rename to chakra_apps/basic_crud/assets/favicon.ico diff --git a/basic_crud/basic_crud/__init__.py b/chakra_apps/basic_crud/basic_crud/__init__.py similarity index 100% rename from basic_crud/basic_crud/__init__.py rename to chakra_apps/basic_crud/basic_crud/__init__.py diff --git a/basic_crud/basic_crud/api.py b/chakra_apps/basic_crud/basic_crud/api.py similarity index 100% rename from basic_crud/basic_crud/api.py rename to chakra_apps/basic_crud/basic_crud/api.py diff --git a/basic_crud/basic_crud/basic_crud.py b/chakra_apps/basic_crud/basic_crud/basic_crud.py similarity index 100% rename from basic_crud/basic_crud/basic_crud.py rename to chakra_apps/basic_crud/basic_crud/basic_crud.py diff --git a/basic_crud/basic_crud/model.py b/chakra_apps/basic_crud/basic_crud/model.py similarity index 100% rename from basic_crud/basic_crud/model.py rename to chakra_apps/basic_crud/basic_crud/model.py diff --git a/basic_crud/basic_crud/test.http b/chakra_apps/basic_crud/basic_crud/test.http similarity index 100% rename from basic_crud/basic_crud/test.http rename to chakra_apps/basic_crud/basic_crud/test.http diff --git a/basic_crud/requirements.txt b/chakra_apps/basic_crud/requirements.txt similarity index 100% rename from basic_crud/requirements.txt rename to chakra_apps/basic_crud/requirements.txt diff --git a/basic_crud/rxconfig.py b/chakra_apps/basic_crud/rxconfig.py similarity index 100% rename from basic_crud/rxconfig.py rename to chakra_apps/basic_crud/rxconfig.py diff --git a/chatroom/.gitignore b/chakra_apps/chatroom/.gitignore similarity index 100% rename from chatroom/.gitignore rename to chakra_apps/chatroom/.gitignore diff --git a/chatroom/README.md b/chakra_apps/chatroom/README.md similarity index 100% rename from chatroom/README.md rename to chakra_apps/chatroom/README.md diff --git a/chatroom/assets/favicon.ico b/chakra_apps/chatroom/assets/favicon.ico similarity index 100% rename from chatroom/assets/favicon.ico rename to chakra_apps/chatroom/assets/favicon.ico diff --git a/chatroom/assets/screenshot.png b/chakra_apps/chatroom/assets/screenshot.png similarity index 100% rename from chatroom/assets/screenshot.png rename to chakra_apps/chatroom/assets/screenshot.png diff --git a/chatroom/chatroom/__init__.py b/chakra_apps/chatroom/chatroom/__init__.py similarity index 100% rename from chatroom/chatroom/__init__.py rename to chakra_apps/chatroom/chatroom/__init__.py diff --git a/chatroom/chatroom/chatroom.py b/chakra_apps/chatroom/chatroom/chatroom.py similarity index 100% rename from chatroom/chatroom/chatroom.py rename to chakra_apps/chatroom/chatroom/chatroom.py diff --git a/chatroom/requirements.txt b/chakra_apps/chatroom/requirements.txt similarity index 100% rename from chatroom/requirements.txt rename to chakra_apps/chatroom/requirements.txt diff --git a/chatroom/rxconfig.py b/chakra_apps/chatroom/rxconfig.py similarity index 100% rename from chatroom/rxconfig.py rename to chakra_apps/chatroom/rxconfig.py diff --git a/clock/.gitignore b/chakra_apps/clock/.gitignore similarity index 100% rename from clock/.gitignore rename to chakra_apps/clock/.gitignore diff --git a/clock/assets/favicon.ico b/chakra_apps/clock/assets/favicon.ico similarity index 100% rename from clock/assets/favicon.ico rename to chakra_apps/clock/assets/favicon.ico diff --git a/clock/clock/__init__.py b/chakra_apps/clock/clock/__init__.py similarity index 100% rename from clock/clock/__init__.py rename to chakra_apps/clock/clock/__init__.py diff --git a/clock/clock/clock.py b/chakra_apps/clock/clock/clock.py similarity index 100% rename from clock/clock/clock.py rename to chakra_apps/clock/clock/clock.py diff --git a/clock/requirements.txt b/chakra_apps/clock/requirements.txt similarity index 100% rename from clock/requirements.txt rename to chakra_apps/clock/requirements.txt diff --git a/clock/rxconfig.py b/chakra_apps/clock/rxconfig.py similarity index 100% rename from clock/rxconfig.py rename to chakra_apps/clock/rxconfig.py diff --git a/counter/.gitignore b/chakra_apps/counter/.gitignore similarity index 100% rename from counter/.gitignore rename to chakra_apps/counter/.gitignore diff --git a/counter/assets/favicon.ico b/chakra_apps/counter/assets/favicon.ico similarity index 100% rename from counter/assets/favicon.ico rename to chakra_apps/counter/assets/favicon.ico diff --git a/counter/counter/__init__.py b/chakra_apps/counter/counter/__init__.py similarity index 100% rename from counter/counter/__init__.py rename to chakra_apps/counter/counter/__init__.py diff --git a/counter/counter/counter.py b/chakra_apps/counter/counter/counter.py similarity index 100% rename from counter/counter/counter.py rename to chakra_apps/counter/counter/counter.py diff --git a/counter/requirements-dev.txt b/chakra_apps/counter/requirements-dev.txt similarity index 100% rename from counter/requirements-dev.txt rename to chakra_apps/counter/requirements-dev.txt diff --git a/counter/requirements.txt b/chakra_apps/counter/requirements.txt similarity index 100% rename from counter/requirements.txt rename to chakra_apps/counter/requirements.txt diff --git a/counter/rxconfig.py b/chakra_apps/counter/rxconfig.py similarity index 100% rename from counter/rxconfig.py rename to chakra_apps/counter/rxconfig.py diff --git a/counter/tests/test_counter.py b/chakra_apps/counter/tests/test_counter.py similarity index 100% rename from counter/tests/test_counter.py rename to chakra_apps/counter/tests/test_counter.py diff --git a/crm/.gitignore b/chakra_apps/crm/.gitignore similarity index 100% rename from crm/.gitignore rename to chakra_apps/crm/.gitignore diff --git a/crm/README.md b/chakra_apps/crm/README.md similarity index 100% rename from crm/README.md rename to chakra_apps/crm/README.md diff --git a/crm/assets/favicon.ico b/chakra_apps/crm/assets/favicon.ico similarity index 100% rename from crm/assets/favicon.ico rename to chakra_apps/crm/assets/favicon.ico diff --git a/crm/crm/__init__.py b/chakra_apps/crm/crm/__init__.py similarity index 100% rename from crm/crm/__init__.py rename to chakra_apps/crm/crm/__init__.py diff --git a/crm/crm/components/__init__.py b/chakra_apps/crm/crm/components/__init__.py similarity index 100% rename from crm/crm/components/__init__.py rename to chakra_apps/crm/crm/components/__init__.py diff --git a/crm/crm/components/crm.py b/chakra_apps/crm/crm/components/crm.py similarity index 100% rename from crm/crm/components/crm.py rename to chakra_apps/crm/crm/components/crm.py diff --git a/crm/crm/components/navbar.py b/chakra_apps/crm/crm/components/navbar.py similarity index 100% rename from crm/crm/components/navbar.py rename to chakra_apps/crm/crm/components/navbar.py diff --git a/crm/crm/crm.py b/chakra_apps/crm/crm/crm.py similarity index 100% rename from crm/crm/crm.py rename to chakra_apps/crm/crm/crm.py diff --git a/crm/crm/pages/__init__.py b/chakra_apps/crm/crm/pages/__init__.py similarity index 100% rename from crm/crm/pages/__init__.py rename to chakra_apps/crm/crm/pages/__init__.py diff --git a/crm/crm/pages/index.py b/chakra_apps/crm/crm/pages/index.py similarity index 100% rename from crm/crm/pages/index.py rename to chakra_apps/crm/crm/pages/index.py diff --git a/crm/crm/pages/login.py b/chakra_apps/crm/crm/pages/login.py similarity index 100% rename from crm/crm/pages/login.py rename to chakra_apps/crm/crm/pages/login.py diff --git a/crm/crm/state/__init__.py b/chakra_apps/crm/crm/state/__init__.py similarity index 100% rename from crm/crm/state/__init__.py rename to chakra_apps/crm/crm/state/__init__.py diff --git a/crm/crm/state/login.py b/chakra_apps/crm/crm/state/login.py similarity index 100% rename from crm/crm/state/login.py rename to chakra_apps/crm/crm/state/login.py diff --git a/crm/crm/state/models.py b/chakra_apps/crm/crm/state/models.py similarity index 100% rename from crm/crm/state/models.py rename to chakra_apps/crm/crm/state/models.py diff --git a/crm/crm/state/state.py b/chakra_apps/crm/crm/state/state.py similarity index 100% rename from crm/crm/state/state.py rename to chakra_apps/crm/crm/state/state.py diff --git a/crm/requirements.txt b/chakra_apps/crm/requirements.txt similarity index 100% rename from crm/requirements.txt rename to chakra_apps/crm/requirements.txt diff --git a/crm/rxconfig.py b/chakra_apps/crm/rxconfig.py similarity index 100% rename from crm/rxconfig.py rename to chakra_apps/crm/rxconfig.py diff --git a/dalle/.gitignore b/chakra_apps/dalle/.gitignore similarity index 100% rename from dalle/.gitignore rename to chakra_apps/dalle/.gitignore diff --git a/dalle/assets/favicon.ico b/chakra_apps/dalle/assets/favicon.ico similarity index 100% rename from dalle/assets/favicon.ico rename to chakra_apps/dalle/assets/favicon.ico diff --git a/dalle/dalle/__init__.py b/chakra_apps/dalle/dalle/__init__.py similarity index 100% rename from dalle/dalle/__init__.py rename to chakra_apps/dalle/dalle/__init__.py diff --git a/dalle/dalle/dalle.py b/chakra_apps/dalle/dalle/dalle.py similarity index 100% rename from dalle/dalle/dalle.py rename to chakra_apps/dalle/dalle/dalle.py diff --git a/dalle/requirements.txt b/chakra_apps/dalle/requirements.txt similarity index 100% rename from dalle/requirements.txt rename to chakra_apps/dalle/requirements.txt diff --git a/dalle/rxconfig.py b/chakra_apps/dalle/rxconfig.py similarity index 100% rename from dalle/rxconfig.py rename to chakra_apps/dalle/rxconfig.py diff --git a/datatable_tutorial/.gitignore b/chakra_apps/datatable_tutorial/.gitignore similarity index 100% rename from datatable_tutorial/.gitignore rename to chakra_apps/datatable_tutorial/.gitignore diff --git a/datatable_tutorial/assets/favicon.ico b/chakra_apps/datatable_tutorial/assets/favicon.ico similarity index 100% rename from datatable_tutorial/assets/favicon.ico rename to chakra_apps/datatable_tutorial/assets/favicon.ico diff --git a/datatable_tutorial/datatable_tutorial/__init__.py b/chakra_apps/datatable_tutorial/datatable_tutorial/__init__.py similarity index 100% rename from datatable_tutorial/datatable_tutorial/__init__.py rename to chakra_apps/datatable_tutorial/datatable_tutorial/__init__.py diff --git a/datatable_tutorial/datatable_tutorial/datatable_tutorial.py b/chakra_apps/datatable_tutorial/datatable_tutorial/datatable_tutorial.py similarity index 100% rename from datatable_tutorial/datatable_tutorial/datatable_tutorial.py rename to chakra_apps/datatable_tutorial/datatable_tutorial/datatable_tutorial.py diff --git a/datatable_tutorial/requirements.txt b/chakra_apps/datatable_tutorial/requirements.txt similarity index 100% rename from datatable_tutorial/requirements.txt rename to chakra_apps/datatable_tutorial/requirements.txt diff --git a/datatable_tutorial/rxconfig.py b/chakra_apps/datatable_tutorial/rxconfig.py similarity index 100% rename from datatable_tutorial/rxconfig.py rename to chakra_apps/datatable_tutorial/rxconfig.py diff --git a/ecommerce/.gitignore b/chakra_apps/ecommerce/.gitignore similarity index 100% rename from ecommerce/.gitignore rename to chakra_apps/ecommerce/.gitignore diff --git a/ecommerce/assets/favicon.ico b/chakra_apps/ecommerce/assets/favicon.ico similarity index 100% rename from ecommerce/assets/favicon.ico rename to chakra_apps/ecommerce/assets/favicon.ico diff --git a/ecommerce/ecommerce/__init__.py b/chakra_apps/ecommerce/ecommerce/__init__.py similarity index 100% rename from ecommerce/ecommerce/__init__.py rename to chakra_apps/ecommerce/ecommerce/__init__.py diff --git a/ecommerce/ecommerce/ecommerce.py b/chakra_apps/ecommerce/ecommerce/ecommerce.py similarity index 100% rename from ecommerce/ecommerce/ecommerce.py rename to chakra_apps/ecommerce/ecommerce/ecommerce.py diff --git a/ecommerce/products.json b/chakra_apps/ecommerce/products.json similarity index 100% rename from ecommerce/products.json rename to chakra_apps/ecommerce/products.json diff --git a/ecommerce/requirements.txt b/chakra_apps/ecommerce/requirements.txt similarity index 100% rename from ecommerce/requirements.txt rename to chakra_apps/ecommerce/requirements.txt diff --git a/ecommerce/rxconfig.py b/chakra_apps/ecommerce/rxconfig.py similarity index 100% rename from ecommerce/rxconfig.py rename to chakra_apps/ecommerce/rxconfig.py diff --git a/fragments/.gitignore b/chakra_apps/fragments/.gitignore similarity index 100% rename from fragments/.gitignore rename to chakra_apps/fragments/.gitignore diff --git a/fragments/assets/favicon.ico b/chakra_apps/fragments/assets/favicon.ico similarity index 100% rename from fragments/assets/favicon.ico rename to chakra_apps/fragments/assets/favicon.ico diff --git a/fragments/fragments/__init__.py b/chakra_apps/fragments/fragments/__init__.py similarity index 100% rename from fragments/fragments/__init__.py rename to chakra_apps/fragments/fragments/__init__.py diff --git a/fragments/fragments/fragments.py b/chakra_apps/fragments/fragments/fragments.py similarity index 100% rename from fragments/fragments/fragments.py rename to chakra_apps/fragments/fragments/fragments.py diff --git a/fragments/requirements.txt b/chakra_apps/fragments/requirements.txt similarity index 100% rename from fragments/requirements.txt rename to chakra_apps/fragments/requirements.txt diff --git a/fragments/rxconfig.py b/chakra_apps/fragments/rxconfig.py similarity index 100% rename from fragments/rxconfig.py rename to chakra_apps/fragments/rxconfig.py diff --git a/github-stats/.gitignore b/chakra_apps/github-stats/.gitignore similarity index 100% rename from github-stats/.gitignore rename to chakra_apps/github-stats/.gitignore diff --git a/github-stats/assets/favicon.ico b/chakra_apps/github-stats/assets/favicon.ico similarity index 100% rename from github-stats/assets/favicon.ico rename to chakra_apps/github-stats/assets/favicon.ico diff --git a/github-stats/github_stats/__init__.py b/chakra_apps/github-stats/github_stats/__init__.py similarity index 100% rename from github-stats/github_stats/__init__.py rename to chakra_apps/github-stats/github_stats/__init__.py diff --git a/github-stats/github_stats/fetchers.py b/chakra_apps/github-stats/github_stats/fetchers.py similarity index 100% rename from github-stats/github_stats/fetchers.py rename to chakra_apps/github-stats/github_stats/fetchers.py diff --git a/github-stats/github_stats/github_stats.py b/chakra_apps/github-stats/github_stats/github_stats.py similarity index 100% rename from github-stats/github_stats/github_stats.py rename to chakra_apps/github-stats/github_stats/github_stats.py diff --git a/github-stats/requirements.txt b/chakra_apps/github-stats/requirements.txt similarity index 100% rename from github-stats/requirements.txt rename to chakra_apps/github-stats/requirements.txt diff --git a/github-stats/rxconfig.py b/chakra_apps/github-stats/rxconfig.py similarity index 100% rename from github-stats/rxconfig.py rename to chakra_apps/github-stats/rxconfig.py diff --git a/google_auth/README.md b/chakra_apps/google_auth/README.md similarity index 100% rename from google_auth/README.md rename to chakra_apps/google_auth/README.md diff --git a/google_auth/assets/favicon.ico b/chakra_apps/google_auth/assets/favicon.ico similarity index 100% rename from google_auth/assets/favicon.ico rename to chakra_apps/google_auth/assets/favicon.ico diff --git a/google_auth/google_auth/__init__.py b/chakra_apps/google_auth/google_auth/__init__.py similarity index 100% rename from google_auth/google_auth/__init__.py rename to chakra_apps/google_auth/google_auth/__init__.py diff --git a/google_auth/google_auth/google_auth.py b/chakra_apps/google_auth/google_auth/google_auth.py similarity index 100% rename from google_auth/google_auth/google_auth.py rename to chakra_apps/google_auth/google_auth/google_auth.py diff --git a/google_auth/google_auth/react_oauth_google.py b/chakra_apps/google_auth/google_auth/react_oauth_google.py similarity index 100% rename from google_auth/google_auth/react_oauth_google.py rename to chakra_apps/google_auth/google_auth/react_oauth_google.py diff --git a/google_auth/requirements.txt b/chakra_apps/google_auth/requirements.txt similarity index 100% rename from google_auth/requirements.txt rename to chakra_apps/google_auth/requirements.txt diff --git a/google_auth/rxconfig.py b/chakra_apps/google_auth/rxconfig.py similarity index 100% rename from google_auth/rxconfig.py rename to chakra_apps/google_auth/rxconfig.py diff --git a/gpt/.gitignore b/chakra_apps/gpt/.gitignore similarity index 100% rename from gpt/.gitignore rename to chakra_apps/gpt/.gitignore diff --git a/gpt/assets/favicon.ico b/chakra_apps/gpt/assets/favicon.ico similarity index 100% rename from gpt/assets/favicon.ico rename to chakra_apps/gpt/assets/favicon.ico diff --git a/gpt/gpt/__init__.py b/chakra_apps/gpt/gpt/__init__.py similarity index 100% rename from gpt/gpt/__init__.py rename to chakra_apps/gpt/gpt/__init__.py diff --git a/gpt/gpt/gpt.py b/chakra_apps/gpt/gpt/gpt.py similarity index 100% rename from gpt/gpt/gpt.py rename to chakra_apps/gpt/gpt/gpt.py diff --git a/gpt/gpt/helpers.py b/chakra_apps/gpt/gpt/helpers.py similarity index 100% rename from gpt/gpt/helpers.py rename to chakra_apps/gpt/gpt/helpers.py diff --git a/gpt/requirements.txt b/chakra_apps/gpt/requirements.txt similarity index 100% rename from gpt/requirements.txt rename to chakra_apps/gpt/requirements.txt diff --git a/gpt/rxconfig.py b/chakra_apps/gpt/rxconfig.py similarity index 100% rename from gpt/rxconfig.py rename to chakra_apps/gpt/rxconfig.py diff --git a/local_auth/.gitignore b/chakra_apps/local_auth/.gitignore similarity index 100% rename from local_auth/.gitignore rename to chakra_apps/local_auth/.gitignore diff --git a/local_auth/README.md b/chakra_apps/local_auth/README.md similarity index 100% rename from local_auth/README.md rename to chakra_apps/local_auth/README.md diff --git a/local_auth/alembic.ini b/chakra_apps/local_auth/alembic.ini similarity index 100% rename from local_auth/alembic.ini rename to chakra_apps/local_auth/alembic.ini diff --git a/local_auth/alembic/README b/chakra_apps/local_auth/alembic/README similarity index 100% rename from local_auth/alembic/README rename to chakra_apps/local_auth/alembic/README diff --git a/local_auth/alembic/env.py b/chakra_apps/local_auth/alembic/env.py similarity index 100% rename from local_auth/alembic/env.py rename to chakra_apps/local_auth/alembic/env.py diff --git a/local_auth/alembic/script.py.mako b/chakra_apps/local_auth/alembic/script.py.mako similarity index 100% rename from local_auth/alembic/script.py.mako rename to chakra_apps/local_auth/alembic/script.py.mako diff --git a/local_auth/alembic/versions/e50402348eab_.py b/chakra_apps/local_auth/alembic/versions/e50402348eab_.py similarity index 100% rename from local_auth/alembic/versions/e50402348eab_.py rename to chakra_apps/local_auth/alembic/versions/e50402348eab_.py diff --git a/local_auth/assets/favicon.ico b/chakra_apps/local_auth/assets/favicon.ico similarity index 100% rename from local_auth/assets/favicon.ico rename to chakra_apps/local_auth/assets/favicon.ico diff --git a/local_auth/local_auth/__init__.py b/chakra_apps/local_auth/local_auth/__init__.py similarity index 100% rename from local_auth/local_auth/__init__.py rename to chakra_apps/local_auth/local_auth/__init__.py diff --git a/local_auth/local_auth/auth_session.py b/chakra_apps/local_auth/local_auth/auth_session.py similarity index 100% rename from local_auth/local_auth/auth_session.py rename to chakra_apps/local_auth/local_auth/auth_session.py diff --git a/local_auth/local_auth/base_state.py b/chakra_apps/local_auth/local_auth/base_state.py similarity index 100% rename from local_auth/local_auth/base_state.py rename to chakra_apps/local_auth/local_auth/base_state.py diff --git a/local_auth/local_auth/local_auth.py b/chakra_apps/local_auth/local_auth/local_auth.py similarity index 100% rename from local_auth/local_auth/local_auth.py rename to chakra_apps/local_auth/local_auth/local_auth.py diff --git a/local_auth/local_auth/login.py b/chakra_apps/local_auth/local_auth/login.py similarity index 100% rename from local_auth/local_auth/login.py rename to chakra_apps/local_auth/local_auth/login.py diff --git a/local_auth/local_auth/registration.py b/chakra_apps/local_auth/local_auth/registration.py similarity index 100% rename from local_auth/local_auth/registration.py rename to chakra_apps/local_auth/local_auth/registration.py diff --git a/local_auth/local_auth/user.py b/chakra_apps/local_auth/local_auth/user.py similarity index 100% rename from local_auth/local_auth/user.py rename to chakra_apps/local_auth/local_auth/user.py diff --git a/local_auth/requirements.txt b/chakra_apps/local_auth/requirements.txt similarity index 100% rename from local_auth/requirements.txt rename to chakra_apps/local_auth/requirements.txt diff --git a/local_auth/rxconfig.py b/chakra_apps/local_auth/rxconfig.py similarity index 100% rename from local_auth/rxconfig.py rename to chakra_apps/local_auth/rxconfig.py diff --git a/lorem-stream/.gitignore b/chakra_apps/lorem-stream/.gitignore similarity index 100% rename from lorem-stream/.gitignore rename to chakra_apps/lorem-stream/.gitignore diff --git a/lorem-stream/README.md b/chakra_apps/lorem-stream/README.md similarity index 100% rename from lorem-stream/README.md rename to chakra_apps/lorem-stream/README.md diff --git a/lorem-stream/assets/favicon.ico b/chakra_apps/lorem-stream/assets/favicon.ico similarity index 100% rename from lorem-stream/assets/favicon.ico rename to chakra_apps/lorem-stream/assets/favicon.ico diff --git a/lorem-stream/lorem_stream/__init__.py b/chakra_apps/lorem-stream/lorem_stream/__init__.py similarity index 100% rename from lorem-stream/lorem_stream/__init__.py rename to chakra_apps/lorem-stream/lorem_stream/__init__.py diff --git a/lorem-stream/lorem_stream/lorem_stream.py b/chakra_apps/lorem-stream/lorem_stream/lorem_stream.py similarity index 100% rename from lorem-stream/lorem_stream/lorem_stream.py rename to chakra_apps/lorem-stream/lorem_stream/lorem_stream.py diff --git a/lorem-stream/requirements.txt b/chakra_apps/lorem-stream/requirements.txt similarity index 100% rename from lorem-stream/requirements.txt rename to chakra_apps/lorem-stream/requirements.txt diff --git a/lorem-stream/rxconfig.py b/chakra_apps/lorem-stream/rxconfig.py similarity index 100% rename from lorem-stream/rxconfig.py rename to chakra_apps/lorem-stream/rxconfig.py diff --git a/nba/.gitignore b/chakra_apps/nba/.gitignore similarity index 100% rename from nba/.gitignore rename to chakra_apps/nba/.gitignore diff --git a/nba/README.md b/chakra_apps/nba/README.md similarity index 100% rename from nba/README.md rename to chakra_apps/nba/README.md diff --git a/nba/assets/favicon.ico b/chakra_apps/nba/assets/favicon.ico similarity index 100% rename from nba/assets/favicon.ico rename to chakra_apps/nba/assets/favicon.ico diff --git a/nba/assets/nba.png b/chakra_apps/nba/assets/nba.png similarity index 100% rename from nba/assets/nba.png rename to chakra_apps/nba/assets/nba.png diff --git a/nba/nba/__init__.py b/chakra_apps/nba/nba/__init__.py similarity index 100% rename from nba/nba/__init__.py rename to chakra_apps/nba/nba/__init__.py diff --git a/nba/nba/helpers.py b/chakra_apps/nba/nba/helpers.py similarity index 100% rename from nba/nba/helpers.py rename to chakra_apps/nba/nba/helpers.py diff --git a/nba/nba/nba.py b/chakra_apps/nba/nba/nba.py similarity index 100% rename from nba/nba/nba.py rename to chakra_apps/nba/nba/nba.py diff --git a/nba/requirements.txt b/chakra_apps/nba/requirements.txt similarity index 100% rename from nba/requirements.txt rename to chakra_apps/nba/requirements.txt diff --git a/nba/rxconfig.py b/chakra_apps/nba/rxconfig.py similarity index 100% rename from nba/rxconfig.py rename to chakra_apps/nba/rxconfig.py diff --git a/qr-scanner/.gitignore b/chakra_apps/qr-scanner/.gitignore similarity index 100% rename from qr-scanner/.gitignore rename to chakra_apps/qr-scanner/.gitignore diff --git a/qr-scanner/README.md b/chakra_apps/qr-scanner/README.md similarity index 100% rename from qr-scanner/README.md rename to chakra_apps/qr-scanner/README.md diff --git a/qr-scanner/assets/favicon.ico b/chakra_apps/qr-scanner/assets/favicon.ico similarity index 100% rename from qr-scanner/assets/favicon.ico rename to chakra_apps/qr-scanner/assets/favicon.ico diff --git a/qr-scanner/qr_scanner/__init__.py b/chakra_apps/qr-scanner/qr_scanner/__init__.py similarity index 100% rename from qr-scanner/qr_scanner/__init__.py rename to chakra_apps/qr-scanner/qr_scanner/__init__.py diff --git a/qr-scanner/qr_scanner/component.py b/chakra_apps/qr-scanner/qr_scanner/component.py similarity index 100% rename from qr-scanner/qr_scanner/component.py rename to chakra_apps/qr-scanner/qr_scanner/component.py diff --git a/qr-scanner/qr_scanner/qr_scanner.py b/chakra_apps/qr-scanner/qr_scanner/qr_scanner.py similarity index 100% rename from qr-scanner/qr_scanner/qr_scanner.py rename to chakra_apps/qr-scanner/qr_scanner/qr_scanner.py diff --git a/qr-scanner/requirements.txt b/chakra_apps/qr-scanner/requirements.txt similarity index 100% rename from qr-scanner/requirements.txt rename to chakra_apps/qr-scanner/requirements.txt diff --git a/qr-scanner/rxconfig.py b/chakra_apps/qr-scanner/rxconfig.py similarity index 100% rename from qr-scanner/rxconfig.py rename to chakra_apps/qr-scanner/rxconfig.py diff --git a/quiz/.gitignore b/chakra_apps/quiz/.gitignore similarity index 100% rename from quiz/.gitignore rename to chakra_apps/quiz/.gitignore diff --git a/quiz/assets/favicon.ico b/chakra_apps/quiz/assets/favicon.ico similarity index 100% rename from quiz/assets/favicon.ico rename to chakra_apps/quiz/assets/favicon.ico diff --git a/quiz/quiz/__init__.py b/chakra_apps/quiz/quiz/__init__.py similarity index 100% rename from quiz/quiz/__init__.py rename to chakra_apps/quiz/quiz/__init__.py diff --git a/quiz/quiz/quiz.py b/chakra_apps/quiz/quiz/quiz.py similarity index 100% rename from quiz/quiz/quiz.py rename to chakra_apps/quiz/quiz/quiz.py diff --git a/quiz/quiz/results.py b/chakra_apps/quiz/quiz/results.py similarity index 100% rename from quiz/quiz/results.py rename to chakra_apps/quiz/quiz/results.py diff --git a/quiz/requirements.txt b/chakra_apps/quiz/requirements.txt similarity index 100% rename from quiz/requirements.txt rename to chakra_apps/quiz/requirements.txt diff --git a/quiz/rxconfig.py b/chakra_apps/quiz/rxconfig.py similarity index 100% rename from quiz/rxconfig.py rename to chakra_apps/quiz/rxconfig.py diff --git a/random-number-range/.gitignore b/chakra_apps/random-number-range/.gitignore similarity index 100% rename from random-number-range/.gitignore rename to chakra_apps/random-number-range/.gitignore diff --git a/random-number-range/assets/favicon.ico b/chakra_apps/random-number-range/assets/favicon.ico similarity index 100% rename from random-number-range/assets/favicon.ico rename to chakra_apps/random-number-range/assets/favicon.ico diff --git a/random-number-range/random_number_range/__init__.py b/chakra_apps/random-number-range/random_number_range/__init__.py similarity index 100% rename from random-number-range/random_number_range/__init__.py rename to chakra_apps/random-number-range/random_number_range/__init__.py diff --git a/random-number-range/random_number_range/random_number_range.py b/chakra_apps/random-number-range/random_number_range/random_number_range.py similarity index 100% rename from random-number-range/random_number_range/random_number_range.py rename to chakra_apps/random-number-range/random_number_range/random_number_range.py diff --git a/random-number-range/requirements.txt b/chakra_apps/random-number-range/requirements.txt similarity index 100% rename from random-number-range/requirements.txt rename to chakra_apps/random-number-range/requirements.txt diff --git a/random-number-range/rxconfig.py b/chakra_apps/random-number-range/rxconfig.py similarity index 100% rename from random-number-range/rxconfig.py rename to chakra_apps/random-number-range/rxconfig.py diff --git a/sales/.gitignore b/chakra_apps/sales/.gitignore similarity index 100% rename from sales/.gitignore rename to chakra_apps/sales/.gitignore diff --git a/sales/assets/favicon.ico b/chakra_apps/sales/assets/favicon.ico similarity index 100% rename from sales/assets/favicon.ico rename to chakra_apps/sales/assets/favicon.ico diff --git a/sales/assets/pynecone.ico b/chakra_apps/sales/assets/pynecone.ico similarity index 100% rename from sales/assets/pynecone.ico rename to chakra_apps/sales/assets/pynecone.ico diff --git a/sales/requirements.txt b/chakra_apps/sales/requirements.txt similarity index 100% rename from sales/requirements.txt rename to chakra_apps/sales/requirements.txt diff --git a/sales/rxconfig.py b/chakra_apps/sales/rxconfig.py similarity index 100% rename from sales/rxconfig.py rename to chakra_apps/sales/rxconfig.py diff --git a/sales/sales/__init__.py b/chakra_apps/sales/sales/__init__.py similarity index 100% rename from sales/sales/__init__.py rename to chakra_apps/sales/sales/__init__.py diff --git a/sales/sales/models.py b/chakra_apps/sales/sales/models.py similarity index 100% rename from sales/sales/models.py rename to chakra_apps/sales/sales/models.py diff --git a/sales/sales/sales.py b/chakra_apps/sales/sales/sales.py similarity index 100% rename from sales/sales/sales.py rename to chakra_apps/sales/sales/sales.py diff --git a/snakegame/.gitignore b/chakra_apps/snakegame/.gitignore similarity index 100% rename from snakegame/.gitignore rename to chakra_apps/snakegame/.gitignore diff --git a/snakegame/assets/favicon.ico b/chakra_apps/snakegame/assets/favicon.ico similarity index 100% rename from snakegame/assets/favicon.ico rename to chakra_apps/snakegame/assets/favicon.ico diff --git a/snakegame/requirements.txt b/chakra_apps/snakegame/requirements.txt similarity index 100% rename from snakegame/requirements.txt rename to chakra_apps/snakegame/requirements.txt diff --git a/snakegame/rxconfig.py b/chakra_apps/snakegame/rxconfig.py similarity index 100% rename from snakegame/rxconfig.py rename to chakra_apps/snakegame/rxconfig.py diff --git a/snakegame/snakegame/__init__.py b/chakra_apps/snakegame/snakegame/__init__.py similarity index 100% rename from snakegame/snakegame/__init__.py rename to chakra_apps/snakegame/snakegame/__init__.py diff --git a/snakegame/snakegame/snakegame.py b/chakra_apps/snakegame/snakegame/snakegame.py similarity index 100% rename from snakegame/snakegame/snakegame.py rename to chakra_apps/snakegame/snakegame/snakegame.py diff --git a/stable_diffusion/.gitignore b/chakra_apps/stable_diffusion/.gitignore similarity index 100% rename from stable_diffusion/.gitignore rename to chakra_apps/stable_diffusion/.gitignore diff --git a/stable_diffusion/README.md b/chakra_apps/stable_diffusion/README.md similarity index 100% rename from stable_diffusion/README.md rename to chakra_apps/stable_diffusion/README.md diff --git a/stable_diffusion/assets/favicon.ico b/chakra_apps/stable_diffusion/assets/favicon.ico similarity index 100% rename from stable_diffusion/assets/favicon.ico rename to chakra_apps/stable_diffusion/assets/favicon.ico diff --git a/stable_diffusion/docs/stable_diffusion.gif b/chakra_apps/stable_diffusion/docs/stable_diffusion.gif similarity index 100% rename from stable_diffusion/docs/stable_diffusion.gif rename to chakra_apps/stable_diffusion/docs/stable_diffusion.gif diff --git a/stable_diffusion/linux_requirements.txt b/chakra_apps/stable_diffusion/linux_requirements.txt similarity index 100% rename from stable_diffusion/linux_requirements.txt rename to chakra_apps/stable_diffusion/linux_requirements.txt diff --git a/stable_diffusion/mac_requirements.txt b/chakra_apps/stable_diffusion/mac_requirements.txt similarity index 100% rename from stable_diffusion/mac_requirements.txt rename to chakra_apps/stable_diffusion/mac_requirements.txt diff --git a/stable_diffusion/requirements.txt b/chakra_apps/stable_diffusion/requirements.txt similarity index 100% rename from stable_diffusion/requirements.txt rename to chakra_apps/stable_diffusion/requirements.txt diff --git a/stable_diffusion/rxconfig.py b/chakra_apps/stable_diffusion/rxconfig.py similarity index 100% rename from stable_diffusion/rxconfig.py rename to chakra_apps/stable_diffusion/rxconfig.py diff --git a/stable_diffusion/stable_diffusion/__init__.py b/chakra_apps/stable_diffusion/stable_diffusion/__init__.py similarity index 100% rename from stable_diffusion/stable_diffusion/__init__.py rename to chakra_apps/stable_diffusion/stable_diffusion/__init__.py diff --git a/stable_diffusion/stable_diffusion/img2img_linux.py b/chakra_apps/stable_diffusion/stable_diffusion/img2img_linux.py similarity index 100% rename from stable_diffusion/stable_diffusion/img2img_linux.py rename to chakra_apps/stable_diffusion/stable_diffusion/img2img_linux.py diff --git a/stable_diffusion/stable_diffusion/img2img_mac.py b/chakra_apps/stable_diffusion/stable_diffusion/img2img_mac.py similarity index 100% rename from stable_diffusion/stable_diffusion/img2img_mac.py rename to chakra_apps/stable_diffusion/stable_diffusion/img2img_mac.py diff --git a/stable_diffusion/stable_diffusion/img2img_mac_cpu_only.py b/chakra_apps/stable_diffusion/stable_diffusion/img2img_mac_cpu_only.py similarity index 100% rename from stable_diffusion/stable_diffusion/img2img_mac_cpu_only.py rename to chakra_apps/stable_diffusion/stable_diffusion/img2img_mac_cpu_only.py diff --git a/stable_diffusion/stable_diffusion/stable_diffusion.py b/chakra_apps/stable_diffusion/stable_diffusion/stable_diffusion.py similarity index 100% rename from stable_diffusion/stable_diffusion/stable_diffusion.py rename to chakra_apps/stable_diffusion/stable_diffusion/stable_diffusion.py diff --git a/stable_diffusion/stable_diffusion/styles.py b/chakra_apps/stable_diffusion/stable_diffusion/styles.py similarity index 100% rename from stable_diffusion/stable_diffusion/styles.py rename to chakra_apps/stable_diffusion/stable_diffusion/styles.py diff --git a/tailwind/.gitignore b/chakra_apps/tailwind/.gitignore similarity index 100% rename from tailwind/.gitignore rename to chakra_apps/tailwind/.gitignore diff --git a/tailwind/assets/favicon.ico b/chakra_apps/tailwind/assets/favicon.ico similarity index 100% rename from tailwind/assets/favicon.ico rename to chakra_apps/tailwind/assets/favicon.ico diff --git a/tailwind/assets/tailwind.png b/chakra_apps/tailwind/assets/tailwind.png similarity index 100% rename from tailwind/assets/tailwind.png rename to chakra_apps/tailwind/assets/tailwind.png diff --git a/tailwind/requirements.txt b/chakra_apps/tailwind/requirements.txt similarity index 100% rename from tailwind/requirements.txt rename to chakra_apps/tailwind/requirements.txt diff --git a/tailwind/rxconfig.py b/chakra_apps/tailwind/rxconfig.py similarity index 100% rename from tailwind/rxconfig.py rename to chakra_apps/tailwind/rxconfig.py diff --git a/tailwind/tailwind/__init__.py b/chakra_apps/tailwind/tailwind/__init__.py similarity index 100% rename from tailwind/tailwind/__init__.py rename to chakra_apps/tailwind/tailwind/__init__.py diff --git a/tailwind/tailwind/tailwind.py b/chakra_apps/tailwind/tailwind/tailwind.py similarity index 100% rename from tailwind/tailwind/tailwind.py rename to chakra_apps/tailwind/tailwind/tailwind.py diff --git a/todo/.gitignore b/chakra_apps/todo/.gitignore similarity index 100% rename from todo/.gitignore rename to chakra_apps/todo/.gitignore diff --git a/todo/assets/favicon.ico b/chakra_apps/todo/assets/favicon.ico similarity index 100% rename from todo/assets/favicon.ico rename to chakra_apps/todo/assets/favicon.ico diff --git a/todo/requirements.txt b/chakra_apps/todo/requirements.txt similarity index 100% rename from todo/requirements.txt rename to chakra_apps/todo/requirements.txt diff --git a/todo/rxconfig.py b/chakra_apps/todo/rxconfig.py similarity index 100% rename from todo/rxconfig.py rename to chakra_apps/todo/rxconfig.py diff --git a/todo/todo/__init__.py b/chakra_apps/todo/todo/__init__.py similarity index 100% rename from todo/todo/__init__.py rename to chakra_apps/todo/todo/__init__.py diff --git a/todo/todo/todo.py b/chakra_apps/todo/todo/todo.py similarity index 100% rename from todo/todo/todo.py rename to chakra_apps/todo/todo/todo.py diff --git a/translator/.gitignore b/chakra_apps/translator/.gitignore similarity index 100% rename from translator/.gitignore rename to chakra_apps/translator/.gitignore diff --git a/translator/assets/favicon.ico b/chakra_apps/translator/assets/favicon.ico similarity index 100% rename from translator/assets/favicon.ico rename to chakra_apps/translator/assets/favicon.ico diff --git a/translator/requirements.txt b/chakra_apps/translator/requirements.txt similarity index 100% rename from translator/requirements.txt rename to chakra_apps/translator/requirements.txt diff --git a/translator/rxconfig.py b/chakra_apps/translator/rxconfig.py similarity index 100% rename from translator/rxconfig.py rename to chakra_apps/translator/rxconfig.py diff --git a/translator/translator/__init__.py b/chakra_apps/translator/translator/__init__.py similarity index 100% rename from translator/translator/__init__.py rename to chakra_apps/translator/translator/__init__.py diff --git a/translator/translator/langs.py b/chakra_apps/translator/translator/langs.py similarity index 100% rename from translator/translator/langs.py rename to chakra_apps/translator/translator/langs.py diff --git a/translator/translator/translator.py b/chakra_apps/translator/translator/translator.py similarity index 100% rename from translator/translator/translator.py rename to chakra_apps/translator/translator/translator.py diff --git a/traversal/.gitignore b/chakra_apps/traversal/.gitignore similarity index 100% rename from traversal/.gitignore rename to chakra_apps/traversal/.gitignore diff --git a/traversal/assets/favicon.ico b/chakra_apps/traversal/assets/favicon.ico similarity index 100% rename from traversal/assets/favicon.ico rename to chakra_apps/traversal/assets/favicon.ico diff --git a/traversal/requirements.txt b/chakra_apps/traversal/requirements.txt similarity index 100% rename from traversal/requirements.txt rename to chakra_apps/traversal/requirements.txt diff --git a/traversal/rxconfig.py b/chakra_apps/traversal/rxconfig.py similarity index 100% rename from traversal/rxconfig.py rename to chakra_apps/traversal/rxconfig.py diff --git a/traversal/traversal/__init__.py b/chakra_apps/traversal/traversal/__init__.py similarity index 100% rename from traversal/traversal/__init__.py rename to chakra_apps/traversal/traversal/__init__.py diff --git a/traversal/traversal/traversal.py b/chakra_apps/traversal/traversal/traversal.py similarity index 100% rename from traversal/traversal/traversal.py rename to chakra_apps/traversal/traversal/traversal.py diff --git a/twitter/.gitignore b/chakra_apps/twitter/.gitignore similarity index 100% rename from twitter/.gitignore rename to chakra_apps/twitter/.gitignore diff --git a/twitter/README.md b/chakra_apps/twitter/README.md similarity index 100% rename from twitter/README.md rename to chakra_apps/twitter/README.md diff --git a/twitter/assets/bg.svg b/chakra_apps/twitter/assets/bg.svg similarity index 100% rename from twitter/assets/bg.svg rename to chakra_apps/twitter/assets/bg.svg diff --git a/twitter/assets/favicon.ico b/chakra_apps/twitter/assets/favicon.ico similarity index 100% rename from twitter/assets/favicon.ico rename to chakra_apps/twitter/assets/favicon.ico diff --git a/twitter/assets/signup.svg b/chakra_apps/twitter/assets/signup.svg similarity index 100% rename from twitter/assets/signup.svg rename to chakra_apps/twitter/assets/signup.svg diff --git a/twitter/requirements.txt b/chakra_apps/twitter/requirements.txt similarity index 100% rename from twitter/requirements.txt rename to chakra_apps/twitter/requirements.txt diff --git a/twitter/rxconfig.py b/chakra_apps/twitter/rxconfig.py similarity index 100% rename from twitter/rxconfig.py rename to chakra_apps/twitter/rxconfig.py diff --git a/twitter/twitter/__init__.py b/chakra_apps/twitter/twitter/__init__.py similarity index 100% rename from twitter/twitter/__init__.py rename to chakra_apps/twitter/twitter/__init__.py diff --git a/twitter/twitter/components/__init__.py b/chakra_apps/twitter/twitter/components/__init__.py similarity index 100% rename from twitter/twitter/components/__init__.py rename to chakra_apps/twitter/twitter/components/__init__.py diff --git a/twitter/twitter/components/container.py b/chakra_apps/twitter/twitter/components/container.py similarity index 100% rename from twitter/twitter/components/container.py rename to chakra_apps/twitter/twitter/components/container.py diff --git a/twitter/twitter/layouts/__init__.py b/chakra_apps/twitter/twitter/layouts/__init__.py similarity index 100% rename from twitter/twitter/layouts/__init__.py rename to chakra_apps/twitter/twitter/layouts/__init__.py diff --git a/twitter/twitter/layouts/auth.py b/chakra_apps/twitter/twitter/layouts/auth.py similarity index 100% rename from twitter/twitter/layouts/auth.py rename to chakra_apps/twitter/twitter/layouts/auth.py diff --git a/twitter/twitter/pages/__init__.py b/chakra_apps/twitter/twitter/pages/__init__.py similarity index 100% rename from twitter/twitter/pages/__init__.py rename to chakra_apps/twitter/twitter/pages/__init__.py diff --git a/twitter/twitter/pages/home.py b/chakra_apps/twitter/twitter/pages/home.py similarity index 100% rename from twitter/twitter/pages/home.py rename to chakra_apps/twitter/twitter/pages/home.py diff --git a/twitter/twitter/pages/login.py b/chakra_apps/twitter/twitter/pages/login.py similarity index 100% rename from twitter/twitter/pages/login.py rename to chakra_apps/twitter/twitter/pages/login.py diff --git a/twitter/twitter/pages/signup.py b/chakra_apps/twitter/twitter/pages/signup.py similarity index 100% rename from twitter/twitter/pages/signup.py rename to chakra_apps/twitter/twitter/pages/signup.py diff --git a/twitter/twitter/state/auth.py b/chakra_apps/twitter/twitter/state/auth.py similarity index 100% rename from twitter/twitter/state/auth.py rename to chakra_apps/twitter/twitter/state/auth.py diff --git a/twitter/twitter/state/base.py b/chakra_apps/twitter/twitter/state/base.py similarity index 100% rename from twitter/twitter/state/base.py rename to chakra_apps/twitter/twitter/state/base.py diff --git a/twitter/twitter/state/home.py b/chakra_apps/twitter/twitter/state/home.py similarity index 100% rename from twitter/twitter/state/home.py rename to chakra_apps/twitter/twitter/state/home.py diff --git a/twitter/twitter/twitter.py b/chakra_apps/twitter/twitter/twitter.py similarity index 100% rename from twitter/twitter/twitter.py rename to chakra_apps/twitter/twitter/twitter.py diff --git a/upload/.gitignore b/chakra_apps/upload/.gitignore similarity index 100% rename from upload/.gitignore rename to chakra_apps/upload/.gitignore diff --git a/upload/assets/favicon.ico b/chakra_apps/upload/assets/favicon.ico similarity index 100% rename from upload/assets/favicon.ico rename to chakra_apps/upload/assets/favicon.ico diff --git a/upload/requirements.txt b/chakra_apps/upload/requirements.txt similarity index 100% rename from upload/requirements.txt rename to chakra_apps/upload/requirements.txt diff --git a/upload/rxconfig.py b/chakra_apps/upload/rxconfig.py similarity index 100% rename from upload/rxconfig.py rename to chakra_apps/upload/rxconfig.py diff --git a/upload/upload/__init__.py b/chakra_apps/upload/upload/__init__.py similarity index 100% rename from upload/upload/__init__.py rename to chakra_apps/upload/upload/__init__.py diff --git a/upload/upload/upload.py b/chakra_apps/upload/upload/upload.py similarity index 100% rename from upload/upload/upload.py rename to chakra_apps/upload/upload/upload.py From fa70c12a559d83114ef57ff35edfbe69445771b9 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 13 Feb 2024 16:03:37 -0800 Subject: [PATCH 16/45] update for reflex 0.4.0 --- nba/.gitignore | 3 +-- nba/README.md | 3 --- nba/assets/favicon.ico | Bin 15406 -> 4286 bytes nba/nba/helpers.py | 35 ++++++++++++++++++----------------- nba/nba/nba.py | 26 +++++++++++++++----------- nba/requirements.txt | 7 +++---- nba/rxconfig.py | 4 +--- 7 files changed, 38 insertions(+), 40 deletions(-) delete mode 100644 nba/README.md diff --git a/nba/.gitignore b/nba/.gitignore index f6711845..eab0d4b0 100644 --- a/nba/.gitignore +++ b/nba/.gitignore @@ -1,5 +1,4 @@ *.db *.py[cod] .web -__pycache__/ -reflex.db \ No newline at end of file +__pycache__/ \ No newline at end of file diff --git a/nba/README.md b/nba/README.md deleted file mode 100644 index fce6babe..00000000 --- a/nba/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# The way to run nba -pynecone==0.1.27 + The minimum version of node is 16.6.0. -If the node's version is smaller than 16.6.0, the code cannot run. diff --git a/nba/assets/favicon.ico b/nba/assets/favicon.ico index 8a93bfa72ad182e4a21385b6daac8106eb16158e..166ae995eaa63fc96771410a758282dc30e925cf 100644 GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 15406 zcmeI1X{eP|6o$X6=1^H?2{!4mEF>DV%qEJ+XwD)Eq!1b?3Mm>iiXyZhO%M$blz_D|T2;5xVnUIG6s)LsOQnbRF^BQOt6h11}ph1&XznbQ@9;JgF!iByZ>&u~Ja zwmxI#nA;U*;QR<41-<__3$^tbGp9Q^Kks=KysOw=-wkJ#Yje88^#sgc4M)PS;Mc|0 zXUv@LFqyy_I0a6JCl_k#GiFYA*q*?_@GNMriwd>%88heK(2s=I;L1X6eLcZ`B)eav zb|binBDvMVbEXE5g`Q7sv{#_P6&Ot2qppq*ppT4SvmYN^>% zOsBwioXbn$0>OO8!rlXpg7Ll+u{;_x$6RY7rdCf; zf9}jL0#`DIZvA*w$uT#_8aao2AIlorXTtt4_H~ZC|BRWF{n~2v6gyCm&lq*Sf%<*l z^I3~Ne$M)gnG=3THS{-vk15Jp%ek%r3_>{X$yd0R(c73gt;ErYZ-mh^Mt#OM2OgkF^o?=O z=4f1c3}fs}bI{heIpO!-xOeUU15eOYw$WaJ_6jtx0^_I|56_3~-$_`6HrgxDUV*J) z1v`^=dX{)wJ~$d&A$yrd?9{&v}MVQ9Q|EzCfpTHfUmOt$@GRxjwnyO0F+}#sZTt*2A2qt`S!4vJ)4CZLiSYuGw42WE_=f_pgoOg$2`x&UR8K5qxr_niFs

7ijOARPX*DwJVJ|-ed-oQnAmHCd_jCt522L*a2*&4N zo|Cp~XnsIjUwxjnYN)HG+S=yZ)85U(V1%Z@U*S7&3=~t~k1)?|J=e3LHBwt&&avhU zDAZC@ZF^YLOl*tT47d_H2Y=JM2X;Vv&4GDt+RNd6h1&ITYphj6Ej7)thrR6CEVy@9 z!#oGq%KwuI_o@3e$N$OBds_{)a=yLd8N%!}4nZORUn6>bfZx3;PKWi+XXNE^ZOOI9 zS~YT9+g|o;7Dgk~)%yO1e-`w7910(V8({r>;@a3l&|GU~K{X;CqrFDMW?>hEUVx#W z$EEo9FO3dm^g740-AT+GVNG|r_OfTQ;9B`C=DB41Sz>W!+<@KHXQ1y!D9p7cYh>GA z_G~7uMr=LIeZuzah_l-NdA-<0-a>raLt$>5H=z-uJ?zzNc+UR>qfZ`R#h*WKpS|x= zuJ%M2FxQ%_5w<<-)okpC;MXwvIC@U_9ytPv{?PM$AiM<{m$yQF#>^4cSZh3M+QVMW z#^)18S;mkIjieGzvY;Cc8J%=7b^yreKcpXQjG&s#44cbv@({Jxv-VJ+7(`^+)7ufg-> zAy~gp^4yJ?6Mu&>`xFjiHud``&)=9ieHHzf*bJEGob8#!%<0P*!sMQZdEVOkjBN=x zkV$sJxCd>0TM9haXG6bRtt)n4IqR9uf5Pr$`OYu3+i0&qdj;An&|ZP|3ba?CtiWIG CTt?CW diff --git a/nba/nba/helpers.py b/nba/nba/helpers.py index 8cd25893..52e28858 100644 --- a/nba/nba/helpers.py +++ b/nba/nba/helpers.py @@ -1,39 +1,40 @@ import reflex as rx - def navbar(): return rx.box( rx.hstack( rx.hstack( rx.image(src="/nba.png", width="50px"), - rx.heading("NBA Data"), + rx.heading("NBA Data", size="8"), rx.flex( - rx.badge("2015-2016 Season", color_scheme="blue"), + rx.badge("2015-2016 Season"), ), ), - rx.menu( - rx.menu_button( - "Menu", bg="black", color="white", border_radius="md", px=4, py=2 + rx.menu.root( + rx.menu.trigger( + rx.button("Menu", color="white", size="3", radius="medium", px=4, py=2), ), - rx.menu_list( - rx.link(rx.menu_item("Graph"), href="/"), - rx.menu_divider(), - rx.link( - rx.menu_item( - rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")) + rx.menu.content( + rx.menu.item("Graph"), + rx.menu.separator(), + rx.menu.item( + rx.link( + rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")), + href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), - href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), ), ), - justify="space-between", + justify="between", border_bottom="0.2em solid #F0F0F0", - padding_x="2em", - padding_y="1em", + padding_inline_start="2em", + padding_inline_end="2em", + padding_top="1em", + padding_bottom="1em", bg="rgba(255,255,255, 0.97)", ), position="fixed", width="100%", top="0px", z_index="500", - ) + ) \ No newline at end of file diff --git a/nba/nba/nba.py b/nba/nba/nba.py index cc51b21a..78dcd3eb 100644 --- a/nba/nba/nba.py +++ b/nba/nba/nba.py @@ -4,6 +4,7 @@ import plotly.express as px import plotly.graph_objects as go from .helpers import navbar +from reflex.components.radix.themes import theme nba_overview = "https://media.geeksforgeeks.org/wp-content/uploads/nba.csv" nba_data = pd.read_csv(nba_overview) @@ -16,7 +17,7 @@ class State(rx.State): # Filters to apply to the data. position: str college: str - age: tuple[int, int] = (0, 50) + age: tuple[int, int] = (18, 50) salary: tuple[int, int] = (0, 25000000) @rx.var @@ -81,38 +82,40 @@ def selection(): ["C", "PF", "SF", "PG", "SG"], placeholder="Select a position. (All)", on_change=State.set_position, + size="3", ), rx.select( college, placeholder="Select a college. (All)", on_change=State.set_college, + size="3", ), ), rx.vstack( rx.vstack( rx.hstack( rx.badge("Min Age: ", State.age[0]), - rx.spacer(), + rx.divider(orientation="vertical"), rx.badge("Max Age: ", State.age[1]), ), - rx.range_slider(on_change_end=State.set_age, min_=18, max_=50), + rx.slider(default_value=[18, 50], min=18, max=50, on_value_commit=State.set_age,), align_items="left", width="100%", ), rx.vstack( rx.hstack( rx.badge("Min Sal: ", State.salary[0] // 1000000, "M"), - rx.spacer(), + rx.divider(orientation="vertical"), rx.badge("Max Sal: ", State.salary[1] // 1000000, "M"), ), - rx.range_slider( - on_change_end=State.set_salary, min_=0, max_=25000000 + rx.slider( + default_value=[0, 25000000], min=0, max=25000000, on_value_commit=State.set_salary, ), align_items="left", width="100%", ), ), - spacing="1em", + spacing="4", ), width="100%", ) @@ -124,7 +127,7 @@ def index(): rx.vstack( navbar(), selection(), - rx.divider(), + rx.divider(width="100%"), rx.plotly(data=State.scat_fig, layout={"width": "1000", "height": "600"}), rx.plotly(data=State.hist_fig, layout={"width": "1000", "height": "600"}), rx.data_table( @@ -134,12 +137,13 @@ def index(): sort=True, resizable=True, ), - rx.divider(), + rx.divider(width="100%"), padding_top="6em", width="100%", ) ) -app = rx.App() -app.add_page(index, title="NBA App") + +app = rx.App(theme=theme(appearance="light", has_background=True, radius="large", accent_color="amber", gray_color="sand",)) +app.add_page(index, title="NBA App") \ No newline at end of file diff --git a/nba/requirements.txt b/nba/requirements.txt index a0ccbc6e..9166e192 100644 --- a/nba/requirements.txt +++ b/nba/requirements.txt @@ -1,4 +1,3 @@ -reflex>=0.3.8 -plotly-express -plotly -pandas +reflex>=0.4.0 +pandas>=2.2.0 +plotly>=5.18.0 diff --git a/nba/rxconfig.py b/nba/rxconfig.py index 3c46d12d..3879277b 100644 --- a/nba/rxconfig.py +++ b/nba/rxconfig.py @@ -2,6 +2,4 @@ config = rx.Config( app_name="nba", - db_url="sqlite:///reflex.db", - env=rx.Env.DEV, -) +) \ No newline at end of file From 815995887f508f34a440059690793ef2d5a23bdd Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 15:30:48 -0800 Subject: [PATCH 17/45] Move radix converted examples back to top-level --- {chakra_apps/basic_crud => basic_crud}/.gitignore | 0 {chakra_apps/basic_crud => basic_crud}/README.md | 0 .../basic_crud => basic_crud}/assets/favicon.ico | Bin .../basic_crud/__init__.py | 0 .../basic_crud => basic_crud}/basic_crud/api.py | 0 .../basic_crud/basic_crud.py | 0 .../basic_crud => basic_crud}/basic_crud/model.py | 0 .../basic_crud => basic_crud}/basic_crud/test.http | 0 .../basic_crud => basic_crud}/requirements.txt | 0 {chakra_apps/basic_crud => basic_crud}/rxconfig.py | 0 {chakra_apps/counter => counter}/.gitignore | 0 {chakra_apps/counter => counter}/assets/favicon.ico | Bin .../counter => counter}/counter/__init__.py | 0 {chakra_apps/counter => counter}/counter/counter.py | 0 .../counter => counter}/requirements-dev.txt | 0 {chakra_apps/counter => counter}/requirements.txt | 0 {chakra_apps/counter => counter}/rxconfig.py | 0 .../counter => counter}/tests/test_counter.py | 0 .../github-stats => github-stats}/.gitignore | 0 .../assets/favicon.ico | Bin .../github_stats/__init__.py | 0 .../github_stats/fetchers.py | 0 .../github_stats/github_stats.py | 0 .../github-stats => github-stats}/requirements.txt | 0 .../github-stats => github-stats}/rxconfig.py | 0 {chakra_apps/snakegame => snakegame}/.gitignore | 0 .../snakegame => snakegame}/assets/favicon.ico | Bin .../snakegame => snakegame}/requirements.txt | 0 {chakra_apps/snakegame => snakegame}/rxconfig.py | 0 .../snakegame => snakegame}/snakegame/__init__.py | 0 .../snakegame => snakegame}/snakegame/snakegame.py | 0 {chakra_apps/todo => todo}/.gitignore | 0 {chakra_apps/todo => todo}/assets/favicon.ico | Bin {chakra_apps/todo => todo}/requirements.txt | 0 {chakra_apps/todo => todo}/rxconfig.py | 0 {chakra_apps/todo => todo}/todo/__init__.py | 0 {chakra_apps/todo => todo}/todo/todo.py | 0 37 files changed, 0 insertions(+), 0 deletions(-) rename {chakra_apps/basic_crud => basic_crud}/.gitignore (100%) rename {chakra_apps/basic_crud => basic_crud}/README.md (100%) rename {chakra_apps/basic_crud => basic_crud}/assets/favicon.ico (100%) rename {chakra_apps/basic_crud => basic_crud}/basic_crud/__init__.py (100%) rename {chakra_apps/basic_crud => basic_crud}/basic_crud/api.py (100%) rename {chakra_apps/basic_crud => basic_crud}/basic_crud/basic_crud.py (100%) rename {chakra_apps/basic_crud => basic_crud}/basic_crud/model.py (100%) rename {chakra_apps/basic_crud => basic_crud}/basic_crud/test.http (100%) rename {chakra_apps/basic_crud => basic_crud}/requirements.txt (100%) rename {chakra_apps/basic_crud => basic_crud}/rxconfig.py (100%) rename {chakra_apps/counter => counter}/.gitignore (100%) rename {chakra_apps/counter => counter}/assets/favicon.ico (100%) rename {chakra_apps/counter => counter}/counter/__init__.py (100%) rename {chakra_apps/counter => counter}/counter/counter.py (100%) rename {chakra_apps/counter => counter}/requirements-dev.txt (100%) rename {chakra_apps/counter => counter}/requirements.txt (100%) rename {chakra_apps/counter => counter}/rxconfig.py (100%) rename {chakra_apps/counter => counter}/tests/test_counter.py (100%) rename {chakra_apps/github-stats => github-stats}/.gitignore (100%) rename {chakra_apps/github-stats => github-stats}/assets/favicon.ico (100%) rename {chakra_apps/github-stats => github-stats}/github_stats/__init__.py (100%) rename {chakra_apps/github-stats => github-stats}/github_stats/fetchers.py (100%) rename {chakra_apps/github-stats => github-stats}/github_stats/github_stats.py (100%) rename {chakra_apps/github-stats => github-stats}/requirements.txt (100%) rename {chakra_apps/github-stats => github-stats}/rxconfig.py (100%) rename {chakra_apps/snakegame => snakegame}/.gitignore (100%) rename {chakra_apps/snakegame => snakegame}/assets/favicon.ico (100%) rename {chakra_apps/snakegame => snakegame}/requirements.txt (100%) rename {chakra_apps/snakegame => snakegame}/rxconfig.py (100%) rename {chakra_apps/snakegame => snakegame}/snakegame/__init__.py (100%) rename {chakra_apps/snakegame => snakegame}/snakegame/snakegame.py (100%) rename {chakra_apps/todo => todo}/.gitignore (100%) rename {chakra_apps/todo => todo}/assets/favicon.ico (100%) rename {chakra_apps/todo => todo}/requirements.txt (100%) rename {chakra_apps/todo => todo}/rxconfig.py (100%) rename {chakra_apps/todo => todo}/todo/__init__.py (100%) rename {chakra_apps/todo => todo}/todo/todo.py (100%) diff --git a/chakra_apps/basic_crud/.gitignore b/basic_crud/.gitignore similarity index 100% rename from chakra_apps/basic_crud/.gitignore rename to basic_crud/.gitignore diff --git a/chakra_apps/basic_crud/README.md b/basic_crud/README.md similarity index 100% rename from chakra_apps/basic_crud/README.md rename to basic_crud/README.md diff --git a/chakra_apps/basic_crud/assets/favicon.ico b/basic_crud/assets/favicon.ico similarity index 100% rename from chakra_apps/basic_crud/assets/favicon.ico rename to basic_crud/assets/favicon.ico diff --git a/chakra_apps/basic_crud/basic_crud/__init__.py b/basic_crud/basic_crud/__init__.py similarity index 100% rename from chakra_apps/basic_crud/basic_crud/__init__.py rename to basic_crud/basic_crud/__init__.py diff --git a/chakra_apps/basic_crud/basic_crud/api.py b/basic_crud/basic_crud/api.py similarity index 100% rename from chakra_apps/basic_crud/basic_crud/api.py rename to basic_crud/basic_crud/api.py diff --git a/chakra_apps/basic_crud/basic_crud/basic_crud.py b/basic_crud/basic_crud/basic_crud.py similarity index 100% rename from chakra_apps/basic_crud/basic_crud/basic_crud.py rename to basic_crud/basic_crud/basic_crud.py diff --git a/chakra_apps/basic_crud/basic_crud/model.py b/basic_crud/basic_crud/model.py similarity index 100% rename from chakra_apps/basic_crud/basic_crud/model.py rename to basic_crud/basic_crud/model.py diff --git a/chakra_apps/basic_crud/basic_crud/test.http b/basic_crud/basic_crud/test.http similarity index 100% rename from chakra_apps/basic_crud/basic_crud/test.http rename to basic_crud/basic_crud/test.http diff --git a/chakra_apps/basic_crud/requirements.txt b/basic_crud/requirements.txt similarity index 100% rename from chakra_apps/basic_crud/requirements.txt rename to basic_crud/requirements.txt diff --git a/chakra_apps/basic_crud/rxconfig.py b/basic_crud/rxconfig.py similarity index 100% rename from chakra_apps/basic_crud/rxconfig.py rename to basic_crud/rxconfig.py diff --git a/chakra_apps/counter/.gitignore b/counter/.gitignore similarity index 100% rename from chakra_apps/counter/.gitignore rename to counter/.gitignore diff --git a/chakra_apps/counter/assets/favicon.ico b/counter/assets/favicon.ico similarity index 100% rename from chakra_apps/counter/assets/favicon.ico rename to counter/assets/favicon.ico diff --git a/chakra_apps/counter/counter/__init__.py b/counter/counter/__init__.py similarity index 100% rename from chakra_apps/counter/counter/__init__.py rename to counter/counter/__init__.py diff --git a/chakra_apps/counter/counter/counter.py b/counter/counter/counter.py similarity index 100% rename from chakra_apps/counter/counter/counter.py rename to counter/counter/counter.py diff --git a/chakra_apps/counter/requirements-dev.txt b/counter/requirements-dev.txt similarity index 100% rename from chakra_apps/counter/requirements-dev.txt rename to counter/requirements-dev.txt diff --git a/chakra_apps/counter/requirements.txt b/counter/requirements.txt similarity index 100% rename from chakra_apps/counter/requirements.txt rename to counter/requirements.txt diff --git a/chakra_apps/counter/rxconfig.py b/counter/rxconfig.py similarity index 100% rename from chakra_apps/counter/rxconfig.py rename to counter/rxconfig.py diff --git a/chakra_apps/counter/tests/test_counter.py b/counter/tests/test_counter.py similarity index 100% rename from chakra_apps/counter/tests/test_counter.py rename to counter/tests/test_counter.py diff --git a/chakra_apps/github-stats/.gitignore b/github-stats/.gitignore similarity index 100% rename from chakra_apps/github-stats/.gitignore rename to github-stats/.gitignore diff --git a/chakra_apps/github-stats/assets/favicon.ico b/github-stats/assets/favicon.ico similarity index 100% rename from chakra_apps/github-stats/assets/favicon.ico rename to github-stats/assets/favicon.ico diff --git a/chakra_apps/github-stats/github_stats/__init__.py b/github-stats/github_stats/__init__.py similarity index 100% rename from chakra_apps/github-stats/github_stats/__init__.py rename to github-stats/github_stats/__init__.py diff --git a/chakra_apps/github-stats/github_stats/fetchers.py b/github-stats/github_stats/fetchers.py similarity index 100% rename from chakra_apps/github-stats/github_stats/fetchers.py rename to github-stats/github_stats/fetchers.py diff --git a/chakra_apps/github-stats/github_stats/github_stats.py b/github-stats/github_stats/github_stats.py similarity index 100% rename from chakra_apps/github-stats/github_stats/github_stats.py rename to github-stats/github_stats/github_stats.py diff --git a/chakra_apps/github-stats/requirements.txt b/github-stats/requirements.txt similarity index 100% rename from chakra_apps/github-stats/requirements.txt rename to github-stats/requirements.txt diff --git a/chakra_apps/github-stats/rxconfig.py b/github-stats/rxconfig.py similarity index 100% rename from chakra_apps/github-stats/rxconfig.py rename to github-stats/rxconfig.py diff --git a/chakra_apps/snakegame/.gitignore b/snakegame/.gitignore similarity index 100% rename from chakra_apps/snakegame/.gitignore rename to snakegame/.gitignore diff --git a/chakra_apps/snakegame/assets/favicon.ico b/snakegame/assets/favicon.ico similarity index 100% rename from chakra_apps/snakegame/assets/favicon.ico rename to snakegame/assets/favicon.ico diff --git a/chakra_apps/snakegame/requirements.txt b/snakegame/requirements.txt similarity index 100% rename from chakra_apps/snakegame/requirements.txt rename to snakegame/requirements.txt diff --git a/chakra_apps/snakegame/rxconfig.py b/snakegame/rxconfig.py similarity index 100% rename from chakra_apps/snakegame/rxconfig.py rename to snakegame/rxconfig.py diff --git a/chakra_apps/snakegame/snakegame/__init__.py b/snakegame/snakegame/__init__.py similarity index 100% rename from chakra_apps/snakegame/snakegame/__init__.py rename to snakegame/snakegame/__init__.py diff --git a/chakra_apps/snakegame/snakegame/snakegame.py b/snakegame/snakegame/snakegame.py similarity index 100% rename from chakra_apps/snakegame/snakegame/snakegame.py rename to snakegame/snakegame/snakegame.py diff --git a/chakra_apps/todo/.gitignore b/todo/.gitignore similarity index 100% rename from chakra_apps/todo/.gitignore rename to todo/.gitignore diff --git a/chakra_apps/todo/assets/favicon.ico b/todo/assets/favicon.ico similarity index 100% rename from chakra_apps/todo/assets/favicon.ico rename to todo/assets/favicon.ico diff --git a/chakra_apps/todo/requirements.txt b/todo/requirements.txt similarity index 100% rename from chakra_apps/todo/requirements.txt rename to todo/requirements.txt diff --git a/chakra_apps/todo/rxconfig.py b/todo/rxconfig.py similarity index 100% rename from chakra_apps/todo/rxconfig.py rename to todo/rxconfig.py diff --git a/chakra_apps/todo/todo/__init__.py b/todo/todo/__init__.py similarity index 100% rename from chakra_apps/todo/todo/__init__.py rename to todo/todo/__init__.py diff --git a/chakra_apps/todo/todo/todo.py b/todo/todo/todo.py similarity index 100% rename from chakra_apps/todo/todo/todo.py rename to todo/todo/todo.py From 6a8e76b8e686201f2cb4bb1e9ba648ca3a9ee062 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 15:31:23 -0800 Subject: [PATCH 18/45] Update requirements to use reflex>=0.4.0a1 --- basic_crud/requirements.txt | 2 +- counter/requirements.txt | 2 +- github-stats/requirements.txt | 2 +- snakegame/requirements.txt | 2 +- todo/requirements.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/basic_crud/requirements.txt b/basic_crud/requirements.txt index 11eb7423..98df420a 100644 --- a/basic_crud/requirements.txt +++ b/basic_crud/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 \ No newline at end of file +reflex>=0.4.0a1 diff --git a/counter/requirements.txt b/counter/requirements.txt index 1988f5e0..98df420a 100644 --- a/counter/requirements.txt +++ b/counter/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 +reflex>=0.4.0a1 diff --git a/github-stats/requirements.txt b/github-stats/requirements.txt index 1988f5e0..98df420a 100644 --- a/github-stats/requirements.txt +++ b/github-stats/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 +reflex>=0.4.0a1 diff --git a/snakegame/requirements.txt b/snakegame/requirements.txt index 11eb7423..98df420a 100644 --- a/snakegame/requirements.txt +++ b/snakegame/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 \ No newline at end of file +reflex>=0.4.0a1 diff --git a/todo/requirements.txt b/todo/requirements.txt index 1988f5e0..98df420a 100644 --- a/todo/requirements.txt +++ b/todo/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 +reflex>=0.4.0a1 From 06eb317fd34b66706f1733b7f7c08deae3bc5e81 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 15:45:54 -0800 Subject: [PATCH 19/45] snakegame: hide the padding buttons --- snakegame/snakegame/snakegame.py | 1 + 1 file changed, 1 insertion(+) diff --git a/snakegame/snakegame/snakegame.py b/snakegame/snakegame/snakegame.py index 58e04ac9..92b4c674 100644 --- a/snakegame/snakegame/snakegame.py +++ b/snakegame/snakegame/snakegame.py @@ -268,6 +268,7 @@ def padding_button(): "○", border_radius="1em", font_size="2em", + visibility="hidden", ) From 0ad4313a9349422dc9c710a9a9fd4b65a4b90585 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 15:52:34 -0800 Subject: [PATCH 20/45] basic_crud: replace spacing with gap and separator with divider --- basic_crud/basic_crud/basic_crud.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/basic_crud/basic_crud/basic_crud.py b/basic_crud/basic_crud/basic_crud.py index fc14cd56..171f007b 100644 --- a/basic_crud/basic_crud/basic_crud.py +++ b/basic_crud/basic_crud/basic_crud.py @@ -123,13 +123,13 @@ def render_product(product: Product): rx.vstack( rx.text("Stock:", product.quantity), rx.text("Category:", product.category), - spacing="0", + gap="0", width="7vw", ), rx.vstack( rx.text("Seller:", product.seller), rx.text("Sender:", product.sender), - spacing="0", + gap="0", width="7vw", ), rx.spacer(), @@ -161,7 +161,7 @@ def query_form(): rx.button("Clear", on_click=QueryState.clear_query), rx.button("Send", on_click=QueryState.send_query), ), - rx.separator(orientation="horizontal", border="solid black 1px", width="100%"), + rx.divider(orientation="horizontal", border="solid black 1px", width="100%"), rx.hstack( rx.text("Status: ", QueryState.response_code), rx.spacer(), width="100%" ), @@ -182,12 +182,12 @@ def index() -> rx.Component: rx.spacer(), data_display(), rx.spacer(), - rx.separator(orientation="vertical", border="solid black 1px"), + rx.divider(orientation="vertical", border="solid black 1px"), query_form(), rx.spacer(), height="100vh", width="100vw", - spacing="0", + gap="0", ) From 7b0f5012089df54d51884561933db19fecf5e68f Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 16:07:34 -0800 Subject: [PATCH 21/45] todo: fix up styling, use radix colors --- todo/todo/todo.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/todo/todo/todo.py b/todo/todo/todo.py index 34904580..ea4b2ba2 100644 --- a/todo/todo/todo.py +++ b/todo/todo/todo.py @@ -44,7 +44,7 @@ def todo_item(item: rx.Var[str]) -> rx.Component: margin="0 1em 1em 0" ), # The item text. - rx.text(item), + rx.text(item, as_="span"), ) @@ -90,13 +90,14 @@ def index() -> rx.Component: rx.vstack( rx.heading("Todos"), new_item(), - rx.separator(), + rx.divider(), todo_list(), - bg="#ededed", - margin="5em", + bg=rx.color("gray", 7), + margin_top="5em", + margin_x="25vw", padding="1em", border_radius="0.5em", - shadow="lg", + box_shadow=f"{rx.color('gray', 3, alpha=True)} 0px 1px 4px", ) ) From a3e48b725263b39d5134812a1f728c6663e290c7 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 13 Feb 2024 16:16:10 -0800 Subject: [PATCH 22/45] convert nba radix to nba --- {nba_radix => nba}/.gitignore | 0 {nba_radix => nba}/assets/favicon.ico | Bin {nba_radix => nba}/assets/nba.png | Bin {nba_radix/nba_radix => nba/nba}/__init__.py | 0 nba/nba/helpers.py | 20 ++++----- .../nba_radix/nba_radix.py => nba/nba/nba.py | 0 {nba_radix => nba}/requirements.txt | 2 +- {nba_radix => nba}/rxconfig.py | 2 +- nba_radix/nba_radix/helpers.py | 40 ------------------ 9 files changed, 12 insertions(+), 52 deletions(-) rename {nba_radix => nba}/.gitignore (100%) rename {nba_radix => nba}/assets/favicon.ico (100%) rename {nba_radix => nba}/assets/nba.png (100%) rename {nba_radix/nba_radix => nba/nba}/__init__.py (100%) rename nba_radix/nba_radix/nba_radix.py => nba/nba/nba.py (100%) rename {nba_radix => nba}/requirements.txt (67%) rename {nba_radix => nba}/rxconfig.py (61%) delete mode 100644 nba_radix/nba_radix/helpers.py diff --git a/nba_radix/.gitignore b/nba/.gitignore similarity index 100% rename from nba_radix/.gitignore rename to nba/.gitignore diff --git a/nba_radix/assets/favicon.ico b/nba/assets/favicon.ico similarity index 100% rename from nba_radix/assets/favicon.ico rename to nba/assets/favicon.ico diff --git a/nba_radix/assets/nba.png b/nba/assets/nba.png similarity index 100% rename from nba_radix/assets/nba.png rename to nba/assets/nba.png diff --git a/nba_radix/nba_radix/__init__.py b/nba/nba/__init__.py similarity index 100% rename from nba_radix/nba_radix/__init__.py rename to nba/nba/__init__.py diff --git a/nba/nba/helpers.py b/nba/nba/helpers.py index 52e28858..86c06a13 100644 --- a/nba/nba/helpers.py +++ b/nba/nba/helpers.py @@ -10,22 +10,22 @@ def navbar(): rx.badge("2015-2016 Season"), ), ), - rx.menu.root( - rx.menu.trigger( + rx.dropdown_menu.root( + rx.dropdown_menu.trigger( rx.button("Menu", color="white", size="3", radius="medium", px=4, py=2), ), - rx.menu.content( - rx.menu.item("Graph"), - rx.menu.separator(), - rx.menu.item( - rx.link( - rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")), - href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", + rx.dropdown_menu.content( + rx.link(rx.dropdown_menu.item("Graph"), href="/"), + rx.dropdown_menu.separator(), + rx.link( + rx.dropdown_menu.item( + rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")) ), + href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), ), ), - justify="between", + justify="space-between", border_bottom="0.2em solid #F0F0F0", padding_inline_start="2em", padding_inline_end="2em", diff --git a/nba_radix/nba_radix/nba_radix.py b/nba/nba/nba.py similarity index 100% rename from nba_radix/nba_radix/nba_radix.py rename to nba/nba/nba.py diff --git a/nba_radix/requirements.txt b/nba/requirements.txt similarity index 67% rename from nba_radix/requirements.txt rename to nba/requirements.txt index 60b93853..9166e192 100644 --- a/nba_radix/requirements.txt +++ b/nba/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.3.8 +reflex>=0.4.0 pandas>=2.2.0 plotly>=5.18.0 diff --git a/nba_radix/rxconfig.py b/nba/rxconfig.py similarity index 61% rename from nba_radix/rxconfig.py rename to nba/rxconfig.py index 919ea29a..3879277b 100644 --- a/nba_radix/rxconfig.py +++ b/nba/rxconfig.py @@ -1,5 +1,5 @@ import reflex as rx config = rx.Config( - app_name="nba_radix", + app_name="nba", ) \ No newline at end of file diff --git a/nba_radix/nba_radix/helpers.py b/nba_radix/nba_radix/helpers.py deleted file mode 100644 index 86c06a13..00000000 --- a/nba_radix/nba_radix/helpers.py +++ /dev/null @@ -1,40 +0,0 @@ -import reflex as rx - -def navbar(): - return rx.box( - rx.hstack( - rx.hstack( - rx.image(src="/nba.png", width="50px"), - rx.heading("NBA Data", size="8"), - rx.flex( - rx.badge("2015-2016 Season"), - ), - ), - rx.dropdown_menu.root( - rx.dropdown_menu.trigger( - rx.button("Menu", color="white", size="3", radius="medium", px=4, py=2), - ), - rx.dropdown_menu.content( - rx.link(rx.dropdown_menu.item("Graph"), href="/"), - rx.dropdown_menu.separator(), - rx.link( - rx.dropdown_menu.item( - rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")) - ), - href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", - ), - ), - ), - justify="space-between", - border_bottom="0.2em solid #F0F0F0", - padding_inline_start="2em", - padding_inline_end="2em", - padding_top="1em", - padding_bottom="1em", - bg="rgba(255,255,255, 0.97)", - ), - position="fixed", - width="100%", - top="0px", - z_index="500", - ) \ No newline at end of file From ce269531c8101b7bb460d5195272dc645dbb4ff5 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 13 Feb 2024 16:19:30 -0800 Subject: [PATCH 23/45] final nab changes --- nba/nba/helpers.py | 20 ++++++++++---------- nba/nba/nba.py | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/nba/nba/helpers.py b/nba/nba/helpers.py index 86c06a13..52e28858 100644 --- a/nba/nba/helpers.py +++ b/nba/nba/helpers.py @@ -10,22 +10,22 @@ def navbar(): rx.badge("2015-2016 Season"), ), ), - rx.dropdown_menu.root( - rx.dropdown_menu.trigger( + rx.menu.root( + rx.menu.trigger( rx.button("Menu", color="white", size="3", radius="medium", px=4, py=2), ), - rx.dropdown_menu.content( - rx.link(rx.dropdown_menu.item("Graph"), href="/"), - rx.dropdown_menu.separator(), - rx.link( - rx.dropdown_menu.item( - rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")) + rx.menu.content( + rx.menu.item("Graph"), + rx.menu.separator(), + rx.menu.item( + rx.link( + rx.hstack(rx.text("20Dataset"), rx.icon(tag="download")), + href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), - href="https://media.geeksforgeeks.org/wp-content/uploads/nba.csv", ), ), ), - justify="space-between", + justify="between", border_bottom="0.2em solid #F0F0F0", padding_inline_start="2em", padding_inline_end="2em", diff --git a/nba/nba/nba.py b/nba/nba/nba.py index b8ff17a6..78dcd3eb 100644 --- a/nba/nba/nba.py +++ b/nba/nba/nba.py @@ -95,7 +95,7 @@ def selection(): rx.vstack( rx.hstack( rx.badge("Min Age: ", State.age[0]), - rx.separator(orientation="vertical"), + rx.divider(orientation="vertical"), rx.badge("Max Age: ", State.age[1]), ), rx.slider(default_value=[18, 50], min=18, max=50, on_value_commit=State.set_age,), @@ -105,7 +105,7 @@ def selection(): rx.vstack( rx.hstack( rx.badge("Min Sal: ", State.salary[0] // 1000000, "M"), - rx.separator(orientation="vertical"), + rx.divider(orientation="vertical"), rx.badge("Max Sal: ", State.salary[1] // 1000000, "M"), ), rx.slider( @@ -115,7 +115,7 @@ def selection(): width="100%", ), ), - spacing="1em", + spacing="4", ), width="100%", ) @@ -127,7 +127,7 @@ def index(): rx.vstack( navbar(), selection(), - rx.separator(width="100%"), + rx.divider(width="100%"), rx.plotly(data=State.scat_fig, layout={"width": "1000", "height": "600"}), rx.plotly(data=State.hist_fig, layout={"width": "1000", "height": "600"}), rx.data_table( @@ -137,7 +137,7 @@ def index(): sort=True, resizable=True, ), - rx.separator(width="100%"), + rx.divider(width="100%"), padding_top="6em", width="100%", ) From ec94ff3ea49224104bb36c657ebfa69612c4de74 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 13 Feb 2024 16:54:54 -0800 Subject: [PATCH 24/45] twitter app in radix --- twitter/.gitignore | 4 + twitter/assets/favicon.ico | Bin 0 -> 4286 bytes twitter/requirements.txt | 1 + twitter/rxconfig.py | 5 + twitter/twitter/__init__.py | 0 twitter/twitter/components/__init__.py | 2 + twitter/twitter/components/container.py | 21 +++ twitter/twitter/db_model.py | 29 ++++ twitter/twitter/layouts/__init__.py | 2 + twitter/twitter/layouts/auth.py | 44 +++++ twitter/twitter/pages/__init__.py | 4 + twitter/twitter/pages/home.py | 222 ++++++++++++++++++++++++ twitter/twitter/pages/login.py | 39 +++++ twitter/twitter/pages/signup.py | 45 +++++ twitter/twitter/state/auth.py | 38 ++++ twitter/twitter/state/base.py | 25 +++ twitter/twitter/state/home.py | 94 ++++++++++ twitter/twitter/twitter.py | 14 ++ 18 files changed, 589 insertions(+) create mode 100644 twitter/.gitignore create mode 100644 twitter/assets/favicon.ico create mode 100644 twitter/requirements.txt create mode 100644 twitter/rxconfig.py create mode 100644 twitter/twitter/__init__.py create mode 100644 twitter/twitter/components/__init__.py create mode 100644 twitter/twitter/components/container.py create mode 100644 twitter/twitter/db_model.py create mode 100644 twitter/twitter/layouts/__init__.py create mode 100644 twitter/twitter/layouts/auth.py create mode 100644 twitter/twitter/pages/__init__.py create mode 100644 twitter/twitter/pages/home.py create mode 100644 twitter/twitter/pages/login.py create mode 100644 twitter/twitter/pages/signup.py create mode 100644 twitter/twitter/state/auth.py create mode 100644 twitter/twitter/state/base.py create mode 100644 twitter/twitter/state/home.py create mode 100644 twitter/twitter/twitter.py diff --git a/twitter/.gitignore b/twitter/.gitignore new file mode 100644 index 00000000..eab0d4b0 --- /dev/null +++ b/twitter/.gitignore @@ -0,0 +1,4 @@ +*.db +*.py[cod] +.web +__pycache__/ \ No newline at end of file diff --git a/twitter/assets/favicon.ico b/twitter/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..166ae995eaa63fc96771410a758282dc30e925cf GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 0 HcmV?d00001 diff --git a/twitter/requirements.txt b/twitter/requirements.txt new file mode 100644 index 00000000..d4deee8a --- /dev/null +++ b/twitter/requirements.txt @@ -0,0 +1 @@ +reflex>=0.4.0 diff --git a/twitter/rxconfig.py b/twitter/rxconfig.py new file mode 100644 index 00000000..929a4c85 --- /dev/null +++ b/twitter/rxconfig.py @@ -0,0 +1,5 @@ +import reflex as rx + +config = rx.Config( + app_name="twitter", +) \ No newline at end of file diff --git a/twitter/twitter/__init__.py b/twitter/twitter/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/twitter/twitter/components/__init__.py b/twitter/twitter/components/__init__.py new file mode 100644 index 00000000..36af241f --- /dev/null +++ b/twitter/twitter/components/__init__.py @@ -0,0 +1,2 @@ +"""Re-export components.""" +from .container import container \ No newline at end of file diff --git a/twitter/twitter/components/container.py b/twitter/twitter/components/container.py new file mode 100644 index 00000000..d6597554 --- /dev/null +++ b/twitter/twitter/components/container.py @@ -0,0 +1,21 @@ +"""A container component.""" +import reflex as rx + +def container(*children, **props): + """A fixed container based on a 960px grid.""" + # Enable override of default props. + props = ( + dict( + width="100%", + max_width="960px", + background="white", + height="100%", + #px=[4, 12], + px="9", + + margin="0 auto", + position="relative", + ) + | props + ) + return rx.box(*children, **props) diff --git a/twitter/twitter/db_model.py b/twitter/twitter/db_model.py new file mode 100644 index 00000000..2f8c2620 --- /dev/null +++ b/twitter/twitter/db_model.py @@ -0,0 +1,29 @@ +from sqlmodel import Field + +import reflex as rx + + +class Follows(rx.Model, table=True): + """A table of Follows. This is a many-to-many join table. + + See https://sqlmodel.tiangolo.com/tutorial/many-to-many/ for more information. + """ + + followed_username: str = Field(primary_key=True) + follower_username: str = Field(primary_key=True) + + +class User(rx.Model, table=True): + """A table of Users.""" + + username: str = Field() + password: str = Field() + + +class Tweet(rx.Model, table=True): + """A table of Tweets.""" + + content: str = Field() + created_at: str = Field() + + author: str = Field() \ No newline at end of file diff --git a/twitter/twitter/layouts/__init__.py b/twitter/twitter/layouts/__init__.py new file mode 100644 index 00000000..401a24b8 --- /dev/null +++ b/twitter/twitter/layouts/__init__.py @@ -0,0 +1,2 @@ +"""Re-export layouts.""" +from .auth import auth_layout diff --git a/twitter/twitter/layouts/auth.py b/twitter/twitter/layouts/auth.py new file mode 100644 index 00000000..f83f2637 --- /dev/null +++ b/twitter/twitter/layouts/auth.py @@ -0,0 +1,44 @@ +"""Shared auth layout.""" +import reflex as rx + +from ..components import container + + +def auth_layout(*args): + """The shared layout for the login and sign up pages.""" + return rx.box( + container( + rx.heading( + rx.chakra.span("Welcome to PySocial!"), + rx.chakra.span("Sign in or sign up to get started."), + display="flex", + flex_direction="column", + align_items="center", + text_align="center", + ), + rx.text( + "See the source code for this demo app ", + rx.link( + "here", + href="https://github.com/reflex-dev/reflex-examples/tree/main/twitter", + ), + ".", + color="gray", + font_weight="medium", + ), + *args, + border_top_radius="10px", + box_shadow="0 4px 60px 0 rgba(0, 0, 0, 0.08), 0 4px 16px 0 rgba(0, 0, 0, 0.08)", + display="flex", + flex_direction="column", + align_items="center", + padding_top="36px", + padding_bottom="24px", + gap="1rem", + ), + height="100vh", + padding_top="40px", + background="url(bg.svg)", + background_repeat="no-repeat", + background_size="cover", + ) diff --git a/twitter/twitter/pages/__init__.py b/twitter/twitter/pages/__init__.py new file mode 100644 index 00000000..98ea440f --- /dev/null +++ b/twitter/twitter/pages/__init__.py @@ -0,0 +1,4 @@ +"""Re-export pages.""" +from .home import home +from .login import login +from .signup import signup diff --git a/twitter/twitter/pages/home.py b/twitter/twitter/pages/home.py new file mode 100644 index 00000000..a88a1647 --- /dev/null +++ b/twitter/twitter/pages/home.py @@ -0,0 +1,222 @@ +"""The home page. This file includes examples abstracting complex UI into smaller components.""" +import reflex as rx +from twitter.state.base import State +from twitter.state.home import HomeState + +from ..components import container + + +def tab_button(name, href): + """A tab switcher button.""" + return rx.link( + rx.flex(rx.icon(tag="star"), margin_right="1rem"), + name, + display="inline-flex", + align_items="center", + padding="0.75rem", + href=href, + border="1px solid #eaeaea", + font_weight="semibold", + border_radius="2rem", + ) + + +def tabs(): + """The tab switcher displayed on the left.""" + return rx.box( + rx.vstack( + rx.heading("PySocial", size="5"), + tab_button("Home", "/"), + rx.box( + rx.heading("Followers", size="3"), + rx.foreach( + HomeState.followers, + lambda follow: rx.vstack( + rx.hstack( + rx.avatar(fallback=follow.follower_username, size="3"), + rx.text(follow.follower_username), + ), + padding="1em", + ), + ), + padding="2rem", + border_radius="0.5rem", + border="1px solid #eaeaea", + ), + rx.button("Sign out", on_click=State.logout, size="3"), + align_items="left", + gap="4", + ), + padding_top="2rem", + padding_bottom="2rem", + ) + + +def sidebar(HomeState): + """The sidebar displayed on the right.""" + return rx.vstack( + rx.input( + on_change=HomeState.set_friend, + placeholder="Search users", + width="100%", + ), + rx.foreach( + HomeState.search_users, + lambda user: rx.vstack( + rx.hstack( + rx.avatar(fallback=user.username, size="3"), + rx.text(user.username), + rx.spacer(), + rx.button( + rx.icon(tag="plus"), + on_click=lambda: HomeState.follow_user(user.username), + ), + width="100%", + ), + padding_top="1rem", + padding_bottom="1rem", + width="100%", + ), + ), + rx.box( + rx.heading("Following", size="3"), + rx.foreach( + HomeState.following, + lambda follow: rx.vstack( + rx.hstack( + rx.avatar(fallback=follow.followed_username, size="3"), + rx.text(follow.followed_username), + ), + padding="1em", + ), + ), + padding="2rem", + border_radius="0.5rem", + border="1px solid #eaeaea", + width="100%", + ), + align_items="start", + gap="4", + height="100%", + padding_top="2rem", + padding_bottom="2rem", + ) + + +def feed_header(HomeState): + """The header of the feed.""" + return rx.hstack( + rx.heading("Home", size="5"), + rx.input(on_change=HomeState.set_search, placeholder="Search tweets"), + justify="between", + padding="1.5rem", + border_bottom="1px solid #ededed", + ) + + +def composer(HomeState): + """The composer for new tweets.""" + return rx.grid( + rx.vstack( + rx.avatar(fallback=State.user.username.to_string(), size="4"), + padding="1.5rem", + ), + rx.box( + rx.flex( + rx.text_area( + width="100%", + #border="none", + # padding_top="1rem", + # padding_bottom="1rem", + placeholder="What's happening?", + resize="none", + _focus={"border": 0, "outline": 0, "boxShadow": "none"}, + on_blur=HomeState.set_tweet, + ), + padding_top="1.5rem", + padding_bottom="1.5rem", + ), + + rx.hstack( + rx.button( + "Tweet", + on_click=HomeState.post_tweet, + color="white", + radius="full", + size="3", + ), + justify_content="flex-end", + border_top="1px solid #ededed", + padding_inline_start="1.5em", + padding_inline_end="1.5em", + padding_top="0.75rem", + padding_bottom="0.75rem", + ), + ), + grid_template_columns="1fr 5fr", + border_bottom="1px solid #ededed", + ) + + +def tweet(tweet): + """Display for an individual tweet in the feed.""" + return rx.grid( + rx.vstack( + rx.avatar(fallback=tweet.author, size="3"), + ), + rx.box( + rx.vstack( + rx.text("@" + tweet.author, font_weight="bold"), + rx.text(tweet.content, width="100%"), + align_items="left", + ), + ), + grid_template_columns="1fr 5fr", + padding_top="1.5rem", + padding_bottom="1.5rem", + gap="1", + border_bottom="1px solid #ededed", + ) + + +def feed(HomeState): + """The feed.""" + return rx.box( + feed_header(HomeState), + composer(HomeState), + rx.cond( + HomeState.tweets, + rx.foreach( + HomeState.tweets, + tweet, + ), + rx.vstack( + rx.button( + rx.icon( + tag="rotate-cw", + ), + rx.text("Click to load tweets"), + on_click=HomeState.get_tweets, + ), + padding="1.5rem", + ), + ), + border_left="1px solid #ededed", + border_right="1px solid #ededed", + height="100%", + ) + + +def home(): + """The home page.""" + return container( + rx.grid( + tabs(), + feed(HomeState), + sidebar(HomeState), + grid_template_columns="1fr 2fr 1fr", + height="100vh", + gap="4", + ), + max_width="1300px", + ) diff --git a/twitter/twitter/pages/login.py b/twitter/twitter/pages/login.py new file mode 100644 index 00000000..96755b65 --- /dev/null +++ b/twitter/twitter/pages/login.py @@ -0,0 +1,39 @@ +"""Login page. Uses auth_layout to render UI shared with the sign up page.""" +import reflex as rx +from twitter.layouts import auth_layout +from twitter.state.auth import AuthState + + +def login(): + """The login page.""" + return auth_layout( + rx.box( + rx.vstack( + rx.input(placeholder="Username", on_blur=AuthState.set_username, margin_bottom="12px",), + rx.input( + type_="password", + placeholder="Password", + on_blur=AuthState.set_password, + margin_bottom="12px", + ), + rx.button( + "Log in", + on_click=AuthState.login, + color="white", + size="3", + ), + spacing="3", + ), + align_items="left", + background="white", + border="1px solid #eaeaea", + padding="16px", + max_width="400px", + border_radius="8px", + ), + rx.text( + "Don't have an account yet? ", + rx.link("Sign up here.", href="/signup"), + color="gray", + ), + ) diff --git a/twitter/twitter/pages/signup.py b/twitter/twitter/pages/signup.py new file mode 100644 index 00000000..ba2cb298 --- /dev/null +++ b/twitter/twitter/pages/signup.py @@ -0,0 +1,45 @@ +"""Sign up page. Uses auth_layout to render UI shared with the login page.""" +import reflex as rx +from twitter.layouts import auth_layout +from twitter.state.auth import AuthState + + +def signup(): + """The sign up page.""" + return auth_layout( + rx.box( + rx.vstack( + rx.input(placeholder="Username", on_blur=AuthState.set_username, margin_bottom="12px",), + rx.input( + type_="password", + placeholder="Password", + on_blur=AuthState.set_password, + margin_bottom="12px", + ), + rx.input( + type_="password", + placeholder="Confirm password", + on_blur=AuthState.set_confirm_password, + margin_bottom="12px", + ), + rx.button( + "Sign up", + on_click=AuthState.signup, + color="white", + size="3", + ), + spacing="3", + ), + align_items="left", + background="white", + border="1px solid #eaeaea", + padding="16px", + max_width="400px", + border_radius="8px", + ), + rx.text( + "Already have an account? ", + rx.link("Sign in here.", href="/"), + color="gray", + ), + ) diff --git a/twitter/twitter/state/auth.py b/twitter/twitter/state/auth.py new file mode 100644 index 00000000..67da8a6b --- /dev/null +++ b/twitter/twitter/state/auth.py @@ -0,0 +1,38 @@ +"""The authentication state.""" +import reflex as rx +from sqlmodel import select + +from .base import State, User + + +class AuthState(State): + """The authentication state for sign up and login page.""" + + username: str + password: str + confirm_password: str + + def signup(self): + """Sign up a user.""" + with rx.session() as session: + if self.password != self.confirm_password: + return rx.window_alert("Passwords do not match.") + if session.exec(select(User).where(User.username == self.username)).first(): + return rx.window_alert("Username already exists.") + self.user = User(username=self.username, password=self.password) + session.add(self.user) + session.expire_on_commit = False + session.commit() + return rx.redirect("/") + + def login(self): + """Log in a user.""" + with rx.session() as session: + user = session.exec( + select(User).where(User.username == self.username) + ).first() + if user and user.password == self.password: + self.user = user + return rx.redirect("/") + else: + return rx.window_alert("Invalid username or password.") diff --git a/twitter/twitter/state/base.py b/twitter/twitter/state/base.py new file mode 100644 index 00000000..fd77fece --- /dev/null +++ b/twitter/twitter/state/base.py @@ -0,0 +1,25 @@ +"""Base state for Twitter example. Schema is inspired by https://drawsql.app/templates/twitter.""" +from typing import Optional + +import reflex as rx +from twitter.db_model import User + +class State(rx.State): + """The base state for the app.""" + + user: Optional[User] = None + + def logout(self): + """Log out a user.""" + self.reset() + return rx.redirect("/") + + def check_login(self): + """Check if a user is logged in.""" + if not self.logged_in: + return rx.redirect("/login") + + @rx.var + def logged_in(self): + """Check if a user is logged in.""" + return self.user is not None diff --git a/twitter/twitter/state/home.py b/twitter/twitter/state/home.py new file mode 100644 index 00000000..fbe2ae1b --- /dev/null +++ b/twitter/twitter/state/home.py @@ -0,0 +1,94 @@ +"""The state for the home page.""" +from datetime import datetime + +import reflex as rx +from sqlmodel import select + +from .base import State +from twitter.db_model import Follows, Tweet, User + +class HomeState(State): + """The state for the home page.""" + + tweet: str + tweets: list[Tweet] = [] + + friend: str + search: str + + def post_tweet(self): + """Post a tweet.""" + if not self.logged_in: + return rx.window_alert("Please log in to post a tweet.") + with rx.session() as session: + tweet = Tweet( + author=self.user.username, + content=self.tweet, + created_at=datetime.now().strftime("%m/%d %H"), + ) + session.add(tweet) + session.commit() + return self.get_tweets() + + def get_tweets(self): + """Get tweets from the database.""" + with rx.session() as session: + if self.search: + self.tweets = session.exec( + select(Tweet).where(Tweet.content.contains(self.search)) + ).all()[::-1] + else: + self.tweets = session.exec(select(Tweet)).all()[::-1] + + def set_search(self, search): + """Set the search query.""" + self.search = search + return self.get_tweets() + + def follow_user(self, username): + """Follow a user.""" + with rx.session() as session: + friend = Follows( + follower_username=self.user.username, followed_username=username + ) + session.add(friend) + session.commit() + + @rx.var + def following(self) -> list[Follows]: + """Get a list of users the current user is following.""" + if self.logged_in: + with rx.session() as session: + return session.exec( + select(Follows).where( + Follows.follower_username == self.user.username + ) + ).all() + return [] + + @rx.var + def followers(self) -> list[Follows]: + """Get a list of users following the current user.""" + if self.logged_in: + with rx.session() as session: + return session.exec( + select(Follows).where( + Follows.followed_username == self.user.username + ) + ).all() + return [] + + @rx.var + def search_users(self) -> list[User]: + """Get a list of users matching the search query.""" + if self.friend != "": + with rx.session() as session: + current_username = self.user.username if self.user is not None else "" + users = session.exec( + select(User).where( + User.username.contains(self.friend), + User.username != current_username, + ) + ).all() + return users + return [] diff --git a/twitter/twitter/twitter.py b/twitter/twitter/twitter.py new file mode 100644 index 00000000..03dce610 --- /dev/null +++ b/twitter/twitter/twitter.py @@ -0,0 +1,14 @@ +"""Welcome to Reflex! This file outlines the steps to create a basic app.""" +import reflex as rx +from reflex.components.radix.themes import theme + +from .pages import home, login, signup +from .state.base import State + + +app = rx.App( + theme=theme(appearance="light", has_background=True, radius="large", accent_color="teal") +) +app.add_page(login) +app.add_page(signup) +app.add_page(home, route="/", on_load=State.check_login()) From ca0ce465041d8a04b9af6432428bdf4348d96ef0 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 13 Feb 2024 17:11:36 -0800 Subject: [PATCH 25/45] updates from martins comments --- twitter/twitter/components/container.py | 2 -- twitter/twitter/db_model.py | 10 +++++----- twitter/twitter/layouts/auth.py | 6 +++--- twitter/twitter/pages/home.py | 11 ++++------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/twitter/twitter/components/container.py b/twitter/twitter/components/container.py index d6597554..334f3706 100644 --- a/twitter/twitter/components/container.py +++ b/twitter/twitter/components/container.py @@ -10,9 +10,7 @@ def container(*children, **props): max_width="960px", background="white", height="100%", - #px=[4, 12], px="9", - margin="0 auto", position="relative", ) diff --git a/twitter/twitter/db_model.py b/twitter/twitter/db_model.py index 2f8c2620..6bdd0fd6 100644 --- a/twitter/twitter/db_model.py +++ b/twitter/twitter/db_model.py @@ -16,14 +16,14 @@ class Follows(rx.Model, table=True): class User(rx.Model, table=True): """A table of Users.""" - username: str = Field() - password: str = Field() + username: str + password: str class Tweet(rx.Model, table=True): """A table of Tweets.""" - content: str = Field() - created_at: str = Field() + content: str + created_at: str - author: str = Field() \ No newline at end of file + author: str \ No newline at end of file diff --git a/twitter/twitter/layouts/auth.py b/twitter/twitter/layouts/auth.py index f83f2637..a0abcfcc 100644 --- a/twitter/twitter/layouts/auth.py +++ b/twitter/twitter/layouts/auth.py @@ -9,8 +9,8 @@ def auth_layout(*args): return rx.box( container( rx.heading( - rx.chakra.span("Welcome to PySocial!"), - rx.chakra.span("Sign in or sign up to get started."), + rx.text("Welcome to PySocial!", as_="span"), + rx.text("Sign in or sign up to get started.", as_="span"), display="flex", flex_direction="column", align_items="center", @@ -34,7 +34,7 @@ def auth_layout(*args): align_items="center", padding_top="36px", padding_bottom="24px", - gap="1rem", + spacing="4", ), height="100vh", padding_top="40px", diff --git a/twitter/twitter/pages/home.py b/twitter/twitter/pages/home.py index a88a1647..4133c84f 100644 --- a/twitter/twitter/pages/home.py +++ b/twitter/twitter/pages/home.py @@ -45,7 +45,7 @@ def tabs(): ), rx.button("Sign out", on_click=State.logout, size="3"), align_items="left", - gap="4", + spacing="4", ), padding_top="2rem", padding_bottom="2rem", @@ -96,7 +96,7 @@ def sidebar(HomeState): width="100%", ), align_items="start", - gap="4", + spacing="4", height="100%", padding_top="2rem", padding_bottom="2rem", @@ -125,9 +125,6 @@ def composer(HomeState): rx.flex( rx.text_area( width="100%", - #border="none", - # padding_top="1rem", - # padding_bottom="1rem", placeholder="What's happening?", resize="none", _focus={"border": 0, "outline": 0, "boxShadow": "none"}, @@ -174,7 +171,7 @@ def tweet(tweet): grid_template_columns="1fr 5fr", padding_top="1.5rem", padding_bottom="1.5rem", - gap="1", + spacing="1", border_bottom="1px solid #ededed", ) @@ -216,7 +213,7 @@ def home(): sidebar(HomeState), grid_template_columns="1fr 2fr 1fr", height="100vh", - gap="4", + spacing="4", ), max_width="1300px", ) From dff5dc3ba04f0badc0a710c062a0d892b37342cd Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:12:24 -0800 Subject: [PATCH 26/45] translator app --- translator/.gitignore | 5 + translator/assets/favicon.ico | Bin 0 -> 4286 bytes translator/requirements.txt | 2 + translator/rxconfig.py | 7 + translator/translator/__init__.py | 0 translator/translator/translator.py | 216 ++++++++++++++++++++++++++++ 6 files changed, 230 insertions(+) create mode 100644 translator/.gitignore create mode 100644 translator/assets/favicon.ico create mode 100644 translator/requirements.txt create mode 100644 translator/rxconfig.py create mode 100644 translator/translator/__init__.py create mode 100644 translator/translator/translator.py diff --git a/translator/.gitignore b/translator/.gitignore new file mode 100644 index 00000000..f6711845 --- /dev/null +++ b/translator/.gitignore @@ -0,0 +1,5 @@ +*.db +*.py[cod] +.web +__pycache__/ +reflex.db \ No newline at end of file diff --git a/translator/assets/favicon.ico b/translator/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..54b24e938fea915a704034421ad6f6a5d5b96f91 GIT binary patch literal 4286 zcmZQzU<5)11qKkwutI==L5zWcK?8_^LJST-3=#(epqwx_1VaQE7(U;9`hOIUh5@!T z@a5jK|KA?Gfa90918;s2e(r~i}V29O_C^-TWnC?@mYNnG~7y@=HRV&9Pe?`}N6 zYCp)1XXmf~PqKFW?;t7-*5fLz_iGL_T z`%`S3!FGf6xXUX4-@jhu5nw!PqT0aP|1<14!l{Xe~N$N!4psQ<}8H-Pd%y1m=~6Kl8p|4N1U z2jwRZV15cz*Tsqh)O7yG7+Zqf@Z#c4a9IE<58mH=NOIZ(rA_qo2eKc8LFEB93@W2Q zZn(1R5Lhp$JR+yugXN3CXupS?%Ku<31FSemQ~!Ugna%%G>$m-XcJA8$CugpJF|P6& z=1*KSy8l7xFUQRnnC1@szrODn2EMWX`2TZT_WUmk2>%}sbVq`P9WWg_{y)BEGgZ?jssBKEE>J`7KgbQBaKMHO zy#xRIDr>^)Y--lOu)Gh72YeXTUI3}5w*9a&h*+9p`+@B*P`QS!ydy@;O-70A_7|w^ xyt?NIxD5tshmnKV^iBPL_vl%&%VCfkK;;l6n36gGSJ^l!K79I%uyKHaq5-!e-B|zt literal 0 HcmV?d00001 diff --git a/translator/requirements.txt b/translator/requirements.txt new file mode 100644 index 00000000..6a55c557 --- /dev/null +++ b/translator/requirements.txt @@ -0,0 +1,2 @@ +reflex>=0.4.0 +googletrans-py==4.0.0 diff --git a/translator/rxconfig.py b/translator/rxconfig.py new file mode 100644 index 00000000..a688a4f3 --- /dev/null +++ b/translator/rxconfig.py @@ -0,0 +1,7 @@ +import reflex as rx + +config = rx.Config( + app_name="translator", + db_url="sqlite:///reflex.db", + env=rx.Env.DEV, +) diff --git a/translator/translator/__init__.py b/translator/translator/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/translator/translator/translator.py b/translator/translator/translator.py new file mode 100644 index 00000000..51036847 --- /dev/null +++ b/translator/translator/translator.py @@ -0,0 +1,216 @@ +"""Welcome to Reflex! This file outlines the steps to create a basic app.""" + +import reflex as rx + +from datetime import datetime +from googletrans import Translator +from googletrans.constants import LANGUAGES + + +LANGUAGE_CODE_TO_NAME = {k: v.title() for k, v in LANGUAGES.items()} +LANGUAGE_NAMES = list(LANGUAGE_CODE_TO_NAME.values()) + +trans = Translator() + + +class Message(rx.Base): + original_text: str + text: str + created_at: str + to_lang: str + + +class State(rx.State): + """The app state.""" + + text: str + messages: list[Message] = [] + lang: str = LANGUAGE_CODE_TO_NAME["zh-cn"] + + @rx.var + def input_missing(self) -> bool: + return not self.text.strip() + + @rx.var + def output(self) -> str: + if self.input_missing: + return "Translations will appear here." + # The destination language `dest` is case insensitive, `translate` API call accepts both language names and codes. + translated = trans.translate(self.text, dest=self.lang) + return translated.text + + def post(self, form_data: dict[str, str]): + if not (text := form_data.get("text")): + return + # Insert the message at the top of the list. + self.messages.insert( + 0, + Message( + original_text=text, + text=self.output, + created_at=datetime.now().strftime("%B %d, %Y %I:%M %p"), + to_lang=self.lang, + ), + ) + # Manually reset the form input, since input in this app is fully controlled, it does not reset on submit. + self.text = "" + + +# Define views. + + +def header() -> rx.Component: + """The header and the description.""" + return rx.box( + rx.heading("Translator 🗺", size="8"), + rx.text( + "Translate things and post them as messages!", + color_scheme="gray", + ), + margin_bottom="1rem", + ) + + +def down_arrow() -> rx.Component: + return rx.vstack( + rx.icon( + tag="arrow_down", + color="gray", + ), + ) + + +def text_box(text) -> rx.Component: + return rx.text( + text, + background_color="white", + padding="1rem", + border_radius="8px", + ) + + +def past_translation(message: Message) -> rx.Component: + """A layout that contains a past translation.""" + return rx.box( + rx.flex( + text_box(message.original_text), + down_arrow(), + text_box(message.text), + rx.hstack( + rx.text(message.to_lang), + rx.text("·"), + rx.text(message.created_at), + spacing="2", + font_size="0.8rem", + color="var(--gray-11)", + ), + spacing="2", + direction="column", + ), + background_color="var(--gray-3)", + padding="1rem", + border_radius="8px", + ) + + +def smallcaps(text: str, **props): + """A smallcaps text component.""" + return rx.text( + text, + font_size="0.7rem", + font_weight="bold", + text_transform="uppercase", + letter_spacing="0.05rem", + **props, + ) + + +def output(): + """The output layout that contains the translated text.""" + return rx.stack( + smallcaps( + "Output", + color="var(--gray-9)", + background_color="white", + position="absolute", + top="-0.5rem", + ), + rx.text(State.output, size="4"), + padding="1rem", + border="1px solid var(--gray-7)", + border_radius="8px", + position="relative", + ) + + +def translation_form() -> rx.Component: + """This is a form that contains: + - Text input: what to translate + - Select: the destination language + - Output: the translation + - Submit button: to post the text input as part of the past translations view + """ + return rx.form( + rx.flex( + rx.input.input( + placeholder="Text to translate", + value=State.text, + on_change=State.set_text, + debounce_timeout=300, + size="3", + name="text", + ), + rx.select( + placeholder="Select a language", + items=LANGUAGE_NAMES, + value=State.lang, + on_change=State.set_lang, + margin_top="1rem", + size="3", + width="100%", + ), + output(), + rx.form.submit( + rx.button( + "Post", + size="3", + disabled=State.input_missing, + ), + as_child=True, + ), + direction="column", + spacing="4", + ), + # setting `reset_on_submit` here will not work since the input is fully controlled + on_submit=State.post, + ) + + +def past_translations_timeline() -> rx.Component: + """A layout that contains the timeline of posted past translations.""" + return rx.flex( + rx.foreach(State.messages, past_translation), + margin_top="2rem", + spacing="4", + direction="column", + ) + + +def index(): + """The main view.""" + return rx.container( + header(), + translation_form(), + past_translations_timeline(), + padding="2rem", + max_width="600px", + margin="auto", + ) + + +app = rx.App( + theme=rx.theme( + appearance="light", has_background=True, radius="large", accent_color="blue" + ), +) +app.add_page(index, title="Translator") From 08dcd496829cc611b5da896a78830ca2be9d408b Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:16:23 -0800 Subject: [PATCH 27/45] clean up rxconfig --- translator/rxconfig.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/translator/rxconfig.py b/translator/rxconfig.py index a688a4f3..656a727f 100644 --- a/translator/rxconfig.py +++ b/translator/rxconfig.py @@ -1,7 +1,3 @@ import reflex as rx -config = rx.Config( - app_name="translator", - db_url="sqlite:///reflex.db", - env=rx.Env.DEV, -) +config = rx.Config(app_name="translator") From 2c59794e9bc88d75c7d18f785732d2e072a38f21 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:18:31 -0800 Subject: [PATCH 28/45] dalle app update --- dalle/.gitignore | 5 +++ dalle/assets/favicon.ico | Bin 0 -> 4286 bytes dalle/dalle/__init__.py | 0 dalle/dalle/dalle.py | 93 +++++++++++++++++++++++++++++++++++++++ dalle/requirements.txt | 2 + dalle/rxconfig.py | 3 ++ 6 files changed, 103 insertions(+) create mode 100644 dalle/.gitignore create mode 100644 dalle/assets/favicon.ico create mode 100644 dalle/dalle/__init__.py create mode 100644 dalle/dalle/dalle.py create mode 100644 dalle/requirements.txt create mode 100644 dalle/rxconfig.py diff --git a/dalle/.gitignore b/dalle/.gitignore new file mode 100644 index 00000000..f6711845 --- /dev/null +++ b/dalle/.gitignore @@ -0,0 +1,5 @@ +*.db +*.py[cod] +.web +__pycache__/ +reflex.db \ No newline at end of file diff --git a/dalle/assets/favicon.ico b/dalle/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..54b24e938fea915a704034421ad6f6a5d5b96f91 GIT binary patch literal 4286 zcmZQzU<5)11qKkwutI==L5zWcK?8_^LJST-3=#(epqwx_1VaQE7(U;9`hOIUh5@!T z@a5jK|KA?Gfa90918;s2e(r~i}V29O_C^-TWnC?@mYNnG~7y@=HRV&9Pe?`}N6 zYCp)1XXmf~PqKFW?;t7-*5fLz_iGL_T z`%`S3!FGf6xXUX4-@jhu5nw!PqT0aP|1<14!l{Xe~N$N!4psQ<}8H-Pd%y1m=~6Kl8p|4N1U z2jwRZV15cz*Tsqh)O7yG7+Zqf@Z#c4a9IE<58mH=NOIZ(rA_qo2eKc8LFEB93@W2Q zZn(1R5Lhp$JR+yugXN3CXupS?%Ku<31FSemQ~!Ugna%%G>$m-XcJA8$CugpJF|P6& z=1*KSy8l7xFUQRnnC1@szrODn2EMWX`2TZT_WUmk2>%}sbVq`P9WWg_{y)BEGgZ?jssBKEE>J`7KgbQBaKMHO zy#xRIDr>^)Y--lOu)Gh72YeXTUI3}5w*9a&h*+9p`+@B*P`QS!ydy@;O-70A_7|w^ xyt?NIxD5tshmnKV^iBPL_vl%&%VCfkK;;l6n36gGSJ^l!K79I%uyKHaq5-!e-B|zt literal 0 HcmV?d00001 diff --git a/dalle/dalle/__init__.py b/dalle/dalle/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/dalle/dalle/dalle.py b/dalle/dalle/dalle.py new file mode 100644 index 00000000..5be499e3 --- /dev/null +++ b/dalle/dalle/dalle.py @@ -0,0 +1,93 @@ +"""Welcome to Reflex! This file outlines the steps to create a basic app.""" + +import reflex as rx + +import os + +import openai + +_client = None + + +def get_openai_client(): + global _client + if _client is None: + _client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY")) + + return _client + + +class State(rx.State): + """The app state.""" + + image_url = "" + image_processing = False + image_made = False + + def get_dalle_result(self, form_data: dict[str, str]): + prompt_text: str = form_data["prompt_text"] + self.image_made = False + self.image_processing = True + yield + try: + response = get_openai_client().images.generate( + prompt=prompt_text, n=1, size="1024x1024" + ) + self.image_url = response.data[0].url + self.image_processing = False + self.image_made = True + yield + except Exception as ex: + self.image_processing = False + yield rx.window_alert(f"Error with OpenAI Execution. {ex}") + + +def index(): + return rx.center( + rx.vstack( + rx.heading("DALL-E", font_size="1.5em"), + rx.form( + rx.input( + id="prompt_text", + placeholder="Enter a prompt..", + size="3", + ), + rx.button( + "Generate Image", + width="100%", + type="submit", + size="3", + ), + width="100%", + on_submit=State.get_dalle_result, + ), + rx.divider(), + rx.cond( + State.image_processing, + rx.chakra.circular_progress(is_indeterminate=True), + rx.cond( + State.image_made, + rx.image( + src=State.image_url, + ), + ), + ), + width="25em", + bg="white", + padding="2em", + shadow="lg", + border_radius="lg", + ), + width="100%", + height="100vh", + background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", + ) + + +# Add state and page to the app. +app = rx.App( + theme=rx.theme( + appearance="light", has_background=True, radius="medium", accent_color="mint" + ), +) +app.add_page(index, title="Reflex:DALL-E") diff --git a/dalle/requirements.txt b/dalle/requirements.txt new file mode 100644 index 00000000..64bf0145 --- /dev/null +++ b/dalle/requirements.txt @@ -0,0 +1,2 @@ +reflex>=0.4.0 +openai>=1 diff --git a/dalle/rxconfig.py b/dalle/rxconfig.py new file mode 100644 index 00000000..4054890f --- /dev/null +++ b/dalle/rxconfig.py @@ -0,0 +1,3 @@ +import reflex as rx + +config = rx.Config(app_name="dalle") From 4e1616229df4333936196f1a0c53c63167ad8b47 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Tue, 13 Feb 2024 17:21:34 -0800 Subject: [PATCH 29/45] Update GPT app to use radix components (except for spinner) --- chakra_apps/gpt/gpt/gpt.py | 262 --------------- chakra_apps/gpt/gpt/helpers.py | 40 --- chakra_apps/gpt/requirements.txt | 2 - {chakra_apps/gpt => gpt}/.gitignore | 0 {chakra_apps/gpt => gpt}/assets/favicon.ico | Bin {chakra_apps/gpt => gpt}/gpt/__init__.py | 0 gpt/gpt/gpt.py | 351 ++++++++++++++++++++ gpt/gpt/helpers.py | 61 ++++ gpt/requirements.txt | 2 + {chakra_apps/gpt => gpt}/rxconfig.py | 0 10 files changed, 414 insertions(+), 304 deletions(-) delete mode 100644 chakra_apps/gpt/gpt/gpt.py delete mode 100644 chakra_apps/gpt/gpt/helpers.py delete mode 100644 chakra_apps/gpt/requirements.txt rename {chakra_apps/gpt => gpt}/.gitignore (100%) rename {chakra_apps/gpt => gpt}/assets/favicon.ico (100%) rename {chakra_apps/gpt => gpt}/gpt/__init__.py (100%) create mode 100644 gpt/gpt/gpt.py create mode 100644 gpt/gpt/helpers.py create mode 100644 gpt/requirements.txt rename {chakra_apps/gpt => gpt}/rxconfig.py (100%) diff --git a/chakra_apps/gpt/gpt/gpt.py b/chakra_apps/gpt/gpt/gpt.py deleted file mode 100644 index ac4f6686..00000000 --- a/chakra_apps/gpt/gpt/gpt.py +++ /dev/null @@ -1,262 +0,0 @@ -"""Welcome to Reflex! This app is a demonstration of OpenAI's GPT.""" -import datetime - -from openai import OpenAI - -import reflex as rx -from sqlmodel import select - -from .helpers import navbar - -client = OpenAI() -MAX_QUESTIONS = 10 - - -class User(rx.Model, table=True): - """A table for users in the database.""" - - username: str - password: str - - -class Question(rx.Model, table=True): - """A table for questions and answers in the database.""" - - username: str - prompt: str - answer: str - timestamp: datetime.datetime = datetime.datetime.now() - - -class State(rx.State): - """The app state.""" - - show_columns = ["Question", "Answer"] - username: str = "" - password: str = "" - logged_in: bool = False - - prompt: str = "" - result: str = "" - - @rx.var - def questions(self) -> list[Question]: - """Get the users saved questions and answers from the database.""" - with rx.session() as session: - if self.logged_in: - qa = session.exec( - select(Question) - .where(Question.username == self.username) - .distinct(Question.prompt) - .order_by(Question.timestamp.desc()) - .limit(MAX_QUESTIONS) - ).all() - return [[q.prompt, q.answer] for q in qa] - else: - return [] - - def login(self): - with rx.session() as session: - user = session.exec( - select(User).where(User.username == self.username) - ).first() - if (user and user.password == self.password) or self.username == "admin": - self.logged_in = True - return rx.redirect("/home") - else: - return rx.window_alert("Invalid username or password.") - - def logout(self): - self.reset() - return rx.redirect("/") - - def signup(self): - with rx.session() as session: - user = User(username=self.username, password=self.password) - session.add(user) - session.commit() - self.logged_in = True - return rx.redirect("/home") - - def get_result(self): - with rx.session() as session: - if ( - session.exec( - select(Question) - .where(Question.username == self.username) - .where(Question.prompt == self.prompt) - ).first() - or len( - session.exec( - select(Question) - .where(Question.username == self.username) - .where( - Question.timestamp - > datetime.datetime.now() - datetime.timedelta(days=1) - ) - ).all() - ) - > MAX_QUESTIONS - ): - return rx.window_alert( - "You have already asked this question or have asked too many questions in the past 24 hours." - ) - try: - response = client.completions.create( - model="gpt-3.5-turbo-instruct", - prompt=self.prompt, - temperature=0, - max_tokens=100, - top_p=1, - ) - self.result = response.choices[0].text.replace("\n", "") - except Exception as e: - print(e) - return rx.window_alert("Error occured with OpenAI execution.") - - def save_result(self): - with rx.session() as session: - answer = Question( - username=self.username, prompt=self.prompt, answer=self.result - ) - session.add(answer) - session.commit() - - def set_username(self, username): - self.username = username.strip() - - def set_password(self, password): - self.password = password.strip() - - -def home(): - return rx.chakra.center( - navbar(State), - rx.chakra.vstack( - rx.chakra.center( - rx.chakra.vstack( - rx.chakra.heading("Ask GPT", font_size="1.5em"), - rx.chakra.input( - on_blur=State.set_prompt, placeholder="Question", width="100%" - ), - rx.chakra.button("Get Answer", on_click=State.get_result, width="100%"), - rx.chakra.text_area( - default_value=State.result, - placeholder="GPT Result", - width="100%", - ), - rx.chakra.button("Save Answer", on_click=State.save_result, width="100%"), - shadow="lg", - padding="1em", - border_radius="lg", - width="100%", - ), - width="100%", - ), - rx.chakra.center( - rx.chakra.vstack( - rx.chakra.heading("Saved Q&A", font_size="1.5em"), - rx.chakra.divider(), - rx.data_table( - data=State.questions, - # columns=["Question", "Answer"], - columns=State.show_columns, - pagination=True, - search=True, - sort=True, - width="100%", - ), - shadow="lg", - padding="1em", - border_radius="lg", - width="100%", - ), - width="100%", - ), - width="50%", - spacing="2em", - ), - padding_top="6em", - text_align="top", - position="relative", - ) - - -def login(): - return rx.chakra.center( - rx.chakra.vstack( - rx.chakra.input(on_blur=State.set_username, placeholder="Username", width="100%"), - rx.chakra.input( - type_="password", - on_blur=State.set_password, - placeholder="Password", - width="100%", - ), - rx.chakra.button("Login", on_click=State.login, width="100%"), - rx.chakra.link(rx.chakra.button("Sign Up", width="100%"), href="/signup", width="100%"), - ), - shadow="lg", - padding="1em", - border_radius="lg", - background="white", - ) - - -def signup(): - return rx.chakra.box( - rx.chakra.vstack( - rx.chakra.center( - rx.chakra.vstack( - rx.chakra.heading("GPT Sign Up", font_size="1.5em"), - rx.chakra.input( - on_blur=State.set_username, placeholder="Username", width="100%" - ), - rx.chakra.input( - type_="password", - on_blur=State.set_password, - placeholder="Password", - width="100%", - ), - rx.chakra.input( - type_="password", - on_blur=State.set_password, - placeholder="Confirm Password", - width="100%", - ), - rx.chakra.button("Sign Up", on_click=State.signup, width="100%"), - ), - shadow="lg", - padding="1em", - border_radius="lg", - background="white", - ) - ), - padding_top="10em", - text_align="top", - position="relative", - width="100%", - height="100vh", - background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", - ) - - -def index(): - return rx.chakra.box( - rx.chakra.vstack( - navbar(State), - login(), - ), - padding_top="10em", - text_align="top", - position="relative", - width="100%", - height="100vh", - background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", - ) - - -# Add pages to the app. -app = rx.App() -app.add_page(index) -app.add_page(signup) -app.add_page(home) diff --git a/chakra_apps/gpt/gpt/helpers.py b/chakra_apps/gpt/gpt/helpers.py deleted file mode 100644 index 377bfa4d..00000000 --- a/chakra_apps/gpt/gpt/helpers.py +++ /dev/null @@ -1,40 +0,0 @@ -import reflex as rx - - -def navbar(State): - return rx.chakra.box( - rx.chakra.hstack( - rx.chakra.link( - rx.chakra.hstack(rx.chakra.image(src="favicon.ico"), rx.chakra.heading("GPT Demo")), href="/" - ), - rx.chakra.menu( - rx.chakra.menu_button( - rx.cond( - State.logged_in, - rx.chakra.avatar(name=State.username, size="md"), - rx.chakra.box(), - ) - ), - rx.chakra.menu_list( - rx.chakra.center( - rx.chakra.vstack( - rx.chakra.avatar(name=State.username, size="md"), - rx.chakra.text(State.username), - ) - ), - rx.chakra.menu_divider(), - rx.chakra.link(rx.chakra.menu_item("About GPT"), href="https://openai.com/api/"), - rx.chakra.link(rx.chakra.menu_item("Sign Out"), on_click=State.logout), - ), - ), - justify="space-between", - border_bottom="0.2em solid #F0F0F0", - padding_x="2em", - padding_y="1em", - bg="rgba(255,255,255, 0.90)", - ), - position="fixed", - width="100%", - top="0px", - z_index="500", - ) diff --git a/chakra_apps/gpt/requirements.txt b/chakra_apps/gpt/requirements.txt deleted file mode 100644 index 6088ea74..00000000 --- a/chakra_apps/gpt/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -reflex>=0.3.8 -openai>=1 diff --git a/chakra_apps/gpt/.gitignore b/gpt/.gitignore similarity index 100% rename from chakra_apps/gpt/.gitignore rename to gpt/.gitignore diff --git a/chakra_apps/gpt/assets/favicon.ico b/gpt/assets/favicon.ico similarity index 100% rename from chakra_apps/gpt/assets/favicon.ico rename to gpt/assets/favicon.ico diff --git a/chakra_apps/gpt/gpt/__init__.py b/gpt/gpt/__init__.py similarity index 100% rename from chakra_apps/gpt/gpt/__init__.py rename to gpt/gpt/__init__.py diff --git a/gpt/gpt/gpt.py b/gpt/gpt/gpt.py new file mode 100644 index 00000000..70a149f1 --- /dev/null +++ b/gpt/gpt/gpt.py @@ -0,0 +1,351 @@ +"""Welcome to Reflex! This app is a demonstration of OpenAI's GPT.""" + +import datetime + +from openai import OpenAI +from sqlmodel import select, or_ + +import reflex as rx + +from .helpers import navbar + +client = OpenAI() +MAX_QUESTIONS = 10 + + +class User(rx.Model, table=True): + """A table for users in the database.""" + + username: str + password: str + + +class Question(rx.Model, table=True): + """A table for questions and answers in the database.""" + + username: str + prompt: str + answer: str + timestamp: datetime.datetime = datetime.datetime.now() + + +class State(rx.State): + """The app state.""" + + show_columns = ["Question", "Answer"] + username: str = "" + logged_in: bool = False + + prompt: str = "" + result: str = "" + loading: bool = False + + filter: str = "" + + @rx.var + def questions(self) -> list[Question]: + """Get the users saved questions and answers from the database.""" + with rx.session() as session: + if self.logged_in: + query = select(Question).where(Question.username == self.username) + if self.filter: + query = query.where( + or_( + Question.prompt.ilike(f"%{self.filter}%"), + Question.answer.ilike(f"%{self.filter}%"), + ) + ) + return session.exec( + query.distinct(Question.prompt) + .order_by(Question.timestamp.desc()) + .limit(MAX_QUESTIONS) + ).all() + else: + return [] + + def login(self, form_data: dict[str, str]): + self.username = form_data["username"].strip() + password = form_data["password"].strip() + with rx.session() as session: + user = session.exec( + select(User).where(User.username == self.username) + ).first() + if (user and user.password == password) or self.username == "admin": + self.logged_in = True + return rx.redirect("/home") + else: + return rx.window_alert("Invalid username or password.") + + def logout(self): + self.reset() + return rx.redirect("/") + + def signup(self, form_data: dict[str, str]): + self.username = form_data["username"].strip() + password = form_data["password"].strip() + confirm = form_data["confirm"].strip() + if password != confirm: + return [ + rx.set_value("confirm", ""), + rx.window_alert("Passwords do not match."), + ] + with rx.session() as session: + user = User(username=self.username, password=password) + session.add(user) + session.commit() + self.logged_in = True + return rx.redirect("/home") + + def get_result(self, form_data: dict[str, str]): + self.prompt = form_data["prompt"] + with rx.session() as session: + if ( + session.exec( + select(Question) + .where(Question.username == self.username) + .where(Question.prompt == self.prompt) + ).first() + or len( + session.exec( + select(Question) + .where(Question.username == self.username) + .where( + Question.timestamp + > datetime.datetime.now() - datetime.timedelta(days=1) + ) + ).all() + ) + > MAX_QUESTIONS + ): + return rx.window_alert( + "You have already asked this question or have asked too many questions in the past 24 hours." + ) + self.result = "" + self.loading = True + yield + try: + response = client.completions.create( + model="gpt-3.5-turbo-instruct", + prompt=self.prompt, + temperature=0, + max_tokens=100, + top_p=1, + ) + self.result = response.choices[0].text.replace("\n", "") + except Exception as e: + print(e) + return rx.window_alert("Error occured with OpenAI execution.") + finally: + self.loading = False + + def save_result(self): + with rx.session() as session: + answer = Question( + username=self.username, prompt=self.prompt, answer=self.result + ) + session.add(answer) + session.commit() + + +def result_view() -> rx.Component: + return rx.fragment( + rx.flex( + rx.text(State.prompt), + rx.cond( + State.loading, + rx.chakra.spinner(), + ), + justify="between", + ), + rx.scroll_area( + rx.cond( + State.result, + rx.text(State.result), + rx.cond( + State.loading, + rx.text("AI is answering...", color_scheme="gray"), + rx.text( + "Ask a question to get an answer from GPT.", color_scheme="gray" + ), + ), + ), + type_="hover", + width="100%", + max_height="7em", + ), + rx.cond( + State.logged_in & (State.result != ""), + rx.button("Save Answer", on_click=State.save_result, width="100%"), + ), + ) + + +def ask_gpt_form() -> rx.Component: + return rx.flex( + rx.heading("Ask GPT", font_size="1.5em", align="center"), + rx.form( + rx.flex( + rx.input(placeholder="Question", name="prompt", width="100%"), + rx.button("Get Answer", width="100%"), + direction="column", + spacing="3", + ), + on_submit=State.get_result, + reset_on_submit=True, + ), + rx.divider(), + result_view(), + direction="column", + align="stretch", + spacing="3", + width="100%", + ) + + +def saved_qa_item(qa: Question, ix: int) -> rx.Component: + return rx.accordion.item( + header=rx.text(qa.prompt, size="3", align="left"), + content=rx.scroll_area( + rx.text(qa.answer, size="2"), + type_="hover", + max_height="10em", + padding="12px", + ), + value=f"item-{ix}", + ) + + +def saved_qa() -> rx.Component: + return rx.flex( + rx.heading("Saved Q&A", font_size="1.5em"), + rx.divider(), + rx.input( + placeholder="Filter", + value=State.filter, + on_change=State.set_filter, + debounce_timeout=1500, + width="100%", + ), + rx.accordion.root( + rx.foreach( + State.questions, + saved_qa_item, + ), + single=False, + collapsible=True, + ), + direction="column", + spacing="3", + padding="1em", + width="100%", + ) + + +def home(): + return rx.flex( + navbar(State), + rx.flex( + rx.card(ask_gpt_form()), + rx.cond( + State.logged_in, + rx.card(saved_qa()), + ), + direction="column", + spacing="4", + width="50%", + ), + justify="center", + padding_top="6em", + text_align="top", + position="relative", + ) + + +def login(): + return rx.form( + rx.card( + rx.flex( + rx.input(name="username", placeholder="Username", width="100%"), + rx.input( + type="password", + name="password", + placeholder="Password", + width="100%", + ), + rx.button("Login", width="100%"), + rx.button( + "Sign Up", + type="button", + width="100%", + on_click=rx.redirect("/signup"), + ), + direction="column", + spacing="3", + ) + ), + on_submit=State.login, + ) + + +def signup(): + return rx.flex( + rx.form( + rx.flex( + rx.heading("GPT Sign Up", font_size="1.5em"), + rx.input(name="username", placeholder="Username", width="100%"), + rx.input( + type="password", + name="password", + placeholder="Password", + width="100%", + ), + rx.input( + type="password", + name="confirm", + id="confirm", + placeholder="Confirm Password", + width="100%", + ), + rx.button("Sign Up", width="100%"), + direction="column", + spacing="3", + align="center", + justify="center", + padding="1em", + background="white", + ), + on_submit=State.signup, + ), + align="start", + justify="center", + padding_top="10em", + text_align="top", + position="relative", + width="100%", + height="100vh", + background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", + ) + + +def index(): + return rx.flex( + navbar(State), + rx.flex( + login(), + justify="center", + ), + direction="column", + padding_top="10em", + text_align="top", + position="relative", + width="100%", + height="100vh", + background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", + ) + + +# Add pages to the app. +app = rx.App() +app.add_page(index) +app.add_page(signup) +app.add_page(home) diff --git a/gpt/gpt/helpers.py b/gpt/gpt/helpers.py new file mode 100644 index 00000000..c85f38c2 --- /dev/null +++ b/gpt/gpt/helpers.py @@ -0,0 +1,61 @@ +import reflex as rx + + +def navbar(State: rx.State) -> rx.Component: + return rx.box( + rx.flex( + rx.link( + rx.flex( + rx.image(src="/favicon.ico"), + rx.heading("GPT Demo"), + align="center", + ), + href="/", + color="black", + ), + rx.menu.root( + rx.menu.trigger( + rx.button(rx.icon("menu")), + ), + rx.menu.content( + rx.cond( + State.logged_in, + rx.fragment( + rx.flex( + rx.avatar(fallback=State.username[0].to(str), size="3"), + rx.text(State.username), + spacing="2", + align="center", + justify="center", + ), + rx.menu.separator(), + ), + ), + rx.menu.item( + "About GPT", + on_click=rx.redirect("https://openai.com/api/"), + ), + rx.cond( + State.logged_in, + rx.menu.item( + "Sign Out", + on_click=State.logout, + ), + rx.menu.item( + "Log In", + on_click=rx.redirect("/"), + ), + ), + ), + ), + align="center", + justify="between", + border_bottom="0.2em solid #F0F0F0", + padding="1em 2em", + background="rgba(255,255,255, 0.90)", + ), + position="fixed", + width="100%", + top="0px", + z_index="500", + ) diff --git a/gpt/requirements.txt b/gpt/requirements.txt new file mode 100644 index 00000000..4fdfac55 --- /dev/null +++ b/gpt/requirements.txt @@ -0,0 +1,2 @@ +reflex>=0.4.0a1 +openai>=1 diff --git a/chakra_apps/gpt/rxconfig.py b/gpt/rxconfig.py similarity index 100% rename from chakra_apps/gpt/rxconfig.py rename to gpt/rxconfig.py From cf2f648bf592a6efa3da44f7adce6256d5585928 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:03:17 -0800 Subject: [PATCH 30/45] review comments --- translator/translator/translator.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/translator/translator/translator.py b/translator/translator/translator.py index 51036847..a9d6daf2 100644 --- a/translator/translator/translator.py +++ b/translator/translator/translator.py @@ -102,12 +102,12 @@ def past_translation(message: Message) -> rx.Component: rx.text(message.created_at), spacing="2", font_size="0.8rem", - color="var(--gray-11)", + color=rx.color("gray", 11), ), spacing="2", direction="column", ), - background_color="var(--gray-3)", + background_color=rx.color("gray", 3), padding="1rem", border_radius="8px", ) @@ -130,14 +130,15 @@ def output(): return rx.stack( smallcaps( "Output", - color="var(--gray-9)", + color=rx.color("gray", 9), background_color="white", position="absolute", top="-0.5rem", ), rx.text(State.output, size="4"), padding="1rem", - border="1px solid var(--gray-7)", + border="1px solid", + border_color=rx.color("gray", 7), border_radius="8px", position="relative", ) @@ -152,7 +153,7 @@ def translation_form() -> rx.Component: """ return rx.form( rx.flex( - rx.input.input( + rx.input( placeholder="Text to translate", value=State.text, on_change=State.set_text, From 19e02ad8ac799f8462dced99a653349d26b1c817 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 12:49:48 -0800 Subject: [PATCH 31/45] no need for form.submit --- translator/translator/translator.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/translator/translator/translator.py b/translator/translator/translator.py index a9d6daf2..3538434b 100644 --- a/translator/translator/translator.py +++ b/translator/translator/translator.py @@ -171,13 +171,10 @@ def translation_form() -> rx.Component: width="100%", ), output(), - rx.form.submit( - rx.button( - "Post", - size="3", - disabled=State.input_missing, - ), - as_child=True, + rx.button( + "Post", + size="3", + disabled=State.input_missing, ), direction="column", spacing="4", From eb8eb9f6ddf962b5b25c46c684b513ab21edd9d3 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:38:16 -0800 Subject: [PATCH 32/45] review comments --- dalle/dalle/dalle.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/dalle/dalle/dalle.py b/dalle/dalle/dalle.py index 5be499e3..9e3c77c3 100644 --- a/dalle/dalle/dalle.py +++ b/dalle/dalle/dalle.py @@ -28,6 +28,7 @@ def get_dalle_result(self, form_data: dict[str, str]): prompt_text: str = form_data["prompt_text"] self.image_made = False self.image_processing = True + # Yield here so the image_processing take effects and the circular progress is shown. yield try: response = get_openai_client().images.generate( @@ -47,16 +48,19 @@ def index(): rx.vstack( rx.heading("DALL-E", font_size="1.5em"), rx.form( - rx.input( - id="prompt_text", - placeholder="Enter a prompt..", - size="3", - ), - rx.button( - "Generate Image", - width="100%", - type="submit", - size="3", + rx.vstack( + rx.input( + id="prompt_text", + placeholder="Enter a prompt..", + size="3", + ), + rx.button( + "Generate Image", + type="submit", + size="3", + ), + align="stretch", + spacing="2", ), width="100%", on_submit=State.get_dalle_result, @@ -75,8 +79,6 @@ def index(): width="25em", bg="white", padding="2em", - shadow="lg", - border_radius="lg", ), width="100%", height="100vh", From 89a724605284df65fad383ce1d73e1171fa2d917 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:28:25 -0800 Subject: [PATCH 33/45] update CI --- .github/workflows/app_harness.yml | 9 +++++---- .github/workflows/check_export.yml | 13 +++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index 85120c85..315ddc71 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,17 +1,18 @@ name: app-harness env: - REFLEX_VERSION: "==0.3.9" + # TODO: switch to the official release + REFLEX_VERSION: '==0.4.0a1' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: inputs: reflex_version: - description: "Reflex version" + description: 'Reflex version' jobs: list-examples-with-tests: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index 53503b36..d52d922f 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,16 +1,17 @@ name: check-export env: - REFLEX_VERSION: "==0.3.9" + # TODO: switch to the official release + REFLEX_VERSION: '==0.4.0a1' TELEMETRY_ENABLED: false on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: inputs: reflex_version: - description: "Reflex version" + description: 'Reflex version' jobs: list-examples: @@ -24,7 +25,7 @@ jobs: run: | # TODO fix sales export # TODO fix stable_diffusion export (gets stuck) - EXAMPLES="$(find . -not -name '.*' -maxdepth 1 -type d | cut -f2 -d/ | sort | grep -vw sales | grep -vw stable_diffusion | jq -R | jq -s -c)" + 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 @@ -43,7 +44,7 @@ jobs: echo "$f is not a directory!" exit 1 fi - + cd "$f" if [[ ! -f requirements.txt ]]; then From 7c92496a018e7e2d7189ae86ed82b9517cb14cd2 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:31:42 -0800 Subject: [PATCH 34/45] use prerelease to unblock CI --- clock_radix/requirements.txt | 2 +- dalle/requirements.txt | 2 +- nba/requirements.txt | 2 +- translator/requirements.txt | 2 +- twitter/requirements.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clock_radix/requirements.txt b/clock_radix/requirements.txt index 009fa0e2..af426383 100644 --- a/clock_radix/requirements.txt +++ b/clock_radix/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.3.7 +reflex>=0.4.0a1 pytz==2022.7.1 diff --git a/dalle/requirements.txt b/dalle/requirements.txt index 64bf0145..4fdfac55 100644 --- a/dalle/requirements.txt +++ b/dalle/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0 +reflex>=0.4.0a1 openai>=1 diff --git a/nba/requirements.txt b/nba/requirements.txt index 9166e192..20f23497 100644 --- a/nba/requirements.txt +++ b/nba/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.4.0 +reflex>=0.4.0a1 pandas>=2.2.0 plotly>=5.18.0 diff --git a/translator/requirements.txt b/translator/requirements.txt index 6a55c557..8ae44273 100644 --- a/translator/requirements.txt +++ b/translator/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0 +reflex>=0.4.0a1 googletrans-py==4.0.0 diff --git a/twitter/requirements.txt b/twitter/requirements.txt index d4deee8a..98df420a 100644 --- a/twitter/requirements.txt +++ b/twitter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0 +reflex>=0.4.0a1 From 4679f86b6e1004e6a39632ea2453febcb4c48496 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:32:10 -0800 Subject: [PATCH 35/45] clock_radix -> clock --- {clock_radix => clock}/.gitignore | 0 {clock_radix => clock}/assets/favicon.ico | Bin .../clock_radix => clock/clock}/__init__.py | 0 .../clock_radix.py => clock/clock/clock.py | 0 {clock_radix => clock}/requirements.txt | 0 {clock_radix => clock}/rxconfig.py | 4 ++-- 6 files changed, 2 insertions(+), 2 deletions(-) rename {clock_radix => clock}/.gitignore (100%) rename {clock_radix => clock}/assets/favicon.ico (100%) rename {clock_radix/clock_radix => clock/clock}/__init__.py (100%) rename clock_radix/clock_radix/clock_radix.py => clock/clock/clock.py (100%) rename {clock_radix => clock}/requirements.txt (100%) rename {clock_radix => clock}/rxconfig.py (58%) diff --git a/clock_radix/.gitignore b/clock/.gitignore similarity index 100% rename from clock_radix/.gitignore rename to clock/.gitignore diff --git a/clock_radix/assets/favicon.ico b/clock/assets/favicon.ico similarity index 100% rename from clock_radix/assets/favicon.ico rename to clock/assets/favicon.ico diff --git a/clock_radix/clock_radix/__init__.py b/clock/clock/__init__.py similarity index 100% rename from clock_radix/clock_radix/__init__.py rename to clock/clock/__init__.py diff --git a/clock_radix/clock_radix/clock_radix.py b/clock/clock/clock.py similarity index 100% rename from clock_radix/clock_radix/clock_radix.py rename to clock/clock/clock.py diff --git a/clock_radix/requirements.txt b/clock/requirements.txt similarity index 100% rename from clock_radix/requirements.txt rename to clock/requirements.txt diff --git a/clock_radix/rxconfig.py b/clock/rxconfig.py similarity index 58% rename from clock_radix/rxconfig.py rename to clock/rxconfig.py index b90ba40b..c545ccdf 100644 --- a/clock_radix/rxconfig.py +++ b/clock/rxconfig.py @@ -1,5 +1,5 @@ import reflex as rx config = rx.Config( - app_name="clock_radix", -) \ No newline at end of file + app_name="clock", +) From 4223b0d3b7608abd57e73fae033c9b7aeb5e02cb Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:55:14 -0800 Subject: [PATCH 36/45] fix counter test --- counter/tests/test_counter.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/counter/tests/test_counter.py b/counter/tests/test_counter.py index ba6ea20e..d1f09d86 100644 --- a/counter/tests/test_counter.py +++ b/counter/tests/test_counter.py @@ -18,9 +18,11 @@ def test_counter_app(counter_app: AppHarness): state_manager = counter_app.app_instance.state_manager assert len(counter_app.poll_for_clients()) == 1 - backend_state = list(state_manager.states.values())[0].get_substate(["state", "state"]) + backend_state = list(state_manager.states.values())[0].get_substate( + ["state", "state"] + ) - count = driver.find_element(By.TAG_NAME, "h2") + count = driver.find_element(By.TAG_NAME, "h1") assert counter_app.poll_for_content(count) == "0" buttons = driver.find_elements(By.TAG_NAME, "button") @@ -45,4 +47,4 @@ def test_counter_app(counter_app: AppHarness): assert counter_app.poll_for_content(count, exp_not_equal=random_count) == dec_value increment.click() assert counter_app.poll_for_content(count, exp_not_equal=dec_value) == random_count - assert count.text == random_count \ No newline at end of file + assert count.text == random_count From 6b9ccc0b7cdc00e7ae88c06da9d46726ed89bd07 Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:02:22 -0800 Subject: [PATCH 37/45] use a2 --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- basic_crud/requirements.txt | 2 +- clock/requirements.txt | 2 +- counter/requirements.txt | 2 +- dalle/requirements.txt | 2 +- github-stats/requirements.txt | 2 +- gpt/requirements.txt | 2 +- nba/requirements.txt | 2 +- snakegame/requirements.txt | 2 +- todo/requirements.txt | 2 +- translator/requirements.txt | 2 +- twitter/requirements.txt | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index 315ddc71..bceb9247 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,7 +1,7 @@ name: app-harness env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a1' + REFLEX_VERSION: '==0.4.0a2' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index d52d922f..d7a3af69 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,7 +1,7 @@ name: check-export env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a1' + REFLEX_VERSION: '==0.4.0a2' TELEMETRY_ENABLED: false on: push: diff --git a/basic_crud/requirements.txt b/basic_crud/requirements.txt index 98df420a..9e31ae33 100644 --- a/basic_crud/requirements.txt +++ b/basic_crud/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 diff --git a/clock/requirements.txt b/clock/requirements.txt index af426383..ca9cfcc9 100644 --- a/clock/requirements.txt +++ b/clock/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 pytz==2022.7.1 diff --git a/counter/requirements.txt b/counter/requirements.txt index 98df420a..9e31ae33 100644 --- a/counter/requirements.txt +++ b/counter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 diff --git a/dalle/requirements.txt b/dalle/requirements.txt index 4fdfac55..09b27902 100644 --- a/dalle/requirements.txt +++ b/dalle/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 openai>=1 diff --git a/github-stats/requirements.txt b/github-stats/requirements.txt index 98df420a..9e31ae33 100644 --- a/github-stats/requirements.txt +++ b/github-stats/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 diff --git a/gpt/requirements.txt b/gpt/requirements.txt index 4fdfac55..09b27902 100644 --- a/gpt/requirements.txt +++ b/gpt/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 openai>=1 diff --git a/nba/requirements.txt b/nba/requirements.txt index 20f23497..40d7d310 100644 --- a/nba/requirements.txt +++ b/nba/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 pandas>=2.2.0 plotly>=5.18.0 diff --git a/snakegame/requirements.txt b/snakegame/requirements.txt index 98df420a..9e31ae33 100644 --- a/snakegame/requirements.txt +++ b/snakegame/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 diff --git a/todo/requirements.txt b/todo/requirements.txt index 98df420a..9e31ae33 100644 --- a/todo/requirements.txt +++ b/todo/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 diff --git a/translator/requirements.txt b/translator/requirements.txt index 8ae44273..ae2746c8 100644 --- a/translator/requirements.txt +++ b/translator/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 googletrans-py==4.0.0 diff --git a/twitter/requirements.txt b/twitter/requirements.txt index 98df420a..9e31ae33 100644 --- a/twitter/requirements.txt +++ b/twitter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0a2 From beced6c7c930a170a831b9c3b322fc51a31d3661 Mon Sep 17 00:00:00 2001 From: Elijah Ahianyo Date: Thu, 15 Feb 2024 21:34:45 +0000 Subject: [PATCH 38/45] Quiz app to radix namespace (#206) --- quiz/.gitignore | 5 ++ quiz/assets/favicon.ico | Bin 0 -> 4286 bytes quiz/quiz/__init__.py | 0 quiz/quiz/quiz.py | 169 ++++++++++++++++++++++++++++++++++++++++ quiz/quiz/results.py | 67 ++++++++++++++++ quiz/requirements.txt | 1 + quiz/rxconfig.py | 5 ++ 7 files changed, 247 insertions(+) create mode 100644 quiz/.gitignore create mode 100644 quiz/assets/favicon.ico create mode 100644 quiz/quiz/__init__.py create mode 100644 quiz/quiz/quiz.py create mode 100644 quiz/quiz/results.py create mode 100644 quiz/requirements.txt create mode 100644 quiz/rxconfig.py diff --git a/quiz/.gitignore b/quiz/.gitignore new file mode 100644 index 00000000..f6711845 --- /dev/null +++ b/quiz/.gitignore @@ -0,0 +1,5 @@ +*.db +*.py[cod] +.web +__pycache__/ +reflex.db \ No newline at end of file diff --git a/quiz/assets/favicon.ico b/quiz/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..166ae995eaa63fc96771410a758282dc30e925cf GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 0 HcmV?d00001 diff --git a/quiz/quiz/__init__.py b/quiz/quiz/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/quiz/quiz/quiz.py b/quiz/quiz/quiz.py new file mode 100644 index 00000000..3f269748 --- /dev/null +++ b/quiz/quiz/quiz.py @@ -0,0 +1,169 @@ +"""Welcome to Reflex! This file outlines the steps to create a basic app.""" +import reflex as rx +import copy +from .results import results +from typing import Any, List + +question_style = { + "bg": "white", + "padding": "2em", + "border_radius": "25px", + "width": "100%", + "align_items": "start", +} + + +class State(rx.State): + """The app state.""" + + default_answers = [None, None, [False, False, False, False, False]] + answers: List[Any] + answer_key = ["False", "[10, 20, 30, 40]", [False, False, True, True, True]] + score: int + + def onload(self): + self.answers = copy.deepcopy(self.default_answers) + + def set_answers(self, answer, index, sub_index=None): + if sub_index is None: + self.answers[index] = answer + else: + self.answers[index][sub_index] = answer + + def submit(self): + total, correct = 0, 0 + for i in range(len(self.answers)): + if self.answers[i] == self.answer_key[i]: + correct += 1 + total += 1 + self.score = int(correct / total * 100) + return rx.redirect("/result") + + @rx.var + def percent_score(self): + return f"{self.score}%" + + +def header(): + return rx.vstack( + rx.heading("Python Quiz"), + rx.divider(), + rx.text("Here is an example of a quiz made in Reflex."), + rx.text("Once submitted the results will be shown in the results page."), + style=question_style, + ) + + +def question1(): + """The main view.""" + return rx.vstack( + rx.heading("Question #1"), + rx.text( + "In Python 3, the maximum value for an integer is 26", + rx.text("3", as_="sup"), + " - 1", + ), + rx.divider(), + rx.radio( + items=["True", "False"], + default_value=State.default_answers[0], + default_checked=True, + on_change=lambda answer: State.set_answers(answer, 0), + ), + style=question_style, + ) + + +def question2(): + return rx.vstack( + rx.heading("Question #2"), + rx.text("What is the output of the following addition (+) operator?"), + rx.code_block( + """a = [10, 20] +b = a +b += [30, 40] +print(a)""", + language="python", + ), + rx.radio( + items=["[10, 20, 30, 40]", "[10, 20]"], + default_value=State.default_answers[1], + default_check=True, + on_change=lambda answer: State.set_answers(answer, 1), + ), + style=question_style, + ) + + +def question3(): + return rx.vstack( + rx.heading("Question #3"), + rx.text( + "Which of the following are valid ways to specify the string literal ", + rx.code("foo'bar"), + " in Python:", + ), + rx.vstack( + rx.checkbox( + text=rx.code("foo'bar"), + on_change=lambda answer: State.set_answers(answer, 2, 0), + ), + rx.checkbox( + text=rx.code("'foo''bar'"), + on_change=lambda answer: State.set_answers(answer, 2, 1), + ), + rx.checkbox( + text=rx.code("'foo\\\\'bar'"), + on_change=lambda answer: State.set_answers(answer, 2, 2), + ), + rx.checkbox( + text=rx.code('''"""foo'bar"""'''), + on_change=lambda answer: State.set_answers(answer, 2, 3), + ), + rx.checkbox( + text=rx.code('''"foo'bar"'''), + on_change=lambda answer: State.set_answers(answer, 2, 4), + ), + align_items="start", + ), + style=question_style, + ) + + +def index(): + """The main view.""" + return rx.center( + rx.vstack( + header(), + question1(), + question2(), + question3(), + rx.button( + "Submit", + bg="black", + color="white", + width="6em", + padding="1em", + on_click=State.submit, + ), + spacing="2", + ), + padding_y="2em", + height="100vh", + align_items="top", + bg="#ededed", + overflow="auto", + ) + + +def result(): + return results(State) + + +app = rx.App( +theme=rx.theme( + has_background=True, radius="none", accent_color="orange", appearance="light", + ), +) +app.add_page(index, title="Reflex Quiz", on_load=State.onload) +app.add_page(result, title="Quiz Results") diff --git a/quiz/quiz/results.py b/quiz/quiz/results.py new file mode 100644 index 00000000..f0e28ec3 --- /dev/null +++ b/quiz/quiz/results.py @@ -0,0 +1,67 @@ +import reflex as rx + +answer_style = { + "border_radius": "10px", + "border": "1px solid #ededed", + "padding": "0.5em", + "align_items": "left", + "shadow": "0px 0px 5px 0px #ededed", +} + + +def render_answer(State, index): + return rx.table.row( + rx.table.cell(index + 1), + rx.table.cell( + rx.cond( + State.answers[index].to_string() == State.answer_key[index].to_string(), + rx.icon(tag="check", color="green"), + rx.icon(tag="x", color="red"), + ) + ), + rx.table.cell(State.answers[index].to_string()), + rx.table.cell(State.answer_key[index].to_string()), + ) + + +def results(State): + """The results view.""" + return rx.center( + rx.vstack( + rx.heading("Results"), + rx.text("Below are the results of the quiz."), + rx.divider(), + rx.center( + rx.chakra.circular_progress( + rx.chakra.circular_progress_label(State.percent_score), + value=State.score, + size="3em", + ) + ), + rx.table.root( + rx.table.header( + rx.table.row( + rx.table.column_header_cell("#"), + rx.table.column_header_cell("Result"), + rx.table.column_header_cell("Your Answer"), + rx.table.column_header_cell("Correct Answer"), + ), + ), + rx.table.body( + rx.foreach(State.answers, lambda answer, i: render_answer(State, i)), + ), + ), + rx.box(rx.link(rx.button("Take Quiz Again"), href="/")), + bg="white", + padding_x="5em", + padding_y="2em", + border_radius="25px", + align_items="left", + overflow="auto", + ), + padding="1em", + height="100vh", + align_items="top", + bg="#ededed", + overflow="auto", + ) diff --git a/quiz/requirements.txt b/quiz/requirements.txt new file mode 100644 index 00000000..98df420a --- /dev/null +++ b/quiz/requirements.txt @@ -0,0 +1 @@ +reflex>=0.4.0a1 diff --git a/quiz/rxconfig.py b/quiz/rxconfig.py new file mode 100644 index 00000000..58fcd44a --- /dev/null +++ b/quiz/rxconfig.py @@ -0,0 +1,5 @@ +import reflex as rx + +config = rx.Config( + app_name="quiz", +) From 3c7b90dad98c7e33f3b18c8191e6626abf50e668 Mon Sep 17 00:00:00 2001 From: jackie-pc Date: Thu, 15 Feb 2024 14:09:35 -0800 Subject: [PATCH 39/45] upload app to use radix components, hook up progress bar (#202) * upload app to use radix components, hook up progress bar * update req * Move upload app to top-level * Support more upload features in the example * directory uploads * cancellation * show selected files --------- Co-authored-by: Masen Furer --- chakra_apps/crm/requirements.txt | 2 +- chakra_apps/upload/upload/upload.py | 80 ------------- {chakra_apps/upload => upload}/.gitignore | 0 .../upload => upload}/assets/favicon.ico | Bin .../upload => upload}/requirements.txt | 0 {chakra_apps/upload => upload}/rxconfig.py | 0 .../upload => upload}/upload/__init__.py | 0 upload/upload/upload.py | 109 ++++++++++++++++++ 8 files changed, 110 insertions(+), 81 deletions(-) delete mode 100644 chakra_apps/upload/upload/upload.py rename {chakra_apps/upload => upload}/.gitignore (100%) rename {chakra_apps/upload => upload}/assets/favicon.ico (100%) rename {chakra_apps/upload => upload}/requirements.txt (100%) rename {chakra_apps/upload => upload}/rxconfig.py (100%) rename {chakra_apps/upload => upload}/upload/__init__.py (100%) create mode 100644 upload/upload/upload.py diff --git a/chakra_apps/crm/requirements.txt b/chakra_apps/crm/requirements.txt index 11eb7423..889adc5b 100644 --- a/chakra_apps/crm/requirements.txt +++ b/chakra_apps/crm/requirements.txt @@ -1 +1 @@ -reflex>=0.3.8 \ No newline at end of file +reflex>=0.4.0a1 \ No newline at end of file diff --git a/chakra_apps/upload/upload/upload.py b/chakra_apps/upload/upload/upload.py deleted file mode 100644 index 9d6604d6..00000000 --- a/chakra_apps/upload/upload/upload.py +++ /dev/null @@ -1,80 +0,0 @@ -import asyncio -import os -from typing import List - -import reflex as rx - - -class State(rx.State): - """The app state.""" - - # Whether we are currently uploading files. - is_uploading: bool - - @rx.var - def files(self) -> list[str]: - """Get the string representation of the uploaded files.""" - return os.listdir(rx.get_upload_dir()) - - async def handle_upload(self, files: List[rx.UploadFile]): - """Handle the file upload.""" - self.is_uploading = True - - # Iterate through the uploaded files. - for file in files: - upload_data = await file.read() - outfile = os.path.join(rx.get_upload_dir(), file.filename) - with open(outfile, "wb") as file_object: - file_object.write(upload_data) - - # Stop the upload. - return State.stop_upload - - async def stop_upload(self): - """Stop the file upload.""" - await asyncio.sleep(1) - self.is_uploading = False - - -color = "rgb(107,99,246)" - - -def index(): - return rx.chakra.vstack( - rx.upload( - rx.chakra.button( - "Select File(s)", - height="70px", - width="200px", - color=color, - bg="white", - border=f"1px solid {color}", - ), - rx.chakra.text( - "Drag and drop files here or click to select files", - height="100px", - width="200px", - ), - border="1px dotted black", - padding="2em", - ), - rx.chakra.hstack( - rx.chakra.button( - "Upload", - on_click=State.handle_upload(rx.upload_files()), - ), - ), - rx.chakra.heading("Files:"), - rx.cond( - State.is_uploading, - rx.chakra.progress(is_indeterminate=True, color="blue", width="100%"), - rx.chakra.progress(value=0, width="100%"), - ), - rx.chakra.vstack( - rx.foreach(State.files, lambda file: rx.link(file, href=rx.get_upload_url(file))) - ), - ) - - -app = rx.App() -app.add_page(index, title="Upload") diff --git a/chakra_apps/upload/.gitignore b/upload/.gitignore similarity index 100% rename from chakra_apps/upload/.gitignore rename to upload/.gitignore diff --git a/chakra_apps/upload/assets/favicon.ico b/upload/assets/favicon.ico similarity index 100% rename from chakra_apps/upload/assets/favicon.ico rename to upload/assets/favicon.ico diff --git a/chakra_apps/upload/requirements.txt b/upload/requirements.txt similarity index 100% rename from chakra_apps/upload/requirements.txt rename to upload/requirements.txt diff --git a/chakra_apps/upload/rxconfig.py b/upload/rxconfig.py similarity index 100% rename from chakra_apps/upload/rxconfig.py rename to upload/rxconfig.py diff --git a/chakra_apps/upload/upload/__init__.py b/upload/upload/__init__.py similarity index 100% rename from chakra_apps/upload/upload/__init__.py rename to upload/upload/__init__.py diff --git a/upload/upload/upload.py b/upload/upload/upload.py new file mode 100644 index 00000000..55de7cf4 --- /dev/null +++ b/upload/upload/upload.py @@ -0,0 +1,109 @@ +import os +from pathlib import Path +from typing import List + +import reflex as rx + + +class State(rx.State): + """The app state.""" + + # Whether we are currently uploading files. + is_uploading: bool + + # Progress visuals + upload_progress: int + + @rx.var + def files(self) -> list[str]: + """Get the string representation of the uploaded files.""" + return [ + "/".join(p.parts[1:]) + for p in Path(rx.get_upload_dir()).rglob("*") + if p.is_file() + ] + + async def handle_upload(self, files: List[rx.UploadFile]): + """Handle the file upload.""" + # Iterate through the uploaded files. + for file in files: + upload_data = await file.read() + outfile = Path(rx.get_upload_dir()) / file.filename.lstrip("/") + outfile.parent.mkdir(parents=True, exist_ok=True) + outfile.write_bytes(upload_data) + + def on_upload_progress(self, prog: dict): + print("Got progress", prog) + if prog["progress"] < 1: + self.is_uploading = True + else: + self.is_uploading = False + self.upload_progress = round(prog["progress"] * 100) + + def cancel_upload(self, upload_id: str): + self.is_uploading = False + return rx.cancel_upload(upload_id) + + +color = "rgb(107,99,246)" +upload_id = "upload1" + + +def index(): + return rx.vstack( + rx.upload( + rx.vstack( + rx.button( + "Select File(s)", + height="70px", + width="200px", + color=color, + bg="white", + border=f"1px solid {color}", + ), + rx.text( + "Drag and drop files here or click to select files", + height="100px", + width="200px", + ), + rx.cond( + rx.selected_files(upload_id), + rx.foreach( + rx.selected_files(upload_id), + rx.text, + ), + rx.text("No files selected"), + ), + align="center", + ), + id=upload_id, + border="1px dotted black", + padding="2em", + ), + rx.hstack( + rx.button( + "Upload", + on_click=State.handle_upload( + rx.upload_files( + upload_id=upload_id, + on_upload_progress=State.on_upload_progress + ) + ), + ), + ), + rx.heading("Files:"), + + rx.cond( + State.is_uploading, + rx.text("Uploading... ", rx.link("cancel", on_click=State.cancel_upload(upload_id))), + ), + rx.progress(value=State.upload_progress), + rx.vstack( + rx.foreach(State.files, lambda file: rx.link(file, href=rx.get_upload_url(file))) + ), + align="center", + ) + + +app = rx.App() +app.add_page(index, title="Upload") From 5891aa017befec5834a46766d5e6ce66f4dcff9e Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:18:34 -0800 Subject: [PATCH 40/45] test again --- basic_crud/assets/favicon.ico | Bin 15086 -> 4286 bytes basic_crud/basic_crud/basic_crud.py | 13 +++++--- clock/clock/clock.py | 19 ++++++------ counter/assets/favicon.ico | Bin 15406 -> 4286 bytes counter/counter/counter.py | 3 ++ dalle/dalle/dalle.py | 1 + github-stats/assets/favicon.ico | Bin 15086 -> 4286 bytes github-stats/github_stats/fetchers.py | 5 +-- github-stats/github_stats/github_stats.py | 22 +++++-------- gpt/assets/favicon.ico | Bin 15406 -> 4286 bytes gpt/gpt/gpt.py | 21 +++++-------- gpt/gpt/helpers.py | 5 ++- snakegame/snakegame/snakegame.py | 36 ++++++++++++++-------- todo/todo/todo.py | 24 ++++++++------- translator/translator/translator.py | 5 +-- twitter/twitter/components/container.py | 4 ++- twitter/twitter/layouts/auth.py | 12 +++----- twitter/twitter/pages/home.py | 24 ++++++++------- twitter/twitter/pages/login.py | 20 ++++++------ twitter/twitter/pages/signup.py | 21 ++++++++----- 20 files changed, 122 insertions(+), 113 deletions(-) diff --git a/basic_crud/assets/favicon.ico b/basic_crud/assets/favicon.ico index 609f6abcbeb0fec5157b54a36d7b2aeb759f9e1b..166ae995eaa63fc96771410a758282dc30e925cf 100644 GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 15086 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 rx.Component: rx.spacer(), height="100vh", width="100vw", - gap="0", + spacing="0", ) diff --git a/clock/clock/clock.py b/clock/clock/clock.py index 29dc5b1f..e6dd3a49 100644 --- a/clock/clock/clock.py +++ b/clock/clock/clock.py @@ -6,12 +6,10 @@ import reflex as rx from reflex.components.radix.themes import theme -# import reflex.components.radix.themes as rdxt import pytz - # The supported time zones. TIMEZONES = [ "Asia/Tokyo", @@ -117,7 +115,6 @@ def flip_switch(self, running: bool): return State.tick - def clock_hand(rotation: str, color: str, length: str) -> rx.Component: """Create a clock hand. @@ -140,7 +137,6 @@ def clock_hand(rotation: str, color: str, length: str) -> rx.Component: ) - def analog_clock() -> rx.Component: """Create the analog clock.""" return rx.chakra.circle( @@ -211,14 +207,19 @@ def index(): border_color="#43464B", border_radius="25px", background="#ededed", - #bg=accent_color, text_align="center", ), padding="5em", ) - - -app = rx.App(theme=theme(appearance="light", has_background=True, radius="large", accent_color="amber", gray_color="sand",)) -app.add_page(index, title="Clock", on_load=State.on_load) \ No newline at end of file +app = rx.App( + theme=theme( + appearance="light", + has_background=True, + radius="large", + accent_color="amber", + gray_color="sand", + ) +) +app.add_page(index, title="Clock", on_load=State.on_load) diff --git a/counter/assets/favicon.ico b/counter/assets/favicon.ico index 8a93bfa72ad182e4a21385b6daac8106eb16158e..166ae995eaa63fc96771410a758282dc30e925cf 100644 GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 15406 zcmeI1X{eP|6o$X6=1^H?2{!4mEF>DV%qEJ+XwD)Eq!1b?3Mm>iiXyZhO%M$blz_D|T2;5xVnUIG6s)LsOQnbRF^BQOt6h11}ph1&XznbQ@9;JgF!iByZ>&u~Ja zwmxI#nA;U*;QR<41-<__3$^tbGp9Q^Kks=KysOw=-wkJ#Yje88^#sgc4M)PS;Mc|0 zXUv@LFqyy_I0a6JCl_k#GiFYA*q*?_@GNMriwd>%88heK(2s=I;L1X6eLcZ`B)eav zb|binBDvMVbEXE5g`Q7sv{#_P6&Ot2qppq*ppT4SvmYN^>% zOsBwioXbn$0>OO8!rlXpg7Ll+u{;_x$6RY7rdCf; zf9}jL0#`DIZvA*w$uT#_8aao2AIlorXTtt4_H~ZC|BRWF{n~2v6gyCm&lq*Sf%<*l z^I3~Ne$M)gnG=3THS{-vk15Jp%ek%r3_>{X$yd0R(c73gt;ErYZ-mh^Mt#OM2OgkF^o?=O z=4f1c3}fs}bI{heIpO!-xOeUU15eOYw$WaJ_6jtx0^_I|56_3~-$_`6HrgxDUV*J) z1v`^=dX{)wJ~$d&A$yrd?9{&v}MVQ9Q|EzCfpTHfUmOt$@GRxjwnyO0F+}#sZTt*2A2qt`S!4vJ)4CZLiSYuGw42WE_=f_pgoOg$2`x&UR8K5qxr_niFs

7ijOARPX*DwJVJ|-ed-oQnAmHCd_jCt522L*a2*&4N zo|Cp~XnsIjUwxjnYN)HG+S=yZ)85U(V1%Z@U*S7&3=~t~k1)?|J=e3LHBwt&&avhU zDAZC@ZF^YLOl*tT47d_H2Y=JM2X;Vv&4GDt+RNd6h1&ITYphj6Ej7)thrR6CEVy@9 z!#oGq%KwuI_o@3e$N$OBds_{)a=yLd8N%!}4nZORUn6>bfZx3;PKWi+XXNE^ZOOI9 zS~YT9+g|o;7Dgk~)%yO1e-`w7910(V8({r>;@a3l&|GU~K{X;CqrFDMW?>hEUVx#W z$EEo9FO3dm^g740-AT+GVNG|r_OfTQ;9B`C=DB41Sz>W!+<@KHXQ1y!D9p7cYh>GA z_G~7uMr=LIeZuzah_l-NdA-<0-a>raLt$>5H=z-uJ?zzNc+UR>qfZ`R#h*WKpS|x= zuJ%M2FxQ%_5w<<-)okpC;MXwvIC@U_9ytPv{?PM$AiM<{m$yQF#>^4cSZh3M+QVMW z#^)18S;mkIjieGzvY;Cc8J%=7b^yreKcpXQjG&s#44cbv@({Jxv-VJ+7(`^+)7ufg-> zAy~gp^4yJ?6Mu&>`xFjiHud``&)=9ieHHzf*bJEGob8#!%<0P*!sMQZdEVOkjBN=x zkV$sJxCd>0TM9haXG6bRtt)n4IqR9uf5Pr$`OYu3+i0&qdj;An&|ZP|3ba?CtiWIG CTt?CW diff --git a/counter/counter/counter.py b/counter/counter/counter.py index aaec592d..a694875c 100644 --- a/counter/counter/counter.py +++ b/counter/counter/counter.py @@ -1,4 +1,5 @@ """Welcome to Reflex! This file create a counter app.""" + import reflex as rx import random @@ -37,6 +38,8 @@ def index(): rx.button("Increment", on_click=State.increment, color_scheme="green"), ), padding="1em", + bg="#ededed", + border_radius="1em", ), padding_y="5em", font_size="2em", diff --git a/dalle/dalle/dalle.py b/dalle/dalle/dalle.py index 9e3c77c3..cd07f7e8 100644 --- a/dalle/dalle/dalle.py +++ b/dalle/dalle/dalle.py @@ -79,6 +79,7 @@ def index(): width="25em", bg="white", padding="2em", + align="center", ), width="100%", height="100vh", diff --git a/github-stats/assets/favicon.ico b/github-stats/assets/favicon.ico index 609f6abcbeb0fec5157b54a36d7b2aeb759f9e1b..166ae995eaa63fc96771410a758282dc30e925cf 100644 GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 15086 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 rx.Component: rx.color_mode.button(rx.color_mode.icon(), float="right"), rx.vstack( rx.heading("Github Stats", font_size="2em"), - rx.flex( + rx.hstack( rx.foreach( State.selected_users, lambda user: rx.box( @@ -122,7 +110,6 @@ def index() -> rx.Component: padding="5px", ), ), - direction="row", wrap="wrap", ), rx.cond( @@ -131,7 +118,12 @@ def index() -> rx.Component: rx.text("Fetching Data..."), ), ), - rx.input(placeholder="Github Username", id="username", value=State.username, on_change=State.set_username), + rx.input( + placeholder="Github Username", + id="username", + value=State.username, + on_change=State.set_username, + ), rx.button("Get Stats", on_click=State.add_user), rx.box( rx.recharts.bar_chart( diff --git a/gpt/assets/favicon.ico b/gpt/assets/favicon.ico index 8a93bfa72ad182e4a21385b6daac8106eb16158e..166ae995eaa63fc96771410a758282dc30e925cf 100644 GIT binary patch literal 4286 zcmeHL>rYc>81ELdEe;}zmYd}cUgmJRfwjUwD1`#s5KZP>mMqza#Viv|_7|8f+0+bX zHuqusuw-7Ca`DTu#4U4^o2bjO#K>4%N?Wdi*wZ3Vx%~Ef4}D1`U_EMRg3u z#2#M|V>}}q-@IaO@{9R}d*u7f&~5HfxSkmHVcazU#i30H zAGxQ5Spe!j9`KuGqR@aExK`-}sH1jvqoIp3C7Vm)9Tu=UPE;j^esN~a6^a$ZILngo;^ zGLXl(ZFyY&U!li`6}y-hUQ99v?s`U4O!kgog74FPw-9g+V)qs!jFGEQyvBf><U|E2vRmx|+(VI~S=lT?@~C5pvZOd`x{Q_+3tG6H=gtdWcf z)+7-Zp=UqH^J4sk^>_G-Ufn-2Hz z2mN12|C{5}U`^eCQuFz=F%wp@}SzA1MHEaM^CtJs<{}Tzu$bx2orTKiedgmtVGM{ zdd#vX`&cuiec|My_KW;y{Ryz2kFu9}=~us6hvx1ZqQCk(d+>HP>ks>mmHCjjDh{pe zKQkKpk0SeDX#XMqf$}QV{z=xrN!mQczJAvud@;zFqaU1ocq==Py)qsa=8UKrt!J7r z{RsTo^rgtZo%$rak)DN*D)!(Y^$@yL6Nd=#eu&?unzhH8yq>v{gkt8xcG3S%H)-y_ zqQ1|v|JT$0R~Y}omg2Y+nDvR+K|kzR5i^fmKF>j~N;A35Vr`JWh4yRqKl#P|qlx?` z@|CmBiP}ysYO%m2{eBG6&ix5 zr#u((F2{vb=W4jNmTQh3M^F2o80T49?w>*rv0mt)-o1y!{hRk`E#UVPdna6jnz`rw dKpn)r^--YJZpr;bYU`N~>#v3X5BRU&{{=gv-{1fM literal 15406 zcmeI1X{eP|6o$X6=1^H?2{!4mEF>DV%qEJ+XwD)Eq!1b?3Mm>iiXyZhO%M$blz_D|T2;5xVnUIG6s)LsOQnbRF^BQOt6h11}ph1&XznbQ@9;JgF!iByZ>&u~Ja zwmxI#nA;U*;QR<41-<__3$^tbGp9Q^Kks=KysOw=-wkJ#Yje88^#sgc4M)PS;Mc|0 zXUv@LFqyy_I0a6JCl_k#GiFYA*q*?_@GNMriwd>%88heK(2s=I;L1X6eLcZ`B)eav zb|binBDvMVbEXE5g`Q7sv{#_P6&Ot2qppq*ppT4SvmYN^>% zOsBwioXbn$0>OO8!rlXpg7Ll+u{;_x$6RY7rdCf; zf9}jL0#`DIZvA*w$uT#_8aao2AIlorXTtt4_H~ZC|BRWF{n~2v6gyCm&lq*Sf%<*l z^I3~Ne$M)gnG=3THS{-vk15Jp%ek%r3_>{X$yd0R(c73gt;ErYZ-mh^Mt#OM2OgkF^o?=O z=4f1c3}fs}bI{heIpO!-xOeUU15eOYw$WaJ_6jtx0^_I|56_3~-$_`6HrgxDUV*J) z1v`^=dX{)wJ~$d&A$yrd?9{&v}MVQ9Q|EzCfpTHfUmOt$@GRxjwnyO0F+}#sZTt*2A2qt`S!4vJ)4CZLiSYuGw42WE_=f_pgoOg$2`x&UR8K5qxr_niFs

7ijOARPX*DwJVJ|-ed-oQnAmHCd_jCt522L*a2*&4N zo|Cp~XnsIjUwxjnYN)HG+S=yZ)85U(V1%Z@U*S7&3=~t~k1)?|J=e3LHBwt&&avhU zDAZC@ZF^YLOl*tT47d_H2Y=JM2X;Vv&4GDt+RNd6h1&ITYphj6Ej7)thrR6CEVy@9 z!#oGq%KwuI_o@3e$N$OBds_{)a=yLd8N%!}4nZORUn6>bfZx3;PKWi+XXNE^ZOOI9 zS~YT9+g|o;7Dgk~)%yO1e-`w7910(V8({r>;@a3l&|GU~K{X;CqrFDMW?>hEUVx#W z$EEo9FO3dm^g740-AT+GVNG|r_OfTQ;9B`C=DB41Sz>W!+<@KHXQ1y!D9p7cYh>GA z_G~7uMr=LIeZuzah_l-NdA-<0-a>raLt$>5H=z-uJ?zzNc+UR>qfZ`R#h*WKpS|x= zuJ%M2FxQ%_5w<<-)okpC;MXwvIC@U_9ytPv{?PM$AiM<{m$yQF#>^4cSZh3M+QVMW z#^)18S;mkIjieGzvY;Cc8J%=7b^yreKcpXQjG&s#44cbv@({Jxv-VJ+7(`^+)7ufg-> zAy~gp^4yJ?6Mu&>`xFjiHud``&)=9ieHHzf*bJEGob8#!%<0P*!sMQZdEVOkjBN=x zkV$sJxCd>0TM9haXG6bRtt)n4IqR9uf5Pr$`OYu3+i0&qdj;An&|ZP|3ba?CtiWIG CTt?CW diff --git a/gpt/gpt/gpt.py b/gpt/gpt/gpt.py index 70a149f1..0b2ae332 100644 --- a/gpt/gpt/gpt.py +++ b/gpt/gpt/gpt.py @@ -181,13 +181,12 @@ def result_view() -> rx.Component: def ask_gpt_form() -> rx.Component: - return rx.flex( + return rx.vstack( rx.heading("Ask GPT", font_size="1.5em", align="center"), rx.form( - rx.flex( + rx.vstack( rx.input(placeholder="Question", name="prompt", width="100%"), rx.button("Get Answer", width="100%"), - direction="column", spacing="3", ), on_submit=State.get_result, @@ -195,7 +194,6 @@ def ask_gpt_form() -> rx.Component: ), rx.divider(), result_view(), - direction="column", align="stretch", spacing="3", width="100%", @@ -216,7 +214,7 @@ def saved_qa_item(qa: Question, ix: int) -> rx.Component: def saved_qa() -> rx.Component: - return rx.flex( + return rx.vstack( rx.heading("Saved Q&A", font_size="1.5em"), rx.divider(), rx.input( @@ -234,7 +232,6 @@ def saved_qa() -> rx.Component: single=False, collapsible=True, ), - direction="column", spacing="3", padding="1em", width="100%", @@ -244,13 +241,12 @@ def saved_qa() -> rx.Component: def home(): return rx.flex( navbar(State), - rx.flex( + rx.vstack( rx.card(ask_gpt_form()), rx.cond( State.logged_in, rx.card(saved_qa()), ), - direction="column", spacing="4", width="50%", ), @@ -264,7 +260,7 @@ def home(): def login(): return rx.form( rx.card( - rx.flex( + rx.vstack( rx.input(name="username", placeholder="Username", width="100%"), rx.input( type="password", @@ -279,7 +275,6 @@ def login(): width="100%", on_click=rx.redirect("/signup"), ), - direction="column", spacing="3", ) ), @@ -290,7 +285,7 @@ def login(): def signup(): return rx.flex( rx.form( - rx.flex( + rx.vstack( rx.heading("GPT Sign Up", font_size="1.5em"), rx.input(name="username", placeholder="Username", width="100%"), rx.input( @@ -307,7 +302,6 @@ def signup(): width="100%", ), rx.button("Sign Up", width="100%"), - direction="column", spacing="3", align="center", justify="center", @@ -328,13 +322,12 @@ def signup(): def index(): - return rx.flex( + return rx.vstack( navbar(State), rx.flex( login(), justify="center", ), - direction="column", padding_top="10em", text_align="top", position="relative", diff --git a/gpt/gpt/helpers.py b/gpt/gpt/helpers.py index c85f38c2..8af336e0 100644 --- a/gpt/gpt/helpers.py +++ b/gpt/gpt/helpers.py @@ -5,7 +5,7 @@ def navbar(State: rx.State) -> rx.Component: return rx.box( rx.flex( rx.link( - rx.flex( + rx.hstack( rx.image(src="/favicon.ico"), rx.heading("GPT Demo"), align="center", @@ -21,10 +21,9 @@ def navbar(State: rx.State) -> rx.Component: rx.cond( State.logged_in, rx.fragment( - rx.flex( + rx.hstack( rx.avatar(fallback=State.username[0].to(str), size="3"), rx.text(State.username), - spacing="2", align="center", justify="center", ), diff --git a/snakegame/snakegame/snakegame.py b/snakegame/snakegame/snakegame.py index 92b4c674..07a06db0 100644 --- a/snakegame/snakegame/snakegame.py +++ b/snakegame/snakegame/snakegame.py @@ -236,36 +236,42 @@ def render(self) -> str: def colored_box(color, index): """One square of the game grid.""" - return rx.box(background_color=color, width="1em", height="1em", border="1px solid white") + return rx.chakra.box( + background_color=color, width="1em", height="1em", border="1px solid white" + ) def stat_box(label, value): """One of the score, magic, or rate boxes.""" return rx.vstack( rx.heading(label, font_size="1em"), - rx.heading(value, font_size="2em"), + rx.heading( + value, + font_size="2em", + margin_bottom="0.1em", + ), bg_color="yellow", border_width="1px", padding_left="1em", padding_right="1em", + align="center", ) def control_button(label, on_click): """One of the arrow buttons for touch/mouse control.""" - return rx.button( - label, + return rx.icon_button( + rx.icon(tag=label), on_click=on_click, color_scheme="red", - border_radius="1em", - font_size="2em", + radius="full", + size="3", ) def padding_button(): """A button that is used for padding in the controls panel.""" return rx.button( - "○", border_radius="1em", font_size="2em", visibility="hidden", @@ -282,27 +288,28 @@ def controls_panel(): rx.vstack( padding_button(), control_button( - "←", + "arrow_left", on_click=State.arrow_left, ), ), rx.vstack( control_button( - "↑", + "arrow_up", on_click=State.arrow_up, ), control_button( - "↓", + "arrow_down", on_click=State.arrow_down, ), ), rx.vstack( padding_button(), control_button( - "→", + "arrow_right", on_click=State.arrow_right, ), ), + align="end", ) @@ -313,15 +320,16 @@ def index(): "PAUSE", on_click=State.pause, color_scheme="blue", - border_radius="1em", + radius="full", ), rx.button( "RUN", on_click=State.play, color_scheme="green", - border_radius="1em", + radius="full", ), rx.switch(checked=State.running, on_change=State.flip_switch), + align="center", ), rx.hstack( stat_box("RATE", State.rate), @@ -339,6 +347,8 @@ def index(): rx.cond(State.died, rx.heading("Game Over 🐍")), controls_panel(), padding_top="3%", + spacing="2", + align="center", ) diff --git a/todo/todo/todo.py b/todo/todo/todo.py index ea4b2ba2..776bf2ba 100644 --- a/todo/todo/todo.py +++ b/todo/todo/todo.py @@ -39,10 +39,11 @@ def todo_item(item: rx.Var[str]) -> rx.Component: """ return rx.list_item( # A button to finish the item. - rx.button("✓", - on_click=lambda: State.finish_item(item), - margin="0 1em 1em 0" - ), + rx.icon_button( + rx.icon(tag="check"), + on_click=lambda: State.finish_item(item), + margin="0 1em 1em 0", + ), # The item text. rx.text(item, as_="span"), ) @@ -69,13 +70,14 @@ def new_item() -> rx.Component: Returns: A form to add a new item to the todo list. """ - return rx.hstack(rx.input( - id="new_item", - placeholder="Add a todo...", - bg="white", - on_change=State.set_new_item, - value=State.new_item, - ), + return rx.hstack( + rx.input( + id="new_item", + placeholder="Add a todo...", + bg="white", + on_change=State.set_new_item, + value=State.new_item, + ), rx.button("Add", on_click=State.add_item), ) diff --git a/translator/translator/translator.py b/translator/translator/translator.py index 3538434b..dcb90cae 100644 --- a/translator/translator/translator.py +++ b/translator/translator/translator.py @@ -77,6 +77,7 @@ def down_arrow() -> rx.Component: tag="arrow_down", color="gray", ), + align="center", ) @@ -92,7 +93,7 @@ def text_box(text) -> rx.Component: def past_translation(message: Message) -> rx.Component: """A layout that contains a past translation.""" return rx.box( - rx.flex( + rx.vstack( text_box(message.original_text), down_arrow(), text_box(message.text), @@ -105,7 +106,7 @@ def past_translation(message: Message) -> rx.Component: color=rx.color("gray", 11), ), spacing="2", - direction="column", + align="stretch", ), background_color=rx.color("gray", 3), padding="1rem", diff --git a/twitter/twitter/components/container.py b/twitter/twitter/components/container.py index 334f3706..6c32dad0 100644 --- a/twitter/twitter/components/container.py +++ b/twitter/twitter/components/container.py @@ -1,6 +1,8 @@ """A container component.""" + import reflex as rx + def container(*children, **props): """A fixed container based on a 960px grid.""" # Enable override of default props. @@ -16,4 +18,4 @@ def container(*children, **props): ) | props ) - return rx.box(*children, **props) + return rx.stack(*children, **props) diff --git a/twitter/twitter/layouts/auth.py b/twitter/twitter/layouts/auth.py index a0abcfcc..90f55d24 100644 --- a/twitter/twitter/layouts/auth.py +++ b/twitter/twitter/layouts/auth.py @@ -1,4 +1,5 @@ """Shared auth layout.""" + import reflex as rx from ..components import container @@ -8,13 +9,10 @@ def auth_layout(*args): """The shared layout for the login and sign up pages.""" return rx.box( container( - rx.heading( - rx.text("Welcome to PySocial!", as_="span"), - rx.text("Sign in or sign up to get started.", as_="span"), - display="flex", - flex_direction="column", - align_items="center", - text_align="center", + rx.vstack( + rx.heading("Welcome to PySocial!", size="8"), + rx.heading("Sign in or sign up to get started.", size="8"), + align="center", ), rx.text( "See the source code for this demo app ", diff --git a/twitter/twitter/pages/home.py b/twitter/twitter/pages/home.py index 4133c84f..595fb24b 100644 --- a/twitter/twitter/pages/home.py +++ b/twitter/twitter/pages/home.py @@ -1,4 +1,5 @@ """The home page. This file includes examples abstracting complex UI into smaller components.""" + import reflex as rx from twitter.state.base import State from twitter.state.home import HomeState @@ -6,6 +7,10 @@ from ..components import container +def avatar(name: str): + return rx.avatar(fallback=name[:2], size="4") + + def tab_button(name, href): """A tab switcher button.""" return rx.link( @@ -33,7 +38,7 @@ def tabs(): HomeState.followers, lambda follow: rx.vstack( rx.hstack( - rx.avatar(fallback=follow.follower_username, size="3"), + avatar(follow.follower_username), rx.text(follow.follower_username), ), padding="1em", @@ -64,7 +69,7 @@ def sidebar(HomeState): HomeState.search_users, lambda user: rx.vstack( rx.hstack( - rx.avatar(fallback=user.username, size="3"), + avatar(user.username), rx.text(user.username), rx.spacer(), rx.button( @@ -84,7 +89,7 @@ def sidebar(HomeState): HomeState.following, lambda follow: rx.vstack( rx.hstack( - rx.avatar(fallback=follow.followed_username, size="3"), + avatar(follow.followed_username), rx.text(follow.followed_username), ), padding="1em", @@ -118,7 +123,7 @@ def composer(HomeState): """The composer for new tweets.""" return rx.grid( rx.vstack( - rx.avatar(fallback=State.user.username.to_string(), size="4"), + avatar(State.user.username), padding="1.5rem", ), rx.box( @@ -130,15 +135,13 @@ def composer(HomeState): _focus={"border": 0, "outline": 0, "boxShadow": "none"}, on_blur=HomeState.set_tweet, ), - padding_top="1.5rem", - padding_bottom="1.5rem", + padding_y="1.5rem", + padding_right="1.5rem", ), - rx.hstack( rx.button( "Tweet", on_click=HomeState.post_tweet, - color="white", radius="full", size="3", ), @@ -159,7 +162,7 @@ def tweet(tweet): """Display for an individual tweet in the feed.""" return rx.grid( rx.vstack( - rx.avatar(fallback=tweet.author, size="3"), + avatar(tweet.author), ), rx.box( rx.vstack( @@ -169,8 +172,7 @@ def tweet(tweet): ), ), grid_template_columns="1fr 5fr", - padding_top="1.5rem", - padding_bottom="1.5rem", + padding="1.5rem", spacing="1", border_bottom="1px solid #ededed", ) diff --git a/twitter/twitter/pages/login.py b/twitter/twitter/pages/login.py index 96755b65..be78aa39 100644 --- a/twitter/twitter/pages/login.py +++ b/twitter/twitter/pages/login.py @@ -1,4 +1,5 @@ """Login page. Uses auth_layout to render UI shared with the sign up page.""" + import reflex as rx from twitter.layouts import auth_layout from twitter.state.auth import AuthState @@ -9,26 +10,25 @@ def login(): return auth_layout( rx.box( rx.vstack( - rx.input(placeholder="Username", on_blur=AuthState.set_username, margin_bottom="12px",), rx.input( - type_="password", + placeholder="Username", + on_blur=AuthState.set_username, + size="3", + ), + rx.input( + type="password", placeholder="Password", on_blur=AuthState.set_password, - margin_bottom="12px", - ), - rx.button( - "Log in", - on_click=AuthState.login, - color="white", size="3", ), - spacing="3", + rx.button("Log in", on_click=AuthState.login, size="3", width="5em"), + spacing="4", ), align_items="left", background="white", border="1px solid #eaeaea", padding="16px", - max_width="400px", + width="400px", border_radius="8px", ), rx.text( diff --git a/twitter/twitter/pages/signup.py b/twitter/twitter/pages/signup.py index ba2cb298..5625b57d 100644 --- a/twitter/twitter/pages/signup.py +++ b/twitter/twitter/pages/signup.py @@ -1,4 +1,5 @@ """Sign up page. Uses auth_layout to render UI shared with the login page.""" + import reflex as rx from twitter.layouts import auth_layout from twitter.state.auth import AuthState @@ -9,32 +10,36 @@ def signup(): return auth_layout( rx.box( rx.vstack( - rx.input(placeholder="Username", on_blur=AuthState.set_username, margin_bottom="12px",), rx.input( - type_="password", + placeholder="Username", + on_blur=AuthState.set_username, + size="3", + ), + rx.input( + type="password", placeholder="Password", on_blur=AuthState.set_password, - margin_bottom="12px", + size="3", ), rx.input( - type_="password", + type="password", placeholder="Confirm password", on_blur=AuthState.set_confirm_password, - margin_bottom="12px", + size="3", ), rx.button( "Sign up", on_click=AuthState.signup, - color="white", size="3", + width="6em", ), - spacing="3", + spacing="4", ), align_items="left", background="white", border="1px solid #eaeaea", padding="16px", - max_width="400px", + width="400px", border_radius="8px", ), rx.text( From 591bb8db1d3a0a54b987bb610f9de559b5c1f31f Mon Sep 17 00:00:00 2001 From: Martin Xu <15661672+martinxu9@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:22:05 -0800 Subject: [PATCH 41/45] bump up pre-release used --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- basic_crud/requirements.txt | 2 +- clock/requirements.txt | 2 +- counter/requirements.txt | 2 +- dalle/requirements.txt | 2 +- github-stats/requirements.txt | 2 +- gpt/requirements.txt | 2 +- nba/requirements.txt | 2 +- snakegame/requirements.txt | 2 +- todo/requirements.txt | 2 +- translator/requirements.txt | 2 +- twitter/requirements.txt | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index bceb9247..b7ba6d32 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,7 +1,7 @@ name: app-harness env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a2' + REFLEX_VERSION: '==0.4.0a3' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index d7a3af69..680e97f0 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,7 +1,7 @@ name: check-export env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a2' + REFLEX_VERSION: '==0.4.0a3' TELEMETRY_ENABLED: false on: push: diff --git a/basic_crud/requirements.txt b/basic_crud/requirements.txt index 9e31ae33..af29bf04 100644 --- a/basic_crud/requirements.txt +++ b/basic_crud/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 diff --git a/clock/requirements.txt b/clock/requirements.txt index ca9cfcc9..f9d97c91 100644 --- a/clock/requirements.txt +++ b/clock/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 pytz==2022.7.1 diff --git a/counter/requirements.txt b/counter/requirements.txt index 9e31ae33..af29bf04 100644 --- a/counter/requirements.txt +++ b/counter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 diff --git a/dalle/requirements.txt b/dalle/requirements.txt index 09b27902..efd7265a 100644 --- a/dalle/requirements.txt +++ b/dalle/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 openai>=1 diff --git a/github-stats/requirements.txt b/github-stats/requirements.txt index 9e31ae33..af29bf04 100644 --- a/github-stats/requirements.txt +++ b/github-stats/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 diff --git a/gpt/requirements.txt b/gpt/requirements.txt index 09b27902..efd7265a 100644 --- a/gpt/requirements.txt +++ b/gpt/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 openai>=1 diff --git a/nba/requirements.txt b/nba/requirements.txt index 40d7d310..efbfa305 100644 --- a/nba/requirements.txt +++ b/nba/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 pandas>=2.2.0 plotly>=5.18.0 diff --git a/snakegame/requirements.txt b/snakegame/requirements.txt index 9e31ae33..af29bf04 100644 --- a/snakegame/requirements.txt +++ b/snakegame/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 diff --git a/todo/requirements.txt b/todo/requirements.txt index 9e31ae33..af29bf04 100644 --- a/todo/requirements.txt +++ b/todo/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 diff --git a/translator/requirements.txt b/translator/requirements.txt index ae2746c8..60af77fd 100644 --- a/translator/requirements.txt +++ b/translator/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 googletrans-py==4.0.0 diff --git a/twitter/requirements.txt b/twitter/requirements.txt index 9e31ae33..af29bf04 100644 --- a/twitter/requirements.txt +++ b/twitter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a2 +reflex>=0.4.0a3 From c46134dffa889f91228c102d257b346683fb70f6 Mon Sep 17 00:00:00 2001 From: Elijah Ahianyo Date: Fri, 16 Feb 2024 05:56:06 +0000 Subject: [PATCH 42/45] Local auth app to radix namespace (#207) * remove alembic * Fix PR comments * requirements.txt: use pre-release version for CI pass --------- Co-authored-by: Masen Furer --- local_auth/.gitignore | 4 + local_auth/README.md | 91 ++++++++++++++ local_auth/assets/favicon.ico | Bin 0 -> 15086 bytes local_auth/local_auth/__init__.py | 0 local_auth/local_auth/auth_session.py | 18 +++ local_auth/local_auth/base_state.py | 94 ++++++++++++++ local_auth/local_auth/local_auth.py | 48 ++++++++ local_auth/local_auth/login.py | 169 ++++++++++++++++++++++++++ local_auth/local_auth/registration.py | 168 +++++++++++++++++++++++++ local_auth/local_auth/user.py | 43 +++++++ local_auth/requirements.txt | 3 + local_auth/rxconfig.py | 5 + 12 files changed, 643 insertions(+) create mode 100644 local_auth/.gitignore create mode 100644 local_auth/README.md create mode 100644 local_auth/assets/favicon.ico create mode 100644 local_auth/local_auth/__init__.py create mode 100644 local_auth/local_auth/auth_session.py create mode 100644 local_auth/local_auth/base_state.py create mode 100644 local_auth/local_auth/local_auth.py create mode 100644 local_auth/local_auth/login.py create mode 100644 local_auth/local_auth/registration.py create mode 100644 local_auth/local_auth/user.py create mode 100644 local_auth/requirements.txt create mode 100644 local_auth/rxconfig.py diff --git a/local_auth/.gitignore b/local_auth/.gitignore new file mode 100644 index 00000000..eab0d4b0 --- /dev/null +++ b/local_auth/.gitignore @@ -0,0 +1,4 @@ +*.db +*.py[cod] +.web +__pycache__/ \ No newline at end of file diff --git a/local_auth/README.md b/local_auth/README.md new file mode 100644 index 00000000..3cb7dc2e --- /dev/null +++ b/local_auth/README.md @@ -0,0 +1,91 @@ +# Local Authentication Example + +See example app code: [`local_auth.py`](./local_auth/local_auth.py) + +## Models + +This example makes use of two models, [`User`](./local_auth/user.py) and +[`AuthSession`](./local_auth/auth_session.py), which store user login +information and authenticated user sessions respectively. + +User passwords are hashed in the database with +[`passlib`](https://pypi.org/project/passlib/) using +[`bcrypt`](https://pypi.org/project/bcrypt/) algorithm. However, during +registration and login, the unhashed password is sent over the websocket, so +**it is critical to use TLS to protect the websocket connection**. + +## States + +The base [`State`](./local_auth/base_state.py) class stores the `auth_token` as +a `LocalStorage` var, allowing logins to persist across browser tabs and +sessions. + +It also exposes `authenticated_user` as a cached computed var, which +looks up the `auth_token` in the `AuthSession` table and returns a matching +`User` if any exists. The `is_authenticated` cached var is a convenience for +determining whether the `auth_token` is associated with a valid user. + +The public event handler, `do_logout`, may be called from the frontend and will +destroy the `AuthSession` associated with the current `auth_token`. + +The private event handler, `_login` is only callable from the backend, and +establishes an `AuthSession` for the given `user_id`. It assumes that the +validity of the user credential has already been established, which is why it is +a private handler. + +### Registration + +The [`RegistrationState`](./local_auth/registration.py) class handles the +submission of the register form, checking for input validity and ultimately +creating a new user in the database. + +After successful registration, the event handler redirects back to the login +page after a brief delay. + +### Login + +The [`LoginState`](./local_auth/login.py) class handles the submission of the +login form, checking the user password, and ultimately redirecting back to the +last page that requested login (or the index page). + +The `LoginState.redir` event handler is a bit special because it behaves +differently depending on the page it is called from. + + * If `redir` is called from any page except `/login` and there is no + authenticated user, it saves the current page route as `redirect_to` and + forces a redirect to `/login`. + * If `redir` is called from `/login` and the there is an authenticated + user, it will redirect to the route saved as `redirect_to` (or `/`) + +## Forms and Flow + +### `@require_login` + +The `login.require_login` decorator is intended to be used on pages that require +authentication to be viewed. It uses `rx.cond` to conditionally render either +the wrapped page, or some loading spinners as placeholders. Because one of the +spinners specifies `LoginState.redir` as the event handler for its `on_mount` +trigger, it will handle redirection to the login page if needed. + +### Login Form + +The login form triggers `LoginState.on_submit` when submitted, and this function +is responsible for looking up the user and validating the password against the +database. Once the user is authenticated, `State._login` is called to create the +`AuthSession` associating the `user_id` with the `auth_token` stored in the +browser's `LocalStorage` area. + +Finally `on_submit` chains back into `LoginState.redir` to handle redirection +back to the page that requested the login (stored as `LoginState.redirect_to`). + +### Protect the State + +Keep in mind that **all pages in a reflex app are publicly accessible**! The +`redir` mechanism is designed to get users to and from the login page, it is NOT +designed to protect private data. + +All private data needs to originate from computed vars or event handlers setting +vars after explicitly checking `State.authenticated_user` on the backend. +Static data passed to components, even on protected pages, can be retrieved +without logging in. It cannot be stressed enough that **private data MUST come +from the state**. diff --git a/local_auth/assets/favicon.ico b/local_auth/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..609f6abcbeb0fec5157b54a36d7b2aeb759f9e1b GIT binary patch literal 15086 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 User: + """The currently authenticated user, or a dummy user if not authenticated. + + Returns: + A User instance with id=-1 if not authenticated, or the User instance + corresponding to the currently authenticated user. + """ + with rx.session() as session: + result = session.exec( + select(User, AuthSession).where( + AuthSession.session_id == self.auth_token, + AuthSession.expiration + >= datetime.datetime.now(datetime.timezone.utc), + User.id == AuthSession.user_id, + ), + ).first() + if result: + user, session = result + return user + return User(id=-1) # type: ignore + + @rx.cached_var + def is_authenticated(self) -> bool: + """Whether the current user is authenticated. + + Returns: + True if the authenticated user has a positive user ID, False otherwise. + """ + return self.authenticated_user.id >= 0 + + def do_logout(self) -> None: + """Destroy AuthSessions associated with the auth_token.""" + with rx.session() as session: + for auth_session in session.exec( + select(AuthSession).where(AuthSession.session_id == self.auth_token) + ).all(): + session.delete(auth_session) + session.commit() + self.auth_token = self.auth_token + + def _login( + self, + user_id: int, + expiration_delta: datetime.timedelta = DEFAULT_AUTH_SESSION_EXPIRATION_DELTA, + ) -> None: + """Create an AuthSession for the given user_id. + + If the auth_token is already associated with an AuthSession, it will be + logged out first. + + Args: + user_id: The user ID to associate with the AuthSession. + expiration_delta: The amount of time before the AuthSession expires. + """ + if self.is_authenticated: + self.do_logout() + if user_id < 0: + return + self.auth_token = self.auth_token or self.router.session.client_token + with rx.session() as session: + session.add( + AuthSession( # type: ignore + user_id=user_id, + session_id=self.auth_token, + expiration=datetime.datetime.now(datetime.timezone.utc) + + expiration_delta, + ) + ) + session.commit() diff --git a/local_auth/local_auth/local_auth.py b/local_auth/local_auth/local_auth.py new file mode 100644 index 00000000..db8ce362 --- /dev/null +++ b/local_auth/local_auth/local_auth.py @@ -0,0 +1,48 @@ +"""Main app module to demo local authentication.""" +import reflex as rx + +from .base_state import State +from .login import require_login +from .registration import registration_page as registration_page + + +def index() -> rx.Component: + """Render the index page. + + Returns: + A reflex component. + """ + return rx.fragment( + rx.color_mode.button(rx.color_mode.icon(), float="right"), + rx.vstack( + rx.heading("Welcome to my homepage!", font_size="2em"), + rx.link("Protected Page", href="/protected"), + spacing="2", + padding_top="10%", + align_items="center" + ), + ) + + +@require_login +def protected() -> rx.Component: + """Render a protected page. + + The `require_login` decorator will redirect to the login page if the user is + not authenticated. + + Returns: + A reflex component. + """ + return rx.vstack( + rx.heading( + "Protected Page for ", State.authenticated_user.username, font_size="2em" + ), + rx.link("Home", href="/"), + rx.link("Logout", href="/", on_click=State.do_logout), + ) + + +app = rx.App(theme=rx.theme(has_background=True, accent_color="orange")) +app.add_page(index) +app.add_page(protected) \ No newline at end of file diff --git a/local_auth/local_auth/login.py b/local_auth/local_auth/login.py new file mode 100644 index 00000000..9e87ea11 --- /dev/null +++ b/local_auth/local_auth/login.py @@ -0,0 +1,169 @@ +"""Login page and authentication logic.""" +import reflex as rx +from sqlmodel import select + +from .base_state import State +from .user import User + + +LOGIN_ROUTE = "/login" +REGISTER_ROUTE = "/register" + + +class LoginState(State): + """Handle login form submission and redirect to proper routes after authentication.""" + + error_message: str = "" + redirect_to: str = "" + + def on_submit(self, form_data) -> rx.event.EventSpec: + """Handle login form on_submit. + + Args: + form_data: A dict of form fields and values. + """ + self.error_message = "" + username = form_data["username"] + password = form_data["password"] + with rx.session() as session: + user = session.exec( + select(User).where(User.username == username) + ).one_or_none() + if user is not None and not user.enabled: + self.error_message = "This account is disabled." + return rx.set_value("password", "") + if user is None or not user.verify(password): + self.error_message = "There was a problem logging in, please try again." + return rx.set_value("password", "") + if ( + user is not None + and user.id is not None + and user.enabled + and user.verify(password) + ): + # mark the user as logged in + self._login(user.id) + self.error_message = "" + return LoginState.redir() # type: ignore + + def redir(self) -> rx.event.EventSpec | None: + """Redirect to the redirect_to route if logged in, or to the login page if not.""" + if not self.is_hydrated: + # wait until after hydration to ensure auth_token is known + return LoginState.redir() # type: ignore + page = self.router.page.path + if not self.is_authenticated and page != LOGIN_ROUTE: + self.redirect_to = page + return rx.redirect(LOGIN_ROUTE) + elif page == LOGIN_ROUTE: + return rx.redirect(self.redirect_to or "/") + + +@rx.page(route=LOGIN_ROUTE) +def login_page() -> rx.Component: + """Render the login page. + + Returns: + A reflex component. + """ + + login_form = rx.box( + rx.vstack( + rx.form( + rx.fragment( + rx.heading( + "Login into your Account", size="7", margin_bottom="2rem" + ), + rx.text( + "Username", + color="hsl(240, 5%, 64.9%)", + margin_top="2px", + margin_bottom="4px", + ), + rx.input( + placeholder="username", + id="username", + border_color="hsl(240,3.7%,15.9%)", + justify_content="center", + ), + rx.text( + "Password", + color="hsl(240, 5%, 64.9%)", + margin_top="2px", + margin_bottom="4px", + ), + rx.input( + placeholder="password", + id="password", + border_color="hsl(240,3.7%,15.9%)", + justify_content="center", + type="password", + ), + rx.box( + rx.button( + "Sign in", + type="submit", + width="100%", + ), + padding_top="14px", + ), + ), + on_submit=LoginState.on_submit, + ), + rx.link("Register", href=REGISTER_ROUTE), + align_items="center" + ), + padding="8rem 10rem", + margin_top="10vh", + margin_x="auto", + border="2px solid black", + border_color="gray.300", + border_radius=10, + ) + + return rx.fragment( + rx.cond( + LoginState.is_hydrated, # type: ignore + rx.vstack( + rx.cond( # conditionally show error messages + LoginState.error_message != "", + rx.callout( + LoginState.error_message, + icon="alert_triangle", + color_scheme="red", + role="alert", + ), + ), + login_form, + padding_top="10vh", + ), + ) + ) + + +def require_login(page: rx.app.ComponentCallable) -> rx.app.ComponentCallable: + """Decorator to require authentication before rendering a page. + + If the user is not authenticated, then redirect to the login page. + + Args: + page: The page to wrap. + + Returns: + The wrapped page component. + """ + + def protected_page(): + return rx.fragment( + rx.cond( + State.is_hydrated & State.is_authenticated, # type: ignore + page(), + rx.center( + # When this spinner mounts, it will redirect to the login page + rx.chakra.spinner(on_mount=LoginState.redir), + ), + ) + ) + + protected_page.__name__ = page.__name__ + return protected_page \ No newline at end of file diff --git a/local_auth/local_auth/registration.py b/local_auth/local_auth/registration.py new file mode 100644 index 00000000..9b94aa52 --- /dev/null +++ b/local_auth/local_auth/registration.py @@ -0,0 +1,168 @@ +"""New user registration form and validation logic.""" +from __future__ import annotations + +import asyncio +from collections.abc import AsyncGenerator + +import reflex as rx + +from sqlmodel import select + +from .base_state import State +from .login import LOGIN_ROUTE, REGISTER_ROUTE +from .user import User + + +class RegistrationState(State): + """Handle registration form submission and redirect to login page after registration.""" + + success: bool = False + error_message: str = "" + + async def handle_registration( + self, form_data + ) -> AsyncGenerator[rx.event.EventSpec | list[rx.event.EventSpec] | None, None]: + """Handle registration form on_submit. + + Set error_message appropriately based on validation results. + + Args: + form_data: A dict of form fields and values. + """ + with rx.session() as session: + username = form_data["username"] + if not username: + self.error_message = "Username cannot be empty" + yield rx.set_focus("username") + return + existing_user = session.exec( + select(User).where(User.username == username) + ).one_or_none() + if existing_user is not None: + self.error_message = ( + f"Username {username} is already registered. Try a different name" + ) + yield [rx.set_value("username", ""), rx.set_focus("username")] + return + password = form_data["password"] + if not password: + self.error_message = "Password cannot be empty" + yield rx.set_focus("password") + return + if password != form_data["confirm_password"]: + self.error_message = "Passwords do not match" + yield [ + rx.set_value("confirm_password", ""), + rx.set_focus("confirm_password"), + ] + return + # Create the new user and add it to the database. + new_user = User() # type: ignore + new_user.username = username + new_user.password_hash = User.hash_password(password) + new_user.enabled = True + session.add(new_user) + session.commit() + # Set success and redirect to login page after a brief delay. + self.error_message = "" + self.success = True + yield + await asyncio.sleep(0.5) + yield [rx.redirect(LOGIN_ROUTE), RegistrationState.set_success(False)] + + +@rx.page(route=REGISTER_ROUTE) +def registration_page() -> rx.Component: + """Render the registration page. + + Returns: + A reflex component. + """ + + register_form = rx.box( + rx.vstack( + rx.form( + rx.fragment( + rx.heading("Create an account", size="7", margin_bottom="2rem"), + rx.text( + "Username", + color="hsl(240, 5%, 64.9%)", + margin_top="2px", + margin_bottom="4px", + ), + rx.input( + placeholder="username", + id="username", + border_color="hsl(240,3.7%,15.9%)", + justify_content="center", + ), + rx.text( + "Password", + color="hsl(240, 5%, 64.9%)", + margin_top="2px", + margin_bottom="4px", + ), + rx.input( + placeholder="password", + id="password", + border_color="hsl(240,3.7%,15.9%)", + justify_content="center", + type="password", + ), + rx.text( + "Confirm Password", + color="hsl(240, 5%, 64.9%)", + margin_top="2px", + margin_bottom="4px", + ), + rx.input( + placeholder="confirm", + id="confirm_password", + border_color="hsl(240,3.7%,15.9%)", + justify_content="center", + type="password", + ), + rx.box( + rx.button( + "Sign up", + type="submit", + width="100%", + ), + padding_top="14px", + ), + ), + on_submit=RegistrationState.handle_registration, + ), + rx.link("Login", href=LOGIN_ROUTE), + align_items="center" + ), + padding="8rem 10rem", + margin_top="10vh", + margin_x="auto", + border="2px solid black", + border_color="gray.300", + border_radius=10, + ) + + return rx.fragment( + rx.cond( + RegistrationState.success, + rx.vstack( + rx.text("Registration successful!"), + rx.chakra.spinner(), + ), + rx.vstack( + rx.cond( # conditionally show error messages + RegistrationState.error_message != "", + rx.callout( + RegistrationState.error_message, + icon="alert_triangle", + color_scheme="red", + role="alert", + ), + ), + register_form, + padding_top="10vh", + ), + ) + ) \ No newline at end of file diff --git a/local_auth/local_auth/user.py b/local_auth/local_auth/user.py new file mode 100644 index 00000000..bc58fe4a --- /dev/null +++ b/local_auth/local_auth/user.py @@ -0,0 +1,43 @@ +from passlib.context import CryptContext +from sqlmodel import Field + +import reflex as rx + +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + + +class User( + rx.Model, + table=True, # type: ignore +): + """A local User model with bcrypt password hashing.""" + + username: str = Field(unique=True, nullable=False, index=True) + password_hash: str = Field(nullable=False) + enabled: bool = False + + @staticmethod + def hash_password(secret: str) -> str: + """Hash the secret using bcrypt. + + Args: + secret: The password to hash. + + Returns: + The hashed password. + """ + return pwd_context.hash(secret) + + def verify(self, secret: str) -> bool: + """Validate the user's password. + + Args: + secret: The password to check. + + Returns: + True if the hashed secret matches this user's password_hash. + """ + return pwd_context.verify( + secret, + self.password_hash, + ) diff --git a/local_auth/requirements.txt b/local_auth/requirements.txt new file mode 100644 index 00000000..3b94c4c9 --- /dev/null +++ b/local_auth/requirements.txt @@ -0,0 +1,3 @@ +reflex>=0.4.0a4 +passlib +bcrypt diff --git a/local_auth/rxconfig.py b/local_auth/rxconfig.py new file mode 100644 index 00000000..20b40337 --- /dev/null +++ b/local_auth/rxconfig.py @@ -0,0 +1,5 @@ +import reflex as rx + +config = rx.Config( + app_name="local_auth", +) \ No newline at end of file From 49ed041630a7f0e76b3e42d29fd81dc668c7148e Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Thu, 15 Feb 2024 21:58:56 -0800 Subject: [PATCH 43/45] CI: bump workflows to 0.4.0a4 --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index b7ba6d32..708e1832 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,7 +1,7 @@ name: app-harness env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a3' + REFLEX_VERSION: '==0.4.0a4' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index 680e97f0..b00b1bde 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,7 +1,7 @@ name: check-export env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a3' + REFLEX_VERSION: '==0.4.0a4' TELEMETRY_ENABLED: false on: push: From 4b9162d8f8549274d5e78791bd90ab9d0583f10b Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Fri, 16 Feb 2024 12:10:29 -0800 Subject: [PATCH 44/45] Use REFLEX_DEP instead of REFLEX_VERSION (#209) Allow specification of reflex as a full pip URL so CI can test with unreleased versions of reflex. --- .github/workflows/app_harness.yml | 8 ++++---- .github/workflows/check_export.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index 708e1832..d7da2c47 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,7 +1,7 @@ name: app-harness env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a4' + REFLEX_DEP: 'reflex==0.4.0a4' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: @@ -11,8 +11,8 @@ on: branches: [main] workflow_dispatch: inputs: - reflex_version: - description: 'Reflex version' + reflex_dep: + description: 'Reflex dep (raw pip spec)' jobs: list-examples-with-tests: @@ -51,6 +51,6 @@ jobs: python -m venv venv source venv/bin/activate - pip install 'reflex${{ github.event.inputs.reflex_version || env.REFLEX_VERSION }}' -r requirements.txt -r requirements-dev.txt + pip install '${{ github.event.inputs.reflex_dep || env.REFLEX_DEP }}' -r requirements.txt -r requirements-dev.txt reflex init pytest tests -vv diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index b00b1bde..6a76c88e 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,7 +1,7 @@ name: check-export env: # TODO: switch to the official release - REFLEX_VERSION: '==0.4.0a4' + REFLEX_DEP: 'reflex==0.4.0a4' TELEMETRY_ENABLED: false on: push: @@ -10,8 +10,8 @@ on: branches: [main] workflow_dispatch: inputs: - reflex_version: - description: 'Reflex version' + reflex_dep: + description: 'Reflex dep (raw pip spec)' jobs: list-examples: @@ -60,7 +60,7 @@ jobs: python -m venv venv source venv/bin/activate - pip install 'reflex${{ github.event.inputs.reflex_version || env.REFLEX_VERSION }}' -r requirements.txt + pip install '${{ github.event.inputs.reflex_dep || env.REFLEX_DEP }}' -r requirements.txt export OPENAI_API_KEY="dummy" reflex init reflex export From 377bc38abe7eaed72e4045e4721cc5bbe078e4da Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Fri, 16 Feb 2024 16:21:11 -0800 Subject: [PATCH 45/45] Update to released version 0.4.0 --- .github/workflows/app_harness.yml | 2 +- .github/workflows/check_export.yml | 2 +- basic_crud/requirements.txt | 2 +- chakra_apps/crm/requirements.txt | 2 +- clock/requirements.txt | 2 +- counter/requirements.txt | 2 +- dalle/requirements.txt | 2 +- github-stats/requirements.txt | 2 +- gpt/requirements.txt | 2 +- local_auth/requirements.txt | 2 +- nba/requirements.txt | 2 +- quiz/requirements.txt | 2 +- snakegame/requirements.txt | 2 +- todo/requirements.txt | 2 +- translator/requirements.txt | 2 +- twitter/requirements.txt | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/app_harness.yml b/.github/workflows/app_harness.yml index d7da2c47..50c10194 100644 --- a/.github/workflows/app_harness.yml +++ b/.github/workflows/app_harness.yml @@ -1,7 +1,7 @@ name: app-harness env: # TODO: switch to the official release - REFLEX_DEP: 'reflex==0.4.0a4' + REFLEX_DEP: 'reflex==0.4.0' TELEMETRY_ENABLED: false APP_HARNESS_HEADLESS: 1 on: diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index 6a76c88e..d6ad1ad8 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -1,7 +1,7 @@ name: check-export env: # TODO: switch to the official release - REFLEX_DEP: 'reflex==0.4.0a4' + REFLEX_DEP: 'reflex==0.4.0' TELEMETRY_ENABLED: false on: push: diff --git a/basic_crud/requirements.txt b/basic_crud/requirements.txt index af29bf04..d4deee8a 100644 --- a/basic_crud/requirements.txt +++ b/basic_crud/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 diff --git a/chakra_apps/crm/requirements.txt b/chakra_apps/crm/requirements.txt index 889adc5b..02a76621 100644 --- a/chakra_apps/crm/requirements.txt +++ b/chakra_apps/crm/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 \ No newline at end of file +reflex>=0.4.0 \ No newline at end of file diff --git a/clock/requirements.txt b/clock/requirements.txt index f9d97c91..6616cd0c 100644 --- a/clock/requirements.txt +++ b/clock/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 pytz==2022.7.1 diff --git a/counter/requirements.txt b/counter/requirements.txt index af29bf04..d4deee8a 100644 --- a/counter/requirements.txt +++ b/counter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 diff --git a/dalle/requirements.txt b/dalle/requirements.txt index efd7265a..64bf0145 100644 --- a/dalle/requirements.txt +++ b/dalle/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 openai>=1 diff --git a/github-stats/requirements.txt b/github-stats/requirements.txt index af29bf04..d4deee8a 100644 --- a/github-stats/requirements.txt +++ b/github-stats/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 diff --git a/gpt/requirements.txt b/gpt/requirements.txt index efd7265a..64bf0145 100644 --- a/gpt/requirements.txt +++ b/gpt/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 openai>=1 diff --git a/local_auth/requirements.txt b/local_auth/requirements.txt index 3b94c4c9..b85bea82 100644 --- a/local_auth/requirements.txt +++ b/local_auth/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.4.0a4 +reflex>=0.4.0 passlib bcrypt diff --git a/nba/requirements.txt b/nba/requirements.txt index efbfa305..9166e192 100644 --- a/nba/requirements.txt +++ b/nba/requirements.txt @@ -1,3 +1,3 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 pandas>=2.2.0 plotly>=5.18.0 diff --git a/quiz/requirements.txt b/quiz/requirements.txt index 98df420a..d4deee8a 100644 --- a/quiz/requirements.txt +++ b/quiz/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a1 +reflex>=0.4.0 diff --git a/snakegame/requirements.txt b/snakegame/requirements.txt index af29bf04..d4deee8a 100644 --- a/snakegame/requirements.txt +++ b/snakegame/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 diff --git a/todo/requirements.txt b/todo/requirements.txt index af29bf04..02a76621 100644 --- a/todo/requirements.txt +++ b/todo/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 \ No newline at end of file diff --git a/translator/requirements.txt b/translator/requirements.txt index 60af77fd..6a55c557 100644 --- a/translator/requirements.txt +++ b/translator/requirements.txt @@ -1,2 +1,2 @@ -reflex>=0.4.0a3 +reflex>=0.4.0 googletrans-py==4.0.0 diff --git a/twitter/requirements.txt b/twitter/requirements.txt index af29bf04..d4deee8a 100644 --- a/twitter/requirements.txt +++ b/twitter/requirements.txt @@ -1 +1 @@ -reflex>=0.4.0a3 +reflex>=0.4.0