datapass / components /catalog.py
waroca's picture
Upload folder using huggingface_hub
4e2c730 verified
def create_catalog_html(datasets, username=None):
"""Creates HTML string for the dataset catalog with improved card design."""
if not datasets:
return """
<div class="empty-state">
<div class="empty-state-icon">📦</div>
<div class="empty-state-title">No datasets available</div>
<div class="empty-state-text">Check back soon for new data products.</div>
</div>
"""
cards_html = ""
for i, dataset in enumerate(datasets):
dataset_id = dataset.get('dataset_id', '')
display_name = dataset.get('display_name', dataset_id)
description = dataset.get('description', 'No description available.')
# Determine pricing display
plans = dataset.get("plans", [])
is_free = False
price = "10"
trial_days = 1
if plans:
plan = plans[0]
price_id = plan.get("stripe_price_id", "")
if price_id in ["free", "0", 0]:
is_free = True
trial_days = plan.get("access_duration_days", 1)
else:
price = plan.get("price", "10")
# Price badge
if is_free:
trial_text = "24h" if trial_days == 1 else f"{trial_days}-day"
price_badge = f'<span class="catalog-price-badge free">{trial_text} Free Trial</span>'
else:
price_badge = f'<span class="catalog-price-badge paid">${price}<span class="period">/mo</span></span>'
# Action area - only show hint when not logged in
if not username:
action_html = '''
<div class="catalog-card-action">
<span class="action-hint login-required">Sign in to subscribe</span>
</div>
'''
else:
action_html = ''
cards_html += f"""
<div class="catalog-card" data-dataset-id="{dataset_id}">
<div class="catalog-card-header">
<div class="catalog-card-icon">📊</div>
<div class="catalog-card-title-area">
<h3 class="catalog-card-title">{display_name}</h3>
<span class="catalog-card-id">{dataset_id}</span>
</div>
</div>
<p class="catalog-card-description">{description}</p>
<div class="catalog-card-footer">
{price_badge}
{action_html}
</div>
</div>
"""
# Wrap in container with improved styles
html = f"""
<div class="catalog-container">
{cards_html}
</div>
<style>
.catalog-container {{
display: flex;
flex-direction: column;
gap: 1rem;
padding: 0.5rem 0;
}}
.catalog-card {{
background: var(--bg-card, #1c1c1e);
border: 1px solid var(--border-color, rgba(255,255,255,0.08));
border-radius: 16px;
padding: 1.25rem 1.5rem;
transition: all 0.2s ease;
position: relative;
}}
.catalog-card:hover {{
border-color: var(--border-color-strong, rgba(255,255,255,0.15));
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}}
.catalog-card-header {{
display: flex;
align-items: flex-start;
gap: 1rem;
margin-bottom: 0.75rem;
}}
.catalog-card-icon {{
font-size: 2rem;
line-height: 1;
flex-shrink: 0;
}}
.catalog-card-title-area {{
flex: 1;
min-width: 0;
}}
.catalog-card-title {{
font-size: 1.125rem;
font-weight: 600;
color: var(--text-primary, #f5f5f7);
margin: 0 0 0.25rem 0;
line-height: 1.3;
}}
.catalog-card-id {{
font-size: 0.75rem;
color: var(--text-tertiary, #6e6e73);
font-family: 'SF Mono', Monaco, monospace;
background: var(--bg-tertiary, rgba(255,255,255,0.05));
padding: 0.125rem 0.5rem;
border-radius: 4px;
display: inline-block;
}}
.catalog-card-description {{
font-size: 0.875rem;
color: var(--text-secondary, #a1a1a6);
line-height: 1.5;
margin: 0 0 1rem 0;
}}
.catalog-card-footer {{
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.75rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border-color, rgba(255,255,255,0.06));
}}
.catalog-price-badge {{
font-size: 1rem;
font-weight: 600;
padding: 0.375rem 0.875rem;
border-radius: 20px;
display: inline-flex;
align-items: baseline;
gap: 0.125rem;
}}
.catalog-price-badge.free {{
background: rgba(52, 199, 89, 0.15);
color: #34c759;
}}
.catalog-price-badge.paid {{
background: var(--bg-tertiary, rgba(255,255,255,0.05));
color: var(--text-primary, #f5f5f7);
}}
.catalog-price-badge .period {{
font-size: 0.75rem;
font-weight: 400;
color: var(--text-tertiary, #6e6e73);
}}
.catalog-card-action {{
display: flex;
align-items: center;
}}
.action-hint {{
font-size: 0.8125rem;
color: var(--text-tertiary, #6e6e73);
}}
.action-hint.login-required {{
font-style: italic;
color: var(--text-tertiary, #6e6e73);
}}
@media (max-width: 640px) {{
.catalog-card-footer {{
flex-direction: column;
align-items: flex-start;
}}
}}
</style>
"""
return html
def get_dataset_choices(datasets, username=None):
"""Returns list of (label, dataset_id) tuples for dropdown."""
if not datasets or not username:
return []
choices = []
for dataset in datasets:
plans = dataset.get("plans", [])
if plans:
plan = plans[0]
price_id = plan.get("stripe_price_id", "")
if price_id in ["free", "0", 0]:
trial_days = plan.get("access_duration_days", 1)
trial_text = "24h" if trial_days == 1 else f"{trial_days}-day"
label = f"{dataset.get('display_name', dataset.get('dataset_id'))} ({trial_text} Trial)"
else:
price = plan.get("price", "10")
label = f"{dataset.get('display_name', dataset.get('dataset_id'))} (${price}/mo)"
choices.append((label, dataset.get('dataset_id')))
return choices