@memori.ai/memori-react 9.0.0-alpha.5 → 9.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/dist/components/AgeVerificationModal/AgeVerificationModal.js +8 -3
- package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
- package/dist/components/Auth/Auth.js +3 -1
- package/dist/components/Auth/Auth.js.map +1 -1
- package/dist/components/Avatar/Avatar.js +5 -10
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +8 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +14 -5
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/dist/components/Chat/Chat.js +3 -1
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.js +21 -15
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ChatHistoryDrawer/ChatHistory.js +3 -1
- package/dist/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/dist/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
- package/dist/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
- package/dist/components/DateSelector/DateSelector.d.ts +2 -1
- package/dist/components/DateSelector/DateSelector.js +17 -7
- package/dist/components/DateSelector/DateSelector.js.map +1 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/dist/components/FilePreview/FilePreview.js +22 -5
- package/dist/components/FilePreview/FilePreview.js.map +1 -1
- package/dist/components/KnownFacts/KnownFacts.js +5 -3
- package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
- package/dist/components/LoginDrawer/LoginDrawer.js +3 -1
- package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.js +14 -12
- package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
- package/dist/components/MediaWidget/MediaItemWidget.utils.js +28 -6
- package/dist/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
- package/dist/components/MediaWidget/MediaPreviewModal.js +6 -7
- package/dist/components/MediaWidget/MediaPreviewModal.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
- package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +4 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.css +4 -2
- package/dist/components/MemoriWidget/MemoriWidget.js +760 -404
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/SettingsDrawer/SettingsDrawer.js +3 -1
- package/dist/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +3 -1
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.js +21 -5
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +126 -60
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/dist/components/UploadButton/UploadImages/UploadImages.js +3 -1
- package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +3 -1
- package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
- package/dist/components/layouts/WebsiteAssistant/website-assistant.css +21 -1
- package/dist/components/layouts/chat.css +2 -1
- package/dist/components/layouts/fullpage.css +31 -8
- package/dist/components/layouts/hidden-chat.css +1 -0
- package/dist/components/layouts/totem.css +2 -1
- package/dist/components/layouts/zoomed-full-body.css +32 -7
- package/dist/context/widgetSurfaceContext.d.ts +3 -0
- package/dist/context/widgetSurfaceContext.js +11 -0
- package/dist/context/widgetSurfaceContext.js.map +1 -0
- package/dist/helpers/constants.d.ts +3 -0
- package/dist/helpers/constants.js +27 -1
- package/dist/helpers/constants.js.map +1 -1
- package/dist/helpers/credits.d.ts +5 -2
- package/dist/helpers/credits.js +5 -1
- package/dist/helpers/credits.js.map +1 -1
- package/dist/helpers/message.d.ts +1 -1
- package/dist/helpers/message.js +4 -4
- package/dist/helpers/message.js.map +1 -1
- package/dist/helpers/nats/getNatsConfig.d.ts +9 -0
- package/dist/helpers/nats/getNatsConfig.js +65 -0
- package/dist/helpers/nats/getNatsConfig.js.map +1 -0
- package/dist/helpers/nats/isSessionExpiredError.d.ts +3 -0
- package/dist/helpers/nats/isSessionExpiredError.js +36 -0
- package/dist/helpers/nats/isSessionExpiredError.js.map +1 -0
- package/dist/helpers/nats/useNats.d.ts +12 -0
- package/dist/helpers/nats/useNats.js +75 -0
- package/dist/helpers/nats/useNats.js.map +1 -0
- package/dist/helpers/nats/useNatsSession.d.ts +28 -0
- package/dist/helpers/nats/useNatsSession.js +212 -0
- package/dist/helpers/nats/useNatsSession.js.map +1 -0
- package/dist/helpers/utils.d.ts +21 -0
- package/dist/helpers/utils.js +75 -4
- package/dist/helpers/utils.js.map +1 -1
- package/dist/locales/de.json +1 -0
- package/dist/locales/en.json +1 -0
- package/dist/locales/es.json +1 -0
- package/dist/locales/fr.json +1 -0
- package/dist/locales/it.json +1 -0
- package/dist/styles.css +1 -1
- package/dist/types/integration.d.ts +3 -0
- package/dist/types/integration.js +16 -0
- package/dist/types/integration.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/AgeVerificationModal/AgeVerificationModal.js +8 -3
- package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
- package/esm/components/Auth/Auth.js +3 -1
- package/esm/components/Auth/Auth.js.map +1 -1
- package/esm/components/Avatar/Avatar.js +5 -10
- package/esm/components/Avatar/Avatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +9 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +2 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +13 -4
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/esm/components/Chat/Chat.js +3 -1
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.js +21 -15
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ChatHistoryDrawer/ChatHistory.js +3 -1
- package/esm/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/esm/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
- package/esm/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
- package/esm/components/DateSelector/DateSelector.d.ts +2 -1
- package/esm/components/DateSelector/DateSelector.js +17 -7
- package/esm/components/DateSelector/DateSelector.js.map +1 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/esm/components/FilePreview/FilePreview.js +24 -7
- package/esm/components/FilePreview/FilePreview.js.map +1 -1
- package/esm/components/KnownFacts/KnownFacts.js +5 -3
- package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
- package/esm/components/LoginDrawer/LoginDrawer.js +3 -1
- package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.js +16 -14
- package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
- package/esm/components/MediaWidget/MediaItemWidget.utils.js +27 -6
- package/esm/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
- package/esm/components/MediaWidget/MediaPreviewModal.js +6 -7
- package/esm/components/MediaWidget/MediaPreviewModal.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
- package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +4 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.css +4 -2
- package/esm/components/MemoriWidget/MemoriWidget.js +760 -404
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/SettingsDrawer/SettingsDrawer.js +3 -1
- package/esm/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +3 -1
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.js +21 -5
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +126 -60
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/esm/components/UploadButton/UploadImages/UploadImages.js +3 -1
- package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +3 -1
- package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
- package/esm/components/layouts/WebsiteAssistant/website-assistant.css +21 -1
- package/esm/components/layouts/chat.css +2 -1
- package/esm/components/layouts/fullpage.css +31 -8
- package/esm/components/layouts/hidden-chat.css +1 -0
- package/esm/components/layouts/totem.css +2 -1
- package/esm/components/layouts/zoomed-full-body.css +32 -7
- package/esm/context/widgetSurfaceContext.d.ts +3 -0
- package/esm/context/widgetSurfaceContext.js +7 -0
- package/esm/context/widgetSurfaceContext.js.map +1 -0
- package/esm/helpers/constants.d.ts +3 -0
- package/esm/helpers/constants.js +26 -0
- package/esm/helpers/constants.js.map +1 -1
- package/esm/helpers/credits.d.ts +5 -2
- package/esm/helpers/credits.js +5 -1
- package/esm/helpers/credits.js.map +1 -1
- package/esm/helpers/message.d.ts +1 -1
- package/esm/helpers/message.js +2 -2
- package/esm/helpers/message.js.map +1 -1
- package/esm/helpers/nats/getNatsConfig.d.ts +9 -0
- package/esm/helpers/nats/getNatsConfig.js +61 -0
- package/esm/helpers/nats/getNatsConfig.js.map +1 -0
- package/esm/helpers/nats/isSessionExpiredError.d.ts +3 -0
- package/esm/helpers/nats/isSessionExpiredError.js +32 -0
- package/esm/helpers/nats/isSessionExpiredError.js.map +1 -0
- package/esm/helpers/nats/useNats.d.ts +12 -0
- package/esm/helpers/nats/useNats.js +72 -0
- package/esm/helpers/nats/useNats.js.map +1 -0
- package/esm/helpers/nats/useNatsSession.d.ts +28 -0
- package/esm/helpers/nats/useNatsSession.js +208 -0
- package/esm/helpers/nats/useNatsSession.js.map +1 -0
- package/esm/helpers/utils.d.ts +21 -0
- package/esm/helpers/utils.js +68 -3
- package/esm/helpers/utils.js.map +1 -1
- package/esm/locales/de.json +1 -0
- package/esm/locales/en.json +1 -0
- package/esm/locales/es.json +1 -0
- package/esm/locales/fr.json +1 -0
- package/esm/locales/it.json +1 -0
- package/esm/styles.css +1 -1
- package/esm/types/integration.d.ts +3 -0
- package/esm/types/integration.js +11 -0
- package/esm/types/integration.js.map +1 -0
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +5 -3
- package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +9 -1
- package/src/components/Auth/Auth.tsx +3 -0
- package/src/components/Avatar/Avatar.stories.tsx +45 -28
- package/src/components/Avatar/Avatar.test.tsx +54 -0
- package/src/components/Avatar/Avatar.tsx +8 -12
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +12 -5
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +2 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +16 -4
- package/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +164 -0
- package/src/components/Chat/Chat.tsx +3 -0
- package/src/components/ChatBubble/ChatBubble.tsx +40 -12
- package/src/components/ChatHistoryDrawer/ChatHistory.tsx +3 -0
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +8 -4
- package/src/components/ContentPreviewModal/ContentPreviewModal.tsx +3 -0
- package/src/components/DateSelector/DateSelector.stories.tsx +11 -2
- package/src/components/DateSelector/DateSelector.tsx +28 -9
- package/src/components/ExpertsDrawer/ExpertsDrawer.tsx +3 -0
- package/src/components/FilePreview/FilePreview.tsx +28 -7
- package/src/components/KnownFacts/KnownFacts.tsx +5 -0
- package/src/components/LoginDrawer/LoginDrawer.tsx +3 -0
- package/src/components/MediaWidget/MediaItemWidget.tsx +26 -13
- package/src/components/MediaWidget/MediaItemWidget.utils.test.ts +45 -2
- package/src/components/MediaWidget/MediaItemWidget.utils.ts +39 -6
- package/src/components/MediaWidget/MediaPreviewModal.tsx +9 -7
- package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
- package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +4 -0
- package/src/components/MemoriWidget/MemoriWidget.css +4 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +818 -349
- package/src/components/SettingsDrawer/SettingsDrawer.tsx +3 -0
- package/src/components/StartPanel/StartPanel.stories.tsx +22 -0
- package/src/components/StartPanel/StartPanel.test.tsx +64 -1
- package/src/components/StartPanel/StartPanel.tsx +3 -0
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +261 -0
- package/src/components/UploadButton/UploadButton.tsx +30 -11
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +151 -61
- package/src/components/UploadButton/UploadImages/UploadImages.tsx +3 -0
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +2 -2
- package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +3 -0
- package/src/components/layouts/WebsiteAssistant/WebsiteAssistant.tsx +4 -0
- package/src/components/layouts/WebsiteAssistant/__snapshots__/WebsiteAssistant.test.tsx.snap +48 -44
- package/src/components/layouts/WebsiteAssistant/website-assistant.css +21 -1
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +533 -529
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +1058 -1050
- package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +443 -439
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +584 -580
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +528 -524
- package/src/components/layouts/chat.css +2 -1
- package/src/components/layouts/fullpage.css +31 -8
- package/src/components/layouts/hidden-chat.css +1 -0
- package/src/components/layouts/layouts.stories.tsx +131 -12
- package/src/components/layouts/totem.css +2 -1
- package/src/components/layouts/zoomed-full-body.css +32 -7
- package/src/context/widgetSurfaceContext.tsx +14 -0
- package/src/helpers/constants.ts +32 -1
- package/src/helpers/credits.ts +16 -1
- package/src/helpers/message.test.ts +28 -1
- package/src/helpers/message.ts +4 -4
- package/src/helpers/nats/getNatsConfig.ts +145 -0
- package/src/helpers/nats/isSessionExpiredError.test.ts +38 -0
- package/src/helpers/nats/isSessionExpiredError.ts +51 -0
- package/src/helpers/nats/useNats.ts +124 -0
- package/src/helpers/nats/useNatsSession.ts +394 -0
- package/src/helpers/utils.test.ts +162 -0
- package/src/helpers/utils.ts +108 -3
- package/src/index.stories.tsx +32 -0
- package/src/locales/de.json +1 -0
- package/src/locales/en.json +1 -0
- package/src/locales/es.json +1 -0
- package/src/locales/fr.json +1 -0
- package/src/locales/it.json +1 -0
- package/src/styles.css +61 -1
- package/src/types/integration.test.ts +32 -0
- package/src/types/integration.ts +31 -0
- package/src/version.ts +1 -1
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
import { Expandable, Modal } from '@memori.ai/ui';
|
|
37
37
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
38
38
|
import { usePressTooltip } from '../../helpers/usePressTooltip';
|
|
39
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
39
40
|
const ASSET_URL_PATTERN = /https?:\/\/\S*\/api\/v\d+\/asset\/\S+/gi;
|
|
40
41
|
|
|
41
42
|
const sanitizeRawCopyText = (text: string) =>
|
|
@@ -122,6 +123,7 @@ const ChatBubble: React.FC<Props> = ({
|
|
|
122
123
|
customMediaRenderer,
|
|
123
124
|
}) => {
|
|
124
125
|
const { t, i18n } = useTranslation();
|
|
126
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
125
127
|
const lang = i18n.language || 'en';
|
|
126
128
|
const generatedByAiTooltip = usePressTooltip();
|
|
127
129
|
const [showingWhyThisAnswer, setShowingWhyThisAnswer] = useState(false);
|
|
@@ -129,13 +131,16 @@ const ChatBubble: React.FC<Props> = ({
|
|
|
129
131
|
const [copyStatus, setCopyStatus] = useState<{
|
|
130
132
|
plain: 'idle' | 'success' | 'error';
|
|
131
133
|
raw: 'idle' | 'success' | 'error';
|
|
132
|
-
|
|
134
|
+
functionCache: 'idle' | 'success' | 'error';
|
|
135
|
+
}>({ plain: 'idle', raw: 'idle', functionCache: 'idle' });
|
|
133
136
|
const copyResetTimers = useRef<{
|
|
134
137
|
plain: ReturnType<typeof setTimeout> | null;
|
|
135
138
|
raw: ReturnType<typeof setTimeout> | null;
|
|
139
|
+
functionCache: ReturnType<typeof setTimeout> | null;
|
|
136
140
|
}>({
|
|
137
141
|
plain: null,
|
|
138
142
|
raw: null,
|
|
143
|
+
functionCache: null,
|
|
139
144
|
});
|
|
140
145
|
// Initialize MathJax on component mount
|
|
141
146
|
useEffect(() => {
|
|
@@ -244,26 +249,33 @@ const ChatBubble: React.FC<Props> = ({
|
|
|
244
249
|
|
|
245
250
|
useEffect(() => {
|
|
246
251
|
return () => {
|
|
247
|
-
(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
(
|
|
253
|
+
Object.keys(copyResetTimers.current) as Array<
|
|
254
|
+
'plain' | 'raw' | 'functionCache'
|
|
255
|
+
>
|
|
256
|
+
).forEach(key => {
|
|
257
|
+
const timer = copyResetTimers.current[key];
|
|
258
|
+
if (timer) {
|
|
259
|
+
clearTimeout(timer);
|
|
260
|
+
copyResetTimers.current[key] = null;
|
|
254
261
|
}
|
|
255
|
-
);
|
|
262
|
+
});
|
|
256
263
|
};
|
|
257
264
|
}, []);
|
|
258
265
|
|
|
259
|
-
const
|
|
266
|
+
const functionCacheCopyText =
|
|
267
|
+
functionCacheData
|
|
268
|
+
?.map(f => `${f.title}\n\n${f.content}`)
|
|
269
|
+
.join('\n\n---\n\n') ?? '';
|
|
270
|
+
|
|
271
|
+
const clearCopyReset = (type: 'plain' | 'raw' | 'functionCache') => {
|
|
260
272
|
if (copyResetTimers.current[type]) {
|
|
261
273
|
clearTimeout(copyResetTimers.current[type]!);
|
|
262
274
|
copyResetTimers.current[type] = null;
|
|
263
275
|
}
|
|
264
276
|
};
|
|
265
277
|
|
|
266
|
-
const scheduleCopyReset = (type: 'plain' | 'raw') => {
|
|
278
|
+
const scheduleCopyReset = (type: 'plain' | 'raw' | 'functionCache') => {
|
|
267
279
|
clearCopyReset(type);
|
|
268
280
|
copyResetTimers.current[type] = setTimeout(() => {
|
|
269
281
|
setCopyStatus(prev => ({ ...prev, [type]: 'idle' }));
|
|
@@ -271,7 +283,10 @@ const ChatBubble: React.FC<Props> = ({
|
|
|
271
283
|
}, COPY_FEEDBACK_MS);
|
|
272
284
|
};
|
|
273
285
|
|
|
274
|
-
const handleCopyClick = async (
|
|
286
|
+
const handleCopyClick = async (
|
|
287
|
+
type: 'plain' | 'raw' | 'functionCache',
|
|
288
|
+
text: string
|
|
289
|
+
) => {
|
|
275
290
|
if (!text?.length) return;
|
|
276
291
|
try {
|
|
277
292
|
if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
|
|
@@ -821,12 +836,25 @@ const ChatBubble: React.FC<Props> = ({
|
|
|
821
836
|
)}
|
|
822
837
|
|
|
823
838
|
<Modal
|
|
839
|
+
container={surfaceEl ?? undefined}
|
|
824
840
|
open={openFunctionCache}
|
|
825
841
|
className="memori-chat--function-cache-modal"
|
|
826
842
|
title={t('functionCache') || 'Function Cache'}
|
|
827
843
|
closable={true}
|
|
828
844
|
onOpenChange={setOpenFunctionCache}
|
|
829
845
|
>
|
|
846
|
+
<div style={{ marginBottom: '1rem' }}>
|
|
847
|
+
<Button
|
|
848
|
+
icon={<Copy aria-hidden />}
|
|
849
|
+
onClick={() =>
|
|
850
|
+
handleCopyClick('functionCache', functionCacheCopyText)
|
|
851
|
+
}
|
|
852
|
+
>
|
|
853
|
+
{copyStatus.functionCache === 'success'
|
|
854
|
+
? copiedLabel
|
|
855
|
+
: t('copy') || 'Copy'}
|
|
856
|
+
</Button>
|
|
857
|
+
</div>
|
|
830
858
|
{functionCacheData?.map((f, i) => (
|
|
831
859
|
<div
|
|
832
860
|
key={f.mediumID}
|
|
@@ -21,6 +21,7 @@ import { stripAllInternalTags } from '../../helpers/message';
|
|
|
21
21
|
import debounce from 'lodash/debounce';
|
|
22
22
|
import { Spin } from '@memori.ai/ui';
|
|
23
23
|
import { SelectBox } from '@memori.ai/ui';
|
|
24
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
24
25
|
// Helpers / Utils
|
|
25
26
|
import { getTranslation } from '../../helpers/translations';
|
|
26
27
|
import ChatResumeDrawer from './ChatResumeDrawer';
|
|
@@ -440,6 +441,7 @@ const ChatHistoryDrawer = ({
|
|
|
440
441
|
userLang,
|
|
441
442
|
isMultilanguageEnabled = false,
|
|
442
443
|
}: Props) => {
|
|
444
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
443
445
|
const { t } = useTranslation();
|
|
444
446
|
const { add } = useAlertManager();
|
|
445
447
|
const { getUserChatLogsByTokenPaged } = apiClient.chatLogs;
|
|
@@ -1136,6 +1138,7 @@ const ChatHistoryDrawer = ({
|
|
|
1136
1138
|
|
|
1137
1139
|
return (
|
|
1138
1140
|
<Drawer
|
|
1141
|
+
container={surfaceEl ?? undefined}
|
|
1139
1142
|
className="memori-chat-history-drawer"
|
|
1140
1143
|
open={open}
|
|
1141
1144
|
onClose={onClose}
|
|
@@ -33,17 +33,21 @@ const PROVIDER_CONFIGS: Record<string, ProviderConfig> = {
|
|
|
33
33
|
statusPage: 'https://status.mistral-data.com/',
|
|
34
34
|
apiComponentName: ['Mistral'],
|
|
35
35
|
},
|
|
36
|
+
// Use status.claude.com directly: status.anthropic.com 302-redirects and
|
|
37
|
+
// browsers block the redirected response (missing CORS on the redirect).
|
|
36
38
|
Anthropic: {
|
|
37
|
-
statusUrl: 'https://status.
|
|
38
|
-
statusPage: 'https://status.
|
|
39
|
-
apiComponentName: [
|
|
39
|
+
statusUrl: 'https://status.claude.com/api/v2/summary.json',
|
|
40
|
+
statusPage: 'https://status.claude.com/',
|
|
41
|
+
apiComponentName: [
|
|
42
|
+
'Claude API (api.anthropic.com)',
|
|
43
|
+
'api.anthropic.com',
|
|
44
|
+
],
|
|
40
45
|
},
|
|
41
46
|
};
|
|
42
47
|
|
|
43
48
|
// Modified to handle fetch errors, different component names, and check incidents
|
|
44
49
|
const fetchProviderStatus = async (config: ProviderConfig): Promise<Status> => {
|
|
45
50
|
try {
|
|
46
|
-
// Use cross-fetch instead of native fetch
|
|
47
51
|
const response = await fetch(config.statusUrl);
|
|
48
52
|
if (!response.ok) {
|
|
49
53
|
console.warn(`Status API returned ${response.status}`);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { FC } from 'react';
|
|
2
2
|
import { Modal } from '@memori.ai/ui';
|
|
3
3
|
import cx from 'classnames';
|
|
4
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
4
5
|
|
|
5
6
|
export interface ContentPreviewModalProps {
|
|
6
7
|
open: boolean;
|
|
@@ -25,10 +26,12 @@ const ContentPreviewModal: FC<ContentPreviewModalProps> = ({
|
|
|
25
26
|
children,
|
|
26
27
|
className,
|
|
27
28
|
}) => {
|
|
29
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
28
30
|
const width = 'min(90vw, 800px)';
|
|
29
31
|
|
|
30
32
|
return (
|
|
31
33
|
<Modal
|
|
34
|
+
container={surfaceEl ?? undefined}
|
|
32
35
|
open={open}
|
|
33
36
|
onClose={() => onClose()}
|
|
34
37
|
width={width}
|
|
@@ -25,14 +25,23 @@ const Template: Story<Props> = args => (
|
|
|
25
25
|
// https://storybook.js.org/docs/react/workflows/unit-testing
|
|
26
26
|
export const Default = Template.bind({});
|
|
27
27
|
Default.args = {
|
|
28
|
-
defaultDate:
|
|
28
|
+
defaultDate: '1990-06-15',
|
|
29
|
+
minAge: 18,
|
|
30
|
+
onChange: console.log,
|
|
31
|
+
disabled: false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const MinAge14 = Template.bind({});
|
|
35
|
+
MinAge14.args = {
|
|
36
|
+
minAge: 14,
|
|
29
37
|
onChange: console.log,
|
|
30
38
|
disabled: false,
|
|
31
39
|
};
|
|
32
40
|
|
|
33
41
|
export const Disabled = Template.bind({});
|
|
34
42
|
Disabled.args = {
|
|
35
|
-
defaultDate:
|
|
43
|
+
defaultDate: '1990-06-15',
|
|
44
|
+
minAge: 18,
|
|
36
45
|
onChange: () => {},
|
|
37
46
|
disabled: true,
|
|
38
47
|
};
|
|
@@ -5,16 +5,23 @@ import { useTranslation } from 'react-i18next';
|
|
|
5
5
|
export interface Props {
|
|
6
6
|
defaultDate?: string | Date;
|
|
7
7
|
disabled?: boolean;
|
|
8
|
+
/** Minimum age; latest selectable birth date is today minus this many years. */
|
|
9
|
+
minAge?: number;
|
|
8
10
|
onChange: (date: DateTime | undefined) => void;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
const DateSelector = memo(
|
|
12
|
-
({ defaultDate, onChange, disabled = false }: Props) => {
|
|
14
|
+
({ defaultDate, onChange, disabled = false, minAge = 18 }: Props) => {
|
|
13
15
|
const { t } = useTranslation();
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
const maxDate = useMemo(
|
|
18
|
+
() => DateTime.now().minus({ years: minAge }).startOf('day'),
|
|
19
|
+
[minAge]
|
|
20
|
+
);
|
|
21
|
+
const minDate = useMemo(
|
|
22
|
+
() => DateTime.fromObject({ year: 1900, month: 1, day: 1 }),
|
|
23
|
+
[]
|
|
24
|
+
);
|
|
18
25
|
|
|
19
26
|
// State for individual fields as strings to allow empty values
|
|
20
27
|
const [day, setDay] = useState<string>('');
|
|
@@ -54,10 +61,22 @@ const DateSelector = memo(
|
|
|
54
61
|
return () => window.removeEventListener('resize', checkMobile);
|
|
55
62
|
}, []);
|
|
56
63
|
|
|
64
|
+
// Avoid re-running when parent passes an unstable onChange (inline arrow).
|
|
65
|
+
const onChangeRef = useRef(onChange);
|
|
66
|
+
onChangeRef.current = onChange;
|
|
67
|
+
const lastEmittedRef = useRef<string | null | undefined>(undefined);
|
|
68
|
+
|
|
57
69
|
// Validate and propagate changes
|
|
58
70
|
useEffect(() => {
|
|
71
|
+
const emit = (next: DateTime | undefined) => {
|
|
72
|
+
const key = next?.isValid ? next.toISODate() : null;
|
|
73
|
+
if (key === lastEmittedRef.current) return;
|
|
74
|
+
lastEmittedRef.current = key;
|
|
75
|
+
onChangeRef.current(next);
|
|
76
|
+
};
|
|
77
|
+
|
|
59
78
|
if (!day || !month || !year) {
|
|
60
|
-
|
|
79
|
+
emit(undefined);
|
|
61
80
|
return;
|
|
62
81
|
}
|
|
63
82
|
|
|
@@ -66,7 +85,7 @@ const DateSelector = memo(
|
|
|
66
85
|
const y = parseInt(year);
|
|
67
86
|
|
|
68
87
|
if (isNaN(d) || isNaN(m) || isNaN(y)) {
|
|
69
|
-
|
|
88
|
+
emit(undefined);
|
|
70
89
|
return;
|
|
71
90
|
}
|
|
72
91
|
|
|
@@ -75,11 +94,11 @@ const DateSelector = memo(
|
|
|
75
94
|
// Basic validation: check if it's a valid date (e.g. not Feb 30)
|
|
76
95
|
// and within range.
|
|
77
96
|
if (newDate.isValid && newDate >= minDate && newDate <= maxDate) {
|
|
78
|
-
|
|
97
|
+
emit(newDate);
|
|
79
98
|
} else {
|
|
80
|
-
|
|
99
|
+
emit(undefined);
|
|
81
100
|
}
|
|
82
|
-
}, [day, month, year,
|
|
101
|
+
}, [day, month, year, minDate, maxDate]);
|
|
83
102
|
|
|
84
103
|
// Handle mobile native input change
|
|
85
104
|
const handleMobileChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Tenant,
|
|
4
4
|
} from '@memori.ai/memori-api-client/dist/types';
|
|
5
5
|
import { Drawer } from '@memori.ai/ui';
|
|
6
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
6
7
|
import { useTranslation } from 'react-i18next';
|
|
7
8
|
import { getResourceUrl } from '../../helpers/media';
|
|
8
9
|
|
|
@@ -24,9 +25,11 @@ const ExpertsDrawer = ({
|
|
|
24
25
|
onClose,
|
|
25
26
|
}: Props) => {
|
|
26
27
|
const { t } = useTranslation();
|
|
28
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
27
29
|
|
|
28
30
|
return (
|
|
29
31
|
<Drawer
|
|
32
|
+
container={surfaceEl ?? undefined}
|
|
30
33
|
open={open}
|
|
31
34
|
onClose={onClose}
|
|
32
35
|
className="memori--experts-drawer"
|
|
@@ -3,8 +3,13 @@ import { File, X } from 'lucide-react';
|
|
|
3
3
|
import { Button } from '@memori.ai/ui';
|
|
4
4
|
import ContentPreviewModal from '../ContentPreviewModal';
|
|
5
5
|
import Snippet from '../Snippet/Snippet';
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
stripHTML,
|
|
8
|
+
stripDocumentAttachmentTags,
|
|
9
|
+
isOfficeNativeFilename,
|
|
10
|
+
getDocumentAttachmentAssetUrl,
|
|
11
|
+
} from '../../helpers/utils';
|
|
12
|
+
import { getDocumentBadgeLabel } from '../MediaWidget/MediaItemWidget.utils';
|
|
8
13
|
import { useTranslation } from 'react-i18next';
|
|
9
14
|
|
|
10
15
|
type FilePreviewProps = {
|
|
@@ -60,6 +65,15 @@ const FilePreview = ({
|
|
|
60
65
|
return 'CSV';
|
|
61
66
|
case 'html':
|
|
62
67
|
return 'HTML';
|
|
68
|
+
case 'doc':
|
|
69
|
+
case 'docx':
|
|
70
|
+
case 'dotx':
|
|
71
|
+
return 'Word';
|
|
72
|
+
case 'xls':
|
|
73
|
+
case 'xltx':
|
|
74
|
+
return 'Excel';
|
|
75
|
+
case 'potx':
|
|
76
|
+
return 'PowerPoint';
|
|
63
77
|
case 'jpg':
|
|
64
78
|
case 'jpeg':
|
|
65
79
|
return 'JPEG';
|
|
@@ -111,9 +125,7 @@ const FilePreview = ({
|
|
|
111
125
|
if (isHtmlFile(file)) {
|
|
112
126
|
let htmlContent = content;
|
|
113
127
|
if (htmlContent.includes('<') || htmlContent.includes('"')) {
|
|
114
|
-
|
|
115
|
-
div.innerHTML = htmlContent;
|
|
116
|
-
htmlContent = div.textContent || div.innerText || htmlContent;
|
|
128
|
+
htmlContent = stripHTML(htmlContent) || htmlContent;
|
|
117
129
|
}
|
|
118
130
|
htmlContent = stripDocumentAttachmentTags(htmlContent);
|
|
119
131
|
return htmlContent;
|
|
@@ -169,7 +181,16 @@ const FilePreview = ({
|
|
|
169
181
|
<button
|
|
170
182
|
type="button"
|
|
171
183
|
className="memori--preview-item-trigger"
|
|
172
|
-
onClick={() =>
|
|
184
|
+
onClick={() => {
|
|
185
|
+
if (isOfficeNativeFilename(file.name || '')) {
|
|
186
|
+
const url = getDocumentAttachmentAssetUrl(file);
|
|
187
|
+
if (url) {
|
|
188
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
setSelectedFile(file);
|
|
192
|
+
}
|
|
193
|
+
}}
|
|
173
194
|
aria-label={file.name}
|
|
174
195
|
>
|
|
175
196
|
{isImageContent(file.content, file.type) ? (
|
|
@@ -184,7 +205,7 @@ const FilePreview = ({
|
|
|
184
205
|
<span className="memori--preview-filename">{file.name}</span>
|
|
185
206
|
<span className="memori--preview-filetype">
|
|
186
207
|
{file.mimeType
|
|
187
|
-
?
|
|
208
|
+
? getDocumentBadgeLabel(file.mimeType, file.name)
|
|
188
209
|
: getFileType(file.name, file.type)}
|
|
189
210
|
</span>
|
|
190
211
|
</div>
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
} from '@tanstack/react-table';
|
|
24
24
|
import { getErrori18nKey } from '../../helpers/error';
|
|
25
25
|
import { useTranslation } from 'react-i18next';
|
|
26
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
26
27
|
import { Trash2 } from 'lucide-react';
|
|
27
28
|
|
|
28
29
|
export interface Props {
|
|
@@ -45,6 +46,7 @@ const KnownFacts = ({
|
|
|
45
46
|
initialKnownFacts = [],
|
|
46
47
|
closeDrawer,
|
|
47
48
|
}: Props) => {
|
|
49
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
48
50
|
const { t, i18n } = useTranslation();
|
|
49
51
|
const { add } = useAlertManager();
|
|
50
52
|
const { getKnownFactsPaginated, deleteKnownFact } = apiClient.knownFacts;
|
|
@@ -168,6 +170,7 @@ const KnownFacts = ({
|
|
|
168
170
|
|
|
169
171
|
return (
|
|
170
172
|
<Drawer
|
|
173
|
+
container={surfaceEl ?? undefined}
|
|
171
174
|
open={visible}
|
|
172
175
|
anchor="right"
|
|
173
176
|
className="memori-known-facts-drawer"
|
|
@@ -180,6 +183,7 @@ const KnownFacts = ({
|
|
|
180
183
|
>
|
|
181
184
|
<div className="memori-known-facts-body">
|
|
182
185
|
<Modal
|
|
186
|
+
container={surfaceEl ?? undefined}
|
|
183
187
|
className="memori-known-facts-modal"
|
|
184
188
|
open={bulkDeleteModalVisible}
|
|
185
189
|
closable
|
|
@@ -316,6 +320,7 @@ const KnownFacts = ({
|
|
|
316
320
|
/>
|
|
317
321
|
|
|
318
322
|
<Modal
|
|
323
|
+
container={surfaceEl ?? undefined}
|
|
319
324
|
className="memori-known-facts-modal"
|
|
320
325
|
open={deleteModalVisibleFor !== undefined}
|
|
321
326
|
closable
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Form,
|
|
12
12
|
} from '@memori.ai/ui';
|
|
13
13
|
import { useTranslation } from 'react-i18next';
|
|
14
|
+
import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
|
|
14
15
|
import cx from 'classnames';
|
|
15
16
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
16
17
|
import { getErrori18nKey } from '../../helpers/error';
|
|
@@ -50,6 +51,7 @@ const LoginDrawer = ({
|
|
|
50
51
|
__TEST__signup = false,
|
|
51
52
|
__TEST__needMissingData = false,
|
|
52
53
|
}: Props) => {
|
|
54
|
+
const surfaceEl = useWidgetSurfaceEl();
|
|
53
55
|
const { t, i18n } = useTranslation();
|
|
54
56
|
const { add } = useAlertManager();
|
|
55
57
|
const lang = i18n.language === 'it' ? 'it' : 'en';
|
|
@@ -436,6 +438,7 @@ const LoginDrawer = ({
|
|
|
436
438
|
|
|
437
439
|
return (
|
|
438
440
|
<Drawer
|
|
441
|
+
container={surfaceEl ?? undefined}
|
|
439
442
|
open={open}
|
|
440
443
|
onClose={onClose}
|
|
441
444
|
className={cx('memori--login-drawer', {
|
|
@@ -11,7 +11,10 @@ import React, {
|
|
|
11
11
|
import { getResourceUrl } from '../../helpers/media';
|
|
12
12
|
import {
|
|
13
13
|
withLinksOpenInNewTab,
|
|
14
|
+
stripHTML,
|
|
14
15
|
stripDocumentAttachmentTags,
|
|
16
|
+
isAssetOnlyDocumentAttachment,
|
|
17
|
+
getDocumentAttachmentAssetUrl,
|
|
15
18
|
} from '../../helpers/utils';
|
|
16
19
|
import { getTranslation } from '../../helpers/translations';
|
|
17
20
|
import { prismSyntaxLangs } from '../../helpers/constants';
|
|
@@ -32,7 +35,7 @@ import type {
|
|
|
32
35
|
import {
|
|
33
36
|
formatBytes,
|
|
34
37
|
getFileExtensionFromUrl,
|
|
35
|
-
|
|
38
|
+
getDocumentBadgeLabel,
|
|
36
39
|
countLines,
|
|
37
40
|
shouldUseDarkFileCard,
|
|
38
41
|
fetchLinkPreview,
|
|
@@ -268,7 +271,7 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
268
271
|
) : (
|
|
269
272
|
<DocumentCard
|
|
270
273
|
title={medium.title || 'File'}
|
|
271
|
-
badge={
|
|
274
|
+
badge={getDocumentBadgeLabel(medium.mimeType, medium.title)}
|
|
272
275
|
meta={(() => {
|
|
273
276
|
const size = getContentSize(medium);
|
|
274
277
|
return size != null && size > 0 ? formatBytes(size) : null;
|
|
@@ -284,7 +287,7 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
284
287
|
return (
|
|
285
288
|
<DocumentCard
|
|
286
289
|
title={medium.title || 'File'}
|
|
287
|
-
badge={
|
|
290
|
+
badge={getDocumentBadgeLabel(medium.mimeType, medium.title)}
|
|
288
291
|
meta={(() => {
|
|
289
292
|
const size = getContentSize(medium);
|
|
290
293
|
return size != null && size > 0 ? formatBytes(size) : null;
|
|
@@ -298,7 +301,7 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
298
301
|
return (
|
|
299
302
|
<DocumentCard
|
|
300
303
|
title={medium.title || 'File'}
|
|
301
|
-
badge={
|
|
304
|
+
badge={getDocumentBadgeLabel(medium.mimeType, medium.title)}
|
|
302
305
|
meta={(() => {
|
|
303
306
|
const size = getContentSize(medium);
|
|
304
307
|
return size != null && size > 0 ? formatBytes(size) : null;
|
|
@@ -324,8 +327,11 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
324
327
|
|
|
325
328
|
// Extension and file detection helpers
|
|
326
329
|
const fileExtensionFromUrl = getFileExtensionFromUrl(normURL || item.url);
|
|
327
|
-
const
|
|
328
|
-
|
|
330
|
+
const fileExtension = getDocumentBadgeLabel(
|
|
331
|
+
item.mimeType,
|
|
332
|
+
item.title,
|
|
333
|
+
normURL || item.url
|
|
334
|
+
);
|
|
329
335
|
const isFile = shouldUseDarkFileCard(
|
|
330
336
|
item,
|
|
331
337
|
fileExtensionFromUrl,
|
|
@@ -355,8 +361,16 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
355
361
|
const metaParts = [lineText, sizeText].filter(Boolean);
|
|
356
362
|
const metaLine = metaParts.length > 0 ? metaParts.join(' · ') : null;
|
|
357
363
|
|
|
364
|
+
// Asset-only attachments (e.g. Office native files) open via URL, not modal
|
|
365
|
+
const isAssetOnlyAttachment = isAssetOnlyDocumentAttachment(item);
|
|
366
|
+
|
|
358
367
|
// Document attachments and attached files should open in modal, not as links
|
|
359
|
-
if (
|
|
368
|
+
if (
|
|
369
|
+
(isDocumentAttachment || isAttachedFile) &&
|
|
370
|
+
item.mediumID &&
|
|
371
|
+
_onClick &&
|
|
372
|
+
!isAssetOnlyAttachment
|
|
373
|
+
) {
|
|
360
374
|
return (
|
|
361
375
|
<div
|
|
362
376
|
onClick={() => _onClick(item)}
|
|
@@ -395,16 +409,17 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
395
409
|
|
|
396
410
|
// Build href: open in new tab (never modal). Use URL, or blob for content-only items.
|
|
397
411
|
const getFileCardHref = (): string => {
|
|
398
|
-
|
|
412
|
+
const assetUrl = getDocumentAttachmentAssetUrl(item);
|
|
413
|
+
if (assetUrl) {
|
|
399
414
|
return (
|
|
400
415
|
getResourceUrl({
|
|
401
|
-
resourceURI:
|
|
416
|
+
resourceURI: assetUrl,
|
|
402
417
|
sessionID,
|
|
403
418
|
tenantID,
|
|
404
419
|
baseURL,
|
|
405
420
|
apiURL,
|
|
406
421
|
}) ||
|
|
407
|
-
|
|
422
|
+
assetUrl ||
|
|
408
423
|
'#'
|
|
409
424
|
);
|
|
410
425
|
}
|
|
@@ -416,9 +431,7 @@ export const RenderMediaItem = memo(function RenderMediaItem({
|
|
|
416
431
|
htmlContent.includes('<document_attachment')
|
|
417
432
|
) {
|
|
418
433
|
if (htmlContent.includes('<') || htmlContent.includes('"')) {
|
|
419
|
-
|
|
420
|
-
div.innerHTML = htmlContent;
|
|
421
|
-
htmlContent = div.textContent || div.innerText || htmlContent;
|
|
434
|
+
htmlContent = stripHTML(htmlContent) || htmlContent;
|
|
422
435
|
}
|
|
423
436
|
htmlContent = stripDocumentAttachmentTags(htmlContent);
|
|
424
437
|
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
formatBytes,
|
|
3
3
|
getFileExtensionFromUrl,
|
|
4
4
|
getFileExtensionFromMime,
|
|
5
|
+
getDocumentBadgeLabel,
|
|
5
6
|
countLines,
|
|
6
7
|
shouldUseDarkFileCard,
|
|
7
8
|
fetchLinkPreview,
|
|
@@ -57,8 +58,25 @@ describe('MediaItemWidget.utils', () => {
|
|
|
57
58
|
expect(getFileExtensionFromMime('text/html')).toBe('HTML');
|
|
58
59
|
expect(getFileExtensionFromMime('text/plain')).toBe('TXT');
|
|
59
60
|
expect(getFileExtensionFromMime('application/json')).toBe('JSON');
|
|
60
|
-
expect(getFileExtensionFromMime('application/vnd.ms-excel')).toBe('
|
|
61
|
-
expect(
|
|
61
|
+
expect(getFileExtensionFromMime('application/vnd.ms-excel')).toBe('Excel');
|
|
62
|
+
expect(
|
|
63
|
+
getFileExtensionFromMime(
|
|
64
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
65
|
+
)
|
|
66
|
+
).toBe('Excel');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('maps office mime types with parameters to short labels', () => {
|
|
70
|
+
expect(
|
|
71
|
+
getFileExtensionFromMime(
|
|
72
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=binary'
|
|
73
|
+
)
|
|
74
|
+
).toBe('Word');
|
|
75
|
+
expect(
|
|
76
|
+
getFileExtensionFromMime(
|
|
77
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.template'
|
|
78
|
+
)
|
|
79
|
+
).toBe('Excel');
|
|
62
80
|
});
|
|
63
81
|
|
|
64
82
|
it('uses subtype when not in MIME_TO_EXT map', () => {
|
|
@@ -71,6 +89,31 @@ describe('MediaItemWidget.utils', () => {
|
|
|
71
89
|
});
|
|
72
90
|
});
|
|
73
91
|
|
|
92
|
+
describe('getDocumentBadgeLabel', () => {
|
|
93
|
+
it('prefers URL extension, then filename, then mime type', () => {
|
|
94
|
+
expect(
|
|
95
|
+
getDocumentBadgeLabel(
|
|
96
|
+
'application/pdf',
|
|
97
|
+
'report.docx',
|
|
98
|
+
'https://example.com/file.pdf'
|
|
99
|
+
)
|
|
100
|
+
).toBe('PDF');
|
|
101
|
+
expect(
|
|
102
|
+
getDocumentBadgeLabel(
|
|
103
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
104
|
+
'report.docx',
|
|
105
|
+
'https://example.com/asset/123'
|
|
106
|
+
)
|
|
107
|
+
).toBe('Word');
|
|
108
|
+
expect(
|
|
109
|
+
getDocumentBadgeLabel(
|
|
110
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
111
|
+
'budget.xlsx'
|
|
112
|
+
)
|
|
113
|
+
).toBe('Excel');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
74
117
|
describe('countLines', () => {
|
|
75
118
|
it('returns 0 for undefined or empty', () => {
|
|
76
119
|
expect(countLines(undefined)).toBe(0);
|