@budibase/frontend-core 3.46.0 → 3.47.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "v3.
|
|
3
|
+
"version": "v3.47.0",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -24,5 +24,5 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"vitest": "^5.0.0"
|
|
26
26
|
},
|
|
27
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "adfff86585b1d393941175f58cbe74f2005616b4"
|
|
28
28
|
}
|
|
@@ -30,31 +30,64 @@
|
|
|
30
30
|
|
|
31
31
|
// Resolved either by this card's action (statusMessage) or elsewhere (poll).
|
|
32
32
|
let isResolved = $derived(!!statusMessage || resolution !== "pending")
|
|
33
|
+
let expanded = $state(true)
|
|
34
|
+
let showDetails = $derived(!showApproval || expanded)
|
|
35
|
+
|
|
36
|
+
const toggleDetails = () => {
|
|
37
|
+
expanded = !expanded
|
|
38
|
+
}
|
|
33
39
|
</script>
|
|
34
40
|
|
|
35
41
|
<div class="escalation-card" aria-live="polite">
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
{#if showApproval}
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
class="escalation-card-header escalation-card-toggle"
|
|
46
|
+
aria-expanded={expanded}
|
|
47
|
+
aria-label={`${expanded ? "Collapse" : "Expand"} approval details${title ? ` for ${title}` : ""}`}
|
|
48
|
+
onclick={toggleDetails}
|
|
49
|
+
>
|
|
50
|
+
<Icon name={isResolved ? "check-circle" : "clock"} size="M" />
|
|
51
|
+
<span class="escalation-card-title">{title || "Approval required"}</span>
|
|
52
|
+
<span class="escalation-card-header-end">
|
|
53
|
+
{#if !isResolved}
|
|
54
|
+
<span class="escalation-card-badge">Test mode</span>
|
|
55
|
+
{/if}
|
|
56
|
+
<span class="escalation-card-chevron" class:expanded>
|
|
57
|
+
<Icon name="caret-down" size="S" />
|
|
58
|
+
</span>
|
|
59
|
+
</span>
|
|
60
|
+
</button>
|
|
61
|
+
{:else}
|
|
62
|
+
<div class="escalation-card-header">
|
|
63
|
+
<Icon name={isResolved ? "check-circle" : "clock"} size="M" />
|
|
64
|
+
<span class="escalation-card-title">{title || "Approval required"}</span>
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
{#if showDetails}
|
|
69
|
+
{#if summary}
|
|
70
|
+
<Body size="S" color="var(--spectrum-global-color-gray-700)">
|
|
71
|
+
{summary}
|
|
72
|
+
</Body>
|
|
41
73
|
{/if}
|
|
42
|
-
</div>
|
|
43
74
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
75
|
+
{#if isResolved}
|
|
76
|
+
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
77
|
+
{statusMessage || "Response recorded."}
|
|
78
|
+
</Body>
|
|
79
|
+
{:else if showApproval}
|
|
80
|
+
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
81
|
+
Approve or reject here to simulate a reviewer response.
|
|
82
|
+
</Body>
|
|
83
|
+
{:else}
|
|
84
|
+
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
85
|
+
Awaiting a human response.
|
|
86
|
+
</Body>
|
|
87
|
+
{/if}
|
|
48
88
|
{/if}
|
|
49
89
|
|
|
50
|
-
{#if isResolved}
|
|
51
|
-
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
52
|
-
{statusMessage || "Response recorded."}
|
|
53
|
-
</Body>
|
|
54
|
-
{:else if showApproval}
|
|
55
|
-
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
56
|
-
Approve or reject here to simulate a reviewer response.
|
|
57
|
-
</Body>
|
|
90
|
+
{#if showApproval && !isResolved}
|
|
58
91
|
<div class="escalation-card-actions">
|
|
59
92
|
<Button cta disabled={resolving} on:click={() => onApprove?.()}>
|
|
60
93
|
Approve
|
|
@@ -63,10 +96,6 @@
|
|
|
63
96
|
Reject
|
|
64
97
|
</Button>
|
|
65
98
|
</div>
|
|
66
|
-
{:else}
|
|
67
|
-
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
68
|
-
Awaiting a human response.
|
|
69
|
-
</Body>
|
|
70
99
|
{/if}
|
|
71
100
|
</div>
|
|
72
101
|
|
|
@@ -89,13 +118,37 @@
|
|
|
89
118
|
align-items: center;
|
|
90
119
|
gap: var(--spacing-s);
|
|
91
120
|
}
|
|
121
|
+
.escalation-card-toggle {
|
|
122
|
+
width: 100%;
|
|
123
|
+
margin: 0;
|
|
124
|
+
padding: 0;
|
|
125
|
+
border: none;
|
|
126
|
+
background: none;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
text-align: left;
|
|
129
|
+
color: inherit;
|
|
130
|
+
font: inherit;
|
|
131
|
+
}
|
|
132
|
+
.escalation-card-header-end {
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
gap: var(--spacing-xs);
|
|
136
|
+
margin-left: auto;
|
|
137
|
+
}
|
|
138
|
+
.escalation-card-chevron {
|
|
139
|
+
display: flex;
|
|
140
|
+
color: var(--spectrum-global-color-gray-700);
|
|
141
|
+
transition: transform 130ms ease-in-out;
|
|
142
|
+
}
|
|
143
|
+
.escalation-card-chevron.expanded {
|
|
144
|
+
transform: rotate(180deg);
|
|
145
|
+
}
|
|
92
146
|
.escalation-card-title {
|
|
93
147
|
font-weight: 600;
|
|
94
148
|
font-size: 14px;
|
|
95
149
|
color: var(--spectrum-global-color-gray-900);
|
|
96
150
|
}
|
|
97
151
|
.escalation-card-badge {
|
|
98
|
-
margin-left: auto;
|
|
99
152
|
border-radius: 999px;
|
|
100
153
|
border: 1px solid var(--spectrum-global-color-blue-400);
|
|
101
154
|
color: var(--spectrum-global-color-blue-700);
|
|
@@ -412,6 +412,10 @@
|
|
|
412
412
|
}
|
|
413
413
|
})
|
|
414
414
|
|
|
415
|
+
// Tool/reasoning toggles mutate the chat DOM; the observer below would
|
|
416
|
+
// otherwise pin the viewport to the bottom as height changes.
|
|
417
|
+
let skipAutoScroll = false
|
|
418
|
+
|
|
415
419
|
const scrollToBottom = async () => {
|
|
416
420
|
await tick()
|
|
417
421
|
if (chatAreaElement) {
|
|
@@ -421,6 +425,9 @@
|
|
|
421
425
|
|
|
422
426
|
$effect(() => {
|
|
423
427
|
if (messages?.length) {
|
|
428
|
+
if (skipAutoScroll) {
|
|
429
|
+
return
|
|
430
|
+
}
|
|
424
431
|
scrollToBottom()
|
|
425
432
|
}
|
|
426
433
|
})
|
|
@@ -495,8 +502,17 @@
|
|
|
495
502
|
await sendMessage()
|
|
496
503
|
}
|
|
497
504
|
|
|
498
|
-
const
|
|
499
|
-
|
|
505
|
+
const toggleExpanded = (id: string) => {
|
|
506
|
+
const area = chatAreaElement
|
|
507
|
+
const previousScrollTop = area?.scrollTop ?? 0
|
|
508
|
+
skipAutoScroll = true
|
|
509
|
+
expandedTools = { ...expandedTools, [id]: !expandedTools[id] }
|
|
510
|
+
tick().then(() => {
|
|
511
|
+
if (area) {
|
|
512
|
+
area.scrollTop = previousScrollTop
|
|
513
|
+
}
|
|
514
|
+
skipAutoScroll = false
|
|
515
|
+
})
|
|
500
516
|
}
|
|
501
517
|
|
|
502
518
|
const formatToolOutput = (output: unknown): string =>
|
|
@@ -530,7 +546,12 @@
|
|
|
530
546
|
$effect(() => {
|
|
531
547
|
if (!chatAreaElement) return
|
|
532
548
|
|
|
533
|
-
const obs = new MutationObserver(
|
|
549
|
+
const obs = new MutationObserver(() => {
|
|
550
|
+
if (skipAutoScroll) {
|
|
551
|
+
return
|
|
552
|
+
}
|
|
553
|
+
scrollToBottom()
|
|
554
|
+
})
|
|
534
555
|
obs.observe(chatAreaElement, {
|
|
535
556
|
childList: true,
|
|
536
557
|
subtree: true,
|
|
@@ -543,8 +564,8 @@
|
|
|
543
564
|
})
|
|
544
565
|
</script>
|
|
545
566
|
|
|
546
|
-
<div class="chat-area"
|
|
547
|
-
<div class="chatbox">
|
|
567
|
+
<div class="chat-area">
|
|
568
|
+
<div class="chatbox" bind:this={chatAreaElement}>
|
|
548
569
|
{#if !hasMessages && !isRequestPending}
|
|
549
570
|
<div class="empty-state">
|
|
550
571
|
<div class="empty-state-icon">
|
|
@@ -597,35 +618,13 @@
|
|
|
597
618
|
interactive={!!reasoningText}
|
|
598
619
|
expanded={Boolean(expandedTools[reasoningId])}
|
|
599
620
|
content={reasoningText}
|
|
600
|
-
ontoggle={() =>
|
|
601
|
-
(expandedTools = {
|
|
602
|
-
...expandedTools,
|
|
603
|
-
[reasoningId]: !expandedTools[reasoningId],
|
|
604
|
-
})}
|
|
621
|
+
ontoggle={() => toggleExpanded(reasoningId)}
|
|
605
622
|
/>
|
|
606
623
|
{/if}
|
|
607
624
|
{#each message.parts ?? [] as part, partIndex}
|
|
608
625
|
{#if isTextUIPart(part)}
|
|
609
626
|
<MarkdownViewer value={part.text} />
|
|
610
|
-
{:else if isToolUIPart(part) && isRaisedEscalation(part.output)}
|
|
611
|
-
{@const card = escalationCardProps(part)}
|
|
612
|
-
<EscalationCard
|
|
613
|
-
title={card.title}
|
|
614
|
-
summary={card.summary}
|
|
615
|
-
resolution={card.resolution}
|
|
616
|
-
statusMessage={card.escalationId
|
|
617
|
-
? resolveMessages[card.escalationId]
|
|
618
|
-
: undefined}
|
|
619
|
-
showApproval={showInlineApproval}
|
|
620
|
-
resolving={!!card.escalationId &&
|
|
621
|
-
!!resolvingEscalations[card.escalationId]}
|
|
622
|
-
onApprove={() =>
|
|
623
|
-
card.escalationId && handleResolve(card.escalationId, true)}
|
|
624
|
-
onReject={() =>
|
|
625
|
-
card.escalationId &&
|
|
626
|
-
handleResolve(card.escalationId, false)}
|
|
627
|
-
/>
|
|
628
|
-
{:else if isToolUIPart(part)}
|
|
627
|
+
{:else if isToolUIPart(part) && !isRaisedEscalation(part.output)}
|
|
629
628
|
{@const rawToolName = getToolName(part)}
|
|
630
629
|
{@const displayToolName = formatToolName(
|
|
631
630
|
rawToolName,
|
|
@@ -642,7 +641,7 @@
|
|
|
642
641
|
class="tool-header"
|
|
643
642
|
class:tool-header-expanded={expandedTools[toolId]}
|
|
644
643
|
type="button"
|
|
645
|
-
onclick={() =>
|
|
644
|
+
onclick={() => toggleExpanded(toolId)}
|
|
646
645
|
>
|
|
647
646
|
<span
|
|
648
647
|
class="tool-chevron"
|
|
@@ -753,6 +752,27 @@
|
|
|
753
752
|
</ul>
|
|
754
753
|
</div>
|
|
755
754
|
{/if}
|
|
755
|
+
{#each message.parts ?? [] as part}
|
|
756
|
+
{#if isToolUIPart(part) && isRaisedEscalation(part.output)}
|
|
757
|
+
{@const card = escalationCardProps(part)}
|
|
758
|
+
<EscalationCard
|
|
759
|
+
title={card.title}
|
|
760
|
+
summary={card.summary}
|
|
761
|
+
resolution={card.resolution}
|
|
762
|
+
statusMessage={card.escalationId
|
|
763
|
+
? resolveMessages[card.escalationId]
|
|
764
|
+
: undefined}
|
|
765
|
+
showApproval={showInlineApproval}
|
|
766
|
+
resolving={!!card.escalationId &&
|
|
767
|
+
!!resolvingEscalations[card.escalationId]}
|
|
768
|
+
onApprove={() =>
|
|
769
|
+
card.escalationId && handleResolve(card.escalationId, true)}
|
|
770
|
+
onReject={() =>
|
|
771
|
+
card.escalationId &&
|
|
772
|
+
handleResolve(card.escalationId, false)}
|
|
773
|
+
/>
|
|
774
|
+
{/if}
|
|
775
|
+
{/each}
|
|
756
776
|
</div>
|
|
757
777
|
{/if}
|
|
758
778
|
{/if}
|
|
@@ -803,7 +823,7 @@
|
|
|
803
823
|
flex: 1 1 0;
|
|
804
824
|
display: flex;
|
|
805
825
|
flex-direction: column;
|
|
806
|
-
overflow
|
|
826
|
+
overflow: hidden;
|
|
807
827
|
min-height: 0;
|
|
808
828
|
font-family: var(--chat-font-sans, var(--font-sans));
|
|
809
829
|
--font-serif: var(--chat-font-sans, var(--font-sans));
|
|
@@ -819,7 +839,9 @@
|
|
|
819
839
|
flex-direction: column;
|
|
820
840
|
gap: 24px;
|
|
821
841
|
width: 100%;
|
|
822
|
-
flex: 1 1
|
|
842
|
+
flex: 1 1 0;
|
|
843
|
+
min-height: 0;
|
|
844
|
+
overflow-y: auto;
|
|
823
845
|
padding: 48px 0 24px 0;
|
|
824
846
|
}
|
|
825
847
|
|
|
@@ -868,14 +890,13 @@
|
|
|
868
890
|
}
|
|
869
891
|
|
|
870
892
|
.input-wrapper {
|
|
871
|
-
position: sticky;
|
|
872
|
-
bottom: 0;
|
|
873
893
|
width: 100%;
|
|
874
894
|
display: flex;
|
|
875
895
|
flex-direction: column;
|
|
876
896
|
flex-shrink: 0;
|
|
877
897
|
line-height: 1.4;
|
|
878
898
|
gap: 6px;
|
|
899
|
+
padding-top: 8px;
|
|
879
900
|
}
|
|
880
901
|
|
|
881
902
|
.input-footer {
|
|
@@ -983,7 +1004,9 @@
|
|
|
983
1004
|
}
|
|
984
1005
|
|
|
985
1006
|
.tool-part {
|
|
986
|
-
|
|
1007
|
+
display: flex;
|
|
1008
|
+
flex-direction: column;
|
|
1009
|
+
align-items: stretch;
|
|
987
1010
|
margin-top: var(--spacing-l);
|
|
988
1011
|
margin-bottom: 0;
|
|
989
1012
|
}
|
|
@@ -1076,22 +1099,17 @@
|
|
|
1076
1099
|
}
|
|
1077
1100
|
|
|
1078
1101
|
.tool-details {
|
|
1079
|
-
|
|
1080
|
-
top: 100%;
|
|
1081
|
-
left: 0;
|
|
1082
|
-
margin-top: var(--spacing-m);
|
|
1102
|
+
margin-top: var(--spacing-s);
|
|
1083
1103
|
width: 100%;
|
|
1084
1104
|
max-width: 100%;
|
|
1085
1105
|
box-sizing: border-box;
|
|
1086
1106
|
display: flex;
|
|
1087
1107
|
flex-direction: column;
|
|
1088
1108
|
gap: var(--spacing-s);
|
|
1089
|
-
background: var(--
|
|
1109
|
+
background: var(--spectrum-global-color-gray-75);
|
|
1090
1110
|
border: 1px solid var(--spectrum-global-color-gray-200);
|
|
1091
1111
|
border-radius: 6px;
|
|
1092
1112
|
padding: var(--spacing-m);
|
|
1093
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
1094
|
-
z-index: 1;
|
|
1095
1113
|
overflow-x: hidden;
|
|
1096
1114
|
min-width: 0;
|
|
1097
1115
|
}
|
package/src/fetch/UserFetch.ts
CHANGED
|
@@ -11,7 +11,6 @@ import BaseDataFetch, { DataFetchParams } from "./DataFetch"
|
|
|
11
11
|
|
|
12
12
|
interface UserFetchQuery {
|
|
13
13
|
appId?: string
|
|
14
|
-
workspaceId?: string
|
|
15
14
|
paginated?: boolean
|
|
16
15
|
string?: {
|
|
17
16
|
email: string
|
|
@@ -36,6 +35,7 @@ export default class UserFetch extends BaseDataFetch<
|
|
|
36
35
|
super({
|
|
37
36
|
...opts,
|
|
38
37
|
datasource: {
|
|
38
|
+
...opts.datasource,
|
|
39
39
|
type: "user",
|
|
40
40
|
},
|
|
41
41
|
})
|
|
@@ -56,9 +56,14 @@ export default class UserFetch extends BaseDataFetch<
|
|
|
56
56
|
async getData() {
|
|
57
57
|
const { limit, paginate } = this.options
|
|
58
58
|
const { cursor, query } = get(this.store)
|
|
59
|
+
const {
|
|
60
|
+
groupIds,
|
|
61
|
+
workspaceId: datasourceWorkspaceId,
|
|
62
|
+
workspaceRoleId,
|
|
63
|
+
} = this.options.datasource
|
|
59
64
|
|
|
60
65
|
// Convert old format to new one - we now allow use of the lucene format
|
|
61
|
-
const { appId, paginated,
|
|
66
|
+
const { appId, paginated, ...rest } = query
|
|
62
67
|
|
|
63
68
|
const finalQuery: SearchFilters = utils.isSupportedUserSearch(rest)
|
|
64
69
|
? rest
|
|
@@ -69,7 +74,9 @@ export default class UserFetch extends BaseDataFetch<
|
|
|
69
74
|
bookmark: cursor ?? undefined,
|
|
70
75
|
query: finalQuery ?? undefined,
|
|
71
76
|
appId: appId,
|
|
72
|
-
workspaceId,
|
|
77
|
+
workspaceId: datasourceWorkspaceId,
|
|
78
|
+
groupIds,
|
|
79
|
+
workspaceRoleId,
|
|
73
80
|
paginate: paginated || paginate,
|
|
74
81
|
limit,
|
|
75
82
|
}
|