@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.
Files changed (43) hide show
  1. package/app/components/actions/case-export/core-export.ts +11 -2
  2. package/app/components/actions/case-export/download-handlers.ts +3 -1
  3. package/app/components/canvas/canvas.module.css +1 -1
  4. package/app/components/canvas/canvas.tsx +32 -11
  5. package/app/components/colors/colors.module.css +19 -0
  6. package/app/components/colors/colors.tsx +5 -1
  7. package/app/components/icon/icons.svg +1 -1
  8. package/app/components/icon/manifest.json +1 -1
  9. package/app/components/navbar/navbar.tsx +32 -16
  10. package/app/components/sidebar/cases/case-sidebar.tsx +27 -25
  11. package/app/components/sidebar/files/files-modal.tsx +39 -15
  12. package/app/components/sidebar/notes/addl-notes-modal.tsx +9 -2
  13. package/app/components/sidebar/notes/{class-details/class-details-fields.tsx → item-details/item-details-fields.tsx} +10 -10
  14. package/app/components/sidebar/notes/{class-details/class-details-modal.tsx → item-details/item-details-modal.tsx} +20 -22
  15. package/app/components/sidebar/notes/{class-details/class-details-sections.tsx → item-details/item-details-sections.tsx} +16 -16
  16. package/app/components/sidebar/notes/{class-details/class-details-shared.ts → item-details/item-details-shared.ts} +4 -3
  17. package/app/components/sidebar/notes/{class-details/use-class-details-state.ts → item-details/use-item-details-state.ts} +4 -4
  18. package/app/components/sidebar/notes/notes-editor-form.tsx +357 -146
  19. package/app/components/sidebar/notes/notes-editor-modal.tsx +3 -0
  20. package/app/components/sidebar/notes/notes.module.css +40 -20
  21. package/app/components/sidebar/sidebar-container.tsx +1 -1
  22. package/app/components/sidebar/sidebar.tsx +3 -3
  23. package/app/components/toolbar/toolbar.tsx +5 -5
  24. package/app/hooks/useFileListPreferences.ts +22 -17
  25. package/app/routes/striae/striae.tsx +6 -13
  26. package/app/types/annotations.ts +29 -5
  27. package/app/utils/data/confirmation-summary/summary-core.ts +40 -8
  28. package/app/utils/data/file-filters.ts +39 -17
  29. package/app/utils/data/permissions.ts +123 -0
  30. package/package.json +12 -12
  31. package/workers/audit-worker/package.json +2 -2
  32. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  33. package/workers/data-worker/package.json +2 -2
  34. package/workers/data-worker/wrangler.jsonc.example +1 -1
  35. package/workers/image-worker/package.json +2 -2
  36. package/workers/image-worker/wrangler.jsonc.example +1 -1
  37. package/workers/pdf-worker/package.json +2 -2
  38. package/workers/pdf-worker/src/formats/format-striae.ts +65 -8
  39. package/workers/pdf-worker/src/report-types.ts +18 -4
  40. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  41. package/workers/user-worker/package.json +2 -2
  42. package/workers/user-worker/wrangler.jsonc.example +1 -1
  43. package/wrangler.toml.example +1 -1
@@ -3,18 +3,16 @@ import type {
3
3
  BulletAnnotationData,
4
4
  CartridgeCaseAnnotationData,
5
5
  ShotshellAnnotationData,
6
+ ItemType,
6
7
  } from '~/types/annotations';
7
- import {
8
- type ClassType,
9
- } from './class-details-shared';
10
- import { BulletSection, CartridgeCaseSection, ShotshellSection } from './class-details-sections';
11
- import { useClassDetailsState } from './use-class-details-state';
8
+ import { BulletSection, CartridgeCaseSection, ShotshellSection } from './item-details-sections';
9
+ import { useItemDetailsState } from './use-item-details-state';
12
10
  import styles from '../notes.module.css';
13
11
 
