quidproquo-web-admin 0.1.12 → 0.1.13

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 (65) hide show
  1. package/lib/commonjs/App/App.js +4 -1
  2. package/lib/commonjs/App/App.js.map +1 -1
  3. package/lib/commonjs/Auth/Auth.js +1 -2
  4. package/lib/commonjs/Auth/Auth.js.map +1 -1
  5. package/lib/commonjs/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js +7 -2
  6. package/lib/commonjs/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js.map +1 -1
  7. package/lib/commonjs/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js +7 -2
  8. package/lib/commonjs/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js.map +1 -1
  9. package/lib/commonjs/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js +7 -2
  10. package/lib/commonjs/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js.map +1 -1
  11. package/lib/commonjs/Auth/logic/authRuntime.d.ts +2 -1
  12. package/lib/commonjs/Auth/logic/authRuntime.js +8 -1
  13. package/lib/commonjs/Auth/logic/authRuntime.js.map +1 -1
  14. package/lib/commonjs/LogViewer/LogChat/LogChat.js +1 -2
  15. package/lib/commonjs/LogViewer/LogChat/LogChat.js.map +1 -1
  16. package/lib/commonjs/LogViewer/LogChat/eventDocAiLogChatRuntime.js +11 -3
  17. package/lib/commonjs/LogViewer/LogChat/eventDocAiLogChatRuntime.js.map +1 -1
  18. package/lib/commonjs/adminApp/actions/askApplySessionEventToLog.js +3 -1
  19. package/lib/commonjs/adminApp/actions/askApplySessionEventToLog.js.map +1 -1
  20. package/lib/commonjs/adminApp/adminAppRuntime.js +13 -1
  21. package/lib/commonjs/adminApp/adminAppRuntime.js.map +1 -1
  22. package/lib/commonjs/adminApp/components/AdminAppProvider/AdminAppProvider.js +5 -10
  23. package/lib/commonjs/adminApp/components/AdminAppProvider/AdminAppProvider.js.map +1 -1
  24. package/lib/commonjs/adminApp/hooks/useAdminApp.d.ts +1 -1
  25. package/lib/commonjs/adminApp/hooks/useAdminApp.js +3 -4
  26. package/lib/commonjs/adminApp/hooks/useAdminApp.js.map +1 -1
  27. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventAppended.js +7 -8
  28. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventAppended.js.map +1 -1
  29. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventSaved.js +3 -2
  30. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventSaved.js.map +1 -1
  31. package/lib/commonjs/adminApp/testHelpers/makeSessionEvent.js +2 -1
  32. package/lib/commonjs/adminApp/testHelpers/makeSessionEvent.js.map +1 -1
  33. package/lib/esm/App/App.js +5 -2
  34. package/lib/esm/App/App.js.map +1 -1
  35. package/lib/esm/Auth/Auth.js +1 -2
  36. package/lib/esm/Auth/Auth.js.map +1 -1
  37. package/lib/esm/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js +7 -2
  38. package/lib/esm/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js.map +1 -1
  39. package/lib/esm/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js +7 -2
  40. package/lib/esm/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js.map +1 -1
  41. package/lib/esm/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js +7 -2
  42. package/lib/esm/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js.map +1 -1
  43. package/lib/esm/Auth/logic/authRuntime.d.ts +2 -1
  44. package/lib/esm/Auth/logic/authRuntime.js +8 -1
  45. package/lib/esm/Auth/logic/authRuntime.js.map +1 -1
  46. package/lib/esm/LogViewer/LogChat/LogChat.js +1 -2
  47. package/lib/esm/LogViewer/LogChat/LogChat.js.map +1 -1
  48. package/lib/esm/LogViewer/LogChat/eventDocAiLogChatRuntime.js +11 -3
  49. package/lib/esm/LogViewer/LogChat/eventDocAiLogChatRuntime.js.map +1 -1
  50. package/lib/esm/adminApp/actions/askApplySessionEventToLog.js +4 -2
  51. package/lib/esm/adminApp/actions/askApplySessionEventToLog.js.map +1 -1
  52. package/lib/esm/adminApp/adminAppRuntime.js +13 -1
  53. package/lib/esm/adminApp/adminAppRuntime.js.map +1 -1
  54. package/lib/esm/adminApp/components/AdminAppProvider/AdminAppProvider.js +6 -11
  55. package/lib/esm/adminApp/components/AdminAppProvider/AdminAppProvider.js.map +1 -1
  56. package/lib/esm/adminApp/hooks/useAdminApp.d.ts +1 -1
  57. package/lib/esm/adminApp/hooks/useAdminApp.js +3 -4
  58. package/lib/esm/adminApp/hooks/useAdminApp.js.map +1 -1
  59. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventAppended.js +6 -13
  60. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventAppended.js.map +1 -1
  61. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventSaved.js +3 -8
  62. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventSaved.js.map +1 -1
  63. package/lib/esm/adminApp/testHelpers/makeSessionEvent.js +2 -1
  64. package/lib/esm/adminApp/testHelpers/makeSessionEvent.js.map +1 -1
  65. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"eventAppended.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventAppended.ts"],"names":[],"mappings":";;;AAEA,2EAAwE;AAIxE,MAAM,cAAc,GAAG,CAAC,KAAsB,EAAU,EAAE;;IACxD,MAAM,IAAI,GAAG,MAAA,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,mCAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1G,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AACxD,MAAM,aAAa,GAAG,CAAC,KAAsB,EAAE,KAAoB,EAAmB,EAAE;IAC7F,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEjE,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpF,MAAM,cAAc,GAClB,CAAC,CAAC,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,uCAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAA6B,CAAC,CAAC;IAEhI,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,SAAS,mCACV,KAAK,KACR,OAAO,kCACF,KAAK,CAAC,OAAO,KAChB,QAAQ,kCAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,SAE5E,CAAC;QAEF,uCACK,KAAK,KACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,IAC/D;IACJ,CAAC;IAED,MAAM,QAAQ,mCACT,KAAK,KACR,OAAO,kCACF,KAAK,CAAC,OAAO,KAChB,QAAQ,kCAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,SAEtE,CAAC;IAEF,uCACK,KAAK,KACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC,IACjD;AACJ,CAAC,CAAC;AAlCW,QAAA,aAAa,iBAkCxB","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { coalesceEventTypes } from '../../constants/coalesceEventTypes';\nimport { AdminSessionEventType } from '../../effects/session/AdminSessionEventType';\nimport { SessionLogState } from '../../SessionLogState';\n\nconst nextLocalIndex = (state: SessionLogState): number => {\n const tail = state.pendingEvents[state.pendingEvents.length - 1] ?? state.events[state.events.length - 1];\n return tail ? tail.payload.metadata.index + 1 : 0;\n};\n\n// Optimistic append with coalescing: while the previous event of the same\n// coalescable type is still pending, the new one replaces it (latest value\n// wins). The head is never coalesced while the flush has it in flight — the\n// POSTed clientMessageId must stay matchable for the save ack.\nexport const eventAppended = (state: SessionLogState, event: EventDocEvent): SessionLogState => {\n const last = state.pendingEvents[state.pendingEvents.length - 1];\n\n const lastIsInFlightHead = state.pendingEvents.length === 1 && state.flush.inFlight;\n const shouldCoalesce =\n !!last && !lastIsInFlightHead && last.type === event.type && coalesceEventTypes.includes(event.type as AdminSessionEventType);\n\n if (shouldCoalesce) {\n const coalesced: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: last.payload.metadata.index },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents.slice(0, -1), coalesced],\n };\n }\n\n const appended: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: nextLocalIndex(state) },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents, appended],\n };\n};\n"]}
1
+ {"version":3,"file":"eventAppended.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventAppended.ts"],"names":[],"mappings":";;;AAEA,2EAAwE;AAIxE,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AACxD,MAAM,aAAa,GAAG,CAAC,KAAsB,EAAE,KAAoB,EAAmB,EAAE;IAC7F,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEjE,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpF,MAAM,cAAc,GAClB,CAAC,CAAC,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,uCAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAA6B,CAAC,CAAC;IAEhI,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,SAAS,mCACV,KAAK,KACR,OAAO,kCACF,KAAK,CAAC,OAAO;gBAChB,mFAAmF;gBACnF,kCAAkC;gBAClC,QAAQ,kCAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,SAEhF,CAAC;QAEF,uCACK,KAAK,KACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,IAC/D;IACJ,CAAC;IAED,sFAAsF;IACtF,kDAAkD;IAClD,uCACK,KAAK,KACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,IAC9C;AACJ,CAAC,CAAC;AA9BW,QAAA,aAAa,iBA8BxB","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { coalesceEventTypes } from '../../constants/coalesceEventTypes';\nimport { AdminSessionEventType } from '../../effects/session/AdminSessionEventType';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Optimistic append with coalescing: while the previous event of the same\n// coalescable type is still pending, the new one replaces it (latest value\n// wins). The head is never coalesced while the flush has it in flight — the\n// POSTed clientMessageId must stay matchable for the save ack.\nexport const eventAppended = (state: SessionLogState, event: EventDocEvent): SessionLogState => {\n const last = state.pendingEvents[state.pendingEvents.length - 1];\n\n const lastIsInFlightHead = state.pendingEvents.length === 1 && state.flush.inFlight;\n const shouldCoalesce =\n !!last && !lastIsInFlightHead && last.type === event.type && coalesceEventTypes.includes(event.type as AdminSessionEventType);\n\n if (shouldCoalesce) {\n const coalesced: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n // Keeps the replaced event's id, so the coalesced event holds its place in the log\n // rather than jumping to the end.\n metadata: { ...event.payload.metadata, eventId: last.payload.metadata.eventId },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents.slice(0, -1), coalesced],\n };\n }\n\n // The event already carries the id minted when it was created, and sortable ids order\n // themselves, so there is nothing to assign here.\n return {\n ...state,\n pendingEvents: [...state.pendingEvents, event],\n };\n};\n"]}
@@ -7,8 +7,9 @@ exports.eventSaved = void 0;
7
7
  const eventSaved = (state, payload) => {
8
8
  const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);
9
9
  const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];
10
- const renumbered = remaining.map((event, offset) => (Object.assign(Object.assign({}, event), { payload: Object.assign(Object.assign({}, event.payload), { metadata: Object.assign(Object.assign({}, event.payload.metadata), { index: payload.storedEvent.payload.metadata.index + 1 + offset }) }) })));
11
- return Object.assign(Object.assign({}, state), { events: [...state.events, payload.storedEvent], pendingEvents: renumbered, flush: { inFlight: false, lastError: null, retryCount: 0 } });
10
+ // No renumbering: each pending event minted its own sortable id, which already sorts after
11
+ // the saved log. Removing one from the middle leaves the rest correctly ordered.
12
+ return Object.assign(Object.assign({}, state), { events: [...state.events, payload.storedEvent], pendingEvents: remaining, flush: { inFlight: false, lastError: null, retryCount: 0 } });
12
13
  };
