@open-mercato/ui 0.6.2-develop.3461.1.605f31c2c9 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/ai/AiChat.js +130 -22
- package/dist/ai/AiChat.js.map +2 -2
- package/dist/ai/AiChatSessions.js +73 -3
- package/dist/ai/AiChatSessions.js.map +2 -2
- package/dist/ai/conversation-store.js +149 -0
- package/dist/ai/conversation-store.js.map +7 -0
- package/dist/ai/parts/MutationPreviewCard.js +4 -3
- package/dist/ai/parts/MutationPreviewCard.js.map +2 -2
- package/dist/ai/parts/MutationResultCard.js +9 -16
- package/dist/ai/parts/MutationResultCard.js.map +2 -2
- package/dist/ai/useAiChat.js +80 -4
- package/dist/ai/useAiChat.js.map +2 -2
- package/dist/backend/AuthSessionGuard.js +99 -0
- package/dist/backend/AuthSessionGuard.js.map +7 -0
- package/dist/backend/CrudForm.js +2 -1
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/FilterOverlay.js +1 -1
- package/dist/backend/FilterOverlay.js.map +1 -1
- package/dist/backend/dashboard/widgetRegistry.js +2 -1
- package/dist/backend/dashboard/widgetRegistry.js.map +2 -2
- package/dist/backend/date-range/dateRanges.js +16 -18
- package/dist/backend/date-range/dateRanges.js.map +2 -2
- package/dist/backend/detail/AttachmentMetadataDialog.js +3 -1
- package/dist/backend/detail/AttachmentMetadataDialog.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +1 -1
- package/dist/backend/detail/InlineEditors.js.map +1 -1
- package/dist/backend/injection/useAppEvent.js +2 -7
- package/dist/backend/injection/useAppEvent.js.map +2 -2
- package/dist/backend/injection/widgetRegistry.js +2 -1
- package/dist/backend/injection/widgetRegistry.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +62 -5
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/backend/messages/useMessageComposeOperations.js +64 -5
- package/dist/backend/messages/useMessageComposeOperations.js.map +2 -2
- package/dist/backend/schedule/ScheduleCalendar.js +11 -1
- package/dist/backend/schedule/ScheduleCalendar.js.map +2 -2
- package/dist/backend/schedule/ScheduleToolbar.js +11 -1
- package/dist/backend/schedule/ScheduleToolbar.js.map +2 -2
- package/dist/primitives/calendar.js +1 -1
- package/dist/primitives/calendar.js.map +1 -1
- package/dist/primitives/date-format.js +1 -1
- package/dist/primitives/date-format.js.map +1 -1
- package/dist/primitives/date-picker-helpers.js +7 -9
- package/dist/primitives/date-picker-helpers.js.map +2 -2
- package/dist/primitives/date-picker.js +1 -1
- package/dist/primitives/date-picker.js.map +2 -2
- package/dist/primitives/date-range-picker.js +1 -1
- package/dist/primitives/date-range-picker.js.map +2 -2
- package/jest.config.cjs +4 -1
- package/package.json +6 -7
- package/src/ai/AiChat.tsx +138 -22
- package/src/ai/AiChatSessions.tsx +89 -9
- package/src/ai/__tests__/AiAssistantLauncher.test.tsx +1 -1
- package/src/ai/__tests__/AiChat.conversation.test.tsx +86 -0
- package/src/ai/__tests__/AiChat.test.tsx +17 -2
- package/src/ai/__tests__/conversation-store.test.ts +29 -0
- package/src/ai/conversation-store.ts +246 -0
- package/src/ai/parts/MutationPreviewCard.tsx +25 -20
- package/src/ai/parts/MutationResultCard.tsx +15 -27
- package/src/ai/parts/__tests__/MutationPreviewCard.test.tsx +26 -1
- package/src/ai/parts/__tests__/MutationResultCard.test.tsx +16 -1
- package/src/ai/useAiChat.ts +97 -8
- package/src/backend/AuthSessionGuard.tsx +114 -0
- package/src/backend/CrudForm.tsx +3 -2
- package/src/backend/FilterOverlay.tsx +1 -1
- package/src/backend/__tests__/AppShell.test.tsx +1 -1
- package/src/backend/__tests__/AuthSessionGuard.test.tsx +150 -0
- package/src/backend/__tests__/SidebarCustomizationEditor.test.tsx +8 -1
- package/src/backend/dashboard/widgetRegistry.ts +2 -1
- package/src/backend/date-range/dateRanges.ts +16 -18
- package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
- package/src/backend/detail/InlineEditors.tsx +1 -1
- package/src/backend/injection/__tests__/useAppEvent.test.ts +16 -0
- package/src/backend/injection/useAppEvent.ts +2 -9
- package/src/backend/injection/widgetRegistry.ts +2 -1
- package/src/backend/messages/__tests__/MessageComposer.test.tsx +77 -0
- package/src/backend/messages/useMessageCompose.ts +64 -5
- package/src/backend/messages/useMessageComposeOperations.ts +70 -4
- package/src/backend/schedule/ScheduleCalendar.tsx +11 -1
- package/src/backend/schedule/ScheduleToolbar.tsx +11 -1
- package/src/primitives/calendar.tsx +2 -2
- package/src/primitives/date-format.ts +2 -2
- package/src/primitives/date-picker-helpers.ts +7 -9
- package/src/primitives/date-picker.tsx +2 -2
- package/src/primitives/date-range-picker.tsx +2 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { apiCall } from "./utils/apiCall.js";
|
|
4
|
+
const AUTH_IDENTITY_STORAGE_KEY = "om:auth:identity";
|
|
5
|
+
const AUTH_IDENTITY_BROADCAST_CHANNEL = "om-auth-identity";
|
|
6
|
+
const __reload = {
|
|
7
|
+
fn: () => {
|
|
8
|
+
if (typeof window !== "undefined") window.location.reload();
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
function AuthSessionGuard({ serverUserId }) {
|
|
12
|
+
React.useEffect(() => {
|
|
13
|
+
if (typeof window === "undefined") return;
|
|
14
|
+
let cancelled = false;
|
|
15
|
+
let reloadScheduled = false;
|
|
16
|
+
const triggerReload = () => {
|
|
17
|
+
if (reloadScheduled) return;
|
|
18
|
+
reloadScheduled = true;
|
|
19
|
+
__reload.fn();
|
|
20
|
+
};
|
|
21
|
+
const checkIdentity = async () => {
|
|
22
|
+
if (cancelled || reloadScheduled) return;
|
|
23
|
+
try {
|
|
24
|
+
const res = await apiCall("/api/auth/feature-check", {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: { "content-type": "application/json" },
|
|
27
|
+
body: JSON.stringify({ features: [] }),
|
|
28
|
+
cache: "no-store"
|
|
29
|
+
});
|
|
30
|
+
if (cancelled || reloadScheduled) return;
|
|
31
|
+
if (res.status === 401) {
|
|
32
|
+
if (serverUserId) triggerReload();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!res.ok) return;
|
|
36
|
+
const currentUserId = typeof res.result?.userId === "string" ? res.result.userId : null;
|
|
37
|
+
if (!currentUserId) return;
|
|
38
|
+
if (currentUserId !== serverUserId) triggerReload();
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const onVisibilityOrFocus = () => {
|
|
43
|
+
if (typeof document !== "undefined" && document.visibilityState === "hidden") return;
|
|
44
|
+
void checkIdentity();
|
|
45
|
+
};
|
|
46
|
+
const onStorage = (event) => {
|
|
47
|
+
if (event.key !== AUTH_IDENTITY_STORAGE_KEY) return;
|
|
48
|
+
void checkIdentity();
|
|
49
|
+
};
|
|
50
|
+
let broadcastChannel = null;
|
|
51
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
52
|
+
try {
|
|
53
|
+
broadcastChannel = new BroadcastChannel(AUTH_IDENTITY_BROADCAST_CHANNEL);
|
|
54
|
+
broadcastChannel.onmessage = () => {
|
|
55
|
+
void checkIdentity();
|
|
56
|
+
};
|
|
57
|
+
} catch {
|
|
58
|
+
broadcastChannel = null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
window.addEventListener("focus", onVisibilityOrFocus);
|
|
62
|
+
document.addEventListener("visibilitychange", onVisibilityOrFocus);
|
|
63
|
+
window.addEventListener("storage", onStorage);
|
|
64
|
+
return () => {
|
|
65
|
+
cancelled = true;
|
|
66
|
+
window.removeEventListener("focus", onVisibilityOrFocus);
|
|
67
|
+
document.removeEventListener("visibilitychange", onVisibilityOrFocus);
|
|
68
|
+
window.removeEventListener("storage", onStorage);
|
|
69
|
+
if (broadcastChannel) {
|
|
70
|
+
broadcastChannel.onmessage = null;
|
|
71
|
+
broadcastChannel.close();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}, [serverUserId]);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
function notifyAuthIdentityChange() {
|
|
78
|
+
if (typeof window === "undefined") return;
|
|
79
|
+
try {
|
|
80
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
81
|
+
const channel = new BroadcastChannel(AUTH_IDENTITY_BROADCAST_CHANNEL);
|
|
82
|
+
channel.postMessage("changed");
|
|
83
|
+
channel.close();
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
window.localStorage.setItem(AUTH_IDENTITY_STORAGE_KEY, String(Date.now()));
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
AUTH_IDENTITY_BROADCAST_CHANNEL,
|
|
94
|
+
AUTH_IDENTITY_STORAGE_KEY,
|
|
95
|
+
AuthSessionGuard,
|
|
96
|
+
__reload,
|
|
97
|
+
notifyAuthIdentityChange
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=AuthSessionGuard.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/backend/AuthSessionGuard.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\nimport * as React from 'react'\nimport { apiCall } from './utils/apiCall'\n\nexport const AUTH_IDENTITY_STORAGE_KEY = 'om:auth:identity'\nexport const AUTH_IDENTITY_BROADCAST_CHANNEL = 'om-auth-identity'\n\ntype FeatureCheckResponse = {\n ok: boolean\n granted?: string[]\n userId?: string\n}\n\nexport type AuthSessionGuardProps = {\n serverUserId: string | null\n}\n\nexport const __reload = {\n fn: (): void => {\n if (typeof window !== 'undefined') window.location.reload()\n },\n}\n\nexport function AuthSessionGuard({ serverUserId }: AuthSessionGuardProps) {\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n let cancelled = false\n let reloadScheduled = false\n\n const triggerReload = () => {\n if (reloadScheduled) return\n reloadScheduled = true\n __reload.fn()\n }\n\n const checkIdentity = async () => {\n if (cancelled || reloadScheduled) return\n try {\n const res = await apiCall<FeatureCheckResponse>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: [] }),\n cache: 'no-store',\n })\n if (cancelled || reloadScheduled) return\n if (res.status === 401) {\n if (serverUserId) triggerReload()\n return\n }\n if (!res.ok) return\n const currentUserId = typeof res.result?.userId === 'string' ? res.result.userId : null\n if (!currentUserId) return\n if (currentUserId !== serverUserId) triggerReload()\n } catch {\n // network errors are ignored \u2014 next focus/storage event retries\n }\n }\n\n const onVisibilityOrFocus = () => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return\n void checkIdentity()\n }\n\n const onStorage = (event: StorageEvent) => {\n if (event.key !== AUTH_IDENTITY_STORAGE_KEY) return\n void checkIdentity()\n }\n\n let broadcastChannel: BroadcastChannel | null = null\n if (typeof BroadcastChannel !== 'undefined') {\n try {\n broadcastChannel = new BroadcastChannel(AUTH_IDENTITY_BROADCAST_CHANNEL)\n broadcastChannel.onmessage = () => { void checkIdentity() }\n } catch {\n broadcastChannel = null\n }\n }\n\n window.addEventListener('focus', onVisibilityOrFocus)\n document.addEventListener('visibilitychange', onVisibilityOrFocus)\n window.addEventListener('storage', onStorage)\n\n return () => {\n cancelled = true\n window.removeEventListener('focus', onVisibilityOrFocus)\n document.removeEventListener('visibilitychange', onVisibilityOrFocus)\n window.removeEventListener('storage', onStorage)\n if (broadcastChannel) {\n broadcastChannel.onmessage = null\n broadcastChannel.close()\n }\n }\n }, [serverUserId])\n\n return null\n}\n\nexport function notifyAuthIdentityChange(): void {\n if (typeof window === 'undefined') return\n try {\n if (typeof BroadcastChannel !== 'undefined') {\n const channel = new BroadcastChannel(AUTH_IDENTITY_BROADCAST_CHANNEL)\n channel.postMessage('changed')\n channel.close()\n }\n } catch {\n // ignore \u2014 fall back to storage event below\n }\n try {\n window.localStorage.setItem(AUTH_IDENTITY_STORAGE_KEY, String(Date.now()))\n } catch {\n // private mode / quota errors are non-fatal\n }\n}\n"],
|
|
5
|
+
"mappings": ";AACA,YAAY,WAAW;AACvB,SAAS,eAAe;AAEjB,MAAM,4BAA4B;AAClC,MAAM,kCAAkC;AAYxC,MAAM,WAAW;AAAA,EACtB,IAAI,MAAY;AACd,QAAI,OAAO,WAAW,YAAa,QAAO,SAAS,OAAO;AAAA,EAC5D;AACF;AAEO,SAAS,iBAAiB,EAAE,aAAa,GAA0B;AACxE,QAAM,UAAU,MAAM;AACpB,QAAI,OAAO,WAAW,YAAa;AACnC,QAAI,YAAY;AAChB,QAAI,kBAAkB;AAEtB,UAAM,gBAAgB,MAAM;AAC1B,UAAI,gBAAiB;AACrB,wBAAkB;AAClB,eAAS,GAAG;AAAA,IACd;AAEA,UAAM,gBAAgB,YAAY;AAChC,UAAI,aAAa,gBAAiB;AAClC,UAAI;AACF,cAAM,MAAM,MAAM,QAA8B,2BAA2B;AAAA,UACzE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;AAAA,UACrC,OAAO;AAAA,QACT,CAAC;AACD,YAAI,aAAa,gBAAiB;AAClC,YAAI,IAAI,WAAW,KAAK;AACtB,cAAI,aAAc,eAAc;AAChC;AAAA,QACF;AACA,YAAI,CAAC,IAAI,GAAI;AACb,cAAM,gBAAgB,OAAO,IAAI,QAAQ,WAAW,WAAW,IAAI,OAAO,SAAS;AACnF,YAAI,CAAC,cAAe;AACpB,YAAI,kBAAkB,aAAc,eAAc;AAAA,MACpD,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,sBAAsB,MAAM;AAChC,UAAI,OAAO,aAAa,eAAe,SAAS,oBAAoB,SAAU;AAC9E,WAAK,cAAc;AAAA,IACrB;AAEA,UAAM,YAAY,CAAC,UAAwB;AACzC,UAAI,MAAM,QAAQ,0BAA2B;AAC7C,WAAK,cAAc;AAAA,IACrB;AAEA,QAAI,mBAA4C;AAChD,QAAI,OAAO,qBAAqB,aAAa;AAC3C,UAAI;AACF,2BAAmB,IAAI,iBAAiB,+BAA+B;AACvE,yBAAiB,YAAY,MAAM;AAAE,eAAK,cAAc;AAAA,QAAE;AAAA,MAC5D,QAAQ;AACN,2BAAmB;AAAA,MACrB;AAAA,IACF;AAEA,WAAO,iBAAiB,SAAS,mBAAmB;AACpD,aAAS,iBAAiB,oBAAoB,mBAAmB;AACjE,WAAO,iBAAiB,WAAW,SAAS;AAE5C,WAAO,MAAM;AACX,kBAAY;AACZ,aAAO,oBAAoB,SAAS,mBAAmB;AACvD,eAAS,oBAAoB,oBAAoB,mBAAmB;AACpE,aAAO,oBAAoB,WAAW,SAAS;AAC/C,UAAI,kBAAkB;AACpB,yBAAiB,YAAY;AAC7B,yBAAiB,MAAM;AAAA,MACzB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,SAAO;AACT;AAEO,SAAS,2BAAiC;AAC/C,MAAI,OAAO,WAAW,YAAa;AACnC,MAAI;AACF,QAAI,OAAO,qBAAqB,aAAa;AAC3C,YAAM,UAAU,IAAI,iBAAiB,+BAA+B;AACpE,cAAQ,YAAY,SAAS;AAC7B,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI;AACF,WAAO,aAAa,QAAQ,2BAA2B,OAAO,KAAK,IAAI,CAAC,CAAC;AAAA,EAC3E,QAAQ;AAAA,EAER;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/backend/CrudForm.js
CHANGED
|
@@ -73,7 +73,8 @@ import { buildFormFieldFromCustomFieldDef } from "./utils/customFieldForms.js";
|
|
|
73
73
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
74
74
|
import { TagsInput } from "./inputs/TagsInput.js";
|
|
75
75
|
import { ComboboxInput } from "./inputs/ComboboxInput.js";
|
|
76
|
-
import { format
|
|
76
|
+
import { format } from "date-fns/format";
|
|
77
|
+
import { parseISO } from "date-fns/parseISO";
|
|
77
78
|
import { DateTimePicker } from "./inputs/DateTimePicker.js";
|
|
78
79
|
import { TimePicker } from "./inputs/TimePicker.js";
|
|
79
80
|
import { DatePicker } from "./inputs/DatePicker.js";
|