ru_characters_explorer / src /ui_components.py
loim's picture
update texts
c7d803a
import streamlit as st
from database import get_hash, upsert_data
@st.cache_resource
def load_css():
"""Загрузка CSS стилей"""
with open("assets/styles.css") as f:
return f.read()
def render_sidebar(localS, locale, all_langs, moods, all_tags):
"""Рендеринг боковой панели с фильтрами"""
with st.sidebar:
st.markdown(
"""
[![🤗 Open in Datasets](https://img.shields.io/badge/🤗-Download_Dataset-blue)](
https://huggingface.co/datasets/loim/ru_fantasy_characters)
"""
)
def on_language_change():
if st.session_state.lang_select != st.session_state.lang:
localS.setItem("lang", st.session_state.lang_select)
st.selectbox(
locale['filter_lang'],
all_langs,
index=all_langs.index(st.session_state.lang),
on_change=on_language_change,
key="lang_select"
)
st.markdown("---")
st.title(locale['filter_title'])
search_query = st.text_input(locale['filter_search'], "")
sort_option = st.selectbox(
locale['filter_sort_title'],
locale['filter_sort']
)
absurdity_range = st.slider(locale['filter_absurd'], 0, 10, (0, 10))
selected_mood = st.selectbox(locale['filter_mood'], moods)
selected_tags = st.multiselect(locale['filter_tags'], all_tags)
return {
"search_query": search_query,
"sort_option": sort_option,
"absurdity_range": absurdity_range,
"selected_mood": selected_mood,
"selected_tags": selected_tags
}
@st.cache_data
def generate_rpg_card(locale, row):
"""Генерация RPG-карточки персонажа"""
return f"""
{locale['rpt_card_world']} {row['world']}
{locale['rpt_card_name']} {row['name']}
{locale['rpt_card_desc']} {row['description']}
{locale['rpt_card_story']} {row['short_story']}
{locale['rpt_card_style']} {row['style']}
{locale['rpt_card_msg']} {row['first_message']}
"""
# Кэшированный рендеринг карточек
@st.cache_data
def render_character_card(locale, row):
with st.container():
st.markdown("---")
st.markdown(f"### {row['name']}")
st.caption(f"*{row['short_story']}*")
col1, col2 = st.columns([1, 3])
with col1:
st.markdown(f"**{locale['char_world']}** {row['world']}")
st.markdown(f"**{locale['char_mood']}** `{row['mood']}`")
st.markdown(f"**{locale['char_absurd']}** `{row['absurdity']}/10`")
st.markdown(f"**{locale['char_tags']}** `{' '.join(row['tags'].split())}`")
with col2:
st.markdown(f"**{locale['char_desc']}** {row['description']}")
st.markdown(f"**{locale['char_style']}** *{row['style']}*")
with st.expander(locale['char_rpg_card'], expanded=False):
rpg_card = generate_rpg_card(locale, row)
st.code(rpg_card, language="markdown")
def render_character_rating(locale, database, localS, row):
current_hash = row['hash']
rating_data, _ = get_hash(database, "rating", current_hash)
rating_data = rating_data[1][0] if rating_data[1] else {"hash": current_hash, "likes": 0, "dislikes": 0}
# Проверяем, оценивали ли уже этот хэш
if current_hash in st.session_state.rated and (rating_data['likes'] != 0 or rating_data['dislikes'] != 0):
# Показываем текущий рейтинг
st.write(locale["rating_text"].format(rating_data['likes'], rating_data['dislikes']))
else:
# Показываем кнопки для оценки
if st.button(locale["rating_like"], key=f"like_{current_hash}"):
rating_data["likes"] += 1
upsert_data(database, "rating", rating_data)
st.session_state.rated.append(current_hash)
localS.setItem("rated", st.session_state.rated)
st.rerun()
if st.button(locale["rating_dislike"], key=f"dislike_{current_hash}"):
rating_data["dislikes"] += 1
upsert_data(database, "rating", rating_data)
st.session_state.rated.append(current_hash)
localS.setItem("rated", st.session_state.rated)
st.rerun()
def feedback_system(locale, database, localS):
if 'feedback_enabled' not in st.session_state:
st.session_state.feedback_enabled = False
if st.session_state.feedback_enabled:
st.header(locale["feedback_header"])
rating = st.slider(locale["feedback_rating"], 1, 5, 3)
comment = st.text_area(locale["feedback_comment_label"], help=locale["feedback_comment_help"])
if st.button(locale["feedback_send_btn"]):
if comment.strip() == "" and rating == 3:
st.warning(locale["feedback_warn"])
else:
upsert_data(database, "feedback", {"text": comment.strip(), "rating": rating})
st.success(locale["feedback_suc"])
else:
if st.button(locale["feedback_quest"]):
st.session_state.feedback_enabled = True
st.rerun()
def render_main_content(locale, database, localS, filtered_df):
feedback_system(locale, database, localS)
"""Рендеринг основного контента с пагинацией"""
st.title("🧙 Characters Explorer")
if len(filtered_df) == 0:
st.warning(locale['main_not_found'])
else:
# Инициализация состояния пагинации
if 'page' not in st.session_state:
st.session_state.page = 0
# Настройки пагинации
per_page = 5 # Персонажей на странице
total_pages = max(1, (len(filtered_df) // per_page) + (1 if len(filtered_df) % per_page else 0))
if st.session_state.page >= total_pages:
st.session_state.page = 0
# Управление пагинацией в колонках
col1, col2, _ = st.columns([2, 3, 5])
with col1:
st.selectbox(
locale['main_counter'],
options=[5, 10, 20],
index=0,
key='per_page',
on_change=lambda: st.session_state.update(page=0)
)
with col2:
st.number_input(
locale['main_page'],
min_value=0,
max_value=total_pages-1,
value=st.session_state.page,
key='page_input',
format="%d",
on_change=lambda: setattr(st.session_state, 'page', st.session_state.page_input)
)
# Рассчет диапазона записей
start_idx = st.session_state.page * st.session_state.per_page
end_idx = min((st.session_state.page + 1) * st.session_state.per_page, len(filtered_df))
# Отображение статистики
st.markdown(locale['main_found'].format(len(filtered_df), st.session_state.page, total_pages-1))
# Рендеринг только видимых карточек
for idx in range(start_idx, end_idx):
row = filtered_df.iloc[idx]
render_character_card(locale, row)
render_character_rating(locale, database, localS, row)
st.markdown("---")
# Кнопки навигации
if total_pages > 1:
cols = st.columns(4)
with cols[0]:
if st.button(locale['pages_first'], disabled=(st.session_state.page == 0)):
st.session_state.page = 0
st.rerun()
with cols[1]:
if st.button(locale['pages_before'], disabled=(st.session_state.page == 0)):
st.session_state.page -= 1
st.rerun()
with cols[2]:
if st.button(locale['pages_next'], disabled=(st.session_state.page >= total_pages-1)):
st.session_state.page += 1
st.rerun()
with cols[3]:
if st.button(locale['pages_last'], disabled=(st.session_state.page == total_pages-1)):
st.session_state.page = total_pages-1
st.rerun()