Skip to content

Commit 31bd281

Browse files
Add the latest version of the webpage and incread the version for the release
1 parent 8f3f955 commit 31bd281

File tree

10 files changed

+915
-69
lines changed

10 files changed

+915
-69
lines changed

mcp_nexus/mcp_nexus.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
7-
<Version>1.0.3.8</Version>
8-
<AssemblyVersion>1.0.3.8</AssemblyVersion>
9-
<FileVersion>1.0.3.8</FileVersion>
7+
<Version>1.0.4.0</Version>
8+
<AssemblyVersion>1.0.4.0</AssemblyVersion>
9+
<FileVersion>1.0.4.0</FileVersion>
1010
<Product>MCP Nexus</Product>
1111
<Description>Model Context Protocol Server for Windows Debugging Tools</Description>
1212
<Company>MCP Nexus</Company>

mcp_nexus_web/admin-api.aspx

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
case "deletefailed":
4848
HandleDeleteFailedRequest();
4949
break;
50+
case "deletejob":
51+
HandleDeleteJobRequest();
52+
break;
5053
default:
5154
Response.ContentType = "application/json";
5255
Response.Write("{\"success\": false, \"error\": \"Unknown action: " + action + "\"}");
@@ -1310,6 +1313,128 @@
13101313
}
13111314
}
13121315
1316+
void HandleDeleteJobRequest()
1317+
{
1318+
Response.ContentType = "text/plain";
1319+
string jobId = Request.QueryString["jobid"];
1320+
1321+
if (string.IsNullOrEmpty(jobId))
1322+
{
1323+
Response.Write("[ERROR] Job ID parameter is required\n");
1324+
return;
1325+
}
1326+
1327+
Response.Write("=== DELETING SPECIFIC JOB ===\n\n");
1328+
Response.Write("Job ID: " + jobId + "\n\n");
1329+
1330+
var deletedFromQueue = false;
1331+
var deletedFolderCount = 0;
1332+
string jobName = null;
1333+
1334+
try
1335+
{
1336+
// Step 1: Remove job from queue
1337+
Response.Write("Step 1: Removing job from queue...\n");
1338+
string queueFile = Server.MapPath("~/App_Data/queue.json");
1339+
1340+
if (File.Exists(queueFile))
1341+
{
1342+
string json = File.ReadAllText(queueFile);
1343+
var serializer = new JavaScriptSerializer();
1344+
var queueData = serializer.DeserializeObject(json) as Dictionary<string, object>;
1345+
1346+
if (queueData != null && queueData.ContainsKey("jobs"))
1347+
{
1348+
var jobsArray = queueData["jobs"] as object[];
1349+
if (jobsArray != null)
1350+
{
1351+
var keptJobs = new List<object>();
1352+
1353+
foreach (var job in jobsArray)
1354+
{
1355+
var jobDict = job as Dictionary<string, object>;
1356+
if (jobDict != null && jobDict.ContainsKey("id"))
1357+
{
1358+
string currentJobId = jobDict["id"].ToString();
1359+
if (currentJobId == jobId)
1360+
{
1361+
// Found the job to delete
1362+
deletedFromQueue = true;
1363+
if (jobDict.ContainsKey("name"))
1364+
{
1365+
jobName = jobDict["name"].ToString();
1366+
}
1367+
Response.Write("[OK] Found job in queue: " + jobName + "\n");
1368+
}
1369+
else
1370+
{
1371+
keptJobs.Add(job);
1372+
}
1373+
}
1374+
}
1375+
1376+
if (deletedFromQueue)
1377+
{
1378+
// Update queue with job removed
1379+
var updatedQueue = new { jobs = keptJobs.ToArray() };
1380+
File.WriteAllText(queueFile, serializer.Serialize(updatedQueue));
1381+
Response.Write("[OK] Removed job from queue\n");
1382+
}
1383+
else
1384+
{
1385+
Response.Write("[INFO] Job not found in queue\n");
1386+
}
1387+
}
1388+
}
1389+
}
1390+
else
1391+
{
1392+
Response.Write("[INFO] Queue file does not exist\n");
1393+
}
1394+
1395+
// Step 2: Delete analysis folder if we found the job name
1396+
if (!string.IsNullOrEmpty(jobName))
1397+
{
1398+
Response.Write("\nStep 2: Deleting analysis folder...\n");
1399+
string analysisDir = Server.MapPath("~/analysis");
1400+
string jobFolder = Path.Combine(analysisDir, jobName);
1401+
1402+
if (Directory.Exists(jobFolder))
1403+
{
1404+
Directory.Delete(jobFolder, true);
1405+
deletedFolderCount = 1;
1406+
Response.Write("[OK] Deleted analysis folder: " + jobName + "\n");
1407+
}
1408+
else
1409+
{
1410+
Response.Write("[INFO] Analysis folder not found: " + jobName + "\n");
1411+
}
1412+
}
1413+
else
1414+
{
1415+
Response.Write("\nStep 2: Skipping folder deletion (job name not found)\n");
1416+
}
1417+
1418+
Response.Write("\n=== DELETE JOB COMPLETE ===\n");
1419+
if (deletedFromQueue)
1420+
{
1421+
Response.Write("[SUCCESS] Job " + jobId + " deleted successfully\n");
1422+
Response.Write("[OK] Removed from queue: " + (deletedFromQueue ? "Yes" : "No") + "\n");
1423+
Response.Write("[OK] Deleted folders: " + deletedFolderCount + "\n");
1424+
Response.Write("[INFO] Refresh the main page to see the updated list\n");
1425+
}
1426+
else
1427+
{
1428+
Response.Write("[WARNING] Job " + jobId + " was not found in the queue\n");
1429+
Response.Write("[INFO] The job may have already been deleted or never existed\n");
1430+
}
1431+
}
1432+
catch (Exception ex)
1433+
{
1434+
Response.Write("[ERROR] Error deleting job: " + ex.Message + "\n");
1435+
}
1436+
}
1437+
13131438
string FormatFileSize(long bytes)
13141439
{
13151440
if (bytes == 0) return "0 B";

mcp_nexus_web/admin.html

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
<title>Admin - Crash Dump Analyzer</title>
77
<link rel="stylesheet" href="styles.css">
88
<style>
9+
/* Override body overflow for admin page */
10+
body {
11+
height: auto !important;
12+
overflow: visible !important;
13+
min-height: 100vh;
14+
}
915
/* Additional admin-specific styles */
1016
.admin-grid {
1117
display: grid;
@@ -64,6 +70,59 @@
6470
.admin-btn.danger:hover {
6571
background: #e5484d;
6672
}
73+
74+
.delete-job-section {
75+
margin-top: 16px;
76+
padding-top: 16px;
77+
border-top: 1px solid #30363d;
78+
}
79+
80+
.input-label {
81+
color: #e6edf3;
82+
font-size: 13px;
83+
font-weight: 600;
84+
margin-bottom: 8px;
85+
display: block;
86+
}
87+
88+
.input-group {
89+
display: flex;
90+
gap: 8px;
91+
align-items: stretch;
92+
}
93+
94+
.job-id-input {
95+
flex: 1;
96+
padding: 8px 12px;
97+
background: #21262d;
98+
border: 1px solid #30363d;
99+
border-radius: 6px;
100+
color: #e6edf3;
101+
font-size: 12px;
102+
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
103+
min-width: 0;
104+
}
105+
106+
.job-id-input:focus {
107+
outline: none;
108+
border-color: #58a6ff;
109+
box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2);
110+
}
111+
112+
.job-id-input::placeholder {
113+
color: #8b949e;
114+
}
115+
116+
@media (max-width: 768px) {
117+
.input-group {
118+
flex-direction: column;
119+
gap: 8px;
120+
}
121+
122+
.job-id-input {
123+
margin-bottom: 0;
124+
}
125+
}
67126

68127
.admin-btn.warning {
69128
background: #fb8500;
@@ -80,8 +139,12 @@
80139
padding: 16px;
81140
font-family: 'Consolas', 'Monaco', monospace;
82141
font-size: 12px;
142+
line-height: 1.4;
143+
color: #e6edf3;
83144
white-space: pre-wrap;
145+
word-break: break-word;
84146
max-height: 400px;
147+
min-height: 200px;
85148
overflow-y: auto;
86149
margin-top: 16px;
87150
}
@@ -138,10 +201,18 @@
138201
opacity: 0.6;
139202
}
140203

