@striae-org/striae 6.1.5 → 6.1.7
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/.env.example +1 -1
- package/app/components/navbar/case-modals/all-cases-modal.tsx +14 -12
- package/app/components/sidebar/sidebar-container.tsx +2 -2
- package/app/routes/auth/emailActionHandler.tsx +2 -12
- package/app/routes/auth/login.tsx +2 -4
- package/app/routes/striae/striae.tsx +7 -3
- package/app/utils/api/data-api-client.ts +1 -0
- package/app/utils/data/permissions.ts +4 -0
- package/package.json +4 -5
- package/vite.config.ts +3 -2
- 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/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/.env.example
CHANGED
|
@@ -149,4 +149,4 @@ PRIMERSHEAR_EMAILS=
|
|
|
149
149
|
# Comma-separated list of email addresses that may register an account.
|
|
150
150
|
# Leave empty to disable the feature. Never commit this value to source control.
|
|
151
151
|
# Example: REGISTRATION_EMAILS=analyst@org.com,user2@org.com
|
|
152
|
-
REGISTRATION_EMAILS=
|
|
152
|
+
REGISTRATION_EMAILS=
|
|
@@ -33,6 +33,7 @@ interface CasesModalProps {
|
|
|
33
33
|
isOpen: boolean;
|
|
34
34
|
onClose: () => void;
|
|
35
35
|
onSelectCase: (caseNum: string) => void;
|
|
36
|
+
onCurrentCaseDeleted?: () => void;
|
|
36
37
|
currentCase: string;
|
|
37
38
|
user: User;
|
|
38
39
|
confirmationSaveVersion?: number;
|
|
@@ -64,6 +65,7 @@ export const CasesModal = ({
|
|
|
64
65
|
isOpen,
|
|
65
66
|
onClose,
|
|
66
67
|
onSelectCase,
|
|
68
|
+
onCurrentCaseDeleted,
|
|
67
69
|
currentCase,
|
|
68
70
|
user,
|
|
69
71
|
confirmationSaveVersion = 0,
|
|
@@ -224,16 +226,14 @@ export const CasesModal = ({
|
|
|
224
226
|
);
|
|
225
227
|
|
|
226
228
|
const canDeleteSelectedCase = Boolean(
|
|
227
|
-
selectedCase &&
|
|
229
|
+
selectedCase && !selectedCase.isReadOnly
|
|
228
230
|
);
|
|
229
231
|
|
|
230
232
|
const deleteSelectedCaseTitle = !selectedCase
|
|
231
233
|
? 'Select a case to delete.'
|
|
232
|
-
: selectedCase.
|
|
233
|
-
? '
|
|
234
|
-
:
|
|
235
|
-
? 'Read-only review cases cannot be deleted. Use Clear RO Case under Case Management first.'
|
|
236
|
-
: undefined;
|
|
234
|
+
: selectedCase.isReadOnly
|
|
235
|
+
? 'Read-only review cases cannot be deleted here. Use Clear RO Case under Case Management first.'
|
|
236
|
+
: undefined;
|
|
237
237
|
|
|
238
238
|
const effectiveFocusedIndex = paginatedCases.length === 0 ? 0 : Math.min(focusedIndex, paginatedCases.length - 1);
|
|
239
239
|
|
|
@@ -475,16 +475,13 @@ export const CasesModal = ({
|
|
|
475
475
|
|
|
476
476
|
const handleDeleteSelectedCase = async () => {
|
|
477
477
|
if (!selectedCase || !canDeleteSelectedCase) {
|
|
478
|
-
const isCurrentCaseSelection = selectedCase?.caseNumber === currentCase;
|
|
479
478
|
const isReadOnlyReviewSelection = selectedCase?.isReadOnly === true;
|
|
480
479
|
|
|
481
480
|
setActionNotice({
|
|
482
481
|
type: 'warning',
|
|
483
|
-
message:
|
|
484
|
-
? '
|
|
485
|
-
:
|
|
486
|
-
? 'Read-only review cases cannot be deleted. Use Clear RO Case under Case Management first.'
|
|
487
|
-
: 'Selected case cannot be deleted.',
|
|
482
|
+
message: isReadOnlyReviewSelection
|
|
483
|
+
? 'Read-only review cases cannot be deleted here. Use Clear RO Case under Case Management first.'
|
|
484
|
+
: 'Selected case cannot be deleted.',
|
|
488
485
|
});
|
|
489
486
|
return;
|
|
490
487
|
}
|
|
@@ -506,11 +503,16 @@ export const CasesModal = ({
|
|
|
506
503
|
setActionNotice(null);
|
|
507
504
|
|
|
508
505
|
try {
|
|
506
|
+
const wasCurrentCase = selectedCase.caseNumber === currentCase;
|
|
509
507
|
const deleteResult = await deleteCase(user, selectedCase.caseNumber);
|
|
510
508
|
setSelectedCaseNumber(null);
|
|
511
509
|
setIsDeleteModalOpen(false);
|
|
512
510
|
setRefreshKey((k) => k + 1);
|
|
513
511
|
|
|
512
|
+
if (wasCurrentCase) {
|
|
513
|
+
onCurrentCaseDeleted?.();
|
|
514
|
+
}
|
|
515
|
+
|
|
514
516
|
if (deleteResult.missingImages.length > 0) {
|
|
515
517
|
setActionNotice({
|
|
516
518
|
type: 'warning',
|
|
@@ -113,11 +113,11 @@ export const SidebarContainer: React.FC<SidebarContainerProps> = (props) => {
|
|
|
113
113
|
Security Policy
|
|
114
114
|
</Link>
|
|
115
115
|
<Link
|
|
116
|
-
to="https://
|
|
116
|
+
to="https://account.striae.org/p/login/dRmcMZ3HC5vVfFZ4St4wM00"
|
|
117
117
|
target="_blank"
|
|
118
118
|
rel="noopener noreferrer"
|
|
119
119
|
className={styles.footerModalLink}>
|
|
120
|
-
|
|
120
|
+
Manage Membership
|
|
121
121
|
</Link>
|
|
122
122
|
</div>
|
|
123
123
|
|
|
@@ -20,7 +20,7 @@ interface EmailActionHandlerProps {
|
|
|
20
20
|
lang: string | null;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
type HandlerState = 'loading' | 'ready-reset' | 'success' | 'error'
|
|
23
|
+
type HandlerState = 'loading' | 'ready-reset' | 'success' | 'error';
|
|
24
24
|
|
|
25
25
|
const getUserAgent = (): string | undefined => {
|
|
26
26
|
if (typeof navigator === 'undefined') {
|
|
@@ -171,16 +171,6 @@ export const EmailActionHandler = ({ mode, oobCode, continueUrl, lang }: EmailAc
|
|
|
171
171
|
return;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
if (mode === 'recoverEmail') {
|
|
175
|
-
if (!isMounted) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
setState('unsupported');
|
|
180
|
-
setError('Email change recovery is not supported for Striae accounts.');
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
174
|
if (!isMounted) {
|
|
185
175
|
return;
|
|
186
176
|
}
|
|
@@ -378,7 +368,7 @@ export const EmailActionHandler = ({ mode, oobCode, continueUrl, lang }: EmailAc
|
|
|
378
368
|
</form>
|
|
379
369
|
)}
|
|
380
370
|
|
|
381
|
-
{(state === 'success' || state === 'error'
|
|
371
|
+
{(state === 'success' || state === 'error') && (
|
|
382
372
|
<div className={styles.actions}>
|
|
383
373
|
{showContinueButton && (
|
|
384
374
|
<button
|
|
@@ -28,9 +28,7 @@ import { generateUniqueId } from '~/utils/common';
|
|
|
28
28
|
import { evaluatePasswordPolicy, buildActionCodeSettings, userHasMFA } from '~/utils/auth';
|
|
29
29
|
import type { UserData } from '~/types';
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const SUPPORTED_EMAIL_ACTION_MODES = new Set(['resetPassword', 'verifyEmail', 'recoverEmail']);
|
|
31
|
+
const SUPPORTED_EMAIL_ACTION_MODES = new Set(['resetPassword', 'verifyEmail']);
|
|
34
32
|
|
|
35
33
|
const getUserFirstName = (user: User): string => {
|
|
36
34
|
const displayName = user.displayName?.trim();
|
|
@@ -69,7 +67,7 @@ export const Login = () => {
|
|
|
69
67
|
const [isClient, setIsClient] = useState(false);
|
|
70
68
|
const [firstName, setFirstName] = useState('');
|
|
71
69
|
const [lastName, setLastName] = useState('');
|
|
72
|
-
const [company, setCompany] = useState(
|
|
70
|
+
const [company, setCompany] = useState('');
|
|
73
71
|
const [badgeId, setBadgeId] = useState('');
|
|
74
72
|
const [confirmPasswordValue, setConfirmPasswordValue] = useState('');
|
|
75
73
|
|
|
@@ -22,7 +22,7 @@ import { fetchUserApi } from '~/utils/api';
|
|
|
22
22
|
import { type AnnotationData, type FileData, type ExportOptions } from '~/types';
|
|
23
23
|
import { validateCaseNumber, renameCase, deleteCase, checkExistingCase, createNewCase, archiveCase, deriveCaseArchiveDetails } from '~/components/actions/case-manage';
|
|
24
24
|
import { checkReadOnlyCaseExists, deleteReadOnlyCase } from '~/components/actions/case-review';
|
|
25
|
-
import { canCreateCase,
|
|
25
|
+
import { canCreateCase, ensureCaseConfirmationSummary, getCaseData, getConfirmationSummaryDocument, type UserConfirmationSummaryDocument } from '~/utils/data';
|
|
26
26
|
import {
|
|
27
27
|
resolveEarliestAnnotationTimestamp,
|
|
28
28
|
CREATE_READ_ONLY_CASE_EXISTS_ERROR,
|
|
@@ -382,7 +382,9 @@ export const Striae = ({ user }: StriaePage) => {
|
|
|
382
382
|
if (!currentCase || !user) return;
|
|
383
383
|
|
|
384
384
|
try {
|
|
385
|
-
const summary = await
|
|
385
|
+
const summary = await ensureCaseConfirmationSummary(user, currentCase, files, {
|
|
386
|
+
forceRefresh: true,
|
|
387
|
+
});
|
|
386
388
|
const filesById = summary?.filesById ?? {};
|
|
387
389
|
const values = Object.values(filesById);
|
|
388
390
|
const confirmedCount = values.filter((f) => f.includeConfirmation && f.isConfirmed).length;
|
|
@@ -729,7 +731,7 @@ export const Striae = ({ user }: StriaePage) => {
|
|
|
729
731
|
supportLevel: notes.supportLevel || 'Inconclusive',
|
|
730
732
|
includeConfirmation: notes.includeConfirmation ?? false,
|
|
731
733
|
boxAnnotations: notes.boxAnnotations || [],
|
|
732
|
-
updatedAt: notes.updatedAt ||
|
|
734
|
+
updatedAt: notes.updatedAt || ''
|
|
733
735
|
});
|
|
734
736
|
} else {
|
|
735
737
|
setAnnotationData(null);
|
|
@@ -794,6 +796,7 @@ export const Striae = ({ user }: StriaePage) => {
|
|
|
794
796
|
const now = new Date().toISOString();
|
|
795
797
|
const dataWithEarliestTimestamp: AnnotationData = {
|
|
796
798
|
...data,
|
|
799
|
+
updatedAt: now,
|
|
797
800
|
earliestAnnotationTimestamp: resolveEarliestAnnotationTimestamp(
|
|
798
801
|
data.earliestAnnotationTimestamp,
|
|
799
802
|
annotationData?.earliestAnnotationTimestamp,
|
|
@@ -954,6 +957,7 @@ export const Striae = ({ user }: StriaePage) => {
|
|
|
954
957
|
onSelectCase={(selectedCase) => {
|
|
955
958
|
void loadCaseIntoWorkspace(selectedCase);
|
|
956
959
|
}}
|
|
960
|
+
onCurrentCaseDeleted={clearLoadedCaseState}
|
|
957
961
|
currentCase={currentCase || ''}
|
|
958
962
|
user={user}
|
|
959
963
|
confirmationSaveVersion={confirmationSaveVersion}
|
|
@@ -550,6 +550,8 @@ export const addUserCase = async (user: User, caseData: CaseMetadata): Promise<v
|
|
|
550
550
|
const errorText = await response.text();
|
|
551
551
|
throw new Error(`Failed to add case to user: ${response.status} - ${errorText}`);
|
|
552
552
|
}
|
|
553
|
+
|
|
554
|
+
invalidateUserDataCache(user.uid);
|
|
553
555
|
|
|
554
556
|
} catch (error) {
|
|
555
557
|
console.error('Error adding case to user:', error);
|
|
@@ -595,6 +597,8 @@ export const removeUserCase = async (user: User, caseNumber: string): Promise<vo
|
|
|
595
597
|
const errorText = await response.text();
|
|
596
598
|
throw new Error(`Failed to remove case from user: ${response.status} - ${errorText}`);
|
|
597
599
|
}
|
|
600
|
+
|
|
601
|
+
invalidateUserDataCache(user.uid);
|
|
598
602
|
|
|
599
603
|
} catch (error) {
|
|
600
604
|
console.error('Error removing case from user:', error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@striae-org/striae",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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",
|
|
@@ -124,10 +124,9 @@
|
|
|
124
124
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
125
125
|
"firebase-admin": "^13.8.0",
|
|
126
126
|
"modern-normalize": "^3.0.1",
|
|
127
|
-
"typescript": "^
|
|
128
|
-
"vite": "^
|
|
129
|
-
"
|
|
130
|
-
"wrangler": "^4.83.0"
|
|
127
|
+
"typescript": "^6.0.3",
|
|
128
|
+
"vite": "^8.0.9",
|
|
129
|
+
"wrangler": "^4.84.0"
|
|
131
130
|
},
|
|
132
131
|
"overrides": {
|
|
133
132
|
"@tootallnate/once": "3.0.1"
|
package/vite.config.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { reactRouter } from "@react-router/dev/vite";
|
|
2
2
|
import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";
|
|
3
3
|
import { defineConfig } from "vite";
|
|
4
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
5
4
|
|
|
6
5
|
export default defineConfig({
|
|
7
6
|
server: {
|
|
@@ -11,9 +10,11 @@ export default defineConfig({
|
|
|
11
10
|
chunkSizeWarningLimit: 500,
|
|
12
11
|
minify: true,
|
|
13
12
|
},
|
|
13
|
+
resolve: {
|
|
14
|
+
tsconfigPaths: true,
|
|
15
|
+
},
|
|
14
16
|
plugins: [
|
|
15
17
|
cloudflareDevProxy(),
|
|
16
18
|
reactRouter(),
|
|
17
|
-
tsconfigPaths(),
|
|
18
19
|
],
|
|
19
20
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audit-worker",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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.84.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-worker",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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.84.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "image-worker",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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.84.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-worker",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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.84.0"
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "user-worker",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.7",
|
|
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.84.0"
|
|
12
12
|
}
|
|
13
13
|
}
|
package/wrangler.toml.example
CHANGED