Spaces:
Sleeping
Sleeping
import streamlit as st | |
import requests | |
from PIL import Image as PILImage | |
from io import BytesIO | |
import re | |
import pandas as pd | |
import os | |
from streamlit_autorefresh import st_autorefresh | |
# Auto-refresh every 30 seconds (30,000 milliseconds) | |
st_autorefresh(interval=30 * 1000, key="auto-refresh") | |
# ------------------ UI and Styling ------------------ | |
# Fullscreen mode and hide Streamlit elements (Menu, Footer) | |
# ------------------ UI and Styling ------------------ | |
# ------------------ UI and Styling ------------------ | |
# ------------------ UI and Styling ------------------ | |
# Fullscreen mode and hide Streamlit elements (Menu, Footer) | |
st.markdown(""" | |
<style> | |
#MainMenu {visibility: hidden;} | |
footer {visibility: hidden;} | |
.reportview-container { background-color: #111111; } | |
.block-container { | |
padding-top: 0px; | |
padding-left: 0px; | |
padding-right: 0px; | |
padding-bottom: 0px; | |
} | |
.css-1v0mbdj {padding-top: 0px;} | |
h1 { | |
font-size: 5em; | |
color: white; | |
text-align: center; | |
margin-top: 50px; | |
} | |
.stImage > div { | |
width: 100%; | |
} | |
/* Ensure full-width image display */ | |
.stImage img { | |
object-fit: contain; | |
width: 100%; | |
} | |
.block-container { | |
padding: 0; | |
} | |
/* Custom grid layout for images */ | |
.grid-container { | |
display: grid; | |
grid-template-columns: repeat(5, 1fr); | |
gap: 20px; | |
padding: 20px; | |
} | |
.grid-item { | |
background-color: #222222; | |
padding: 10px; | |
border-radius: 10px; | |
text-align: center; | |
display: flex; | |
flex-direction: column; | |
justify-content: space-between; | |
height: 550px; /* Fixed height to ensure consistent spacing */ | |
} | |
/* Styling for the container that holds both the name and greeting */ | |
.cloud-container { | |
margin-top: 10px; | |
padding: 20px; | |
background-color: #83c5be; | |
border-radius: 50px; | |
font-size: 1.2em; | |
color: white; | |
text-align: center; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
width: 100%; | |
display: flex; | |
flex-direction: column; /* Stacks name and greeting vertically */ | |
justify-content: center; | |
align-items: center; | |
word-wrap: break-word; /* Ensures text wraps nicely */ | |
} | |
.cloud-container h2 { | |
font-size: 2.5em; | |
font-weight: bold; | |
margin-bottom: 10px; | |
} | |
.separator { | |
border: 0; | |
height: 1px; | |
background: #333; | |
margin: 15px 0; | |
} | |
/* Placeholder image style */ | |
.placeholder-img { | |
background-color: #333; | |
color: #fff; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100%; | |
font-size: 2em; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# ------------------ Image Helpers ------------------ | |
# Convert Google Drive URL to direct link | |
def convert_drive_url(url): | |
match = re.search(r'/d/([a-zA-Z0-9_-]+)|id=([a-zA-Z0-9_-]+)', url) | |
file_id = match.group(1) if match and match.group(1) else match.group(2) if match else None | |
if file_id: | |
return f"https://drive.google.com/uc?export=view&id={file_id}" | |
return None | |
def prepare_image(img, size=(500, 500), bg_color=(17, 17, 17)): | |
# Resize image keeping aspect ratio, then pad to desired size | |
img.thumbnail(size, PILImage.Resampling.LANCZOS) | |
background = PILImage.new('RGB', size, bg_color) | |
offset = ((size[0] - img.width) // 2, (size[1] - img.height) // 2) | |
background.paste(img, offset) | |
return background | |
# Download image from URL | |
def download_image(url): | |
try: | |
response = requests.get(url) | |
response.raise_for_status() | |
return PILImage.open(BytesIO(response.content)).convert("RGB") | |
except Exception as e: | |
st.error(f"Failed to load image from {url}: {e}") | |
return None | |
import streamlit as st | |
import pandas as pd | |
import gspread | |
from oauth2client.service_account import ServiceAccountCredentials | |
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
# Construct full path to app.json | |
CONFIG_PATH = os.path.join(ROOT_DIR, "test_app_1.json") | |
# Google Sheets Setup | |
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"] | |
creds = ServiceAccountCredentials.from_json_keyfile_name("src/test_app_1.json", scope) | |
client = gspread.authorize(creds) | |
#https://docs.google.com/spreadsheets/d/1t96-Y21Nuj4dSy1UM4xJOnG3mlfF0C_vtfKRrptzKQ8/edit?usp=sharing | |
# Access the sheet | |
sheet = client.open_by_key("1t96-Y21Nuj4dSy1UM4xJOnG3mlfF0C_vtfKRrptzKQ8").sheet1 | |
data = sheet.get_all_records() | |
df = pd.DataFrame(data) | |
# ------------------ App Layout ------------------ | |
# App title | |
#st.markdown("<hr><hr/>", unsafe_allow_html=True) | |
# Let user select number of columns (1 to 5) | |
cols_count = 3 | |
# Prepare images and captions | |
rows_data = list(df.tail(3).itertuples(index=False)) # Exclude the index from tuple | |
# Create columns for grid layout | |
cols = st.columns(cols_count) | |
# ------------------ Image Grid ------------------ | |
for idx, row in enumerate(rows_data): | |
col = cols[idx % cols_count] | |
name = row.Name | |
greeting = row.Greetings | |
url = convert_drive_url(row.Picture) | |
img = download_image(url) | |
with col: | |
# Image Display | |
if img: | |
uniform_img = prepare_image(img, size=(500, 500)) | |
st.image(uniform_img, use_container_width=True) | |
else: | |
st.markdown('<div class="placeholder-img">No Image</div>', unsafe_allow_html=True) | |
# Separator Line (between Image and Greeting) | |
st.markdown('<hr class="separator">', unsafe_allow_html=True) | |
# Create the cloud-like container for both Name and Greeting below the image | |
st.markdown(f""" | |
<div class="cloud-container"> | |
<h2>{name}</h2> | |
<p>{greeting}</p> | |
</div> | |
""", unsafe_allow_html=True) | |