@servicetitan/titan-chatbot-ui 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/README.md +15 -0
  3. package/dist/components/chatbot/__tests-cy__/chatbot-help-center.test.d.ts +2 -0
  4. package/dist/components/chatbot/__tests-cy__/chatbot-help-center.test.d.ts.map +1 -0
  5. package/dist/components/chatbot/__tests-cy__/chatbot-help-center.test.js +160 -0
  6. package/dist/components/chatbot/__tests-cy__/chatbot-help-center.test.js.map +1 -0
  7. package/dist/components/chatbot/__tests-cy__/chatbot-live.test.d.ts +2 -0
  8. package/dist/components/chatbot/__tests-cy__/chatbot-live.test.d.ts.map +1 -0
  9. package/dist/components/chatbot/__tests-cy__/chatbot-live.test.js +90 -0
  10. package/dist/components/chatbot/__tests-cy__/chatbot-live.test.js.map +1 -0
  11. package/dist/components/chatbot/__tests-cy__/chatbot-titan-chatbot.test.d.ts +2 -0
  12. package/dist/components/chatbot/__tests-cy__/chatbot-titan-chatbot.test.d.ts.map +1 -0
  13. package/dist/components/chatbot/__tests-cy__/chatbot-titan-chatbot.test.js +155 -0
  14. package/dist/components/chatbot/__tests-cy__/chatbot-titan-chatbot.test.js.map +1 -0
  15. package/dist/components/chatbot/__tests-cy__/chatbot.test.d.ts +2 -0
  16. package/dist/components/chatbot/__tests-cy__/chatbot.test.d.ts.map +1 -0
  17. package/dist/components/chatbot/__tests-cy__/chatbot.test.js +139 -0
  18. package/dist/components/chatbot/__tests-cy__/chatbot.test.js.map +1 -0
  19. package/dist/components/chatbot/chatbot-to-chat-provider-adapter.d.ts +6 -0
  20. package/dist/components/chatbot/chatbot-to-chat-provider-adapter.d.ts.map +1 -0
  21. package/dist/components/chatbot/chatbot-to-chat-provider-adapter.js +21 -0
  22. package/dist/components/chatbot/chatbot-to-chat-provider-adapter.js.map +1 -0
  23. package/dist/components/chatbot/chatbot.d.ts +9 -0
  24. package/dist/components/chatbot/chatbot.d.ts.map +1 -0
  25. package/dist/components/chatbot/chatbot.js +68 -0
  26. package/dist/components/chatbot/chatbot.js.map +1 -0
  27. package/dist/components/chatbot/dialog/chatbot-restart-dialog.d.ts +6 -0
  28. package/dist/components/chatbot/dialog/chatbot-restart-dialog.d.ts.map +1 -0
  29. package/dist/components/chatbot/dialog/chatbot-restart-dialog.js +20 -0
  30. package/dist/components/chatbot/dialog/chatbot-restart-dialog.js.map +1 -0
  31. package/dist/components/chatbot/dialog/chatbot-restart-link.d.ts +4 -0
  32. package/dist/components/chatbot/dialog/chatbot-restart-link.d.ts.map +1 -0
  33. package/dist/components/chatbot/dialog/chatbot-restart-link.js +13 -0
  34. package/dist/components/chatbot/dialog/chatbot-restart-link.js.map +1 -0
  35. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form-guardrail.test.d.ts +2 -0
  36. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form-guardrail.test.d.ts.map +1 -0
  37. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form-guardrail.test.js +65 -0
  38. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form-guardrail.test.js.map +1 -0
  39. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form.test.d.ts +2 -0
  40. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form.test.d.ts.map +1 -0
  41. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form.test.js +100 -0
  42. package/dist/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form.test.js.map +1 -0
  43. package/dist/components/chatbot/feedback/chatbot-message-feedback-form-guardrail.d.ts +3 -0
  44. package/dist/components/chatbot/feedback/chatbot-message-feedback-form-guardrail.d.ts.map +1 -0
  45. package/dist/components/chatbot/feedback/chatbot-message-feedback-form-guardrail.js +13 -0
  46. package/dist/components/chatbot/feedback/chatbot-message-feedback-form-guardrail.js.map +1 -0
  47. package/dist/components/chatbot/feedback/chatbot-message-feedback-form.d.ts +3 -0
  48. package/dist/components/chatbot/feedback/chatbot-message-feedback-form.d.ts.map +1 -0
  49. package/dist/components/chatbot/feedback/chatbot-message-feedback-form.js +12 -0
  50. package/dist/components/chatbot/feedback/chatbot-message-feedback-form.js.map +1 -0
  51. package/dist/components/chatbot/feedback/chatbot-message-feedback-form.module.less +15 -0
  52. package/dist/components/chatbot/feedback/chatbot-message-feedback-popover.d.ts +9 -0
  53. package/dist/components/chatbot/feedback/chatbot-message-feedback-popover.d.ts.map +1 -0
  54. package/dist/components/chatbot/feedback/chatbot-message-feedback-popover.js +60 -0
  55. package/dist/components/chatbot/feedback/chatbot-message-feedback-popover.js.map +1 -0
  56. package/dist/components/chatbot/feedback/chatbot-message-feedback-popover.module.less +10 -0
  57. package/dist/components/chatbot/feedback/chatbot-message-feedback.d.ts +9 -0
  58. package/dist/components/chatbot/feedback/chatbot-message-feedback.d.ts.map +1 -0
  59. package/dist/components/chatbot/feedback/chatbot-message-feedback.js +17 -0
  60. package/dist/components/chatbot/feedback/chatbot-message-feedback.js.map +1 -0
  61. package/dist/components/chatbot/feedback/chatbot-session-feedback-link.d.ts +4 -0
  62. package/dist/components/chatbot/feedback/chatbot-session-feedback-link.d.ts.map +1 -0
  63. package/dist/components/chatbot/feedback/chatbot-session-feedback-link.js +16 -0
  64. package/dist/components/chatbot/feedback/chatbot-session-feedback-link.js.map +1 -0
  65. package/dist/components/chatbot/feedback/chatbot-session-feedback-modal.d.ts +5 -0
  66. package/dist/components/chatbot/feedback/chatbot-session-feedback-modal.d.ts.map +1 -0
  67. package/dist/components/chatbot/feedback/chatbot-session-feedback-modal.js +24 -0
  68. package/dist/components/chatbot/feedback/chatbot-session-feedback-modal.js.map +1 -0
  69. package/dist/components/chatbot/filters/chatbot-filter.d.ts +8 -0
  70. package/dist/components/chatbot/filters/chatbot-filter.d.ts.map +1 -0
  71. package/dist/components/chatbot/filters/chatbot-filter.js +61 -0
  72. package/dist/components/chatbot/filters/chatbot-filter.js.map +1 -0
  73. package/dist/components/chatbot/filters/chatbot-filter.module.css +19 -0
  74. package/dist/components/chatbot/filters/chatbot-filters.d.ts +5 -0
  75. package/dist/components/chatbot/filters/chatbot-filters.d.ts.map +1 -0
  76. package/dist/components/chatbot/filters/chatbot-filters.js +11 -0
  77. package/dist/components/chatbot/filters/chatbot-filters.js.map +1 -0
  78. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-answer.test.d.ts +2 -0
  79. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-answer.test.d.ts.map +1 -0
  80. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-answer.test.js +85 -0
  81. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-answer.test.js.map +1 -0
  82. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-typing.test.d.ts +2 -0
  83. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-typing.test.d.ts.map +1 -0
  84. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-typing.test.js +57 -0
  85. package/dist/components/chatbot/messages/__tests-cy__/chatbot-message-typing.test.js.map +1 -0
  86. package/dist/components/chatbot/messages/chatbot-links.d.ts +15 -0
  87. package/dist/components/chatbot/messages/chatbot-links.d.ts.map +1 -0
  88. package/dist/components/chatbot/messages/chatbot-links.js +21 -0
  89. package/dist/components/chatbot/messages/chatbot-links.js.map +1 -0
  90. package/dist/components/chatbot/messages/chatbot-links.module.less +22 -0
  91. package/dist/components/chatbot/messages/chatbot-message-agent-footer.d.ts +8 -0
  92. package/dist/components/chatbot/messages/chatbot-message-agent-footer.d.ts.map +1 -0
  93. package/dist/components/chatbot/messages/chatbot-message-agent-footer.js +13 -0
  94. package/dist/components/chatbot/messages/chatbot-message-agent-footer.js.map +1 -0
  95. package/dist/components/chatbot/messages/chatbot-message-answer-readonly.d.ts +6 -0
  96. package/dist/components/chatbot/messages/chatbot-message-answer-readonly.d.ts.map +1 -0
  97. package/dist/components/chatbot/messages/chatbot-message-answer-readonly.js +17 -0
  98. package/dist/components/chatbot/messages/chatbot-message-answer-readonly.js.map +1 -0
  99. package/dist/components/chatbot/messages/chatbot-message-answer.d.ts +6 -0
  100. package/dist/components/chatbot/messages/chatbot-message-answer.d.ts.map +1 -0
  101. package/dist/components/chatbot/messages/chatbot-message-answer.js +29 -0
  102. package/dist/components/chatbot/messages/chatbot-message-answer.js.map +1 -0
  103. package/dist/components/chatbot/messages/chatbot-message-answer.module.less +3 -0
  104. package/dist/components/chatbot/messages/chatbot-message-timeout.d.ts +6 -0
  105. package/dist/components/chatbot/messages/chatbot-message-timeout.d.ts.map +1 -0
  106. package/dist/components/chatbot/messages/chatbot-message-timeout.js +17 -0
  107. package/dist/components/chatbot/messages/chatbot-message-timeout.js.map +1 -0
  108. package/dist/components/chatbot/messages/chatbot-message-typing.d.ts +8 -0
  109. package/dist/components/chatbot/messages/chatbot-message-typing.d.ts.map +1 -0
  110. package/dist/components/chatbot/messages/chatbot-message-typing.js +27 -0
  111. package/dist/components/chatbot/messages/chatbot-message-typing.js.map +1 -0
  112. package/dist/components/chatbot/messages/chatbot-message-welcome.d.ts +3 -0
  113. package/dist/components/chatbot/messages/chatbot-message-welcome.d.ts.map +1 -0
  114. package/dist/components/chatbot/messages/chatbot-message-welcome.js +4 -0
  115. package/dist/components/chatbot/messages/chatbot-message-welcome.js.map +1 -0
  116. package/dist/components/chatbot/templates/chatbot-message-template-agent-readonly.d.ts +6 -0
  117. package/dist/components/chatbot/templates/chatbot-message-template-agent-readonly.d.ts.map +1 -0
  118. package/dist/components/chatbot/templates/chatbot-message-template-agent-readonly.js +12 -0
  119. package/dist/components/chatbot/templates/chatbot-message-template-agent-readonly.js.map +1 -0
  120. package/dist/components/chatbot/templates/chatbot-message-template-agent.d.ts +6 -0
  121. package/dist/components/chatbot/templates/chatbot-message-template-agent.d.ts.map +1 -0
  122. package/dist/components/chatbot/templates/chatbot-message-template-agent.js +10 -0
  123. package/dist/components/chatbot/templates/chatbot-message-template-agent.js.map +1 -0
  124. package/dist/components/chatbot/templates/chatbot-message-template-user-readonly.d.ts +6 -0
  125. package/dist/components/chatbot/templates/chatbot-message-template-user-readonly.d.ts.map +1 -0
  126. package/dist/components/chatbot/templates/chatbot-message-template-user-readonly.js +7 -0
  127. package/dist/components/chatbot/templates/chatbot-message-template-user-readonly.js.map +1 -0
  128. package/dist/index.d.ts +6 -0
  129. package/dist/index.d.ts.map +1 -0
  130. package/dist/index.js +6 -0
  131. package/dist/index.js.map +1 -0
  132. package/dist/stores/__tests__/message-feedback-guardrail.store.test.d.ts +2 -0
  133. package/dist/stores/__tests__/message-feedback-guardrail.store.test.d.ts.map +1 -0
  134. package/dist/stores/__tests__/message-feedback-guardrail.store.test.js +49 -0
  135. package/dist/stores/__tests__/message-feedback-guardrail.store.test.js.map +1 -0
  136. package/dist/stores/__tests__/message-feedback.store.test.d.ts +2 -0
  137. package/dist/stores/__tests__/message-feedback.store.test.d.ts.map +1 -0
  138. package/dist/stores/__tests__/message-feedback.store.test.js +114 -0
  139. package/dist/stores/__tests__/message-feedback.store.test.js.map +1 -0
  140. package/dist/stores/__tests__/session-feedback.store.test.d.ts +2 -0
  141. package/dist/stores/__tests__/session-feedback.store.test.d.ts.map +1 -0
  142. package/dist/stores/__tests__/session-feedback.store.test.js +39 -0
  143. package/dist/stores/__tests__/session-feedback.store.test.js.map +1 -0
  144. package/dist/stores/message-feedback-base.store.d.ts +8 -0
  145. package/dist/stores/message-feedback-base.store.d.ts.map +1 -0
  146. package/dist/stores/message-feedback-base.store.js +2 -0
  147. package/dist/stores/message-feedback-base.store.js.map +1 -0
  148. package/dist/stores/message-feedback-guardrail.store.d.ts +16 -0
  149. package/dist/stores/message-feedback-guardrail.store.d.ts.map +1 -0
  150. package/dist/stores/message-feedback-guardrail.store.js +85 -0
  151. package/dist/stores/message-feedback-guardrail.store.js.map +1 -0
  152. package/dist/stores/message-feedback.store.d.ts +23 -0
  153. package/dist/stores/message-feedback.store.d.ts.map +1 -0
  154. package/dist/stores/message-feedback.store.js +145 -0
  155. package/dist/stores/message-feedback.store.js.map +1 -0
  156. package/dist/stores/session-feedback.store.d.ts +15 -0
  157. package/dist/stores/session-feedback.store.d.ts.map +1 -0
  158. package/dist/stores/session-feedback.store.js +75 -0
  159. package/dist/stores/session-feedback.store.js.map +1 -0
  160. package/dist/utils/__tests__/axios-utils.test.d.ts +2 -0
  161. package/dist/utils/__tests__/axios-utils.test.d.ts.map +1 -0
  162. package/dist/utils/__tests__/axios-utils.test.js +33 -0
  163. package/dist/utils/__tests__/axios-utils.test.js.map +1 -0
  164. package/dist/utils/axios-utils.d.ts +5 -0
  165. package/dist/utils/axios-utils.d.ts.map +1 -0
  166. package/dist/utils/axios-utils.js +23 -0
  167. package/dist/utils/axios-utils.js.map +1 -0
  168. package/dist/utils/test-utils.d.ts +5 -0
  169. package/dist/utils/test-utils.d.ts.map +1 -0
  170. package/dist/utils/test-utils.js +17 -0
  171. package/dist/utils/test-utils.js.map +1 -0
  172. package/package.json +59 -0
  173. package/src/components/chatbot/__tests-cy__/chatbot-help-center.test.tsx +210 -0
  174. package/src/components/chatbot/__tests-cy__/chatbot-live.test.tsx +120 -0
  175. package/src/components/chatbot/__tests-cy__/chatbot-titan-chatbot.test.tsx +206 -0
  176. package/src/components/chatbot/__tests-cy__/chatbot.test.tsx +181 -0
  177. package/src/components/chatbot/chatbot-to-chat-provider-adapter.tsx +36 -0
  178. package/src/components/chatbot/chatbot.tsx +95 -0
  179. package/src/components/chatbot/dialog/chatbot-restart-dialog.tsx +36 -0
  180. package/src/components/chatbot/dialog/chatbot-restart-link.tsx +26 -0
  181. package/src/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form-guardrail.test.tsx +89 -0
  182. package/src/components/chatbot/feedback/__tests-cy__/chatbot-message-feedback-form.test.tsx +131 -0
  183. package/src/components/chatbot/feedback/chatbot-message-feedback-form-guardrail.tsx +35 -0
  184. package/src/components/chatbot/feedback/chatbot-message-feedback-form.module.less +15 -0
  185. package/src/components/chatbot/feedback/chatbot-message-feedback-form.module.less.d.ts +4 -0
  186. package/src/components/chatbot/feedback/chatbot-message-feedback-form.tsx +65 -0
  187. package/src/components/chatbot/feedback/chatbot-message-feedback-popover.module.less +10 -0
  188. package/src/components/chatbot/feedback/chatbot-message-feedback-popover.module.less.d.ts +4 -0
  189. package/src/components/chatbot/feedback/chatbot-message-feedback-popover.tsx +200 -0
  190. package/src/components/chatbot/feedback/chatbot-message-feedback.tsx +27 -0
  191. package/src/components/chatbot/feedback/chatbot-session-feedback-link.tsx +29 -0
  192. package/src/components/chatbot/feedback/chatbot-session-feedback-modal.tsx +96 -0
  193. package/src/components/chatbot/filters/chatbot-filter.module.css +19 -0
  194. package/src/components/chatbot/filters/chatbot-filter.module.css.d.ts +5 -0
  195. package/src/components/chatbot/filters/chatbot-filter.tsx +160 -0
  196. package/src/components/chatbot/filters/chatbot-filters.tsx +17 -0
  197. package/src/components/chatbot/messages/__tests-cy__/chatbot-message-answer.test.tsx +110 -0
  198. package/src/components/chatbot/messages/__tests-cy__/chatbot-message-typing.test.tsx +71 -0
  199. package/src/components/chatbot/messages/chatbot-links.module.less +22 -0
  200. package/src/components/chatbot/messages/chatbot-links.module.less.d.ts +4 -0
  201. package/src/components/chatbot/messages/chatbot-links.tsx +76 -0
  202. package/src/components/chatbot/messages/chatbot-message-agent-footer.tsx +35 -0
  203. package/src/components/chatbot/messages/chatbot-message-answer-readonly.tsx +39 -0
  204. package/src/components/chatbot/messages/chatbot-message-answer.module.less +3 -0
  205. package/src/components/chatbot/messages/chatbot-message-answer.module.less.d.ts +3 -0
  206. package/src/components/chatbot/messages/chatbot-message-answer.tsx +55 -0
  207. package/src/components/chatbot/messages/chatbot-message-timeout.tsx +20 -0
  208. package/src/components/chatbot/messages/chatbot-message-typing.tsx +39 -0
  209. package/src/components/chatbot/messages/chatbot-message-welcome.tsx +16 -0
  210. package/src/components/chatbot/templates/chatbot-message-template-agent-readonly.tsx +25 -0
  211. package/src/components/chatbot/templates/chatbot-message-template-agent.tsx +25 -0
  212. package/src/components/chatbot/templates/chatbot-message-template-user-readonly.tsx +16 -0
  213. package/src/cypress.d.ts +10 -0
  214. package/src/index.ts +5 -0
  215. package/src/stores/__tests__/message-feedback-guardrail.store.test.ts +61 -0
  216. package/src/stores/__tests__/message-feedback.store.test.ts +121 -0
  217. package/src/stores/__tests__/session-feedback.store.test.ts +47 -0
  218. package/src/stores/message-feedback-base.store.ts +8 -0
  219. package/src/stores/message-feedback-guardrail.store.ts +60 -0
  220. package/src/stores/message-feedback.store.ts +113 -0
  221. package/src/stores/session-feedback.store.ts +44 -0
  222. package/src/utils/__tests__/axios-utils.test.ts +40 -0
  223. package/src/utils/axios-utils.ts +25 -0
  224. package/src/utils/test-utils.ts +22 -0
  225. package/tsconfig.json +25 -0
  226. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,65 @@
