pegavisao / gallery.py
Roudrigus's picture
Upload 17 files
3168916 verified
# gallery.py
# -*- coding: utf-8 -*-
import os
from pathlib import Path
import streamlit as st
# ===== Config: suporta pasta 'Config' (maiúscula) e 'config' (minúscula) =====
try:
from Config.settings import PAGE_SIZE_DEFAULT
except Exception:
try:
from config.settings import PAGE_SIZE_DEFAULT
except Exception:
PAGE_SIZE_DEFAULT = 12 # fallback seguro
# ===== Storage da galeria: tenta 'core.gallery_storage' e, se não houver 'core/', usa raiz =====
try:
from core.gallery_storage import (
save_report_image,
gallery_list_images_sorted,
delete_report_image,
)
except Exception:
from gallery_storage import (
save_report_image,
gallery_list_images_sorted,
delete_report_image,
)
def render_reports_gallery_uploader(key_prefix: str) -> None:
"""Uploader de imagens para a galeria (qualquer usuário)."""
st.subheader("📤 Publicar foto do relatório")
st.caption("Envie uma imagem (JPG/PNG/WEBP). Todos os usuários poderão visualizar na galeria.")
uploader_name = ""
uploader_email = ""
if st.session_state.get("aluno_logged_in"):
uploader_name = st.session_state.get("aluno_nome") or ""
uploader_email = st.session_state.get("aluno_email") or ""
elif st.session_state.get("is_admin"):
uploader_name = st.session_state.get("admin_user") or ""
col_name, _ = st.columns([2, 3])
name_input = col_name.text_input(
"Seu nome (opcional)",
value=uploader_name,
max_chars=40,
placeholder="Ex.: Rodrigo",
key=f"{key_prefix}gallery_name_input",
)
up = st.file_uploader(
"Selecione a imagem do relatório",
type=["png", "jpg", "jpeg", "webp"],
accept_multiple_files=False,
help="Dica: até ~5MB carrega mais rápido",
key=f"{key_prefix}gallery_file_uploader",
)
if up:
try:
st.image(up, caption="Pré-visualização", use_container_width=True)
except Exception:
st.info("Pré-visualização indisponível para este arquivo.")
publish_col, _ = st.columns([1, 3])
if publish_col.button(
"📌 Publicar",
type="primary",
use_container_width=True,
disabled=(up is None),
key=f"{key_prefix}gallery_publish_btn",
):
if up is None:
st.warning("Selecione uma imagem antes de publicar.")
return
try:
saved = save_report_image(
uploaded_file=up,
uploader_name=(name_input or None),
uploader_email=(uploader_email or None),
)
if saved:
st.success("Imagem publicada com sucesso!")
st.rerun()
except Exception as e:
st.error(f"Falha ao salvar imagem: {e}")
def render_reports_gallery_grid(page_size: int = PAGE_SIZE_DEFAULT, key_prefix: str = "") -> None:
"""Grade com miniaturas + download; exclusão apenas para Admin (server-side check)."""
st.subheader("🖼️ Galeria de Relatórios")
imgs = gallery_list_images_sorted()
if not imgs:
st.info("Ainda não há imagens publicadas.")
return
import math
total = len(imgs)
pages = max(1, math.ceil(total / page_size))
key_page = f"{key_prefix}gallery_page"
st.session_state.setdefault(key_page, 1)
cur_page = st.session_state[key_page]
if cur_page > pages:
cur_page = pages
st.session_state[key_page] = cur_page
if cur_page < 1:
cur_page = 1
st.session_state[key_page] = cur_page
col_left, col_center, col_right = st.columns([1, 3, 1])
with col_left:
if st.button("⬅️", disabled=(cur_page <= 1), key=f"{key_prefix}gallery_nav_prev"):
st.session_state[key_page] = max(1, cur_page - 1)
st.rerun()
with col_center:
sel = st.selectbox(
"Página",
options=list(range(1, pages + 1)),
index=cur_page - 1,
key=f"{key_prefix}gallery_page_select",
label_visibility="collapsed",
)
if sel != cur_page:
st.session_state[key_page] = sel
st.rerun()
with col_right:
if st.button("➡️", disabled=(cur_page >= pages), key=f"{key_prefix}gallery_nav_next"):
st.session_state[key_page] = min(pages, cur_page + 1)
st.rerun()
st.caption(
f"Mostrando {page_size} por página — {total} imagens no total · "
f"Página {st.session_state.get(key_page, 1)} de {pages}"
)
start = (st.session_state[key_page] - 1) * page_size
end = min(start + page_size, total)
page_items = imgs[start:end]
cols = st.columns(3)
is_admin = bool(st.session_state.get("is_admin"))
for i, (name, mtime, orig_path, thumb_path) in enumerate(page_items):
col = cols[i % 3]
with col:
try:
if Path(thumb_path).exists():
col.image(str(thumb_path), use_container_width=True, caption=name)
else:
col.image(str(orig_path), use_container_width=True, caption=name)
except Exception:
col.warning(f"Não foi possível carregar {name}.")
continue
# Download do original
try:
with open(orig_path, "rb") as f:
mime = "image/jpeg" if name.lower().endswith((".jpg", ".jpeg")) else "image/png"
st.download_button(
label="⬇️ Baixar original",
data=f,
file_name=name,
mime=mime,
use_container_width=True,
key=f"{key_prefix}dl_{name}",
)
except Exception as e:
col.warning(f"Download indisponível: {e}")
# Exclusão — somente Admin (verificação também no servidor)
if is_admin:
if st.button("🗑️ Remover", key=f"{key_prefix}rm_{name}", type="secondary", use_container_width=True):
try:
delete_report_image(filename=name, is_admin=True)
st.success("Imagem removida.")
st.rerun()
except PermissionError as e:
st.error(str(e))
except Exception as e:
st.error(f"Erro ao remover: {e}")
else:
st.caption("Somente Admin pode excluir.")
def aba_galeria_relatorios(context_key: str) -> None:
"""Aba completa: upload + grid (keys isoladas por contexto)."""
with st.container(border=True):
render_reports_gallery_uploader(key_prefix=context_key)
st.divider()
render_reports_gallery_grid(page_size=PAGE_SIZE_DEFAULT, key_prefix=context_key)