Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import pandas as pd | |
| import json | |
| import io | |
| st.set_page_config(page_title="URL Discovery Tool", layout="wide") | |
| # β STYLE | |
| st.markdown(""" | |
| <style> | |
| .card { | |
| padding:15px; | |
| border-radius:10px; | |
| background-color:#f9f9f9; | |
| margin-bottom:10px; | |
| border:1px solid #ddd; | |
| } | |
| .metric-box { | |
| padding:15px; | |
| border-radius:10px; | |
| text-align:center; | |
| background:#f3f6fb; | |
| border:1px solid #ddd; | |
| } | |
| .metric-value { | |
| font-size:28px; | |
| font-weight:bold; | |
| } | |
| .metric-label { | |
| font-size:14px; | |
| color:#555; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.image("logo.png", width=80) | |
| st.title("π· URL Discovery Tool") | |
| # β SESSION STATES | |
| if "index" not in st.session_state: | |
| st.session_state.index = 0 | |
| if "df" not in st.session_state: | |
| st.session_state.df = None | |
| if "started" not in st.session_state: | |
| st.session_state.started = False | |
| if "stop" not in st.session_state: | |
| st.session_state.stop = False | |
| if "verified_added" not in st.session_state: | |
| st.session_state.verified_added = False | |
| if "reset_inputs" not in st.session_state: | |
| st.session_state.reset_inputs = False | |
| uploaded_file = st.file_uploader("Upload Excel File", type=["xlsx"]) | |
| if uploaded_file: | |
| # β LOAD DATA | |
| if st.session_state.df is None: | |
| st.session_state.df = pd.read_excel(uploaded_file) | |
| df = st.session_state.df | |
| # β SUMMARY CARDS | |
| st.markdown("## π Summary") | |
| total = len(df) | |
| completed = df["Status"].eq("Completed").sum() if "Status" in df.columns else 0 | |
| pending = df["Status"].eq("Pending").sum() if "Status" in df.columns else 0 | |
| if "Verified URL Count" in df.columns: | |
| total_urls = df["Verified URL Count"].fillna(0).sum() | |
| else: | |
| total_urls = 0 | |
| c1, c2, c3, c4 = st.columns(4) | |
| c1.markdown(f""" | |
| <div class="metric-box"> | |
| <div class="metric-value">{total}</div> | |
| <div class="metric-label">Total Entities</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| c2.markdown(f""" | |
| <div class="metric-box"> | |
| <div class="metric-value">{completed}</div> | |
| <div class="metric-label">Completed</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| c3.markdown(f""" | |
| <div class="metric-box"> | |
| <div class="metric-value">{pending}</div> | |
| <div class="metric-label">Pending</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| c4.markdown(f""" | |
| <div class="metric-box"> | |
| <div class="metric-value">{int(total_urls)}</div> | |
| <div class="metric-label">Total URLs Verified</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("---") | |
| # β START / STOP | |
| col1, col2 = st.columns(2) | |
| if col1.button("βΆ Start Processing", disabled=st.session_state.started): | |
| st.session_state.started = True | |
| if col2.button("π Stop Processing"): | |
| st.session_state.stop = True | |
| st.session_state.started = False | |
| # β STOP | |
| if st.session_state.stop: | |
| st.warning("β οΈ Processing stopped") | |
| buffer = io.BytesIO() | |
| df.to_excel(buffer, index=False, engine="openpyxl") | |
| st.download_button("β¬ Download Progress", buffer.getvalue(), "partial.xlsx") | |
| st.stop() | |
| if not st.session_state.started: | |
| st.info("π Click Start Processing") | |
| st.stop() | |
| entity_list = df["Entity ID"].tolist() | |
| # β ALL DONE | |
| if st.session_state.index >= len(entity_list): | |
| st.success("β All Done!") | |
| buffer = io.BytesIO() | |
| df.to_excel(buffer, index=False, engine="openpyxl") | |
| st.download_button("β¬ Download Final File", buffer.getvalue(), "final.xlsx") | |
| st.stop() | |
| # β CURRENT ENTITY | |
| entity_id = entity_list[st.session_state.index] | |
| row = df[df["Entity ID"] == entity_id].iloc[0] | |
| # β LINK | |
| st.markdown( | |
| f'<h3>π <a href="https://crawler-admin.consumerism.pressganey.com/#/verify-sources/{entity_id}" target="_blank">Entity ID: {entity_id}</a></h3>', | |
| unsafe_allow_html=True | |
| ) | |
| # β ENTITY NAME | |
| try: | |
| payload = json.loads(row["Payload"]) | |
| entity_name = payload.get("name", "") | |
| except: | |
| entity_name = "N/A" | |
| # β ENTITY DETAILS | |
| st.markdown("### π§Ύ Entity Details") | |
| c1, c2, c3 = st.columns(3) | |
| with c1: | |
| st.markdown(f"""<div class="card"> | |
| <b>Entity Name:</b> {entity_name}<br> | |
| <b>Client Name:</b> {row['Client Name']} | |
| </div>""", unsafe_allow_html=True) | |
| with c2: | |
| st.markdown(f"""<div class="card"> | |
| <b>Industry:</b> {row['Industry ID']}<br> | |
| <b>Sync Partner:</b> {row['Sync Partner']} | |
| </div>""", unsafe_allow_html=True) | |
| with c3: | |
| st.markdown(f"""<div class="card"> | |
| <b>Products:</b> {row['Client Products']}<br> | |
| <b>Type:</b> {row['Entity Type']} | |
| </div>""", unsafe_allow_html=True) | |
| # β ERROR DETAILS | |
| st.markdown("### π Error Details") | |
| cols = df.columns.tolist() | |
| start = cols.index("Healthgrades") | |
| end = cols.index("AppleMaps") + 1 | |
| sources = cols[start:end] | |
| data = [] | |
| for col in sources: | |
| val = str(row[col]).strip() | |
| if val and val.lower() != "nan": | |
| if "404" in val or "No URLs" in val: | |
| action = "Add URL" | |
| elif "500" in val: | |
| action = "Retry" | |
| elif "Different URL already exists" in val: | |
| action = "Verify Duplicate" | |
| else: | |
| action = "" | |
| data.append({ | |
| "Source": col, | |
| "Value": val, | |
| "Action": action | |
| }) | |
| if data: | |
| st.dataframe(pd.DataFrame(data), use_container_width=True) | |
| # β PROGRESS | |
| progress = (st.session_state.index + 1) / len(entity_list) | |
| st.progress(progress) | |
| st.caption(f"{st.session_state.index + 1} / {len(entity_list)}") | |
| # β RESET INPUTS | |
| if st.session_state.reset_inputs: | |
| st.session_state["verified_input"] = "" | |
| st.session_state["remarks_input"] = "" | |
| st.session_state.reset_inputs = False | |
| # β REMARKS | |
| st.markdown("### π Remarks") | |
| remarks = st.text_area("Enter remarks", key="remarks_input") | |
| # β URL COUNT | |
| st.markdown("### π’ URL Verification") | |
| col1, col2 = st.columns([2, 1]) | |
| verified_count = col1.text_input( | |
| "No of URLs Verified", | |
| key="verified_input" | |
| ) | |
| if col2.button("β Add"): | |
| if verified_count.strip().isdigit(): | |
| df.loc[df["Entity ID"] == entity_id, "Verified URL Count"] = int(verified_count) | |
| df.loc[df["Entity ID"] == entity_id, "Remarks"] = remarks | |
| st.session_state.verified_added = True | |
| st.success("β Added successfully") | |
| else: | |
| st.error("β Enter valid number") | |
| # β ACTION BUTTONS | |
| col_done, col_pending = st.columns(2) | |
| if st.session_state.verified_added: | |
| if col_done.button("β Completed & Next"): | |
| df.loc[df["Entity ID"] == entity_id, "Status"] = "Completed" | |
| st.session_state.index += 1 | |
| st.session_state.verified_added = False | |
| st.session_state.reset_inputs = True | |
| st.rerun() | |
| if col_pending.button("β³ Pending & Next"): | |
| df.loc[df["Entity ID"] == entity_id, "Status"] = "Pending" | |
| st.session_state.index += 1 | |
| st.session_state.verified_added = False | |
| st.session_state.reset_inputs = True | |
| st.rerun() | |
| else: | |
| st.info("π Add verified URL count to proceed") |