13
14
  exports.eventSaved = eventSaved;
14
15
  //# sourceMappingURL=eventSaved.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"eventSaved.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventSaved.ts"],"names":[],"mappings":";;;AAKA,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AAC1E,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,OAAoC,EAAmB,EAAE;IAC1G,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7H,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAE/I,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAiB,EAAE,CAAC,iCAC9D,KAAK,KACR,OAAO,kCACF,KAAK,CAAC,OAAO,KAChB,QAAQ,kCAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,UAEvG,CAAC,CAAC;IAEJ,uCACK,KAAK,KACR,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,EAC9C,aAAa,EAAE,UAAU,EACzB,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,IAC1D;AACJ,CAAC,CAAC;AAnBW,QAAA,UAAU,cAmBrB","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { SessionLogEventSavedPayload } from '../../effects/sessionLog/SessionLogEventSavedEffect';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Server ack: the pending event moves to the acked log with its server-stamped\n// metadata, and the remaining pending events renumber onto consecutive indexes\n// after it (the server may have assigned a later index than our optimistic one).\nexport const eventSaved = (state: SessionLogState, payload: SessionLogEventSavedPayload): SessionLogState => {\n const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);\n\n const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];\n\n const renumbered = remaining.map((event, offset): EventDocEvent => ({\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: payload.storedEvent.payload.metadata.index + 1 + offset },\n },\n }));\n\n return {\n ...state,\n events: [...state.events, payload.storedEvent],\n pendingEvents: renumbered,\n flush: { inFlight: false, lastError: null, retryCount: 0 },\n };\n};\n"]}
1
+ {"version":3,"file":"eventSaved.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventSaved.ts"],"names":[],"mappings":";;;AAKA,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AAC1E,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,OAAoC,EAAmB,EAAE;IAC1G,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7H,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAE/I,2FAA2F;IAC3F,iFAAiF;IACjF,uCACK,KAAK,KACR,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,EAC9C,aAAa,EAAE,SAAS,EACxB,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,IAC1D;AACJ,CAAC,CAAC;AAbW,QAAA,UAAU,cAarB","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { SessionLogEventSavedPayload } from '../../effects/sessionLog/SessionLogEventSavedEffect';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Server ack: the pending event moves to the acked log with its server-stamped\n// metadata, and the remaining pending events renumber onto consecutive indexes\n// after it (the server may have assigned a later index than our optimistic one).\nexport const eventSaved = (state: SessionLogState, payload: SessionLogEventSavedPayload): SessionLogState => {\n const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);\n\n const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];\n\n // No renumbering: each pending event minted its own sortable id, which already sorts after\n // the saved log. Removing one from the middle leaves the rest correctly ordered.\n return {\n ...state,\n events: [...state.events, payload.storedEvent],\n pendingEvents: remaining,\n flush: { inFlight: false, lastError: null, retryCount: 0 },\n };\n};\n"]}
@@ -15,7 +15,8 @@ const makeSessionEvent = (type, data, index, overrides) => {
15
15
  clientMessageId: (_a = overrides === null || overrides === void 0 ? void 0 : overrides.clientMessageId) !== null && _a !== void 0 ? _a : `cmid-${index}`,
16
16
  createdBy: { userId: 'test-user', userDisplayName: 'Test User' },
17
17
  createdAt: (_b = overrides === null || overrides === void 0 ? void 0 : overrides.createdAt) !== null && _b !== void 0 ? _b : `2026-07-07T00:00:0${Math.min(index, 9)}.000Z`,
18
- index,
18
+ // Padded so the stub ids sort in creation order, like real sortable ids.
19
+ eventId: String(index).padStart(4, '0'),
19
20
  },
20
21
  },
21
22
  });
@@ -1 +1 @@
1
- {"version":3,"file":"makeSessionEvent.js","sourceRoot":"","sources":["../../../../src/adminApp/testHelpers/makeSessionEvent.ts"],"names":[],"mappings":";;;AACA,6DAAoE;AAEpE,sFAAmF;AAEnF,oEAAoE;AAC7D,MAAM,gBAAgB,GAAG,CAC9B,IAAY,EACZ,IAAO,EACP,KAAa,EACb,SAAoE,EACrD,EAAE;;IAAC,OAAA,CAAC;QACnB,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,qDAAyB;gBAClC,eAAe,EAAE,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,eAAe,mCAAI,QAAQ,KAAK,EAAE;gBAC9D,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE;gBAChE,SAAS,EAAE,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,SAAS,mCAAK,qBAAqB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAA0B;gBACrG,KAAK;aACN;SACF;KACF,CAAC,CAAA;CAAA,CAAC;AAjBU,QAAA,gBAAgB,oBAiB1B;AAEI,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,IAAY,EAAiB,EAAE,CAC5E,IAAA,wBAAgB,EAAC,oCAAc,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AADvE,QAAA,kBAAkB,sBACqD","sourcesContent":["import { QpqIsoDateTime } from 'quidproquo-core';\nimport { EventDocEffect, EventDocEvent } from 'quidproquo-features';\n\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\n\n// Builds a session event with sensible metadata defaults for tests.\nexport const makeSessionEvent = <T>(\n type: string,\n data: T,\n index: number,\n overrides?: { clientMessageId?: string; createdAt?: QpqIsoDateTime },\n): EventDocEvent => ({\n type,\n payload: {\n data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId: overrides?.clientMessageId ?? `cmid-${index}`,\n createdBy: { userId: 'test-user', userDisplayName: 'Test User' },\n createdAt: overrides?.createdAt ?? (`2026-07-07T00:00:0${Math.min(index, 9)}.000Z` as QpqIsoDateTime),\n index,\n },\n },\n});\n\nexport const makeInitStateEvent = (id: string, name: string): EventDocEvent =>\n makeSessionEvent(EventDocEffect.InitState, { id, code: 'session-code', name }, 0);\n"]}
1
+ {"version":3,"file":"makeSessionEvent.js","sourceRoot":"","sources":["../../../../src/adminApp/testHelpers/makeSessionEvent.ts"],"names":[],"mappings":";;;AACA,6DAAoE;AAEpE,sFAAmF;AAEnF,oEAAoE;AAC7D,MAAM,gBAAgB,GAAG,CAC9B,IAAY,EACZ,IAAO,EACP,KAAa,EACb,SAAoE,EACrD,EAAE;;IAAC,OAAA,CAAC;QACnB,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,qDAAyB;gBAClC,eAAe,EAAE,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,eAAe,mCAAI,QAAQ,KAAK,EAAE;gBAC9D,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE;gBAChE,SAAS,EAAE,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,SAAS,mCAAK,qBAAqB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAA0B;gBACrG,yEAAyE;gBACzE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;aACxC;SACF;KACF,CAAC,CAAA;CAAA,CAAC;AAlBU,QAAA,gBAAgB,oBAkB1B;AAEI,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,IAAY,EAAiB,EAAE,CAC5E,IAAA,wBAAgB,EAAC,oCAAc,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AADvE,QAAA,kBAAkB,sBACqD","sourcesContent":["import { QpqIsoDateTime } from 'quidproquo-core';\nimport { EventDocEffect, EventDocEvent } from 'quidproquo-features';\n\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\n\n// Builds a session event with sensible metadata defaults for tests.\nexport const makeSessionEvent = <T>(\n type: string,\n data: T,\n index: number,\n overrides?: { clientMessageId?: string; createdAt?: QpqIsoDateTime },\n): EventDocEvent => ({\n type,\n payload: {\n data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId: overrides?.clientMessageId ?? `cmid-${index}`,\n createdBy: { userId: 'test-user', userDisplayName: 'Test User' },\n createdAt: overrides?.createdAt ?? (`2026-07-07T00:00:0${Math.min(index, 9)}.000Z` as QpqIsoDateTime),\n // Padded so the stub ids sort in creation order, like real sortable ids.\n eventId: String(index).padStart(4, '0'),\n },\n },\n});\n\nexport const makeInitStateEvent = (id: string, name: string): EventDocEvent =>\n makeSessionEvent(EventDocEffect.InitState, { id, code: 'session-code', name }, 0);\n"]}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { BaseUrlProvider, QpqContextProvider, WebsocketProvider } from 'quidproquo-web-react';
2
+ import { BaseUrlProvider, createQpqStore, QpqContextProvider, QpqStoreProvider, WebsocketProvider } from 'quidproquo-web-react';
3
3
  import { useMemo } from 'react';
4
4
  import CssBaseline from '@mui/material/CssBaseline';
5
5
  import { createTheme, ThemeProvider } from '@mui/material/styles';
@@ -15,11 +15,14 @@ const darkTheme = createTheme({
15
15
  mode: 'light',
16
16
  },
17
17
  });
18
+ // Owned here (not by the provider) so the Redux DevTools bridge wires up once
19
+ // at module load; the extension shows the whole admin state as one object.
20
+ const adminQpqStore = createQpqStore({ devToolsName: 'qpq-admin' });
18
21
  export const App = ({ urlResolvers, loadAddons }) => {
19
22
  const baseUrls = useMemo(() => ({
20
23
  api: urlResolvers.getApiUrl(),
21
24
  ws: urlResolvers.getWsUrl(),
22
25
  }), [urlResolvers]);
23
- return (_jsx(QpqContextProvider, { contextIdentifier: baseUrlsContext, value: baseUrls, children: _jsx(BaseUrlProvider, { urlResolvers: urlResolvers, children: _jsxs(ThemeProvider, { theme: darkTheme, children: [_jsx(CssBaseline, {}), _jsx(LoadingProvider, { children: _jsx(Auth, { children: _jsx(AdminAppProvider, { children: _jsx(WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: _jsx(WebSocketAuthProvider, { children: _jsx(FederatedAddonProvider, { loadAddons: loadAddons, children: _jsx(MainLayout, {}) }) }) }) }) }) })] }) }) }));
26
+ return (_jsx(QpqStoreProvider, { store: adminQpqStore, children: _jsx(QpqContextProvider, { contextIdentifier: baseUrlsContext, value: baseUrls, children: _jsx(BaseUrlProvider, { urlResolvers: urlResolvers, children: _jsxs(ThemeProvider, { theme: darkTheme, children: [_jsx(CssBaseline, {}), _jsx(LoadingProvider, { children: _jsx(Auth, { children: _jsx(AdminAppProvider, { children: _jsx(WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: _jsx(WebSocketAuthProvider, { children: _jsx(FederatedAddonProvider, { loadAddons: loadAddons, children: _jsx(MainLayout, {}) }) }) }) }) }) })] }) }) }) }));
24
27
  };