14
- interface ClassDetailsModalProps {
12
+ interface ItemDetailsModalProps {
15
13
  isOpen: boolean;
16
14
  onClose: () => void;
17
- classType: ClassType | '';
15
+ itemType: ItemType | '';
18
16
  bulletData?: BulletAnnotationData;
19
17
  cartridgeCaseData?: CartridgeCaseAnnotationData;
20
18
  shotshellData?: ShotshellAnnotationData;
@@ -27,17 +25,17 @@ interface ClassDetailsModalProps {
27
25
  isReadOnly?: boolean;
28
26
  }
29
27
 
30
- const ClassDetailsModalContent = ({
28
+ const ItemDetailsModalContent = ({
31
29
  isOpen,
32
30
  onClose,
33
- classType,
31
+ itemType,
34
32
  bulletData,
35
33
  cartridgeCaseData,
36
34
  shotshellData,
37
35
  onSave,
38
36
  showNotification,
39
37
  isReadOnly = false,
40
- }: ClassDetailsModalProps) => {
38
+ }: ItemDetailsModalProps) => {
41
39
  const {
42
40
  bullet,
43
41
  cartridgeCase,
@@ -45,7 +43,7 @@ const ClassDetailsModalContent = ({
45
43
  isSaving,
46
44
  setIsSaving,
47
45
  buildSaveData,
48
- } = useClassDetailsState({
46
+ } = useItemDetailsState({
49
47
  bulletData,
50
48
  cartridgeCaseData,
51
49
  shotshellData,
@@ -55,10 +53,10 @@ const ClassDetailsModalContent = ({
55
53
 
56
54
  if (!isOpen) return null;
57
55
 
58
- const showBullet = classType === 'Bullet' || classType === 'Other' || classType === '';
59
- const showCartridge = classType === 'Cartridge Case' || classType === 'Other' || classType === '';
60
- const showShotshell = classType === 'Shotshell' || classType === 'Other' || classType === '';
61
- const showHeaders = classType === 'Other' || classType === '';
56
+ const showBullet = itemType === 'Bullet' || itemType === 'Other' || itemType === '';
57
+ const showCartridge = itemType === 'Cartridge Case' || itemType === 'Other' || itemType === '';
58
+ const showShotshell = itemType === 'Shotshell' || itemType === 'Other' || itemType === '';
59
+ const showHeaders = itemType === 'Other' || itemType === '';
62
60
 
63
61
  const handleSave = async () => {
64
62
  setIsSaving(true);
@@ -90,10 +88,10 @@ const ClassDetailsModalContent = ({
90
88
  aria-label="Close class details dialog"
91
89
  {...overlayProps}
92
90
  >
93
- <div className={`${styles.modal} ${styles.classDetailsModal}`}>
91
+ <div className={`${styles.modal} ${styles.itemDetailsModal}`}>
94
92
  <button {...getCloseButtonProps({ ariaLabel: 'Close class details dialog' })}>×</button>
95
93
  <h5 className={styles.modalTitle}>Class Characteristic Details</h5>
96
- <div className={styles.classDetailsContent}>
94
+ <div className={styles.itemDetailsContent}>
97
95
  {showBullet && (
98
96
  <BulletSection
99
97
  showHeader={showHeaders}
@@ -118,10 +116,10 @@ const ClassDetailsModalContent = ({
118
116
  />
119
117
  )}
120
118
  </div>
121
- <div className={`${styles.modalButtons} ${styles.classDetailsModalButtons}`}>
119
+ <div className={`${styles.modalButtons} ${styles.itemDetailsModalButtons}`}>
122
120
  <button
123
121
  onClick={handleSave}
124
- className={`${styles.saveButton} ${styles.classDetailsModalAction}`}
122
+ className={`${styles.saveButton} ${styles.itemDetailsModalAction}`}
125
123
  disabled={isSaving || isReadOnly}
126
124
  aria-busy={isSaving}
127
125
  >
@@ -129,7 +127,7 @@ const ClassDetailsModalContent = ({
129
127
  </button>
130
128
  <button
131
129
  onClick={requestClose}
132
- className={`${styles.cancelButton} ${styles.classDetailsModalAction}`}
130
+ className={`${styles.cancelButton} ${styles.itemDetailsModalAction}`}
133
131
  disabled={isSaving}
134
132
  >
135
133
  Cancel
@@ -140,8 +138,8 @@ const ClassDetailsModalContent = ({
140
138
  );
141
139
  };
142
140
 
143
- export const ClassDetailsModal = (props: ClassDetailsModalProps) => {
141
+ export const ItemDetailsModal = (props: ItemDetailsModalProps) => {
144
142
  if (!props.isOpen) return null;
145
143
 
146
- return <ClassDetailsModalContent {...props} />;
144
+ return <ItemDetailsModalContent {...props} />;
147
145
  };
@@ -16,9 +16,9 @@ import {
16
16
  SHOTSHELL_GAUGES,
17
17
  SHOTSHELL_STEEL_WATERFOWL_OPTIONS,
18
18
  formatCalculatedDiameter,
19
- } from './class-details-shared';
20
- import { CheckboxField, SelectField, SelectWithCustomField, TextField } from './class-details-fields';
21
- import type { BulletDetailsState, CartridgeCaseDetailsState, ShotshellDetailsState } from './use-class-details-state';
19
+ } from './item-details-shared';
20
+ import { CheckboxField, SelectField, SelectWithCustomField, TextField } from './item-details-fields';
21
+ import type { BulletDetailsState, CartridgeCaseDetailsState, ShotshellDetailsState } from './use-item-details-state';
22
22
 
23
23
  interface BulletSectionProps {
24
24
  showHeader: boolean;
@@ -294,14 +294,14 @@ export const BulletSection = ({
294
294
  ];
295
295
 
296
296
  return (
297
- <div className={styles.classDetailsSection}>
298
- {showHeader && <h6 className={styles.classDetailsSectionHeader}>Bullet</h6>}
299
- <div className={styles.classDetailsFieldGrid}>
297
+ <div className={styles.itemDetailsSection}>
298
+ {showHeader && <h6 className={styles.itemDetailsSectionHeader}>Bullet</h6>}
299
+ <div className={styles.itemDetailsFieldGrid}>
300
300
  {bulletFields.map((field) => renderConfiguredField(field, isReadOnly))}
301
301
  </div>
302
302
  {bullet.lgCount > 0 && (
303
303
  <div className={styles.lgWidthsSection}>
304
- <h6 className={styles.classDetailsSectionHeader}>L / G Widths</h6>
304
+ <h6 className={styles.itemDetailsSectionHeader}>L / G Widths</h6>
305
305
  <div className={styles.lgWidthsLayout}>
306
306
  <div className={styles.lgWidthsColumn}>
307
307
  {Array.from({ length: bullet.lgCount }, (_, index) => (
@@ -331,7 +331,7 @@ export const BulletSection = ({
331
331
  {bullet.calculatedDiameter !== null && (
332
332
  <div className={styles.calculatedDiameterWrapper}>
333
333
  <div className={styles.calculatedDiameterDisplay}>
334
- <span className={styles.classDetailsLabel}>Calculated Diameter</span>
334
+ <span className={styles.itemDetailsLabel}>Calculated Diameter</span>
335
335
  <span className={styles.calculatedDiameterValue}>{formatCalculatedDiameter(bullet.calculatedDiameter)}</span>
336
336
  </div>
337
337
  <button
@@ -448,12 +448,12 @@ export const CartridgeCaseSection = ({
448
448
  ];
449
449
 
450
450
  return (
451
- <div className={styles.classDetailsSection}>
452
- {showHeader && <h6 className={styles.classDetailsSectionHeader}>Cartridge Case</h6>}
453
- <div className={styles.classDetailsFieldGrid}>
451
+ <div className={styles.itemDetailsSection}>
452
+ {showHeader && <h6 className={styles.itemDetailsSectionHeader}>Cartridge Case</h6>}
453
+ <div className={styles.itemDetailsFieldGrid}>
454
454
  {cartridgeFields.map((field) => renderConfiguredField(field, isReadOnly))}
455
455
  </div>
456
- <div className={styles.classDetailsCheckboxGroup}>
456
+ <div className={styles.itemDetailsCheckboxGroup}>
457
457
  {renderCheckboxes([
458
458
  { key: 'fpDrag', label: 'FP Drag', checked: cartridgeCase.hasFpDrag, onChange: cartridgeCase.setHasFpDrag },
459
459
  { key: 'extractor', label: 'Extractor Marks', checked: cartridgeCase.hasExtractorMarks, onChange: cartridgeCase.setHasExtractorMarks },
@@ -544,12 +544,12 @@ export const ShotshellSection = ({
544
544
  ];
545
545
 
546
546
  return (
547
- <div className={styles.classDetailsSection}>
548
- {showHeader && <h6 className={styles.classDetailsSectionHeader}>Shotshell</h6>}
549
- <div className={styles.classDetailsFieldGrid}>
547
+ <div className={styles.itemDetailsSection}>
548
+ {showHeader && <h6 className={styles.itemDetailsSectionHeader}>Shotshell</h6>}
549
+ <div className={styles.itemDetailsFieldGrid}>
550
550
  {shotshellFields.map((field) => renderConfiguredField(field, isReadOnly))}
551
551
  </div>
552
- <div className={styles.classDetailsCheckboxGroup}>
552
+ <div className={styles.itemDetailsCheckboxGroup}>
553
553
  {renderCheckboxes([
554
554
  { key: 'extractor', label: 'Extractor Marks', checked: shotshell.hasExtractorMarks, onChange: shotshell.setHasExtractorMarks },
555
555
  { key: 'ejector', label: 'Ejector Marks', checked: shotshell.hasEjectorMarks, onChange: shotshell.setHasEjectorMarks },
@@ -1,6 +1,7 @@
1
- import type { BulletAnnotationData, CartridgeCaseAnnotationData, ShotshellAnnotationData } from '~/types/annotations';
1
+ import type { BulletAnnotationData, CartridgeCaseAnnotationData, ShotshellAnnotationData, ItemType } from '~/types/annotations';
2
2
 
3
- export type ClassType = 'Bullet' | 'Cartridge Case' | 'Shotshell' | 'Other';
3
+ // Re-export ItemType from annotations for backwards compatibility
4
+ export type ClassType = ItemType;
4
5
 
5
6
  export const CUSTOM = '__custom__';
6
7
 
@@ -133,7 +134,7 @@ const avgWidth = (widths: string[] | undefined): number | null => {
133
134
  return vals.reduce((a, b) => a + b, 0) / vals.length;
134
135
  };
135
136
 
136
- export const buildClassDetailsSummary = (
137
+ export const buildItemDetailsSummary = (
137
138
  bulletData: BulletAnnotationData | undefined,
138
139
  cartridgeCaseData: CartridgeCaseAnnotationData | undefined,
139
140
  shotshellData: ShotshellAnnotationData | undefined,
@@ -18,9 +18,9 @@ import {
18
18
  calculateBulletDiameter,
19
19
  formatCalculatedDiameter,
20
20
  isCustomValue,
21
- } from './class-details-shared';
21
+ } from './item-details-shared';
22
22
 
23
- interface UseClassDetailsStateParams {
23
+ interface UseItemDetailsStateParams {
24
24
  bulletData?: BulletAnnotationData;
25
25
  cartridgeCaseData?: CartridgeCaseAnnotationData;
26
26
  shotshellData?: ShotshellAnnotationData;
@@ -139,11 +139,11 @@ export interface ShotshellDetailsState {
139
139
  setHasChamberMarks: (value: boolean) => void;
140
140
  }
141
141
 
142
- export const useClassDetailsState = ({
142
+ export const useItemDetailsState = ({
143
143
  bulletData,
144
144
  cartridgeCaseData,
145
145
  shotshellData,
146
- }: UseClassDetailsStateParams) => {
146
+ }: UseItemDetailsStateParams) => {
147
147
  const [bCaliber, setBCaliber] = useState(() => bulletData?.caliber || '');
148
148
  const [bCaliberIsCustom, setBCaliberIsCustom] = useState(() => isCustomValue(bulletData?.caliber, ALL_CALIBERS));
149
149
  const [bMass, setBMass] = useState(() => bulletData?.mass || '');