141-
/* Make System Status panel more compact */
204+
/* Make System Status panel more compact and ensure proper positioning */
142205
.panel.system-status {
143206
min-height: auto;
144207
padding: 16px;
208+
margin-bottom: 24px;
209+
position: relative;
210+
z-index: 1;
211+
}
212+
213+
.admin-grid {
214+
position: relative;
215+
z-index: 0;
145216
}
146217

147218
@media (max-width: 768px) {
@@ -173,7 +244,7 @@
173244
</div>
174245
</div>
175246

176-
<div class="layout" style="grid-template-columns: 1fr; max-width: 1200px; margin: 24px auto;">
247+
<div style="max-width: 1200px; margin: 24px auto;">
177248
<!-- System Status Overview -->
178249
<div class="panel system-status">
179250
<h2>System Status</h2>
@@ -206,7 +277,7 @@ <h2>System Status</h2>
206277
</div>
207278

208279
<!-- Admin Actions -->
209-
<div class="admin-grid">
280+
<div class="admin-grid" style="margin-top: 24px;">
210281
<div class="admin-card">
211282
<h3><span class="status-indicator online"></span>Queue Management</h3>
212283
<p>Monitor and control the analysis queue. View current jobs, restart stuck processes, and manage the processing pipeline.</p>
@@ -243,6 +314,13 @@ <h3><span class="status-indicator online"></span>Analysis List Management</h3>
243314
<button class="admin-btn warning" onclick="resetAnalysisList()">🗑️ Reset All</button>
244315
<button class="admin-btn" onclick="refreshAnalysisList()">🔄 Refresh List</button>
245316
</div>
317+
<div class="delete-job-section">
318+
<label for="jobIdInput" class="input-label">Delete Specific Job:</label>
319+
<div class="input-group">
320+
<input type="text" id="jobIdInput" class="job-id-input" placeholder="Enter Job ID (e.g., 4fa1e0f5-50c1-4439-bb06-9140ea3bd86c)" />
321+
<button class="admin-btn danger" onclick="deleteJobById()">🗑️ Delete Job</button>
322+
</div>
323+
</div>
246324
</div>
247325

248326
<div class="admin-card">
@@ -306,6 +384,44 @@ <h2>Output</h2>
306384
}
307385
}
308386

