-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuser_guide_uploader.html
More file actions
1541 lines (1389 loc) · 84.9 KB
/
Copy pathuser_guide_uploader.html
File metadata and controls
1541 lines (1389 loc) · 84.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Guide: Assessment Uploader - 4Set System</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="assets/js/tailwind.config.js"></script>
<link rel="stylesheet" href="assets/css/theme_pantone_light_1.css">
<link rel="stylesheet" href="assets/css/global.css">
<link rel="stylesheet" href="assets/css/user-guides.css">
<link rel="stylesheet" href="assets/css/spotlight-system.css">
<link rel="stylesheet" href="assets/css/tooltip-styles.css">
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<script src="assets/js/smart-navigation.js"></script>
<style>
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.mermaid {
display: flex;
justify-content: center;
margin: 2rem 0;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
mermaid.initialize({
startOnLoad: true,
theme: 'base',
themeVariables: {
primaryColor: '#4A90E2',
primaryTextColor: '#1F2937',
primaryBorderColor: '#2E5C8A',
lineColor: '#6B7280',
secondaryColor: '#E8F5E9',
tertiaryColor: '#FFF3E0',
edgeLabelBackground: '#ffffff',
textColor: '#1F2937',
mainBkg: '#ffffff',
nodeBorder: '#6B7280'
}
});
});
</script>
</head>
<body class="min-h-screen">
<!-- Header -->
<header class="bg-white shadow-md sticky top-0 z-50">
<div class="container mx-auto px-6 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<a href="index.html" class="text-2xl font-bold" style="color: var(--primary)">4Set System</a>
<span class="text-gray-400">|</span>
<h1 class="text-xl font-semibold text-gray-700">User Guide: Assessment Uploader</h1>
</div>
<div class="flex items-center gap-3">
<a href="quick_start_guide.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Quick Start Guide">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 20V10"></path>
<path d="M18 20V4"></path>
<path d="M6 20v-4"></path>
</svg>
</a>
<a href="user_guide_checking_system.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Checking System Guide">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="9 11 12 14 22 4"></polyline>
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
</svg>
</a>
<a href="user_guide_uploader.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Assessment Uploader Guide">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
</a>
<a href="user_guide_processor_setup.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Processor Agent Setup Guide">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"></circle>
<path d="M12 1v6m0 6v6"></path>
<path d="m4.93 4.93 4.24 4.24m5.66 5.66 4.24 4.24"></path>
<path d="m1 12 6 0m6 0 6 0"></path>
<path d="m4.93 19.07 4.24-4.24m5.66-5.66 4.24-4.24"></path>
</svg>
</a>
<a href="guide_homepage.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Back to Guide Homepage">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
</svg>
</a>
<a href="index.html" class="text-gray-600 hover:text-primary transition p-2 rounded-lg hover:bg-gray-100" title="Back to System Home">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
</a>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container mx-auto px-6 py-8">
<div class="flex gap-8">
<!-- Sidebar Navigation -->
<aside class="sidebar w-64 flex-shrink-0">
<div class="bg-white rounded-lg shadow-lg p-6">
<h2 class="text-lg font-bold mb-4" style="color: var(--primary)">Table of Contents</h2>
<nav class="space-y-2">
<a href="#overview" class="toc-link block text-sm text-gray-700 py-1">I. Overview</a>
<a href="#getting-started" class="toc-link block text-sm text-gray-700 py-1">II. Getting Started</a>
<a href="#requirements" class="toc-link block text-sm text-gray-700 py-1">III. System Requirements</a>
<a href="#upload-process" class="toc-link block text-sm text-gray-700 py-1">IV. Upload Process</a>
<a href="#pipeline" class="toc-link block text-sm text-gray-700 py-1">V. Upload Pipeline</a>
<a href="#processor-agent" class="toc-link block text-sm text-gray-700 py-1">VI. Processor Agent</a>
<a href="#configuration" class="toc-link block text-sm text-gray-700 py-1">VII. Configuration</a>
<a href="#troubleshooting" class="toc-link block text-sm text-gray-700 py-1">VIII. Troubleshooting</a>
<a href="#faqs" class="toc-link block text-sm text-gray-700 py-1">IX. FAQs</a>
<a href="#best-practices" class="toc-link block text-sm text-gray-700 py-1">X. Best Practices</a>
</nav>
</div>
</aside>
<!-- Main Content Area -->
<main class="flex-1 max-w-4xl">
<div class="bg-white rounded-lg shadow-lg p-8 mb-8">
<!-- Document Info -->
<div class="mb-8 pb-6 border-b border-gray-200">
<div class="flex flex-wrap gap-4 text-sm text-gray-600">
<div><strong>Version:</strong> 2.0</div>
<div><strong>Last Updated:</strong> October 16, 2025</div>
<div><strong>Target Users:</strong> Research assistants, test administrators, operators</div>
</div>
</div>
<!-- Overview Section -->
<section id="overview" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">I</span>
Overview
</h2>
<!-- Source Note -->
<div class="mb-6 p-4 bg-blue-50 border-l-4 border-blue-500 rounded">
<p class="text-sm text-gray-700">
📄 <strong>Markdown Source:</strong> This guide is also available in markdown format at
<a href="PRDs/assessment_uploader_user_guide_prd.md" class="text-blue-600 hover:underline font-mono">PRDs/assessment_uploader_user_guide_prd.md</a>
</p>
</div>
<p class="text-gray-700 mb-6 text-lg leading-relaxed">
The <strong>4Set Assessment Uploader</strong> is a web-based interface that allows you to upload assessment PDFs directly from your browser. The system uses modern browser technology to write files to monitored folders.
</p>
<h3 id="overview-what-it-does" class="text-2xl font-semibold mb-4">What It Does</h3>
<ul class="space-y-2 text-gray-700 mb-6">
<li>✅ <strong>Direct File Upload:</strong> Write PDF files directly to OneDrive-synced folders</li>
<li>✅ <strong>Automatic Processing:</strong> Files automatically validated, parsed, and uploaded</li>
<li>✅ <strong>No Backend Required:</strong> Everything happens in your browser</li>
<li>✅ <strong>Real-time Status:</strong> See upload progress and completion status instantly</li>
<li>✅ <strong>Metadata Tracking:</strong> Tracks which PC uploaded each file</li>
</ul>
<div class="diagram-box bg-green-50 border-green-300">
<h4 class="font-semibold mb-3">Key Benefits</h4>
<ul class="space-y-1 text-gray-700">
<li>• <strong>Simple:</strong> Drag and drop PDFs or click to browse</li>
<li>• <strong>Secure:</strong> Files never leave your local network until synced via OneDrive</li>
<li>• <strong>Fast:</strong> No server uploads - files written directly to local folders</li>
<li>• <strong>Reliable:</strong> Built-in validation and error handling</li>
</ul>
</div>
</section>
<!-- Getting Started Section -->
<section id="getting-started" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">II</span>
Getting Started
</h2>
<h3 id="getting-started-quick" class="text-2xl font-semibold mb-4">Quick Start (3 Steps)</h3>
<div class="diagram-box bg-blue-50 border-blue-300">
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="step-number">1</div>
<div class="text-gray-800">Open <code>upload.html</code> in Chrome/Edge browser</div>
</div>
<div class="flex items-center gap-3">
<div class="step-number">2</div>
<div class="text-gray-800">Configure your PC number and upload destination</div>
</div>
<div class="flex items-center gap-3">
<div class="step-number">3</div>
<div class="text-gray-800">Drag & drop PDF or E-Prime (.edat3) files to upload</div>
</div>
</div>
<p class="mt-4 text-center text-gray-600 font-semibold">That's it! The processor agent will handle the rest.</p>
</div>
</section>
<!-- System Requirements Section -->
<section id="requirements" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">III</span>
System Requirements
</h2>
<div class="grid md:grid-cols-2 gap-6">
<div class="diagram-box bg-green-50 border-green-300">
<h3 class="text-xl font-semibold mb-3">✅ Required</h3>
<ul class="space-y-2 text-sm text-gray-700">
<li>• <strong>Browser:</strong> Chrome 86+ or Edge 86+</li>
<li>• <strong>OS:</strong> Windows 10/11 with OneDrive sync</li>
<li>• <strong>Network:</strong> OneDrive folder syncing properly</li>
<li>• <strong>Agent:</strong> Processor agent running</li>
</ul>
</div>
<div class="diagram-box bg-red-50 border-red-300">
<h3 class="text-xl font-semibold mb-3">❌ Not Supported</h3>
<ul class="space-y-2 text-sm text-gray-700">
<li>• Firefox (no File System Access API)</li>
<li>• Safari (no File System Access API)</li>
<li>• Mobile browsers (limited API support)</li>
<li>• Private/Incognito mode</li>
</ul>
</div>
</div>
<div class="collapsible-section mt-6">
<div class="collapsible-header">
<h3 class="text-xl font-semibold">How to Check Compatibility</h3>
<span class="text-2xl">▼</span>
</div>
<div class="collapsible-content">
<ol class="list-decimal ml-6 space-y-2 text-gray-700">
<li>Open Chrome or Edge</li>
<li>Visit: <code>chrome://version</code> or <code>edge://version</code></li>
<li>Check version number is 86 or higher</li>
<li>Verify OneDrive icon shows "Up to date" in system tray</li>
</ol>
</div>
</div>
</section>
<!-- Upload Process Section -->
<section id="upload-process" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">IV</span>
Step-by-Step Upload Process
</h2>
<h3 id="upload-process-setup" class="text-2xl font-semibold mb-4">First Time Setup</h3>
<div class="collapsible-section">
<div class="collapsible-header">
<h4 class="text-lg font-semibold">Step 1: Configure PC Number</h4>
<span class="text-xl">▼</span>
</div>
<div class="collapsible-content">
<div class="bg-yellow-50 border rounded p-4 mb-4">
<div class="text-center space-y-2">
<div class="font-semibold">System Status: Setup Required</div>
<div><span class="status-badge status-warning">⚠️ PC Number: Not Set</span></div>
<div><span class="status-badge status-error">🔴 Destination: Not Set</span></div>
</div>
</div>
<ol class="list-decimal ml-6 space-y-2 text-gray-700">
<li><strong>Click on the red "PC Number" badge</strong> at the top of the page</li>
<li>A modal will appear asking for your PC number</li>
<li><strong>Enter your 3-digit PC number</strong> (e.g., <code>010</code>, <code>095</code>, <code>999</code>)
<ul class="list-disc ml-6 mt-1 space-y-1 text-sm">
<li>If your computer is named <code>KS095</code>, enter <code>095</code></li>
<li>If you're on <code>LAPTOP-123</code>, enter the assigned number</li>
</ul>
</li>
<li>Click <strong>"Save PC Number"</strong></li>
<li>The badge should turn green ✅</li>
</ol>
<div class="alert-box alert-info mt-4">
<strong>Why is this needed?</strong> The PC number identifies which computer uploaded each file, helping track the source of submissions.
</div>
</div>
</div>
<div class="collapsible-section">
<div class="collapsible-header">
<h4 class="text-lg font-semibold">Step 2: Set Upload Destination</h4>
<span class="text-xl">▼</span>
</div>
<div class="collapsible-content">
<ol class="list-decimal ml-6 space-y-2 text-gray-700">
<li><strong>Click on the red "Upload Destination" badge</strong></li>
<li>Read the information modal about folder permissions</li>
<li>Click <strong>"Set Upload Destination"</strong></li>
<li>A browser folder picker will appear</li>
<li><strong>Navigate to the monitored folder</strong> (typically <code>incoming/</code>)</li>
<li><strong>Click "Select Folder"</strong> to grant permission</li>
<li>The badge should turn green ✅</li>
</ol>
<div class="alert-box alert-warning mt-4">
<strong>Important:</strong> This is a one-time setup per browser. The permission is saved and you won't be asked again.
</div>
</div>
</div>
<h3 class="text-2xl font-semibold mb-4 mt-8">Regular Upload Process</h3>
<div class="diagram-box">
<h4 class="font-semibold mb-3">Once Configured</h4>
<div class="space-y-4">
<div class="border-l-4 border-blue-500 pl-4">
<div class="font-semibold">Method A: Drag & Drop</div>
<ol class="text-sm text-gray-700 mt-1 space-y-1">
<li>1. Drag one or more PDF files from File Explorer</li>
<li>2. Drop them on the upload zone (large dotted box)</li>
<li>3. Files will be added to the upload queue</li>
</ol>
</div>
<div class="border-l-4 border-green-500 pl-4">
<div class="font-semibold">Method B: Click to Browse</div>
<ol class="text-sm text-gray-700 mt-1 space-y-1">
<li>1. Click anywhere in the upload zone</li>
<li>2. A file picker will open</li>
<li>3. Select one or more PDF files</li>
<li>4. Click "Open"</li>
</ol>
</div>
</div>
</div>
<h4 class="text-lg font-semibold mb-3 mt-6">Monitor Progress</h4>
<div class="bg-gray-50 border rounded p-4">
<p class="mb-3">A floating panel will show:</p>
<div class="space-y-2">
<div class="flex items-center gap-2">
<span class="text-yellow-600">⏳</span>
<span class="text-sm"><strong>Uploading:</strong> File being written</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-600">✅</span>
<span class="text-sm"><strong>Complete:</strong> File uploaded successfully</span>
</div>
<div class="flex items-center gap-2">
<span class="text-red-600">❌</span>
<span class="text-sm"><strong>Error:</strong> Upload failed (see error message)</span>
</div>
</div>
</div>
</section>
<!-- Pipeline Section -->
<section id="pipeline" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">V</span>
Understanding the Upload Pipeline
</h2>
<div class="diagram-box bg-purple-50 border-purple-300">
<h3 class="text-lg font-semibold mb-4 text-center">Complete Data Flow</h3>
<div class="space-y-3 text-sm">
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">1</div>
<div><strong>User:</strong> Drag & drop PDF to browser</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">2</div>
<div><strong>Browser:</strong> Validate PC number & destination</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">3</div>
<div><strong>Local Folder:</strong> Write PDF file & metadata.json</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">4</div>
<div><strong>OneDrive:</strong> Auto-sync to cloud (seconds)</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">5</div>
<div><strong>Agent:</strong> Detect file and process</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">6</div>
<div><strong>Jotform:</strong> Upload submission</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">7</div>
<div><strong>Filed:</strong> Move to school folder</div>
</div>
</div>
<div class="mt-4 pt-4 border-t border-purple-200 text-center">
<strong>Total Time:</strong> <span class="text-purple-700">~30-60 seconds</span> end-to-end
</div>
</div>
<h3 class="text-2xl font-semibold mb-4 mt-8">Timeline Summary</h3>
<table class="text-sm">
<thead>
<tr>
<th>Step</th>
<th>Time</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Upload to browser</td>
<td>Instant</td>
<td>You see feedback</td>
</tr>
<tr>
<td>Write files</td>
<td>1-2 sec</td>
<td>Floating panel updates</td>
</tr>
<tr>
<td>OneDrive sync</td>
<td>5-30 sec</td>
<td>Background</td>
</tr>
<tr>
<td>Agent detection</td>
<td>Immediate</td>
<td>Background</td>
</tr>
<tr>
<td>Processing</td>
<td>5-10 sec</td>
<td>Check logs</td>
</tr>
<tr>
<td>Jotform upload</td>
<td>10-30 sec</td>
<td>Check logs</td>
</tr>
<tr>
<td>Filing</td>
<td>Instant</td>
<td>Check filed/ folder</td>
</tr>
</tbody>
</table>
</section>
<!-- Processor Agent Workflow Section -->
<section id="processor-agent" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">VI</span>
Processor Agent: How It Works
</h2>
<p class="text-gray-700 mb-6">
The <strong>Processor Agent</strong> is an autonomous PowerShell service that continuously monitors the upload folder, validates PDFs, enriches data, and submits to Jotform. Here's how it processes your uploaded files:
</p>
<!-- Complete Processing Flowchart -->
<div class="bg-gradient-to-br from-indigo-50 to-purple-50 p-6 rounded-lg border-2 border-indigo-200 mb-8">
<h3 class="font-semibold mb-6 text-center text-lg">Complete Processing Workflow</h3>
<div class="mermaid">
flowchart TD
Start([📂 File Detected]) --> NameCheck{Filename<br/>approximately<br/>correct?}
NameCheck -->|NO - Invalid format| Reject1[❌ REJECTED<br/>→ Quarantine folder]
NameCheck -->|YES - Lenient match| Phase1{Is filename<br/>valid?<br/>Phase 1}
Phase1 -->|NO| Reject2[❌ REJECTED<br/>→ Quarantine folder]
Phase1 -->|YES| Phase2{PDF fields<br/>valid?<br/>Phase 2}
Phase2 -->|NO| Reject3[❌ REJECTED<br/>→ Quarantine folder]
Phase2 -->|YES| Process[🔄 Processing<br/>1. Parse PDF<br/>2. Calculate termination<br/>3. Enrich metadata<br/>4. Prepare JSON]
Process --> Conflict{Data<br/>conflict?}
Conflict -->|CONFLICT| Blocked[⚠️ BLOCKED<br/>→ Quarantine folder]
Conflict -->|SAFE| Upload[📤 Upload to Jotform<br/>Max 3 retries + backoff]
Upload --> UploadResult{Upload<br/>success?}
UploadResult -->|FAILED| Error[❌ ERROR<br/>→ Quarantine folder]
UploadResult -->|SUCCESS| File["📁 File to School Folder<br/>→ School-specific folder"]
File --> Complete([✅ COMPLETE])
style Start fill:#4A90E2,stroke:#2E5C8A,color:#fff
style Complete fill:#4CAF50,stroke:#2E7D32,color:#fff
style Process fill:#E1BEE7,stroke:#9C27B0,color:#4A148C
style Upload fill:#BBDEFB,stroke:#2196F3,color:#0D47A1
style File fill:#C8E6C9,stroke:#4CAF50,color:#1B5E20
style Reject1 fill:#FFE0E0,stroke:#E57373,color:#C62828
style Reject2 fill:#FFE0E0,stroke:#E57373,color:#C62828
style Reject3 fill:#FFE0E0,stroke:#E57373,color:#C62828
style Blocked fill:#FFE0B2,stroke:#FF9800,color:#E65100
style Error fill:#FFE0E0,stroke:#E57373,color:#C62828
style NameCheck fill:#E1F5FE,stroke:#03A9F4,color:#01579B
style Phase1 fill:#FFF9E0,stroke:#FFD54F,color:#F57C00
style Phase2 fill:#FFE0B2,stroke:#FF9800,color:#E65100
style Conflict fill:#F8BBD0,stroke:#F06292,color:#880E4F
style UploadResult fill:#B2DFDB,stroke:#26A69A,color:#004D40
</div>
<div class="mt-6 pt-4 border-t border-indigo-200 text-center text-sm text-gray-700">
<strong>Total Processing Time:</strong> 5-30 seconds per PDF (typical)<br/>
<span class="text-xs text-gray-600 mt-1">Note: Filename validation uses lenient matching - slight variations in format are accepted</span>
</div>
</div>
<!-- Validation Phases Detail -->
<h3 class="text-2xl font-semibold mb-4 mt-8">Validation Phases Explained</h3>
<div class="grid md:grid-cols-2 gap-6 mb-8">
<div class="bg-yellow-50 border-l-4 border-yellow-500 p-4 rounded shadow">
<h4 class="font-semibold mb-3 text-yellow-800">Phase 1: Filename Validation</h4>
<p class="text-sm text-gray-700 mb-2"><strong>Expected Format:</strong></p>
<code class="text-xs bg-white px-2 py-1 rounded">coreID_YYYYMMDD_HH_MM.pdf</code>
<p class="text-xs mt-2 text-gray-600 italic">Core ID: 5-digit numeric identifier from AITable</p>
<p class="text-sm text-gray-700 mt-3"><strong>Checks:</strong></p>
<ul class="text-xs space-y-1 mt-2">
<li>✓ 5-digit Core ID (numeric only, starts with 1)</li>
<li>✓ Valid date format (YYYYMMDD)</li>
<li>✓ Valid time format (HH_MM)</li>
<li>✓ Underscores in correct positions</li>
</ul>
<p class="text-xs mt-3 text-gray-600"><strong>Example:</strong> 10001_20251016_14_30.pdf ✅</p>
</div>
<div class="bg-orange-50 border-l-4 border-orange-500 p-4 rounded shadow">
<h4 class="font-semibold mb-3 text-orange-800">Phase 2: PDF Content Validation</h4>
<p class="text-sm text-gray-700 mb-2"><strong>Checks:</strong></p>
<ul class="text-xs space-y-1">
<li>✓ Student ID in mapping file</li>
<li>✓ School ID exists</li>
<li>✓ Required fields present</li>
<li>✓ Data types correct</li>
<li>✓ Value ranges valid</li>
</ul>
<p class="text-xs mt-3 text-gray-600"><strong>Sources:</strong> assets/*.enc mapping files</p>
</div>
</div>
<!-- Data Overwrite Protection -->
<h3 class="text-2xl font-semibold mb-4">Data Overwrite Protection (Optional - Configurable)</h3>
<!-- Configuration Notice -->
<div class="bg-yellow-50 p-4 rounded-lg border-2 border-yellow-300 mb-4">
<h4 class="font-semibold mb-2 text-yellow-900">⚙️ This Feature is Configurable</h4>
<p class="text-sm text-gray-700">
Data Overwrite Protection can be <strong>enabled or disabled</strong> by administrators via <code>config/agent.json</code>:
</p>
<pre class="bg-gray-800 text-green-400 p-2 rounded text-xs mt-2 overflow-x-auto">{
"dataProtection": {
"enableDataOverwriteProtection": true // Set to false to disable
}
}</pre>
<ul class="text-sm text-gray-700 mt-2 space-y-1">
<li>• <strong>When ENABLED (default):</strong> Protects against accidental data overwrites (as described below)</li>
<li>• <strong>When DISABLED:</strong> Allows full data overwrites, relying on human due diligence</li>
</ul>
</div>
<!-- Why This Matters -->
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-lg border-2 border-blue-300 mb-6">
<h4 class="font-semibold mb-3 text-blue-900">🔒 Why Data Overwrite Protection Matters (When Enabled)</h4>
<div class="text-sm text-gray-700 space-y-2">
<p><strong>Assessment data integrity is paramount.</strong> Once test administrators record student responses and upload PDFs, that data becomes the official record of the child's performance. Any accidental overwrite could:</p>
<ul class="list-disc ml-6 space-y-1 mt-2">
<li><strong>Loss of irreplaceable data:</strong> Student responses cannot be re-administered - once lost, they're gone forever</li>
<li><strong>Research validity compromise:</strong> Changing recorded answers invalidates study results and scientific conclusions</li>
<li><strong>Regulatory compliance issues:</strong> Educational research requires audit trails showing data hasn't been tampered with</li>
<li><strong>Accidental errors:</strong> Re-uploading the same student by mistake (e.g., wrong filename) could silently overwrite correct data</li>
</ul>
<p class="mt-3 font-semibold text-blue-800">The system prevents these scenarios by blocking any attempt to change existing assessment answers while still allowing corrections to administrative metadata (student names, school IDs, etc.).</p>
</div>
</div>
<!-- Conflict Detection Workflow -->
<div class="bg-gradient-to-br from-pink-50 to-red-50 p-6 rounded-lg border-2 border-pink-300 mb-6">
<h4 class="font-semibold mb-6 text-center text-lg">Data Overwrite Protection Workflow</h4>
<div class="mermaid">
flowchart TD
Start([New PDF Upload<br/>Attempt]) --> Parse[Parse PDF<br/>Extract Data]
Parse --> Search{Does student<br/>submission<br/>exist?}
Search -->|NO - New Student| AllowNew[✅ ALLOW<br/>Create New<br/>Submission]
Search -->|YES - Existing| CheckFields{Check Each<br/>Field}
CheckFields --> FieldType{Field<br/>Type?}
FieldType -->|Admin Info<br/>student-id, name,<br/>school-id, class| MetaCheck{Current<br/>Value?}
MetaCheck -->|Empty/Null| AllowMeta[✅ ALLOW<br/>Fill Empty<br/>Admin Info]
MetaCheck -->|Has Value| AllowUpdate[✅ ALLOW<br/>Update Admin Info]
FieldType -->|Test Answers<br/>ERV, CM, CWR,<br/>termination| DataCheck{Current<br/>Value?}
DataCheck -->|Empty/Null| AllowData[✅ ALLOW<br/>Fill Empty<br/>Test Data]
DataCheck -->|Has Value| BlockData[❌ BLOCK<br/>Protect Existing<br/>Test Answers]
AllowNew --> LogSuccess[📝 Log to CSV:<br/>Success entry]
AllowMeta --> LogSuccess
AllowUpdate --> LogSuccess
AllowData --> LogSuccess
BlockData --> LogConflict["📝 Log to CSV:<br/>CONFLICT entry<br/>with field details"]
LogConflict --> MoveQuarantine["⚠️ Move PDF to<br/>Quarantine Folder"]
MoveQuarantine --> NotifyAdmin["🔔 Admin Reviews<br/>CSV Log Entry<br/>+ Quarantined PDF"]
LogSuccess --> FileSchool["📁 Move PDF to<br/>School's Folder<br/>+ Create JSON"]
FileSchool --> Complete([✅ Upload Complete])
NotifyAdmin --> End([❌ Upload Blocked])
style Start fill:#4A90E2,stroke:#2E5C8A,color:#fff
style Complete fill:#4CAF50,stroke:#2E7D32,color:#fff
style End fill:#E57373,stroke:#C62828,color:#fff
style AllowNew fill:#C8E6C9,stroke:#4CAF50,color:#1B5E20
style AllowMeta fill:#C8E6C9,stroke:#4CAF50,color:#1B5E20
style AllowUpdate fill:#C8E6C9,stroke:#4CAF50,color:#1B5E20
style AllowData fill:#C8E6C9,stroke:#4CAF50,color:#1B5E20
style BlockData fill:#FFCDD2,stroke:#E57373,color:#C62828
style MoveQuarantine fill:#FFE0B2,stroke:#FF9800,color:#E65100
style LogConflict fill:#FFF9C4,stroke:#FDD835,color:#F57F17
style LogSuccess fill:#E8F5E9,stroke:#66BB6A,color:#2E7D32
style Search fill:#E1F5FE,stroke:#03A9F4,color:#01579B
style CheckFields fill:#F3E5F5,stroke:#AB47BC,color:#4A148C
style FieldType fill:#FFF3E0,stroke:#FFA726,color:#E65100
style MetaCheck fill:#E0F2F1,stroke:#26A69A,color:#004D40
style DataCheck fill:#FCE4EC,stroke:#EC407A,color:#880E4F
</div>
<div class="mt-6 p-4 bg-white rounded border border-pink-200">
<p class="text-sm font-semibold mb-2">Key Decision Points:</p>
<ol class="text-xs text-gray-700 space-y-1 ml-4">
<li>1. <strong>New vs Existing:</strong> New students always allowed; existing students trigger protection checks</li>
<li>2. <strong>Field Type:</strong> Administrative info (student details, school assignment) vs Test Answers (actual assessment responses)</li>
<li>3. <strong>Admin Info:</strong> Can be updated to correct administrative errors (typos in names, wrong school assignment, PC number, etc.)</li>
<li>4. <strong>Test Answers:</strong> Once recorded, cannot be changed - protects scientific integrity of the assessment data</li>
<li>5. <strong>Empty Fields:</strong> Can always be filled, whether admin info or test data</li>
<li>6. <strong>Logging:</strong> All decisions logged to daily CSV file (YYYYMMDD_processing_agent.csv) for audit trail</li>
</ol>
</div>
</div>
<div class="bg-gradient-to-r from-pink-50 to-red-50 p-6 rounded-lg border-2 border-pink-300 mb-6">
<h4 class="font-semibold mb-4 text-center">Conflict Detection Rules (When Protection is Enabled)</h4>
<div class="bg-yellow-50 p-3 rounded border border-yellow-300 mb-4">
<p class="text-sm text-gray-700">
⚠️ <strong>Note:</strong> These rules apply only when <code>enableDataOverwriteProtection</code> is set to <code>true</code>. When disabled, all fields can be overwritten.
</p>
</div>
<div class="grid md:grid-cols-2 gap-4">
<div class="bg-white rounded p-4 shadow-sm border-l-4 border-green-500">
<h5 class="font-semibold text-green-800 mb-2">✅ ALLOWED Updates</h5>
<ul class="text-sm space-y-1">
<li>• Filling blank/null fields</li>
<li>• Updating metadata fields:
<ul class="ml-4 text-xs mt-1 space-y-1">
<li>- student-id</li>
<li>- child-name</li>
<li>- school-id</li>
<li>- district</li>
<li>- class-id</li>
<li>- computerno</li>
</ul>
</li>
<li>• Same value (no change)</li>
</ul>
</div>
<div class="bg-white rounded p-4 shadow-sm border-l-4 border-red-500">
<h5 class="font-semibold text-red-800 mb-2">❌ BLOCKED Updates</h5>
<ul class="text-sm space-y-1">
<li>• Changing assessment data:
<ul class="ml-4 text-xs mt-1 space-y-1">
<li>- ERV answers</li>
<li>- CM answers</li>
<li>- CWR answers</li>
<li>- Termination values</li>
<li>- Background data</li>
</ul>
</li>
<li>• Overwriting non-empty fields</li>
</ul>
</div>
</div>
<div class="mt-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-center">
<p class="text-sm text-gray-800">
<strong>🛡️ Protection Goal:</strong> Prevent accidental data corruption while allowing metadata corrections
</p>
</div>
</div>
<!-- Where Blocked Updates Go -->
<div class="bg-gradient-to-r from-orange-50 to-yellow-50 p-6 rounded-lg border-2 border-orange-300 mb-6">
<h4 class="font-semibold mb-3 text-orange-900">📂 Where Do Blocked Updates Go?</h4>
<div class="text-sm text-gray-700 space-y-3">
<p>When the processor agent detects a data conflict and blocks an upload, the files are moved to a special quarantine location for review:</p>
<div class="bg-white p-4 rounded border-l-4 border-orange-500 mt-3">
<p class="font-semibold mb-2">📁 File Destination:</p>
<div class="bg-gray-800 text-gray-100 p-3 rounded font-mono text-xs">
<div>quarantine_folder/</div>
<div>├── 10523_20251016_14_30.pdf</div>
<div>└── (Logged in CSV: YYYYMMDD_processing_agent.csv)</div>
</div>
<p class="text-xs text-gray-600 mt-2 italic">Note: Quarantine folder path is configurable (default: "unsorted")</p>
</div>
<p><strong>What Happens:</strong></p>
<ol class="list-decimal ml-6 space-y-2">
<li><strong>PDF moved to quarantine folder:</strong> The file is not deleted, just quarantined for manual review</li>
<li><strong>Conflict logged to CSV:</strong> Details written to the daily CSV log file (not individual .log files)</li>
<li><strong>JSON data deleted:</strong> The processed JSON is not saved to prevent corruption</li>
<li><strong>Jotform not updated:</strong> No API call is made to Jotform, protecting existing data</li>
<li><strong>PC number recorded:</strong> The uploader's PC number (from upload.html manual setting) is logged for tracking</li>
</ol>
<p class="mt-3"><strong>⚠️ Important:</strong> Files in quarantine folder require manual review by administrators to determine if:</p>
<ul class="list-disc ml-6 space-y-1">
<li>It's a legitimate re-upload attempt that should be manually processed</li>
<li>It's an accidental duplicate that should be deleted</li>
<li>It's a different student with a similar/wrong filename</li>
</ul>
</div>
</div>
<!-- How Logs Help -->
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 p-6 rounded-lg border-2 border-purple-300 mb-6">
<h4 class="font-semibold mb-3 text-purple-900">📝 How Logs Help Check What Went Wrong</h4>
<div class="text-sm text-gray-700 space-y-3">
<p>The processor agent maintains a detailed CSV log that helps administrators diagnose and resolve conflicts:</p>
<div class="bg-white p-4 rounded border-l-4 border-purple-500 mt-4">
<h5 class="font-semibold mb-2">Daily Processing Log (CSV Format)</h5>
<p class="text-xs mb-2"><code class="bg-gray-200 px-2 py-1 rounded">logs/YYYYMMDD_processing_agent.csv</code></p>
<p class="text-xs mb-2">Single CSV file per day tracking all processing activity</p>
<div class="mt-3 p-2 bg-blue-50 border border-blue-200 rounded text-xs">
<p class="font-semibold mb-1">📌 Configurable Log Levels:</p>
<p class="mb-2">Edit <code class="bg-white px-1 rounded">config/jotform_config.json</code> → "logging" section to enable/disable each level:</p>
<ul class="space-y-0.5 ml-4">
<li>• <strong>REJECT:</strong> Validation failures (sessionkey mismatch, Core ID errors, filename format)</li>
<li>• <strong>DATA_OVERWRITE_DIFF:</strong> Data overwrite conflicts (field-level details)</li>
<li>• <strong>UPLOAD:</strong> Jotform operations (created/updated submissions)</li>
<li>• <strong>FILED:</strong> Successfully archived files with destination folder</li>
<li>• <strong>CLEANUP:</strong> Maintenance operations (orphaned JSON cleanup)</li>
<li>• <strong>RENAME:</strong> Filename normalization (original → canonical)</li>
<li>• <strong>WARN:</strong> Non-critical issues (missing mappings, upload failures)</li>
<li>• <strong>ERROR:</strong> Critical failures (parser errors, exceptions)</li>
<li>• <strong>INFO:</strong> Verbose details (queued, parsing, validating, enriching)</li>
</ul>
<p class="mt-2 text-gray-600 italic">Set each level to <code>true</code> (log) or <code>false</code> (skip) in config</p>
</div>
</div>
<div class="bg-white p-4 rounded border border-purple-200 mt-4">
<p class="font-semibold mb-3">Example CSV Log Entries (as viewed in Excel/CSV reader):</p>
<!-- Excel-like table view -->
<div class="overflow-x-auto">
<table class="w-full text-xs border-collapse">
<thead>
<tr class="bg-gray-100 border-b-2 border-gray-300">
<th class="border border-gray-300 px-3 py-2 text-left font-semibold">Timestamp</th>
<th class="border border-gray-300 px-3 py-2 text-left font-semibold">Level</th>
<th class="border border-gray-300 px-3 py-2 text-left font-semibold">File</th>
<th class="border border-gray-300 px-3 py-2 text-left font-semibold">Message</th>
</tr>
</thead>
<tbody class="font-mono">
<tr class="bg-white hover:bg-gray-50">
<td class="border border-gray-300 px-3 py-2">2025-10-25 14:30:15</td>
<td class="border border-gray-300 px-3 py-2 text-red-600 font-semibold">REJECT</td>
<td class="border border-gray-300 px-3 py-2">10523_20251016_14_30.pdf</td>
<td class="border border-gray-300 px-3 py-2">Phase2 validation failed: Core ID 10523 not in mapping</td>
</tr>
<tr class="bg-gray-50 hover:bg-gray-100">
<td class="border border-gray-300 px-3 py-2">2025-10-25 14:31:22</td>
<td class="border border-gray-300 px-3 py-2 text-orange-600 font-semibold">DATA_OVERWRITE_DIFF</td>
<td class="border border-gray-300 px-3 py-2">10524_20251016_14_35.pdf</td>
<td class="border border-gray-300 px-3 py-2">Field q37_englishReceptive[0]: Current '1' vs Attempted '0'</td>
</tr>
<tr class="bg-white hover:bg-gray-50">
<td class="border border-gray-300 px-3 py-2">2025-10-25 14:32:10</td>
<td class="border border-gray-300 px-3 py-2 text-blue-600 font-semibold">UPLOAD</td>
<td class="border border-gray-300 px-3 py-2">10525_20251016_14_40.pdf</td>
<td class="border border-gray-300 px-3 py-2">Created submission 234567890123456789 (87 fields, 1 chunk)</td>
</tr>
<tr class="bg-gray-50 hover:bg-gray-100">
<td class="border border-gray-300 px-3 py-2">2025-10-25 14:33:05</td>
<td class="border border-gray-300 px-3 py-2 text-green-600 font-semibold">FILED</td>
<td class="border border-gray-300 px-3 py-2">10525_20251016_14_40.pdf</td>
<td class="border border-gray-300 px-3 py-2">10525_20251016_14_40.pdf → S023/</td>
</tr>
</tbody>
</table>
</div>
<p class="text-xs text-gray-600 mt-3 italic">💡 Tip: Open CSV files in Excel, Google Sheets, or VS Code with Rainbow CSV extension for easier filtering and analysis</p>
</div>
<div class="mt-4 p-3 bg-purple-100 border border-purple-300 rounded">
<p class="font-semibold mb-2">Using CSV Logs for Troubleshooting:</p>
<ol class="text-xs space-y-1 ml-4">
<li>1. <strong>Open today's CSV log:</strong> Find YYYYMMDD_processing_agent.csv in the logs directory</li>
<li>2. <strong>Search for filename:</strong> Look for rows with the problematic PDF filename</li>
<li>3. <strong>Check log level:</strong> REJECT/ERROR/CONFLICT indicate problems; SUCCESS/FILED indicate completion</li>
<li>4. <strong>Read the message:</strong> Detailed reason explains exactly what went wrong</li>
<li>5. <strong>Locate quarantined PDF:</strong> Check the quarantine folder for the actual file</li>
<li>6. <strong>Determine action:</strong> Based on the CSV message, decide whether to:
<ul class="list-disc ml-6 mt-1">
<li>Delete the quarantined file (if duplicate/wrong)</li>
<li>Manually fix Jotform data (if existing data is wrong)</li>
<li>Contact test administrator (if assessment needs re-administration)</li>
</ul>
</li>
</ol>
</div>
</div>
</div>
<!-- Retry Logic -->
<h3 class="text-2xl font-semibold mb-4">Upload Retry Strategy</h3>
<div class="bg-blue-50 p-4 rounded border-2 border-blue-300">
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="bg-blue-600 text-white rounded-full w-10 h-10 flex items-center justify-center font-bold flex-shrink-0">1</div>
<div class="text-sm">
<strong>First Attempt:</strong> Immediate upload
</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-blue-600 text-white rounded-full w-10 h-10 flex items-center justify-center font-bold flex-shrink-0">2</div>
<div class="text-sm">
<strong>Retry 1:</strong> Wait 2 seconds + random jitter (0-1s)
</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-blue-600 text-white rounded-full w-10 h-10 flex items-center justify-center font-bold flex-shrink-0">3</div>
<div class="text-sm">
<strong>Retry 2:</strong> Wait 4 seconds + random jitter (0-2s)
</div>
</div>
<div class="flex items-center gap-3">
<div class="bg-blue-600 text-white rounded-full w-10 h-10 flex items-center justify-center font-bold flex-shrink-0">4</div>
<div class="text-sm">
<strong>Retry 3:</strong> Wait 8 seconds + random jitter (0-4s)
</div>
</div>
<div class="mt-3 pt-3 border-t border-blue-200 text-center">
<div class="text-sm">
<strong>If all retries fail:</strong> <span class="text-red-600">File moved to Unsorted/ with error log</span>
</div>
</div>
</div>
</div>
</section>
<!-- Configuration Section -->
<section id="configuration" class="content-section mb-12">
<h2 class="text-3xl font-bold mb-6" style="color: var(--primary)">
<span class="step-number">VII</span>
Configuration and Setup
</h2>
<!-- Config File Overview -->
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-lg border-2 border-blue-300 mb-6">
<h3 class="text-2xl font-semibold mb-4 text-blue-900">📋 Configuration Files</h3>
<p class="text-sm text-gray-700 mb-4">The processor agent uses JSON configuration files to control its behavior. All files are located in the <code class="bg-white px-2 py-1 rounded">config/</code> directory.</p>
<div class="space-y-4">
<div class="bg-white p-4 rounded border-l-4 border-blue-500">
<h4 class="font-semibold text-blue-800 mb-2">config/agent.json</h4>
<p class="text-sm text-gray-700 mb-2"><strong>Purpose:</strong> Main agent configuration - folder paths, OneDrive sync, polling behavior</p>
<details class="text-sm">
<summary class="cursor-pointer font-semibold text-blue-700 hover:text-blue-900">View Key Settings</summary>
<ul class="ml-6 mt-2 space-y-1 text-xs">
<li><strong>oneDrive.relativePath:</strong> Path to project folder within OneDrive</li>
<li><strong>watchPath:</strong> Folder where uploader writes PDFs (default: ./incoming)</li>
<li><strong>stagingPath:</strong> Temporary processing folder (default: ./processing)</li>
<li><strong>filingRoot:</strong> Base folder for organized PDFs (default: ./filed)</li>
<li><strong>unsortedRoot:</strong> Quarantine folder for rejected PDFs (default: ./filed/Unsorted)</li>
<li><strong>worker.maxConcurrent:</strong> Max PDFs processed simultaneously (default: 2)</li>
<li><strong>worker.pollIntervalSeconds:</strong> How often to check for new files (default: 5s)</li>
</ul>
</details>
</div>
<div class="bg-white p-4 rounded border-l-4 border-green-500">
<h4 class="font-semibold text-green-800 mb-2">config/jotform_config.json</h4>
<p class="text-sm text-gray-700 mb-2"><strong>Purpose:</strong> Jotform API settings, retry logic, and log level configuration</p>
<details class="text-sm">
<summary class="cursor-pointer font-semibold text-green-700 hover:text-green-900">View Key Settings</summary>
<ul class="ml-6 mt-2 space-y-1 text-xs">
<li><strong>powershell.maxConcurrentPdfs:</strong> PDFs processed in parallel (default: 2)</li>
<li><strong>powershell.maxRetries:</strong> Upload retry attempts (default: 4)</li>
<li><strong>powershell.rateLimitMs:</strong> Delay between API calls (default: 200ms)</li>
<li><strong>logging.*:</strong> Enable/disable each log level (true/false)</li>
</ul>
<div class="mt-2 p-2 bg-green-50 rounded">
<p class="font-semibold text-xs">💡 See "How Logs Help" section for all 9 configurable log levels</p>
</div>
</details>
</div>
<div class="bg-white p-4 rounded border-l-4 border-purple-500">
<h4 class="font-semibold text-purple-800 mb-2">config/host_identity.json</h4>
<p class="text-sm text-gray-700 mb-2"><strong>Purpose:</strong> Override PC identity (optional - usually auto-detected)</p>
<details class="text-sm">
<summary class="cursor-pointer font-semibold text-purple-700 hover:text-purple-900">View Example</summary>
<pre class="mt-2 p-2 bg-gray-800 text-gray-100 rounded text-xs overflow-x-auto">{
"computerName": "KS095",
"pcNumber": "095"
}</pre>
</details>
</div>
</div>
</div>
<!-- Config GUI -->
<div class="bg-gradient-to-r from-purple-50 to-pink-50 p-6 rounded-lg border-2 border-purple-300 mb-6">
<h3 class="text-2xl font-semibold mb-4 text-purple-900">🖥️ Configuration GUI Tool</h3>
<p class="text-sm text-gray-700 mb-4">A graphical interface for editing agent configuration without manually editing JSON files.</p>
<div class="bg-white p-4 rounded border-l-4 border-purple-500 mb-4">
<h4 class="font-semibold mb-2">How to Launch</h4>
<ol class="list-decimal ml-6 space-y-1 text-sm text-gray-700">
<li>Navigate to <code class="bg-gray-200 px-2 py-1 rounded">tools/</code> directory</li>
<li>Run: <code class="bg-gray-800 text-gray-100 px-2 py-1 rounded">python agent_config_gui.py</code></li>
<li>GUI window opens with editable configuration fields</li>
</ol>
</div>
<div class="grid md:grid-cols-2 gap-4">
<div class="bg-white p-4 rounded shadow">
<h5 class="font-semibold text-purple-800 mb-2">✅ What You Can Edit</h5>
<ul class="text-sm space-y-1">
<li>• OneDrive Relative Path</li>
<li>• Watch Path (incoming folder)</li>
<li>• Staging Path (processing folder)</li>
<li>• Filing Root (organized PDFs)</li>
<li>• Unsorted Root (quarantine folder)</li>
</ul>
</div>
<div class="bg-white p-4 rounded shadow">
<h5 class="font-semibold text-purple-800 mb-2">🛠️ Features</h5>
<ul class="text-sm space-y-1">
<li>• Browse button (...) to select folders</li>
<li>• Save button to persist changes</li>
<li>• Reset to Defaults button</li>
<li>• Reload from File button</li>
<li>• Status bar shows operation results</li>
</ul>
</div>
</div>
<div class="mt-4 p-3 bg-yellow-100 border border-yellow-300 rounded">
<p class="text-sm"><strong>⚠️ Important:</strong> After saving changes in the GUI, restart the processor agent for changes to take effect.</p>
</div>
</div>
<!-- PC Number Config -->
<div class="collapsible-section">
<div class="collapsible-header">
<h3 class="text-xl font-semibold">PC Number Configuration</h3>
<span class="text-2xl">▼</span>
</div>
<div class="collapsible-content">
<h4 class="font-semibold mb-2">Auto-Detection</h4>
<!-- Interactive Screenshot: Upload Configuration Status Badges -->
<div class="border-2 border-gray-300 rounded-lg overflow-hidden my-6 shadow-lg upload-config-preview-container" style="position: relative;">
<!-- "See More" button - shown on hover -->
<button
class="upload-config-enlarge-btn"
onclick="openUploadConfigModal()"
style="position: absolute; top: 12px; right: 12px; z-index: 50; background-color: rgba(43, 57, 144, 0.95); color: white; padding: 8px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; box-shadow: 0 4px 12px rgba(0,0,0,0.2); opacity: 0; transition: opacity 0.2s ease; cursor: pointer; border: none;"
title="See More"
>