diff --git a/app_config.json b/app_config.json index 7493633..b1ded3f 100644 --- a/app_config.json +++ b/app_config.json @@ -1,5 +1,5 @@ { - "hashed_password": "$2b$12$RM9HcqRHwZlXCXwCL2ZIdeMICCOuPXFnikxDbQE96nskZ2zxXlcQ2", + "hashed_password": "$2b$12$xd6TiT9jvURdLrScQPMw8evomDS1DPE70pnk63NORpR21/bu5wOt6", "persistence": { "method": "none", "firestore": { diff --git a/src/streamlit_analytics2/display/dashboard.py b/src/streamlit_analytics2/display/dashboard.py index a8ad612..977e4ca 100644 --- a/src/streamlit_analytics2/display/dashboard.py +++ b/src/streamlit_analytics2/display/dashboard.py @@ -6,11 +6,11 @@ def show_settings(app_config): - st.sidebar.title("Settings") - st.sidebar.write( + st.title("Settings") + st.write( "Here you can configure the settings for streamlit-analytics." ) - st.sidebar.markdown( + st.markdown( """ **Note:** Changes to the settings will be saved to `app_config.json` in the current working directory. @@ -18,15 +18,15 @@ def show_settings(app_config): ) # Show password protection settings. - st.sidebar.header("Password protection") + st.header("Password protection") hashed_password = app_config.get_setting("hashed_password") if hashed_password: - st.sidebar.write("Password is set.") - if st.sidebar.button("Remove password"): + st.write("Password is set.") + if st.button("Remove password"): app_config.update_setting("hashed_password", "") else: - st.sidebar.write("No password set.") - new_password = st.sidebar.text_input("Set new password", type="password") + st.write("No password set.") + new_password = st.text_input("Set new password", type="password") if new_password: app_config.update_setting("hashed_password", hash_password(new_password)) @@ -44,116 +44,104 @@ def show_results(): """ ) - # Ask for password if one was given. - show = True - if unsafe_password is not None: - password_input = st.text_input( - "Enter password to show results", type="password" - ) - if password_input != unsafe_password: - show = False - if len(password_input) > 0: - st.write("Nope, that's not correct ☝️") + # Show traffic. + st.header("Traffic") + st.write(f"since {counts['start_time']}") + col1, col2, col3 = st.columns(3) + col1.metric( + "Pageviews", + counts["total_pageviews"], + help="Every time a user (re-)loads the site.", + ) + col2.metric( + "Script runs", + counts["total_script_runs"], + help="Every time Streamlit reruns upon changes or interactions.", + ) + col3.metric( + "Time spent", + format_seconds(counts["total_time_seconds"]), + help="Time from initial page load to last widget interaction, summed over all users.", + ) + st.write("") - if show: - # Show traffic. - st.header("Traffic") - st.write(f"since {counts['start_time']}") - col1, col2, col3 = st.columns(3) - col1.metric( - "Pageviews", - counts["total_pageviews"], - help="Every time a user (re-)loads the site.", - ) - col2.metric( - "Script runs", - counts["total_script_runs"], - help="Every time Streamlit reruns upon changes or interactions.", + # Plot altair chart with pageviews and script runs. + try: + alt.themes.enable("streamlit") + except: + pass # probably old Streamlit version + df = pd.DataFrame(counts["per_day"]) + base = alt.Chart(df).encode( + x=alt.X("monthdate(days):O", axis=alt.Axis(title="", grid=True)) + ) + line1 = base.mark_line(point=True, stroke="#5276A7").encode( + alt.Y( + "pageviews:Q", + axis=alt.Axis( + titleColor="#5276A7", + tickColor="#5276A7", + labelColor="#5276A7", + format=".0f", + tickMinStep=1, + ), + scale=alt.Scale(domain=(0, df["pageviews"].max() + 1)), ) - col3.metric( - "Time spent", - format_seconds(counts["total_time_seconds"]), - help="Time from initial page load to last widget interaction, summed over all users.", + ) + line2 = base.mark_line(point=True, stroke="#57A44C").encode( + alt.Y( + "script_runs:Q", + axis=alt.Axis( + title="script runs", + titleColor="#57A44C", + tickColor="#57A44C", + labelColor="#57A44C", + format=".0f", + tickMinStep=1, + ), ) - st.write("") + ) + layer = ( + alt.layer(line1, line2) + .resolve_scale(y="independent") + .configure_axis(titleFontSize=15, labelFontSize=12, titlePadding=10) + ) + st.altair_chart(layer, use_container_width=True) - # Plot altair chart with pageviews and script runs. - try: - alt.themes.enable("streamlit") - except: - pass # probably old Streamlit version - df = pd.DataFrame(counts["per_day"]) - base = alt.Chart(df).encode( - x=alt.X("monthdate(days):O", axis=alt.Axis(title="", grid=True)) - ) - line1 = base.mark_line(point=True, stroke="#5276A7").encode( - alt.Y( - "pageviews:Q", - axis=alt.Axis( - titleColor="#5276A7", - tickColor="#5276A7", - labelColor="#5276A7", - format=".0f", - tickMinStep=1, - ), - scale=alt.Scale(domain=(0, df["pageviews"].max() + 1)), - ) - ) - line2 = base.mark_line(point=True, stroke="#57A44C").encode( - alt.Y( - "script_runs:Q", - axis=alt.Axis( - title="script runs", - titleColor="#57A44C", - tickColor="#57A44C", - labelColor="#57A44C", - format=".0f", - tickMinStep=1, - ), - ) - ) - layer = ( - alt.layer(line1, line2) - .resolve_scale(y="independent") - .configure_axis(titleFontSize=15, labelFontSize=12, titlePadding=10) - ) - st.altair_chart(layer, use_container_width=True) + # Show widget interactions. + st.header("Widget interactions") + st.markdown( + """ + Find out how users interacted with your app! +
+ Numbers indicate how often a button was clicked, how often a specific text + input was given, ... +
+ Note: Numbers only increase if the state of the widget + changes, not every time streamlit runs the script. + """, + unsafe_allow_html=True, + ) + st.write(counts["widgets"]) - # Show widget interactions. - st.header("Widget interactions") - st.markdown( + # Show button to reset analytics. + st.header("Danger zone") + with st.expander("Here be dragons 🐲🔥"): + st.write( + """ + Here you can reset all analytics results. + + **This will erase everything tracked so far. You will not be able to + retrieve it. This will also overwrite any results synced to Firestore.** """ - Find out how users interacted with your app! -
- Numbers indicate how often a button was clicked, how often a specific text - input was given, ... -
- Note: Numbers only increase if the state of the widget - changes, not every time streamlit runs the script. - """, - unsafe_allow_html=True, ) - st.write(counts["widgets"]) - - # Show button to reset analytics. - st.header("Danger zone") - with st.expander("Here be dragons 🐲🔥"): - st.write( - """ - Here you can reset all analytics results. - - **This will erase everything tracked so far. You will not be able to - retrieve it. This will also overwrite any results synced to Firestore.** - """ - ) - reset_prompt = st.selectbox( - "Continue?", - [ - "No idea what I'm doing here", - "I'm absolutely sure that I want to reset the results", - ], - ) - if reset_prompt == "I'm absolutely sure that I want to reset the results": - reset_clicked = st.button("Click here to reset") - if reset_clicked: - st.write("Done! Please refresh the page.") + reset_prompt = st.selectbox( + "Continue?", + [ + "No idea what I'm doing here", + "I'm absolutely sure that I want to reset the results", + ], + ) + if reset_prompt == "I'm absolutely sure that I want to reset the results": + reset_clicked = st.button("Click here to reset") + if reset_clicked: + st.write("Done! Please refresh the page.") diff --git a/src/streamlit_analytics2/main.py b/src/streamlit_analytics2/main.py index 5191e93..3127aa5 100644 --- a/src/streamlit_analytics2/main.py +++ b/src/streamlit_analytics2/main.py @@ -7,27 +7,6 @@ app_config = AppConfig() analytics_tracker = AnalyticsTracker() -def main(): - # Check for the analytics=on query parameter before showing sidebar content - query_params = st.query_params - analytics_enabled = "analytics" in query_params and "on" in query_params["analytics"] - - if analytics_enabled: - # analytics_tracker.start_tracking() # Start tracking within context - password_hash = app_config.get_setting('hashed_password') - - if not password_hash: - set_admin_password() - elif not st.session_state.get('authenticated', False): - login_field(password_hash) - reset_password_and_data() - - if st.session_state.get('authenticated', False): - analytics_navigation() - - # analytics_tracker.stop_tracking() # Ensure tracking stops appropriately - else: - st.write("Welcome to the app! Append '?analytics=on' to the URL to access the analytics dashboard.") # Function to render the admin password setup field def set_admin_password(): @@ -65,10 +44,32 @@ def analytics_navigation(): st.sidebar.header('---Streamlit Analytics---') page = st.sidebar.radio('Go to', ['Insights', 'Settings'], key="analytics_nav") if page == 'Insights': - show_results() # Ensure this function is implemented and imported + show_results(analytics_tracker) elif page == 'Settings': - show_settings() # Ensure this function is implemented and imported + show_settings(app_config) +def main(): + # Check for the analytics=on query parameter before showing sidebar content + query_params = st.query_params + analytics_enabled = "analytics" in query_params and "on" in query_params["analytics"] + + if analytics_enabled: + # analytics_tracker.start_tracking() # Start tracking within context + password_hash = app_config.get_setting('hashed_password') + + if not password_hash: + set_admin_password() + elif not st.session_state.get('authenticated', False): + login_field(password_hash) + reset_password_and_data() + + if st.session_state.get('authenticated', False): + analytics_navigation() + + # analytics_tracker.stop_tracking() # Ensure tracking stops appropriately + else: + st.write("Welcome to the app! Append '?analytics=on' to the URL to access the analytics dashboard.") + st.button("Click me") if __name__ == "__main__": main() diff --git a/tree b/tree deleted file mode 100644 index 5954b4e..0000000 --- a/tree +++ /dev/null @@ -1,34 +0,0 @@ -. -├── LICENSE -├── Pipfile -├── Pipfile.lock -├── app_config.json -├── examples -│   ├── minimal.py -│   ├── pages -│   │   ├── all-widgets.py -│   │   └── sharing-demo.py -│   └── requirements.txt -├── pyproject.toml -├── src -│   └── streamlit_analytics2 -│   ├── __init__.py -│   ├── analytics -│   │   ├── __init__.py -│   │   ├── firestore_manager.py -│   │   └── tracker.py -│   ├── config -│   │   ├── __init__.py -│   │   ├── app_config.json -│   │   └── settings.py -│   ├── display -│   │   ├── __init__.py -│   │   └── dashboard.py -│   ├── main.py -│   └── utils -│   ├── __init__.py -│   └── common.py -├── tests -└── tree - -9 directories, 22 files