387+
async function deleteJobById() {
388+
const jobIdInput = document.getElementById('jobIdInput');
389+
const jobId = jobIdInput.value.trim();
390+
391+
if (!jobId) {
392+
alert('Please enter a Job ID');
393+
jobIdInput.focus();
394+
return;
395+
}
396+
397+
// Validate Job ID format (UUID)
398+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
399+
if (!uuidRegex.test(jobId)) {
400+
alert('Invalid Job ID format. Please enter a valid UUID (e.g., 4fa1e0f5-50c1-4439-bb06-9140ea3bd86c)');
401+
jobIdInput.focus();
402+
return;
403+
}
404+
405+
if (!confirm(`Are you sure you want to delete job "${jobId}"? This will permanently remove the job from the queue and delete its analysis files.`)) {
406+
return;
407+
}
408+
409+
showOutput(`Deleting job ${jobId}...\n`);
410+
411+
try {
412+
const response = await fetch(`admin-api.aspx?action=deletejob&jobid=${encodeURIComponent(jobId)}`);
413+
const result = await response.text();
414+
showOutput(result);
415+
416+
// Clear the input field on success
417+
if (result.includes('SUCCESS') || result.includes('deleted')) {
418+
jobIdInput.value = '';
419+
}
420+
} catch (error) {
421+
showOutput('Error deleting job: ' + error.message);
422+
}
423+
}
424+
309425
async function resetAnalysisList() {
310426
if (!confirm('Are you sure you want to reset the analysis list? This will hide all analysis folders from the main page but will not delete the actual files.')) {
311427
return;

mcp_nexus_web/analysis-list.aspx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
var files = new System.Collections.Generic.Dictionary<string, object>();
2020
2121
try {
22-
// Check for MD file (should match directory name)
23-
var mdFile = d.GetFiles(d.Name + ".md").FirstOrDefault();
22+
// Check for MD file (prefer clean naming)
23+
var mdFile = d.GetFiles("analysis.md").FirstOrDefault();
2424
if (mdFile == null) {
25-
// Fallback to analysis.md for existing files
26-
mdFile = d.GetFiles("analysis.md").FirstOrDefault();
25+
// Fallback to timestamped name for backward compatibility
26+
mdFile = d.GetFiles(d.Name + ".md").FirstOrDefault();
2727
}
2828
if (mdFile != null) {
2929
files["analysis"] = new System.Collections.Generic.Dictionary<string, object> {

0 commit comments

Comments
 (0)