I’m trying to integrate some js code to enable user interaction with my videos so they would play on hover in my app. However, none of my js, even a test one seem to not come through and I keep getting messages like this “Uncaught SyntaxError: Unexpected token ‘<’ (at hover_video.js?m=1726775435.0881474:1:1)”.
I have checked the server access to the js file:
http://localhost:8050/assets/hover_video.js
and it loads proper contents of my assets/hover_video.js
document.addEventListener('DOMContentLoaded', function() {
const videos = document.querySelectorAll('.hover-video');
videos.forEach(video => {
video.addEventListener('mouseenter', function() {
video.play();
});
video.addEventListener('mouseleave', function() {
video.pause();
video.currentTime = 0; // Reset to the beginning when mouse leaves
});
});
});
my app.py
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Access the REACT_VERSION variable
react_version = os.getenv('REACT_VERSION', '18.2.0') # Default to '18.2.0' if not set
import dash
from flask_socketio import SocketIO
from app_factory import create_app
# Create Flask app
flask_app = create_app()
# Set React version for Dash
dash._dash_renderer._set_react_version(react_version)
# Stylesheets for Dash Mantine Components
stylesheets = [
"https://unpkg.com/@mantine/dates@7/styles.css",
"https://unpkg.com/@mantine/code-highlight@7/styles.css",
"https://unpkg.com/@mantine/charts@7/styles.css",
"https://unpkg.com/@mantine/carousel@7/styles.css",
"https://unpkg.com/@mantine/notifications@7/styles.css",
"https://unpkg.com/@mantine/nprogress@7/styles.css",
]
# Initialize the Dash app
app = dash.Dash(
__name__,
server=flask_app,
suppress_callback_exceptions=True,
external_stylesheets=stylesheets,
assets_folder='assets', # Correct assets folder
assets_url_path='/assets/' # Correct URL path for assets
)
# Set secret key for session management in Flask
flask_app.secret_key = os.getenv('FLASK_SECRET_KEY')
# Initialize SocketIO
socketio = SocketIO(flask_app)
and my index.py
# index.py
import dash_mantine_components as dmc
import dash
from dash import ClientsideFunction
from apps.layouts.landing_page import loading_layout
import os
# Importing callbacks
from CallBacks.ServingLotties import serve_lotties
from CallBacks.handling_user.UserRegistration import register_user_callbacks
from CallBacks.handling_user.UserLogin import login_user_callbacks
# Importing Services
from Services.routes.auth_routes import init_auth_routes
from app import app, flask_app
from flask import session
# Server Side callbacks
serve_lotties(flask_app)
init_auth_routes(flask_app)
react_version = os.getenv('REACT_VERSION', '18.2.0') # Default to '18.2.0' if not set
def is_user_authenticated():
# Retrieve user info and role from session
user = session.get('user')
if user is not None:
return user.get('role'), user.get('first_name'), user.get('last_name') # Return role and first name for personalized experience
return None, None, None # Not authenticated or unknown role
def serve_layout():
# role, first_name, last_name = is_user_authenticated()
# if role: # If the user is authenticated
# return authenticated_layout(role, first_name, last_name)
# else:
return loading_layout # Default to the landing page for unauthenticated users
from dash import html, dcc, Output, Input
# Initial layout setup
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content'), # Placeholder for page content
])
# Callback to render the correct layout based on URL
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def display_page(pathname):
# role, first_name, last_name = is_user_authenticated()
# if role: # If the user is authenticated
# return authenticated_layout()
# else:
return loading_layout # Default to the landing page for unauthenticated users
### CallBacks
register_user_callbacks(app)
login_user_callbacks(app)
if __name__ == "__main__":
app.run_server(debug=True)
app_factory.py
import os
from flask import Flask
from dotenv import load_dotenv
from Services.postgres.db_config import db
from flask_login import LoginManager
# Load environment variables
load_dotenv()
def create_app():
app = Flask(__name__, static_folder='assets')
# Load configuration from environment variables
app.config['SQLALCHEMY_DATABASE_URI'] = (
f"postgresql://{os.getenv('DATABASE_USER')}:{os.getenv('DATABASE_PASSWORD')}@"
f"{os.getenv('DATABASE_HOST')}:{os.getenv('DATABASE_PORT')}/{os.getenv('DATABASE_NAME')}"
)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY')
# Initialize the database with the app
db.init_app(app)
# Initialize the LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'auth.login'
login_manager.login_message = "Please log in to access this page."
# Serve static files from the assets folder
@app.route('/assets/<path:filename>')
def custom_static(filename):
return app.send_static_file(filename)
# Create database tables if they don't exist
with app.app_context():
db.create_all()
return app
and finally the .py that generated the cards with videos
from dash import html
import dash_mantine_components as dmc
# Helper function to generate the interactive element
def create_interactive_element(title, description, video_path):
video_id = title.lower().replace(' ', '-') + "-video"
return dmc.Card(
shadow="sm",
padding="lg",
radius="md",
style={
"borderRadius": "8px",
"textAlign": "center",
"width": "500px",
"height": "320px",
"zIndex": "3",
"marginTop": "20px",
"backgroundColor": "#DEE2EE",
"overflow": "hidden"
},
children=[
dmc.CardSection(
html.Video(
id=video_id,
src=video_path,
className="hover-video",
style={
"width": "100%",
"height": "220px",
"objectFit": "cover",
"borderRadius": "8px 8px 0 0"
},
muted=True,
autoPlay=False
)
),
dmc.Group(
[
dmc.Text(title, fw=500, c="#14232F"),
],
justify="space-between",
mt="md",
mb="xs",
),
dmc.Text(
description,
size="sm",
c="#14232F"
),
]
)
def create_main_banner():
return html.Div(
style={
"position": "relative",
"display": "flex",
"flexDirection": "column",
"alignItems": "center",
"justifyContent": "center",
"textAlign": "center",
"padding": "3rem 1.5rem", # Adjusted padding
"background": "linear-gradient(135deg, #1e3c72 0%, #2a5298 50%, #0f2027 100%)", # Professional gradient
"marginTop": "50px"
},
children=[
# Title and Subtitle
html.Div(
style={"textAlign": "center", "marginBottom": "1.5rem"},
children=[
dmc.Space(h=40),
dmc.Title("Nurture your life, grow your potential.",
style={"color": "white", "fontSize": "2.5rem", "fontWeight": "bold"}),
dmc.Space(h=20),
dmc.Text(
"Thrive in every aspect of your life with tools to guide every choice.",
style={"color": "white", "fontSize": "1.25rem", "lineHeight": "1.75rem", "maxWidth": "700px",
"margin": "0 auto"},
),
]
),
# Tree Image
html.Div(
style={"position": "relative", "width": "100%", "maxWidth": "1800px"},
children=[
html.Img(
src="/assets/final_tree_2.svg",
style={
"width": "100%", # Reduce width
"maxWidth": "1200px", # Reduce max width
"height": "auto",
"opacity": "0.75",
"marginBottom": "1rem", # Reduce margin
}
),
]
),
# Interactive Elements (Cards)
html.Div(
style={
"position": "relative",
"display": "flex",
"justifyContent": "space-around",
"width": "100%", # Increase width to give cards more space
"zIndex": "2", # Ensure the cards are in front of the tree
},
children=[
create_interactive_element(
title="Well-being",
description="balanced life",
video_path="assets/loading_page/fitness_domain.mp4"
),
create_interactive_element(
title=" Finances",
description=" financial future ",
video_path="assets/loading_page/finance_domain_wide.mp4"
),
create_interactive_element(
title="Connections",
description="intentional actions.",
video_path="assets/loading_page/relationship_building.mp4"
)
]
),
# Call to Action Button
dmc.Button(
"Get Started",
size="lg",
variant="filled",
radius="xl",
style={"marginTop": "3rem"}
),
]
)
main_banner = create_main_banner()