streamlit-bridge
streamlit-bridge copied to clipboard
Không hoạt động trong streamlit multipages
Khi mình dùng st.html thì html_content vẫn hiện bình thường, nhưng khi dùng html từ st_bridge thì nó lại không hiện Code multipages:
- users.py:
from datetime import datetime
from urllib.parse import urljoin
import streamlit as st
import requests
from src.config import api_url, api_path, config
from src.credentials import cookies
from src.crypt import decrypt
from st_bridge import bridge, html
# Nếu đã login thì hiện nội dung
st.title("Users Management")
headers = {
"Authorization": f"Bearer {decrypt(cookies.get('token'))}"
}
@st.dialog("Thông tin người dùng")
def usrn(data):
st.write(data)
def add_user(data):
res=requests.post(f"{urljoin(api_url, api_path+config.get('api').get('users'))}", json=data, headers=headers)
if res.status_code == 200:
st.success("User added successfully")
return True
else:
st.error("Error adding user")
res.raise_for_status() # Raise exception for bad status codes
@st.dialog("Add User")
def add_user_form():
with st.form("add_user"):
chatid=st.text_input("Chat ID")
user=st.text_input("Username")
balance=st.text_input("Balance")
status=st.checkbox("Status")
st.form_submit_button("Add User", on_click=add_user, args=[{"chatId": chatid, "username": user, "balance": balance, "status": 0 if not status else 1}])
try:
res = requests.get(
f"{urljoin(api_url, api_path+config.get('api').get('users'))}",
headers=headers
)
res.raise_for_status() # Raise exception for bad status codes
# Tạo HTML component
html_content = """
<style>
.container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.user-list {
max-width: 800px;
margin: 0 auto;
}
.user-item {
display: flex;
align-items: center;
padding: 15px;
margin: 8px 0;
border: 1px solid #ddd;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
background-color: white;
}
.user-item:hover {
background-color: #f8f9fa;
transform: translateX(5px);
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.avatar {
width: 45px;
height: 45px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 15px;
background-color: #0066cc;
}
.user-info {
flex-grow: 1;
}
.status-badge {
padding: 4px 8px;
border-radius: 12px;
color: white;
font-size: 0.8em;
margin-left: 10px;
}
.meta-info {
color: #666;
font-size: 0.9em;
margin-top: 4px;
}
.active {
background-color: #28a745;
}
.inactive {
background-color: #dc3545;
}
</style>
<div class="container">
<div class="user-list">
"""
# Thêm user items vào HTML
for user in res.json().get("content"):
status_class = "active" if user['status'] == 1 else "inactive"
status_text = "Active" if user['status'] == 1 else "Inactive"
html_content += f"""
<div class="user-item" onclick="stBridges.send('click-id', {user['chatId']})">
<div class="avatar">
{user['username'][0].upper()}
</div>
<div class="user-info">
<div style="font-weight: bold">
{user['username']}
<span class="status-badge {status_class}">
{status_text}
</span>
</div>
<div class="meta-info">
ID: {user['chatId']} | Create at: {datetime.fromisoformat(user['createdAt'].replace('Z', '+00:00')).strftime("%d-%m-%Y %H:%M:%S")}
</div>
</div>
</div>
"""
# Thêm JavaScript để xử lý click event
html_content += """
</div>
</div>
"""
html(html_content)
cid=bridge('click-id', "")
if cid != "":
usrn(cid)
st.button("Add User", on_click=add_user)
except Exception as e:
st.error(f"Error fetching users: {str(e)}")
- main.py
import streamlit as st
from src.credentials import logout, check_logged_in, login_form
if check_logged_in():
st.navigation([
st.Page("src/users.py"),
st.Page("src/groups.py"),
st.Page("src/keys.py"),
], position="hidden").run()
with st.sidebar:
st.page_link("src/users.py", label="Users")
st.page_link("src/groups.py", label="Groups")
st.page_link("src/keys.py", label="Keys")
if st.button("Logout"):
logout()
st.rerun()
elif login_form(): # Nếu login thành công
st.rerun()
khi mình thử test.py với dữ liệu mẫu thì nó vẫn chạy bình thường
- test.py
import streamlit as st
from datetime import datetime
from st_bridge import html, bridge
# Data mẫu
data = {
"content": [
{
"chatId": 1813442391,
"username": "afewsfga",
"createdAt": "2025-02-07T10:29:09.486299",
"balance": 0,
"status": 1
},
{
"chatId": 1,
"username": "test",
"createdAt": "2025-02-10T04:54:20.696043",
"balance": 0,
"status": 1
}
],
"totalElements": 2,
"number": 0,
"totalPages": 1,
"numberOfElements": 2
}
def format_datetime(dt_str):
dt = datetime.fromisoformat(dt_str.replace('Z', '+00:00'))
return dt.strftime("%d-%m-%Y %H:%M:%S")
# Khởi tạo session state
if 'selected_user' not in st.session_state:
st.session_state.selected_user = None
# Tạo HTML component
html_content = """
<style>
.container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.user-list {
max-width: 800px;
margin: 0 auto;
}
.user-item {
display: flex;
align-items: center;
padding: 15px;
margin: 8px 0;
border: 1px solid #ddd;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
background-color: white;
}
.user-item:hover {
background-color: #f8f9fa;
transform: translateX(5px);
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.avatar {
width: 45px;
height: 45px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 15px;
background-color: #0066cc;
}
.user-info {
flex-grow: 1;
}
.status-badge {
padding: 4px 8px;
border-radius: 12px;
color: white;
font-size: 0.8em;
margin-left: 10px;
}
.meta-info {
color: #666;
font-size: 0.9em;
margin-top: 4px;
}
.active {
background-color: #28a745;
}
.inactive {
background-color: #dc3545;
}
</style>
<div class="container">
<div class="user-list">
"""
# Thêm user items vào HTML
for user in data['content']:
status_class = "active" if user['status'] == 1 else "inactive"
status_text = "Active" if user['status'] == 1 else "Inactive"
html_content += f"""
<div class="user-item" onclick="stBridges.send('click-id', {user['chatId']})">
<div class="avatar">
{user['username'][0].upper()}
</div>
<div class="user-info">
<div style="font-weight: bold">
{user['username']}
<span class="status-badge {status_class}">
{status_text}
</span>
</div>
<div class="meta-info">
ID: {user['chatId']} | Create at: {format_datetime(user['createdAt'])}
</div>
</div>
</div>
"""
# Thêm JavaScript để xử lý click event
html_content += """
</div>
</div>
"""
@st.dialog("Thông tin người dùng")
def usrn():
st.write(f"Username: {data["content"][cid]["username"]}")
cid = bridge('click-id', "")
if cid != "":
usrn()
# Render HTML component
html(html_content)
Hi there, thanks for reporting and sharing the code. However, I’m facing some issues in reproducing it since it’s missing certain files, such as credentials and config. Could you kindly create some dummy code for these files? That would help me a lot in resolving this problem. Thanks.