25
28
  //# sourceMappingURL=App.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/App/App.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAoB,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEhH,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAY,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,SAAS,GAAG,WAAW,CAAC;IAC5B,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;KACd;CACF,CAAC,CAAC;AAUH,MAAM,CAAC,MAAM,GAAG,GAAuB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE;IACtE,MAAM,QAAQ,GAAa,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE;QAC7B,EAAE,EAAE,YAAY,CAAC,QAAQ,EAAE;KAC5B,CAAC,EACF,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,IAAC,iBAAiB,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,YACrE,KAAC,eAAe,IAAC,YAAY,EAAE,YAAY,YACzC,MAAC,aAAa,IAAC,KAAK,EAAE,SAAS,aAC7B,KAAC,WAAW,KAAG,EACf,KAAC,eAAe,cACd,KAAC,IAAI,cACH,KAAC,gBAAgB,cACf,KAAC,iBAAiB,IAAC,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,YAC/C,KAAC,qBAAqB,cACpB,KAAC,sBAAsB,IAAC,UAAU,EAAE,UAAU,YAC5C,KAAC,UAAU,KAAG,GACS,GACH,GACN,GACH,GACd,GACS,IACJ,GACA,GACC,CACtB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { BaseUrlProvider, BaseUrlResolvers, QpqContextProvider, WebsocketProvider } from 'quidproquo-web-react';\n\nimport React, { useMemo } from 'react';\nimport CssBaseline from '@mui/material/CssBaseline';\nimport { createTheme, ThemeProvider } from '@mui/material/styles';\n\nimport { AdminAppProvider } from '../adminApp';\nimport { Auth } from '../Auth/Auth';\nimport { MainLayout } from '../components';\nimport { LoadFederatedAddons } from '../FederatedAddon';\nimport { FederatedAddonProvider } from '../FederatedAddonProvider';\nimport { BaseUrls, baseUrlsContext } from '../platformLogic/contexts';\nimport { LoadingProvider } from '../view';\nimport { WebSocketAuthProvider } from '../WebSocketAuthProvider';\n\nconst darkTheme = createTheme({\n palette: {\n mode: 'light',\n },\n});\n\nexport type AppProps = {\n urlResolvers: BaseUrlResolvers;\n\n // Optional hook for the host application to federate / load admin addons.\n // When omitted, no addons are loaded.\n loadAddons?: LoadFederatedAddons;\n};\n\nexport const App: React.FC<AppProps> = ({ urlResolvers, loadAddons }) => {\n const baseUrls: BaseUrls = useMemo(\n () => ({\n api: urlResolvers.getApiUrl(),\n ws: urlResolvers.getWsUrl(),\n }),\n [urlResolvers],\n );\n\n return (\n <QpqContextProvider contextIdentifier={baseUrlsContext} value={baseUrls}>\n <BaseUrlProvider urlResolvers={urlResolvers}>\n <ThemeProvider theme={darkTheme}>\n <CssBaseline />\n <LoadingProvider>\n <Auth>\n <AdminAppProvider>\n <WebsocketProvider wsUrl={urlResolvers.getWsUrl()}>\n <WebSocketAuthProvider>\n <FederatedAddonProvider loadAddons={loadAddons}>\n <MainLayout />\n </FederatedAddonProvider>\n </WebSocketAuthProvider>\n </WebsocketProvider>\n </AdminAppProvider>\n </Auth>\n </LoadingProvider>\n </ThemeProvider>\n </BaseUrlProvider>\n </QpqContextProvider>\n );\n};\n"]}
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/App/App.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAoB,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAElJ,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAY,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,SAAS,GAAG,WAAW,CAAC;IAC5B,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;KACd;CACF,CAAC,CAAC;AAEH,8EAA8E;AAC9E,2EAA2E;AAC3E,MAAM,aAAa,GAAG,cAAc,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;AAUpE,MAAM,CAAC,MAAM,GAAG,GAAuB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE;IACtE,MAAM,QAAQ,GAAa,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE;QAC7B,EAAE,EAAE,YAAY,CAAC,QAAQ,EAAE;KAC5B,CAAC,EACF,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,OAAO,CACL,KAAC,gBAAgB,IAAC,KAAK,EAAE,aAAa,YACpC,KAAC,kBAAkB,IAAC,iBAAiB,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,YACrE,KAAC,eAAe,IAAC,YAAY,EAAE,YAAY,YACzC,MAAC,aAAa,IAAC,KAAK,EAAE,SAAS,aAC7B,KAAC,WAAW,KAAG,EACf,KAAC,eAAe,cACd,KAAC,IAAI,cACH,KAAC,gBAAgB,cACf,KAAC,iBAAiB,IAAC,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,YAC/C,KAAC,qBAAqB,cACpB,KAAC,sBAAsB,IAAC,UAAU,EAAE,UAAU,YAC5C,KAAC,UAAU,KAAG,GACS,GACH,GACN,GACH,GACd,GACS,IACJ,GACA,GACC,GACJ,CACpB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { BaseUrlProvider, BaseUrlResolvers, createQpqStore, QpqContextProvider, QpqStoreProvider, WebsocketProvider } from 'quidproquo-web-react';\n\nimport React, { useMemo } from 'react';\nimport CssBaseline from '@mui/material/CssBaseline';\nimport { createTheme, ThemeProvider } from '@mui/material/styles';\n\nimport { AdminAppProvider } from '../adminApp';\nimport { Auth } from '../Auth/Auth';\nimport { MainLayout } from '../components';\nimport { LoadFederatedAddons } from '../FederatedAddon';\nimport { FederatedAddonProvider } from '../FederatedAddonProvider';\nimport { BaseUrls, baseUrlsContext } from '../platformLogic/contexts';\nimport { LoadingProvider } from '../view';\nimport { WebSocketAuthProvider } from '../WebSocketAuthProvider';\n\nconst darkTheme = createTheme({\n palette: {\n mode: 'light',\n },\n});\n\n// Owned here (not by the provider) so the Redux DevTools bridge wires up once\n// at module load; the extension shows the whole admin state as one object.\nconst adminQpqStore = createQpqStore({ devToolsName: 'qpq-admin' });\n\nexport type AppProps = {\n urlResolvers: BaseUrlResolvers;\n\n // Optional hook for the host application to federate / load admin addons.\n // When omitted, no addons are loaded.\n loadAddons?: LoadFederatedAddons;\n};\n\nexport const App: React.FC<AppProps> = ({ urlResolvers, loadAddons }) => {\n const baseUrls: BaseUrls = useMemo(\n () => ({\n api: urlResolvers.getApiUrl(),\n ws: urlResolvers.getWsUrl(),\n }),\n [urlResolvers],\n );\n\n return (\n <QpqStoreProvider store={adminQpqStore}>\n <QpqContextProvider contextIdentifier={baseUrlsContext} value={baseUrls}>\n <BaseUrlProvider urlResolvers={urlResolvers}>\n <ThemeProvider theme={darkTheme}>\n <CssBaseline />\n <LoadingProvider>\n <Auth>\n <AdminAppProvider>\n <WebsocketProvider wsUrl={urlResolvers.getWsUrl()}>\n <WebSocketAuthProvider>\n <FederatedAddonProvider loadAddons={loadAddons}>\n <MainLayout />\n </FederatedAddonProvider>\n </WebSocketAuthProvider>\n </WebsocketProvider>\n </AdminAppProvider>\n </Auth>\n </LoadingProvider>\n </ThemeProvider>\n </BaseUrlProvider>\n </QpqContextProvider>\n </QpqStoreProvider>\n );\n};\n"]}
@@ -5,11 +5,10 @@ import { AuthChallengeMfaSetup } from './AuthChallengeMfaSetup/AuthChallengeMfaS
5
5
  import { AuthChallengeNewPasswordRequired } from './AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired';
6
6
  import { AuthChallengeSoftwareTokenMfa } from './AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa';
7
7
  import { isLoggedOn } from './logic/isLoggedOn';
8
- import { askAuthMain } from './logic/runtime/askAuthMain';
9
8
  import { authRuntime } from './logic';
10
9
  import { Login } from './Login';
