Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -180,22 +180,13 @@ def read_csv_to_dataframe() -> pd.DataFrame:
|
|
| 180 |
return pd.DataFrame()
|
| 181 |
|
| 182 |
def format_dataframe_for_display(df: pd.DataFrame) -> pd.DataFrame:
|
| 183 |
-
"""
|
| 184 |
if df.empty:
|
| 185 |
return df
|
| 186 |
|
| 187 |
-
#
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
# Apply formatting only for display
|
| 191 |
-
if not display_df.empty:
|
| 192 |
-
display_df['repo id'] = display_df['repo id'].apply(lambda x: format_text_for_dataframe(x, 50))
|
| 193 |
-
display_df['strength'] = display_df['strength'].apply(lambda x: format_text_for_dataframe(x, 180))
|
| 194 |
-
display_df['weaknesses'] = display_df['weaknesses'].apply(lambda x: format_text_for_dataframe(x, 180))
|
| 195 |
-
display_df['speciality'] = display_df['speciality'].apply(lambda x: format_text_for_dataframe(x, 150))
|
| 196 |
-
# Keep relevance rating as is since it should be short
|
| 197 |
-
|
| 198 |
-
return display_df
|
| 199 |
|
| 200 |
def analyze_and_update_single_repo(repo_id: str, user_requirements: str = "") -> Tuple[str, str, pd.DataFrame]:
|
| 201 |
"""
|
|
@@ -261,7 +252,7 @@ def analyze_and_update_single_repo(repo_id: str, user_requirements: str = "") ->
|
|
| 261 |
logger.error(f"Failed to write CSV for {repo_id} on retry: {retry_error}")
|
| 262 |
|
| 263 |
logger.info(f"Successfully analyzed and updated CSV for {repo_id}")
|
| 264 |
-
return combined_content, summary,
|
| 265 |
|
| 266 |
except Exception as e:
|
| 267 |
logger.error(f"An error occurred during analysis of {repo_id}: {e}")
|
|
@@ -389,37 +380,41 @@ def create_ui() -> gr.Blocks:
|
|
| 389 |
border-radius: 4px;
|
| 390 |
}
|
| 391 |
|
| 392 |
-
/* Improved dataframe styling */
|
| 393 |
.gr-dataframe {
|
| 394 |
-
max-height:
|
| 395 |
overflow-y: auto;
|
|
|
|
| 396 |
}
|
| 397 |
|
| 398 |
.gr-dataframe table {
|
| 399 |
-
table-layout:
|
| 400 |
width: 100%;
|
|
|
|
| 401 |
}
|
| 402 |
|
| 403 |
.gr-dataframe th,
|
| 404 |
.gr-dataframe td {
|
| 405 |
-
padding:
|
| 406 |
vertical-align: top;
|
| 407 |
word-wrap: break-word;
|
| 408 |
overflow-wrap: break-word;
|
| 409 |
-
max-height:
|
| 410 |
overflow-y: auto;
|
|
|
|
|
|
|
| 411 |
}
|
| 412 |
|
| 413 |
.gr-dataframe th:nth-child(1),
|
| 414 |
-
.gr-dataframe td:nth-child(1) { width:
|
| 415 |
.gr-dataframe th:nth-child(2),
|
| 416 |
-
.gr-dataframe td:nth-child(2) { width:
|
| 417 |
.gr-dataframe th:nth-child(3),
|
| 418 |
-
.gr-dataframe td:nth-child(3) { width:
|
| 419 |
.gr-dataframe th:nth-child(4),
|
| 420 |
-
.gr-dataframe td:nth-child(4) { width:
|
| 421 |
.gr-dataframe th:nth-child(5),
|
| 422 |
-
.gr-dataframe td:nth-child(5) { width:
|
| 423 |
|
| 424 |
/* Make repository names clickable */
|
| 425 |
.gr-dataframe td:nth-child(1) {
|
|
@@ -435,24 +430,13 @@ def create_ui() -> gr.Blocks:
|
|
| 435 |
transform: scale(1.02);
|
| 436 |
}
|
| 437 |
|
| 438 |
-
/*
|
| 439 |
.gr-dataframe td:nth-child(2),
|
| 440 |
.gr-dataframe td:nth-child(3),
|
| 441 |
-
.gr-dataframe td:nth-child(4)
|
| 442 |
-
cursor: pointer;
|
| 443 |
-
transition: all 0.3s ease;
|
| 444 |
-
}
|
| 445 |
-
|
| 446 |
-
.gr-dataframe td:nth-child(2):hover,
|
| 447 |
-
.gr-dataframe td:nth-child(3):hover,
|
| 448 |
-
.gr-dataframe td:nth-child(4):hover {
|
| 449 |
-
background-color: rgba(102, 126, 234, 0.08);
|
| 450 |
-
box-shadow: inset 0 0 0 1px rgba(102, 126, 234, 0.2);
|
| 451 |
-
}
|
| 452 |
-
|
| 453 |
-
/* Relevance column - not clickable */
|
| 454 |
.gr-dataframe td:nth-child(5) {
|
| 455 |
cursor: default;
|
|
|
|
| 456 |
}
|
| 457 |
|
| 458 |
.gr-dataframe tbody tr:hover {
|
|
@@ -494,15 +478,42 @@ def create_ui() -> gr.Blocks:
|
|
| 494 |
});
|
| 495 |
});
|
| 496 |
|
| 497 |
-
//
|
| 498 |
let lastSelectedTab = null;
|
| 499 |
-
setInterval(function() {
|
| 500 |
const currentSelectedTab = document.querySelector('.gr-tab-nav button.selected');
|
| 501 |
if (currentSelectedTab && currentSelectedTab !== lastSelectedTab) {
|
| 502 |
lastSelectedTab = currentSelectedTab;
|
| 503 |
-
scrollToTop
|
| 504 |
}
|
| 505 |
-
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
});
|
| 507 |
</script>
|
| 508 |
"""
|
|
@@ -634,9 +645,9 @@ def create_ui() -> gr.Blocks:
|
|
| 634 |
interactive=False
|
| 635 |
)
|
| 636 |
|
| 637 |
-
gr.Markdown("π‘ **Tip:** Click on
|
| 638 |
|
| 639 |
-
# Text expansion modal for showing full content
|
| 640 |
with gr.Row():
|
| 641 |
with gr.Column():
|
| 642 |
text_expansion_modal = gr.Column(visible=False)
|
|
@@ -860,7 +871,7 @@ def create_ui() -> gr.Blocks:
|
|
| 860 |
return final_keywords_str, status, user_requirements
|
| 861 |
|
| 862 |
def handle_dataframe_select(evt: gr.SelectData, df_data) -> Tuple[str, Any, Any, str, str, Any]:
|
| 863 |
-
"""Handle dataframe row selection - repo ID shows modal
|
| 864 |
print(f"DEBUG: Selection event triggered!")
|
| 865 |
print(f"DEBUG: evt = {evt}")
|
| 866 |
print(f"DEBUG: df_data type = {type(df_data)}")
|
|
@@ -877,31 +888,7 @@ def create_ui() -> gr.Blocks:
|
|
| 877 |
# Handle pandas DataFrame
|
| 878 |
if isinstance(df_data, pd.DataFrame) and not df_data.empty and row_idx < len(df_data):
|
| 879 |
|
| 880 |
-
|
| 881 |
-
if col_idx in [1, 2, 3]: # Strength, Weakness, or Speciality columns
|
| 882 |
-
repo_name = str(df_data.iloc[row_idx, 0])
|
| 883 |
-
|
| 884 |
-
# Read full data from CSV file to get untruncated text
|
| 885 |
-
full_df = read_csv_to_dataframe()
|
| 886 |
-
|
| 887 |
-
# Find the matching row in the full data
|
| 888 |
-
matching_rows = full_df[full_df['repo id'] == repo_name]
|
| 889 |
-
if not matching_rows.empty:
|
| 890 |
-
full_row = matching_rows.iloc[0]
|
| 891 |
-
|
| 892 |
-
if col_idx == 1: # Strengths column
|
| 893 |
-
full_text = str(full_row['strength'])
|
| 894 |
-
title = f"Strengths - {repo_name}"
|
| 895 |
-
elif col_idx == 2: # Weaknesses column
|
| 896 |
-
full_text = str(full_row['weaknesses'])
|
| 897 |
-
title = f"Weaknesses - {repo_name}"
|
| 898 |
-
elif col_idx == 3: # Speciality column
|
| 899 |
-
full_text = str(full_row['speciality'])
|
| 900 |
-
title = f"Speciality - {repo_name}"
|
| 901 |
-
|
| 902 |
-
return "", gr.update(visible=False), gr.update(), title, full_text, gr.update(visible=True)
|
| 903 |
-
|
| 904 |
-
elif col_idx == 0: # Repository name column - show action modal
|
| 905 |
repo_id = df_data.iloc[row_idx, 0]
|
| 906 |
print(f"DEBUG: Extracted repo_id = '{repo_id}'")
|
| 907 |
|
|
@@ -910,9 +897,9 @@ def create_ui() -> gr.Blocks:
|
|
| 910 |
logger.info(f"Showing modal for repository: {clean_repo_id}")
|
| 911 |
return clean_repo_id, gr.update(visible=True), gr.update(), "", "", gr.update(visible=False)
|
| 912 |
|
| 913 |
-
# For
|
| 914 |
else:
|
| 915 |
-
print(f"DEBUG: Clicked on column {col_idx},
|
| 916 |
return "", gr.update(visible=False), gr.update(), "", "", gr.update(visible=False)
|
| 917 |
else:
|
| 918 |
print(f"DEBUG: df_data is not a DataFrame or row_idx {row_idx} out of range")
|
|
@@ -1200,7 +1187,8 @@ def create_ui() -> gr.Blocks:
|
|
| 1200 |
explore_repo_btn.click(
|
| 1201 |
fn=handle_explore_repo,
|
| 1202 |
inputs=[selected_repo_display],
|
| 1203 |
-
outputs=[repo_action_modal, tabs, repo_components["repo_explorer_input"]]
|
|
|
|
| 1204 |
)
|
| 1205 |
cancel_modal_btn.click(
|
| 1206 |
fn=handle_cancel_modal,
|
|
|
|
| 180 |
return pd.DataFrame()
|
| 181 |
|
| 182 |
def format_dataframe_for_display(df: pd.DataFrame) -> pd.DataFrame:
|
| 183 |
+
"""Returns dataframe with full text (no truncation) for display."""
|
| 184 |
if df.empty:
|
| 185 |
return df
|
| 186 |
|
| 187 |
+
# Return the dataframe as-is without any text truncation
|
| 188 |
+
# This will show the full text content in the CSV display
|
| 189 |
+
return df.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
|
| 191 |
def analyze_and_update_single_repo(repo_id: str, user_requirements: str = "") -> Tuple[str, str, pd.DataFrame]:
|
| 192 |
"""
|
|
|
|
| 252 |
logger.error(f"Failed to write CSV for {repo_id} on retry: {retry_error}")
|
| 253 |
|
| 254 |
logger.info(f"Successfully analyzed and updated CSV for {repo_id}")
|
| 255 |
+
return combined_content, summary, df
|
| 256 |
|
| 257 |
except Exception as e:
|
| 258 |
logger.error(f"An error occurred during analysis of {repo_id}: {e}")
|
|
|
|
| 380 |
border-radius: 4px;
|
| 381 |
}
|
| 382 |
|
| 383 |
+
/* Improved dataframe styling for full text display */
|
| 384 |
.gr-dataframe {
|
| 385 |
+
max-height: 600px;
|
| 386 |
overflow-y: auto;
|
| 387 |
+
overflow-x: auto;
|
| 388 |
}
|
| 389 |
|
| 390 |
.gr-dataframe table {
|
| 391 |
+
table-layout: auto;
|
| 392 |
width: 100%;
|
| 393 |
+
min-width: 1200px;
|
| 394 |
}
|
| 395 |
|
| 396 |
.gr-dataframe th,
|
| 397 |
.gr-dataframe td {
|
| 398 |
+
padding: 12px 15px;
|
| 399 |
vertical-align: top;
|
| 400 |
word-wrap: break-word;
|
| 401 |
overflow-wrap: break-word;
|
| 402 |
+
max-height: 200px;
|
| 403 |
overflow-y: auto;
|
| 404 |
+
white-space: pre-wrap;
|
| 405 |
+
line-height: 1.4;
|
| 406 |
}
|
| 407 |
|
| 408 |
.gr-dataframe th:nth-child(1),
|
| 409 |
+
.gr-dataframe td:nth-child(1) { width: 200px; min-width: 200px; }
|
| 410 |
.gr-dataframe th:nth-child(2),
|
| 411 |
+
.gr-dataframe td:nth-child(2) { width: 300px; min-width: 300px; }
|
| 412 |
.gr-dataframe th:nth-child(3),
|
| 413 |
+
.gr-dataframe td:nth-child(3) { width: 300px; min-width: 300px; }
|
| 414 |
.gr-dataframe th:nth-child(4),
|
| 415 |
+
.gr-dataframe td:nth-child(4) { width: 250px; min-width: 250px; }
|
| 416 |
.gr-dataframe th:nth-child(5),
|
| 417 |
+
.gr-dataframe td:nth-child(5) { width: 150px; min-width: 150px; }
|
| 418 |
|
| 419 |
/* Make repository names clickable */
|
| 420 |
.gr-dataframe td:nth-child(1) {
|
|
|
|
| 430 |
transform: scale(1.02);
|
| 431 |
}
|
| 432 |
|
| 433 |
+
/* Content columns - readable styling with scroll for long text */
|
| 434 |
.gr-dataframe td:nth-child(2),
|
| 435 |
.gr-dataframe td:nth-child(3),
|
| 436 |
+
.gr-dataframe td:nth-child(4),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
.gr-dataframe td:nth-child(5) {
|
| 438 |
cursor: default;
|
| 439 |
+
font-size: 0.9rem;
|
| 440 |
}
|
| 441 |
|
| 442 |
.gr-dataframe tbody tr:hover {
|
|
|
|
| 478 |
});
|
| 479 |
});
|
| 480 |
|
| 481 |
+
// Enhanced listener for programmatic tab changes (button-triggered navigation)
|
| 482 |
let lastSelectedTab = null;
|
| 483 |
+
const checkInterval = setInterval(function() {
|
| 484 |
const currentSelectedTab = document.querySelector('.gr-tab-nav button.selected');
|
| 485 |
if (currentSelectedTab && currentSelectedTab !== lastSelectedTab) {
|
| 486 |
lastSelectedTab = currentSelectedTab;
|
| 487 |
+
setTimeout(scrollToTop, 100);
|
| 488 |
}
|
| 489 |
+
}, 100);
|
| 490 |
+
|
| 491 |
+
// Additional scroll trigger for repo explorer navigation
|
| 492 |
+
window.addEventListener('repoExplorerNavigation', function() {
|
| 493 |
+
setTimeout(scrollToTop, 200);
|
| 494 |
+
});
|
| 495 |
+
|
| 496 |
+
// Watch for specific tab transitions to repo explorer
|
| 497 |
+
const repoExplorerObserver = new MutationObserver(function(mutations) {
|
| 498 |
+
mutations.forEach(function(mutation) {
|
| 499 |
+
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
| 500 |
+
const target = mutation.target;
|
| 501 |
+
if (target.textContent && target.textContent.includes('π Repo Explorer') && target.classList.contains('selected')) {
|
| 502 |
+
setTimeout(scrollToTop, 150);
|
| 503 |
+
}
|
| 504 |
+
}
|
| 505 |
+
});
|
| 506 |
+
});
|
| 507 |
+
|
| 508 |
+
// Start observing for repo explorer specific changes
|
| 509 |
+
setTimeout(function() {
|
| 510 |
+
const repoExplorerTab = Array.from(document.querySelectorAll('.gr-tab-nav button')).find(btn =>
|
| 511 |
+
btn.textContent && btn.textContent.includes('π Repo Explorer')
|
| 512 |
+
);
|
| 513 |
+
if (repoExplorerTab) {
|
| 514 |
+
repoExplorerObserver.observe(repoExplorerTab, { attributes: true });
|
| 515 |
+
}
|
| 516 |
+
}, 1000);
|
| 517 |
});
|
| 518 |
</script>
|
| 519 |
"""
|
|
|
|
| 645 |
interactive=False
|
| 646 |
)
|
| 647 |
|
| 648 |
+
gr.Markdown("π‘ **Tip:** Full text is displayed directly in the table. Click on repository names to explore or visit them!")
|
| 649 |
|
| 650 |
+
# Text expansion modal for showing full content (kept for backwards compatibility)
|
| 651 |
with gr.Row():
|
| 652 |
with gr.Column():
|
| 653 |
text_expansion_modal = gr.Column(visible=False)
|
|
|
|
| 871 |
return final_keywords_str, status, user_requirements
|
| 872 |
|
| 873 |
def handle_dataframe_select(evt: gr.SelectData, df_data) -> Tuple[str, Any, Any, str, str, Any]:
|
| 874 |
+
"""Handle dataframe row selection - only repo ID (column 0) shows modal since full text is now displayed directly."""
|
| 875 |
print(f"DEBUG: Selection event triggered!")
|
| 876 |
print(f"DEBUG: evt = {evt}")
|
| 877 |
print(f"DEBUG: df_data type = {type(df_data)}")
|
|
|
|
| 888 |
# Handle pandas DataFrame
|
| 889 |
if isinstance(df_data, pd.DataFrame) and not df_data.empty and row_idx < len(df_data):
|
| 890 |
|
| 891 |
+
if col_idx == 0: # Repository name column - show action modal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 892 |
repo_id = df_data.iloc[row_idx, 0]
|
| 893 |
print(f"DEBUG: Extracted repo_id = '{repo_id}'")
|
| 894 |
|
|
|
|
| 897 |
logger.info(f"Showing modal for repository: {clean_repo_id}")
|
| 898 |
return clean_repo_id, gr.update(visible=True), gr.update(), "", "", gr.update(visible=False)
|
| 899 |
|
| 900 |
+
# For content columns (1,2,3) and relevance (4), do nothing since full text is shown directly
|
| 901 |
else:
|
| 902 |
+
print(f"DEBUG: Clicked on column {col_idx}, full text already shown in table")
|
| 903 |
return "", gr.update(visible=False), gr.update(), "", "", gr.update(visible=False)
|
| 904 |
else:
|
| 905 |
print(f"DEBUG: df_data is not a DataFrame or row_idx {row_idx} out of range")
|
|
|
|
| 1187 |
explore_repo_btn.click(
|
| 1188 |
fn=handle_explore_repo,
|
| 1189 |
inputs=[selected_repo_display],
|
| 1190 |
+
outputs=[repo_action_modal, tabs, repo_components["repo_explorer_input"]],
|
| 1191 |
+
js="() => { setTimeout(() => { window.scrollTo({top: 0, behavior: 'smooth'}); window.dispatchEvent(new Event('repoExplorerNavigation')); }, 150); }"
|
| 1192 |
)
|
| 1193 |
cancel_modal_btn.click(
|
| 1194 |
fn=handle_cancel_modal,
|