Make posts table scrollable and fix file-finder to ignore non-export files
- All Posts table now scrolls within a fixed height instead of paginating/ growing indefinitely as more posts accumulate, with column widths tuned so Short title gets the most room and narrow columns (dates, rates, counts) stay compact. - _find_latest_file/_find_all_files now only match real LinkedIn export filenames (txproducts_*), so unrelated files sitting in the same folder (a manual roster, an Office lock file) can no longer crash the loader.
This commit is contained in:
1 parent
348fe65b88
commit
f631ba26a0
2 files changed
+36
-8
No files matched your search
@@ -12,3 +12,4 @@ __pycache__/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
manual_followers_list_*
|
||||
@@ -103,9 +103,21 @@ def mark_posts(fig, fts_df, posts_df):
|
||||
return fig
|
||||
|
||||
|
||||
def _is_linkedin_export(fname, keyword, extensions):
|
||||
"""True only for real LinkedIn export files (e.g. txproducts_followers_<id>.xls) —
|
||||
excludes unrelated files that happen to contain the keyword (like a manually-built
|
||||
roster) and Office lock files (~$...) left behind by a file currently open in Excel."""
|
||||
lower = fname.lower()
|
||||
if lower.startswith("~$") or lower.startswith("."):
|
||||
return False
|
||||
if not lower.startswith("txproducts_"):
|
||||
return False
|
||||
return keyword.lower() in lower and lower.endswith(extensions)
|
||||
|
||||
|
||||
def _find_latest_file(keyword, extensions=(".xls", ".xlsx")):
|
||||
"""Most recently modified file across DATA_DIR and UPLOAD_DIR whose name contains
|
||||
`keyword` (case-insensitive) — replaces matching one exact hardcoded filename, so any
|
||||
"""Most recently modified real LinkedIn export across DATA_DIR and UPLOAD_DIR whose
|
||||
name contains `keyword` — replaces matching one exact hardcoded filename, so any
|
||||
correctly-named LinkedIn export (including freshly uploaded ones) is picked up without
|
||||
needing the file's exact auto-generated export ID."""
|
||||
candidates = []
|
||||
@@ -113,7 +125,7 @@ def _find_latest_file(keyword, extensions=(".xls", ".xlsx")):
|
||||
if not os.path.isdir(folder):
|
||||
continue
|
||||
for fname in os.listdir(folder):
|
||||
if keyword.lower() in fname.lower() and fname.lower().endswith(extensions):
|
||||
if _is_linkedin_export(fname, keyword, extensions):
|
||||
candidates.append(os.path.join(folder, fname))
|
||||
if not candidates:
|
||||
raise FileNotFoundError(
|
||||
@@ -130,7 +142,7 @@ def _find_all_files(keyword, extensions=(".xls", ".xlsx")):
|
||||
if not os.path.isdir(folder):
|
||||
continue
|
||||
for fname in os.listdir(folder):
|
||||
if keyword.lower() in fname.lower() and fname.lower().endswith(extensions):
|
||||
if _is_linkedin_export(fname, keyword, extensions):
|
||||
candidates.append(os.path.join(folder, fname))
|
||||
return sorted(set(candidates), key=os.path.getmtime)
|
||||
|
||||
@@ -494,14 +506,29 @@ def refresh_data():
|
||||
id="posts-table",
|
||||
data=_posts_table_df.to_dict("records"),
|
||||
columns=[{"name": c, "id": c} for c in post_table_cols],
|
||||
page_size=20,
|
||||
style_table={"overflowX": "auto"},
|
||||
page_action="none",
|
||||
fixed_rows={"headers": True},
|
||||
style_table={"overflowX": "auto", "overflowY": "auto", "maxHeight": "260px"},
|
||||
style_header={"backgroundColor": "#f0f4f8", "color": "#333", "fontWeight": "bold", "border": "1px solid #ccc",
|
||||
"fontSize": "11px", "padding": "3px 6px", "height": "22px", "lineHeight": "16px"},
|
||||
"fontSize": "11px", "padding": "3px 6px", "height": "22px", "lineHeight": "16px",
|
||||
"whiteSpace": "nowrap", "overflow": "hidden", "textOverflow": "ellipsis"},
|
||||
style_cell={"backgroundColor": "#ffffff", "color": "#333", "border": "1px solid #e0e0e0",
|
||||
"fontSize": "11px", "padding": "3px 6px", "height": "22px", "lineHeight": "16px",
|
||||
"textAlign": "left",
|
||||
"textAlign": "left", "whiteSpace": "nowrap",
|
||||
"maxWidth": "300px", "overflow": "hidden", "textOverflow": "ellipsis"},
|
||||
style_cell_conditional=[
|
||||
{"if": {"column_id": "Short title"}, "minWidth": "250px", "maxWidth": "none"},
|
||||
{"if": {"column_id": "Created date"}, "width": "95px", "minWidth": "95px", "maxWidth": "95px"},
|
||||
{"if": {"column_id": "Post type"}, "width": "75px", "minWidth": "75px", "maxWidth": "75px"},
|
||||
{"if": {"column_id": "Content Type"}, "width": "100px", "minWidth": "100px", "maxWidth": "100px"},
|
||||
{"if": {"column_id": "Impressions"}, "width": "85px", "minWidth": "85px", "maxWidth": "85px"},
|
||||
{"if": {"column_id": "Clicks"}, "width": "60px", "minWidth": "60px", "maxWidth": "60px"},
|
||||
{"if": {"column_id": "Eng %"}, "width": "60px", "minWidth": "60px", "maxWidth": "60px"},
|
||||
{"if": {"column_id": "CTR %"}, "width": "60px", "minWidth": "60px", "maxWidth": "60px"},
|
||||
{"if": {"column_id": "Likes"}, "width": "60px", "minWidth": "60px", "maxWidth": "60px"},
|
||||
{"if": {"column_id": "Comments"}, "width": "70px", "minWidth": "70px", "maxWidth": "70px"},
|
||||
{"if": {"column_id": "Reposts"}, "width": "70px", "minWidth": "70px", "maxWidth": "70px"},
|
||||
],
|
||||
style_data_conditional=post_highlight_styles,
|
||||
tooltip_data=[{c: {"value": str(row[c]), "type": "markdown"} for c in post_table_cols}
|
||||
for row in _posts_table_df.to_dict("records")],
|
||||
|
||||
Reference in new issue
Block a user