Spaces:
Sleeping
Sleeping
Pointf5ive commited on
Commit Β·
6233ead
1
Parent(s): 2d9935c
Fix: update rights on duplicate upload, add rights editor UI
Browse files- smoke_signal_tab.py +35 -2
smoke_signal_tab.py
CHANGED
|
@@ -505,9 +505,15 @@ def ingest_pdfs(files, rights_class: str, notes: str) -> tuple:
|
|
| 505 |
|
| 506 |
file_hash = sha256_file(path)
|
| 507 |
|
| 508 |
-
# Check duplicate
|
| 509 |
if not df.empty and file_hash in df["sha256"].values:
|
| 510 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 511 |
dup_count += 1
|
| 512 |
continue
|
| 513 |
|
|
@@ -568,6 +574,17 @@ def _ingest_status_html(state: str, new=0, dups=0) -> str:
|
|
| 568 |
</div>{alert}"""
|
| 569 |
|
| 570 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
# ββ Step 2: PROFILE ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 572 |
def run_profile() -> tuple:
|
| 573 |
"""Profile all pending PDFs."""
|
|
@@ -1151,6 +1168,22 @@ def smoke_signal_tab():
|
|
| 1151 |
refresh_btn = gr.Button("β» Refresh Manifest", size="sm")
|
| 1152 |
refresh_btn.click(lambda: load_manifest_df(), outputs=[manifest_table])
|
| 1153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1154 |
ingest_btn.click(
|
| 1155 |
ingest_pdfs,
|
| 1156 |
inputs=[pdf_upload, rights_dd, ingest_notes],
|
|
|
|
| 505 |
|
| 506 |
file_hash = sha256_file(path)
|
| 507 |
|
| 508 |
+
# Check duplicate β update rights/notes if changed
|
| 509 |
if not df.empty and file_hash in df["sha256"].values:
|
| 510 |
+
existing_rights = df.loc[df["sha256"] == file_hash, "rights_class"].values[0]
|
| 511 |
+
if rights_class != "unknown" and existing_rights != rights_class:
|
| 512 |
+
df.loc[df["sha256"] == file_hash, "rights_class"] = rights_class
|
| 513 |
+
df.loc[df["sha256"] == file_hash, "notes"] = notes
|
| 514 |
+
log.append(log_line(f"β» Updated rights for duplicate: {path.name} β {rights_class}"))
|
| 515 |
+
else:
|
| 516 |
+
log.append(log_line(f"β© Duplicate: {path.name} (rights={existing_rights})"))
|
| 517 |
dup_count += 1
|
| 518 |
continue
|
| 519 |
|
|
|
|
| 574 |
</div>{alert}"""
|
| 575 |
|
| 576 |
|
| 577 |
+
# ββ Rights class updater ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 578 |
+
def update_rights(book_id: str, new_rights: str) -> tuple:
|
| 579 |
+
"""Update rights class for an existing book."""
|
| 580 |
+
df = load_manifest_df()
|
| 581 |
+
if df.empty or book_id not in df["book_id"].values:
|
| 582 |
+
return _ingest_status_html("idle"), df, f"Book ID {book_id} not found."
|
| 583 |
+
df.loc[df["book_id"] == book_id, "rights_class"] = new_rights
|
| 584 |
+
save_manifest_df(df)
|
| 585 |
+
return _ingest_status_html("done"), df, f"[{datetime.utcnow().strftime('%H:%M:%S')}] β Updated {book_id} rights β {new_rights}"
|
| 586 |
+
|
| 587 |
+
|
| 588 |
# ββ Step 2: PROFILE ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 589 |
def run_profile() -> tuple:
|
| 590 |
"""Profile all pending PDFs."""
|
|
|
|
| 1168 |
refresh_btn = gr.Button("β» Refresh Manifest", size="sm")
|
| 1169 |
refresh_btn.click(lambda: load_manifest_df(), outputs=[manifest_table])
|
| 1170 |
|
| 1171 |
+
gr.Markdown("**Update rights class for existing book:**")
|
| 1172 |
+
with gr.Row():
|
| 1173 |
+
update_book_id = gr.Textbox(label="Book ID", placeholder="SS-BOOK-0001", scale=1)
|
| 1174 |
+
update_rights_dd = gr.Dropdown(
|
| 1175 |
+
label="New Rights Class",
|
| 1176 |
+
choices=["public-domain","licensed-owned","controlled-internal","unknown"],
|
| 1177 |
+
value="licensed-owned",
|
| 1178 |
+
scale=1,
|
| 1179 |
+
)
|
| 1180 |
+
update_rights_btn = gr.Button("Update Rights", size="sm", scale=1)
|
| 1181 |
+
update_rights_btn.click(
|
| 1182 |
+
update_rights,
|
| 1183 |
+
inputs=[update_book_id, update_rights_dd],
|
| 1184 |
+
outputs=[ingest_status, manifest_table, ingest_log],
|
| 1185 |
+
)
|
| 1186 |
+
|
| 1187 |
ingest_btn.click(
|
| 1188 |
ingest_pdfs,
|
| 1189 |
inputs=[pdf_upload, rights_dd, ingest_notes],
|