@red-hat-developer-hub/backstage-plugin-lightspeed 1.0.3 → 1.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 (33) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +1 -0
  3. package/dist/alpha.d.ts +38 -7
  4. package/dist/api/LightspeedApiClient.esm.js +19 -0
  5. package/dist/api/LightspeedApiClient.esm.js.map +1 -1
  6. package/dist/api/api.esm.js.map +1 -1
  7. package/dist/components/DeleteModal.esm.js +86 -10
  8. package/dist/components/DeleteModal.esm.js.map +1 -1
  9. package/dist/components/LightSpeedChat.esm.js +146 -56
  10. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  11. package/dist/components/LightspeedChatBox.esm.js +4 -0
  12. package/dist/components/LightspeedChatBox.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatBoxHeader.esm.js +88 -23
  14. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  15. package/dist/components/PermissionRequiredState.esm.js +2 -1
  16. package/dist/components/PermissionRequiredState.esm.js.map +1 -1
  17. package/dist/components/RenameConversationModal.esm.js +139 -0
  18. package/dist/components/RenameConversationModal.esm.js.map +1 -0
  19. package/dist/hooks/useLightspeedUpdatePermission.esm.js +12 -0
  20. package/dist/hooks/useLightspeedUpdatePermission.esm.js.map +1 -0
  21. package/dist/hooks/useRenameConversation.esm.js +44 -0
  22. package/dist/hooks/useRenameConversation.esm.js.map +1 -0
  23. package/dist/translations/de.esm.js +40 -8
  24. package/dist/translations/de.esm.js.map +1 -1
  25. package/dist/translations/es.esm.js +40 -8
  26. package/dist/translations/es.esm.js.map +1 -1
  27. package/dist/translations/fr.esm.js +40 -8
  28. package/dist/translations/fr.esm.js.map +1 -1
  29. package/dist/translations/ref.esm.js +40 -8
  30. package/dist/translations/ref.esm.js.map +1 -1
  31. package/dist/utils/lightspeed-chatbox-utils.esm.js +24 -45
  32. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
  33. package/package.json +11 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  ## @red-hat-developer-hub/backstage-plugin-lightspeed
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 99f35d5: Backstage version bump to v1.45.2
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [99f35d5]
12
+ - @red-hat-developer-hub/backstage-plugin-lightspeed-common@1.1.0
13
+
14
+ ## 1.0.4
15
+
16
+ ### Patch Changes
17
+
18
+ - 58e26ba: '@red-hat-developer-hub/backstage-plugin-lightspeed' :
19
+ - Added missing translations for untranslated labels across the Lightspeed chat UI.
20
+ - Added lightspeed settings kebab menu
21
+ - Added a new “Pinned” section. The section is conditionally visible only when pinning chats are enabled in Lightspeed settings. It shows an empty state when no chats are pinned.
22
+ - Added Kebab menu actions to each chat item with actions: Rename, Pin, Unpin
23
+ - Implemented logic to move chats between Pinned and Recent sections based on the selected action (“Pin” / “Unpin”).
24
+ - Updated search behavior to show results under both Pinned and Recent groups (when enabled), including appropriate empty search messaging.
25
+ - The Rename action opens a dialog with an editable text field and confirm/cancel actions.
26
+ - Replaced the patternfly components with MUI to match the Figma designs [Design 1](https://www.figma.com/design/urwU8VqRvHfbxMqxeVknrv/RHDH-Lightspeed---AI-Assistant?node-id=1523-1670&t=CqnUYsxar0PtjAjZ-0)
27
+ [Design 2](https://www.figma.com/design/urwU8VqRvHfbxMqxeVknrv/RHDH-Lightspeed---AI-Assistant?node-id=2514-5415&t=PphIEOl5Yzmgv5tI-0)
28
+
29
+ '@red-hat-developer-hub/backstage-plugin-lightspeed-common':
30
+
31
+ Added the Update api client
32
+
33
+ - 40b80fe: Remove "lifecycle" keywords and "supported-versions" in package.json. Change "lifecycle" to active in catalog.yaml
34
+ - b609890: update lightspeed model dropdown styles
35
+ - Updated dependencies [58e26ba]
36
+ - Updated dependencies [40b80fe]
37
+ - @red-hat-developer-hub/backstage-plugin-lightspeed-common@1.0.4
38
+
3
39
  ## 1.0.3
4
40
 
5
41
  ### Patch Changes
package/README.md CHANGED
@@ -22,6 +22,7 @@ The Lightspeed plugin has support for the permission framework.
22
22
  p, role:default/team_a, lightspeed.chat.read, read, allow
23
23
  p, role:default/team_a, lightspeed.chat.create, create, allow
24
24
  p, role:default/team_a, lightspeed.chat.delete, delete, allow
25
+ p, role:default/team_a, lightspeed.chat.update, update, allow
25
26
 
26
27
  g, user:default/<your-user-name>, role:default/team_a
27
28
 
package/dist/alpha.d.ts CHANGED
@@ -33,9 +33,13 @@ declare const lightspeedTranslationRef: _backstage_core_plugin_api_alpha.Transla
33
33
  readonly "prompts.rhdh.message": string;
34
34
  readonly "page.title": string;
35
35
  readonly "page.subtitle": string;
36
- readonly "conversation.history.confirm.title": string;
37
- readonly "conversation.history.confirm.message": string;
38
- readonly "conversation.history.confirm.delete": string;
36
+ readonly "conversation.delete.confirm.title": string;
37
+ readonly "conversation.delete.confirm.message": string;
38
+ readonly "conversation.delete.confirm.action": string;
39
+ readonly "conversation.rename.confirm.title": string;
40
+ readonly "conversation.rename.confirm.action": string;
41
+ readonly "conversation.rename.placeholder": string;
42
+ readonly "conversation.action.error": string;
39
43
  readonly "permission.required.title": string;
40
44
  readonly "permission.required.description": string;
41
45
  readonly "footer.accuracy.label": string;
@@ -45,9 +49,17 @@ declare const lightspeedTranslationRef: _backstage_core_plugin_api_alpha.Transla
45
49
  readonly "footer.accuracy.popover.cta.label": string;
46
50
  readonly "footer.accuracy.popover.link.label": string;
47
51
  readonly "common.cancel": string;
52
+ readonly "common.close": string;
53
+ readonly "common.readMore": string;
54
+ readonly "common.noSearchResults": string;
48
55
  readonly "menu.newConversation": string;
49
56
  readonly "chatbox.header.title": string;
50
57
  readonly "chatbox.search.placeholder": string;
58
+ readonly "chatbox.provider.other": string;
59
+ readonly "chatbox.emptyState.noPinnedChats": string;
60
+ readonly "chatbox.emptyState.noRecentChats": string;
61
+ readonly "chatbox.emptyState.noResults.title": string;
62
+ readonly "chatbox.emptyState.noResults.body": string;
51
63
  readonly "chatbox.welcome.greeting": string;
52
64
  readonly "chatbox.welcome.description": string;
53
65
  readonly "chatbox.message.placeholder": string;
@@ -55,11 +67,23 @@ declare const lightspeedTranslationRef: _backstage_core_plugin_api_alpha.Transla
55
67
  readonly "chatbox.fileUpload.infoText": string;
56
68
  readonly "aria.chatbotSelector": string;
57
69
  readonly "aria.important": string;
70
+ readonly "aria.chatHistoryMenu": string;
71
+ readonly "aria.closeDrawerPanel": string;
72
+ readonly "aria.search.placeholder": string;
73
+ readonly "aria.searchPreviousConversations": string;
74
+ readonly "aria.resize": string;
75
+ readonly "aria.options.label": string;
76
+ readonly "aria.scroll.down": string;
77
+ readonly "aria.scroll.up": string;
78
+ readonly "aria.settings.label": string;
58
79
  readonly "modal.edit": string;
59
80
  readonly "modal.save": string;
60
81
  readonly "modal.close": string;
61
82
  readonly "modal.cancel": string;
62
83
  readonly "conversation.delete": string;
84
+ readonly "conversation.rename": string;
85
+ readonly "conversation.addToPinnedChats": string;
86
+ readonly "conversation.removeFromPinnedChats": string;
63
87
  readonly "conversation.announcement.userMessage": string;
64
88
  readonly "user.guest": string;
65
89
  readonly "user.loading": string;
@@ -68,6 +92,11 @@ declare const lightspeedTranslationRef: _backstage_core_plugin_api_alpha.Transla
68
92
  readonly "tooltip.microphone.active": string;
69
93
  readonly "tooltip.microphone.inactive": string;
70
94
  readonly "button.newChat": string;
95
+ readonly "tooltip.chatHistoryMenu": string;
96
+ readonly "tooltip.responseRecorded": string;
97
+ readonly "tooltip.backToTop": string;
98
+ readonly "tooltip.backToBottom": string;
99
+ readonly "tooltip.settings": string;
71
100
  readonly "modal.title.preview": string;
72
101
  readonly "modal.title.edit": string;
73
102
  readonly "icon.lightspeed.alt": string;
@@ -96,10 +125,12 @@ declare const lightspeedTranslationRef: _backstage_core_plugin_api_alpha.Transla
96
125
  readonly "feedback.quickResponses.negative.notHelpful": string;
97
126
  readonly "feedback.completion.title": string;
98
127
  readonly "feedback.completion.body": string;
99
- readonly "conversation.category.today": string;
100
- readonly "conversation.category.yesterday": string;
101
- readonly "conversation.category.previous7Days": string;
102
- readonly "conversation.category.previous30Days": string;
128
+ readonly "conversation.category.pinnedChats": string;
129
+ readonly "conversation.category.recent": string;
130
+ readonly "settings.pinned.enable": string;
131
+ readonly "settings.pinned.disable": string;
132
+ readonly "settings.pinned.enabled.description": string;
133
+ readonly "settings.pinned.disabled.description": string;
103
134
  }>;
104
135
 
105
136
  /**
@@ -131,6 +131,25 @@ class LightspeedApiClient {
131
131
  }
132
132
  return { success: true };
133
133
  }
134
+ async renameConversation(conversation_id, newName) {
135
+ const baseUrl = await this.getBaseUrl();
136
+ const response = await this.fetchApi.fetch(
137
+ `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,
138
+ {
139
+ method: "PUT",
140
+ headers: {
141
+ "Content-Type": "application/json"
142
+ },
143
+ body: JSON.stringify({ topic_summary: newName })
144
+ }
145
+ );
146
+ if (!response.ok) {
147
+ throw new Error(
148
+ `failed to rename conversation, status ${response.status}: ${response.statusText}`
149
+ );
150
+ }
151
+ return { success: true };
152
+ }
134
153
  getFeedbackStatus = async () => {
135
154
  const baseUrl = await this.getBaseUrl();
136
155
  const response = await this.fetchApi.fetch(
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedApiClient.esm.js","sources":["../../src/api/LightspeedApiClient.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConfigApi, FetchApi } from '@backstage/core-plugin-api';\n\nimport {\n TEMP_CONVERSATION_ID,\n VALID_TOPIC_RESTRICTION_PROVIDER_IDS,\n} from '../const';\nimport { Attachment, CaptureFeedback } from '../types';\nimport { LightspeedAPI } from './api';\n\nexport type Options = {\n configApi: ConfigApi;\n fetchApi: FetchApi;\n};\n\nexport class LightspeedApiClient implements LightspeedAPI {\n private readonly configApi: ConfigApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.configApi = options.configApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getBaseUrl() {\n return `${this.configApi.getString('backend.baseUrl')}/api/lightspeed`;\n }\n\n async createMessage(\n prompt: string,\n selectedModel: string,\n selectedProvider: string,\n conversation_id: string,\n attachments: Attachment[],\n ) {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(`${baseUrl}/v1/query`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n conversation_id:\n conversation_id === TEMP_CONVERSATION_ID\n ? undefined\n : conversation_id,\n model: selectedModel,\n provider: selectedProvider,\n query: prompt,\n attachments,\n }),\n });\n\n if (!response.body) {\n throw new Error('Readable stream is not supported or there is no body.');\n }\n\n if (!response.ok) {\n const body = await response.body.getReader();\n const reader = body.read();\n const decoder = new TextDecoder('utf-8');\n const text = await reader.then(({ done, value }) => {\n if (done) {\n return '';\n }\n return decoder.decode(value);\n });\n const errorMessage = JSON.parse(text);\n if (errorMessage?.error) {\n throw new Error(`failed to create message: ${errorMessage.error}`);\n }\n }\n return response.body.getReader();\n }\n\n private async fetcher(url: string) {\n const response = await this.fetchApi.fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) {\n throw new Error(\n `failed to fetch data, status ${response.status}: ${response.statusText}`,\n );\n }\n return response;\n }\n\n async isTopicRestrictionEnabled() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v1/shields`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get shields, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n if (!response?.shields || !Array.isArray(response.shields)) {\n return false;\n }\n\n return response.shields.some((shield: any) => {\n const providerId = shield.provider_resource_id;\n\n return VALID_TOPIC_RESTRICTION_PROVIDER_IDS.some(\n validId => providerId.toLowerCase() === validId.toLowerCase(),\n );\n });\n }\n\n async getAllModels() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v1/models`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get models, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n\n return response?.models ? response?.models : [];\n }\n\n async getConversationMessages(conversation_id: string) {\n if (conversation_id === TEMP_CONVERSATION_ID) {\n return [];\n }\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(\n `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,\n );\n if (!result.ok) {\n throw new Error(\n `failed to get conversation messages, status ${result.status}: ${result.statusText}`,\n );\n }\n const response = await result.json();\n return response.chat_history ?? [];\n }\n\n async getConversations() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v2/conversations`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get conversation, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n return response.conversations ?? [];\n }\n\n async deleteConversation(conversation_id: string) {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(\n `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,\n {\n method: 'DELETE',\n headers: {},\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `failed to delete conversation, status ${response.status}: ${response.statusText}`,\n );\n }\n return { success: true };\n }\n\n getFeedbackStatus = async () => {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(\n `${baseUrl}/v1/feedback/status`,\n {\n method: 'GET',\n headers: {},\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `failed to GET feedback status, status ${response.status}: ${response.statusText}`,\n );\n }\n const result = await response.json();\n return result?.status?.enabled ?? false;\n };\n\n captureFeedback = async (payload: CaptureFeedback) => {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(`${baseUrl}/v1/feedback`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n accept: 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(\n `failed to capture feedback, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n };\n}\n"],"names":[],"mappings":";;AA8BO,MAAM,mBAA6C,CAAA;AAAA,EACvC,SAAA;AAAA,EACA,QAAA;AAAA,EAEjB,YAAY,OAAkB,EAAA;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA;AACzB,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA;AAAA;AAC1B,EAEA,MAAM,UAAa,GAAA;AACjB,IAAA,OAAO,CAAG,EAAA,IAAA,CAAK,SAAU,CAAA,SAAA,CAAU,iBAAiB,CAAC,CAAA,eAAA,CAAA;AAAA;AACvD,EAEA,MAAM,aACJ,CAAA,MAAA,EACA,aACA,EAAA,gBAAA,EACA,iBACA,WACA,EAAA;AACA,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AAEtC,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,SAAS,KAAM,CAAA,CAAA,EAAG,OAAO,CAAa,SAAA,CAAA,EAAA;AAAA,MAChE,MAAQ,EAAA,MAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAU,CAAA;AAAA,QACnB,eAAA,EACE,eAAoB,KAAA,oBAAA,GAChB,SACA,GAAA,eAAA;AAAA,QACN,KAAO,EAAA,aAAA;AAAA,QACP,QAAU,EAAA,gBAAA;AAAA,QACV,KAAO,EAAA,MAAA;AAAA,QACP;AAAA,OACD;AAAA,KACF,CAAA;AAED,IAAI,IAAA,CAAC,SAAS,IAAM,EAAA;AAClB,MAAM,MAAA,IAAI,MAAM,uDAAuD,CAAA;AAAA;AAGzE,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAO,GAAA,MAAM,QAAS,CAAA,IAAA,CAAK,SAAU,EAAA;AAC3C,MAAM,MAAA,MAAA,GAAS,KAAK,IAAK,EAAA;AACzB,MAAM,MAAA,OAAA,GAAU,IAAI,WAAA,CAAY,OAAO,CAAA;AACvC,MAAM,MAAA,IAAA,GAAO,MAAM,MAAO,CAAA,IAAA,CAAK,CAAC,EAAE,IAAA,EAAM,OAAY,KAAA;AAClD,QAAA,IAAI,IAAM,EAAA;AACR,UAAO,OAAA,EAAA;AAAA;AAET,QAAO,OAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AAAA,OAC5B,CAAA;AACD,MAAM,MAAA,YAAA,GAAe,IAAK,CAAA,KAAA,CAAM,IAAI,CAAA;AACpC,MAAA,IAAI,cAAc,KAAO,EAAA;AACvB,QAAA,MAAM,IAAI,KAAA,CAAM,CAA6B,0BAAA,EAAA,YAAA,CAAa,KAAK,CAAE,CAAA,CAAA;AAAA;AACnE;AAEF,IAAO,OAAA,QAAA,CAAS,KAAK,SAAU,EAAA;AAAA;AACjC,EAEA,MAAc,QAAQ,GAAa,EAAA;AACjC,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,QAAA,CAAS,MAAM,GAAK,EAAA;AAAA,MAC9C,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA;AAAA;AAClB,KACD,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAgC,6BAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OACzE;AAAA;AAEF,IAAO,OAAA,QAAA;AAAA;AACT,EAEA,MAAM,yBAA4B,GAAA;AAChC,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AACtC,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,OAAQ,CAAA,CAAA,EAAG,OAAO,CAAa,WAAA,CAAA,CAAA;AAEzD,IAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAiC,8BAAA,EAAA,MAAA,CAAO,MAAM,CAAA,EAAA,EAAK,OAAO,UAAU,CAAA;AAAA,OACtE;AAAA;AAGF,IAAM,MAAA,QAAA,GAAW,MAAM,MAAA,CAAO,IAAK,EAAA;AACnC,IAAI,IAAA,CAAC,UAAU,OAAW,IAAA,CAAC,MAAM,OAAQ,CAAA,QAAA,CAAS,OAAO,CAAG,EAAA;AAC1D,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,IAAK,CAAA,CAAC,MAAgB,KAAA;AAC5C,MAAA,MAAM,aAAa,MAAO,CAAA,oBAAA;AAE1B,MAAA,OAAO,oCAAqC,CAAA,IAAA;AAAA,QAC1C,CAAW,OAAA,KAAA,UAAA,CAAW,WAAY,EAAA,KAAM,QAAQ,WAAY;AAAA,OAC9D;AAAA,KACD,CAAA;AAAA;AACH,EAEA,MAAM,YAAe,GAAA;AACnB,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AACtC,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,OAAQ,CAAA,CAAA,EAAG,OAAO,CAAY,UAAA,CAAA,CAAA;AAExD,IAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAgC,6BAAA,EAAA,MAAA,CAAO,MAAM,CAAA,EAAA,EAAK,OAAO,UAAU,CAAA;AAAA,OACrE;AAAA;AAGF,IAAM,MAAA,QAAA,GAAW,MAAM,MAAA,CAAO,IAAK,EAAA;AAEnC,IAAA,OAAO,QAAU,EAAA,MAAA,GAAS,QAAU,EAAA,MAAA,GAAS,EAAC;AAAA;AAChD,EAEA,MAAM,wBAAwB,eAAyB,EAAA;AACrD,IAAA,IAAI,oBAAoB,oBAAsB,EAAA;AAC5C,MAAA,OAAO,EAAC;AAAA;AAEV,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AACtC,IAAM,MAAA,MAAA,GAAS,MAAM,IAAK,CAAA,OAAA;AAAA,MACxB,CAAG,EAAA,OAAO,CAAqB,kBAAA,EAAA,kBAAA,CAAmB,eAAe,CAAC,CAAA;AAAA,KACpE;AACA,IAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAA+C,4CAAA,EAAA,MAAA,CAAO,MAAM,CAAA,EAAA,EAAK,OAAO,UAAU,CAAA;AAAA,OACpF;AAAA;AAEF,IAAM,MAAA,QAAA,GAAW,MAAM,MAAA,CAAO,IAAK,EAAA;AACnC,IAAO,OAAA,QAAA,CAAS,gBAAgB,EAAC;AAAA;AACnC,EAEA,MAAM,gBAAmB,GAAA;AACvB,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AACtC,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,OAAQ,CAAA,CAAA,EAAG,OAAO,CAAmB,iBAAA,CAAA,CAAA;AAE/D,IAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAsC,mCAAA,EAAA,MAAA,CAAO,MAAM,CAAA,EAAA,EAAK,OAAO,UAAU,CAAA;AAAA,OAC3E;AAAA;AAGF,IAAM,MAAA,QAAA,GAAW,MAAM,MAAA,CAAO,IAAK,EAAA;AACnC,IAAO,OAAA,QAAA,CAAS,iBAAiB,EAAC;AAAA;AACpC,EAEA,MAAM,mBAAmB,eAAyB,EAAA;AAChD,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AAEtC,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA;AAAA,MACnC,CAAG,EAAA,OAAO,CAAqB,kBAAA,EAAA,kBAAA,CAAmB,eAAe,CAAC,CAAA,CAAA;AAAA,MAClE;AAAA,QACE,MAAQ,EAAA,QAAA;AAAA,QACR,SAAS;AAAC;AACZ,KACF;AAEA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAyC,sCAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OAClF;AAAA;AAEF,IAAO,OAAA,EAAE,SAAS,IAAK,EAAA;AAAA;AACzB,EAEA,oBAAoB,YAAY;AAC9B,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AAEtC,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA;AAAA,MACnC,GAAG,OAAO,CAAA,mBAAA,CAAA;AAAA,MACV;AAAA,QACE,MAAQ,EAAA,KAAA;AAAA,QACR,SAAS;AAAC;AACZ,KACF;AAEA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAyC,sCAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OAClF;AAAA;AAEF,IAAM,MAAA,MAAA,GAAS,MAAM,QAAA,CAAS,IAAK,EAAA;AACnC,IAAO,OAAA,MAAA,EAAQ,QAAQ,OAAW,IAAA,KAAA;AAAA,GACpC;AAAA,EAEA,eAAA,GAAkB,OAAO,OAA6B,KAAA;AACpD,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAW,EAAA;AAEtC,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,SAAS,KAAM,CAAA,CAAA,EAAG,OAAO,CAAgB,YAAA,CAAA,EAAA;AAAA,MACnE,MAAQ,EAAA,MAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA,kBAAA;AAAA,QAChB,MAAQ,EAAA;AAAA,OACV;AAAA,MACA,IAAA,EAAM,IAAK,CAAA,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAED,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAsC,mCAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OAC/E;AAAA;AAEF,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA,GAC7B;AACF;;;;"}
1
+ {"version":3,"file":"LightspeedApiClient.esm.js","sources":["../../src/api/LightspeedApiClient.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConfigApi, FetchApi } from '@backstage/core-plugin-api';\n\nimport {\n TEMP_CONVERSATION_ID,\n VALID_TOPIC_RESTRICTION_PROVIDER_IDS,\n} from '../const';\nimport { Attachment, CaptureFeedback } from '../types';\nimport { LightspeedAPI } from './api';\n\nexport type Options = {\n configApi: ConfigApi;\n fetchApi: FetchApi;\n};\n\nexport class LightspeedApiClient implements LightspeedAPI {\n private readonly configApi: ConfigApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.configApi = options.configApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getBaseUrl() {\n return `${this.configApi.getString('backend.baseUrl')}/api/lightspeed`;\n }\n\n async createMessage(\n prompt: string,\n selectedModel: string,\n selectedProvider: string,\n conversation_id: string,\n attachments: Attachment[],\n ) {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(`${baseUrl}/v1/query`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n conversation_id:\n conversation_id === TEMP_CONVERSATION_ID\n ? undefined\n : conversation_id,\n model: selectedModel,\n provider: selectedProvider,\n query: prompt,\n attachments,\n }),\n });\n\n if (!response.body) {\n throw new Error('Readable stream is not supported or there is no body.');\n }\n\n if (!response.ok) {\n const body = await response.body.getReader();\n const reader = body.read();\n const decoder = new TextDecoder('utf-8');\n const text = await reader.then(({ done, value }) => {\n if (done) {\n return '';\n }\n return decoder.decode(value);\n });\n const errorMessage = JSON.parse(text);\n if (errorMessage?.error) {\n throw new Error(`failed to create message: ${errorMessage.error}`);\n }\n }\n return response.body.getReader();\n }\n\n private async fetcher(url: string) {\n const response = await this.fetchApi.fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) {\n throw new Error(\n `failed to fetch data, status ${response.status}: ${response.statusText}`,\n );\n }\n return response;\n }\n\n async isTopicRestrictionEnabled() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v1/shields`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get shields, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n if (!response?.shields || !Array.isArray(response.shields)) {\n return false;\n }\n\n return response.shields.some((shield: any) => {\n const providerId = shield.provider_resource_id;\n\n return VALID_TOPIC_RESTRICTION_PROVIDER_IDS.some(\n validId => providerId.toLowerCase() === validId.toLowerCase(),\n );\n });\n }\n\n async getAllModels() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v1/models`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get models, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n\n return response?.models ? response?.models : [];\n }\n\n async getConversationMessages(conversation_id: string) {\n if (conversation_id === TEMP_CONVERSATION_ID) {\n return [];\n }\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(\n `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,\n );\n if (!result.ok) {\n throw new Error(\n `failed to get conversation messages, status ${result.status}: ${result.statusText}`,\n );\n }\n const response = await result.json();\n return response.chat_history ?? [];\n }\n\n async getConversations() {\n const baseUrl = await this.getBaseUrl();\n const result = await this.fetcher(`${baseUrl}/v2/conversations`);\n\n if (!result.ok) {\n throw new Error(\n `failed to get conversation, status ${result.status}: ${result.statusText}`,\n );\n }\n\n const response = await result.json();\n return response.conversations ?? [];\n }\n\n async deleteConversation(conversation_id: string) {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(\n `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,\n {\n method: 'DELETE',\n headers: {},\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `failed to delete conversation, status ${response.status}: ${response.statusText}`,\n );\n }\n return { success: true };\n }\n\n async renameConversation(conversation_id: string, newName: string) {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(\n `${baseUrl}/v2/conversations/${encodeURIComponent(conversation_id)}`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ topic_summary: newName }),\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `failed to rename conversation, status ${response.status}: ${response.statusText}`,\n );\n }\n return { success: true };\n }\n\n getFeedbackStatus = async () => {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(\n `${baseUrl}/v1/feedback/status`,\n {\n method: 'GET',\n headers: {},\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `failed to GET feedback status, status ${response.status}: ${response.statusText}`,\n );\n }\n const result = await response.json();\n return result?.status?.enabled ?? false;\n };\n\n captureFeedback = async (payload: CaptureFeedback) => {\n const baseUrl = await this.getBaseUrl();\n\n const response = await this.fetchApi.fetch(`${baseUrl}/v1/feedback`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n accept: 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(\n `failed to capture feedback, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.esm.js","sources":["../../src/api/api.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nimport {\n Attachment,\n BaseMessage,\n CaptureFeedback,\n ConversationList,\n LCSModel,\n} from '../types';\n\nexport type LightspeedAPI = {\n getAllModels: () => Promise<LCSModel[]>;\n getConversationMessages: (conversation_id: string) => Promise<BaseMessage[]>;\n createMessage: (\n prompt: string,\n selectedModel: string,\n selectedProvider: string,\n conversation_id: string,\n attachments: Attachment[],\n ) => Promise<ReadableStreamDefaultReader>;\n deleteConversation: (\n conversation_id: string,\n ) => Promise<{ success: boolean }>;\n getConversations: () => Promise<ConversationList>;\n getFeedbackStatus: () => Promise<boolean>;\n captureFeedback: (payload: CaptureFeedback) => Promise<{ response: string }>;\n isTopicRestrictionEnabled: () => Promise<boolean>;\n};\n\nexport const lightspeedApiRef = createApiRef<LightspeedAPI>({\n id: 'plugin.lightspeed.service',\n});\n"],"names":[],"mappings":";;AA6CO,MAAM,mBAAmB,YAA4B,CAAA;AAAA,EAC1D,EAAI,EAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"api.esm.js","sources":["../../src/api/api.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nimport {\n Attachment,\n BaseMessage,\n CaptureFeedback,\n ConversationList,\n LCSModel,\n} from '../types';\n\nexport type LightspeedAPI = {\n getAllModels: () => Promise<LCSModel[]>;\n getConversationMessages: (conversation_id: string) => Promise<BaseMessage[]>;\n createMessage: (\n prompt: string,\n selectedModel: string,\n selectedProvider: string,\n conversation_id: string,\n attachments: Attachment[],\n ) => Promise<ReadableStreamDefaultReader>;\n deleteConversation: (\n conversation_id: string,\n ) => Promise<{ success: boolean }>;\n renameConversation: (\n conversation_id: string,\n newName: string,\n ) => Promise<{ success: boolean }>;\n getConversations: () => Promise<ConversationList>;\n getFeedbackStatus: () => Promise<boolean>;\n captureFeedback: (payload: CaptureFeedback) => Promise<{ response: string }>;\n isTopicRestrictionEnabled: () => Promise<boolean>;\n};\n\nexport const lightspeedApiRef = createApiRef<LightspeedAPI>({\n id: 'plugin.lightspeed.service',\n});\n"],"names":[],"mappings":";;AAiDO,MAAM,mBAAmB,YAA4B,CAAA;AAAA,EAC1D,EAAI,EAAA;AACN,CAAC;;;;"}
@@ -1,28 +1,104 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { Modal, ModalVariant, ModalHeader, ModalBody, ModalFooter, Button } from '@patternfly/react-core';
2
+ import CloseIcon from '@mui/icons-material/Close';
3
+ import Alert from '@mui/material/Alert';
4
+ import Box from '@mui/material/Box';
5
+ import Button from '@mui/material/Button';
6
+ import Dialog from '@mui/material/Dialog';
7
+ import DialogActions from '@mui/material/DialogActions';
8
+ import DialogContent from '@mui/material/DialogContent';
9
+ import DialogTitle from '@mui/material/DialogTitle';
10
+ import IconButton from '@mui/material/IconButton';
11
+ import Typography from '@mui/material/Typography';
12
+ import '@backstage/core-plugin-api';
13
+ import '@tanstack/react-query';
14
+ import '../api/api.esm.js';
15
+ import 'react-use';
16
+ import 'react';
17
+ import '@mui/icons-material/PushPin';
18
+ import { useDeleteConversation } from '../hooks/useDeleteConversation.esm.js';
19
+ import '@backstage/plugin-permission-react';
20
+ import '@red-hat-developer-hub/backstage-plugin-lightspeed-common';
3
21
  import { useTranslation } from '../hooks/useTranslation.esm.js';
4
22
 
5
23
  const DeleteModal = ({
6
24
  isOpen,
25
+ conversationId,
7
26
  onClose,
8
27
  onConfirm
9
28
  }) => {
10
29
  const { t } = useTranslation();
30
+ const {
31
+ mutateAsync: deleteConversation,
32
+ isError,
33
+ error,
34
+ isPending
35
+ } = useDeleteConversation();
36
+ const handleDeleteConversation = async () => {
37
+ try {
38
+ await deleteConversation({
39
+ conversation_id: conversationId,
40
+ invalidateCache: false
41
+ });
42
+ onConfirm();
43
+ } catch (e) {
44
+ console.warn(e);
45
+ }
46
+ };
11
47
  return /* @__PURE__ */ jsxs(
12
- Modal,
48
+ Dialog,
13
49
  {
14
- variant: ModalVariant.small,
15
- isOpen,
50
+ open: isOpen,
16
51
  onClose,
17
- ouiaId: "DeleteModal",
18
52
  "aria-labelledby": "delete-modal",
19
53
  "aria-describedby": "delete-modal-confiramtion",
20
54
  children: [
21
- /* @__PURE__ */ jsx(ModalHeader, { title: t("conversation.history.confirm.title") }),
22
- /* @__PURE__ */ jsx(ModalBody, { id: "delete-modal-body-confirmation", children: t("conversation.history.confirm.message") }),
23
- /* @__PURE__ */ jsxs(ModalFooter, { children: [
24
- /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: onConfirm, children: t("conversation.history.confirm.delete") }, "confirm"),
25
- /* @__PURE__ */ jsx(Button, { variant: "link", onClick: onClose, children: t("common.cancel") }, "cancel")
55
+ /* @__PURE__ */ jsx(DialogTitle, { sx: { p: "16px 20px", fontStyle: "inherit" }, children: /* @__PURE__ */ jsxs(
56
+ Box,
57
+ {
58
+ sx: {
59
+ display: "flex",
60
+ alignItems: "center",
61
+ gap: 1
62
+ },
63
+ children: [
64
+ /* @__PURE__ */ jsx(Typography, { component: "span", sx: { fontWeight: "bold" }, children: t("conversation.delete.confirm.title") }),
65
+ /* @__PURE__ */ jsx(
66
+ IconButton,
67
+ {
68
+ "aria-label": "close",
69
+ onClick: onClose,
70
+ title: t("common.close"),
71
+ size: "large",
72
+ sx: {
73
+ position: "absolute",
74
+ right: 1,
75
+ top: 1,
76
+ color: "grey.700"
77
+ },
78
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
79
+ }
80
+ )
81
+ ]
82
+ }
83
+ ) }),
84
+ /* @__PURE__ */ jsx(DialogContent, { id: "delete-modal-body-confirmation", children: t("conversation.delete.confirm.message") }),
85
+ isError && /* @__PURE__ */ jsx(Box, { maxWidth: "650px", marginLeft: "20px", children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: t("conversation.action.error", {
86
+ error: String(error)
87
+ }) }) }),
88
+ /* @__PURE__ */ jsxs(DialogActions, { style: { justifyContent: "left", padding: "20px" }, children: [
89
+ /* @__PURE__ */ jsx(
90
+ Button,
91
+ {
92
+ variant: "contained",
93
+ color: "error",
94
+ onClick: handleDeleteConversation,
95
+ style: { marginRight: "16px" },
96
+ disabled: isPending,
97
+ children: t("conversation.delete.confirm.action")
98
+ },
99
+ "confirm"
100
+ ),
101
+ /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: onClose, children: t("common.cancel") }, "cancel")
26
102
  ] })
27
103
  ]
