@striae-org/striae 6.0.1 → 6.1.0
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/icon/icons.svg +1 -1
- package/app/components/icon/manifest.json +1 -1
- package/app/components/navbar/navbar.tsx +10 -9
- package/app/components/sidebar/cases/case-sidebar.tsx +6 -1
- 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 +333 -124
- 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 -0
- package/app/components/sidebar/sidebar.tsx +3 -0
- package/app/components/toolbar/toolbar.tsx +5 -5
- package/app/hooks/useFileListPreferences.ts +22 -17
- package/app/routes/striae/striae.tsx +4 -10
- package/app/types/annotations.ts +28 -5
- package/app/utils/data/confirmation-summary/summary-core.ts +40 -8
- package/app/utils/data/file-filters.ts +39 -17
- package/package.json +139 -139
- 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 +13 -1
- 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
package/package.json
CHANGED
|
@@ -1,140 +1,140 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@striae-org/striae",
|
|
3
|
-
"version": "6.0
|
|
4
|
-
"private": false,
|
|
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
|
-
"license": "Apache-2.0",
|
|
7
|
-
"homepage": "https://github.com/striae-org/striae/wiki",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/striae-org/striae.git"
|
|
11
|
-
},
|
|
12
|
-
"funding": {
|
|
13
|
-
"type": "github",
|
|
14
|
-
"url": "https://github.com/sponsors/striae-org"
|
|
15
|
-
},
|
|
16
|
-
"bugs": {
|
|
17
|
-
"url": "https://github.com/striae-org/striae/issues"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"forensics",
|
|
21
|
-
"firearms",
|
|
22
|
-
"annotation",
|
|
23
|
-
"react",
|
|
24
|
-
"cloudflare-workers",
|
|
25
|
-
"authenticated",
|
|
26
|
-
"confirmations",
|
|
27
|
-
"chain-of-custody",
|
|
28
|
-
"audit-trail"
|
|
29
|
-
],
|
|
30
|
-
"publishConfig": {
|
|
31
|
-
"access": "public"
|
|
32
|
-
},
|
|
33
|
-
"files": [
|
|
34
|
-
"app/",
|
|
35
|
-
"!app/config",
|
|
36
|
-
"!app/routes/auth/login.tsx",
|
|
37
|
-
"!app/routes/auth/login.module.css",
|
|
38
|
-
"react-router.config.ts",
|
|
39
|
-
"load-context.ts",
|
|
40
|
-
"scripts/",
|
|
41
|
-
"functions/",
|
|
42
|
-
"public/",
|
|
43
|
-
"workers/",
|
|
44
|
-
"!workers/*/.wrangler",
|
|
45
|
-
"!workers/*/package-lock.json",
|
|
46
|
-
"!workers/*/worker-configuration.d.ts",
|
|
47
|
-
"!workers/*/wrangler.jsonc",
|
|
48
|
-
"!workers/*/src/**/*worker.ts",
|
|
49
|
-
"!workers/pdf-worker/src/assets/**/*",
|
|
50
|
-
"workers/pdf-worker/src/assets/generated-assets.example.ts",
|
|
51
|
-
"!workers/pdf-worker/src/formats/**/*",
|
|
52
|
-
"workers/pdf-worker/src/formats/format-striae.ts",
|
|
53
|
-
".env.example",
|
|
54
|
-
"firebase.json",
|
|
55
|
-
"tsconfig.json",
|
|
56
|
-
"vite.config.ts",
|
|
57
|
-
"/worker-configuration.d.ts",
|
|
58
|
-
"wrangler.toml.example",
|
|
59
|
-
"LICENSE"
|
|
60
|
-
],
|
|
61
|
-
"sideEffects": false,
|
|
62
|
-
"type": "module",
|
|
63
|
-
"scripts": {
|
|
64
|
-
"deploy:all": "bash ./scripts/deploy-all.sh",
|
|
65
|
-
"emulators": "firebase emulators:start --only auth",
|
|
66
|
-
"dev": "node ./scripts/dev.cjs && react-router dev",
|
|
67
|
-
"build": "node ./scripts/dev.cjs && react-router build",
|
|
68
|
-
"clean": "rm -rf build node_modules/.cache .cache",
|
|
69
|
-
"clean:build": "npm run clean && npm run build",
|
|
70
|
-
"deploy": "npm run build && wrangler pages deploy",
|
|
71
|
-
"publish:npm": "npm publish --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
72
|
-
"publish:npm:dry-run": "npm publish --dry-run --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
73
|
-
"publish:github": "npm publish --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
74
|
-
"publish:github:dry-run": "npm publish --dry-run --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
75
|
-
"publish:all": "npm run publish:npm && npm run publish:github",
|
|
76
|
-
"publish:all:dry-run": "npm run publish:npm:dry-run && npm run publish:github:dry-run",
|
|
77
|
-
"lint": "node ./scripts/run-eslint.cjs",
|
|
78
|
-
"start": "node ./scripts/dev.cjs && wrangler pages dev",
|
|
79
|
-
"typecheck": "react-router typegen && tsc",
|
|
80
|
-
"typegen": "wrangler types",
|
|
81
|
-
"preview": "npm run build && wrangler pages dev",
|
|
82
|
-
"cf-typegen": "wrangler types",
|
|
83
|
-
"enable-totp-mfa": "node ./scripts/enable-totp-mfa.mjs",
|
|
84
|
-
"unenroll-totp-mfa": "node ./scripts/unenroll-totp-mfa.mjs",
|
|
85
|
-
"update-versions": "node ./scripts/update-markdown-versions.cjs",
|
|
86
|
-
"update-compatibility-dates": "node ./scripts/update-compatibility-dates.cjs",
|
|
87
|
-
"deploy-config": "bash ./scripts/deploy-config.sh",
|
|
88
|
-
"update-env": "bash ./scripts/deploy-config.sh --update-env",
|
|
89
|
-
"install-workers": "bash ./scripts/install-workers.sh",
|
|
90
|
-
"deploy-workers": "npm run deploy-workers:audit && npm run deploy-workers:data && npm run deploy-workers:image && npm run deploy-workers:pdf && npm run deploy-workers:user",
|
|
91
|
-
"deploy-workers:secrets": "bash ./scripts/deploy-worker-secrets.sh",
|
|
92
|
-
"deploy-pages:secrets": "bash ./scripts/deploy-pages-secrets.sh",
|
|
93
|
-
"deploy-pages": "bash ./scripts/deploy-pages.sh",
|
|
94
|
-
"deploy-primershear": "bash ./scripts/deploy-primershear-emails.sh",
|
|
95
|
-
"deploy-members": "bash ./scripts/deploy-members-emails.sh",
|
|
96
|
-
"deploy-workers:audit": "cd workers/audit-worker && npm run deploy",
|
|
97
|
-
"deploy-workers:data": "cd workers/data-worker && npm run deploy",
|
|
98
|
-
"deploy-workers:image": "cd workers/image-worker && npm run deploy",
|
|
99
|
-
"deploy-workers:pdf": "cd workers/pdf-worker && npm run deploy",
|
|
100
|
-
"deploy-workers:user": "cd workers/user-worker && npm run deploy"
|
|
101
|
-
},
|
|
102
|
-
"dependencies": {
|
|
103
|
-
"@react-router/cloudflare": "^7.14.
|
|
104
|
-
"firebase": "^12.12.0",
|
|
105
|
-
"isbot": "^5.1.
|
|
106
|
-
"jszip": "^3.10.1",
|
|
107
|
-
"qrcode": "^1.5.4",
|
|
108
|
-
"react": "^19.2.5",
|
|
109
|
-
"react-dom": "^19.2.5",
|
|
110
|
-
"react-router": "^7.14.
|
|
111
|
-
},
|
|
112
|
-
"devDependencies": {
|
|
113
|
-
"@react-router/dev": "^7.14.
|
|
114
|
-
"@react-router/fs-routes": "^7.14.
|
|
115
|
-
"@types/qrcode": "^1.5.6",
|
|
116
|
-
"@types/react": "^19.2.14",
|
|
117
|
-
"@types/react-dom": "^19.2.3",
|
|
118
|
-
"@typescript-eslint/eslint-plugin": "^8.58.
|
|
119
|
-
"@typescript-eslint/parser": "^8.58.
|
|
120
|
-
"eslint": "^9.39.4",
|
|
121
|
-
"eslint-import-resolver-typescript": "^4.4.4",
|
|
122
|
-
"eslint-plugin-import": "^2.32.0",
|
|
123
|
-
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
124
|
-
"eslint-plugin-react": "^7.37.5",
|
|
125
|
-
"eslint-plugin-react-hooks": "^7.0.1",
|
|
126
|
-
"firebase-admin": "^13.8.0",
|
|
127
|
-
"modern-normalize": "^3.0.1",
|
|
128
|
-
"typescript": "^5.9.3",
|
|
129
|
-
"vite": "^7.3.2",
|
|
130
|
-
"vite-tsconfig-paths": "^6.1.1",
|
|
131
|
-
"wrangler": "^4.
|
|
132
|
-
},
|
|
133
|
-
"overrides": {
|
|
134
|
-
"@tootallnate/once": "3.0.1"
|
|
135
|
-
},
|
|
136
|
-
"engines": {
|
|
137
|
-
"node": ">=20.19.0"
|
|
138
|
-
},
|
|
139
|
-
"packageManager": "npm@11.
|
|
1
|
+
{
|
|
2
|
+
"name": "@striae-org/striae",
|
|
3
|
+
"version": "6.1.0",
|
|
4
|
+
"private": false,
|
|
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
|
+
"license": "Apache-2.0",
|
|
7
|
+
"homepage": "https://github.com/striae-org/striae/wiki",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/striae-org/striae.git"
|
|
11
|
+
},
|
|
12
|
+
"funding": {
|
|
13
|
+
"type": "github",
|
|
14
|
+
"url": "https://github.com/sponsors/striae-org"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/striae-org/striae/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"forensics",
|
|
21
|
+
"firearms",
|
|
22
|
+
"annotation",
|
|
23
|
+
"react",
|
|
24
|
+
"cloudflare-workers",
|
|
25
|
+
"authenticated",
|
|
26
|
+
"confirmations",
|
|
27
|
+
"chain-of-custody",
|
|
28
|
+
"audit-trail"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"app/",
|
|
35
|
+
"!app/config",
|
|
36
|
+
"!app/routes/auth/login.tsx",
|
|
37
|
+
"!app/routes/auth/login.module.css",
|
|
38
|
+
"react-router.config.ts",
|
|
39
|
+
"load-context.ts",
|
|
40
|
+
"scripts/",
|
|
41
|
+
"functions/",
|
|
42
|
+
"public/",
|
|
43
|
+
"workers/",
|
|
44
|
+
"!workers/*/.wrangler",
|
|
45
|
+
"!workers/*/package-lock.json",
|
|
46
|
+
"!workers/*/worker-configuration.d.ts",
|
|
47
|
+
"!workers/*/wrangler.jsonc",
|
|
48
|
+
"!workers/*/src/**/*worker.ts",
|
|
49
|
+
"!workers/pdf-worker/src/assets/**/*",
|
|
50
|
+
"workers/pdf-worker/src/assets/generated-assets.example.ts",
|
|
51
|
+
"!workers/pdf-worker/src/formats/**/*",
|
|
52
|
+
"workers/pdf-worker/src/formats/format-striae.ts",
|
|
53
|
+
".env.example",
|
|
54
|
+
"firebase.json",
|
|
55
|
+
"tsconfig.json",
|
|
56
|
+
"vite.config.ts",
|
|
57
|
+
"/worker-configuration.d.ts",
|
|
58
|
+
"wrangler.toml.example",
|
|
59
|
+
"LICENSE"
|
|
60
|
+
],
|
|
61
|
+
"sideEffects": false,
|
|
62
|
+
"type": "module",
|
|
63
|
+
"scripts": {
|
|
64
|
+
"deploy:all": "bash ./scripts/deploy-all.sh",
|
|
65
|
+
"emulators": "firebase emulators:start --only auth",
|
|
66
|
+
"dev": "node ./scripts/dev.cjs && react-router dev",
|
|
67
|
+
"build": "node ./scripts/dev.cjs && react-router build",
|
|
68
|
+
"clean": "rm -rf build node_modules/.cache .cache",
|
|
69
|
+
"clean:build": "npm run clean && npm run build",
|
|
70
|
+
"deploy": "npm run build && wrangler pages deploy",
|
|
71
|
+
"publish:npm": "npm publish --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
72
|
+
"publish:npm:dry-run": "npm publish --dry-run --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
73
|
+
"publish:github": "npm publish --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
74
|
+
"publish:github:dry-run": "npm publish --dry-run --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
75
|
+
"publish:all": "npm run publish:npm && npm run publish:github",
|
|
76
|
+
"publish:all:dry-run": "npm run publish:npm:dry-run && npm run publish:github:dry-run",
|
|
77
|
+
"lint": "node ./scripts/run-eslint.cjs",
|
|
78
|
+
"start": "node ./scripts/dev.cjs && wrangler pages dev",
|
|
79
|
+
"typecheck": "react-router typegen && tsc",
|
|
80
|
+
"typegen": "wrangler types",
|
|
81
|
+
"preview": "npm run build && wrangler pages dev",
|
|
82
|
+
"cf-typegen": "wrangler types",
|
|
83
|
+
"enable-totp-mfa": "node ./scripts/enable-totp-mfa.mjs",
|
|
84
|
+
"unenroll-totp-mfa": "node ./scripts/unenroll-totp-mfa.mjs",
|
|
85
|
+
"update-versions": "node ./scripts/update-markdown-versions.cjs",
|
|
86
|
+
"update-compatibility-dates": "node ./scripts/update-compatibility-dates.cjs",
|
|
87
|
+
"deploy-config": "bash ./scripts/deploy-config.sh",
|
|
88
|
+
"update-env": "bash ./scripts/deploy-config.sh --update-env",
|
|
89
|
+
"install-workers": "bash ./scripts/install-workers.sh",
|
|
90
|
+
"deploy-workers": "npm run deploy-workers:audit && npm run deploy-workers:data && npm run deploy-workers:image && npm run deploy-workers:pdf && npm run deploy-workers:user",
|
|
91
|
+
"deploy-workers:secrets": "bash ./scripts/deploy-worker-secrets.sh",
|
|
92
|
+
"deploy-pages:secrets": "bash ./scripts/deploy-pages-secrets.sh",
|
|
93
|
+
"deploy-pages": "bash ./scripts/deploy-pages.sh",
|
|
94
|
+
"deploy-primershear": "bash ./scripts/deploy-primershear-emails.sh",
|
|
95
|
+
"deploy-members": "bash ./scripts/deploy-members-emails.sh",
|
|
96
|
+
"deploy-workers:audit": "cd workers/audit-worker && npm run deploy",
|
|
97
|
+
"deploy-workers:data": "cd workers/data-worker && npm run deploy",
|
|
98
|
+
"deploy-workers:image": "cd workers/image-worker && npm run deploy",
|
|
99
|
+
"deploy-workers:pdf": "cd workers/pdf-worker && npm run deploy",
|
|
100
|
+
"deploy-workers:user": "cd workers/user-worker && npm run deploy"
|
|
101
|
+
},
|
|
102
|
+
"dependencies": {
|
|
103
|
+
"@react-router/cloudflare": "^7.14.1",
|
|
104
|
+
"firebase": "^12.12.0",
|
|
105
|
+
"isbot": "^5.1.38",
|
|
106
|
+
"jszip": "^3.10.1",
|
|
107
|
+
"qrcode": "^1.5.4",
|
|
108
|
+
"react": "^19.2.5",
|
|
109
|
+
"react-dom": "^19.2.5",
|
|
110
|
+
"react-router": "^7.14.1"
|
|
111
|
+
},
|
|
112
|
+
"devDependencies": {
|
|
113
|
+
"@react-router/dev": "^7.14.1",
|
|
114
|
+
"@react-router/fs-routes": "^7.14.1",
|
|
115
|
+
"@types/qrcode": "^1.5.6",
|
|
116
|
+
"@types/react": "^19.2.14",
|
|
117
|
+
"@types/react-dom": "^19.2.3",
|
|
118
|
+
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
|
119
|
+
"@typescript-eslint/parser": "^8.58.2",
|
|
120
|
+
"eslint": "^9.39.4",
|
|
121
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
122
|
+
"eslint-plugin-import": "^2.32.0",
|
|
123
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
124
|
+
"eslint-plugin-react": "^7.37.5",
|
|
125
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
126
|
+
"firebase-admin": "^13.8.0",
|
|
127
|
+
"modern-normalize": "^3.0.1",
|
|
128
|
+
"typescript": "^5.9.3",
|
|
129
|
+
"vite": "^7.3.2",
|
|
130
|
+
"vite-tsconfig-paths": "^6.1.1",
|
|
131
|
+
"wrangler": "^4.82.2"
|
|
132
|
+
},
|
|
133
|
+
"overrides": {
|
|
134
|
+
"@tootallnate/once": "3.0.1"
|
|
135
|
+
},
|
|
136
|
+
"engines": {
|
|
137
|
+
"node": ">=20.19.0"
|
|
138
|
+
},
|
|
139
|
+
"packageManager": "npm@11.12.0"
|
|
140
140
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audit-worker",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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.82.2"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-worker",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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.82.2"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "image-worker",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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.82.2"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-worker",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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.82.2"
|
|
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>
|
|
@@ -33,7 +33,17 @@ export interface AnnotationData {
|
|
|
33
33
|
// ID/Support level annotations
|
|
34
34
|
supportLevel?: 'ID' | 'Exclusion' | 'Inconclusive';
|
|
35
35
|
|
|
36
|
-
// Class annotations
|
|
36
|
+
// Class annotations (left/right per-item)
|
|
37
|
+
leftItemType?: string;
|
|
38
|
+
leftCustomClass?: string;
|
|
39
|
+
leftClassNote?: string;
|
|
40
|
+
leftHasSubclass?: boolean;
|
|
41
|
+
rightItemType?: string;
|
|
42
|
+
rightCustomClass?: string;
|
|
43
|
+
rightClassNote?: string;
|
|
44
|
+
rightHasSubclass?: boolean;
|
|
45
|
+
// Legacy (kept for backward compatibility)
|
|
46
|
+
itemType?: string;
|
|
37
47
|
classType?: string;
|
|
38
48
|
customClass?: string;
|
|
39
49
|
classNote?: string;
|
|
@@ -44,6 +54,8 @@ export interface AnnotationData {
|
|
|
44
54
|
confirmationData?: ConfirmationData;
|
|
45
55
|
|
|
46
56
|
// Notes
|
|
57
|
+
leftAdditionalNotes?: string;
|
|
58
|
+
rightAdditionalNotes?: string;
|
|
47
59
|
additionalNotes?: string;
|
|
48
60
|
}
|
|
49
61
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "user-worker",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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.82.2"
|
|
12
12
|
}
|
|
13
13
|
}
|
package/wrangler.toml.example
CHANGED