Lavender825 commited on
Commit
ce1a6a7
·
1 Parent(s): 26dd6cb

Compact consumer product card image fallback

Browse files
Files changed (1) hide show
  1. app.py +27 -11
app.py CHANGED
@@ -9,7 +9,7 @@ import traceback
9
  from functools import lru_cache
10
  from pathlib import Path
11
  from typing import Any, Dict, List, Tuple
12
- from urllib.parse import quote_plus
13
 
14
  try:
15
  import huggingface_hub as _hf_hub
@@ -200,6 +200,13 @@ def _esc(value: Any) -> str:
200
  return html.escape(str(value))
201
 
202
 
 
 
 
 
 
 
 
203
  def _pct(value: Any) -> str:
204
  try:
205
  return f"{float(value) * 100:.2f}%"
@@ -260,12 +267,18 @@ def _product_image_url(product: Dict[str, Any]) -> str:
260
  image_url = str(product.get("image_url") or "").strip()
261
  if image_url:
262
  return image_url
263
- query = quote_plus(" ".join([
264
- str(product.get("category") or "clothing"),
265
- str(product.get("tags", ["fashion"])[0] if product.get("tags") else "fashion"),
266
- "product"
267
- ]))
268
- return f"https://source.unsplash.com/320x420/?{query}"
 
 
 
 
 
 
269
 
270
 
271
  def _meta(product_or_meta: Dict[str, Any]) -> Dict[str, Any]:
@@ -436,7 +449,7 @@ def consumer_product_view(product_name: str, selected_aspect: str) -> Tuple[str,
436
  f'<span>Price: ${_safe_float(product["price"]):.2f}</span>'
437
  f'<span>Rating: {_safe_float(product["average_rating"]):.1f}</span>'
438
  f'<span>Reviews: {int(_safe_float(product["rating_number"]))}</span></div>'
439
- f'<p><b>Metadata:</b> {_esc(product["features"])}</p>'
440
  f'{_recommendation_html(result, product["name"])}{_overall_html(result)}</div></div>'
441
  )
442
  evidence = f'<h4>Key review evidence</h4>{_highlight_review(product["review"], selected_aspect)}'
