@striae-org/striae 6.0.1 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/actions/case-export/core-export.ts +11 -2
- package/app/components/actions/case-export/download-handlers.ts +3 -1
- package/app/components/canvas/canvas.module.css +1 -1
- package/app/components/canvas/canvas.tsx +32 -11
- package/app/components/colors/colors.module.css +19 -0
- package/app/components/colors/colors.tsx +5 -1
- package/app/components/icon/icons.svg +1 -1
- package/app/components/icon/manifest.json +1 -1
- package/app/components/navbar/navbar.tsx +32 -16
- package/app/components/sidebar/cases/case-sidebar.tsx +27 -25
- package/app/components/sidebar/files/files-modal.tsx +39 -15
- package/app/components/sidebar/notes/addl-notes-modal.tsx +9 -2
- package/app/components/sidebar/notes/{class-details/class-details-fields.tsx → item-details/item-details-fields.tsx} +10 -10
- package/app/components/sidebar/notes/{class-details/class-details-modal.tsx → item-details/item-details-modal.tsx} +20 -22
- package/app/components/sidebar/notes/{class-details/class-details-sections.tsx → item-details/item-details-sections.tsx} +16 -16
- package/app/components/sidebar/notes/{class-details/class-details-shared.ts → item-details/item-details-shared.ts} +4 -3
- package/app/components/sidebar/notes/{class-details/use-class-details-state.ts → item-details/use-item-details-state.ts} +4 -4
- package/app/components/sidebar/notes/notes-editor-form.tsx +357 -146
- package/app/components/sidebar/notes/notes-editor-modal.tsx +3 -0
- package/app/components/sidebar/notes/notes.module.css +40 -20
- package/app/components/sidebar/sidebar-container.tsx +1 -1
- package/app/components/sidebar/sidebar.tsx +3 -3
- package/app/components/toolbar/toolbar.tsx +5 -5
- package/app/hooks/useFileListPreferences.ts +22 -17
- package/app/routes/striae/striae.tsx +6 -13
- package/app/types/annotations.ts +29 -5
- package/app/utils/data/confirmation-summary/summary-core.ts +40 -8
- package/app/utils/data/file-filters.ts +39 -17
- package/app/utils/data/permissions.ts +123 -0
- package/package.json +12 -12
- package/workers/audit-worker/package.json +2 -2
- package/workers/audit-worker/wrangler.jsonc.example +1 -1
- package/workers/data-worker/package.json +2 -2
- package/workers/data-worker/wrangler.jsonc.example +1 -1
- package/workers/image-worker/package.json +2 -2
- package/workers/image-worker/wrangler.jsonc.example +1 -1
- package/workers/pdf-worker/package.json +2 -2
- package/workers/pdf-worker/src/formats/format-striae.ts +65 -8
- package/workers/pdf-worker/src/report-types.ts +18 -4
- package/workers/pdf-worker/wrangler.jsonc.example +1 -1
- package/workers/user-worker/package.json +2 -2
- package/workers/user-worker/wrangler.jsonc.example +1 -1
- package/wrangler.toml.example +1 -1
|
@@ -26,6 +26,16 @@ export interface CaseMetadata {
|
|
|
26
26
|
createdAt: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Result for notes viewing permissions
|
|
31
|
+
* Determines if notes can be viewed and in what mode (edit or view-only)
|
|
32
|
+
*/
|
|
33
|
+
export interface NotesViewPermission {
|
|
34
|
+
canOpen: boolean; // Can the notes panel be opened
|
|
35
|
+
isReadOnly: boolean; // Are notes in read-only mode (can view but not edit)
|
|
36
|
+
reason?: string; // Reason if notes cannot be opened
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
/**
|
|
30
40
|
* Get user data from KV store
|
|
31
41
|
*/
|
|
@@ -565,4 +575,117 @@ export const removeUserCase = async (user: User, caseNumber: string): Promise<vo
|
|
|
565
575
|
console.error('Error removing case from user:', error);
|
|
566
576
|
throw error;
|
|
567
577
|
}
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
// ============================================================================
|
|
581
|
+
// NOTES VIEW PERMISSIONS
|
|
582
|
+
// ============================================================================
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Determine if notes can be opened and viewed, and whether they should be in read-only mode
|
|
586
|
+
*
|
|
587
|
+
* Notes can be viewed in the following scenarios:
|
|
588
|
+
* - Normal active case with unconfirmed image: Can edit and save
|
|
589
|
+
* - Active case with confirmed image: Can view only (read-only)
|
|
590
|
+
* - Read-only case (review/confirmation case): Can view only (read-only)
|
|
591
|
+
* - Archived case: Can view only (read-only)
|
|
592
|
+
*
|
|
593
|
+
* Notes cannot be opened when:
|
|
594
|
+
* - Files are uploading
|
|
595
|
+
* - Confirmation status is still being checked
|
|
596
|
+
* - No image is loaded
|
|
597
|
+
*
|
|
598
|
+
* @param config Configuration object with state flags
|
|
599
|
+
* @returns NotesViewPermission object indicating if notes can be opened and if they're read-only
|
|
600
|
+
*/
|
|
601
|
+
export const getNotesViewPermission = (config: {
|
|
602
|
+
imageLoaded: boolean;
|
|
603
|
+
isUploading: boolean;
|
|
604
|
+
isCheckingConfirmation: boolean;
|
|
605
|
+
isReadOnlyCase?: boolean;
|
|
606
|
+
isArchivedCase?: boolean;
|
|
607
|
+
isConfirmedImage?: boolean;
|
|
608
|
+
}): NotesViewPermission => {
|
|
609
|
+
const {
|
|
610
|
+
imageLoaded,
|
|
611
|
+
isUploading,
|
|
612
|
+
isCheckingConfirmation,
|
|
613
|
+
isReadOnlyCase = false,
|
|
614
|
+
isArchivedCase = false,
|
|
615
|
+
isConfirmedImage = false
|
|
616
|
+
} = config;
|
|
617
|
+
|
|
618
|
+
// Cannot open if uploading files
|
|
619
|
+
if (isUploading) {
|
|
620
|
+
return {
|
|
621
|
+
canOpen: false,
|
|
622
|
+
isReadOnly: false,
|
|
623
|
+
reason: 'Cannot open notes while uploading'
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Cannot open if checking confirmation status
|
|
628
|
+
if (isCheckingConfirmation) {
|
|
629
|
+
return {
|
|
630
|
+
canOpen: false,
|
|
631
|
+
isReadOnly: false,
|
|
632
|
+
reason: 'Checking confirmation status...'
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Cannot open if no image is loaded
|
|
637
|
+
if (!imageLoaded) {
|
|
638
|
+
return {
|
|
639
|
+
canOpen: false,
|
|
640
|
+
isReadOnly: false,
|
|
641
|
+
reason: 'Select an image first'
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// Can open, determine if read-only
|
|
646
|
+
const isReadOnly = isConfirmedImage || isReadOnlyCase || isArchivedCase;
|
|
647
|
+
|
|
648
|
+
return {
|
|
649
|
+
canOpen: true,
|
|
650
|
+
isReadOnly
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Get a user-friendly tooltip message for the Image Notes button
|
|
656
|
+
*
|
|
657
|
+
* This centralizes all the tooltip logic that appears in the navbar and sidebar
|
|
658
|
+
*
|
|
659
|
+
* @param permission NotesViewPermission object from getNotesViewPermission
|
|
660
|
+
* @param additionalContext Optional context for more specific messages
|
|
661
|
+
* @returns Tooltip string, or undefined if button has no specific tooltip
|
|
662
|
+
*/
|
|
663
|
+
export const getNotesButtonTooltip = (
|
|
664
|
+
permission: NotesViewPermission,
|
|
665
|
+
additionalContext?: {
|
|
666
|
+
isReadOnlyCase?: boolean;
|
|
667
|
+
isArchivedCase?: boolean;
|
|
668
|
+
isConfirmedImage?: boolean;
|
|
669
|
+
}
|
|
670
|
+
): string | undefined => {
|
|
671
|
+
// If cannot open, return the reason
|
|
672
|
+
if (!permission.canOpen) {
|
|
673
|
+
return permission.reason;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Can open - provide context-specific read-only messages
|
|
677
|
+
if (permission.isReadOnly && additionalContext) {
|
|
678
|
+
if (additionalContext.isConfirmedImage) {
|
|
679
|
+
return 'Image notes: viewing only (image is confirmed)';
|
|
680
|
+
}
|
|
681
|
+
if (additionalContext.isReadOnlyCase) {
|
|
682
|
+
return 'Image notes: viewing only (case is read-only)';
|
|
683
|
+
}
|
|
684
|
+
if (additionalContext.isArchivedCase) {
|
|
685
|
+
return 'Image notes: viewing only (case is archived)';
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// No tooltip needed for normal edit mode
|
|
690
|
+
return undefined;
|
|
568
691
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@striae-org/striae",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Striae is a specialized, cloud-native platform designed to streamline forensic firearms identification by providing an intuitive environment for digital comparison image annotation, authenticated confirmations, and automated report generation.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,12 +50,12 @@
|
|
|
50
50
|
"workers/pdf-worker/src/assets/generated-assets.example.ts",
|
|
51
51
|
"!workers/pdf-worker/src/formats/**/*",
|
|
52
52
|
"workers/pdf-worker/src/formats/format-striae.ts",
|
|
53
|
-
".env.example",
|
|
53
|
+
".env.example",
|
|
54
54
|
"firebase.json",
|
|
55
55
|
"tsconfig.json",
|
|
56
56
|
"vite.config.ts",
|
|
57
57
|
"/worker-configuration.d.ts",
|
|
58
|
-
"wrangler.toml.example",
|
|
58
|
+
"wrangler.toml.example",
|
|
59
59
|
"LICENSE"
|
|
60
60
|
],
|
|
61
61
|
"sideEffects": false,
|
|
@@ -100,23 +100,23 @@
|
|
|
100
100
|
"deploy-workers:user": "cd workers/user-worker && npm run deploy"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
|
-
"@react-router/cloudflare": "^7.14.
|
|
103
|
+
"@react-router/cloudflare": "^7.14.1",
|
|
104
104
|
"firebase": "^12.12.0",
|
|
105
|
-
"isbot": "^5.1.
|
|
105
|
+
"isbot": "^5.1.38",
|
|
106
106
|
"jszip": "^3.10.1",
|
|
107
107
|
"qrcode": "^1.5.4",
|
|
108
108
|
"react": "^19.2.5",
|
|
109
109
|
"react-dom": "^19.2.5",
|
|
110
|
-
"react-router": "^7.14.
|
|
110
|
+
"react-router": "^7.14.1"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
|
-
"@react-router/dev": "^7.14.
|
|
114
|
-
"@react-router/fs-routes": "^7.14.
|
|
113
|
+
"@react-router/dev": "^7.14.1",
|
|
114
|
+
"@react-router/fs-routes": "^7.14.1",
|
|
115
115
|
"@types/qrcode": "^1.5.6",
|
|
116
116
|
"@types/react": "^19.2.14",
|
|
117
117
|
"@types/react-dom": "^19.2.3",
|
|
118
|
-
"@typescript-eslint/eslint-plugin": "^8.58.
|
|
119
|
-
"@typescript-eslint/parser": "^8.58.
|
|
118
|
+
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
|
119
|
+
"@typescript-eslint/parser": "^8.58.2",
|
|
120
120
|
"eslint": "^9.39.4",
|
|
121
121
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
122
122
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"typescript": "^5.9.3",
|
|
129
129
|
"vite": "^7.3.2",
|
|
130
130
|
"vite-tsconfig-paths": "^6.1.1",
|
|
131
|
-
"wrangler": "^4.
|
|
131
|
+
"wrangler": "^4.83.0"
|
|
132
132
|
},
|
|
133
133
|
"overrides": {
|
|
134
134
|
"@tootallnate/once": "3.0.1"
|
|
@@ -136,5 +136,5 @@
|
|
|
136
136
|
"engines": {
|
|
137
137
|
"node": ">=20.19.0"
|
|
138
138
|
},
|
|
139
|
-
"packageManager": "npm@11.
|
|
139
|
+
"packageManager": "npm@11.12.0"
|
|
140
140
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audit-worker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"deploy": "wrangler deploy",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"start": "wrangler dev"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"wrangler": "^4.
|
|
11
|
+
"wrangler": "^4.83.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-worker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"deploy": "wrangler deploy",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"start": "wrangler dev"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"wrangler": "^4.
|
|
11
|
+
"wrangler": "^4.83.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "image-worker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"deploy": "wrangler deploy",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"start": "wrangler dev"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"wrangler": "^4.
|
|
11
|
+
"wrangler": "^4.83.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-worker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"generate:assets": "node scripts/generate-assets.js",
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
"start": "wrangler dev"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"wrangler": "^4.
|
|
12
|
+
"wrangler": "^4.83.0"
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -7,6 +7,14 @@ export const renderReport: ReportRenderer = (data: PDFGenerationData): string =>
|
|
|
7
7
|
const annotationsSet = new Set(activeAnnotations);
|
|
8
8
|
const hasImage = Boolean(imageUrl && imageUrl !== '/clear.jpg');
|
|
9
9
|
const safeText = (value: unknown): string => escapeHtml(String(value ?? ''));
|
|
10
|
+
const leftAdditionalNotes = annotationData?.leftAdditionalNotes?.trim() || '';
|
|
11
|
+
const rightAdditionalNotes = annotationData?.rightAdditionalNotes?.trim() || '';
|
|
12
|
+
const generalAdditionalNotes = annotationData?.additionalNotes?.trim() || '';
|
|
13
|
+
const hasSideAdditionalNotes = Boolean(leftAdditionalNotes || rightAdditionalNotes);
|
|
14
|
+
const hasGeneralAdditionalNotes = Boolean(generalAdditionalNotes);
|
|
15
|
+
const hasAdditionalNotes = hasSideAdditionalNotes || hasGeneralAdditionalNotes;
|
|
16
|
+
const hasConfirmationOrNotes = Boolean(annotationData && ((annotationData.includeConfirmation === true) || hasAdditionalNotes));
|
|
17
|
+
const notesShouldStartNewPage = hasImage || annotationData?.includeConfirmation === true;
|
|
10
18
|
|
|
11
19
|
// Programmatically determine if a color is dark and needs a light background
|
|
12
20
|
const needsLightBackground = (color: string | undefined): boolean => {
|
|
@@ -323,6 +331,15 @@ export const renderReport: ReportRenderer = (data: PDFGenerationData): string =>
|
|
|
323
331
|
font-family: 'Inter', Arial, sans-serif;
|
|
324
332
|
color: #333;
|
|
325
333
|
}
|
|
334
|
+
.additional-notes-grid {
|
|
335
|
+
display: flex;
|
|
336
|
+
align-items: stretch;
|
|
337
|
+
gap: 12px;
|
|
338
|
+
}
|
|
339
|
+
.additional-notes-section--half {
|
|
340
|
+
flex: 1 1 50%;
|
|
341
|
+
width: 50%;
|
|
342
|
+
}
|
|
326
343
|
.additional-notes-title {
|
|
327
344
|
margin: 0 0 10px;
|
|
328
345
|
font-size: 12px;
|
|
@@ -415,15 +432,31 @@ export const renderReport: ReportRenderer = (data: PDFGenerationData): string =>
|
|
|
415
432
|
</div>
|
|
416
433
|
` : '<div class="support-level-annotation"></div>'}
|
|
417
434
|
|
|
418
|
-
${annotationData && annotationsSet?.has('
|
|
435
|
+
${annotationData && annotationsSet?.has('item') ? `
|
|
419
436
|
<div class="class-annotation">
|
|
420
437
|
<div class="class-text-annotation">
|
|
421
|
-
${
|
|
438
|
+
${(() => {
|
|
439
|
+
const leftValue = annotationData.leftCustomClass || annotationData.leftItemType;
|
|
440
|
+
const rightValue = annotationData.rightCustomClass || annotationData.rightItemType;
|
|
441
|
+
const legacyValue = annotationData.customClass || annotationData.itemType || annotationData.classType;
|
|
442
|
+
const displayValue =
|
|
443
|
+
leftValue && rightValue && leftValue !== rightValue
|
|
444
|
+
? `${leftValue} / ${rightValue}`
|
|
445
|
+
: leftValue || rightValue || legacyValue;
|
|
446
|
+
const leftClassNote = annotationData.leftClassNote?.trim();
|
|
447
|
+
const rightClassNote = annotationData.rightClassNote?.trim();
|
|
448
|
+
const legacyClassNote = annotationData.classNote?.trim();
|
|
449
|
+
const displayClassNote =
|
|
450
|
+
leftClassNote && rightClassNote && leftClassNote !== rightClassNote
|
|
451
|
+
? `${leftClassNote} / ${rightClassNote}`
|
|
452
|
+
: leftClassNote || rightClassNote || legacyClassNote;
|
|
453
|
+
return safeText(displayValue || '') + (displayClassNote ? ` (${safeText(displayClassNote)})` : '');
|
|
454
|
+
})()}
|
|
422
455
|
</div>
|
|
423
456
|
</div>
|
|
424
457
|
` : '<div class="class-annotation"></div>'}
|
|
425
458
|
|
|
426
|
-
${annotationData && annotationsSet?.has('
|
|
459
|
+
${annotationData && annotationsSet?.has('item') && (annotationData.leftHasSubclass || annotationData.rightHasSubclass || annotationData.hasSubclass) ? `
|
|
427
460
|
<div class="subclass-annotation">
|
|
428
461
|
<div class="subclass-text">
|
|
429
462
|
POTENTIAL SUBCLASS
|
|
@@ -434,7 +467,7 @@ export const renderReport: ReportRenderer = (data: PDFGenerationData): string =>
|
|
|
434
467
|
</div>
|
|
435
468
|
` : ''}
|
|
436
469
|
|
|
437
|
-
${
|
|
470
|
+
${hasConfirmationOrNotes ? `
|
|
438
471
|
<div class="confirmation-section">
|
|
439
472
|
${annotationData && (annotationData.includeConfirmation === true) ? `
|
|
440
473
|
<div class="confirmation-summary">
|
|
@@ -465,10 +498,34 @@ export const renderReport: ReportRenderer = (data: PDFGenerationData): string =>
|
|
|
465
498
|
</div>
|
|
466
499
|
` : ''}
|
|
467
500
|
|
|
468
|
-
${annotationData && annotationsSet?.has('notes') &&
|
|
469
|
-
<section class="
|
|
470
|
-
|
|
471
|
-
|
|
501
|
+
${annotationData && annotationsSet?.has('notes') && hasAdditionalNotes ? `
|
|
502
|
+
<section class="${notesShouldStartNewPage ? 'notes-page' : ''}">
|
|
503
|
+
${hasSideAdditionalNotes ? `
|
|
504
|
+
${leftAdditionalNotes && rightAdditionalNotes ? `
|
|
505
|
+
<div class="additional-notes-grid">
|
|
506
|
+
<div class="additional-notes-section additional-notes-section--half">
|
|
507
|
+
<h2 class="additional-notes-title">Additional Notes (L)</h2>
|
|
508
|
+
<p class="additional-notes-body">${escapeHtml(leftAdditionalNotes)}</p>
|
|
509
|
+
</div>
|
|
510
|
+
<div class="additional-notes-section additional-notes-section--half">
|
|
511
|
+
<h2 class="additional-notes-title">Additional Notes (R)</h2>
|
|
512
|
+
<p class="additional-notes-body">${escapeHtml(rightAdditionalNotes)}</p>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
` : `
|
|
516
|
+
<div class="additional-notes-section">
|
|
517
|
+
<h2 class="additional-notes-title">Additional Notes (${leftAdditionalNotes ? 'L' : 'R'})</h2>
|
|
518
|
+
<p class="additional-notes-body">${escapeHtml(leftAdditionalNotes || rightAdditionalNotes)}</p>
|
|
519
|
+
</div>
|
|
520
|
+
`}
|
|
521
|
+
` : ''}
|
|
522
|
+
|
|
523
|
+
${hasGeneralAdditionalNotes ? `
|
|
524
|
+
<div class="additional-notes-section" style="margin-top: ${hasSideAdditionalNotes ? '12px' : '0'};">
|
|
525
|
+
<h2 class="additional-notes-title">Additional Notes (General)</h2>
|
|
526
|
+
<p class="additional-notes-body">${escapeHtml(generalAdditionalNotes)}</p>
|
|
527
|
+
</div>
|
|
528
|
+
` : ''}
|
|
472
529
|
</section>
|
|
473
530
|
` : ''}
|
|
474
531
|
</div>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { IndexType, SupportLevel } from '../../../shared/types/annotation-literals';
|
|
2
|
+
|
|
1
3
|
export interface BoxAnnotation {
|
|
2
4
|
x: number;
|
|
3
5
|
y: number;
|
|
@@ -16,7 +18,7 @@ export interface ConfirmationData {
|
|
|
16
18
|
|
|
17
19
|
export interface AnnotationData {
|
|
18
20
|
// Index annotations
|
|
19
|
-
indexType?:
|
|
21
|
+
indexType?: IndexType;
|
|
20
22
|
indexNumber?: string;
|
|
21
23
|
indexColor?: string;
|
|
22
24
|
|
|
@@ -31,9 +33,19 @@ export interface AnnotationData {
|
|
|
31
33
|
boxAnnotations?: BoxAnnotation[];
|
|
32
34
|
|
|
33
35
|
// ID/Support level annotations
|
|
34
|
-
supportLevel?:
|
|
35
|
-
|
|
36
|
-
// Class annotations
|
|
36
|
+
supportLevel?: SupportLevel;
|
|
37
|
+
|
|
38
|
+
// Class annotations (left/right per-item)
|
|
39
|
+
leftItemType?: string;
|
|
40
|
+
leftCustomClass?: string;
|
|
41
|
+
leftClassNote?: string;
|
|
42
|
+
leftHasSubclass?: boolean;
|
|
43
|
+
rightItemType?: string;
|
|
44
|
+
rightCustomClass?: string;
|
|
45
|
+
rightClassNote?: string;
|
|
46
|
+
rightHasSubclass?: boolean;
|
|
47
|
+
// Legacy (kept for backward compatibility)
|
|
48
|
+
itemType?: string;
|
|
37
49
|
classType?: string;
|
|
38
50
|
customClass?: string;
|
|
39
51
|
classNote?: string;
|
|
@@ -44,6 +56,8 @@ export interface AnnotationData {
|
|
|
44
56
|
confirmationData?: ConfirmationData;
|
|
45
57
|
|
|
46
58
|
// Notes
|
|
59
|
+
leftAdditionalNotes?: string;
|
|
60
|
+
rightAdditionalNotes?: string;
|
|
47
61
|
additionalNotes?: string;
|
|
48
62
|
}
|
|
49
63
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "user-worker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"deploy": "wrangler deploy",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"start": "wrangler dev"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"wrangler": "^4.
|
|
11
|
+
"wrangler": "^4.83.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
package/wrangler.toml.example
CHANGED