1
+ import { BodyText, Form } from '@servicetitan/design-system';
2
+ import { useDependencies } from '@servicetitan/react-ioc';
3
+ import classNames from 'classnames';
4
+ import { observer } from 'mobx-react';
5
+ import { FC } from 'react';
6
+ import { MessageFeedbackStore } from '../../../stores/message-feedback.store';
7
+ import * as Styles from './chatbot-message-feedback-form.module.less';
8
+
9
+ export const ChatbotMessageFeedbackForm: FC = observer(() => {
10
+ const [store] = useDependencies(MessageFeedbackStore);
11
+ return (
12
+ <Form data-cy="titan-chatbot-message-feedback-form">
13
+ <Form.Checkbox
14
+ label="Answer is unrelated to my question"
15
+ className={Styles.formItem}
16
+ value={store.formState.$.unrelated.value}
17
+ onChange={store.formState.$.unrelated.onChangeHandler}
18
+ data-cy="titan-chatbot-message-feedback-form-unrelated"
19
+ />
20
+ <Form.Checkbox
21
+ label="Answer is unclear, not sure what it means"
22
+ className={Styles.formItem}
23
+ value={store.formState.$.unclear.value}
24
+ onChange={store.formState.$.unclear.onChangeHandler}
25
+ data-cy="titan-chatbot-message-feedback-form-unclear"
26
+ />
27
+ <Form.Checkbox
28
+ label="Answer doesn’t fully address the question"
29
+ className={Styles.formItem}
30
+ value={store.formState.$.notFull.value}
31
+ onChange={store.formState.$.notFull.onChangeHandler}
32
+ data-cy="titan-chatbot-message-feedback-form-not-full"
33
+ />
34
+ <Form.Checkbox
35
+ label="Answer is incorrect or doesn’t work"
36
+ className={Styles.formItem}
37
+ value={store.formState.$.incorrect.value}
38
+ onChange={store.formState.$.incorrect.onChangeHandler}
39
+ data-cy="titan-chatbot-message-feedback-form-incorrect"
40
+ />
41
+ <Form.Checkbox
42
+ label="Other"
43
+ className={Styles.formItem}
44
+ value={store.formState.$.other.value}
45
+ onChange={store.formState.$.other.onChangeHandler}
46
+ data-cy="titan-chatbot-message-feedback-form-other"
47
+ />
48
+ {store.isTextAreaVisible && (
49
+ <div className="m-l-4">
50
+ <Form.TextArea
51
+ className={classNames(Styles.formItem, Styles.textArea)}
52
+ error={store.formState.$.otherComment.error}
53
+ value={store.formState.$.otherComment.value}
54
+ onChange={store.formState.$.otherComment.onChangeHandler}
55
+ onBlur={store.formState.$.otherComment.enableAutoValidationAndValidate}
56
+ data-cy="titan-chatbot-message-feedback-form-other-comment"
57
+ />
58
+ <BodyText size="small" className="c-neutral-100 m-b-1">
59
+ Tell us more about what can be improved.
60
+ </BodyText>
61
+ </div>
62
+ )}
63
+ </Form>
64
+ );
65
+ });
@@ -0,0 +1,10 @@
1
+ @import '@servicetitan/tokens/dist/tokens.less';
2
+
3
+ .feedback {
4
+ min-width: 200px;
5
+ max-width: 200px;
6
+ }
7
+
8
+ .feedbackResultText {
9
+ white-space: nowrap;
10
+ }
@@ -0,0 +1,4 @@
1
+ export const __esModule: true;
2
+ export const feedback: string;
3
+ export const feedbackResultText: string;
4
+
@@ -0,0 +1,200 @@
1
+ import {
2
+ BodyText,
3
+ Button,
4
+ ButtonGroup,
5
+ Eyebrow,
6
+ Headline,
7
+ Icon,
8
+ Link,
9
+ Popover,
10
+ Spinner,
11
+ Stack,
12
+ } from '@servicetitan/design-system';
13
+ import { provide, useDependencies } from '@servicetitan/react-ioc';
14
+ import { CHATBOT_UI_STORE_TOKEN, Models } from '@servicetitan/titan-chatbot-api';
15
+ import classNames from 'classnames';
16
+ import { observer } from 'mobx-react';
17
+ import { FC, useCallback, useState } from 'react';
18
+ import { IMessageFeedbackBaseStore } from '../../../stores/message-feedback-base.store';
19
+ import { MessageFeedbackGuardrailStore } from '../../../stores/message-feedback-guardrail.store';
20
+ import { MessageFeedbackStore } from '../../../stores/message-feedback.store';
21
+ import { ChatbotMessageFeedbackForm } from './chatbot-message-feedback-form';
22
+ import { ChatbotMessageFeedbackFormGuardrail } from './chatbot-message-feedback-form-guardrail';
23
+ import * as Styles from './chatbot-message-feedback-popover.module.less';
24
+
25
+ interface IChatbotMessageFeedbackProps {
26
+ botMessage: Models.IBotMessage;
27
+ className?: string;
28
+ }
29
+
30
+ export const ChatbotMessageFeedbackPopover: FC<IChatbotMessageFeedbackProps> = provide({
31
+ singletons: [MessageFeedbackStore, MessageFeedbackGuardrailStore],
32
+ })(
33
+ observer(({ botMessage, className }) => {
34
+ const [chatbotUiStore, messageFeedbackStore, messageFeedbackGuardrailStore] =
35
+ useDependencies(
36
+ CHATBOT_UI_STORE_TOKEN,
37
+ MessageFeedbackStore,
38
+ MessageFeedbackGuardrailStore
39
+ );
40
+ const [feedbackState, setFeedbackState] = useState<Models.ChatbotFeedbackState>(
41
+ Models.ChatbotFeedbackState.None
42
+ );
43
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
44
+ const title = chatbotUiStore.customizations.feedback?.title;
45
+ const isGuardrail = botMessage.isGuardrailed;
46
+ const feedbackStore: IMessageFeedbackBaseStore = isGuardrail
47
+ ? messageFeedbackGuardrailStore
48
+ : messageFeedbackStore;
49
+
50
+ const sendFeedback = useCallback(
51
+ async (feedback: Models.IFeedback) => {
52
+ setFeedbackState(Models.ChatbotFeedbackState.Sent);
53
+ try {
54
+ const result = await chatbotUiStore.sendMessageFeedback(botMessage, feedback);
55
+ setFeedbackState(result ?? Models.ChatbotFeedbackState.Success);
56
+ } catch {
57
+ setFeedbackState(Models.ChatbotFeedbackState.Failure);
58
+ }
59
+ },
60
+ [chatbotUiStore, botMessage]
61
+ );
62
+
63
+ const handleFeedbackThumbsUp = useCallback(async () => {
64
+ await sendFeedback(new Models.Feedback({ rating: Models.FeedbackRatings.ThumbsUp }));
65
+ }, [sendFeedback]);
66
+
67
+ const handleFeedbackSubmit = useCallback(async () => {
68
+ const validateResult = await feedbackStore.formState.validate();
69
+ if (validateResult.hasError) {
70
+ return;
71
+ }
72
+ const feedback = feedbackStore.export();
73
+ await sendFeedback(feedback);
74
+ }, [feedbackStore, sendFeedback]);
75
+
76
+ if (feedbackState === Models.ChatbotFeedbackState.Sent) {
77
+ return (
78
+ <Stack
79
+ direction="row"
80
+ spacing="1"
81
+ alignItems="center"
82
+ className={classNames(className, Styles.feedback)}
83
+ data-cy="titan-chatbot-message-feedback-loading"
84
+ >
85
+ <Spinner size="tiny" />
86
+ </Stack>
87
+ );
88
+ }
89
+ if (feedbackState === Models.ChatbotFeedbackState.Success) {
90
+ return (
91
+ <Stack
92
+ direction="row"
93
+ spacing="1"
94
+ alignItems="center"
95
+ className={classNames(className, Styles.feedback)}
96
+ >
97
+ <Icon name="check" className="c-green-500" />
98
+ <BodyText
99
+ className={classNames('c-neutral-100', Styles.feedbackResultText)}
100
+ data-cy="titan-chatbot-message-feedback-success"
101
+ >
102
+ Thanks for your feedback.
103
+ </BodyText>
104
+ </Stack>
105
+ );
106
+ }
107
+ if (feedbackState === Models.ChatbotFeedbackState.Failure) {
108
+ // Feedback is done: either user clicked thumbs up or submitted feedback
109
+ return (
110
+ <Stack
111
+ direction="row"
112
+ spacing="1"
113
+ alignItems="center"
114
+ className={classNames(className, Styles.feedback)}
115
+ data-cy="titan-chatbot-message-feedback-failed"
116
+ >
117
+ <Icon name="error" className="c-red-500" />
118
+ <BodyText className={classNames('c-red-100', Styles.feedbackResultText)}>
119
+ Failed to send feedback.
120
+ </BodyText>
121
+ </Stack>
122
+ );
123
+ }
124
+ return (
125
+ <Stack direction="row" spacing="1" alignItems="center" className={className}>
126
+ {!isGuardrail && title && <Eyebrow>{title}</Eyebrow>}
127
+ {!isGuardrail && (
128
+ <Button
129
+ iconName="thumb_up"
130
+ xsmall
131
+ fill="subtle"
132
+ aria-label="thumb up"
133
+ onClick={handleFeedbackThumbsUp}
134
+ data-cy="titan-chatbot-message-feedback-thumbs-up"
135
+ />
136
+ )}
137
+ <Popover
138
+ trigger={
139
+ isGuardrail ? (
140
+ <Link
141
+ onClick={() => setIsPopoverOpen(true)}
142
+ className="fs-1 tt-uppercase"
143
+ color="blue"
144
+ data-cy="titan-chatbot-message-feedback-provide-answer"
145
+ >
146
+ Provide correct answer
147
+ </Link>
148
+ ) : (
149
+ <Button
150
+ iconName="thumb_down"
151
+ xsmall
152
+ fill="subtle"
153
+ onClick={() => setIsPopoverOpen(true)}
154
+ aria-label="thumb down"
155
+ data-cy="titan-chatbot-message-feedback-thumbs-down"
156
+ />
157
+ )
158
+ }
159
+ header={
160
+ <Stack justifyContent="space-between" alignItems="center" className="w-100">
161
+ <Headline size="small">
162
+ {isGuardrail
163
+ ? 'Provide correct answer'
164
+ : 'Why didn’t this answer solve your problem?'}
165
+ </Headline>
166
+ </Stack>
167
+ }
168
+ onClickOutside={() => setIsPopoverOpen(false)}
169
+ headerAlign="space-between"
170
+ footer={
171
+ <ButtonGroup>
172
+ <Button
173
+ primary
174
+ disabled={!feedbackStore.isValid}
175
+ onClick={handleFeedbackSubmit}
176
+ data-cy="titan-chatbot-message-feedback-submit"
177
+ >
178
+ Submit
179
+ </Button>
180
+ </ButtonGroup>
181
+ }
182
+ className="feedback-form-popover-body"
183
+ footerAlign="right"
184
+ direction="tr"
185
+ width="m"
186
+ padding="m"
187
+ autoFlipVertically
188
+ autoFlipHorizontally
189
+ open={isPopoverOpen}
190
+ >
191
+ {isGuardrail ? (
192
+ <ChatbotMessageFeedbackFormGuardrail />
193
+ ) : (
194
+ <ChatbotMessageFeedbackForm />
195
+ )}
196
+ </Popover>
197
+ </Stack>
198
+ );
199
+ })
200
+ );
@@ -0,0 +1,27 @@
1
+ import { useDependencies } from '@servicetitan/react-ioc';
2
+ import { CHATBOT_UI_STORE_TOKEN, Models } from '@servicetitan/titan-chatbot-api';
3
+ import { observer } from 'mobx-react';
4
+ import { FC } from 'react';
5
+ import { ChatbotMessageFeedbackPopover } from './chatbot-message-feedback-popover';
6
+
7
+ interface IChatbotFeedbackProps {
8
+ botMessage: Models.IBotMessage;
9
+ className?: string;
10
+ }
11
+
12
+ export const ChatbotMessageFeedback: FC<IChatbotFeedbackProps> = observer(
13
+ ({ botMessage, className }) => {
14
+ const [chatbotUiStore] = useDependencies(CHATBOT_UI_STORE_TOKEN);
15
+
16
+ // We show feedback for all messages with normal answer and for guardrailed messages if internal chatbot setting is enabled
17
+ const showGuardrailFeedback = Boolean(
18
+ chatbotUiStore.customizations?.feedback?.showGuardrailFeedback
19
+ );
20
+ const isFeedbackVisible = showGuardrailFeedback || !botMessage.isGuardrailed;
21
+
22
+ if (!isFeedbackVisible) {
23
+ return null;
24
+ }
25
+ return <ChatbotMessageFeedbackPopover className={className} botMessage={botMessage} />;
26
+ }
27
+ );
@@ -0,0 +1,29 @@
1
+ import { Link, LinkProps } from '@servicetitan/design-system';
2
+ import { FC, Fragment, useCallback, useState } from 'react';
3
+ import { ChatbotSessionFeedbackModal } from './chatbot-session-feedback-modal';
4
+
5
+ export const ChatbotSessionFeedbackLink: FC<LinkProps> = ({ children, onClick, ...rest }) => {
6
+ const [isFeedbackOpen, setIsFeedbackOpen] = useState(false);
7
+
8
+ const handleFeedbackOpen = useCallback(() => {
9
+ setIsFeedbackOpen(true);
10
+ onClick?.();
11
+ }, [onClick]);
12
+
13
+ const handleFeedback = useCallback(() => {
14
+ setIsFeedbackOpen(false);
15
+ }, []);
16
+
17
+ return (
18
+ <Fragment>
19
+ <Link
20
+ {...rest}
21
+ onClick={handleFeedbackOpen}
22
+ data-cy="titan-chatbot-session-feedback-link"
23
+ >
24
+ {children}
25
+ </Link>
26
+ {isFeedbackOpen && <ChatbotSessionFeedbackModal onClose={handleFeedback} />}
27
+ </Fragment>
28
+ );
29
+ };
@@ -0,0 +1,96 @@
1
+ import { BodyText, Button, ButtonGroup, Form, Modal, Stack } from '@servicetitan/design-system';
2
+ import { provide, useDependencies } from '@servicetitan/react-ioc';
3
+ import { CHATBOT_UI_STORE_TOKEN } from '@servicetitan/titan-chatbot-api';
4
+ import { observer } from 'mobx-react';
5
+ import { FC, useCallback } from 'react';
6
+ import { SessionFeedbackStore } from '../../../stores/session-feedback.store';
7
+
8
+ export const ChatbotSessionFeedbackModal: FC<{ onClose: () => void }> = provide({
9
+ singletons: [SessionFeedbackStore],
10
+ })(
11
+ observer(({ onClose }) => {
12
+ const [chatbotFeedbackStore, chatbotUiStore] = useDependencies(
13
+ SessionFeedbackStore,
14
+ CHATBOT_UI_STORE_TOKEN
15
+ );
16
+
17
+ const handleClose = useCallback(() => {
18
+ onClose();
19
+ }, [onClose]);
20
+
21
+ const handleSubmit = useCallback(() => {
22
+ chatbotUiStore.sendSessionFeedback(chatbotFeedbackStore.feedback);
23
+ onClose();
24
+ }, [chatbotUiStore, chatbotFeedbackStore, onClose]);
25
+
26
+ const handleThumbs = useCallback(
27
+ (isThumbsUp: boolean) => {
28
+ chatbotFeedbackStore.formState.$.thumbs.onChange(isThumbsUp ? 1 : -1);
29
+ },
30
+ [chatbotFeedbackStore]
31
+ );
32
+
33
+ return (
34
+ <Modal
35
+ onClose={handleClose}
36
+ open
37
+ title="Give Feedback on Titan"
38
+ size={Modal.Sizes.S}
39
+ footer={
40
+ <ButtonGroup>
41
+ <Button
42
+ onClick={handleClose}
43
+ data-cy="titan-chatbot-session-feedback-cancel"
44
+ >
45
+ Cancel
46
+ </Button>
47
+ <Button
48
+ onClick={handleSubmit}
49
+ primary
50
+ disabled={!chatbotFeedbackStore.isValid}
51
+ data-cy="titan-chatbot-session-feedback-submit"
52
+ >
53
+ Submit Feedback
54
+ </Button>
55
+ </ButtonGroup>
56
+ }
57
+ data-cy="titan-chatbot-session-feedback-modal"
58
+ >
59
+ <Stack direction="column" spacing="3">
60
+ <Stack direction="column" spacing="2">
61
+ <BodyText>Was Titan able to help solve your problem?</BodyText>
62
+ <ButtonGroup>
63
+ <Button
64
+ small
65
+ aria-label="Thumbs Up"
66
+ title="Thumbs Up"
67
+ iconName="thumb_up"
68
+ fill="outline"
69
+ selected={chatbotFeedbackStore.isThumbsUp}
70
+ onClick={() => handleThumbs(true)}
71
+ data-cy="titan-chatbot-session-feedback-thumbs-up"
72
+ />
73
+ <Button
74
+ small
75
+ fill="outline"
76
+ aria-label="Thumbs Down"
77
+ title="Thumbs Down"
78
+ selected={chatbotFeedbackStore.isThumbsDown}
79
+ iconName="thumb_down"
80
+ onClick={() => handleThumbs(false)}
81
+ data-cy="titan-chatbot-session-feedback-thumbs-down"
82
+ />
83
+ </ButtonGroup>
84
+ </Stack>
85
+ <Form.TextArea
86
+ label="Tell us more"
87
+ maxRows={3}
88
+ value={chatbotFeedbackStore.formState.$.comment.value}
89
+ onChange={chatbotFeedbackStore.formState.$.comment.onChangeHandler}
90
+ data-cy="titan-chatbot-session-feedback-comment"
91
+ />
92
+ </Stack>
93
+ </Modal>
94
+ );
95
+ })
96
+ );
@@ -0,0 +1,19 @@
1
+ @import '@servicetitan/tokens/dist/tokens.css';
2
+
3
+ .filterBottomButton {
4
+ padding-left: var(--spacing-half);
5
+ padding-right: var(--spacing-half);
6
+ }
7
+
8
+ .filterBottomText {
9
+ padding-right: var(--spacing-half);
10
+ }
11
+
12
+ .filterPopover {
13
+ :global(.Popover__header),
14
+ :global(.Popover__content),
15
+ :global(.Popover__footer) {
16
+ padding-left: var(--spacing-1);
17
+ padding-right: var(--spacing-1);
18
+ }
19
+ }
@@ -0,0 +1,5 @@
1
+ export const __esModule: true;
2
+ export const filterBottomButton: string;
3
+ export const filterBottomText: string;
4
+ export const filterPopover: string;
5
+
@@ -0,0 +1,160 @@
1
+ import {
2
+ BodyText,
3
+ Button,
4
+ FilterButton,
5
+ Input,
6
+ OptionList,
7
+ Popover,
8
+ Stack,
9
+ } from '@servicetitan/design-system';
10
+ import { useDependencies } from '@servicetitan/react-ioc';
11
+ import { CHATBOT_UI_STORE_TOKEN, Models } from '@servicetitan/titan-chatbot-api';
12
+ import classNames from 'classnames';
13
+ import { observer } from 'mobx-react';
14
+ import { ChangeEvent, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
+ import * as Style from './chatbot-filter.module.css';
16
+
17
+ interface IChatFilterProps {
18
+ filter: Models.IOption;
19
+ }
20
+
21
+ export const ChatFilter: FC<IChatFilterProps> = observer(({ filter }: IChatFilterProps) => {
22
+ const [filterText, setFilterText] = useState('');
23
+ const [open, setOpen] = useState(false);
24
+ const [listMaxHeight, setListMaxHeight] = useState(400);
25
+ const [{ filterStore }] = useDependencies(CHATBOT_UI_STORE_TOKEN);
26
+ const filterLabel = filterStore.getFilterLabel(filter.displayName ?? filter.key);
27
+ const triggerRef = useRef<HTMLDivElement>(null);
28
+
29
+ const allOptions = useMemo(() => {
30
+ return (
31
+ filter.subOptions?.map(filterSelectable => ({
32
+ text: filterStore.getFilterLabel(
33
+ filterSelectable.displayName ?? filterSelectable.key
34
+ ),
35
+ value: filterSelectable.key,
36
+ })) ?? []
37
+ );
38
+ }, [filterStore, filter.subOptions]);
39
+
40
+ const filteredOptions = useMemo(() => {
41
+ return allOptions.filter(
42
+ opt => opt.text && opt.text.toLowerCase().indexOf(filterText.toLowerCase()) > -1
43
+ );
44
+ }, [filterText, allOptions]);
45
+
46
+ useEffect(() => {
47
+ if (triggerRef.current) {
48
+ const triggerElement = triggerRef.current;
49
+ const boundingRect = triggerElement.getBoundingClientRect();
50
+ const headerFooterSize = 160;
51
+ setListMaxHeight(boundingRect.top - headerFooterSize);
52
+ }
53
+ }, []);
54
+
55
+ const handleToggle = () => {
56
+ setOpen(prev => !prev);
57
+ };
58
+
59
+ const handleCancel = () => {
60
+ setOpen(false);
61
+ };
62
+
63
+ const handleFilterChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
64
+ setFilterText(event.target.value);
65
+ }, []);
66
+
67
+ const handleItemChecked = useCallback(
68
+ (value: string, checked: boolean) => {
69
+ if (checked) {
70
+ filterStore.selectOption(filter.key, value);
71
+ } else {
72
+ filterStore.deselectOption(filter.key, value);
73
+ }
74
+ },
75
+ [filterStore, filter]
76
+ );
77
+
78
+ return (
79
+ <Popover
80
+ el="span"
81
+ direction="t"
82
+ padding="s"
83
+ onClickOutside={handleCancel}
84
+ open={open}
85
+ portal
86
+ className={classNames(Style.filterPopover)}
87
+ scrollHeight={`${listMaxHeight}px`}
88
+ header={
89
+ <Stack className={classNames('w-100 p-x-2 p-y-half')}>
90
+ <Input
91
+ onChange={handleFilterChange}
92
+ value={filterText}
93
+ size="small"
94
+ icon="search"
95
+ iconPosition="left"
96
+ placeholder="Search"
97
+ className="w-100"
98
+ data-cy="titan-chatbot-filter-search"
99
+ />
100
+ </Stack>
101
+ }
102
+ footer={
103
+ <Stack direction="row" className="w-100 p-l-2" alignItems="baseline">
104
+ <BodyText size="small" className={Style.filterBottomText}>
105
+ Select
106
+ </BodyText>
107
+ <Button
108
+ fill="subtle"
109
+ primary
110
+ xsmall
111
+ onClick={() => {
112
+ filterStore.selectAll(filter.key);
113
+ }}
114
+ className={Style.filterBottomButton}
115
+ data-cy="titan-chatbot-filter-all"
116
+ >
117
+ All
118
+ </Button>
119
+ <Button
120
+ fill="subtle"
121
+ primary
122
+ xsmall
123
+ onClick={() => {
124
+ filterStore.deselectAll(filter.key);
125
+ }}
126
+ className={Style.filterBottomButton}
127
+ data-cy="titan-chatbot-filter-none"
128
+ >
129
+ None
130
+ </Button>
131
+ </Stack>
132
+ }
133
+ trigger={
134
+ <FilterButton
135
+ ref={triggerRef}
136
+ onClick={handleToggle}
137
+ value={filterStore.selectedOptions[filter.key]?.length || undefined}
138
+ label={filterLabel}
139
+ expandIcon={open}
140
+ disabled={false}
141
+ data-cy="titan-chatbot-filter-button"
142
+ />
143
+ }
144
+ >
145
+ {allOptions.length > 0 ? (
146
+ <OptionList
147
+ multiple
148
+ options={filteredOptions}
149
+ onChange={handleItemChecked}
150
+ value={filterStore.selectedOptions[filter.key] || []}
151
+ data-cy="titan-chatbot-filter-options"
152
+ />
153
+ ) : (
154
+ <BodyText className="ta-center" size="small" subdued>
155
+ No items available
156
+ </BodyText>
157
+ )}
158
+ </Popover>
159
+ );
160
+ });
@@ -0,0 +1,17 @@
1
+ import { Stack } from '@servicetitan/design-system';
2
+ import { useDependencies } from '@servicetitan/react-ioc';
3
+ import { CHATBOT_UI_STORE_TOKEN } from '@servicetitan/titan-chatbot-api';
4
+ import { observer } from 'mobx-react';
5
+ import { FC } from 'react';
6
+ import { ChatFilter } from './chatbot-filter';
7
+
8
+ export const ChatFilters: FC<{ className?: string }> = observer(({ className }) => {
9
+ const [{ filterStore }] = useDependencies(CHATBOT_UI_STORE_TOKEN);
10
+ return filterStore.filters.length > 0 ? (
11
+ <Stack className={className} spacing="1" data-cy="titan-chatbot-filters">
12
+ {filterStore.filters.map(filter => (
13
+ <ChatFilter key={filter.key} filter={filter} />
14
+ ))}
15
+ </Stack>
16
+ ) : null;
17
+ });