@@ -656,8 +669,11 @@ button.primary, .gradio-button.primary { background:var(--accent) !important; bo
656
  .status.ok { background:#ecfdf5; border-color:#86efac; color:#065f46; }
657
  .status.bad { background:#fff1f2; border-color:#fda4af; color:#991b1b; }
658
  .product-card, .overall-card, .note-card { border:1px solid var(--line); border-radius:8px; padding:16px; background:white; }
659
- .product-layout { display:grid; grid-template-columns:132px 1fr; gap:16px; align-items:start; }
660
- .product-img { width:132px; height:166px; object-fit:cover; border-radius:8px; border:1px solid var(--line); background:#f8fafc; }
 
 
 
661
  .recommendation-card { border:1px solid #fed7aa; border-left:5px solid var(--accent); background:#fff7ed; border-radius:8px; padding:13px 14px; margin:12px 0; }
662
  .recommendation-card p { margin:7px 0 0; }
663
  .muted { color:var(--muted); }
@@ -690,7 +706,7 @@ mark { background:#fde68a; color:#111827; border-radius:4px; padding:1px 3px; }
690
  .kv-table td { border-bottom:1px solid #e2e8f0; padding:9px 12px; }
691
  .kv-table td:first-child { width:220px; color:#334155; font-weight:700; background:#f8fafc; }
692
  .compact-note { color:#475569; font-size:13px; margin:4px 0 10px; }
693
- @media (max-width:860px) { .aspect-grid, .metric-grid, .product-layout { grid-template-columns:1fr; } .product-img { width:100%; height:220px; } }
694
  """
695
 
696
 
 
9
  from functools import lru_cache
10
  from pathlib import Path
11
  from typing import Any, Dict, List, Tuple
12
+ from urllib.parse import quote
13
 
14
  try:
15
  import huggingface_hub as _hf_hub
 
200
  return html.escape(str(value))
201
 
202
 
203
+ def _short_text(value: Any, limit: int = 220) -> str:
204
+ text = re.sub(r"\s+", " ", str(value or "")).strip()
205
+ if len(text) <= limit:
206
+ return text
207
+ return text[: limit - 3].rstrip() + "..."
208
+
209
+
210
  def _pct(value: Any) -> str:
211
  try:
212
  return f"{float(value) * 100:.2f}%"
 
267
  image_url = str(product.get("image_url") or "").strip()
268
  if image_url:
269
  return image_url
270
+ category = _short_text(product.get("category") or "Clothing", 28)
271
+ tag = _short_text(product.get("tags", ["fashion"])[0] if product.get("tags") else "fashion", 18)
272
+ svg = f"""<svg xmlns="http://www.w3.org/2000/svg" width="320" height="420" viewBox="0 0 320 420">
273
+ <defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#eff6ff"/><stop offset="1" stop-color="#fff7ed"/></linearGradient></defs>
274
+ <rect width="320" height="420" rx="24" fill="url(#g)"/>
275
+ <rect x="62" y="58" width="196" height="250" rx="30" fill="#ffffff" stroke="#dbe3ef" stroke-width="4"/>
276
+ <path d="M116 90 C128 120 192 120 204 90 L238 124 L214 166 L202 150 L202 300 L118 300 L118 150 L106 166 L82 124 Z" fill="#1f2937"/>
277
+ <path d="M126 96 C140 114 180 114 194 96" fill="none" stroke="#f97316" stroke-width="8" stroke-linecap="round"/>
278
+ <text x="160" y="350" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#0f172a">{html.escape(category)}</text>
279
+ <text x="160" y="382" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" fill="#475569">{html.escape(tag)}</text>
280
+ </svg>"""
281
+ return "data:image/svg+xml;charset=utf-8," + quote(svg)
282
 
283
 
284
  def _meta(product_or_meta: Dict[str, Any]) -> Dict[str, Any]:
 
449
  f'<span>Price: ${_safe_float(product["price"]):.2f}</span>'
450
  f'<span>Rating: {_safe_float(product["average_rating"]):.1f}</span>'
451
  f'<span>Reviews: {int(_safe_float(product["rating_number"]))}</span></div>'
452
+ f'<p class="metadata-summary"><b>Metadata:</b> {_esc(_short_text(product["features"], 190))}</p>'
453
  f'{_recommendation_html(result, product["name"])}{_overall_html(result)}</div></div>'
454
  )
455
  evidence = f'<h4>Key review evidence</h4>{_highlight_review(product["review"], selected_aspect)}'
 
669
  .status.ok { background:#ecfdf5; border-color:#86efac; color:#065f46; }
670
  .status.bad { background:#fff1f2; border-color:#fda4af; color:#991b1b; }
671
  .product-card, .overall-card, .note-card { border:1px solid var(--line); border-radius:8px; padding:16px; background:white; }
672
+ .product-layout { display:grid; grid-template-columns:104px 1fr; gap:14px; align-items:start; }
673
+ .product-img { width:104px; height:132px; object-fit:cover; border-radius:8px; border:1px solid var(--line); background:#f8fafc; }
674
+ .product-card h3 { margin:0 0 6px; font-size:18px; line-height:1.25; }
675
+ .product-card p { margin:7px 0; }
676
+ .metadata-summary { color:#334155; font-size:13px; line-height:1.45; }
677
  .recommendation-card { border:1px solid #fed7aa; border-left:5px solid var(--accent); background:#fff7ed; border-radius:8px; padding:13px 14px; margin:12px 0; }
678
  .recommendation-card p { margin:7px 0 0; }
679
  .muted { color:var(--muted); }
 
706
  .kv-table td { border-bottom:1px solid #e2e8f0; padding:9px 12px; }
707
  .kv-table td:first-child { width:220px; color:#334155; font-weight:700; background:#f8fafc; }
708
  .compact-note { color:#475569; font-size:13px; margin:4px 0 10px; }
709
+ @media (max-width:860px) { .aspect-grid, .metric-grid, .product-layout { grid-template-columns:1fr; } .product-img { width:100%; height:180px; } }
710
  """
711
 
712