@propriety/court-calendar 1.0.163 → 1.0.164

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/dist/__tests__/CalendarNavCreateGate.test.d.ts +1 -0
  2. package/dist/__tests__/ReferenceDataPermissions.test.d.ts +1 -0
  3. package/dist/__tests__/helpers/api/permissions.test.d.ts +1 -0
  4. package/dist/_components/Modal/DateDetails/CaseViewer.d.ts +1 -1
  5. package/dist/_components/Modal/DateDetails/DateDetails.d.ts +3 -1
  6. package/dist/_components/Modal/DateDetails/DateTabs.d.ts +2 -2
  7. package/dist/_components/Modal/DateDetails/MotionToPreclude.d.ts +8 -1
  8. package/dist/_components/Modal/Layout/ModalActions.d.ts +4 -1
  9. package/dist/_components/Toolbar/CalendarNav.d.ts +2 -2
  10. package/dist/constants.d.ts +0 -1
  11. package/dist/context/ReferenceDataContext.d.ts +3 -0
  12. package/dist/helpers/api/courtDates.d.ts +1 -1
  13. package/dist/helpers/api/headers.d.ts +12 -0
  14. package/dist/helpers/api/people.d.ts +22 -1
  15. package/dist/index.mjs +7658 -7629
  16. package/package.json +1 -1
  17. package/src/__tests__/CalendarListLabels.test.tsx +1 -0
  18. package/src/__tests__/CalendarNavCreateGate.test.tsx +58 -0
  19. package/src/__tests__/CreateEditCaseOpenCases.test.tsx +1 -0
  20. package/src/__tests__/DateDetailsHearingLink.test.tsx +2 -0
  21. package/src/__tests__/DateDetailsMotion.test.tsx +44 -1
  22. package/src/__tests__/ModalActionsSaveGuard.test.tsx +2 -0
  23. package/src/__tests__/ReferenceDataLookups.test.tsx +4 -1
  24. package/src/__tests__/ReferenceDataPermissions.test.tsx +116 -0
  25. package/src/__tests__/WeekWidget.test.tsx +1 -0
  26. package/src/__tests__/helpers/api/permissions.test.ts +146 -0
  27. package/src/__tests__/hooks/UseModalActions.test.ts +137 -3
  28. package/src/_components/CCalendar.tsx +6 -3
  29. package/src/_components/Modal/DateDetails/CaseViewer.tsx +5 -5
  30. package/src/_components/Modal/DateDetails/DateDetails.tsx +4 -0
  31. package/src/_components/Modal/DateDetails/DateTabs.tsx +3 -3
  32. package/src/_components/Modal/DateDetails/MotionToPreclude.tsx +19 -3
  33. package/src/_components/Modal/DateEdit/CreateEditCase.tsx +8 -3
  34. package/src/_components/Modal/Layout/ModalActions.tsx +5 -1
  35. package/src/_components/Modal/Modal.tsx +9 -5
  36. package/src/_components/Toolbar/CalendarNav.tsx +3 -3
  37. package/src/constants.ts +0 -1
  38. package/src/context/ReferenceDataContext.tsx +43 -9
  39. package/src/helpers/api/cases.ts +2 -1
  40. package/src/helpers/api/courtDates.ts +12 -4
  41. package/src/helpers/api/headers.ts +19 -0
  42. package/src/helpers/api/people.ts +46 -17
  43. package/src/hooks/UseModalActions.ts +21 -2
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -6,7 +6,7 @@ declare const CaseViewer: import('react').NamedExoticComponent<{
6
6
  selectedDate: Date;
7
7
  isVillage: boolean;
8
8
  csvFileName?: string;
9
- isAdmin?: boolean;
9
+ canEdit?: boolean;
10
10
  onSelectedCasesAdjournmentChange?: (cases: Case[], date: Date | null) => Promise<boolean>;
11
11
  onSelectedCasesClearDetermination?: (cases: Case[]) => Promise<boolean>;
12
12
  firstChair?: number | null;
@@ -1,5 +1,5 @@
1
1
  import { AdjournmentEntry, Case, CourtDate, DateEditItem } from '../../../types';
2
- export default function DateDetails({ selectedCourtDate, cases, isVillage, isFetchingCases, onUpdateChair, adjournments, courtDateHistory, }: {
2
+ export default function DateDetails({ selectedCourtDate, cases, isVillage, isFetchingCases, onUpdateChair, adjournments, courtDateHistory, canFileMotion, }: {
3
3
  selectedCourtDate: CourtDate | null;
4
4
  cases: Case[];
5
5
  isVillage: boolean;
@@ -7,4 +7,6 @@ export default function DateDetails({ selectedCourtDate, cases, isVillage, isFet
7
7
  onUpdateChair?: (position: 'first' | 'second', userId: number | null) => void;
8
8
  adjournments?: AdjournmentEntry[];
9
9
  courtDateHistory?: DateEditItem[];
10
+ /** Passed straight to MotionToPreclude — see the note on its own prop. */
11
+ canFileMotion: boolean;
10
12
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,12 @@
1
1
  import { Case, CourtDate } from '../../../types';
2
- export default function DateTabs({ cases, isFetchingCases, setClickedCase, selectedDate, isVillage, csvFileName, isAdmin, onSelectedCasesAdjournmentChange, onSelectedCasesClearDetermination, selectedCourtDate, }: {
2
+ export default function DateTabs({ cases, isFetchingCases, setClickedCase, selectedDate, isVillage, csvFileName, canEdit, onSelectedCasesAdjournmentChange, onSelectedCasesClearDetermination, selectedCourtDate, }: {
3
3
  cases: Case[];
4
4
  isFetchingCases: boolean;
5
5
  setClickedCase: (caseItem: Case | null) => void;
6
6
  selectedDate: Date;
7
7
  isVillage: boolean;
8
8
  csvFileName?: string;
9
- isAdmin?: boolean;
9
+ canEdit?: boolean;
10
10
  onSelectedCasesAdjournmentChange?: (cases: Case[], date: Date | null) => Promise<boolean>;
11
11
  onSelectedCasesClearDetermination?: (cases: Case[]) => Promise<boolean>;
12
12
  selectedCourtDate: CourtDate | null;
@@ -12,11 +12,18 @@ export interface MotionToast {
12
12
  * themselves through the status line and their tooltips.
13
13
  *
14
14
  * Callers gate on `isScarDate`: negotiation and collections dates never carry a motion.
15
+ *
16
+ * Download stays open to everyone — reading the draft is how a non-admin checks a motion
17
+ * before asking an admin to file it. Only the upload, which files with the court and
18
+ * cannot be undone, is restricted.
15
19
  */
16
- export default function MotionToPreclude({ courtDate, township, adjournments, cases, onNotify, }: {
20
+ export default function MotionToPreclude({ courtDate, township, adjournments, cases, onNotify, canFileMotion, }: {
17
21
  courtDate: CourtDate;
18
22
  township: string;
19
23
  adjournments?: AdjournmentEntry[];
20
24
  cases?: Pick<Case, 'AdjournedDate'>[];
21
25
  onNotify: (toast: MotionToast) => void;
26
+ /** Required rather than optional: a forgotten prop should fail the build, not silently
27
+ * hand every user an irreversible court filing. */
28
+ canFileMotion: boolean;
22
29
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,13 @@
1
1
  import { ModalMode } from '../types';
2
- export default function ModalActions({ modalMode, onDelete, onSave, setModalMode, setIsOpen, isAdmin, createdBy, createdOn, }: {
2
+ export default function ModalActions({ modalMode, onDelete, onSave, setModalMode, setIsOpen, canEdit, isAdmin, createdBy, createdOn, }: {
3
3
  modalMode: ModalMode;
4
4
  onDelete: () => void | Promise<unknown>;
5
5
  onSave: () => void | Promise<unknown>;
6
6
  setModalMode: (mode: ModalMode) => void;
7
7
  setIsOpen: (isOpen: boolean) => void;
8
+ /** Gates Edit/Save — everyone who works on cases. */
9
+ canEdit: boolean;
10
+ /** Gates Delete only. Deleting a date is not recoverable from the UI. */
8
11
  isAdmin: boolean;
9
12
  createdBy?: number | null;
10
13
  createdOn?: Date | string | null;
@@ -1,5 +1,5 @@
1
1
  import { Calendar } from '@fullcalendar/core/index.js';
2
- export default function CalendarNav({ calendarApi, handleCreateClick, onPrint, onRefresh, currentView, setCurrentView, currentDate, setCurrentDate, isFetchingDates, isFetchingCases, lastFetchedAt, isAdmin, }: {
2
+ export default function CalendarNav({ calendarApi, handleCreateClick, onPrint, onRefresh, currentView, setCurrentView, currentDate, setCurrentDate, isFetchingDates, isFetchingCases, lastFetchedAt, canEdit, }: {
3
3
  calendarApi: Calendar | null;
4
4
  handleCreateClick: () => void;
5
5
  onPrint: () => void;
@@ -11,5 +11,5 @@ export default function CalendarNav({ calendarApi, handleCreateClick, onPrint, o
11
11
  isFetchingDates: boolean;
12
12
  isFetchingCases: boolean;
13
13
  lastFetchedAt: Date | null;
14
- isAdmin: boolean;
14
+ canEdit: boolean;
15
15
  }): import("react/jsx-runtime").JSX.Element;
@@ -5,7 +5,6 @@ export declare const S3_NOTICES_URL = "https://aventine-court-notices.s3.us-east
5
5
  export declare const S3_DOCS_URL = "https://aventine-court-docs.s3.amazonaws.com";
6
6
  export declare const SETTLED_ACTIONS: string[];
7
7
  export declare const EXCLUDED_USER_NAMES: string[];
8
- export declare const ADMIN_GROUP = "calendar-admin";
9
8
  export declare const PRIMARY_USER_IDS: number[];
10
9
  export declare const CASES_CACHE_EXPIRY: number;
11
10
  export declare const COURT_DATES_CACHE_EXPIRY: number;
@@ -9,6 +9,9 @@ interface ReferenceDataContextType {
9
9
  getTownshipName: (muniCode: string) => string;
10
10
  getCountyName: (muniCode: string) => string;
11
11
  isLoading: boolean;
12
+ /** May add and edit court dates and negotiation dates. Everyone who works on cases. */
13
+ canEdit: boolean;
14
+ /** May delete a date and file a Motion to Preclude. A much smaller set than canEdit. */
12
15
  isAdmin: boolean;
13
16
  apiKey: string;
14
17
  activeUser: number;
@@ -11,7 +11,7 @@ export declare function getCourtDate(courtDateId: number, apiKey: string, type?:
11
11
  * edit-log trail, so both come back empty for negotiation dates rather than throwing.
12
12
  */
13
13
  export declare function getCourtDateDetail(courtDateId: number, apiKey: string, type?: DateType): Promise<CourtDateDetail | null>;
14
- export declare function deleteCourtDate(courtDateId: number, apiKey: string, type?: DateType): Promise<boolean>;
14
+ export declare function deleteCourtDate(courtDateId: number, apiKey: string, type?: DateType, user?: number): Promise<boolean>;
15
15
  export declare function createCourtDate(courtDate: Date, muniCode: string, apiKey: string, courtCases?: string[], hearingTime?: string, multipleDates?: Date[], type?: DateType, noticeFiles?: File[], editUser?: number): Promise<number | null>;
16
16
  export declare function snoozeUploadDeadline(courtDateId: number, apiKey: string): Promise<boolean>;
17
17
  export declare function getDateEditLogs(courtDateId: number, apiKey: string, type?: DateType): Promise<DateEditLog | null>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Headers for a mutating request.
3
+ *
4
+ * The API key is shared across the team, so it identifies the *app*, not the person. The
5
+ * backend resolves the caller's roles from `X-User-Id` (see ../../../utility-api/utils/roles.py),
6
+ * so a write that omits it is rejected once role enforcement is on.
7
+ *
8
+ * `userId` is optional because a few callers genuinely have no user — background refreshes
9
+ * and the automated ingest paths. Those are reads, which are never gated; if one turns out
10
+ * to write, the missing header is the symptom to look for.
11
+ */
12
+ export declare function writeHeaders(apiKey: string, userId?: number, extra?: Record<string, string>): Record<string, string>;
@@ -6,4 +6,25 @@ export interface HearingOfficer {
6
6
  }
7
7
  export declare function getAllUsers(apiKey: string): Promise<Record<number, User>>;
8
8
  export declare function getAllHearingOfficers(apiKey: string): Promise<Record<number, HearingOfficer>>;
9
- export declare function isUserAdmin(User: User, apiKey: string): Promise<boolean>;
9
+ /** What the signed-in user may do on the calendar. */
10
+ export interface CalendarPermissions {
11
+ /** Add and edit court dates and negotiation dates. An admin always may. */
12
+ canEdit: boolean;
13
+ /** Delete a date, and file a Motion to Preclude with the court. */
14
+ isAdmin: boolean;
15
+ }
16
+ /**
17
+ * Resolve what `userId` may do, from the roles held in `Rules.UserRoles`.
18
+ *
19
+ * Replaces an older check that asked whether the user's *email* was in the
20
+ * `calendar-admin` AWS Cognito group. Keying on the numeric UserID matters twice over:
21
+ * several active users have no email address at all, and `activeUser` already is a
22
+ * UserID — so permissions no longer have to wait for the user list to load before they
23
+ * can resolve.
24
+ *
25
+ * Fails closed on every path. The backend answers 200 with empty roles for a user who
26
+ * simply holds none, so any non-200 here is a genuine fault, and a fault must never read
27
+ * as permission. Comparisons are `=== true` because a `null` or the string `"true"`
28
+ * arriving from a changed backend would otherwise be truthy.
29
+ */
30
+ export declare function getUserPermissions(userId: number, apiKey: string): Promise<CalendarPermissions>;