28
104
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DeleteModal.esm.js","sources":["../../src/components/DeleteModal.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Button,\n Modal,\n ModalBody,\n ModalFooter,\n ModalHeader,\n ModalVariant,\n} from '@patternfly/react-core';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const DeleteModal = ({\n isOpen,\n onClose,\n onConfirm,\n}: {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n}) => {\n const { t } = useTranslation();\n\n return (\n <Modal\n variant={ModalVariant.small}\n isOpen={isOpen}\n onClose={onClose}\n ouiaId=\"DeleteModal\"\n aria-labelledby=\"delete-modal\"\n aria-describedby=\"delete-modal-confiramtion\"\n >\n <ModalHeader title={t('conversation.history.confirm.title')} />\n <ModalBody id=\"delete-modal-body-confirmation\">\n {t('conversation.history.confirm.message')}\n </ModalBody>\n <ModalFooter>\n <Button key=\"confirm\" variant=\"danger\" onClick={onConfirm}>\n {t('conversation.history.confirm.delete')}\n </Button>\n <Button key=\"cancel\" variant=\"link\" onClick={onClose}>\n {t('common.cancel')}\n </Button>\n </ModalFooter>\n </Modal>\n );\n};\n"],"names":[],"mappings":";;;;AA2BO,MAAM,cAAc,CAAC;AAAA,EAC1B,MAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAIM,KAAA;AACJ,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EACE,uBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAS,YAAa,CAAA,KAAA;AAAA,MACtB,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAO,EAAA,aAAA;AAAA,MACP,iBAAgB,EAAA,cAAA;AAAA,MAChB,kBAAiB,EAAA,2BAAA;AAAA,MAEjB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAY,EAAA,EAAA,KAAA,EAAO,CAAE,CAAA,oCAAoC,CAAG,EAAA,CAAA;AAAA,4BAC5D,SAAU,EAAA,EAAA,EAAA,EAAG,gCACX,EAAA,QAAA,EAAA,CAAA,CAAE,sCAAsC,CAC3C,EAAA,CAAA;AAAA,6BACC,WACC,EAAA,EAAA,QAAA,EAAA;AAAA,0BAAC,GAAA,CAAA,MAAA,EAAA,EAAqB,SAAQ,QAAS,EAAA,OAAA,EAAS,WAC7C,QAAE,EAAA,CAAA,CAAA,qCAAqC,KAD9B,SAEZ,CAAA;AAAA,0BACA,GAAA,CAAC,UAAoB,OAAQ,EAAA,MAAA,EAAO,SAAS,OAC1C,EAAA,QAAA,EAAA,CAAA,CAAE,eAAe,CAAA,EAAA,EADR,QAEZ;AAAA,SACF,EAAA;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
1
+ {"version":3,"file":"DeleteModal.esm.js","sources":["../../src/components/DeleteModal.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CloseIcon from '@mui/icons-material/Close';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\n\nimport { useDeleteConversation } from '../hooks';\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const DeleteModal = ({\n isOpen,\n conversationId,\n onClose,\n onConfirm,\n}: {\n isOpen: boolean;\n conversationId: string;\n onClose: () => void;\n onConfirm: () => void;\n}) => {\n const { t } = useTranslation();\n const {\n mutateAsync: deleteConversation,\n isError,\n error,\n isPending,\n } = useDeleteConversation();\n\n const handleDeleteConversation = async () => {\n try {\n await deleteConversation({\n conversation_id: conversationId,\n invalidateCache: false,\n });\n onConfirm();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n };\n\n return (\n <Dialog\n open={isOpen}\n onClose={onClose}\n aria-labelledby=\"delete-modal\"\n aria-describedby=\"delete-modal-confiramtion\"\n >\n <DialogTitle sx={{ p: '16px 20px', fontStyle: 'inherit' }}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n }}\n >\n <Typography component=\"span\" sx={{ fontWeight: 'bold' }}>\n {t('conversation.delete.confirm.title')}\n </Typography>\n\n <IconButton\n aria-label=\"close\"\n onClick={onClose}\n title={t('common.close')}\n size=\"large\"\n sx={{\n position: 'absolute',\n right: 1,\n top: 1,\n color: 'grey.700',\n }}\n >\n <CloseIcon />\n </IconButton>\n </Box>\n </DialogTitle>\n <DialogContent id=\"delete-modal-body-confirmation\">\n {t('conversation.delete.confirm.message')}\n </DialogContent>\n {isError && (\n <Box maxWidth=\"650px\" marginLeft=\"20px\">\n <Alert severity=\"error\">\n {t('conversation.action.error' as any, {\n error: String(error),\n })}\n </Alert>\n </Box>\n )}\n <DialogActions style={{ justifyContent: 'left', padding: '20px' }}>\n <Button\n key=\"confirm\"\n variant=\"contained\"\n color=\"error\"\n onClick={handleDeleteConversation}\n style={{ marginRight: '16px' }}\n disabled={isPending}\n >\n {t('conversation.delete.confirm.action')}\n </Button>\n <Button key=\"cancel\" variant=\"outlined\" onClick={onClose}>\n {t('common.cancel')}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}