cryogenic22 commited on
Commit
32485ad
·
verified ·
1 Parent(s): c574fb0

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +202 -937
index.html CHANGED
@@ -3,10 +3,13 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>DocMap Agent - R&D Accelerator</title>
 
7
  <script src="https://cdn.tailwindcss.com"></script>
 
8
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lucide-static@latest/font/Lucide.css">
9
- <script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
 
10
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
11
  <style>
12
  /* Base styles */
@@ -63,6 +66,7 @@
63
  .document-item[data-phase="Clinical (All Phases)"] { border-left-color: #7c3aed; }
64
  .document-item[data-phase="Regulatory Submission"] { border-left-color: #ec4899; }
65
  .document-item[data-phase="Post-Marketing"] { border-left-color: #f59e0b; }
 
66
 
67
  /* Tab styles for document detail modal */
68
  .details-tabs {
@@ -155,6 +159,88 @@
155
  -webkit-box-orient: vertical;
156
  overflow: hidden;
157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  </style>
159
  <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🗺️</text></svg>">
160
  </head>
@@ -165,7 +251,7 @@
165
  <span id="logo-placeholder" class="inline-block bg-white rounded-full p-1 leading-none">
166
  <i class="lucide lucide-map text-blue-700 text-2xl"></i>
167
  </span>
168
- <h1 class="text-2xl font-bold">DocMap Agent</h1>
169
  </div>
170
  <div class="flex items-center space-x-4">
171
  <button id="homeButton" class="text-white hover:text-blue-200 flex items-center text-sm">
@@ -191,8 +277,8 @@
191
 
192
  <section id="home" class="space-y-6">
193
  <div class="bg-white rounded-lg shadow p-6 text-center">
194
- <h2 class="text-2xl font-semibold text-gray-800 mb-2">Welcome to DocMap Agent</h2>
195
- <p class="text-gray-600">A comprehensive R&D document authoring accelerator</p>
196
  </div>
197
 
198
  <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
@@ -208,26 +294,26 @@
208
  <p class="text-sm text-gray-500 mb-4 flex-grow">Visualize document workflows and dependencies.</p>
209
  <button class="bg-purple-500 hover:bg-purple-600 text-white font-medium py-2 px-4 rounded-md text-sm w-full">Explore</button>
210
  </div>
211
- <div class="dashboard-card bg-white rounded-lg shadow p-6 text-center flex flex-col items-center opacity-70 cursor-not-allowed">
212
- <i class="lucide lucide-clipboard-check text-4xl text-yellow-500 mb-4"></i>
213
- <h3 class="text-lg font-semibold text-gray-700 mb-2">Assessment Tools</h3>
214
- <p class="text-sm text-gray-500 mb-4 flex-grow">Evaluate document ecosystem and identify gaps (Coming Soon).</p>
215
- <button disabled class="bg-yellow-400 text-white font-medium py-2 px-4 rounded-md text-sm w-full cursor-not-allowed">Explore</button>
216
  </div>
217
- <div class="dashboard-card bg-white rounded-lg shadow p-6 text-center flex flex-col items-center opacity-70 cursor-not-allowed">
218
- <i class="lucide lucide-file-text text-4xl text-green-500 mb-4"></i>
219
- <h3 class="text-lg font-semibold text-gray-700 mb-2">Document Blueprints</h3>
220
- <p class="text-sm text-gray-500 mb-4 flex-grow">Access templates and prompt libraries (Coming Soon).</p>
221
- <button disabled class="bg-green-400 text-white font-medium py-2 px-4 rounded-md text-sm w-full cursor-not-allowed">Explore</button>
222
  </div>
223
  </div>
224
 
225
  <div class="bg-white rounded-lg shadow p-4 mt-6">
226
  <h3 class="font-semibold text-gray-700 mb-3">Recent Updates</h3>
227
  <ul class="text-sm text-gray-600 space-y-1">
 
228
  <li><span class="text-gray-400 mr-2">[April 6, 2025]</span>Enhanced document visualization system launched.</li>
229
  <li><span class="text-gray-400 mr-2">[April 5, 2025]</span>Added IND pathway and clinical program flows.</li>
230
- <li><span class="text-gray-400 mr-2">[April 4, 2025]</span>Integrated 20 document templates into the system.</li>
231
  </ul>
232
  </div>
233
  </section>
@@ -268,6 +354,88 @@
268
  </div>
269
  </section>
270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  </main>
272
 
273
  <div id="exampleFlowModal" class="modal">
@@ -305,935 +473,32 @@
305
  <div id="loadingSpinner" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
306
  <div class="bg-white p-8 rounded-lg shadow-lg flex flex-col items-center">
307
  <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mb-4"></div>
308
- <p class="text-gray-700 font-medium">Loading DocMap Agent...</p>
309
  </div>
310
  </div>
311
 
312
  <script>
313
- // Initialize Mermaid
314
- mermaid.initialize({
315
- startOnLoad: false,
316
- theme: 'base',
317
- securityLevel: 'loose',
318
- themeVariables: {
319
- primaryColor: '#eff6ff',
320
- primaryTextColor: '#1e3a8a',
321
- primaryBorderColor: '#60a5fa',
322
- lineColor: '#6b7280',
323
- secondaryColor: '#f1f5f9',
324
- tertiaryColor: '#e0f2fe'
325
- }
326
- });
327
-
328
- // --- Global Variables ---
329
- let documentsData = [];
330
- let templateData = [];
331
- const flowDefinitions = {
332
- "p1_sad": `graph TD; subgraph Preclinical & Setup; IB(IB v1):::input --> CLI-PROT-P1(Phase 1 Protocol):::core; PRE-REP-TOX(Tox Report):::input --> IB; PRE-REP-PK(PK Report):::input --> IB; PRE-REP-CMC-STAB(Stability Report):::input --> IB; CLI-PROT-P1 --> REG-SUB-IND(IND / CTA):::output; CLI-PROT-P1 --> ICF(Informed Consent Form):::output; CLI-PROT-P1 --> CRF(eCRF Spec):::output; CLI-PROT-P1 --> CLI-PLAN-SAP(Stat Analysis Plan):::output; CLI-PROT-P1 --> CLI-PLAN-DMP(Data Mgt Plan):::output; CLI-PROT-P1 --> CLI-MAN-IMPHANDLE(IMP Handling Manual):::output; CLI-PROT-P1 --> CMC-LABEL-IMP(IMP Label Spec):::output; end; subgraph Execution & Reporting; ICF --> SiteOps[Site Operations / Enrollment]; CRF --> SiteOps; CLI-MAN-IMPHANDLE --> SiteOps; CMC-LABEL-IMP --> SiteOps; CLI-PLAN-DMP --> SiteOps; SiteOps --> ClinicalData[(Clinical Database)]; CLI-PLAN-SAP --> Analysis[Statistical Analysis]; ClinicalData --> Analysis; Analysis --> CLI-REP-CSR(Phase 1 CSR):::core; ClinicalData --> CLI-REP-CSR; IB --> CLI-REP-CSR; end; subgraph Updates & Follow-on; CLI-REP-CSR --> IB_v2(IB Update v2):::output; CLI-REP-CSR --> REG-AR(IND Annual Report / DSUR):::output; CLI-REP-CSR --> CLI-PLAN-CDP(Clinical Dev Plan Update):::output; end; classDef input fill:#f3e8ff,stroke:#a855f7,color:#581c87; classDef core fill:#e0f2fe,stroke:#38bdf8,color:#075985; classDef output fill:#f0fdf4,stroke:#4ade80,color:#15803d; click IB call displayDetailsAndGraphFromGraph("IB") "View Details"; click PRE-REP-TOX call displayDetailsAndGraphFromGraph("PRE-REP-TOX") "View Details"; click PRE-REP-PK call displayDetailsAndGraphFromGraph("PRE-REP-PK") "View Details"; click PRE-REP-CMC-STAB call displayDetailsAndGraphFromGraph("PRE-REP-CMC-STAB") "View Details"; click CLI-PROT-P1 call displayDetailsAndGraphFromGraph("CLI-PROT-P1") "View Details"; click REG-SUB-IND call displayDetailsAndGraphFromGraph("REG-SUB-IND") "View Details"; click ICF call displayDetailsAndGraphFromGraph("ICF") "View Details"; click CRF call displayDetailsAndGraphFromGraph("CRF") "View Details"; click CLI-PLAN-SAP call displayDetailsAndGraphFromGraph("CLI-PLAN-SAP") "View Details"; click CLI-PLAN-DMP call displayDetailsAndGraphFromGraph("CLI-PLAN-DMP") "View Details"; click CLI-MAN-IMPHANDLE call displayDetailsAndGraphFromGraph("CLI-MAN-IMPHANDLE") "View Details"; click CMC-LABEL-IMP call displayDetailsAndGraphFromGraph("CMC-LABEL-IMP") "View Details"; click CLI-REP-CSR call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View Details"; click IB_v2 call displayDetailsAndGraphFromGraph("IB") "View Details (Latest IB)"; click REG-AR call displayDetailsAndGraphFromGraph("REG-AR") "View Details"; click CLI-PLAN-CDP call displayDetailsAndGraphFromGraph("CLI-PLAN-CDP") "View Details";`,
333
- "nda_submission": `graph TD; subgraph Inputs; CSRs(All Phase 1-3 CSRs):::input --> REG-ISS(ISS):::core; CSRs --> REG-ISE(ISE):::core; NonClinReps(All Nonclinical Reports):::input --> REG-CTD-M2(CTD Module 2 Summaries):::core; CMCDataPkg(Full CMC Data Package):::input --> REG-CTD-M3(CTD Module 3 Quality):::core; ProposedLabel(Proposed Label / SmPC):::input --> REG-CTD-M1(CTD Module 1 Admin & Label):::core; end; subgraph CTD_Assembly; REG-ISS --> REG-CTD-M5(CTD Module 5 Clinical):::output; REG-ISE --> REG-CTD-M5; CSRs --> REG-CTD-M5; NonClinReps --> REG-CTD-M4(CTD Module 4 Nonclinical):::output; REG-CTD-M1 --> FullSubmission[eCTD Submission Package]; REG-CTD-M2 --> FullSubmission; REG-CTD-M3 --> FullSubmission; REG-CTD-M4 --> FullSubmission; REG-CTD-M5 --> FullSubmission; end; subgraph Submission_Output; FullSubmission --> REG-SUB-NDA(NDA / MAA Submission):::final; REG-SUB-NDA --> AgencyReview{Agency Review}; AgencyReview --> REG-RTQ(Responses to Questions):::input; REG-RTQ --> AgencyReview; AgencyReview --> ApprovalDecision[Approval / Rejection]; end; classDef input fill:#fef9c3,stroke:#eab308,color:#854d0e; classDef core fill:#e0f2fe,stroke:#38bdf8,color:#075985; classDef output fill:#f0fdf4,stroke:#4ade80,color:#15803d; classDef final fill:#fee2e2,stroke:#f87171,color:#991b1b; click CSRs call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View CSR Details (Example)"; click NonClinReps call displayDetailsAndGraphFromGraph("PRE-REP-TOX") "View Tox Report (Example)"; click CMCDataPkg call displayDetailsAndGraphFromGraph("PRE-REP-CMC-PROCDEV") "View CMC Report (Example)"; click ProposedLabel call displayDetailsAndGraphFromGraph("REG-LABEL-US") "View Label Details (Example)"; click REG-ISS call displayDetailsAndGraphFromGraph("REG-ISS") "View Details"; click REG-ISE call displayDetailsAndGraphFromGraph("REG-ISE") "View Details"; click REG-CTD-M1 call displayDetailsAndGraphFromGraph("REG-CTD-M1") "View Details"; click REG-CTD-M2 call displayDetailsAndGraphFromGraph("REG-CTD-M2") "View Details"; click REG-CTD-M3 call displayDetailsAndGraphFromGraph("REG-CTD-M3") "View Details"; click REG-CTD-M4 call displayDetailsAndGraphFromGraph("REG-CTD-M4") "View Details"; click REG-CTD-M5 call displayDetailsAndGraphFromGraph("REG-CTD-M5") "View Details"; click REG-SUB-NDA call displayDetailsAndGraphFromGraph("REG-SUB-NDA") "View Details"; click REG-RTQ call displayDetailsAndGraphFromGraph("REG-RTQ") "View Details";`,
334
- "ind_pathway": `graph TD;
335
- DIS-REP-TVAL(Target Validation Report):::discovery --> DIS-REP-LO(Lead Optimization Report):::discovery;
336
- DIS-REP-LO --> DIS-REP-CANDSEL(Candidate Selection Report):::discovery;
337
- DIS-REP-CANDSEL --> PRE-PLAN-DEV(Preclinical Development Plan):::preclinical;
338
- PRE-PLAN-DEV --> PRE-PROT-TOX(Toxicology Study Protocol):::preclinical;
339
- PRE-PLAN-DEV --> PRE-PROT-PK(PK Study Protocol):::preclinical;
340
- PRE-PLAN-DEV --> PRE-REP-CMC-PROCDEV(CMC Process Development):::preclinical;
341
- PRE-PROT-TOX --> PRE-REP-TOX(Toxicology Study Report):::preclinical;
342
- PRE-PROT-PK --> PRE-REP-PK(PK Study Report):::preclinical;
343
- PRE-REP-CMC-PROCDEV --> PRE-REP-CMC-STAB(Stability Report):::preclinical;
344
- PRE-REP-TOX --> IB(Investigator's Brochure):::clinical;
345
- PRE-REP-PK --> IB;
346
- PRE-REP-CMC-STAB --> IB;
347
- IB --> REG-SUB-IND(IND Submission):::regulatory;
348
- IB --> CLI-PROT-P1(Phase 1 Protocol):::clinical;
349
- CLI-PROT-P1 --> REG-SUB-IND;
350
- REG-SUB-IND --> CLI-REP-CSR(Clinical Study Reports):::clinical;
351
-
352
- classDef discovery fill:#dbeafe,stroke:#3b82f6,color:#1e40af;
353
- classDef preclinical fill:#dcfce7,stroke:#22c55e,color:#166534;
354
- classDef clinical fill:#ede9fe,stroke:#8b5cf6,color:#5b21b6;
355
- classDef regulatory fill:#fef3c7,stroke:#f59e0b,color:#92400e;
356
-
357
- click DIS-REP-TVAL call displayDetailsAndGraphFromGraph("DIS-REP-TVAL") "View Details";
358
- click DIS-REP-LO call displayDetailsAndGraphFromGraph("DIS-REP-LO") "View Details";
359
- click DIS-REP-CANDSEL call displayDetailsAndGraphFromGraph("DIS-REP-CANDSEL") "View Details";
360
- click PRE-PLAN-DEV call displayDetailsAndGraphFromGraph("PRE-PLAN-DEV") "View Details";
361
- click PRE-PROT-TOX call displayDetailsAndGraphFromGraph("PRE-PROT-TOX") "View Details";
362
- click PRE-PROT-PK call displayDetailsAndGraphFromGraph("PRE-PROT-PK") "View Details";
363
- click PRE-REP-CMC-PROCDEV call displayDetailsAndGraphFromGraph("PRE-REP-CMC-PROCDEV") "View Details";
364
- click PRE-REP-TOX call displayDetailsAndGraphFromGraph("PRE-REP-TOX") "View Details";
365
- click PRE-REP-PK call displayDetailsAndGraphFromGraph("PRE-REP-PK") "View Details";
366
- click PRE-REP-CMC-STAB call displayDetailsAndGraphFromGraph("PRE-REP-CMC-STAB") "View Details";
367
- click IB call displayDetailsAndGraphFromGraph("IB") "View Details";
368
- click CLI-PROT-P1 call displayDetailsAndGraphFromGraph("CLI-PROT-P1") "View Details";
369
- click REG-SUB-IND call displayDetailsAndGraphFromGraph("REG-SUB-IND") "View Details";
370
- click CLI-REP-CSR call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View Details";`,
371
- "clinical_program": `graph TD;
372
- CLI-PLAN-TPP(Target Product Profile):::planning --> CLI-PLAN-CDP(Clinical Development Plan):::planning;
373
- CLI-PLAN-CDP --> CLI-PROT-P1(Phase 1 Protocol):::phase1;
374
- CLI-PLAN-CDP --> CLI-PROT-P2(Phase 2 Protocol):::phase2;
375
- CLI-PLAN-CDP --> CLI-PROT-P3(Phase 3 Protocol):::phase3;
376
- CLI-PROT-P1 --> ICF1(Phase 1 ICF):::phase1;
377
- CLI-PROT-P1 --> CRF1(Phase 1 CRF):::phase1;
378
- CLI-PROT-P1 --> CLI-PLAN-SAP1(Phase 1 SAP):::phase1;
379
- CLI-PROT-P2 --> ICF2(Phase 2 ICF):::phase2;
380
- CLI-PROT-P2 --> CRF2(Phase 2 CRF):::phase2;
381
- CLI-PROT-P2 --> CLI-PLAN-SAP2(Phase 2 SAP):::phase2;
382
- CLI-PROT-P3 --> ICF3(Phase 3 ICF):::phase3;
383
- CLI-PROT-P3 --> CRF3(Phase 3 CRF):::phase3;
384
- CLI-PROT-P3 --> CLI-PLAN-SAP3(Phase 3 SAP):::phase3;
385
- CLI-PROT-P3 --> CLI-CHARTER-DMC(DMC Charter):::phase3;
386
- CLI-PLAN-SAP1 --> CLI-REP-CSR1(Phase 1 CSR):::phase1;
387
- CLI-PLAN-SAP2 --> CLI-REP-CSR2(Phase 2 CSR):::phase2;
388
- CLI-PLAN-SAP3 --> CLI-REP-CSR3(Phase 3 CSR):::phase3;
389
- CLI-REP-CSR1 & CLI-REP-CSR2 & CLI-REP-CSR3 --> REG-ISS(Integrated Summary of Safety):::submission;
390
- CLI-REP-CSR2 & CLI-REP-CSR3 --> REG-ISE(Integrated Summary of Efficacy):::submission;
391
- REG-ISS & REG-ISE --> REG-SUB-NDA(NDA Submission):::submission;
392
-
393
- classDef planning fill:#dbeafe,stroke:#3b82f6,color:#1e40af;
394
- classDef phase1 fill:#ede9fe,stroke:#8b5cf6,color:#5b21b6;
395
- classDef phase2 fill:#fae8ff,stroke:#d946ef,color:#86198f;
396
- classDef phase3 fill:#fce7f3,stroke:#ec4899,color:#9d174d;
397
- classDef submission fill:#fee2e2,stroke:#f87171,color:#991b1b;
398
-
399
- click CLI-PLAN-TPP call displayDetailsAndGraphFromGraph("CLI-PLAN-TPP") "View Details";
400
- click CLI-PLAN-CDP call displayDetailsAndGraphFromGraph("CLI-PLAN-CDP") "View Details";
401
- click CLI-PROT-P1 call displayDetailsAndGraphFromGraph("CLI-PROT-P1") "View Details";
402
- click CLI-PROT-P2 call displayDetailsAndGraphFromGraph("CLI-PROT-P2") "View Details";
403
- click CLI-PROT-P3 call displayDetailsAndGraphFromGraph("CLI-PROT-P3") "View Details";
404
- click ICF1 call displayDetailsAndGraphFromGraph("ICF") "View Details";
405
- click CRF1 call displayDetailsAndGraphFromGraph("CRF") "View Details";
406
- click CLI-PLAN-SAP1 call displayDetailsAndGraphFromGraph("CLI-PLAN-SAP") "View Details";
407
- click ICF2 call displayDetailsAndGraphFromGraph("ICF") "View Details";
408
- click CRF2 call displayDetailsAndGraphFromGraph("CRF") "View Details";
409
- click CLI-PLAN-SAP2 call displayDetailsAndGraphFromGraph("CLI-PLAN-SAP") "View Details";
410
- click ICF3 call displayDetailsAndGraphFromGraph("ICF") "View Details";
411
- click CRF3 call displayDetailsAndGraphFromGraph("CRF") "View Details";
412
- click CLI-PLAN-SAP3 call displayDetailsAndGraphFromGraph("CLI-PLAN-SAP") "View Details";
413
- click CLI-CHARTER-DMC call displayDetailsAndGraphFromGraph("CLI-CHARTER-DMC") "View Details";
414
- click CLI-REP-CSR1 call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View Details";
415
- click CLI-REP-CSR2 call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View Details";
416
- click CLI-REP-CSR3 call displayDetailsAndGraphFromGraph("CLI-REP-CSR") "View Details";
417
- click REG-ISS call displayDetailsAndGraphFromGraph("REG-ISS") "View Details";
418
- click REG-ISE call displayDetailsAndGraphFromGraph("REG-ISE") "View Details";
419
- click REG-SUB-NDA call displayDetailsAndGraphFromGraph("REG-SUB-NDA") "View Details";`
420
- };
421
-
422
- // --- DOM Elements Cache ---
423
- const mainContentArea = document.getElementById('mainContentArea');
424
- const homeSection = document.getElementById('home');
425
- const documentViewWrapper = document.getElementById('documentViewWrapper');
426
- const flowsViewWrapper = document.getElementById('flowsViewWrapper');
427
-
428
- const searchInputDocView = document.getElementById('searchInputDocView');
429
- const headerSearchInput = document.getElementById('headerSearchInput');
430
- const mainTabsDocViewContainer = document.getElementById('mainTabsDocView');
431
- const documentListDocViewContainer = document.getElementById('documentListDocView');
432
-
433
- const flowsListContainer = document.getElementById('flowsList');
434
- const mermaidFlowGraphContainer = document.getElementById('mermaidFlowGraph');
435
- const flowPlaceholder = document.getElementById('flowPlaceholder');
436
- const showExampleFlowBtnFlowView = document.getElementById('showExampleFlowBtnFlowView');
437
-
438
- const homeButton = document.getElementById('homeButton');
439
- const breadcrumbNav = document.getElementById('breadcrumbNav');
440
-
441
- // Modals
442
- const showExampleFlowBtnHeader = document.getElementById('showExampleFlowBtn');
443
- const exampleFlowModal = document.getElementById('exampleFlowModal');
444
- const exampleMermaidGraphContainer = document.getElementById('exampleMermaidGraph');
445
- const closeExampleModalBtn = document.getElementById('closeExampleModalBtn');
446
- const detailsModal = document.getElementById('detailsModal');
447
- const detailsModalTitle = document.getElementById('detailsModalTitle');
448
- const detailsContentInModal = document.getElementById('detailsContentInModal');
449
- const closeDetailsModalBtn = document.getElementById('closeDetailsModalBtn');
450
- const prevDocBtn = document.getElementById('prevDocBtn');
451
- const nextDocBtn = document.getElementById('nextDocBtn');
452
- const loadingSpinner = document.getElementById('loadingSpinner');
453
-
454
- // --- State Variables ---
455
- let currentVisibleView = 'home';
456
- let currentDocViewTab = 'All';
457
- let currentSelectedDocId = null;
458
- let currentSelectedFlowId = null;
459
- let currentDocListIndices = { prev: null, next: null };
460
-
461
- // --- Utility Functions ---
462
- function getDocNameById(docId) {
463
- const doc = documentsData.find(d => d.Doc_ID_Type === docId);
464
- return doc ? (doc.Document_Name.split('(')[0].trim() || doc.Document_Name) : docId;
465
- }
466
-
467
- function extractDocIDs(text) {
468
- if (!text || documentsData.length === 0) return [];
469
- const knownIDs = new Set(documentsData.map(doc => doc.Doc_ID_Type));
470
- const potentialIDs = text.match(/[A-Z0-9]+(?:-[A-Z0-9]+)*\b/g) || [];
471
- return potentialIDs.filter(id => knownIDs.has(id));
472
- }
473
-
474
- function getComplexityIcon(complexity) {
475
- switch (complexity?.toLowerCase()) {
476
- case 'low': return '<i class="lucide lucide-bar-chart text-green-500" title="Low Complexity"></i>';
477
- case 'low-medium': return '<i class="lucide lucide-bar-chart-2 text-lime-500" title="Low-Medium Complexity"></i>';
478
- case 'medium': return '<i class="lucide lucide-bar-chart-3 text-yellow-500" title="Medium Complexity"></i>';
479
- case 'medium-high': return '<i class="lucide lucide-bar-chart-4 text-orange-500" title="Medium-High Complexity"></i>';
480
- case 'high': return '<i class="lucide lucide-bar-chart-big text-red-500" title="High Complexity"></i>';
481
- default: return '';
482
- }
483
- }
484
-
485
- function getRegulatoryIcon(significance) {
486
- if (!significance) return '';
487
- const lowerSig = significance.toLowerCase();
488
- if (lowerSig.includes('submission critical')) return '<i class="lucide lucide-shield-check text-red-600" title="Submission Critical"></i>';
489
- if (lowerSig.includes('gcp')) return '<i class="lucide lucide-clipboard-check text-blue-600" title="GCP Relevant"></i>';
490
- if (lowerSig.includes('glp')) return '<i class="lucide lucide-flask-conical text-purple-600" title="GLP Relevant"></i>';
491
- if (lowerSig.includes('gmp')) return '<i class="lucide lucide-factory text-indigo-600" title="GMP Relevant"></i>';
492
- if (lowerSig.includes('gvp')) return '<i class="lucide lucide-activity text-teal-600" title="GVP Relevant"></i>';
493
- if (lowerSig.includes('regulatory requirement')) return '<i class="lucide lucide-shield-alert text-orange-600" title="Regulatory Requirement"></i>';
494
- if (lowerSig.includes('internal')) return '<i class="lucide lucide-home text-gray-500" title="Internal Governance/Strategy"></i>';
495
- return '<i class="lucide lucide-shield text-gray-400" title="Regulatory Significance"></i>';
496
- }
497
-
498
- function getMainTabIcon(tabName) {
499
- if (!tabName) return '<i class="lucide lucide-file-question"></i>';
500
- const lowerTab = tabName.toLowerCase();
501
- if (lowerTab.includes('discovery')) return '<i class="lucide lucide-search"></i>';
502
- if (lowerTab.includes('preclinical')) return '<i class="lucide lucide-flask-conical"></i>';
503
- if (lowerTab === 'clinical development') return '<i class="lucide lucide-users"></i>';
504
- if (lowerTab === 'regulatory submission') return '<i class="lucide lucide-file-check-2"></i>';
505
- if (lowerTab === 'post-marketing & quality') return '<i class="lucide lucide-recycle"></i>';
506
- if (lowerTab.includes('flows')) return '<i class="lucide lucide-git-fork"></i>';
507
- if (lowerTab.includes('all')) return '<i class="lucide lucide-layers"></i>';
508
- return '<i class="lucide lucide-folder-open"></i>';
509
- }
510
-
511
- function linkDocumentIDsForDetails(text) {
512
- if (!text || documentsData.length === 0) return 'N/A';
513
- const knownIDs = new Set(documentsData.map(doc => doc.Doc_ID_Type));
514
- let linkedText = text.replace(/(\b[A-Z0-9]+(?:-[A-Z0-9]+)*\b)/g, (match) => {
515
- if (knownIDs.has(match)) {
516
- return `<span class="doc-link" data-doc-id="${match}">${match}</span>`;
517
- }
518
- return match;
519
- });
520
- return linkedText;
521
- }
522
-
523
- // --- Core Rendering & View Switching ---
524
- function switchToView(viewId, initialTab = null) {
525
- console.log(`Switching view to: ${viewId}, Initial Tab: ${initialTab}`);
526
- currentVisibleView = viewId;
527
-
528
- // Hide all main sections
529
- homeSection.classList.add('hidden-container');
530
- documentViewWrapper.classList.add('hidden-container');
531
- flowsViewWrapper.classList.add('hidden-container');
532
-
533
- // Show the target section
534
- const targetSection = document.getElementById(viewId);
535
- if (targetSection) {
536
- targetSection.classList.remove('hidden-container');
537
-
538
- // Handle specific view initializations
539
- if (viewId === 'documentViewWrapper') {
540
- currentDocViewTab = initialTab || 'All';
541
- renderDocumentViewTabs();
542
- renderDocumentList();
543
- } else if (viewId === 'flowsViewWrapper') {
544
- renderFlowsList();
545
- mermaidFlowGraphContainer.innerHTML = '';
546
- flowPlaceholder.style.display = 'block';
547
- currentSelectedFlowId = null;
548
- } else {
549
- currentDocViewTab = 'All';
550
- }
551
- } else {
552
- console.error(`Target view section not found: ${viewId}. Defaulting to home.`);
553
- homeSection.classList.remove('hidden-container');
554
- currentVisibleView = 'home';
555
- }
556
- updateBreadcrumb();
557
- clearSelection();
558
- }
559
-
560
- function updateBreadcrumb() {
561
- breadcrumbNav.innerHTML = '';
562
- const homeLink = `<a href="#" data-view-target="home" class="text-blue-600 hover:underline">Home</a>`;
563
-
564
- if (currentVisibleView === 'home') {
565
- breadcrumbNav.innerHTML = `<span class="text-gray-500">Home</span>`;
566
- } else if (currentVisibleView === 'documentViewWrapper') {
567
- breadcrumbNav.innerHTML = `${homeLink} <span class="mx-2 text-gray-400">/</span> <span class="text-gray-500">Document Catalog (${currentDocViewTab})</span>`;
568
- } else if (currentVisibleView === 'flowsViewWrapper') {
569
- breadcrumbNav.innerHTML = `${homeLink} <span class="mx-2 text-gray-400">/</span> <span class="text-gray-500">Process Visualization</span>`;
570
- }
571
- }
572
-
573
- function renderDocumentViewTabs() {
574
- const phaseMap = {
575
- 'Discovery': 'Discovery', 'Preclinical': 'Preclinical',
576
- 'Clinical Phase 1': 'Clinical Development', 'Clinical Phase 2': 'Clinical Development', 'Clinical Phase 3': 'Clinical Development', 'Clinical (All Phases)': 'Clinical Development',
577
- 'Regulatory Submission': 'Regulatory Submission', 'Regulatory Submission Review Phase': 'Regulatory Submission',
578
- 'Post-Marketing': 'Post-Marketing & Quality', 'All Phases': 'Post-Marketing & Quality',
579
- 'Discovery, Preclinical': 'Discovery', 'Preclinical, Clinical': 'Preclinical',
580
- 'Preclinical (End), Clinical Phase 1': 'Preclinical', 'Discovery (late), Preclinical, Clinical': 'Discovery',
581
- 'Pre/Post-Approval':'Regulatory Submission', 'Clinical (Annual)': 'Clinical Development',
582
- 'Preclinical / Clinical':'Preclinical', 'Clinical (Early Phase 2/End of Phase 2)': 'Clinical Development'
583
- };
584
- const uniquePhases = [...new Set(documentsData.map(doc => phaseMap[doc.Phase] || 'Other'))];
585
- const tabOrder = ['All', 'Discovery', 'Preclinical', 'Clinical Development', 'Regulatory Submission', 'Post-Marketing & Quality', 'Other'];
586
- const sortedTabs = tabOrder.filter(tab => uniquePhases.includes(tab) || tab === 'All');
587
- uniquePhases.forEach(phase => { if (!sortedTabs.includes(phase)) sortedTabs.push(phase); });
588
-
589
- let tabsHtml = '';
590
- sortedTabs.forEach(tabName => {
591
- const isActive = tabName === currentDocViewTab;
592
- tabsHtml += `
593
- <button
594
- data-tab-name="${tabName}"
595
- class="main-tab doc-view-tab px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700 focus:outline-none whitespace-nowrap ${isActive ? 'active' : ''}"
596
- >
597
- ${getMainTabIcon(tabName)} ${tabName}
598
- </button>
599
- `;
600
- });
601
- mainTabsDocViewContainer.innerHTML = tabsHtml;
602
-
603
- // Add event listeners to THESE tabs
604
- mainTabsDocViewContainer.querySelectorAll('.doc-view-tab').forEach(tab => {
605
- tab.addEventListener('click', () => {
606
- currentDocViewTab = tab.dataset.tabName;
607
- renderDocumentViewTabs();
608
- renderDocumentList();
609
- updateBreadcrumb();
610
- clearSelection();
611
- });
612
- });
613
- }
614
-
615
- function renderDocumentList() {
616
- if (currentVisibleView !== 'documentViewWrapper') return;
617
-
618
- const phaseMap = {
619
- 'Discovery': 'Discovery', 'Preclinical': 'Preclinical',
620
- 'Clinical Phase 1': 'Clinical Development', 'Clinical Phase 2': 'Clinical Development', 'Clinical Phase 3': 'Clinical Development', 'Clinical (All Phases)': 'Clinical Development',
621
- 'Regulatory Submission': 'Regulatory Submission', 'Regulatory Submission Review Phase': 'Regulatory Submission',
622
- 'Post-Marketing': 'Post-Marketing & Quality', 'All Phases': 'Post-Marketing & Quality',
623
- 'Discovery, Preclinical': 'Discovery', 'Preclinical, Clinical': 'Preclinical',
624
- 'Preclinical (End), Clinical Phase 1': 'Preclinical', 'Discovery (late), Preclinical, Clinical': 'Discovery',
625
- 'Pre/Post-Approval':'Regulatory Submission', 'Clinical (Annual)': 'Clinical Development',
626
- 'Preclinical / Clinical':'Preclinical', 'Clinical (Early Phase 2/End of Phase 2)': 'Clinical Development'
627
- };
628
-
629
- const searchTerm = searchInputDocView.value.toLowerCase();
630
- let filteredDocs = documentsData;
631
-
632
- // Apply phase filter based on currentDocViewTab
633
- if (currentDocViewTab !== 'All') {
634
- filteredDocs = filteredDocs.filter(doc => {
635
- const primaryPhase = phaseMap[doc.Phase] || 'Other';
636
- return primaryPhase === currentDocViewTab;
637
- });
638
- }
639
-
640
- // Apply search filter
641
- if (searchTerm) {
642
- filteredDocs = filteredDocs.filter(doc =>
643
- doc.Document_Name.toLowerCase().includes(searchTerm) ||
644
- doc.Doc_ID_Type.toLowerCase().includes(searchTerm) ||
645
- (doc.Sub_Phase_Discipline && doc.Sub_Phase_Discipline.toLowerCase().includes(searchTerm)) ||
646
- (doc.Purpose_Key_Content && doc.Purpose_Key_Content.toLowerCase().includes(searchTerm)) ||
647
- (doc["Authoring_Department(s)"] && doc["Authoring_Department(s)"].toLowerCase().includes(searchTerm)) ||
648
- (doc.Key_Metadata && doc.Key_Metadata.toLowerCase().includes(searchTerm))
649
- );
650
- }
651
-
652
- // Render logic with enhanced styling
653
- let listHtml = '';
654
- if (filteredDocs.length === 0) {
655
- listHtml = `<p class="text-gray-500 text-center py-4">No documents found ${searchTerm ? 'matching search in' : 'for'} ${currentDocViewTab === 'All' ? 'any phase' : currentDocViewTab}.</p>`;
656
- } else {
657
- const sortedDocs = filteredDocs.sort((a, b) => a.Document_Name.localeCompare(b.Document_Name));
658
- listHtml = '<ul class="divide-y divide-gray-200">';
659
- sortedDocs.forEach(doc => {
660
- const isSelected = doc.Doc_ID_Type === currentSelectedDocId;
661
- listHtml += `
662
- <li data-doc-id="${doc.Doc_ID_Type}" data-phase="${doc.Phase}" class="document-item doc-list-item px-3 py-3 hover:bg-blue-50 cursor-pointer text-sm flex justify-between items-start ${isSelected ? 'bg-blue-100 font-semibold' : ''}">
663
- <div class="flex flex-col min-w-0 pr-2">
664
- <div class="flex items-center">
665
- <i class="lucide lucide-file-text text-blue-500 mr-2 flex-shrink-0"></i>
666
- <span class="font-medium truncate" title="${doc.Document_Name}">${doc.Document_Name}</span>
667
- </div>
668
- <div class="text-xs text-gray-500 mt-1 ml-6">
669
- <span class="mr-2">${doc.Doc_ID_Type}</span> •
670
- <span class="mx-2">${doc.Phase || 'N/A'}</span> •
671
- <span class="mx-2">${doc.Sub_Phase_Discipline || 'N/A'}</span>
672
- </div>
673
- <div class="text-xs text-gray-600 mt-1 ml-6 line-clamp-2" title="${doc.Purpose_Key_Content || 'No description available'}">
674
- ${doc.Purpose_Key_Content || 'No description available'}
675
- </div>
676
- </div>
677
- <div class="flex items-center space-x-1 flex-shrink-0">
678
- ${getComplexityIcon(doc.Complexity_Authoring)}
679
- ${getRegulatoryIcon(doc.Regulatory_Significance)}
680
- </div>
681
- </li>`;
682
- });
683
- listHtml += '</ul>';
684
- }
685
-
686
- if(documentListDocViewContainer) {
687
- documentListDocViewContainer.innerHTML = listHtml;
688
- } else {
689
- console.error("documentListDocViewContainer element not found!");
690
- return;
691
- }
692
-
693
- // Add event listeners for items in THIS list
694
- document.querySelectorAll('#documentListDocView li.doc-list-item').forEach(item => {
695
- item.addEventListener('click', () => {
696
- currentSelectedDocId = item.dataset.docId;
697
- displayDetailsInModal(currentSelectedDocId);
698
- renderDocumentList();
699
- });
700
- });
701
- }
702
-
703
- function findNextPrevDocs(currentId) {
704
- const listItems = documentListDocViewContainer.querySelectorAll('li[data-doc-id]');
705
- const docIds = Array.from(listItems).map(li => li.dataset.docId);
706
- const currentIndex = docIds.indexOf(currentId);
707
-
708
- if (currentIndex === -1 || docIds.length <= 1) {
709
- return { prev: null, next: null };
710
- }
711
- const prevIndex = currentIndex > 0 ? currentIndex - 1 : docIds.length - 1;
712
- const nextIndex = currentIndex < docIds.length - 1 ? currentIndex + 1 : 0;
713
-
714
- return {
715
- prev: docIds[prevIndex],
716
- next: docIds[nextIndex]
717
- };
718
- }
719
-
720
- async function displayDetailsInModal(docId) {
721
- const doc = documentsData.find(d => d.Doc_ID_Type === docId);
722
- if (!doc) return;
723
-
724
- currentSelectedDocId = docId;
725
- detailsModalTitle.textContent = `${doc.Document_Name} (${doc.Doc_ID_Type})`;
726
-
727
- // Create tabs for different views
728
- const tabsHtml = `
729
- <div class="details-tabs mb-4">
730
- <div class="details-tab active" data-tab="info">Information</div>
731
- <div class="details-tab" data-tab="dependencies">Dependencies</div>
732
- </div>
733
- `;
734
-
735
- // Create content sections
736
- const infoHtml = `
737
- <div class="details-content active" id="tab-content-info">
738
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
739
- <div>
740
- <div class="mb-3">
741
- <span class="text-sm font-medium text-gray-600">Phase:</span>
742
- <span class="ml-2 text-sm px-2 py-1 bg-blue-100 text-blue-800 rounded-full">${doc.Phase || 'N/A'}</span>
743
- </div>
744
- <div class="mb-3">
745
- <span class="text-sm font-medium text-gray-600">Discipline:</span>
746
- <span class="ml-2">${doc.Sub_Phase_Discipline || 'N/A'}</span>
747
- </div>
748
- <div class="mb-3">
749
- <span class="text-sm font-medium text-gray-600">Authoring Department(s):</span>
750
- <span class="ml-2">${doc['Authoring_Department(s)'] || 'N/A'}</span>
751
- </div>
752
- <div class="mb-3">
753
- <span class="text-sm font-medium text-gray-600">Review/Approval Dept(s):</span>
754
- <span class="ml-2">${doc['Review_Approval_Dept(s)'] || 'N/A'}</span>
755
- </div>
756
- <div class="mb-3 flex items-center">
757
- <span class="text-sm font-medium text-gray-600">Complexity:</span>
758
- <span class="ml-2 flex items-center">${getComplexityIcon(doc.Complexity_Authoring)} ${doc.Complexity_Authoring || 'N/A'}</span>
759
- </div>
760
- <div class="mb-3 flex items-center">
761
- <span class="text-sm font-medium text-gray-600">Regulatory Significance:</span>
762
- <span class="ml-2 flex items-center">${getRegulatoryIcon(doc.Regulatory_Significance)} ${doc.Regulatory_Significance || 'N/A'}</span>
763
- </div>
764
- </div>
765
- <div>
766
- <div class="mb-3">
767
- <div class="text-sm font-medium text-gray-600 mb-1">Purpose / Key Content:</div>
768
- <div class="bg-gray-50 p-3 rounded text-sm max-h-28 overflow-y-auto custom-scroll">${doc.Purpose_Key_Content || 'N/A'}</div>
769
- </div>
770
- <div class="mb-3">
771
- <div class="text-sm font-medium text-gray-600 mb-1">Key Metadata:</div>
772
- <div class="bg-gray-50 p-3 rounded text-sm">${doc.Key_Metadata || 'N/A'}</div>
773
- </div>
774
- </div>
775
- </div>
776
- <div class="mt-4">
777
- <div class="text-sm font-medium text-gray-600 mb-1">Input Docs/Data:</div>
778
- <div class="bg-gray-50 p-3 rounded text-sm">${linkDocumentIDsForDetails(doc.Input_Documents_Data_Sources) || 'N/A'}</div>
779
- </div>
780
- <div class="mt-4">
781
- <div class="text-sm font-medium text-gray-600 mb-1">Output/Informs Docs:</div>
782
- <div class="bg-gray-50 p-3 rounded text-sm">${linkDocumentIDsForDetails(doc.Output_Informs_Documents) || 'N/A'}</div>
783
- </div>
784
- </div>
785
- `;
786
-
787
- const dependenciesHtml = `
788
- <div class="details-content" id="tab-content-dependencies">
789
- <div id="document-graph-container" class="dependency-graph mt-3"></div>
790
- </div>
791
- `;
792
-
793
- // Combine all content
794
- detailsContentInModal.innerHTML = tabsHtml + infoHtml + dependenciesHtml;
795
-
796
- // Add tab switching functionality
797
- detailsContentInModal.querySelectorAll('.details-tab').forEach(tab => {
798
- tab.addEventListener('click', () => {
799
- // Update active tab
800
- detailsContentInModal.querySelectorAll('.details-tab').forEach(t => t.classList.remove('active'));
801
- tab.classList.add('active');
802
-
803
- // Show corresponding content
804
- const tabId = tab.dataset.tab;
805
- detailsContentInModal.querySelectorAll('.details-content').forEach(c => c.classList.remove('active'));
806
- document.getElementById(`tab-content-${tabId}`).classList.add('active');
807
-
808
- // If dependencies tab, render the graph
809
- if (tabId === 'dependencies') {
810
- renderDependencyGraph(docId);
811
- }
812
- });
813
- });
814
-
815
- // Add event listeners to document links within the modal
816
- detailsContentInModal.querySelectorAll('.doc-link').forEach(link => {
817
- link.addEventListener('click', (e) => {
818
- displayDetailsInModal(e.target.dataset.docId);
819
- // Optionally update the main list highlight if visible
820
- if (currentVisibleView === 'documentViewWrapper') {
821
- renderDocumentList();
822
- }
823
- });
824
- });
825
-
826
- // Setup Next/Prev Buttons
827
- currentDocListIndices = findNextPrevDocs(docId);
828
- prevDocBtn.disabled = !currentDocListIndices.prev;
829
- nextDocBtn.disabled = !currentDocListIndices.next;
830
-
831
- // Show Modal
832
- detailsModal.style.display = 'flex';
833
-
834
- // Only re-render list if doc view is active
835
- if (currentVisibleView === 'documentViewWrapper') {
836
- renderDocumentList();
837
- }
838
- }
839
-
840
- // New function to render dependency graph using Mermaid
841
- async function renderDependencyGraph(docId) {
842
- const doc = documentsData.find(d => d.Doc_ID_Type === docId);
843
- if (!doc) return;
844
-
845
- const container = document.getElementById('document-graph-container');
846
- if (!container) return;
847
-
848
- // Show loading spinner
849
- container.innerHTML = '<div class="loading-spinner"></div>';
850
-
851
- const inputIDs = extractDocIDs(doc.Input_Documents_Data_Sources);
852
- const outputIDs = extractDocIDs(doc.Output_Informs_Documents);
853
-
854
- let mermaidDefinition = 'graph TD;\n';
855
- const centerNodeName = getDocNameById(doc.Doc_ID_Type);
856
-
857
- // Define center node with improved styling
858
- mermaidDefinition += ` ${doc.Doc_ID_Type}("${centerNodeName}\\n(${doc.Doc_ID_Type})"):::focus;\n`;
859
-
860
- // Define input nodes and connections
861
- inputIDs.forEach(inputId => {
862
- const inputNodeName = getDocNameById(inputId);
863
- mermaidDefinition += ` ${inputId}("${inputNodeName}\\n(${inputId})"):::input --> ${doc.Doc_ID_Type};\n`;
864
- });
865
-
866
- // Define output nodes and connections
867
- outputIDs.forEach(outputId => {
868
- const outputNodeName = getDocNameById(outputId);
869
- mermaidDefinition += ` ${doc.Doc_ID_Type} --> ${outputId}("${outputNodeName}\\n(${outputId})"):::output;\n`;
870
- });
871
-
872
- // Add class definitions for better styling
873
- mermaidDefinition += ` classDef focus fill:#e0f2fe,stroke:#38bdf8,stroke-width:2px,color:#075985;\n`;
874
- mermaidDefinition += ` classDef input fill:#f1f5f9,stroke:#94a3b8,color:#334155;\n`;
875
- mermaidDefinition += ` classDef output fill:#f1f5f9,stroke:#94a3b8,color:#334155;\n`;
876
-
877
- // Add click handlers for all nodes
878
- [doc.Doc_ID_Type, ...inputIDs, ...outputIDs].forEach(id => {
879
- mermaidDefinition += ` click ${id} call displayDetailsAndGraphFromModal("${id}") "View Details";\n`;
880
- });
881
-
882
- try {
883
- const graphId = `mermaid-modal-graph-${docId}-${Date.now()}`;
884
- const { svg } = await mermaid.render(graphId, mermaidDefinition);
885
- container.innerHTML = svg;
886
-
887
- // Make the SVG responsive
888
- const svgElement = container.querySelector('svg');
889
- if (svgElement) {
890
- svgElement.setAttribute('width', '100%');
891
- svgElement.setAttribute('height', '100%');
892
- svgElement.style.maxHeight = '400px';
893
  }
894
- } catch (error) {
895
- console.error("Mermaid rendering error:", error);
896
- container.innerHTML = `
897
- <div class="text-center text-red-500 py-4">
898
- <i class="lucide lucide-alert-triangle text-2xl mb-2"></i>
899
- <p>Failed to render dependency graph.</p>
900
- </div>
901
- `;
902
- }
903
- }
904
-
905
- // Callbacks from Mermaid graphs
906
- window.displayDetailsAndGraphFromGraph = async (docId) => {
907
- console.log("Graph node clicked (main flow or example):", docId);
908
- await displayDetailsInModal(docId);
909
- setTimeout(() => {
910
- // If the doc list view is active, scroll the item into view
911
- if (currentVisibleView === 'documentViewWrapper') {
912
- const listItem = document.querySelector(`#documentListDocView li[data-doc-id="${docId}"]`);
913
- listItem?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
914
- }
915
- }, 100);
916
- };
917
-
918
- window.displayDetailsAndGraphFromModal = async (docId) => {
919
- console.log("Modal graph node clicked:", docId);
920
- await displayDetailsInModal(docId);
921
- setTimeout(() => {
922
- if (currentVisibleView === 'documentViewWrapper') {
923
- const listItem = document.querySelector(`#documentListDocView li[data-doc-id="${docId}"]`);
924
- listItem?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
925
- }
926
- }, 100);
927
- };
928
-
929
- function clearSelection() {
930
- currentSelectedDocId = null;
931
- if (currentVisibleView === 'documentViewWrapper') {
932
- renderDocumentList();
933
- }
934
- }
935
-
936
- // Enhance flow list rendering with better UI
937
- function renderFlowsList() {
938
- const flowDisplayTitles = {
939
- "p1_sad": "Phase 1 SAD Study Documents",
940
- "nda_submission": "NDA/MAA Submission Process",
941
- "ind_pathway": "IND Pathway Documents",
942
- "clinical_program": "Clinical Program Development"
943
- };
944
-
945
- let flowsHtml = `
946
- <div class="mb-4">
947
- <h3 class="text-lg font-semibold text-gray-700 mb-2">Document Workflows</h3>
948
- <p class="text-sm text-gray-500 mb-4">Select a flow to visualize document relationships and dependencies in typical R&D processes.</p>
949
- </div>
950
- `;
951
-
952
- Object.keys(flowDefinitions).forEach(id => {
953
- const title = flowDisplayTitles[id] || `Flow ${id}`;
954
- const isSelected = id === currentSelectedFlowId;
955
-
956
- flowsHtml += `
957
- <div class="flow-card ${isSelected ? 'active' : ''}" data-flow-id="${id}">
958
- <div class="flex items-center justify-between">
959
- <div class="flex items-center">
960
- <i class="lucide lucide-git-branch text-purple-500 mr-2"></i>
961
- <span class="font-medium">${title}</span>
962
- </div>
963
- <i class="lucide lucide-chevron-right text-gray-400"></i>
964
- </div>
965
- <p class="text-xs text-gray-500 mt-1 ml-6">
966
- ${id === 'p1_sad' ? 'Documents required for First-in-Human studies' :
967
- id === 'nda_submission' ? 'Regulatory submission package assembly' :
968
- id === 'ind_pathway' ? 'Discovery to IND enabling documents' :
969
- id === 'clinical_program' ? 'Clinical phase documentation flow' :
970
- 'Document workflow visualization'}
971
- </p>
972
- </div>
973
- `;
974
  });
975
-
976
- flowsListContainer.innerHTML = flowsHtml;
977
-
978
- // Add event listeners
979
- flowsListContainer.querySelectorAll('.flow-card').forEach(card => {
980
- card.addEventListener('click', () => {
981
- const flowId = card.dataset.flowId;
982
- currentSelectedFlowId = flowId;
983
- displayFlowGraph(flowId);
984
- renderFlowsList(); // Update active state
985
- });
986
- });
987
- }
988
-
989
- // Enhanced flow graph display
990
- async function displayFlowGraph(flowId) {
991
- const definition = flowDefinitions[flowId];
992
- if (!definition) {
993
- mermaidFlowGraphContainer.innerHTML = `
994
- <div class="flex flex-col items-center justify-center p-10 text-gray-500">
995
- <i class="lucide lucide-alert-circle text-3xl mb-3"></i>
996
- <p>Flow definition not found.</p>
997
- </div>
998
- `;
999
- flowPlaceholder.style.display = 'none';
1000
- return;
1001
- }
1002
-
1003
- // Show loading indicator
1004
- mermaidFlowGraphContainer.innerHTML = `
1005
- <div class="flex flex-col items-center justify-center p-10">
1006
- <div class="loading-spinner"></div>
1007
- <p class="text-gray-500 mt-4">Rendering flow graph...</p>
1008
- </div>
1009
- `;
1010
- flowPlaceholder.style.display = 'none';
1011
-
1012
- try {
1013
- if (flowsViewWrapper.classList.contains('hidden-container')) return;
1014
-
1015
- const clickableDefinition = definition.replace(/click ([A-Z0-9_\-]+) call displayDetailsAndGraphFromGraph/g,'click $1 call displayDetailsAndGraphFromGraph');
1016
- const graphId = `mermaid-flow-${flowId}-${Date.now()}`;
1017
-
1018
- const { svg } = await mermaid.render(graphId, clickableDefinition);
1019
- mermaidFlowGraphContainer.innerHTML = svg;
1020
-
1021
- // Make the SVG responsive
1022
- const svgElement = mermaidFlowGraphContainer.querySelector('svg');
1023
- if (svgElement) {
1024
- svgElement.setAttribute('width', '100%');
1025
- svgElement.setAttribute('height', '100%');
1026
- svgElement.style.maxHeight = '700px'; // Taller to accommodate complex flows
1027
- }
1028
-
1029
- // Add title and description based on flow ID
1030
- const flowDisplayTitles = {
1031
- "p1_sad": "Phase 1 SAD Study Documents",
1032
- "nda_submission": "NDA/MAA Submission Process",
1033
- "ind_pathway": "IND Pathway Documents",
1034
- "clinical_program": "Clinical Program Development"
1035
- };
1036
-
1037
- const flowDescriptions = {
1038
- "p1_sad": "This diagram shows the key documents needed for a Phase 1 Single Ascending Dose study, from preclinical inputs through to clinical execution and reporting.",
1039
- "nda_submission": "The NDA/MAA submission process flow showing how various documents and data packages are assembled into a regulatory submission.",
1040
- "ind_pathway": "Documents required from Discovery through Preclinical development to enable an IND/CTA submission.",
1041
- "clinical_program": "The integrated flow of clinical documentation across Phases 1-3 leading to regulatory submission."
1042
- };
1043
-
1044
- const title = flowDisplayTitles[flowId] || `Flow ${flowId}`;
1045
- const description = flowDescriptions[flowId] || "Document workflow visualization";
1046
-
1047
- // Add title and description above the graph
1048
- const titleContainer = document.createElement('div');
1049
- titleContainer.className = 'mb-4';
1050
- titleContainer.innerHTML = `
1051
- <h3 class="text-xl font-semibold text-gray-800 mb-2">${title}</h3>
1052
- <p class="text-sm text-gray-600">${description}</p>
1053
- `;
1054
-
1055
- mermaidFlowGraphContainer.insertBefore(titleContainer, mermaidFlowGraphContainer.firstChild);
1056
-
1057
- } catch (error) {
1058
- console.error(`Mermaid rendering error for flow ${flowId}:`, error);
1059
- mermaidFlowGraphContainer.innerHTML = `
1060
- <div class="text-center p-10">
1061
- <i class="lucide lucide-alert-triangle text-red-500 text-3xl mb-3"></i>
1062
- <p class="text-red-500 mb-4">Error rendering flow graph.</p>
1063
- <div class="bg-gray-100 p-4 rounded text-xs overflow-auto max-h-60">
1064
- ${error.message}
1065
- </div>
1066
- </div>
1067
- `;
1068
- }
1069
- }
1070
-
1071
- async function showExampleFlow() {
1072
- const exampleDefinition = flowDefinitions['p1_sad'];
1073
-
1074
- try {
1075
- // Show loading indicator
1076
- exampleMermaidGraphContainer.innerHTML = `
1077
- <div class="flex flex-col items-center justify-center p-10">
1078
- <div class="loading-spinner"></div>
1079
- <p class="text-gray-500 mt-4">Rendering example flow...</p>
1080
- </div>
1081
- `;
1082
-
1083
- const clickableDefinition = exampleDefinition.replace(/click ([A-Z0-9_\-]+) call displayDetailsAndGraphFromGraph/g, 'click $1 call displayDetailsAndGraphFromModal');
1084
- const graphId = `example-mermaid-graph-render-${Date.now()}`;
1085
- const { svg } = await mermaid.render(graphId, clickableDefinition);
1086
- exampleMermaidGraphContainer.innerHTML = svg;
1087
-
1088
- // Add title and description
1089
- const titleContainer = document.createElement('div');
1090
- titleContainer.className = 'mb-4';
1091
- titleContainer.innerHTML = `
1092
- <h3 class="text-lg font-semibold text-gray-800 mb-2">Phase 1 SAD Study Documents</h3>
1093
- <p class="text-sm text-gray-600">This diagram shows the key documents needed for a Phase 1 Single Ascending Dose study, from preclinical inputs through to clinical execution and reporting.</p>
1094
- `;
1095
- exampleMermaidGraphContainer.insertBefore(titleContainer, exampleMermaidGraphContainer.firstChild);
1096
-
1097
- // Make the SVG responsive
1098
- const svgElement = exampleMermaidGraphContainer.querySelector('svg');
1099
- if (svgElement) {
1100
- svgElement.setAttribute('width', '100%');
1101
- svgElement.setAttribute('height', '100%');
1102
- }
1103
-
1104
- exampleFlowModal.style.display = "flex";
1105
- } catch (error) {
1106
- console.error("Mermaid rendering error for example:", error);
1107
- exampleMermaidGraphContainer.innerHTML = `
1108
- <div class="text-center p-10">
1109
- <i class="lucide lucide-alert-triangle text-red-500 text-3xl mb-3"></i>
1110
- <p class="text-red-500">Error rendering example flow graph.</p>
1111
- </div>
1112
- `;
1113
- exampleFlowModal.style.display = "flex";
1114
- }
1115
- }
1116
-
1117
- // --- Global Search Functionality ---
1118
- function performGlobalSearch(searchTerm) {
1119
- if (!searchTerm) return;
1120
-
1121
- searchTerm = searchTerm.toLowerCase();
1122
- let results = documentsData.filter(doc =>
1123
- doc.Document_Name.toLowerCase().includes(searchTerm) ||
1124
- doc.Doc_ID_Type.toLowerCase().includes(searchTerm) ||
1125
- (doc.Purpose_Key_Content && doc.Purpose_Key_Content.toLowerCase().includes(searchTerm))
1126
- );
1127
-
1128
- // Switch to document view with search results
1129
- switchToView('documentViewWrapper', 'All');
1130
-
1131
- // Set the search input in document view to match the global search
1132
- searchInputDocView.value = searchTerm;
1133
-
1134
- // Render the filtered list
1135
- renderDocumentList();
1136
- }
1137
-
1138
- // --- Event Listeners ---
1139
-
1140
- // Search input specific to document view
1141
- searchInputDocView?.addEventListener('input', renderDocumentList);
1142
-
1143
- // Global header search
1144
- headerSearchInput?.addEventListener('keypress', (e) => {
1145
- if (e.key === 'Enter') {
1146
- performGlobalSearch(e.target.value);
1147
- }
1148
- });
1149
-
1150
- // Home button listener
1151
- homeButton?.addEventListener('click', () => switchToView('home'));
1152
-
1153
- // Breadcrumb listener (delegated)
1154
- breadcrumbNav?.addEventListener('click', (e) => {
1155
- if (e.target.tagName === 'A' && e.target.dataset.viewTarget) {
1156
- e.preventDefault();
1157
- switchToView(e.target.dataset.viewTarget);
1158
- }
1159
- });
1160
-
1161
- // Dashboard card listeners (delegated to main content area)
1162
- mainContentArea?.addEventListener('click', (e) => {
1163
- const card = e.target.closest('.dashboard-card[data-target-view]');
1164
- if (card) {
1165
- const targetView = card.dataset.targetView;
1166
- const initialTab = card.dataset.initialTab; // Get initial tab if specified
1167
- if (targetView) {
1168
- switchToView(targetView, initialTab);
1169
- }
1170
- }
1171
  });
1172
 
1173
- // Example Flow Buttons (Header and Flow View)
1174
- showExampleFlowBtnHeader?.addEventListener('click', showExampleFlow);
1175
- showExampleFlowBtnFlowView?.addEventListener('click', showExampleFlow);
1176
-
1177
- // Modal Close Listeners
1178
- closeExampleModalBtn?.addEventListener('click', () => exampleFlowModal.style.display = "none");
1179
- window.addEventListener('click', (event) => { if (event.target == exampleFlowModal) exampleFlowModal.style.display = "none"; });
1180
- closeDetailsModalBtn?.addEventListener('click', () => { detailsModal.style.display = "none"; clearSelection(); });
1181
- window.addEventListener('click', (event) => { if (event.target == detailsModal) { detailsModal.style.display = "none"; clearSelection(); } });
1182
-
1183
- // Modal Next/Prev Button Listeners
1184
- prevDocBtn?.addEventListener('click', () => { if (currentDocListIndices.prev) displayDetailsInModal(currentDocListIndices.prev); });
1185
- nextDocBtn?.addEventListener('click', () => { if (currentDocListIndices.next) displayDetailsInModal(currentDocListIndices.next); });
1186
-
1187
- // --- Initialization ---
1188
- document.addEventListener('DOMContentLoaded', async () => {
1189
- console.log("DOM Loaded. Fetching data...");
1190
-
1191
- try {
1192
- // Load document data
1193
- const docsResponse = await fetch('documents.json');
1194
- if (!docsResponse.ok) {
1195
- throw new Error(`HTTP error! status: ${docsResponse.status}`);
1196
- }
1197
- documentsData = await docsResponse.json();
1198
- console.log(`Successfully loaded ${documentsData.length} documents from documents.json`);
1199
-
1200
- // Try to load template data if available
1201
- try {
1202
- const templatesResponse = await fetch('document_templates.json');
1203
- if (templatesResponse.ok) {
1204
- templateData = await templatesResponse.json();
1205
- console.log(`Successfully loaded ${templateData.length} templates from document_templates.json`);
1206
- } else {
1207
- console.warn("Templates file not found. Document templates will not be available.");
1208
- templateData = [];
1209
- }
1210
- } catch (templateError) {
1211
- console.warn("Error loading templates:", templateError);
1212
- templateData = [];
1213
- }
1214
-
1215
- // Hide the loading spinner
1216
- loadingSpinner.style.display = 'none';
1217
-
1218
- // Start on the 'Home' view
1219
- switchToView('home');
1220
-
1221
- } catch (error) {
1222
- console.error("Failed to load documents.json:", error);
1223
-
1224
- // Hide spinner and show error message
1225
- loadingSpinner.style.display = 'none';
1226
-
1227
- // Display error message more prominently
1228
- mainContentArea.innerHTML = `
1229
- <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative m-4" role="alert">
1230
- <strong class="font-bold">Error!</strong>
1231
- <span class="block sm:inline">Could not load document database (documents.json). Please ensure the file exists in the same folder and is valid JSON.</span>
1232
- <p class="text-xs mt-1">(${error.message})</p>
1233
- </div>
1234
- `;
1235
- }
1236
- });
1237
  </script>
 
 
1238
  </body>
1239
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>R&D DocMap Catalog - Document Dependency Mapper</title>
7
+ <!-- Load Tailwind CSS -->
8
  <script src="https://cdn.tailwindcss.com"></script>
9
+ <!-- Load Lucide Icons -->
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lucide-static@latest/font/Lucide.css">
11
+ <!-- Load Mermaid properly with specific version -->
12
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js"></script>
13
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
14
  <style>
15
  /* Base styles */
 
66
  .document-item[data-phase="Clinical (All Phases)"] { border-left-color: #7c3aed; }
67
  .document-item[data-phase="Regulatory Submission"] { border-left-color: #ec4899; }
68
  .document-item[data-phase="Post-Marketing"] { border-left-color: #f59e0b; }
69
+ .document-item[data-phase="Pre/Post-Approval"] { border-left-color: #f97316; }
70
 
71
  /* Tab styles for document detail modal */
72
  .details-tabs {
 
159
  -webkit-box-orient: vertical;
160
  overflow: hidden;
161
  }
162
+
163
+ /* Enhanced detail card styles for better readability */
164
+ .detail-card {
165
+ background-color: white;
166
+ border-radius: 0.5rem;
167
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
168
+ padding: 1.25rem;
169
+ margin-bottom: 1rem;
170
+ border-left: 4px solid #3b82f6;
171
+ }
172
+
173
+ .detail-card-header {
174
+ display: flex;
175
+ justify-content: space-between;
176
+ margin-bottom: 0.75rem;
177
+ border-bottom: 1px solid #e5e7eb;
178
+ padding-bottom: 0.75rem;
179
+ }
180
+
181
+ .detail-card-title {
182
+ font-size: 1.125rem;
183
+ font-weight: 600;
184
+ color: #1e40af;
185
+ }
186
+
187
+ .detail-card-badge {
188
+ background-color: #eff6ff;
189
+ color: #1e40af;
190
+ padding: 0.25rem 0.5rem;
191
+ border-radius: 9999px;
192
+ font-size: 0.75rem;
193
+ font-weight: 500;
194
+ }
195
+
196
+ .detail-card-section {
197
+ margin-bottom: 0.75rem;
198
+ }
199
+
200
+ .detail-card-label {
201
+ font-weight: 500;
202
+ color: #4b5563;
203
+ margin-bottom: 0.25rem;
204
+ display: block;
205
+ }
206
+
207
+ .detail-card-value {
208
+ background-color: #f9fafb;
209
+ padding: 0.5rem;
210
+ border-radius: 0.25rem;
211
+ font-size: 0.875rem;
212
+ color: #1f2937;
213
+ }
214
+
215
+ /* Data lineage view styles */
216
+ .lineage-container {
217
+ padding: 1.5rem;
218
+ background-color: white;
219
+ border-radius: 0.5rem;
220
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
221
+ }
222
+
223
+ .lineage-filters {
224
+ display: flex;
225
+ gap: 1rem;
226
+ margin-bottom: 1.5rem;
227
+ flex-wrap: wrap;
228
+ }
229
+
230
+ .lineage-filters select {
231
+ padding: 0.5rem;
232
+ border-radius: 0.25rem;
233
+ border: 1px solid #d1d5db;
234
+ background-color: white;
235
+ min-width: 200px;
236
+ }
237
+
238
+ .lineage-graph {
239
+ height: 600px;
240
+ border: 1px solid #e5e7eb;
241
+ border-radius: 0.375rem;
242
+ overflow: hidden;
243
+ }
244
  </style>
245
  <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🗺️</text></svg>">
246
  </head>
 
251
  <span id="logo-placeholder" class="inline-block bg-white rounded-full p-1 leading-none">
252
  <i class="lucide lucide-map text-blue-700 text-2xl"></i>
253
  </span>
254
+ <h1 class="text-2xl font-bold">R&D DocMap Catalog</h1>
255
  </div>
256
  <div class="flex items-center space-x-4">
257
  <button id="homeButton" class="text-white hover:text-blue-200 flex items-center text-sm">
 
277
 
278
  <section id="home" class="space-y-6">
279
  <div class="bg-white rounded-lg shadow p-6 text-center">
280
+ <h2 class="text-2xl font-semibold text-gray-800 mb-2">Welcome to R&D DocMap Catalog</h2>
281
+ <p class="text-gray-600">A comprehensive R&D document catalog and authoring dependency mapper</p>
282
  </div>
283
 
284
  <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
 
294
  <p class="text-sm text-gray-500 mb-4 flex-grow">Visualize document workflows and dependencies.</p>
295
  <button class="bg-purple-500 hover:bg-purple-600 text-white font-medium py-2 px-4 rounded-md text-sm w-full">Explore</button>
296
  </div>
297
+ <div data-target-view="dataLineageViewWrapper" data-initial-tab="Lineage" class="dashboard-card bg-white rounded-lg shadow p-6 text-center cursor-pointer flex flex-col items-center">
298
+ <i class="lucide lucide-git-branch text-4xl text-green-500 mb-4"></i>
299
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">Section Lineage</h3>
300
+ <p class="text-sm text-gray-500 mb-4 flex-grow">Explore section-level document dependencies and data lineage.</p>
301
+ <button class="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 rounded-md text-sm w-full">Explore</button>
302
  </div>
303
+ <div data-target-view="uberDepViewWrapper" data-initial-tab="UberDep" class="dashboard-card bg-white rounded-lg shadow p-6 text-center cursor-pointer flex flex-col items-center">
304
+ <i class="lucide lucide-network text-4xl text-amber-500 mb-4"></i>
305
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">DocGen Dependencies</h3>
306
+ <p class="text-sm text-gray-500 mb-4 flex-grow">Visualize uber interdependencies across document generation.</p>
307
+ <button class="bg-amber-500 hover:bg-amber-600 text-white font-medium py-2 px-4 rounded-md text-sm w-full">Explore</button>
308
  </div>
309
  </div>
310
 
311
  <div class="bg-white rounded-lg shadow p-4 mt-6">
312
  <h3 class="font-semibold text-gray-700 mb-3">Recent Updates</h3>
313
  <ul class="text-sm text-gray-600 space-y-1">
314
+ <li><span class="text-gray-400 mr-2">[April 7, 2025]</span>Added section-level lineage visualization capabilities.</li>
315
  <li><span class="text-gray-400 mr-2">[April 6, 2025]</span>Enhanced document visualization system launched.</li>
316
  <li><span class="text-gray-400 mr-2">[April 5, 2025]</span>Added IND pathway and clinical program flows.</li>
 
317
  </ul>
318
  </div>
319
  </section>
 
354
  </div>
355
  </section>
356
 
357
+ <!-- New Data Lineage View Section -->
358
+ <section id="dataLineageViewWrapper" class="hidden-container flex-1 bg-white rounded-lg shadow p-4 overflow-hidden flex flex-col gap-4">
359
+ <h2 class="text-xl font-semibold text-gray-700 mb-2 flex items-center flex-shrink-0">
360
+ <i class="lucide lucide-git-branch mr-2 text-green-600"></i> Section-Level Lineage
361
+ </h2>
362
+ <div class="lineage-filters">
363
+ <div>
364
+ <label class="block text-sm font-medium text-gray-700 mb-1">Select Document</label>
365
+ <select id="lineageDocumentSelect" class="w-full">
366
+ <option value="">Select a document...</option>
367
+ <!-- Documents will be populated by JavaScript -->
368
+ </select>
369
+ </div>
370
+ <div>
371
+ <label class="block text-sm font-medium text-gray-700 mb-1">Select Section</label>
372
+ <select id="lineageSectionSelect" class="w-full" disabled>
373
+ <option value="">Select a section...</option>
374
+ <!-- Sections will be populated after selecting a document -->
375
+ </select>
376
+ </div>
377
+ </div>
378
+ <div class="lineage-container flex-1 flex flex-col">
379
+ <div id="lineageGraphContainer" class="lineage-graph flex-1">
380
+ <p id="lineagePlaceholder" class="text-gray-500 text-center py-10 px-4">Select a document and section to visualize data lineage.</p>
381
+ <div id="mermaidLineageGraph" class="mermaid w-full h-full p-4">
382
+ </div>
383
+ </div>
384
+ </div>
385
+ </section>
386
+
387
+ <!-- New Uber Dependencies View Section -->
388
+ <section id="uberDepViewWrapper" class="hidden-container flex-1 bg-white rounded-lg shadow p-4 overflow-hidden flex flex-col gap-4">
389
+ <h2 class="text-xl font-semibold text-gray-700 mb-2 flex items-center flex-shrink-0">
390
+ <i class="lucide lucide-network mr-2 text-amber-600"></i> DocGen Dependencies
391
+ </h2>
392
+ <div class="flex flex-1 gap-4 overflow-hidden">
393
+ <div class="w-full md:w-1/4 border-r pr-4 border-gray-200 overflow-y-auto custom-scroll">
394
+ <div>
395
+ <h3 class="font-medium text-gray-700 mb-2">Filter By:</h3>
396
+ <div class="space-y-2">
397
+ <div>
398
+ <label class="block text-sm font-medium text-gray-700 mb-1">Document Type</label>
399
+ <select id="uberDepDocTypeSelect" class="w-full border border-gray-300 rounded-md p-2">
400
+ <option value="all">All Document Types</option>
401
+ <!-- Document types will be populated by JavaScript -->
402
+ </select>
403
+ </div>
404
+ <div>
405
+ <label class="block text-sm font-medium text-gray-700 mb-1">Phase</label>
406
+ <select id="uberDepPhaseSelect" class="w-full border border-gray-300 rounded-md p-2">
407
+ <option value="all">All Phases</option>
408
+ <!-- Phases will be populated by JavaScript -->
409
+ </select>
410
+ </div>
411
+ </div>
412
+ </div>
413
+ <div class="mt-6">
414
+ <h3 class="font-medium text-gray-700 mb-2">Legend</h3>
415
+ <div class="space-y-2 text-sm">
416
+ <div class="flex items-center">
417
+ <span class="w-3 h-3 bg-blue-500 rounded-full mr-2"></span>
418
+ <span>Input Document</span>
419
+ </div>
420
+ <div class="flex items-center">
421
+ <span class="w-3 h-3 bg-green-500 rounded-full mr-2"></span>
422
+ <span>Output Document</span>
423
+ </div>
424
+ <div class="flex items-center">
425
+ <span class="w-3 h-3 bg-purple-500 rounded-full mr-2"></span>
426
+ <span>Input/Output Document</span>
427
+ </div>
428
+ </div>
429
+ </div>
430
+ </div>
431
+ <div id="uberDepContainer" class="w-full md:w-3/4 overflow-auto custom-scroll bg-gray-50 rounded">
432
+ <p id="uberDepPlaceholder" class="text-gray-500 text-center py-10 px-4">Loading document generation dependencies...</p>
433
+ <div id="mermaidUberDepGraph" class="mermaid w-full h-full p-4">
434
+ </div>
435
+ </div>
436
+ </div>
437
+ </section>
438
+
439
  </main>
440
 
441
  <div id="exampleFlowModal" class="modal">
 
473
  <div id="loadingSpinner" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
474
  <div class="bg-white p-8 rounded-lg shadow-lg flex flex-col items-center">
475
  <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mb-4"></div>
476
+ <p class="text-gray-700 font-medium">Loading R&D DocMap Catalog...</p>
477
  </div>
478
  </div>
479
 
480
  <script>
481
+ // Initialize Mermaid with proper configuration
482
+ document.addEventListener('DOMContentLoaded', function() {
483
+ // Initialize Mermaid properly
484
+ mermaid.initialize({
485
+ startOnLoad: false,
486
+ theme: 'base',
487
+ securityLevel: 'loose',
488
+ themeVariables: {
489
+ primaryColor: '#eff6ff',
490
+ primaryTextColor: '#1e3a8a',
491
+ primaryBorderColor: '#60a5fa',
492
+ lineColor: '#6b7280',
493
+ secondaryColor: '#f1f5f9',
494
+ tertiaryColor: '#e0f2fe'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  });
498
 
499
+ // More JavaScript functionality will be added in a separate script file
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  </script>
501
+
502
+ <script src="docmap.js"></script>
503
  </body>
504
  </html>