cozy-search 2.0.11 → 2.1.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 (53) hide show
  1. package/dist/components/Assistant/AssistantAvatar.js +0 -2
  2. package/dist/components/Assistant/AssistantContainer.js +2 -19
  3. package/dist/components/Assistant/AssistantSelection.js +0 -2
  4. package/dist/components/Assistant/AssistantSelectionItem.js +0 -2
  5. package/dist/components/Assistant/styles.styl +0 -7
  6. package/dist/components/AssistantProvider.d.ts +0 -12
  7. package/dist/components/AssistantProvider.js +4 -22
  8. package/dist/components/Conversations/ConversationComposer.js +2 -4
  9. package/dist/components/CreateAssistantSteps/AssistantDialogContent.js +3 -1
  10. package/dist/components/CreateAssistantSteps/BasicInfoStep.d.ts +3 -1
  11. package/dist/components/CreateAssistantSteps/BasicInfoStep.js +9 -2
  12. package/dist/components/CreateAssistantSteps/useAssistantDialog.d.ts +2 -0
  13. package/dist/components/CreateAssistantSteps/useAssistantDialog.js +2 -1
  14. package/dist/components/KnowledgeBase/FolderPickerDialog.d.ts +10 -0
  15. package/dist/components/KnowledgeBase/FolderPickerDialog.js +112 -0
  16. package/dist/components/KnowledgeBase/KnowledgeBaseChip.d.ts +16 -0
  17. package/dist/components/KnowledgeBase/KnowledgeBaseChip.js +156 -0
  18. package/dist/components/KnowledgeBase/KnowledgeBaseSection.d.ts +5 -0
  19. package/dist/components/KnowledgeBase/KnowledgeBaseSection.js +173 -0
  20. package/dist/components/KnowledgeBase/knowledgeBase.d.ts +12 -0
  21. package/dist/components/KnowledgeBase/knowledgeBase.js +131 -0
  22. package/dist/components/KnowledgeBase/knowledgeBase.spec.d.ts +1 -0
  23. package/dist/components/KnowledgeBase/knowledgeBase.spec.js +177 -0
  24. package/dist/components/KnowledgeBase/styles.styl +12 -0
  25. package/dist/components/KnowledgeBase/useSelectedAssistantKnowledgeBase.d.ts +8 -0
  26. package/dist/components/KnowledgeBase/useSelectedAssistantKnowledgeBase.js +117 -0
  27. package/dist/components/TwakeKnowledges/TwakeKnowledgeChip.d.ts +9 -2
  28. package/dist/components/TwakeKnowledges/TwakeKnowledgeChip.js +20 -52
  29. package/dist/components/TwakeKnowledges/TwakeKnowledgeSelector.d.ts +2 -3
  30. package/dist/components/TwakeKnowledges/TwakeKnowledgeSelector.js +43 -24
  31. package/dist/components/TwakeKnowledges/styles.styl +0 -82
  32. package/dist/components/Views/CreateAssistantDialog.js +20 -4
  33. package/dist/components/Views/EditAssistantDialog.js +9 -2
  34. package/dist/components/queries.d.ts +9 -0
  35. package/dist/components/queries.js +17 -1
  36. package/dist/hooks/useConversation.spec.js +24 -13
  37. package/dist/hooks/useConversation.spec.jsx +27 -15
  38. package/dist/locales/en.json +10 -23
  39. package/dist/locales/fr.json +13 -26
  40. package/dist/locales/index.js +20 -58
  41. package/dist/locales/ru.json +0 -6
  42. package/dist/locales/vi.json +0 -6
  43. package/dist/stylesheet.css +12 -88
  44. package/package.json +4 -2
  45. package/dist/assets/tchat.png +0 -0
  46. package/dist/components/TwakeKnowledges/ChatKnowledge.d.ts +0 -6
  47. package/dist/components/TwakeKnowledges/ChatKnowledge.js +0 -107
  48. package/dist/components/TwakeKnowledges/DriveKnowledge.d.ts +0 -6
  49. package/dist/components/TwakeKnowledges/DriveKnowledge.js +0 -244
  50. package/dist/components/TwakeKnowledges/MailKnowledge.d.ts +0 -6
  51. package/dist/components/TwakeKnowledges/MailKnowledge.js +0 -264
  52. package/dist/components/TwakeKnowledges/TwakeKnowledgePanel.d.ts +0 -4
  53. package/dist/components/TwakeKnowledges/TwakeKnowledgePanel.js +0 -230
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+
12
+ var _react = _interopRequireWildcard(require("react"));
13
+
14
+ var _twakeIcons = require("@linagora/twake-icons");
15
+
16
+ var _cozyClient = require("cozy-client");
17
+
18
+ var _cozyFlags = _interopRequireDefault(require("cozy-flags"));
19
+
20
+ var _Buttons = _interopRequireDefault(require("cozy-ui/transpiled/react/Buttons"));
21
+
22
+ var _Chips = _interopRequireDefault(require("cozy-ui/transpiled/react/Chips"));
23
+
24
+ var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
25
+
26
+ var _twakeI18n = require("twake-i18n");
27
+
28
+ var _FolderPickerDialog = _interopRequireDefault(require("./FolderPickerDialog"));
29
+
30
+ var _knowledgeBase = require("./knowledgeBase");
31
+
32
+ var _tdrive = _interopRequireDefault(require("../../assets/tdrive.png"));
33
+
34
+ var _tmail = _interopRequireDefault(require("../../assets/tmail.png"));
35
+
36
+ var _queries = require("../queries");
37
+
38
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
39
+
40
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
41
+
42
+ var KnowledgeBaseSection = function KnowledgeBaseSection(_ref) {
43
+ var _folder$path, _folder$name;
44
+
45
+ var _ref$knowledgeBase = _ref.knowledgeBase,
46
+ knowledgeBase = _ref$knowledgeBase === void 0 ? [] : _ref$knowledgeBase,
47
+ onChange = _ref.onChange;
48
+
49
+ var _useI18n = (0, _twakeI18n.useI18n)(),
50
+ t = _useI18n.t;
51
+
52
+ var _useState = (0, _react.useState)(false),
53
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
54
+ isPickerOpen = _useState2[0],
55
+ setIsPickerOpen = _useState2[1];
56
+
57
+ var dirId = (0, _knowledgeBase.getKnowledgeBaseDirId)({
58
+ knowledgeBase: knowledgeBase
59
+ });
60
+ var hasEmail = (0, _knowledgeBase.hasEmailKnowledgeBase)({
61
+ knowledgeBase: knowledgeBase
62
+ });
63
+ var fileQuery = (0, _queries.buildFileByIdQuery)(dirId);
64
+
65
+ var _useQuery = (0, _cozyClient.useQuery)(fileQuery.definition, fileQuery.options),
66
+ folder = _useQuery.data,
67
+ fetchStatus = _useQuery.fetchStatus;
68
+
69
+ var isUnavailable = !!dirId && (fetchStatus === 'failed' || !!(folder !== null && folder !== void 0 && folder.trashed) || !!(folder !== null && folder !== void 0 && (_folder$path = folder.path) !== null && _folder$path !== void 0 && _folder$path.startsWith('/.cozy_trash')));
70
+ var showMail = (0, _cozyFlags.default)('cozy.assistant.source-knowledge.mail.enabled');
71
+
72
+ var handleSelectFolder = function handleSelectFolder(pickedFolder) {
73
+ return onChange((0, _knowledgeBase.withKnowledgeBaseEntry)(knowledgeBase, (0, _knowledgeBase.makeKnowledgeBaseEntry)(pickedFolder)));
74
+ };
75
+
76
+ var handleRemoveFolder = function handleRemoveFolder() {
77
+ return onChange((0, _knowledgeBase.withoutKnowledgeBaseDoctype)(knowledgeBase, _queries.FILES_DOCTYPE));
78
+ };
79
+
80
+ var handleAddEmails = function handleAddEmails() {
81
+ return onChange((0, _knowledgeBase.withKnowledgeBaseEntry)(knowledgeBase, (0, _knowledgeBase.makeEmailKnowledgeBaseEntry)()));
82
+ };
83
+
84
+ var handleRemoveEmails = function handleRemoveEmails() {
85
+ return onChange((0, _knowledgeBase.withoutKnowledgeBaseDoctype)(knowledgeBase, _queries.EMAIL_DOCTYPE));
86
+ };
87
+
88
+ return /*#__PURE__*/_react.default.createElement("div", {
89
+ className: "u-mb-1"
90
+ }, /*#__PURE__*/_react.default.createElement(_Typography.default, {
91
+ variant: "h6",
92
+ className: "u-mb-half"
93
+ }, t('assistant_create.steps.basic_info.knowledge_base')), /*#__PURE__*/_react.default.createElement(_Typography.default, {
94
+ variant: "body2",
95
+ className: "u-mb-half u-c-text-secondary"
96
+ }, t('assistant_create.steps.basic_info.knowledge_base_placeholder')), /*#__PURE__*/_react.default.createElement("div", {
97
+ className: "u-flex u-flex-row u-flex-items-center u-flex-wrap"
98
+ }, dirId ? /*#__PURE__*/_react.default.createElement(_Chips.default, {
99
+ icon: /*#__PURE__*/_react.default.createElement("img", {
100
+ alt: "",
101
+ "aria-hidden": "true",
102
+ src: _tdrive.default,
103
+ width: 16
104
+ }),
105
+ label: isUnavailable ? t('assistant.knowledge_base.unavailable') : (_folder$name = folder === null || folder === void 0 ? void 0 : folder.name) !== null && _folder$name !== void 0 ? _folder$name : '…',
106
+ deleteIcon: /*#__PURE__*/_react.default.createElement(_twakeIcons.Icon, {
107
+ icon: _twakeIcons.Cross,
108
+ size: 10 // inline width/height beats MUI v4's fixed deleteIcon class size
109
+ ,
110
+ style: {
111
+ height: 10,
112
+ width: 10
113
+ },
114
+ "aria-label": t('assistant.knowledge_base.remove')
115
+ }),
116
+ onDelete: handleRemoveFolder,
117
+ className: "u-w-auto u-ph-half"
118
+ }) : /*#__PURE__*/_react.default.createElement(_Buttons.default, {
119
+ variant: "secondary",
120
+ size: "small",
121
+ startIcon: /*#__PURE__*/_react.default.createElement("img", {
122
+ alt: "",
123
+ "aria-hidden": "true",
124
+ src: _tdrive.default,
125
+ width: 16
126
+ }),
127
+ label: t('assistant_create.steps.basic_info.from_drive'),
128
+ onClick: function onClick() {
129
+ return setIsPickerOpen(true);
130
+ }
131
+ }), showMail && (hasEmail ? /*#__PURE__*/_react.default.createElement(_Chips.default, {
132
+ icon: /*#__PURE__*/_react.default.createElement("img", {
133
+ alt: "",
134
+ "aria-hidden": "true",
135
+ src: _tmail.default,
136
+ width: 16
137
+ }),
138
+ label: t('assistant.knowledge_base.emails'),
139
+ deleteIcon: /*#__PURE__*/_react.default.createElement(_twakeIcons.Icon, {
140
+ icon: _twakeIcons.Cross,
141
+ size: 10 // inline width/height beats MUI v4's fixed deleteIcon class size
142
+ ,
143
+ style: {
144
+ height: 10,
145
+ width: 10
146
+ },
147
+ "aria-label": t('assistant.knowledge_base.remove_emails')
148
+ }),
149
+ onDelete: handleRemoveEmails,
150
+ className: "u-w-auto u-ph-half u-ml-half"
151
+ }) : /*#__PURE__*/_react.default.createElement(_Buttons.default, {
152
+ variant: "secondary",
153
+ size: "small",
154
+ className: "u-ml-half",
155
+ startIcon: /*#__PURE__*/_react.default.createElement("img", {
156
+ alt: "",
157
+ "aria-hidden": "true",
158
+ src: _tmail.default,
159
+ width: 16
160
+ }),
161
+ label: t('assistant_create.steps.basic_info.from_mail'),
162
+ onClick: handleAddEmails
163
+ }))), isPickerOpen && /*#__PURE__*/_react.default.createElement(_FolderPickerDialog.default, {
164
+ open: isPickerOpen,
165
+ onClose: function onClose() {
166
+ return setIsPickerOpen(false);
167
+ },
168
+ onSelect: handleSelectFolder
169
+ }));
170
+ };
171
+
172
+ var _default = KnowledgeBaseSection;
173
+ exports.default = _default;
@@ -0,0 +1,12 @@
1
+ export function makeKnowledgeBaseEntry(pickedFolder: any): {
2
+ doctype: string;
3
+ dirId: any;
4
+ };
5
+ export function makeEmailKnowledgeBaseEntry(): {
6
+ doctype: string;
7
+ };
8
+ export function hasEmailKnowledgeBase(assistant: any): boolean;
9
+ export function withKnowledgeBaseEntry(knowledgeBase: any[] | undefined, entry: any): any[];
10
+ export function withoutKnowledgeBaseDoctype(knowledgeBase: any[] | undefined, doctype: any): any[];
11
+ export function getKnowledgeBaseDirId(assistant: any): any;
12
+ export function saveKnowledgeBase(client: any, assistantId: any, knowledgeBaseOrUpdater: any): Promise<void>;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.withoutKnowledgeBaseDoctype = exports.withKnowledgeBaseEntry = exports.saveKnowledgeBase = exports.makeKnowledgeBaseEntry = exports.makeEmailKnowledgeBaseEntry = exports.hasEmailKnowledgeBase = exports.getKnowledgeBaseDirId = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+
14
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
15
+
16
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
17
+
18
+ var _cozyClient = require("cozy-client");
19
+
20
+ var _queries = require("../queries");
21
+
22
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
23
+
24
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
25
+
26
+ var ASSISTANTS_DOCTYPE = 'io.cozy.ai.chat.assistants';
27
+
28
+ var makeKnowledgeBaseEntry = function makeKnowledgeBaseEntry(pickedFolder) {
29
+ return {
30
+ doctype: _queries.FILES_DOCTYPE,
31
+ dirId: pickedFolder.id
32
+ };
33
+ };
34
+
35
+ exports.makeKnowledgeBaseEntry = makeKnowledgeBaseEntry;
36
+
37
+ var makeEmailKnowledgeBaseEntry = function makeEmailKnowledgeBaseEntry() {
38
+ return {
39
+ doctype: _queries.EMAIL_DOCTYPE
40
+ };
41
+ };
42
+
43
+ exports.makeEmailKnowledgeBaseEntry = makeEmailKnowledgeBaseEntry;
44
+
45
+ var hasEmailKnowledgeBase = function hasEmailKnowledgeBase(assistant) {
46
+ var _assistant$knowledgeB;
47
+
48
+ return !!(assistant !== null && assistant !== void 0 && (_assistant$knowledgeB = assistant.knowledgeBase) !== null && _assistant$knowledgeB !== void 0 && _assistant$knowledgeB.some(function (entry) {
49
+ return entry.doctype === _queries.EMAIL_DOCTYPE;
50
+ }));
51
+ };
52
+ /** Adds/replaces the entry for its doctype, preserving other sources. */
53
+
54
+
55
+ exports.hasEmailKnowledgeBase = hasEmailKnowledgeBase;
56
+
57
+ var withKnowledgeBaseEntry = function withKnowledgeBaseEntry() {
58
+ var knowledgeBase = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
59
+ var entry = arguments.length > 1 ? arguments[1] : undefined;
60
+ return [].concat((0, _toConsumableArray2.default)(knowledgeBase.filter(function (e) {
61
+ return e.doctype !== entry.doctype;
62
+ })), [entry]);
63
+ };
64
+
65
+ exports.withKnowledgeBaseEntry = withKnowledgeBaseEntry;
66
+
67
+ var withoutKnowledgeBaseDoctype = function withoutKnowledgeBaseDoctype() {
68
+ var knowledgeBase = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
69
+ var doctype = arguments.length > 1 ? arguments[1] : undefined;
70
+ return knowledgeBase.filter(function (e) {
71
+ return e.doctype !== doctype;
72
+ });
73
+ };
74
+
75
+ exports.withoutKnowledgeBaseDoctype = withoutKnowledgeBaseDoctype;
76
+
77
+ var getKnowledgeBaseDirId = function getKnowledgeBaseDirId(assistant) {
78
+ var _assistant$knowledgeB2, _assistant$knowledgeB3, _assistant$knowledgeB4;
79
+
80
+ return (_assistant$knowledgeB2 = assistant === null || assistant === void 0 ? void 0 : (_assistant$knowledgeB3 = assistant.knowledgeBase) === null || _assistant$knowledgeB3 === void 0 ? void 0 : (_assistant$knowledgeB4 = _assistant$knowledgeB3.find(function (entry) {
81
+ return entry.doctype === _queries.FILES_DOCTYPE;
82
+ })) === null || _assistant$knowledgeB4 === void 0 ? void 0 : _assistant$knowledgeB4.dirId) !== null && _assistant$knowledgeB2 !== void 0 ? _assistant$knowledgeB2 : null;
83
+ };
84
+ /**
85
+ * Saves the knowledgeBase attribute on an assistant document.
86
+ *
87
+ * `knowledgeBaseOrUpdater` is either the new knowledgeBase array (replaces
88
+ * it wholesale — used when a caller deliberately owns the full array, e.g.
89
+ * the edit dialog) or an updater function `(knowledgeBase) => knowledgeBase`
90
+ * applied to the freshly fetched doc's knowledgeBase. Computing the update
91
+ * from the fresh doc rather than a value the caller may have cached avoids
92
+ * dropping concurrent changes (stale-read race).
93
+ */
94
+
95
+
96
+ exports.getKnowledgeBaseDirId = getKnowledgeBaseDirId;
97
+
98
+ var saveKnowledgeBase = /*#__PURE__*/function () {
99
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(client, assistantId, knowledgeBaseOrUpdater) {
100
+ var _yield$client$query, assistant, knowledgeBase;
101
+
102
+ return _regenerator.default.wrap(function _callee$(_context) {
103
+ while (1) {
104
+ switch (_context.prev = _context.next) {
105
+ case 0:
106
+ _context.next = 2;
107
+ return client.query((0, _cozyClient.Q)(ASSISTANTS_DOCTYPE).getById(assistantId));
108
+
109
+ case 2:
110
+ _yield$client$query = _context.sent;
111
+ assistant = _yield$client$query.data;
112
+ knowledgeBase = typeof knowledgeBaseOrUpdater === 'function' ? knowledgeBaseOrUpdater(assistant === null || assistant === void 0 ? void 0 : assistant.knowledgeBase) : knowledgeBaseOrUpdater;
113
+ _context.next = 7;
114
+ return client.save(_objectSpread(_objectSpread({}, assistant), {}, {
115
+ knowledgeBase: knowledgeBase
116
+ }));
117
+
118
+ case 7:
119
+ case "end":
120
+ return _context.stop();
121
+ }
122
+ }
123
+ }, _callee);
124
+ }));
125
+
126
+ return function saveKnowledgeBase(_x, _x2, _x3) {
127
+ return _ref.apply(this, arguments);
128
+ };
129
+ }();
130
+
131
+ exports.saveKnowledgeBase = saveKnowledgeBase;
@@ -0,0 +1,177 @@
1
+ import {
2
+ makeKnowledgeBaseEntry,
3
+ makeEmailKnowledgeBaseEntry,
4
+ hasEmailKnowledgeBase,
5
+ withKnowledgeBaseEntry,
6
+ withoutKnowledgeBaseDoctype,
7
+ getKnowledgeBaseDirId,
8
+ saveKnowledgeBase
9
+ } from './knowledgeBase'
10
+
11
+ describe('makeKnowledgeBaseEntry', () => {
12
+ it('builds an io.cozy.files entry from a picked folder', () => {
13
+ expect(makeKnowledgeBaseEntry({ id: 'folder-1', name: 'HR' })).toEqual({
14
+ doctype: 'io.cozy.files',
15
+ dirId: 'folder-1'
16
+ })
17
+ })
18
+ })
19
+
20
+ describe('makeEmailKnowledgeBaseEntry', () => {
21
+ it('builds an all-or-nothing email entry', () => {
22
+ expect(makeEmailKnowledgeBaseEntry()).toEqual({
23
+ doctype: 'com.linagora.email'
24
+ })
25
+ })
26
+ })
27
+
28
+ describe('hasEmailKnowledgeBase', () => {
29
+ it('detects the email entry', () => {
30
+ expect(
31
+ hasEmailKnowledgeBase({
32
+ knowledgeBase: [{ doctype: 'com.linagora.email' }]
33
+ })
34
+ ).toBe(true)
35
+ })
36
+
37
+ it('returns false when there is no email entry', () => {
38
+ expect(hasEmailKnowledgeBase(undefined)).toBe(false)
39
+ expect(hasEmailKnowledgeBase({})).toBe(false)
40
+ expect(
41
+ hasEmailKnowledgeBase({
42
+ knowledgeBase: [{ doctype: 'io.cozy.files', dirId: 'folder-1' }]
43
+ })
44
+ ).toBe(false)
45
+ })
46
+ })
47
+
48
+ describe('withKnowledgeBaseEntry', () => {
49
+ it('adds an entry and preserves entries of other doctypes', () => {
50
+ expect(
51
+ withKnowledgeBaseEntry([{ doctype: 'com.linagora.email' }], {
52
+ doctype: 'io.cozy.files',
53
+ dirId: 'folder-1'
54
+ })
55
+ ).toEqual([
56
+ { doctype: 'com.linagora.email' },
57
+ { doctype: 'io.cozy.files', dirId: 'folder-1' }
58
+ ])
59
+ })
60
+
61
+ it('replaces an existing entry of the same doctype', () => {
62
+ expect(
63
+ withKnowledgeBaseEntry(
64
+ [
65
+ { doctype: 'io.cozy.files', dirId: 'folder-1' },
66
+ { doctype: 'com.linagora.email' }
67
+ ],
68
+ { doctype: 'io.cozy.files', dirId: 'folder-2' }
69
+ )
70
+ ).toEqual([
71
+ { doctype: 'com.linagora.email' },
72
+ { doctype: 'io.cozy.files', dirId: 'folder-2' }
73
+ ])
74
+ })
75
+
76
+ it('works from an undefined knowledge base', () => {
77
+ expect(
78
+ withKnowledgeBaseEntry(undefined, { doctype: 'com.linagora.email' })
79
+ ).toEqual([{ doctype: 'com.linagora.email' }])
80
+ })
81
+ })
82
+
83
+ describe('withoutKnowledgeBaseDoctype', () => {
84
+ it('removes only the entries of the given doctype', () => {
85
+ expect(
86
+ withoutKnowledgeBaseDoctype(
87
+ [
88
+ { doctype: 'io.cozy.files', dirId: 'folder-1' },
89
+ { doctype: 'com.linagora.email' }
90
+ ],
91
+ 'com.linagora.email'
92
+ )
93
+ ).toEqual([{ doctype: 'io.cozy.files', dirId: 'folder-1' }])
94
+ })
95
+
96
+ it('works from an undefined knowledge base', () => {
97
+ expect(
98
+ withoutKnowledgeBaseDoctype(undefined, 'com.linagora.email')
99
+ ).toEqual([])
100
+ })
101
+ })
102
+
103
+ describe('getKnowledgeBaseDirId', () => {
104
+ it('returns the dirId of the io.cozy.files entry', () => {
105
+ const assistant = {
106
+ knowledgeBase: [{ doctype: 'io.cozy.files', dirId: 'folder-1' }]
107
+ }
108
+ expect(getKnowledgeBaseDirId(assistant)).toBe('folder-1')
109
+ })
110
+
111
+ it('ignores entries of other doctypes', () => {
112
+ const assistant = {
113
+ knowledgeBase: [
114
+ { doctype: 'com.linagora.email', mailboxId: 'inbox' },
115
+ { doctype: 'io.cozy.files', dirId: 'folder-2' }
116
+ ]
117
+ }
118
+ expect(getKnowledgeBaseDirId(assistant)).toBe('folder-2')
119
+ })
120
+
121
+ it('returns null when there is no knowledge base', () => {
122
+ expect(getKnowledgeBaseDirId({})).toBeNull()
123
+ expect(getKnowledgeBaseDirId(undefined)).toBeNull()
124
+ expect(getKnowledgeBaseDirId({ knowledgeBase: [] })).toBeNull()
125
+ })
126
+ })
127
+
128
+ describe('saveKnowledgeBase', () => {
129
+ it('refetches the assistant and saves it with the new knowledgeBase', async () => {
130
+ const assistantDoc = {
131
+ _id: 'assistant-1',
132
+ _type: 'io.cozy.ai.chat.assistants',
133
+ name: 'My assistant'
134
+ }
135
+ const client = {
136
+ query: jest.fn().mockResolvedValue({ data: assistantDoc }),
137
+ save: jest.fn().mockResolvedValue({ data: assistantDoc })
138
+ }
139
+ const knowledgeBase = [{ doctype: 'io.cozy.files', dirId: 'folder-1' }]
140
+
141
+ await saveKnowledgeBase(client, 'assistant-1', knowledgeBase)
142
+
143
+ expect(client.query).toHaveBeenCalledTimes(1)
144
+ expect(client.save).toHaveBeenCalledWith({
145
+ ...assistantDoc,
146
+ knowledgeBase
147
+ })
148
+ })
149
+
150
+ it('applies an updater function to the freshly fetched knowledgeBase', async () => {
151
+ const assistantDoc = {
152
+ _id: 'assistant-1',
153
+ _type: 'io.cozy.ai.chat.assistants',
154
+ name: 'My assistant',
155
+ knowledgeBase: [{ doctype: 'io.cozy.files', dirId: 'fresh-folder' }]
156
+ }
157
+ const client = {
158
+ query: jest.fn().mockResolvedValue({ data: assistantDoc }),
159
+ save: jest.fn().mockResolvedValue({ data: assistantDoc })
160
+ }
161
+ const updater = jest.fn(kb =>
162
+ withKnowledgeBaseEntry(kb, makeEmailKnowledgeBaseEntry())
163
+ )
164
+
165
+ await saveKnowledgeBase(client, 'assistant-1', updater)
166
+
167
+ expect(client.query).toHaveBeenCalledTimes(1)
168
+ expect(updater).toHaveBeenCalledWith(assistantDoc.knowledgeBase)
169
+ expect(client.save).toHaveBeenCalledWith({
170
+ ...assistantDoc,
171
+ knowledgeBase: [
172
+ { doctype: 'io.cozy.files', dirId: 'fresh-folder' },
173
+ { doctype: 'com.linagora.email' }
174
+ ]
175
+ })
176
+ })
177
+ })
@@ -0,0 +1,12 @@
1
+ .intentHost
2
+ width 100%
3
+ height 70vh
4
+
5
+ // cozy-interapp injects a bare <iframe> with no styling of its own
6
+ // (browser default: 150px tall, display inline — the inline baseline
7
+ // gap adds ~4px below, overflowing the dialog into a phantom scrollbar)
8
+ iframe
9
+ display block
10
+ width 100%
11
+ height 100%
12
+ border none
@@ -0,0 +1,8 @@
1
+ export function useSelectedAssistantKnowledgeBase(): {
2
+ dirId: any;
3
+ folder: object | any[];
4
+ isUnavailable: boolean;
5
+ setKnowledgeBaseFolder: (pickedFolder: any) => Promise<void>;
6
+ isRealAssistant: boolean;
7
+ hasEmail: boolean;
8
+ };
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useSelectedAssistantKnowledgeBase = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _react = require("react");
15
+
16
+ var _cozyClient = require("cozy-client");
17
+
18
+ var _Alert = require("cozy-ui/transpiled/react/providers/Alert");
19
+
20
+ var _twakeI18n = require("twake-i18n");
21
+
22
+ var _knowledgeBase = require("./knowledgeBase");
23
+
24
+ var _AssistantProvider = require("../AssistantProvider");
25
+
26
+ var _constants = require("../constants");
27
+
28
+ var _queries = require("../queries");
29
+
30
+ /**
31
+ * Resolves the selected assistant's knowledge-base sources: the Drive folder
32
+ * (live from io.cozy.files — renames reflected, deletion detected) and the
33
+ * all-or-nothing email source.
34
+ */
35
+ var useSelectedAssistantKnowledgeBase = function useSelectedAssistantKnowledgeBase() {
36
+ var _folder$path;
37
+
38
+ var client = (0, _cozyClient.useClient)();
39
+
40
+ var _useI18n = (0, _twakeI18n.useI18n)(),
41
+ t = _useI18n.t;
42
+
43
+ var _useAlert = (0, _Alert.useAlert)(),
44
+ showAlert = _useAlert.showAlert;
45
+
46
+ var _useAssistant = (0, _AssistantProvider.useAssistant)(),
47
+ selectedAssistantId = _useAssistant.selectedAssistantId;
48
+
49
+ var realAssistantId = selectedAssistantId !== _constants.DEFAULT_ASSISTANT._id ? selectedAssistantId : null;
50
+ var assistantQuery = (0, _queries.buildAssistantByIdQuery)(realAssistantId);
51
+
52
+ var _useQuery = (0, _cozyClient.useQuery)(assistantQuery.definition, assistantQuery.options),
53
+ assistant = _useQuery.data;
54
+
55
+ var dirId = (0, _knowledgeBase.getKnowledgeBaseDirId)(assistant);
56
+ var fileQuery = (0, _queries.buildFileByIdQuery)(dirId);
57
+
58
+ var _useQuery2 = (0, _cozyClient.useQuery)(fileQuery.definition, fileQuery.options),
59
+ folder = _useQuery2.data,
60
+ fetchStatus = _useQuery2.fetchStatus;
61
+
62
+ var hasEmail = (0, _knowledgeBase.hasEmailKnowledgeBase)(assistant);
63
+ var setKnowledgeBaseFolder = (0, _react.useCallback)( /*#__PURE__*/function () {
64
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(pickedFolder) {
65
+ return _regenerator.default.wrap(function _callee$(_context) {
66
+ while (1) {
67
+ switch (_context.prev = _context.next) {
68
+ case 0:
69
+ if (!(!realAssistantId || !pickedFolder)) {
70
+ _context.next = 2;
71
+ break;
72
+ }
73
+
74
+ return _context.abrupt("return");
75
+
76
+ case 2:
77
+ _context.prev = 2;
78
+ _context.next = 5;
79
+ return (0, _knowledgeBase.saveKnowledgeBase)(client, realAssistantId, function (kb) {
80
+ return (0, _knowledgeBase.withKnowledgeBaseEntry)(kb, (0, _knowledgeBase.makeKnowledgeBaseEntry)(pickedFolder));
81
+ });
82
+
83
+ case 5:
84
+ _context.next = 10;
85
+ break;
86
+
87
+ case 7:
88
+ _context.prev = 7;
89
+ _context.t0 = _context["catch"](2);
90
+ showAlert({
91
+ message: t('assistant.default_error'),
92
+ severity: 'error'
93
+ });
94
+
95
+ case 10:
96
+ case "end":
97
+ return _context.stop();
98
+ }
99
+ }
100
+ }, _callee, null, [[2, 7]]);
101
+ }));
102
+
103
+ return function (_x) {
104
+ return _ref.apply(this, arguments);
105
+ };
106
+ }(), [client, realAssistantId, showAlert, t]);
107
+ return {
108
+ dirId: dirId,
109
+ folder: folder !== null && folder !== void 0 ? folder : null,
110
+ isUnavailable: !!dirId && (fetchStatus === 'failed' || !!(folder !== null && folder !== void 0 && folder.trashed) || !!(folder !== null && folder !== void 0 && (_folder$path = folder.path) !== null && _folder$path !== void 0 && _folder$path.startsWith('/.cozy_trash'))),
111
+ setKnowledgeBaseFolder: setKnowledgeBaseFolder,
112
+ isRealAssistant: !!realAssistantId,
113
+ hasEmail: hasEmail
114
+ };
115
+ };
116
+
117
+ exports.useSelectedAssistantKnowledgeBase = useSelectedAssistantKnowledgeBase;
@@ -1,6 +1,13 @@
1
1
  export default TwakeKnowledgeChip;
2
- declare function TwakeKnowledgeChip({ twakeKnowledge, isLast, onSelect }: {
2
+ /**
3
+ * Source chip rendered as an all-or-nothing toggle: clicking the chip (or its
4
+ * cross) selects/deselects the whole source. Selection state and persistence
5
+ * are owned by the parent through isSelected/onToggle. Without onToggle the
6
+ * chip is a static indicator (always-on source, no cross, not clickable).
7
+ */
8
+ declare function TwakeKnowledgeChip({ twakeKnowledge, isLast, isSelected, onToggle }: {
3
9
  twakeKnowledge: any;
4
10
  isLast: any;
5
- onSelect: any;
11
+ isSelected: any;
12
+ onToggle: any;
6
13
  }): JSX.Element;