Spaces:
Sleeping
Sleeping
Upload Advisernote.py
Browse files- Advisernote.py +32 -2
Advisernote.py
CHANGED
|
@@ -419,9 +419,30 @@ def extract_notion_plain_text(prop):
|
|
| 419 |
return ", ".join(item.get("name", "") for item in prop.get("people", []) if item.get("name")).strip()
|
| 420 |
if prop_type == "number":
|
| 421 |
value = prop.get("number")
|
| 422 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 423 |
return ""
|
| 424 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 425 |
def find_notion_property_value(props, preferred_keys, fallback_types=None):
|
| 426 |
normalized_lookup = {str(key).strip().lower(): value for key, value in props.items()}
|
| 427 |
for key in preferred_keys:
|
|
@@ -593,6 +614,8 @@ def fetch_client_contacts_from_notion(search_text="", selected_fields=None, cust
|
|
| 593 |
)
|
| 594 |
else:
|
| 595 |
row[field_name] = find_notion_property_by_exact_or_contains(props, field_name)
|
|
|
|
|
|
|
| 596 |
|
| 597 |
if not any(str(value).strip() for value in row.values()):
|
| 598 |
continue
|
|
@@ -1625,8 +1648,15 @@ if check_password():
|
|
| 1625 |
|
| 1626 |
contacts_df = st.session_state.get("notion_contacts")
|
| 1627 |
if isinstance(contacts_df, pd.DataFrame):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1628 |
st.dataframe(contacts_df, use_container_width=True, hide_index=True)
|
| 1629 |
-
|
|
|
|
|
|
|
|
|
|
| 1630 |
st.download_button(
|
| 1631 |
"Download CSV",
|
| 1632 |
data=csv_data,
|
|
|
|
| 419 |
return ", ".join(item.get("name", "") for item in prop.get("people", []) if item.get("name")).strip()
|
| 420 |
if prop_type == "number":
|
| 421 |
value = prop.get("number")
|
| 422 |
+
if value is None:
|
| 423 |
+
return ""
|
| 424 |
+
if isinstance(value, float) and value.is_integer():
|
| 425 |
+
return str(int(value)).strip()
|
| 426 |
+
return str(value).strip()
|
| 427 |
return ""
|
| 428 |
|
| 429 |
+
def normalize_phone_text(value):
|
| 430 |
+
text = "" if value is None else str(value).strip()
|
| 431 |
+
if text.endswith(".0") and text[:-2].isdigit():
|
| 432 |
+
text = text[:-2]
|
| 433 |
+
return text
|
| 434 |
+
|
| 435 |
+
def is_phone_like_field(field_name):
|
| 436 |
+
normalized = str(field_name or "").strip().lower()
|
| 437 |
+
return any(key in normalized for key in ["phone", "mobile", "telephone", "contact number", "cell", "전화", "연락", "휴대"])
|
| 438 |
+
|
| 439 |
+
def make_excel_safe_phone(value):
|
| 440 |
+
text = normalize_phone_text(value)
|
| 441 |
+
if not text:
|
| 442 |
+
return ""
|
| 443 |
+
escaped = text.replace('"', '""')
|
| 444 |
+
return f'="{escaped}"'
|
| 445 |
+
|
| 446 |
def find_notion_property_value(props, preferred_keys, fallback_types=None):
|
| 447 |
normalized_lookup = {str(key).strip().lower(): value for key, value in props.items()}
|
| 448 |
for key in preferred_keys:
|
|
|
|
| 614 |
)
|
| 615 |
else:
|
| 616 |
row[field_name] = find_notion_property_by_exact_or_contains(props, field_name)
|
| 617 |
+
if is_phone_like_field(field_name):
|
| 618 |
+
row[field_name] = normalize_phone_text(row[field_name])
|
| 619 |
|
| 620 |
if not any(str(value).strip() for value in row.values()):
|
| 621 |
continue
|
|
|
|
| 1648 |
|
| 1649 |
contacts_df = st.session_state.get("notion_contacts")
|
| 1650 |
if isinstance(contacts_df, pd.DataFrame):
|
| 1651 |
+
contacts_df = contacts_df.fillna("").astype(str)
|
| 1652 |
+
phone_columns = [col for col in contacts_df.columns if is_phone_like_field(col)]
|
| 1653 |
+
for col in phone_columns:
|
| 1654 |
+
contacts_df[col] = contacts_df[col].map(normalize_phone_text)
|
| 1655 |
st.dataframe(contacts_df, use_container_width=True, hide_index=True)
|
| 1656 |
+
csv_df = contacts_df.copy()
|
| 1657 |
+
for col in phone_columns:
|
| 1658 |
+
csv_df[col] = csv_df[col].map(make_excel_safe_phone)
|
| 1659 |
+
csv_data = csv_df.to_csv(index=False).encode("utf-8-sig")
|
| 1660 |
st.download_button(
|
| 1661 |
"Download CSV",
|
| 1662 |
data=csv_data,
|