11
10
  export function Auth({ children }) {
12
- const [api, state, dispatch] = useQpqRuntime(authRuntime, askAuthMain);
11
+ const [api, state] = useQpqRuntime(authRuntime);
13
12
  const isAuthenticated = isLoggedOn(state);
14
13
  if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED) {
15
14
  return (_jsx(QpqRuntimeEffectCatcher, { runtime: authRuntime, children: _jsx(AuthChallengeNewPasswordRequired, { authState: state }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"Auth.js","sourceRoot":"","sources":["../../../src/Auth/Auth.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,qEAAqE,CAAC;AACvH,OAAO,EAAE,6BAA6B,EAAE,MAAM,+DAA+D,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMhC,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAa;IAC1C,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAEvE,MAAM,eAAe,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,qBAAqB,EAAE,CAAC;QAClG,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,gCAAgC,IAAC,SAAS,EAAE,KAAK,GAAqC,GAC/D,CAC3B,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,kBAAkB,EAAE,CAAC;QAC/F,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,6BAA6B,IAAC,SAAS,EAAE,KAAK,GAAkC,GACzD,CAC3B,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,SAAS,EAAE,CAAC;QACtF,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,qBAAqB,IAAC,SAAS,EAAE,KAAK,GAA0B,GACzC,CAC3B,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,aAC1C,CAAC,eAAe,IAAI,CACnB,KAAC,KAAK,IACJ,OAAO,EAAE,GAAG,CAAC,SAAS,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,WAAW,EAAE,GAAG,CAAC,iBAAiB,EAClC,WAAW,EAAE,GAAG,CAAC,iBAAiB,EAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GACxB,CACH,EACA,eAAe,IAAI,CAClB,KAAC,WAAW,CAAC,QAAQ,IACnB,KAAK,EAAE;oBACL,SAAS,EAAE,KAAK,CAAC,wBAAwB,EAAE,SAAS;oBACpD,OAAO,EAAE,KAAK,CAAC,wBAAwB,EAAE,OAAO;oBAChD,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,kBAAkB,EAAE,KAAK,CAAC,wBAAwB,EAAE,kBAAkB;iBACvE,YAEA,QAAQ,GACY,CACxB,IACuB,CAC3B,CAAC;AACJ,CAAC","sourcesContent":["import { AuthenticateUserChallenge } from 'quidproquo-core';\nimport { authContext, QpqRuntimeEffectCatcher, useQpqRuntime } from 'quidproquo-web-react';\n\nimport { ReactNode, useEffect } from 'react';\n\nimport { AuthChallengeMfaSetup } from './AuthChallengeMfaSetup/AuthChallengeMfaSetup';\nimport { AuthChallengeNewPasswordRequired } from './AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired';\nimport { AuthChallengeSoftwareTokenMfa } from './AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa';\nimport { isLoggedOn } from './logic/isLoggedOn';\nimport { askAuthMain } from './logic/runtime/askAuthMain';\nimport { authRuntime } from './logic';\nimport { Login } from './Login';\n\ninterface AuthProps {\n children?: ReactNode;\n}\n\nexport function Auth({ children }: AuthProps) {\n const [api, state, dispatch] = useQpqRuntime(authRuntime, askAuthMain);\n\n const isAuthenticated = isLoggedOn(state);\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeNewPasswordRequired authState={state}></AuthChallengeNewPasswordRequired>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeSoftwareTokenMfa authState={state}></AuthChallengeSoftwareTokenMfa>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.MFA_SETUP) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeMfaSetup authState={state}></AuthChallengeMfaSetup>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n {!isAuthenticated && (\n <Login\n onLogin={api.authLogin}\n password={state.password}\n setPassword={api.authUISetPassword}\n setUsername={api.authUISetUsername}\n username={state.username}\n />\n )}\n {isAuthenticated && (\n <authContext.Provider\n value={{\n challenge: state.authenticateUserResponse?.challenge,\n session: state.authenticateUserResponse?.session,\n username: state.username,\n password: state.password,\n authenticationInfo: state.authenticateUserResponse?.authenticationInfo,\n }}\n >\n {children}\n </authContext.Provider>\n )}\n </QpqRuntimeEffectCatcher>\n );\n}\n"]}
1
+ {"version":3,"file":"Auth.js","sourceRoot":"","sources":["../../../src/Auth/Auth.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,qEAAqE,CAAC;AACvH,OAAO,EAAE,6BAA6B,EAAE,MAAM,+DAA+D,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMhC,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAa;IAC1C,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAEhD,MAAM,eAAe,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,qBAAqB,EAAE,CAAC;QAClG,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,gCAAgC,IAAC,SAAS,EAAE,KAAK,GAAqC,GAC/D,CAC3B,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,kBAAkB,EAAE,CAAC;QAC/F,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,6BAA6B,IAAC,SAAS,EAAE,KAAK,GAAkC,GACzD,CAC3B,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,wBAAwB,EAAE,SAAS,KAAK,yBAAyB,CAAC,SAAS,EAAE,CAAC;QACtF,OAAO,CACL,KAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,YAC3C,KAAC,qBAAqB,IAAC,SAAS,EAAE,KAAK,GAA0B,GACzC,CAC3B,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,uBAAuB,IAAC,OAAO,EAAE,WAAW,aAC1C,CAAC,eAAe,IAAI,CACnB,KAAC,KAAK,IACJ,OAAO,EAAE,GAAG,CAAC,SAAS,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,WAAW,EAAE,GAAG,CAAC,iBAAiB,EAClC,WAAW,EAAE,GAAG,CAAC,iBAAiB,EAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GACxB,CACH,EACA,eAAe,IAAI,CAClB,KAAC,WAAW,CAAC,QAAQ,IACnB,KAAK,EAAE;oBACL,SAAS,EAAE,KAAK,CAAC,wBAAwB,EAAE,SAAS;oBACpD,OAAO,EAAE,KAAK,CAAC,wBAAwB,EAAE,OAAO;oBAChD,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,kBAAkB,EAAE,KAAK,CAAC,wBAAwB,EAAE,kBAAkB;iBACvE,YAEA,QAAQ,GACY,CACxB,IACuB,CAC3B,CAAC;AACJ,CAAC","sourcesContent":["import { AuthenticateUserChallenge } from 'quidproquo-core';\nimport { authContext, QpqRuntimeEffectCatcher, useQpqRuntime } from 'quidproquo-web-react';\n\nimport { ReactNode } from 'react';\n\nimport { AuthChallengeMfaSetup } from './AuthChallengeMfaSetup/AuthChallengeMfaSetup';\nimport { AuthChallengeNewPasswordRequired } from './AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired';\nimport { AuthChallengeSoftwareTokenMfa } from './AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa';\nimport { isLoggedOn } from './logic/isLoggedOn';\nimport { authRuntime } from './logic';\nimport { Login } from './Login';\n\ninterface AuthProps {\n children?: ReactNode;\n}\n\nexport function Auth({ children }: AuthProps) {\n const [api, state] = useQpqRuntime(authRuntime);\n\n const isAuthenticated = isLoggedOn(state);\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeNewPasswordRequired authState={state}></AuthChallengeNewPasswordRequired>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeSoftwareTokenMfa authState={state}></AuthChallengeSoftwareTokenMfa>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n if (state.authenticateUserResponse?.challenge === AuthenticateUserChallenge.MFA_SETUP) {\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n <AuthChallengeMfaSetup authState={state}></AuthChallengeMfaSetup>\n </QpqRuntimeEffectCatcher>\n );\n }\n\n return (\n <QpqRuntimeEffectCatcher runtime={authRuntime}>\n {!isAuthenticated && (\n <Login\n onLogin={api.authLogin}\n password={state.password}\n setPassword={api.authUISetPassword}\n setUsername={api.authUISetUsername}\n username={state.username}\n />\n )}\n {isAuthenticated && (\n <authContext.Provider\n value={{\n challenge: state.authenticateUserResponse?.challenge,\n session: state.authenticateUserResponse?.session,\n username: state.username,\n password: state.password,\n authenticationInfo: state.authenticateUserResponse?.authenticationInfo,\n }}\n >\n {children}\n </authContext.Provider>\n )}\n </QpqRuntimeEffectCatcher>\n );\n}\n"]}
@@ -8,7 +8,12 @@ import TextField from '@mui/material/TextField';
8
8
  import Typography from '@mui/material/Typography';
9
9
  import { AsyncButton } from '../../components';
10
10
  import { authChallengeMfaSetupInitalState, authChallengeMfaSetupLogic, authChallengeMfaSetupReducer } from './logic';
11
- const atom = createQpqRuntimeDefinition(authChallengeMfaSetupLogic, authChallengeMfaSetupInitalState, authChallengeMfaSetupReducer);
11
+ const challengeRuntime = createQpqRuntimeDefinition({
12
+ uniqueName: 'qpq/admin/authChallengeMfaSetup',
13
+ api: authChallengeMfaSetupLogic,
14
+ initialState: authChallengeMfaSetupInitalState,
15
+ reducer: authChallengeMfaSetupReducer,
16
+ });
12
17
  // otpauth:// URI consumed by authenticator apps when scanning / importing.
13
18
  const buildOtpAuthUri = (email, secretCode) => {
14
19
  const issuer = window.location.host;
@@ -16,7 +21,7 @@ const buildOtpAuthUri = (email, secretCode) => {
16
21
  return `otpauth://totp/${label}?secret=${secretCode}&issuer=${encodeURIComponent(issuer)}`;
17
22
  };
18
23
  export function AuthChallengeMfaSetup({ authState }) {
19
- const [api, state] = useQpqRuntime(atom);
24
+ const [api, state] = useQpqRuntime(challengeRuntime);
20
25
  const isCodeValid = /^\d{6}$/.test(state.mfaCode);
21
26
  const challenge = authState.authenticateUserResponse?.challenge;
22
27
  const session = authState.authenticateUserResponse?.session;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthChallengeMfaSetup.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport { useEffect, useRef } from 'react';\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeMfaSetupInitalState, authChallengeMfaSetupLogic, authChallengeMfaSetupReducer } from './logic';\n\ninterface AuthChallengeMfaSetupProps {\n authState: AuthState;\n}\n\nconst atom = createQpqRuntimeDefinition(authChallengeMfaSetupLogic, authChallengeMfaSetupInitalState, authChallengeMfaSetupReducer);\n\n// otpauth:// URI consumed by authenticator apps when scanning / importing.\nconst buildOtpAuthUri = (email: string, secretCode: string): string => {\n const issuer = window.location.host;\n const label = encodeURIComponent(`${issuer}:${email}`);\n return `otpauth://totp/${label}?secret=${secretCode}&issuer=${encodeURIComponent(issuer)}`;\n};\n\nexport function AuthChallengeMfaSetup({ authState }: AuthChallengeMfaSetupProps) {\n const [api, state] = useQpqRuntime(atom);\n const isCodeValid = /^\\d{6}$/.test(state.mfaCode);\n\n const challenge = authState.authenticateUserResponse?.challenge;\n const session = authState.authenticateUserResponse?.session;\n\n // Associate a software token once, using the MFA_SETUP challenge session.\n const hasAssociated = useRef(false);\n useEffect(() => {\n if (!hasAssociated.current && session) {\n hasAssociated.current = true;\n api.authChallengeAssociateSoftwareToken(session);\n }\n }, [api, session]);\n\n if (!challenge || !session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Set Up Authenticator\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Add this account to your authenticator app, then enter the 6-digit code it generates.\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"caption\">\n Secret key\n </Typography>\n <Typography sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }} variant=\"body1\">\n {state.secretCode || 'Loading…'}\n </Typography>\n </Grid>\n {state.secretCode && (\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" sx={{ wordBreak: 'break-all' }} variant=\"caption\">\n {buildOtpAuthUri(authState.username, state.secretCode)}\n </Typography>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"mfaCode\"\n inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', maxLength: 6 }}\n label=\"Authentication Code\"\n onChange={(event) => api.authChallengeSetMfaSetupCode(event.target.value.replace(/\\D/g, ''))}\n required\n value={state.mfaCode}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!isCodeValid || !state.secretCode}\n onClick={() => api.authChallengeSendMfaSetupCode(challenge, authState.username)}\n >\n Verify\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"AuthChallengeMfaSetup.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport { useEffect, useRef } from 'react';\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeMfaSetupInitalState, authChallengeMfaSetupLogic, authChallengeMfaSetupReducer } from './logic';\n\ninterface AuthChallengeMfaSetupProps {\n authState: AuthState;\n}\n\nconst challengeRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/authChallengeMfaSetup',\n api: authChallengeMfaSetupLogic,\n initialState: authChallengeMfaSetupInitalState,\n reducer: authChallengeMfaSetupReducer,\n});\n\n// otpauth:// URI consumed by authenticator apps when scanning / importing.\nconst buildOtpAuthUri = (email: string, secretCode: string): string => {\n const issuer = window.location.host;\n const label = encodeURIComponent(`${issuer}:${email}`);\n return `otpauth://totp/${label}?secret=${secretCode}&issuer=${encodeURIComponent(issuer)}`;\n};\n\nexport function AuthChallengeMfaSetup({ authState }: AuthChallengeMfaSetupProps) {\n const [api, state] = useQpqRuntime(challengeRuntime);\n const isCodeValid = /^\\d{6}$/.test(state.mfaCode);\n\n const challenge = authState.authenticateUserResponse?.challenge;\n const session = authState.authenticateUserResponse?.session;\n\n // Associate a software token once, using the MFA_SETUP challenge session.\n const hasAssociated = useRef(false);\n useEffect(() => {\n if (!hasAssociated.current && session) {\n hasAssociated.current = true;\n api.authChallengeAssociateSoftwareToken(session);\n }\n }, [api, session]);\n\n if (!challenge || !session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Set Up Authenticator\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Add this account to your authenticator app, then enter the 6-digit code it generates.\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"caption\">\n Secret key\n </Typography>\n <Typography sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }} variant=\"body1\">\n {state.secretCode || 'Loading…'}\n </Typography>\n </Grid>\n {state.secretCode && (\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" sx={{ wordBreak: 'break-all' }} variant=\"caption\">\n {buildOtpAuthUri(authState.username, state.secretCode)}\n </Typography>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"mfaCode\"\n inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', maxLength: 6 }}\n label=\"Authentication Code\"\n onChange={(event) => api.authChallengeSetMfaSetupCode(event.target.value.replace(/\\D/g, ''))}\n required\n value={state.mfaCode}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!isCodeValid || !state.secretCode}\n onClick={() => api.authChallengeSendMfaSetupCode(challenge, authState.username)}\n >\n Verify\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
@@ -8,9 +8,14 @@ import TextField from '@mui/material/TextField';
8
8
  import Typography from '@mui/material/Typography';
9
9
  import { AsyncButton } from '../../components';
10
10
  import { authChallengeInitalState, authChallengeLogic, authChallengeReducer } from './logic';
11
- const atom = createQpqRuntimeDefinition(authChallengeLogic, authChallengeInitalState, authChallengeReducer);
11
+ const challengeRuntime = createQpqRuntimeDefinition({
12
+ uniqueName: 'qpq/admin/authChallengeNewPasswordRequired',
13
+ api: authChallengeLogic,
14
+ initialState: authChallengeInitalState,
15
+ reducer: authChallengeReducer,
16
+ });
12
17
  export function AuthChallengeNewPasswordRequired({ authState }) {
13
- const [api, state] = useQpqRuntime(atom);
18
+ const [api, state] = useQpqRuntime(challengeRuntime);
14
19
  const arePasswordsMatching = state.passwordA === state.passwordB && state.passwordA !== '';
15
20
  if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {
16
21
  return _jsx("div", { children: "Error, missing challenge / session" });
@@ -1 +1 @@
1
- {"version":3,"file":"AuthChallengeNewPasswordRequired.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */\nimport { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeInitalState, authChallengeLogic, authChallengeReducer } from './logic';\n\ninterface AuthChallengeNewPasswordRequiredProps {\n authState: AuthState;\n}\n\nconst atom = createQpqRuntimeDefinition(authChallengeLogic, authChallengeInitalState, authChallengeReducer);\n\nexport function AuthChallengeNewPasswordRequired({ authState }: AuthChallengeNewPasswordRequiredProps) {\n const [api, state] = useQpqRuntime(atom);\n const arePasswordsMatching = state.passwordA === state.passwordB && state.passwordA !== '';\n\n if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Password Change Required\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"newPassword\"\n label=\"New Password\"\n onChange={(event) => api.authChallengeSetPasswordA(event.target.value)}\n required\n type=\"password\"\n value={state.passwordA}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n id=\"confirmPassword\"\n label=\"Confirm Password\"\n onChange={(event) => api.authChallengeSetPasswordB(event.target.value)}\n required\n type=\"password\"\n value={state.passwordB}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!arePasswordsMatching}\n onClick={() =>\n api.authChallengeSendPasswords(\n authState.authenticateUserResponse?.challenge!,\n authState.authenticateUserResponse?.session!,\n authState.username,\n )\n }\n >\n Update Password\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"AuthChallengeNewPasswordRequired.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */\nimport { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeInitalState, authChallengeLogic, authChallengeReducer } from './logic';\n\ninterface AuthChallengeNewPasswordRequiredProps {\n authState: AuthState;\n}\n\nconst challengeRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/authChallengeNewPasswordRequired',\n api: authChallengeLogic,\n initialState: authChallengeInitalState,\n reducer: authChallengeReducer,\n});\n\nexport function AuthChallengeNewPasswordRequired({ authState }: AuthChallengeNewPasswordRequiredProps) {\n const [api, state] = useQpqRuntime(challengeRuntime);\n const arePasswordsMatching = state.passwordA === state.passwordB && state.passwordA !== '';\n\n if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Password Change Required\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"newPassword\"\n label=\"New Password\"\n onChange={(event) => api.authChallengeSetPasswordA(event.target.value)}\n required\n type=\"password\"\n value={state.passwordA}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n id=\"confirmPassword\"\n label=\"Confirm Password\"\n onChange={(event) => api.authChallengeSetPasswordB(event.target.value)}\n required\n type=\"password\"\n value={state.passwordB}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!arePasswordsMatching}\n onClick={() =>\n api.authChallengeSendPasswords(\n authState.authenticateUserResponse?.challenge!,\n authState.authenticateUserResponse?.session!,\n authState.username,\n )\n }\n >\n Update Password\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
@@ -8,9 +8,14 @@ import TextField from '@mui/material/TextField';
8
8
  import Typography from '@mui/material/Typography';
9
9
  import { AsyncButton } from '../../components';
10
10
  import { authChallengeMfaInitalState, authChallengeMfaLogic, authChallengeMfaReducer } from './logic';
11
- const atom = createQpqRuntimeDefinition(authChallengeMfaLogic, authChallengeMfaInitalState, authChallengeMfaReducer);
11
+ const challengeRuntime = createQpqRuntimeDefinition({
12
+ uniqueName: 'qpq/admin/authChallengeSoftwareTokenMfa',
13
+ api: authChallengeMfaLogic,
14
+ initialState: authChallengeMfaInitalState,
15
+ reducer: authChallengeMfaReducer,
16
+ });
12
17
  export function AuthChallengeSoftwareTokenMfa({ authState }) {
13
- const [api, state] = useQpqRuntime(atom);
18
+ const [api, state] = useQpqRuntime(challengeRuntime);
14
19
  const isCodeValid = /^\d{6}$/.test(state.mfaCode);
15
20
  if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {
16
21
  return _jsx("div", { children: "Error, missing challenge / session" });
@@ -1 +1 @@
1
- {"version":3,"file":"AuthChallengeSoftwareTokenMfa.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */\nimport { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeMfaInitalState, authChallengeMfaLogic, authChallengeMfaReducer } from './logic';\n\ninterface AuthChallengeSoftwareTokenMfaProps {\n authState: AuthState;\n}\n\nconst atom = createQpqRuntimeDefinition(authChallengeMfaLogic, authChallengeMfaInitalState, authChallengeMfaReducer);\n\nexport function AuthChallengeSoftwareTokenMfa({ authState }: AuthChallengeSoftwareTokenMfaProps) {\n const [api, state] = useQpqRuntime(atom);\n const isCodeValid = /^\\d{6}$/.test(state.mfaCode);\n\n if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Verification Code\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Enter the 6-digit code from your authenticator app.\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"mfaCode\"\n inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', maxLength: 6 }}\n label=\"Authentication Code\"\n onChange={(event) => api.authChallengeSetMfaCode(event.target.value.replace(/\\D/g, ''))}\n required\n value={state.mfaCode}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!isCodeValid}\n onClick={() =>\n api.authChallengeSendMfaCode(\n authState.authenticateUserResponse?.challenge!,\n authState.authenticateUserResponse?.session!,\n authState.username,\n )\n }\n >\n Verify\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"AuthChallengeSoftwareTokenMfa.js","sourceRoot":"","sources":["../../../../src/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */\nimport { createQpqRuntimeDefinition, useQpqRuntime } from 'quidproquo-web-react';\n\nimport LockIcon from '@mui/icons-material/Lock';\nimport Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport { AsyncButton } from '../../components';\nimport { AuthState } from '../logic';\nimport { authChallengeMfaInitalState, authChallengeMfaLogic, authChallengeMfaReducer } from './logic';\n\ninterface AuthChallengeSoftwareTokenMfaProps {\n authState: AuthState;\n}\n\nconst challengeRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/authChallengeSoftwareTokenMfa',\n api: authChallengeMfaLogic,\n initialState: authChallengeMfaInitalState,\n reducer: authChallengeMfaReducer,\n});\n\nexport function AuthChallengeSoftwareTokenMfa({ authState }: AuthChallengeSoftwareTokenMfaProps) {\n const [api, state] = useQpqRuntime(challengeRuntime);\n const isCodeValid = /^\\d{6}$/.test(state.mfaCode);\n\n if (!authState.authenticateUserResponse || !authState.authenticateUserResponse.challenge || !authState.authenticateUserResponse.session) {\n return <div>Error, missing challenge / session</div>;\n }\n\n return (\n <Box\n sx={{\n height: '100vh',\n width: '100%',\n p: 2,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <Box component=\"form\" sx={{ width: '100%', maxWidth: 360 }}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography gutterBottom sx={{ display: 'flex', alignItems: 'center' }} variant=\"h5\">\n <LockIcon sx={{ marginRight: 1 }} />\n Verification Code\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Enter the 6-digit code from your authenticator app.\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <TextField\n autoFocus\n fullWidth\n id=\"mfaCode\"\n inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', maxLength: 6 }}\n label=\"Authentication Code\"\n onChange={(event) => api.authChallengeSetMfaCode(event.target.value.replace(/\\D/g, ''))}\n required\n value={state.mfaCode}\n />\n </Grid>\n <Grid item xs={12}>\n <AsyncButton\n disabled={!isCodeValid}\n onClick={() =>\n api.authChallengeSendMfaCode(\n authState.authenticateUserResponse?.challenge!,\n authState.authenticateUserResponse?.session!,\n authState.username,\n )\n }\n >\n Verify\n </AsyncButton>\n </Grid>\n </Grid>\n </Box>\n </Box>\n );\n}\n"]}
@@ -1,7 +1,8 @@
1
+ import { askAuthMain } from './runtime/askAuthMain';
1
2
  export declare const authRuntime: import("quidproquo-web-react").QpqRuntimeDefinition<import("./authTypes").AuthState, import("./authTypes").AuthEffects, {
2
3
  askAuthLogin: typeof import("./runtime/askAuthLogin").askAuthLogin;
3
4
  askAuthLogout: typeof import("./runtime/askAuthLogout").askAuthLogout;
4
- askAuthMain: typeof import("./runtime/askAuthMain").askAuthMain;
5
+ askAuthMain: typeof askAuthMain;
5
6
  askAuthUISetUsername: typeof import("./authActionCreator").askAuthUISetUsername;
6
7
  askAuthUISetPassword: typeof import("./authActionCreator").askAuthUISetPassword;
7
8
  }>;
@@ -1,5 +1,12 @@
1
1
  import { createQpqRuntimeDefinition } from 'quidproquo-web-react';
2
+ import { askAuthMain } from './runtime/askAuthMain';
2
3
  import { authLogic } from './runtime/authLogic';
3
4
  import { authInitalState, authReducer } from './authReducer';
4
- export const authRuntime = createQpqRuntimeDefinition(authLogic, authInitalState, authReducer);
5
+ export const authRuntime = createQpqRuntimeDefinition({
6
+ uniqueName: 'qpq/admin/auth',
7
+ api: authLogic,
8
+ initialState: authInitalState,
9
+ reducer: authReducer,
10
+ onInit: askAuthMain,
11
+ });
5
12
  //# sourceMappingURL=authRuntime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authRuntime.js","sourceRoot":"","sources":["../../../../src/Auth/logic/authRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC,SAAS,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC","sourcesContent":["import { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\nimport { authLogic } from './runtime/authLogic';\nimport { authInitalState, authReducer } from './authReducer';\n\nexport const authRuntime = createQpqRuntimeDefinition(authLogic, authInitalState, authReducer);\n"]}
1
+ {"version":3,"file":"authRuntime.js","sourceRoot":"","sources":["../../../../src/Auth/logic/authRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;IACpD,UAAU,EAAE,gBAAgB;IAC5B,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,eAAe;IAC7B,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,WAAW;CACpB,CAAC,CAAC","sourcesContent":["import { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\nimport { askAuthMain } from './runtime/askAuthMain';\nimport { authLogic } from './runtime/authLogic';\nimport { authInitalState, authReducer } from './authReducer';\n\nexport const authRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/auth',\n api: authLogic,\n initialState: authInitalState,\n reducer: authReducer,\n onInit: askAuthMain,\n});\n"]}
@@ -6,13 +6,12 @@ import { useEffect, useRef, useState } from 'react';
6
6
  import { Android as AndroidIcon, Person as PersonIcon } from '@mui/icons-material';
7
7
  import { Avatar, Box, Button, CircularProgress, Paper, TextField, Typography } from '@mui/material';
8
8
  import { useAdminApp } from '../../adminApp';
9
- import { askEventDocAiLogChatBoot } from './logic/askEventDocAiLogChatBoot';
10
9
  import { eventDocAiLogChatRuntime } from './eventDocAiLogChatRuntime';
11
10
  import { EventDocAiSegments } from './EventDocAiSegments';
12
11
  const LogChatConversation = ({ logCorrelation }) => {
13
12
  const [inputMessage, setInputMessage] = useState('');
14
13
  const chatContainerRef = useRef(null);
15
- const [api, state] = useQpqWebsocketQueueRuntime(eventDocAiLogChatRuntime, askEventDocAiLogChatBoot, logCorrelation);
14
+ const [api, state] = useQpqWebsocketQueueRuntime(eventDocAiLogChatRuntime, logCorrelation);
16
15
  const [adminApi] = useAdminApp();
17
16
  const streamSegments = mergeStreamParts(state.streamParts);
18
17
  const isThinking = state.isSending && streamSegments.length === 0;
@@ -1 +1 @@
1
- {"version":3,"file":"LogChat.js","sourceRoot":"","sources":["../../../../src/LogViewer/LogChat/LogChat.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEvF,OAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEpG,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,MAAM,mBAAmB,GAAyC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;IACvF,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEtD,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,2BAA2B,CAAC,wBAAwB,EAAE,wBAAwB,EAAE,cAAc,CAAC,CAAC;IACrH,MAAM,CAAC,QAAQ,CAAC,GAAG,WAAW,EAAE,CAAC;IAEjC,MAAM,cAAc,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC;IAElE,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,GAAG,EAAE;QAC/C,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/B,+EAA+E;YAC/E,QAAQ,CAAC,eAAe,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YACvD,GAAG,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;YACxC,eAAe,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,CAAC,KAA0C,EAAE,EAAE;QACpE,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YAC1B,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC7B,gBAAgB,CAAC,OAAO,CAAC,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC;QAC7E,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAEzC,OAAO,CACL,MAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aACnE,MAAC,GAAG,IAAC,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,aACrE,KAAK,CAAC,gBAAgB,IAAI,CACzB,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,YAC1D,KAAC,gBAAgB,IAAC,IAAI,EAAE,EAAE,GAAI,GAC1B,CACP,EACA,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1C,KAAC,GAAG,IAEF,EAAE,EAAE;4BACF,OAAO,EAAE,MAAM;4BACf,UAAU,EAAE,YAAY;4BACxB,EAAE,EAAE,CAAC;4BACL,cAAc,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;yBACzE,YAED,MAAC,KAAK,IACJ,EAAE,EAAE;gCACF,CAAC,EAAE,CAAC;gCACJ,YAAY,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB;gCACpF,eAAe,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc;gCAC3E,KAAK,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;gCACvD,QAAQ,EAAE,KAAK;6BAChB,aAED,MAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,aACvD,KAAC,MAAM,IAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,EAAE,YACvF,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,KAAC,WAAW,KAAG,CAAC,CAAC,CAAC,KAAC,UAAU,KAAG,GACzD,EACT,KAAC,UAAU,IAAC,OAAO,EAAC,WAAW,YAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,GAAc,IAChG,EACN,KAAC,kBAAkB,IAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAI,IAC5C,IAxBH,KAAK,CAyBN,CACP,CAAC,EACD,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,CAC5B,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,EAAE,cAAc,EAAE,YAAY,EAAE,YACzF,MAAC,KAAK,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,aACjH,MAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,aACvD,KAAC,MAAM,IAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,YACxC,KAAC,WAAW,KAAG,GACR,EACT,KAAC,UAAU,IAAC,OAAO,EAAC,WAAW,6BAA0B,IACrD,EACN,KAAC,kBAAkB,IAAC,QAAQ,EAAE,cAAc,GAAI,IAC1C,GACJ,CACP,EACA,UAAU,IAAI,CACb,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,EAAE,cAAc,EAAE,YAAY,EAAE,YACzF,KAAC,KAAK,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YACjH,MAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAChD,KAAC,gBAAgB,IAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAI,EAC7C,KAAC,UAAU,IAAC,OAAO,EAAC,OAAO,4BAAyB,IAChD,GACA,GACJ,CACP,EACA,KAAK,CAAC,KAAK,IAAI,CACd,KAAC,UAAU,IAAC,KAAK,EAAC,OAAO,EAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,EAAC,OAAO,YACrD,KAAK,CAAC,KAAK,GACD,CACd,IACG,EACN,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAC5C,MAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAC1B,KAAC,SAAS,IACR,SAAS,QACT,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAChD,SAAS,EAAE,cAAc,EACzB,WAAW,EAAC,uBAAuB,EACnC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EACb,KAAK,EAAE,YAAY,EACnB,OAAO,EAAC,UAAU,GAClB,EACF,KAAC,MAAM,IAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAC,WAAW,qBAE9C,IACL,GACF,IACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAAE,cAAc,EAAE,cAAc,EAAE,EAAE,EAAE;IACpF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,CACL,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAC1F,KAAC,gBAAgB,IAAC,IAAI,EAAE,EAAE,GAAI,GAC1B,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,kBAAkB,IAAC,iBAAiB,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAClI,KAAC,mBAAmB,IAAC,cAAc,EAAE,cAAc,GAAI,GACpC,CACtB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { eventDocAiContext, mergeStreamParts } from 'quidproquo-features';\nimport { useEffectCallback } from 'quidproquo-web-react';\nimport { QpqContextProvider, useQpqWebsocketQueueRuntime } from 'quidproquo-web-react';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Android as AndroidIcon, Person as PersonIcon } from '@mui/icons-material';\nimport { Avatar, Box, Button, CircularProgress, Paper, TextField, Typography } from '@mui/material';\n\nimport { useAdminApp } from '../../adminApp';\nimport { askEventDocAiLogChatBoot } from './logic/askEventDocAiLogChatBoot';\nimport { eventDocAiLogChatRuntime } from './eventDocAiLogChatRuntime';\nimport { EventDocAiSegments } from './EventDocAiSegments';\n\ninterface LogChatProps {\n logServiceName: string;\n logCorrelation: string;\n}\n\nconst LogChatConversation: React.FC<{ logCorrelation: string }> = ({ logCorrelation }) => {\n const [inputMessage, setInputMessage] = useState('');\n const chatContainerRef = useRef<HTMLDivElement>(null);\n\n const [api, state] = useQpqWebsocketQueueRuntime(eventDocAiLogChatRuntime, askEventDocAiLogChatBoot, logCorrelation);\n const [adminApi] = useAdminApp();\n\n const streamSegments = mergeStreamParts(state.streamParts);\n const isThinking = state.isSending && streamSegments.length === 0;\n\n const handleSendMessage = useEffectCallback(() => {\n if (inputMessage.trim() !== '') {\n // Audit trail (session event) and actual chat transport are separate concerns.\n adminApi.sendChatMessage(logCorrelation, inputMessage);\n api.eventDocAiSendMessage(inputMessage);\n setInputMessage('');\n }\n });\n\n const handleKeyPress = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n handleSendMessage();\n }\n };\n\n useEffect(() => {\n if (chatContainerRef.current) {\n chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;\n }\n }, [state.chatMessages, streamSegments]);\n\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>\n <Box ref={chatContainerRef} sx={{ flexGrow: 1, overflowY: 'auto', p: 2 }}>\n {state.isLoadingHistory && (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 2 }}>\n <CircularProgress size={20} />\n </Box>\n )}\n {state.chatMessages.map((message, index) => (\n <Box\n key={index}\n sx={{\n display: 'flex',\n alignItems: 'flex-start',\n mb: 2,\n justifyContent: message.role === 'assistant' ? 'flex-start' : 'flex-end',\n }}\n >\n <Paper\n sx={{\n p: 2,\n borderRadius: message.role === 'assistant' ? '20px 20px 20px 0' : '20px 20px 0 20px',\n backgroundColor: message.role === 'assistant' ? 'grey.300' : 'primary.main',\n color: message.role === 'assistant' ? 'black' : 'white',\n maxWidth: '70%',\n }}\n >\n <Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>\n <Avatar sx={{ mr: 1, bgcolor: message.role === 'assistant' ? 'grey.500' : 'primary.dark' }}>\n {message.role === 'assistant' ? <AndroidIcon /> : <PersonIcon />}\n </Avatar>\n <Typography variant=\"subtitle2\">{message.role === 'assistant' ? 'AI Assistant' : 'You'}</Typography>\n </Box>\n <EventDocAiSegments segments={message.segments} />\n </Paper>\n </Box>\n ))}\n {streamSegments.length > 0 && (\n <Box sx={{ display: 'flex', alignItems: 'flex-start', mb: 2, justifyContent: 'flex-start' }}>\n <Paper sx={{ p: 2, borderRadius: '20px 20px 20px 0', backgroundColor: 'grey.300', color: 'black', maxWidth: '70%' }}>\n <Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>\n <Avatar sx={{ mr: 1, bgcolor: 'grey.500' }}>\n <AndroidIcon />\n </Avatar>\n <Typography variant=\"subtitle2\">AI Assistant</Typography>\n </Box>\n <EventDocAiSegments segments={streamSegments} />\n </Paper>\n </Box>\n )}\n {isThinking && (\n <Box sx={{ display: 'flex', alignItems: 'flex-start', mb: 2, justifyContent: 'flex-start' }}>\n <Paper sx={{ p: 2, borderRadius: '20px 20px 20px 0', backgroundColor: 'grey.300', color: 'black', maxWidth: '70%' }}>\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <CircularProgress size={20} sx={{ mr: 1 }} />\n <Typography variant=\"body1\">Thinking...</Typography>\n </Box>\n </Paper>\n </Box>\n )}\n {state.error && (\n <Typography color=\"error\" sx={{ mt: 1 }} variant=\"body2\">\n {state.error}\n </Typography>\n )}\n </Box>\n <Box sx={{ p: 2, borderTop: '1px solid #ccc' }}>\n <Box sx={{ display: 'flex' }}>\n <TextField\n fullWidth\n onChange={(e) => setInputMessage(e.target.value)}\n onKeyDown={handleKeyPress}\n placeholder=\"Ask about this log...\"\n sx={{ mr: 2 }}\n value={inputMessage}\n variant=\"outlined\"\n />\n <Button onClick={handleSendMessage} variant=\"contained\">\n Send\n </Button>\n </Box>\n </Box>\n </Box>\n );\n};\n\n// The generic EventDocAi chat, scoped to this one log (docId = correlation id).\n// See eventdoc-chat-plan.md — replaces the old one-off Claude chat.\nexport const LogChat: React.FC<LogChatProps> = ({ logServiceName, logCorrelation }) => {\n if (!logServiceName) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>\n <CircularProgress size={20} />\n </Box>\n );\n }\n\n return (\n <QpqContextProvider contextIdentifier={eventDocAiContext} value={{ serviceName: logServiceName, type: 'log', docId: logCorrelation }}>\n <LogChatConversation logCorrelation={logCorrelation} />\n </QpqContextProvider>\n );\n};\n"]}
1
+ {"version":3,"file":"LogChat.js","sourceRoot":"","sources":["../../../../src/LogViewer/LogChat/LogChat.tsx"],"names":[],"mappings":"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","sourcesContent":["import { eventDocAiContext, mergeStreamParts } from 'quidproquo-features';\nimport { useEffectCallback } from 'quidproquo-web-react';\nimport { QpqContextProvider, useQpqWebsocketQueueRuntime } from 'quidproquo-web-react';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Android as AndroidIcon, Person as PersonIcon } from '@mui/icons-material';\nimport { Avatar, Box, Button, CircularProgress, Paper, TextField, Typography } from '@mui/material';\n\nimport { useAdminApp } from '../../adminApp';\nimport { eventDocAiLogChatRuntime } from './eventDocAiLogChatRuntime';\nimport { EventDocAiSegments } from './EventDocAiSegments';\n\ninterface LogChatProps {\n logServiceName: string;\n logCorrelation: string;\n}\n\nconst LogChatConversation: React.FC<{ logCorrelation: string }> = ({ logCorrelation }) => {\n const [inputMessage, setInputMessage] = useState('');\n const chatContainerRef = useRef<HTMLDivElement>(null);\n\n const [api, state] = useQpqWebsocketQueueRuntime(eventDocAiLogChatRuntime, logCorrelation);\n const [adminApi] = useAdminApp();\n\n const streamSegments = mergeStreamParts(state.streamParts);\n const isThinking = state.isSending && streamSegments.length === 0;\n\n const handleSendMessage = useEffectCallback(() => {\n if (inputMessage.trim() !== '') {\n // Audit trail (session event) and actual chat transport are separate concerns.\n adminApi.sendChatMessage(logCorrelation, inputMessage);\n api.eventDocAiSendMessage(inputMessage);\n setInputMessage('');\n }\n });\n\n const handleKeyPress = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n handleSendMessage();\n }\n };\n\n useEffect(() => {\n if (chatContainerRef.current) {\n chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;\n }\n }, [state.chatMessages, streamSegments]);\n\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>\n <Box ref={chatContainerRef} sx={{ flexGrow: 1, overflowY: 'auto', p: 2 }}>\n {state.isLoadingHistory && (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 2 }}>\n <CircularProgress size={20} />\n </Box>\n )}\n {state.chatMessages.map((message, index) => (\n <Box\n key={index}\n sx={{\n display: 'flex',\n alignItems: 'flex-start',\n mb: 2,\n justifyContent: message.role === 'assistant' ? 'flex-start' : 'flex-end',\n }}\n >\n <Paper\n sx={{\n p: 2,\n borderRadius: message.role === 'assistant' ? '20px 20px 20px 0' : '20px 20px 0 20px',\n backgroundColor: message.role === 'assistant' ? 'grey.300' : 'primary.main',\n color: message.role === 'assistant' ? 'black' : 'white',\n maxWidth: '70%',\n }}\n >\n <Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>\n <Avatar sx={{ mr: 1, bgcolor: message.role === 'assistant' ? 'grey.500' : 'primary.dark' }}>\n {message.role === 'assistant' ? <AndroidIcon /> : <PersonIcon />}\n </Avatar>\n <Typography variant=\"subtitle2\">{message.role === 'assistant' ? 'AI Assistant' : 'You'}</Typography>\n </Box>\n <EventDocAiSegments segments={message.segments} />\n </Paper>\n </Box>\n ))}\n {streamSegments.length > 0 && (\n <Box sx={{ display: 'flex', alignItems: 'flex-start', mb: 2, justifyContent: 'flex-start' }}>\n <Paper sx={{ p: 2, borderRadius: '20px 20px 20px 0', backgroundColor: 'grey.300', color: 'black', maxWidth: '70%' }}>\n <Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>\n <Avatar sx={{ mr: 1, bgcolor: 'grey.500' }}>\n <AndroidIcon />\n </Avatar>\n <Typography variant=\"subtitle2\">AI Assistant</Typography>\n </Box>\n <EventDocAiSegments segments={streamSegments} />\n </Paper>\n </Box>\n )}\n {isThinking && (\n <Box sx={{ display: 'flex', alignItems: 'flex-start', mb: 2, justifyContent: 'flex-start' }}>\n <Paper sx={{ p: 2, borderRadius: '20px 20px 20px 0', backgroundColor: 'grey.300', color: 'black', maxWidth: '70%' }}>\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <CircularProgress size={20} sx={{ mr: 1 }} />\n <Typography variant=\"body1\">Thinking...</Typography>\n </Box>\n </Paper>\n </Box>\n )}\n {state.error && (\n <Typography color=\"error\" sx={{ mt: 1 }} variant=\"body2\">\n {state.error}\n </Typography>\n )}\n </Box>\n <Box sx={{ p: 2, borderTop: '1px solid #ccc' }}>\n <Box sx={{ display: 'flex' }}>\n <TextField\n fullWidth\n onChange={(e) => setInputMessage(e.target.value)}\n onKeyDown={handleKeyPress}\n placeholder=\"Ask about this log...\"\n sx={{ mr: 2 }}\n value={inputMessage}\n variant=\"outlined\"\n />\n <Button onClick={handleSendMessage} variant=\"contained\">\n Send\n </Button>\n </Box>\n </Box>\n </Box>\n );\n};\n\n// The generic EventDocAi chat, scoped to this one log (docId = correlation id).\n// See eventdoc-chat-plan.md — replaces the old one-off Claude chat.\nexport const LogChat: React.FC<LogChatProps> = ({ logServiceName, logCorrelation }) => {\n if (!logServiceName) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>\n <CircularProgress size={20} />\n </Box>\n );\n }\n\n return (\n <QpqContextProvider contextIdentifier={eventDocAiContext} value={{ serviceName: logServiceName, type: 'log', docId: logCorrelation }}>\n <LogChatConversation logCorrelation={logCorrelation} />\n </QpqContextProvider>\n );\n};\n"]}
@@ -1,6 +1,14 @@
1
1
  import { createInitialEventDocAiState, eventDocAiReducer, sharedEventDocAiApi } from 'quidproquo-features';
2
2
  import { createQpqRuntimeDefinition } from 'quidproquo-web-react';
3
- // Named per log correlation (see LogChat.tsx) so each open log dialog gets its
4
- // own isolated chat state instead of sharing one across every log.
5
- export const eventDocAiLogChatRuntime = createQpqRuntimeDefinition(sharedEventDocAiApi, createInitialEventDocAiState(), eventDocAiReducer);
3
+ import { askEventDocAiLogChatBoot } from './logic/askEventDocAiLogChatBoot';
4
+ // Bound per log correlation (see LogChat.tsx) so each open log dialog gets its
5
+ // own isolated chat state instead of sharing one across every log. Closing the
6
+ // dialog releases the area; reopening re-runs the boot story.
7
+ export const eventDocAiLogChatRuntime = createQpqRuntimeDefinition({
8
+ uniqueName: 'qpq/admin/eventDocAiLogChat',
9
+ api: sharedEventDocAiApi,
10
+ initialState: createInitialEventDocAiState(),
11
+ reducer: eventDocAiReducer,
12
+ onInit: askEventDocAiLogChatBoot,
13
+ });
6
14
  //# sourceMappingURL=eventDocAiLogChatRuntime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"eventDocAiLogChatRuntime.js","sourceRoot":"","sources":["../../../../src/LogViewer/LogChat/eventDocAiLogChatRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAC,mBAAmB,EAAE,4BAA4B,EAAE,EAAE,iBAAiB,CAAC,CAAC","sourcesContent":["import { createInitialEventDocAiState, eventDocAiReducer, sharedEventDocAiApi } from 'quidproquo-features';\nimport { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\n// Named per log correlation (see LogChat.tsx) so each open log dialog gets its\n// own isolated chat state instead of sharing one across every log.\nexport const eventDocAiLogChatRuntime = createQpqRuntimeDefinition(sharedEventDocAiApi, createInitialEventDocAiState(), eventDocAiReducer);\n"]}
1
+ {"version":3,"file":"eventDocAiLogChatRuntime.js","sourceRoot":"","sources":["../../../../src/LogViewer/LogChat/eventDocAiLogChatRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,+EAA+E;AAC/E,+EAA+E;AAC/E,8DAA8D;AAC9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;IACjE,UAAU,EAAE,6BAA6B;IACzC,GAAG,EAAE,mBAAmB;IACxB,YAAY,EAAE,4BAA4B,EAAE;IAC5C,OAAO,EAAE,iBAAiB;IAC1B,MAAM,EAAE,wBAAwB;CACjC,CAAC,CAAC","sourcesContent":["import { createInitialEventDocAiState, eventDocAiReducer, sharedEventDocAiApi } from 'quidproquo-features';\nimport { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\nimport { askEventDocAiLogChatBoot } from './logic/askEventDocAiLogChatBoot';\n\n// Bound per log correlation (see LogChat.tsx) so each open log dialog gets its\n// own isolated chat state instead of sharing one across every log. Closing the\n// dialog releases the area; reopening re-runs the boot story.\nexport const eventDocAiLogChatRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/eventDocAiLogChat',\n api: sharedEventDocAiApi,\n initialState: createInitialEventDocAiState(),\n reducer: eventDocAiReducer,\n onInit: askEventDocAiLogChatBoot,\n});\n"]}
@@ -1,4 +1,4 @@
1
- import { askDateNow, askNewGuid } from 'quidproquo-core';
1
+ import { askDateNow, askNewGuid, askNewSortableGuid } from 'quidproquo-core';
2
2
  import { askUISessionLogEventAppended } from '../actionCreators/sessionLog/askUISessionLogEventAppended';
3
3
  import { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';
4
4
  import { localSessionEventActor } from '../constants/localSessionEventActor';
@@ -8,6 +8,8 @@ import { localSessionEventActor } from '../constants/localSessionEventActor';
8
8
  // processors with the action's PAYLOAD, so that is what this story receives.
9
9
  export function* askApplySessionEventToLog(payload) {
10
10
  const clientMessageId = yield* askNewGuid();
11
+ // Sortable ids need no allocator, so the id is minted here rather than positioned later.
12
+ const eventId = yield* askNewSortableGuid();
11
13
  const createdAt = yield* askDateNow();
12
14
  const event = {
13
15
  type: payload.type,
@@ -18,7 +20,7 @@ export function* askApplySessionEventToLog(payload) {
18
20
  clientMessageId,
19
21
  createdBy: localSessionEventActor,
20
22
  createdAt,
21
- index: 0,
23
+ eventId,
22
24
  },
23
25
  },
24
26
  };
@@ -1 +1 @@
1
- {"version":3,"file":"askApplySessionEventToLog.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/askApplySessionEventToLog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAC;AAGtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,2DAA2D,CAAC;AACzG,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAG7E,2EAA2E;AAC3E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,MAAM,SAAS,CAAC,CAAC,yBAAyB,CAAC,OAAuC;IAChF,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAkB;QAC3B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE;YACP,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE;gBACR,OAAO,EAAE,yBAAyB;gBAClC,eAAe;gBACf,SAAS,EAAE,sBAAsB;gBACjC,SAAS;gBACT,KAAK,EAAE,CAAC;aACT;SACF;KACF,CAAC;IAEF,KAAK,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { askDateNow, askNewGuid, AskResponse } from 'quidproquo-core';\nimport { EventDocEvent } from 'quidproquo-features';\n\nimport { askUISessionLogEventAppended } from '../actionCreators/sessionLog/askUISessionLogEventAppended';\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\nimport { localSessionEventActor } from '../constants/localSessionEventActor';\nimport { ApplySessionEventActionPayload } from './ApplySessionEventActionTypes';\n\n// The seam between pure yield and the event log: stamps local metadata and\n// appends optimistically (index assignment + coalescing live in the reducer);\n// the flush loop drains it to the backend. NOTE: the runtime invokes action\n// processors with the action's PAYLOAD, so that is what this story receives.\nexport function* askApplySessionEventToLog(payload: ApplySessionEventActionPayload): AskResponse<void> {\n const clientMessageId = yield* askNewGuid();\n const createdAt = yield* askDateNow();\n\n const event: EventDocEvent = {\n type: payload.type,\n payload: {\n data: payload.data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId,\n createdBy: localSessionEventActor,\n createdAt,\n index: 0,\n },\n },\n };\n\n yield* askUISessionLogEventAppended(event);\n}\n"]}
1
+ {"version":3,"file":"askApplySessionEventToLog.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/askApplySessionEventToLog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAe,MAAM,iBAAiB,CAAC;AAG1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,2DAA2D,CAAC;AACzG,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAG7E,2EAA2E;AAC3E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,MAAM,SAAS,CAAC,CAAC,yBAAyB,CAAC,OAAuC;IAChF,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;IAC5C,yFAAyF;IACzF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAkB;QAC3B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE;YACP,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE;gBACR,OAAO,EAAE,yBAAyB;gBAClC,eAAe;gBACf,SAAS,EAAE,sBAAsB;gBACjC,SAAS;gBACT,OAAO;aACR;SACF;KACF,CAAC;IAEF,KAAK,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { askDateNow, askNewGuid, askNewSortableGuid, AskResponse } from 'quidproquo-core';\nimport { EventDocEvent } from 'quidproquo-features';\n\nimport { askUISessionLogEventAppended } from '../actionCreators/sessionLog/askUISessionLogEventAppended';\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\nimport { localSessionEventActor } from '../constants/localSessionEventActor';\nimport { ApplySessionEventActionPayload } from './ApplySessionEventActionTypes';\n\n// The seam between pure yield and the event log: stamps local metadata and\n// appends optimistically (index assignment + coalescing live in the reducer);\n// the flush loop drains it to the backend. NOTE: the runtime invokes action\n// processors with the action's PAYLOAD, so that is what this story receives.\nexport function* askApplySessionEventToLog(payload: ApplySessionEventActionPayload): AskResponse<void> {\n const clientMessageId = yield* askNewGuid();\n // Sortable ids need no allocator, so the id is minted here rather than positioned later.\n const eventId = yield* askNewSortableGuid();\n const createdAt = yield* askDateNow();\n\n const event: EventDocEvent = {\n type: payload.type,\n payload: {\n data: payload.data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId,\n createdBy: localSessionEventActor,\n createdAt,\n eventId,\n },\n },\n };\n\n yield* askUISessionLogEventAppended(event);\n}\n"]}
@@ -1,6 +1,18 @@
1
1
  import { createQpqRuntimeDefinition } from 'quidproquo-web-react';
2
+ import { getApplySessionEventActionProcessor } from './actions/getApplySessionEventActionProcessor';
3
+ import { askAdminAppMain } from './logic/askAdminAppMain';
2
4
  import { adminAppReducer } from './adminAppReducer';
3
5
  import { createInitialAdminAppState } from './AdminAppState';
4
6
  import { sharedAdminAppApi } from './sharedAdminAppApi';
5
- export const adminAppRuntime = createQpqRuntimeDefinition(sharedAdminAppApi, createInitialAdminAppState(), adminAppReducer);
7
+ export const adminAppRuntime = createQpqRuntimeDefinition({
8
+ uniqueName: 'qpq/admin/adminApp',
9
+ api: sharedAdminAppApi,
10
+ initialState: createInitialAdminAppState(),
11
+ reducer: adminAppReducer,
12
+ // Boot story: session start is the first bind of the area (after login).
13
+ onInit: askAdminAppMain,
14
+ // On the definition so every binder (and the boot story, whichever
15
+ // component's bind runs it) gets the ApplyEvent processor.
16
+ getActionProcessors: getApplySessionEventActionProcessor,
17
+ });
6
18
  //# sourceMappingURL=adminAppRuntime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adminAppRuntime.js","sourceRoot":"","sources":["../../../src/adminApp/adminAppRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,0BAA0B,CAAC,iBAAiB,EAAE,0BAA0B,EAAE,EAAE,eAAe,CAAC,CAAC","sourcesContent":["import { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\nimport { adminAppReducer } from './adminAppReducer';\nimport { createInitialAdminAppState } from './AdminAppState';\nimport { sharedAdminAppApi } from './sharedAdminAppApi';\n\nexport const adminAppRuntime = createQpqRuntimeDefinition(sharedAdminAppApi, createInitialAdminAppState(), adminAppReducer);\n"]}
1
+ {"version":3,"file":"adminAppRuntime.js","sourceRoot":"","sources":["../../../src/adminApp/adminAppRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,0BAA0B,CAAC;IACxD,UAAU,EAAE,oBAAoB;IAChC,GAAG,EAAE,iBAAiB;IACtB,YAAY,EAAE,0BAA0B,EAAE;IAC1C,OAAO,EAAE,eAAe;IACxB,yEAAyE;IACzE,MAAM,EAAE,eAAe;IACvB,mEAAmE;IACnE,2DAA2D;IAC3D,mBAAmB,EAAE,mCAAmC;CACzD,CAAC,CAAC","sourcesContent":["import { createQpqRuntimeDefinition } from 'quidproquo-web-react';\n\nimport { getApplySessionEventActionProcessor } from './actions/getApplySessionEventActionProcessor';\nimport { askAdminAppMain } from './logic/askAdminAppMain';\nimport { adminAppReducer } from './adminAppReducer';\nimport { createInitialAdminAppState } from './AdminAppState';\nimport { sharedAdminAppApi } from './sharedAdminAppApi';\n\nexport const adminAppRuntime = createQpqRuntimeDefinition({\n uniqueName: 'qpq/admin/adminApp',\n api: sharedAdminAppApi,\n initialState: createInitialAdminAppState(),\n reducer: adminAppReducer,\n // Boot story: session start is the first bind of the area (after login).\n onInit: askAdminAppMain,\n // On the definition so every binder (and the boot story, whichever\n // component's bind runs it) gets the ApplyEvent processor.\n getActionProcessors: getApplySessionEventActionProcessor,\n});\n"]}
@@ -1,22 +1,17 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { authContext, QpqContextProvider, QpqRuntimeEffectCatcher, useQpqRuntime } from 'quidproquo-web-react';
2
+ import { authContext, QpqContextProvider, QpqRuntimeEffectCatcher } from 'quidproquo-web-react';
3
3
  import { useContext } from 'react';
4
- import { getApplySessionEventActionProcessor } from '../../actions/getApplySessionEventActionProcessor';
5
4
  import { adminAppRuntime } from '../../adminAppRuntime';
6
5
  import { adminUserContext } from '../../contexts/adminUserContext';
7
- import { askAdminAppMain } from '../../logic/askAdminAppMain';
8
- // Mounts only once authenticated (inside Auth), so mounting IS session start:
9
- // the boot story creates the session doc, seeds it from the URL, and runs the
10
- // flush loop for the life of the page.
11
- const AdminAppRuntimeMount = ({ children }) => {
12
- useQpqRuntime(adminAppRuntime, askAdminAppMain, undefined, getApplySessionEventActionProcessor);
13
- return _jsx(QpqRuntimeEffectCatcher, { runtime: adminAppRuntime, children: children });
14
- };
6
+ // Mounts only once authenticated (inside Auth), so the first bind of the
7
+ // adminApp area IS session start: the definition's onInit creates the session
8
+ // doc, seeds it from the URL, and runs the flush loop until logout unmounts
9
+ // the subtree and the area is released.
15
10
  export const AdminAppProvider = ({ children }) => {
16
11
  const authState = useContext(authContext);
17
12
  const adminUser = {
18
13
  username: authState?.username ?? '',
19
14
  };
20
- return (_jsx(QpqContextProvider, { contextIdentifier: adminUserContext, value: adminUser, children: _jsx(AdminAppRuntimeMount, { children: children }) }));
15
+ return (_jsx(QpqContextProvider, { contextIdentifier: adminUserContext, value: adminUser, children: _jsx(QpqRuntimeEffectCatcher, { runtime: adminAppRuntime, children: children }) }));
21
16
  };
22
17
  //# sourceMappingURL=AdminAppProvider.js.map