@kodaris/krubble-app-components 1.0.87 → 1.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +66 -39
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +66 -39
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +39 -31
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +66 -39
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +36 -28
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -5862,31 +5862,42 @@
|
|
|
5862
5862
|
// --- Lifecycle ---
|
|
5863
5863
|
connectedCallback() {
|
|
5864
5864
|
super.connectedCallback();
|
|
5865
|
-
// Default to loading a
|
|
5866
|
-
//
|
|
5867
|
-
// conversation
|
|
5868
|
-
//
|
|
5869
|
-
// ({ type, content }); we only parse each row's
|
|
5870
|
-
// array string of ids) into
|
|
5865
|
+
// Default to loading a conversation's messages when the consumer hasn't
|
|
5866
|
+
// provided their own `load`. With `conversationId` set we rebuild that
|
|
5867
|
+
// conversation; with none set the user wants a NEW conversation, so we start
|
|
5868
|
+
// blank (no resume — the first message creates one via `send`). Rows already
|
|
5869
|
+
// match KRChatbotMessage ({ type, content }); we only parse each row's
|
|
5870
|
+
// `conversationFileIDs` (a JSON array string of ids) into `conversationFiles`.
|
|
5871
5871
|
if (!this.load) {
|
|
5872
5872
|
this.load = () => {
|
|
5873
5873
|
if (this.conversationId == null) {
|
|
5874
5874
|
return Promise.resolve([]);
|
|
5875
5875
|
}
|
|
5876
|
-
return krubbleHttp.Http.fetch({
|
|
5877
|
-
url: `/api/system/conversation/${this.conversationId}/messages`,
|
|
5878
|
-
})
|
|
5876
|
+
return krubbleHttp.Http.fetch({ url: `/api/system/conversation/${this.conversationId}/messages` })
|
|
5879
5877
|
.then((r) => r.json())
|
|
5880
|
-
.then((res) => (res?.data || []).map((msg) => {
|
|
5878
|
+
.then((res) => Promise.all((res?.data || []).map((msg) => {
|
|
5879
|
+
// Resolve this message's `conversationFileIDs` (a JSON array string of
|
|
5880
|
+
// ids) into full file objects — each fetch response IS the
|
|
5881
|
+
// KRChatbotConversationFile (id + niceName + mimeType), and niceName
|
|
5882
|
+
// drives the previewer's file-type detection. A failed fetch drops
|
|
5883
|
+
// that file rather than rendering a broken thumbnail.
|
|
5884
|
+
let ids = [];
|
|
5881
5885
|
try {
|
|
5882
|
-
|
|
5883
|
-
if (ids.length) {
|
|
5884
|
-
msg.conversationFiles = ids.map((id) => ({ conversationFileID: id }));
|
|
5885
|
-
}
|
|
5886
|
+
ids = JSON.parse(msg.conversationFileIDs || '[]');
|
|
5886
5887
|
}
|
|
5887
5888
|
catch { /* no/invalid attachments — leave empty */ }
|
|
5888
|
-
|
|
5889
|
-
|
|
5889
|
+
if (!ids.length) {
|
|
5890
|
+
return Promise.resolve(msg);
|
|
5891
|
+
}
|
|
5892
|
+
return Promise.all(ids.map((id) => krubbleHttp.Http.fetch({ url: `/api/system/conversationFile/${id}` })
|
|
5893
|
+
.then((r) => r.json())
|
|
5894
|
+
.then((meta) => meta?.data)
|
|
5895
|
+
.catch(() => null)))
|
|
5896
|
+
.then((files) => {
|
|
5897
|
+
msg.conversationFiles = files.filter((f) => f != null);
|
|
5898
|
+
return msg;
|
|
5899
|
+
});
|
|
5900
|
+
})));
|
|
5890
5901
|
};
|
|
5891
5902
|
}
|
|
5892
5903
|
this.load().then((messages) => {
|
|
@@ -6681,10 +6692,18 @@
|
|
|
6681
6692
|
}
|
|
6682
6693
|
/** Open the shared full-screen previewer for a message image. */
|
|
6683
6694
|
_openImage(img) {
|
|
6684
|
-
|
|
6685
|
-
|
|
6695
|
+
// Prefix the configured backend base URL — a raw fetch of a relative path
|
|
6696
|
+
// would hit the page origin (e.g. the dev server), not the backend.
|
|
6697
|
+
const preview = krubbleComponents.FilePreview.open({
|
|
6698
|
+
src: `${krubbleHttp.Http.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view`,
|
|
6686
6699
|
name: img.niceName || 'image',
|
|
6687
6700
|
});
|
|
6701
|
+
// The previewer's download button only fires a `download` event — the
|
|
6702
|
+
// consumer performs the actual download. Hit the view endpoint with
|
|
6703
|
+
// `?download=true` (Content-Disposition: attachment) in a new tab.
|
|
6704
|
+
preview.addEventListener('download', () => {
|
|
6705
|
+
window.open(`${krubbleHttp.Http.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view?download=true`, '_blank');
|
|
6706
|
+
});
|
|
6688
6707
|
}
|
|
6689
6708
|
/** Whether the send button is active: needs text or at least one image. */
|
|
6690
6709
|
_canSend() {
|
|
@@ -7533,7 +7552,7 @@
|
|
|
7533
7552
|
@click=${() => this._openImage(img)}
|
|
7534
7553
|
>
|
|
7535
7554
|
<img
|
|
7536
|
-
src="/api/system/conversationFile/${img.conversationFileID}/view"
|
|
7555
|
+
src="${krubbleHttp.Http.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view"
|
|
7537
7556
|
alt=${img.niceName || ''}
|
|
7538
7557
|
/>
|
|
7539
7558
|
</button>
|
|
@@ -7557,7 +7576,7 @@
|
|
|
7557
7576
|
${msg.content ? b `
|
|
7558
7577
|
<button
|
|
7559
7578
|
class="message-copy"
|
|
7560
|
-
title
|
|
7579
|
+
title=${this._copiedIndex === index ? 'Copied' : 'Copy'}
|
|
7561
7580
|
@click=${() => this._handleCopyMessage(msg.content, index)}
|
|
7562
7581
|
>
|
|
7563
7582
|
${this._copiedIndex === index ? b `
|
|
@@ -7571,7 +7590,6 @@
|
|
|
7571
7590
|
>
|
|
7572
7591
|
<path d="M20 6 9 17l-5-5" />
|
|
7573
7592
|
</svg>
|
|
7574
|
-
Copied
|
|
7575
7593
|
` : b `
|
|
7576
7594
|
<svg
|
|
7577
7595
|
viewBox="0 0 24 24"
|
|
@@ -7590,7 +7608,6 @@
|
|
|
7590
7608
|
/>
|
|
7591
7609
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
|
|
7592
7610
|
</svg>
|
|
7593
|
-
Copy
|
|
7594
7611
|
`}
|
|
7595
7612
|
</button>
|
|
7596
7613
|
` : A}
|
|
@@ -7957,7 +7974,7 @@
|
|
|
7957
7974
|
flex: 1;
|
|
7958
7975
|
display: flex;
|
|
7959
7976
|
flex-direction: column;
|
|
7960
|
-
gap:
|
|
7977
|
+
gap: 36px;
|
|
7961
7978
|
padding: 32px;
|
|
7962
7979
|
width: 100%;
|
|
7963
7980
|
max-width: 768px;
|
|
@@ -7986,6 +8003,17 @@
|
|
|
7986
8003
|
flex-direction: column;
|
|
7987
8004
|
max-width: 100%;
|
|
7988
8005
|
animation: chatbot-msg-in 0.3s ease-out;
|
|
8006
|
+
/* Reserve room for the copy button INSIDE the message box (so the button is
|
|
8007
|
+
part of the message's hover region — no dead zone to cross), then cancel
|
|
8008
|
+
that space for layout so message spacing is unchanged. */
|
|
8009
|
+
padding-bottom: 30px;
|
|
8010
|
+
margin-bottom: -30px;
|
|
8011
|
+
}
|
|
8012
|
+
|
|
8013
|
+
/* The reserved padding overhangs into the next message; lift the hovered one
|
|
8014
|
+
so its copy button isn't covered by (or stealing hover from) the sibling. */
|
|
8015
|
+
.message:hover {
|
|
8016
|
+
z-index: 1;
|
|
7989
8017
|
}
|
|
7990
8018
|
|
|
7991
8019
|
@keyframes chatbot-msg-in {
|
|
@@ -8034,43 +8062,41 @@
|
|
|
8034
8062
|
color: #b45309;
|
|
8035
8063
|
}
|
|
8036
8064
|
|
|
8037
|
-
/* Per-message copy button.
|
|
8038
|
-
|
|
8039
|
-
|
|
8065
|
+
/* Per-message copy button. Sits in the message's reserved bottom padding —
|
|
8066
|
+
inside the hover box, so moving the cursor down onto it never leaves the
|
|
8067
|
+
message. Height is reserved (via the message padding) so spacing doesn't
|
|
8068
|
+
jump; only opacity toggles on hover. */
|
|
8040
8069
|
.message-copy {
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8070
|
+
position: absolute;
|
|
8071
|
+
bottom: 0;
|
|
8072
|
+
left: 0;
|
|
8044
8073
|
display: inline-flex;
|
|
8045
8074
|
align-items: center;
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8075
|
+
justify-content: center;
|
|
8076
|
+
width: 26px;
|
|
8077
|
+
height: 26px;
|
|
8078
|
+
padding: 0;
|
|
8049
8079
|
background: none;
|
|
8050
8080
|
border: none;
|
|
8051
8081
|
border-radius: 6px;
|
|
8052
|
-
|
|
8053
|
-
font-size: 12px;
|
|
8054
|
-
color: #64668b;
|
|
8082
|
+
color: #000000;
|
|
8055
8083
|
cursor: pointer;
|
|
8056
8084
|
opacity: 0;
|
|
8057
|
-
pointer-events: none;
|
|
8058
8085
|
transition: opacity 0.15s, background-color 0.15s, color 0.15s;
|
|
8059
8086
|
}
|
|
8060
8087
|
|
|
8061
8088
|
.message--user .message-copy {
|
|
8062
|
-
|
|
8089
|
+
left: auto;
|
|
8090
|
+
right: 0;
|
|
8063
8091
|
}
|
|
8064
8092
|
|
|
8065
8093
|
.message:hover .message-copy,
|
|
8066
8094
|
.message-copy:focus-visible {
|
|
8067
8095
|
opacity: 1;
|
|
8068
|
-
pointer-events: auto;
|
|
8069
8096
|
}
|
|
8070
8097
|
|
|
8071
8098
|
.message-copy:hover {
|
|
8072
8099
|
background: rgba(0, 0, 0, 0.06);
|
|
8073
|
-
color: #1a1a2e;
|
|
8074
8100
|
}
|
|
8075
8101
|
|
|
8076
8102
|
.message-copy svg {
|
|
@@ -8644,6 +8670,7 @@
|
|
|
8644
8670
|
|
|
8645
8671
|
.message--user .attachments {
|
|
8646
8672
|
justify-content: flex-end;
|
|
8673
|
+
margin-bottom: 24px;
|
|
8647
8674
|
}
|
|
8648
8675
|
|
|
8649
8676
|
.attachment {
|