@patternfly/chatbot 2.2.0-prerelease.30 → 2.2.0-prerelease.31
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/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +4 -0
- package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +26 -0
- package/dist/cjs/Message/Message.d.ts +3 -1
- package/dist/cjs/Message/Message.js +4 -3
- package/dist/cjs/Message/Message.test.js +25 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/tracking/console_tracking_provider.d.ts +10 -0
- package/dist/cjs/tracking/console_tracking_provider.js +27 -0
- package/dist/cjs/tracking/index.d.ts +2 -0
- package/dist/cjs/tracking/index.js +23 -0
- package/dist/cjs/tracking/posthog_tracking_provider.d.ts +9 -0
- package/dist/cjs/tracking/posthog_tracking_provider.js +37 -0
- package/dist/cjs/tracking/segment_tracking_provider.d.ts +10 -0
- package/dist/cjs/tracking/segment_tracking_provider.js +50 -0
- package/dist/cjs/tracking/trackingProviderProxy.d.ts +9 -0
- package/dist/cjs/tracking/trackingProviderProxy.js +24 -0
- package/dist/cjs/tracking/tracking_api.d.ts +8 -0
- package/dist/cjs/tracking/tracking_api.js +2 -0
- package/dist/cjs/tracking/tracking_registry.d.ts +4 -0
- package/dist/cjs/tracking/tracking_registry.js +33 -0
- package/dist/cjs/tracking/tracking_spi.d.ts +9 -0
- package/dist/cjs/tracking/tracking_spi.js +2 -0
- package/dist/cjs/tracking/umami_tracking_provider.d.ts +14 -0
- package/dist/cjs/tracking/umami_tracking_provider.js +44 -0
- package/dist/dynamic/tracking/package.json +1 -0
- package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +4 -0
- package/dist/esm/Message/ErrorMessage/ErrorMessage.js +21 -0
- package/dist/esm/Message/Message.d.ts +3 -1
- package/dist/esm/Message/Message.js +4 -3
- package/dist/esm/Message/Message.test.js +25 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/tracking/console_tracking_provider.d.ts +10 -0
- package/dist/esm/tracking/console_tracking_provider.js +23 -0
- package/dist/esm/tracking/index.d.ts +2 -0
- package/dist/esm/tracking/index.js +2 -0
- package/dist/esm/tracking/posthog_tracking_provider.d.ts +9 -0
- package/dist/esm/tracking/posthog_tracking_provider.js +33 -0
- package/dist/esm/tracking/segment_tracking_provider.d.ts +10 -0
- package/dist/esm/tracking/segment_tracking_provider.js +46 -0
- package/dist/esm/tracking/trackingProviderProxy.d.ts +9 -0
- package/dist/esm/tracking/trackingProviderProxy.js +22 -0
- package/dist/esm/tracking/tracking_api.d.ts +8 -0
- package/dist/esm/tracking/tracking_api.js +1 -0
- package/dist/esm/tracking/tracking_registry.d.ts +4 -0
- package/dist/esm/tracking/tracking_registry.js +26 -0
- package/dist/esm/tracking/tracking_spi.d.ts +9 -0
- package/dist/esm/tracking/tracking_spi.js +1 -0
- package/dist/esm/tracking/umami_tracking_provider.d.ts +14 -0
- package/dist/esm/tracking/umami_tracking_provider.js +40 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +3 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +214 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +24 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +24 -1
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +2 -0
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.tsx +37 -24
- package/patternfly-docs/content/extensions/chatbot/img/analytics-example.svg +118 -0
- package/patternfly-docs/content/extensions/chatbot/img/chatbot-analytics.svg +51 -0
- package/patternfly-docs/content/extensions/chatbot/img/posthog.svg +30 -0
- package/patternfly-docs/content/extensions/chatbot/img/segment.svg +36 -0
- package/patternfly-docs/content/extensions/chatbot/img/umami.svg +30 -0
- package/src/Message/ErrorMessage/ErrorMessage.tsx +14 -0
- package/src/Message/Message.test.tsx +32 -0
- package/src/Message/Message.tsx +50 -41
- package/src/index.ts +3 -0
- package/src/tracking/console_tracking_provider.ts +30 -0
- package/src/tracking/index.ts +3 -0
- package/src/tracking/posthog_tracking_provider.ts +42 -0
- package/src/tracking/segment_tracking_provider.ts +62 -0
- package/src/tracking/trackingProviderProxy.ts +28 -0
- package/src/tracking/tracking_api.ts +11 -0
- package/src/tracking/tracking_registry.ts +33 -0
- package/src/tracking/tracking_spi.ts +14 -0
- package/src/tracking/umami_tracking_provider.ts +54 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
"use strict";
|
2
|
+
// ============================================================================
|
3
|
+
// Chatbot Main - Message - Content - Error
|
4
|
+
// ============================================================================
|
5
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
6
|
+
var t = {};
|
7
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
8
|
+
t[p] = s[p];
|
9
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
10
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
11
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
12
|
+
t[p[i]] = s[p[i]];
|
13
|
+
}
|
14
|
+
return t;
|
15
|
+
};
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
|
+
};
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
+
const react_1 = __importDefault(require("react"));
|
21
|
+
const react_core_1 = require("@patternfly/react-core");
|
22
|
+
const ErrorMessage = (_a) => {
|
23
|
+
var { title, actionLinks, children } = _a, props = __rest(_a, ["title", "actionLinks", "children"]);
|
24
|
+
return (react_1.default.createElement(react_core_1.Alert, Object.assign({ isInline: true, variant: "danger", title: title, actionLinks: actionLinks }, props), children));
|
25
|
+
};
|
26
|
+
exports.default = ErrorMessage;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React, { ReactNode } from 'react';
|
2
|
-
import { AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
2
|
+
import { AlertProps, AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
3
3
|
import { ActionProps } from '../ResponseActions/ResponseActions';
|
4
4
|
import { SourcesCardProps } from '../SourcesCard';
|
5
5
|
import { QuickStart, QuickstartAction } from './QuickStarts/types';
|
@@ -102,6 +102,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
102
102
|
additionalRehypePlugins?: PluggableList;
|
103
103
|
/** Whether to open links in message in new tab. */
|
104
104
|
openLinkInNewTab?: boolean;
|
105
|
+
/** Optional inline error message that can be displayed in the message */
|
106
|
+
error?: AlertProps;
|
105
107
|
}
|
106
108
|
export declare const MessageBase: React.FunctionComponent<MessageProps>;
|
107
109
|
declare const Message: React.ForwardRefExoticComponent<Omit<MessageProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
@@ -46,8 +46,9 @@ const rehype_unwrap_images_1 = __importDefault(require("rehype-unwrap-images"));
|
|
46
46
|
const rehype_external_links_1 = __importDefault(require("rehype-external-links"));
|
47
47
|
const rehype_sanitize_1 = __importDefault(require("rehype-sanitize"));
|
48
48
|
const LinkMessage_1 = __importDefault(require("./LinkMessage/LinkMessage"));
|
49
|
+
const ErrorMessage_1 = __importDefault(require("./ErrorMessage/ErrorMessage"));
|
49
50
|
const MessageBase = (_a) => {
|
50
|
-
var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [] } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins"]);
|
51
|
+
var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], error } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "error"]);
|
51
52
|
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
52
53
|
let rehypePlugins = [rehype_unwrap_images_1.default];
|
53
54
|
if (openLinkInNewTab) {
|
@@ -77,7 +78,7 @@ const MessageBase = (_a) => {
|
|
77
78
|
react_1.default.createElement("div", { className: "pf-chatbot__message-and-actions" },
|
78
79
|
isLoading ? (react_1.default.createElement(MessageLoading_1.default, { loadingWord: loadingWord })) : (react_1.default.createElement(react_1.default.Fragment, null,
|
79
80
|
beforeMainContent && react_1.default.createElement(react_1.default.Fragment, null, beforeMainContent),
|
80
|
-
react_1.default.createElement(react_markdown_1.default, { components: {
|
81
|
+
error ? (react_1.default.createElement(ErrorMessage_1.default, Object.assign({}, error))) : (react_1.default.createElement(react_markdown_1.default, { components: {
|
81
82
|
p: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.p }, props)),
|
82
83
|
code: (_a) => {
|
83
84
|
var { children } = _a, props = __rest(_a, ["children"]);
|
@@ -106,7 +107,7 @@ const MessageBase = (_a) => {
|
|
106
107
|
th: (props) => react_1.default.createElement(ThMessage_1.default, Object.assign({}, props)),
|
107
108
|
img: (props) => react_1.default.createElement(ImageMessage_1.default, Object.assign({}, props)),
|
108
109
|
a: (props) => (react_1.default.createElement(LinkMessage_1.default, { href: props.href, rel: props.rel, target: props.target }, props.children))
|
109
|
-
}, remarkPlugins: [remark_gfm_1.default], rehypePlugins: rehypePlugins }, content),
|
110
|
+
}, remarkPlugins: [remark_gfm_1.default], rehypePlugins: rehypePlugins }, content)),
|
110
111
|
afterMainContent && react_1.default.createElement(react_1.default.Fragment, null, afterMainContent))),
|
111
112
|
!isLoading && sources && react_1.default.createElement(SourcesCard_1.default, Object.assign({}, sources)),
|
112
113
|
quickStarts && quickStarts.quickStart && (react_1.default.createElement(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel })),
|
@@ -20,6 +20,7 @@ const user_event_1 = __importDefault(require("@testing-library/user-event"));
|
|
20
20
|
const monitor_sampleapp_quickstart_1 = require("./QuickStarts/monitor-sampleapp-quickstart");
|
21
21
|
const monitor_sampleapp_quickstart_with_image_1 = require("./QuickStarts/monitor-sampleapp-quickstart-with-image");
|
22
22
|
const rehype_external_links_1 = __importDefault(require("../__mocks__/rehype-external-links"));
|
23
|
+
const react_core_1 = require("@patternfly/react-core");
|
23
24
|
const ALL_ACTIONS = [
|
24
25
|
{ label: /Good response/i },
|
25
26
|
{ label: /Bad response/i },
|
@@ -139,6 +140,13 @@ const EMPTY_TABLE = `
|
|
139
140
|
|
140
141
|
`;
|
141
142
|
const IMAGE = ``;
|
143
|
+
const ERROR = {
|
144
|
+
title: 'Could not load chat',
|
145
|
+
children: 'Wait a few minutes and check your network settings. If the issue persists: ',
|
146
|
+
actionLinks: (react_1.default.createElement(react_1.default.Fragment, null,
|
147
|
+
react_1.default.createElement(react_core_1.AlertActionLink, { component: "a", href: "#" }, "Start a new chat"),
|
148
|
+
react_1.default.createElement(react_core_1.AlertActionLink, { component: "a", href: "#" }, "Contact support")))
|
149
|
+
};
|
142
150
|
const checkListItemsRendered = () => {
|
143
151
|
const items = ['Item 1', 'Item 2', 'Item 3'];
|
144
152
|
expect(react_2.screen.getAllByRole('listitem')).toHaveLength(3);
|
@@ -594,4 +602,21 @@ describe('Message', () => {
|
|
594
602
|
// we are mocking rehype libraries, so we can't test target _blank addition on links directly with RTL
|
595
603
|
expect(rehype_external_links_1.default).not.toHaveBeenCalled();
|
596
604
|
});
|
605
|
+
it('should handle error correctly', () => {
|
606
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", error: ERROR }));
|
607
|
+
expect(react_2.screen.getByRole('heading', { name: /Could not load chat/i })).toBeTruthy();
|
608
|
+
expect(react_2.screen.getByRole('link', { name: /Start a new chat/i })).toBeTruthy();
|
609
|
+
expect(react_2.screen.getByRole('link', { name: /Contact support/i })).toBeTruthy();
|
610
|
+
expect(react_2.screen.getByText('Wait a few minutes and check your network settings. If the issue persists:')).toBeTruthy();
|
611
|
+
});
|
612
|
+
it('should handle error correctly when loading', () => {
|
613
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", error: ERROR, isLoading: true }));
|
614
|
+
expect(react_2.screen.queryByRole('heading', { name: /Could not load chat/i })).toBeFalsy();
|
615
|
+
expect(react_2.screen.getByText('Loading message')).toBeTruthy();
|
616
|
+
});
|
617
|
+
it('should handle error correctly when these is content', () => {
|
618
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", error: ERROR, content: "Test" }));
|
619
|
+
expect(react_2.screen.getByRole('heading', { name: /Could not load chat/i })).toBeTruthy();
|
620
|
+
expect(react_2.screen.queryByText('Test')).toBeFalsy();
|
621
|
+
});
|
597
622
|
});
|
package/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.js
CHANGED
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
18
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
19
19
|
};
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
21
|
-
exports.TermsOfUse = exports.SourcesCard = exports.SourceDetailsMenuItem = exports.Settings = exports.ResponseActions = exports.PreviewAttachment = exports.MessageBox = exports.MessageBar = exports.Message = exports.LoadingMessage = exports.FileDropZone = exports.FileDetailsLabel = exports.FileDetails = exports.Compare = exports.CodeModal = exports.ChatbotWelcomePrompt = exports.ChatbotToggle = exports.ChatbotPopover = exports.ChatbotModal = exports.ChatbotHeader = exports.ChatbotFooter = exports.ChatbotConversationHistoryNav = exports.ChatbotContent = exports.ChatbotAlert = exports.Chatbot = exports.AttachMenu = exports.AttachmentEdit = void 0;
|
21
|
+
exports.tracking = exports.TermsOfUse = exports.SourcesCard = exports.SourceDetailsMenuItem = exports.Settings = exports.ResponseActions = exports.PreviewAttachment = exports.MessageBox = exports.MessageBar = exports.Message = exports.LoadingMessage = exports.FileDropZone = exports.FileDetailsLabel = exports.FileDetails = exports.Compare = exports.CodeModal = exports.ChatbotWelcomePrompt = exports.ChatbotToggle = exports.ChatbotPopover = exports.ChatbotModal = exports.ChatbotHeader = exports.ChatbotFooter = exports.ChatbotConversationHistoryNav = exports.ChatbotContent = exports.ChatbotAlert = exports.Chatbot = exports.AttachMenu = exports.AttachmentEdit = void 0;
|
22
22
|
var AttachmentEdit_1 = require("./AttachmentEdit");
|
23
23
|
Object.defineProperty(exports, "AttachmentEdit", { enumerable: true, get: function () { return __importDefault(AttachmentEdit_1).default; } });
|
24
24
|
__exportStar(require("./AttachmentEdit"), exports);
|
@@ -100,3 +100,6 @@ __exportStar(require("./SourcesCard"), exports);
|
|
100
100
|
var TermsOfUse_1 = require("./TermsOfUse");
|
101
101
|
Object.defineProperty(exports, "TermsOfUse", { enumerable: true, get: function () { return __importDefault(TermsOfUse_1).default; } });
|
102
102
|
__exportStar(require("./TermsOfUse"), exports);
|
103
|
+
var tracking_1 = require("./tracking");
|
104
|
+
Object.defineProperty(exports, "tracking", { enumerable: true, get: function () { return __importDefault(tracking_1).default; } });
|
105
|
+
__exportStar(require("./tracking"), exports);
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { TrackingSpi } from './tracking_spi';
|
2
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
3
|
+
export declare class ConsoleTrackingProvider implements TrackingSpi, TrackingApi {
|
4
|
+
trackPageView(url: string | undefined): void;
|
5
|
+
registerProvider(): void;
|
6
|
+
initialize(): void;
|
7
|
+
identify(userID: string): void;
|
8
|
+
trackSingleItem(item: string, properties?: TrackingEventProperties): void;
|
9
|
+
getKey(): string;
|
10
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ConsoleTrackingProvider = void 0;
|
4
|
+
class ConsoleTrackingProvider {
|
5
|
+
trackPageView(url) {
|
6
|
+
// eslint-disable-next-line no-console
|
7
|
+
console.log('ConsoleProvider pageView', url);
|
8
|
+
}
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
10
|
+
registerProvider() { }
|
11
|
+
initialize() {
|
12
|
+
// eslint-disable-next-line no-console
|
13
|
+
console.log('ConsoleProvider initialize');
|
14
|
+
}
|
15
|
+
identify(userID) {
|
16
|
+
// eslint-disable-next-line no-console
|
17
|
+
console.log('ConsoleProvider identify', userID);
|
18
|
+
}
|
19
|
+
trackSingleItem(item, properties) {
|
20
|
+
// eslint-disable-next-line no-console
|
21
|
+
console.log('ConsoleProvider: ' + item, properties);
|
22
|
+
}
|
23
|
+
getKey() {
|
24
|
+
return 'console';
|
25
|
+
}
|
26
|
+
}
|
27
|
+
exports.ConsoleTrackingProvider = ConsoleTrackingProvider;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
|
+
};
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
+
exports.default = void 0;
|
21
|
+
var tracking_registry_1 = require("./tracking_registry");
|
22
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(tracking_registry_1).default; } });
|
23
|
+
__exportStar(require("./tracking_registry"), exports);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
2
|
+
import { InitProps, TrackingSpi } from './tracking_spi';
|
3
|
+
export declare class PosthogTrackingProvider implements TrackingSpi, TrackingApi {
|
4
|
+
getKey(): string;
|
5
|
+
initialize(props: InitProps): void;
|
6
|
+
identify(userID: string): void;
|
7
|
+
trackPageView(url: string | undefined): void;
|
8
|
+
trackSingleItem(item: string, properties?: TrackingEventProperties): void;
|
9
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.PosthogTrackingProvider = void 0;
|
4
|
+
const posthog_js_1 = require("posthog-js");
|
5
|
+
class PosthogTrackingProvider {
|
6
|
+
getKey() {
|
7
|
+
return 'posthogKey';
|
8
|
+
}
|
9
|
+
initialize(props) {
|
10
|
+
// eslint-disable-next-line no-console
|
11
|
+
console.log('PosthogProvider initialize');
|
12
|
+
const posthogKey = props.posthogKey;
|
13
|
+
posthog_js_1.posthog.init(posthogKey, {
|
14
|
+
// eslint-disable-next-line camelcase
|
15
|
+
api_host: 'https://us.i.posthog.com',
|
16
|
+
// eslint-disable-next-line camelcase
|
17
|
+
person_profiles: 'identified_only' // or 'always' to create profiles for anonymous users as well
|
18
|
+
});
|
19
|
+
}
|
20
|
+
identify(userID) {
|
21
|
+
// eslint-disable-next-line no-console
|
22
|
+
console.log('PosthogProvider userID: ' + userID);
|
23
|
+
posthog_js_1.posthog.identify(userID);
|
24
|
+
}
|
25
|
+
trackPageView(url) {
|
26
|
+
// eslint-disable-next-line no-console
|
27
|
+
console.log('PostHogProvider url', url);
|
28
|
+
// TODO posthog seems to record that automatically.
|
29
|
+
// How to not clash with this here? Just leave as no-op?
|
30
|
+
}
|
31
|
+
trackSingleItem(item, properties) {
|
32
|
+
// eslint-disable-next-line no-console
|
33
|
+
console.log('PosthogProvider: trackSingleItem' + item, properties);
|
34
|
+
posthog_js_1.posthog.capture(item, { properties });
|
35
|
+
}
|
36
|
+
}
|
37
|
+
exports.PosthogTrackingProvider = PosthogTrackingProvider;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
2
|
+
import { InitProps, TrackingSpi } from './tracking_spi';
|
3
|
+
export declare class SegmentTrackingProvider implements TrackingSpi, TrackingApi {
|
4
|
+
private analytics;
|
5
|
+
getKey(): string;
|
6
|
+
initialize(props: InitProps): void;
|
7
|
+
identify(userID: string): void;
|
8
|
+
trackPageView(url: string | undefined): void;
|
9
|
+
trackSingleItem(item: string, properties?: TrackingEventProperties): void;
|
10
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SegmentTrackingProvider = void 0;
|
4
|
+
const analytics_next_1 = require("@segment/analytics-next");
|
5
|
+
class SegmentTrackingProvider {
|
6
|
+
getKey() {
|
7
|
+
return 'segmentKey';
|
8
|
+
}
|
9
|
+
initialize(props) {
|
10
|
+
// eslint-disable-next-line no-console
|
11
|
+
console.log('SegmentProvider initialize');
|
12
|
+
const segmentKey = props.segmentKey;
|
13
|
+
// We need to create an object here, as ts lint is unhappy otherwise
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
15
|
+
const integrations = props.segmentIntegrations;
|
16
|
+
this.analytics = analytics_next_1.AnalyticsBrowser.load({
|
17
|
+
writeKey: segmentKey,
|
18
|
+
cdnURL: props.segmentCdn
|
19
|
+
}, {
|
20
|
+
integrations: Object.assign({}, integrations)
|
21
|
+
});
|
22
|
+
}
|
23
|
+
identify(userID) {
|
24
|
+
// eslint-disable-next-line no-console
|
25
|
+
console.log('SegmentProvider userID: ' + userID);
|
26
|
+
if (this.analytics) {
|
27
|
+
this.analytics.identify(userID);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
trackPageView(url) {
|
31
|
+
// eslint-disable-next-line no-console
|
32
|
+
console.log('SegmentProvider url', url);
|
33
|
+
if (this.analytics) {
|
34
|
+
if (url) {
|
35
|
+
this.analytics.page(url);
|
36
|
+
}
|
37
|
+
else {
|
38
|
+
this.analytics.page(); // Uses window.url
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
trackSingleItem(item, properties) {
|
43
|
+
// eslint-disable-next-line no-console
|
44
|
+
console.log('SegmentProvider: trackSingleItem' + item, properties);
|
45
|
+
if (this.analytics) {
|
46
|
+
this.analytics.track(item, { properties });
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
exports.SegmentTrackingProvider = SegmentTrackingProvider;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
2
|
+
declare class TrackingProviderProxy implements TrackingApi {
|
3
|
+
providers: TrackingApi[];
|
4
|
+
constructor(providers: TrackingApi[]);
|
5
|
+
identify(userID: string): void;
|
6
|
+
trackSingleItem(eventName: string, properties?: TrackingEventProperties): void;
|
7
|
+
trackPageView(url: string | undefined): void;
|
8
|
+
}
|
9
|
+
export default TrackingProviderProxy;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
class TrackingProviderProxy {
|
4
|
+
constructor(providers) {
|
5
|
+
this.providers = [];
|
6
|
+
this.providers = providers;
|
7
|
+
}
|
8
|
+
identify(userID) {
|
9
|
+
for (const provider of this.providers) {
|
10
|
+
provider.identify(userID);
|
11
|
+
}
|
12
|
+
}
|
13
|
+
trackSingleItem(eventName, properties) {
|
14
|
+
for (const provider of this.providers) {
|
15
|
+
provider.trackSingleItem(eventName, properties);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
trackPageView(url) {
|
19
|
+
for (const provider of this.providers) {
|
20
|
+
provider.trackPageView(url);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
exports.default = TrackingProviderProxy;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
export interface TrackingEventProperties {
|
2
|
+
[key: string]: string | number | boolean | undefined;
|
3
|
+
}
|
4
|
+
export interface TrackingApi {
|
5
|
+
identify: (userID: string) => void;
|
6
|
+
trackPageView: (url: string | undefined) => void;
|
7
|
+
trackSingleItem: (eventName: string, properties: TrackingEventProperties | undefined) => void;
|
8
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.getTrackingProviders = void 0;
|
7
|
+
const trackingProviderProxy_1 = __importDefault(require("./trackingProviderProxy"));
|
8
|
+
const console_tracking_provider_1 = require("./console_tracking_provider");
|
9
|
+
const segment_tracking_provider_1 = require("./segment_tracking_provider");
|
10
|
+
const posthog_tracking_provider_1 = require("./posthog_tracking_provider");
|
11
|
+
const umami_tracking_provider_1 = require("./umami_tracking_provider");
|
12
|
+
const getTrackingProviders = (initProps) => {
|
13
|
+
const providers = [];
|
14
|
+
providers.push(new segment_tracking_provider_1.SegmentTrackingProvider());
|
15
|
+
providers.push(new posthog_tracking_provider_1.PosthogTrackingProvider());
|
16
|
+
providers.push(new umami_tracking_provider_1.UmamiTrackingProvider());
|
17
|
+
// TODO dynamically find and register providers
|
18
|
+
// Initialize them
|
19
|
+
const enabledProviders = [];
|
20
|
+
for (const provider of providers) {
|
21
|
+
const key = provider.getKey();
|
22
|
+
if (Object.keys(initProps).indexOf(key) > -1) {
|
23
|
+
provider.initialize(initProps);
|
24
|
+
enabledProviders.push(provider);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
// Add the console provider
|
28
|
+
const consoleTrackingProvider = new console_tracking_provider_1.ConsoleTrackingProvider();
|
29
|
+
enabledProviders.push(consoleTrackingProvider); // TODO noop- provider?
|
30
|
+
return new trackingProviderProxy_1.default(enabledProviders);
|
31
|
+
};
|
32
|
+
exports.getTrackingProviders = getTrackingProviders;
|
33
|
+
exports.default = exports.getTrackingProviders;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
2
|
+
export interface InitProps {
|
3
|
+
[key: string]: string | number | boolean;
|
4
|
+
}
|
5
|
+
export interface TrackingSpi extends TrackingApi {
|
6
|
+
getKey: () => string;
|
7
|
+
initialize: (props: InitProps) => void;
|
8
|
+
trackSingleItem: (item: string, properties?: TrackingEventProperties) => void;
|
9
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { InitProps, TrackingSpi } from './tracking_spi';
|
2
|
+
import { TrackingApi, TrackingEventProperties } from './tracking_api';
|
3
|
+
declare global {
|
4
|
+
interface Window {
|
5
|
+
umami: any;
|
6
|
+
}
|
7
|
+
}
|
8
|
+
export declare class UmamiTrackingProvider implements TrackingSpi, TrackingApi {
|
9
|
+
getKey(): string;
|
10
|
+
initialize(props: InitProps): void;
|
11
|
+
identify(userID: string): void;
|
12
|
+
trackPageView(url: string | undefined): void;
|
13
|
+
trackSingleItem(item: string, properties?: TrackingEventProperties): void;
|
14
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.UmamiTrackingProvider = void 0;
|
4
|
+
class UmamiTrackingProvider {
|
5
|
+
getKey() {
|
6
|
+
return 'umamiKey';
|
7
|
+
}
|
8
|
+
initialize(props) {
|
9
|
+
// eslint-disable-next-line no-console
|
10
|
+
console.log('UmamiProvider initialize');
|
11
|
+
const umamiKey = props.umamiKey;
|
12
|
+
const hostUrl = props.umamiHostUrl;
|
13
|
+
const script = document.createElement('script');
|
14
|
+
script.src = hostUrl + '/script.js';
|
15
|
+
script.async = true;
|
16
|
+
script.defer = true;
|
17
|
+
// Configure Umami properties
|
18
|
+
script.setAttribute('data-website-id', umamiKey);
|
19
|
+
script.setAttribute('data-domains', 'localhost'); // TODO ?
|
20
|
+
script.setAttribute('data-auto-track', 'false');
|
21
|
+
script.setAttribute('data-host-url', hostUrl); // TODO ?
|
22
|
+
script.setAttribute('data-exclude-search', 'false'); // TODO ?
|
23
|
+
document.body.appendChild(script);
|
24
|
+
}
|
25
|
+
identify(userID) {
|
26
|
+
var _a;
|
27
|
+
// eslint-disable-next-line no-console
|
28
|
+
console.log('UmamiProvider userID: ' + userID);
|
29
|
+
(_a = window.umami) === null || _a === void 0 ? void 0 : _a.identify({ userID });
|
30
|
+
}
|
31
|
+
trackPageView(url) {
|
32
|
+
var _a;
|
33
|
+
// eslint-disable-next-line no-console
|
34
|
+
console.log('UmamiProvider url', url);
|
35
|
+
(_a = window.umami) === null || _a === void 0 ? void 0 : _a.track({ url });
|
36
|
+
}
|
37
|
+
trackSingleItem(item, properties) {
|
38
|
+
var _a;
|
39
|
+
// eslint-disable-next-line no-console
|
40
|
+
console.log('UmamiProvider: trackSingleItem' + item, properties);
|
41
|
+
(_a = window.umami) === null || _a === void 0 ? void 0 : _a.track(item, properties);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
exports.UmamiTrackingProvider = UmamiTrackingProvider;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"main":"../../cjs/tracking/index.js","module":"../../esm/tracking/index.js","typings":"../../esm/tracking/index.d.ts"}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
// ============================================================================
|
2
|
+
// Chatbot Main - Message - Content - Error
|
3
|
+
// ============================================================================
|
4
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
5
|
+
var t = {};
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
7
|
+
t[p] = s[p];
|
8
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
9
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
10
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
11
|
+
t[p[i]] = s[p[i]];
|
12
|
+
}
|
13
|
+
return t;
|
14
|
+
};
|
15
|
+
import React from 'react';
|
16
|
+
import { Alert } from '@patternfly/react-core';
|
17
|
+
const ErrorMessage = (_a) => {
|
18
|
+
var { title, actionLinks, children } = _a, props = __rest(_a, ["title", "actionLinks", "children"]);
|
19
|
+
return (React.createElement(Alert, Object.assign({ isInline: true, variant: "danger", title: title, actionLinks: actionLinks }, props), children));
|
20
|
+
};
|
21
|
+
export default ErrorMessage;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React, { ReactNode } from 'react';
|
2
|
-
import { AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
2
|
+
import { AlertProps, AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
3
3
|
import { ActionProps } from '../ResponseActions/ResponseActions';
|
4
4
|
import { SourcesCardProps } from '../SourcesCard';
|
5
5
|
import { QuickStart, QuickstartAction } from './QuickStarts/types';
|
@@ -102,6 +102,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
102
102
|
additionalRehypePlugins?: PluggableList;
|
103
103
|
/** Whether to open links in message in new tab. */
|
104
104
|
openLinkInNewTab?: boolean;
|
105
|
+
/** Optional inline error message that can be displayed in the message */
|
106
|
+
error?: AlertProps;
|
105
107
|
}
|
106
108
|
export declare const MessageBase: React.FunctionComponent<MessageProps>;
|
107
109
|
declare const Message: React.ForwardRefExoticComponent<Omit<MessageProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
@@ -40,8 +40,9 @@ import rehypeUnwrapImages from 'rehype-unwrap-images';
|
|
40
40
|
import rehypeExternalLinks from 'rehype-external-links';
|
41
41
|
import rehypeSanitize from 'rehype-sanitize';
|
42
42
|
import LinkMessage from './LinkMessage/LinkMessage';
|
43
|
+
import ErrorMessage from './ErrorMessage/ErrorMessage';
|
43
44
|
export const MessageBase = (_a) => {
|
44
|
-
var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [] } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins"]);
|
45
|
+
var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], error } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "error"]);
|
45
46
|
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
46
47
|
let rehypePlugins = [rehypeUnwrapImages];
|
47
48
|
if (openLinkInNewTab) {
|
@@ -71,7 +72,7 @@ export const MessageBase = (_a) => {
|
|
71
72
|
React.createElement("div", { className: "pf-chatbot__message-and-actions" },
|
72
73
|
isLoading ? (React.createElement(MessageLoading, { loadingWord: loadingWord })) : (React.createElement(React.Fragment, null,
|
73
74
|
beforeMainContent && React.createElement(React.Fragment, null, beforeMainContent),
|
74
|
-
React.createElement(Markdown, { components: {
|
75
|
+
error ? (React.createElement(ErrorMessage, Object.assign({}, error))) : (React.createElement(Markdown, { components: {
|
75
76
|
p: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.p }, props)),
|
76
77
|
code: (_a) => {
|
77
78
|
var { children } = _a, props = __rest(_a, ["children"]);
|
@@ -100,7 +101,7 @@ export const MessageBase = (_a) => {
|
|
100
101
|
th: (props) => React.createElement(ThMessage, Object.assign({}, props)),
|
101
102
|
img: (props) => React.createElement(ImageMessage, Object.assign({}, props)),
|
102
103
|
a: (props) => (React.createElement(LinkMessage, { href: props.href, rel: props.rel, target: props.target }, props.children))
|
103
|
-
}, remarkPlugins: [remarkGfm], rehypePlugins: rehypePlugins }, content),
|
104
|
+
}, remarkPlugins: [remarkGfm], rehypePlugins: rehypePlugins }, content)),
|
104
105
|
afterMainContent && React.createElement(React.Fragment, null, afterMainContent))),
|
105
106
|
!isLoading && sources && React.createElement(SourcesCard, Object.assign({}, sources)),
|
106
107
|
quickStarts && quickStarts.quickStart && (React.createElement(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel })),
|
@@ -15,6 +15,7 @@ import userEvent from '@testing-library/user-event';
|
|
15
15
|
import { monitorSampleAppQuickStart } from './QuickStarts/monitor-sampleapp-quickstart';
|
16
16
|
import { monitorSampleAppQuickStartWithImage } from './QuickStarts/monitor-sampleapp-quickstart-with-image';
|
17
17
|
import rehypeExternalLinks from '../__mocks__/rehype-external-links';
|
18
|
+
import { AlertActionLink } from '@patternfly/react-core';
|
18
19
|
const ALL_ACTIONS = [
|
19
20
|
{ label: /Good response/i },
|
20
21
|
{ label: /Bad response/i },
|
@@ -134,6 +135,13 @@ const EMPTY_TABLE = `
|
|
134
135
|
|
135
136
|
`;
|
136
137
|
const IMAGE = ``;
|
138
|
+
const ERROR = {
|
139
|
+
title: 'Could not load chat',
|
140
|
+
children: 'Wait a few minutes and check your network settings. If the issue persists: ',
|
141
|
+
actionLinks: (React.createElement(React.Fragment, null,
|
142
|
+
React.createElement(AlertActionLink, { component: "a", href: "#" }, "Start a new chat"),
|
143
|
+
React.createElement(AlertActionLink, { component: "a", href: "#" }, "Contact support")))
|
144
|
+
};
|
137
145
|
const checkListItemsRendered = () => {
|
138
146
|
const items = ['Item 1', 'Item 2', 'Item 3'];
|
139
147
|
expect(screen.getAllByRole('listitem')).toHaveLength(3);
|
@@ -589,4 +597,21 @@ describe('Message', () => {
|
|
589
597
|
// we are mocking rehype libraries, so we can't test target _blank addition on links directly with RTL
|
590
598
|
expect(rehypeExternalLinks).not.toHaveBeenCalled();
|
591
599
|
});
|
600
|
+
it('should handle error correctly', () => {
|
601
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", error: ERROR }));
|
602
|
+
expect(screen.getByRole('heading', { name: /Could not load chat/i })).toBeTruthy();
|
603
|
+
expect(screen.getByRole('link', { name: /Start a new chat/i })).toBeTruthy();
|
604
|
+
expect(screen.getByRole('link', { name: /Contact support/i })).toBeTruthy();
|
605
|
+
expect(screen.getByText('Wait a few minutes and check your network settings. If the issue persists:')).toBeTruthy();
|
606
|
+
});
|
607
|
+
it('should handle error correctly when loading', () => {
|
608
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", error: ERROR, isLoading: true }));
|
609
|
+
expect(screen.queryByRole('heading', { name: /Could not load chat/i })).toBeFalsy();
|
610
|
+
expect(screen.getByText('Loading message')).toBeTruthy();
|
611
|
+
});
|
612
|
+
it('should handle error correctly when these is content', () => {
|
613
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", error: ERROR, content: "Test" }));
|
614
|
+
expect(screen.getByRole('heading', { name: /Could not load chat/i })).toBeTruthy();
|
615
|
+
expect(screen.queryByText('Test')).toBeFalsy();
|
616
|
+
});
|
592
617
|
});
|