@budibase/frontend-core 3.23.37 → 3.23.47
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 +2 -2
- package/src/api/agents.ts +19 -40
- package/src/api/automations.ts +18 -3
- package/src/api/datasources.ts +18 -0
- package/src/api/tables.ts +13 -0
- package/src/components/Chatbox/index.svelte +22 -2
- package/src/components/grid/cells/HeaderCell.svelte +11 -2
- package/src/components/grid/cells/TextCell.svelte +14 -0
- package/src/components/grid/overlays/KeyboardManager.svelte +4 -0
- package/src/components/grid/stores/rows.ts +4 -0
- package/src/fetch/DataFetch.ts +1 -0
- package/src/utils/{table.js → table.ts} +10 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "3.23.
|
|
3
|
+
"version": "3.23.47",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -18,5 +18,5 @@
|
|
|
18
18
|
"shortid": "2.2.15",
|
|
19
19
|
"socket.io-client": "^4.7.5"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "534845c38ed0fe209406ebe45fd87f3de79f1da5"
|
|
22
22
|
}
|
package/src/api/agents.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentChat,
|
|
3
|
-
AgentToolSource,
|
|
4
|
-
AgentToolSourceWithTools,
|
|
5
3
|
ChatAgentRequest,
|
|
6
4
|
CreateAgentRequest,
|
|
7
5
|
CreateAgentResponse,
|
|
8
|
-
CreateToolSourceRequest,
|
|
9
6
|
FetchAgentHistoryResponse,
|
|
10
7
|
FetchAgentsResponse,
|
|
11
|
-
|
|
8
|
+
ToolMetadata,
|
|
12
9
|
UpdateAgentRequest,
|
|
13
10
|
UpdateAgentResponse,
|
|
14
11
|
} from "@budibase/types"
|
|
@@ -27,19 +24,23 @@ export interface AgentEndpoints {
|
|
|
27
24
|
removeChat: (chatId: string) => Promise<void>
|
|
28
25
|
fetchChats: (agentId: string) => Promise<FetchAgentHistoryResponse>
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
fetchAvailableTools: (toolSourceType: string) => Promise<Tool[]>
|
|
32
|
-
createToolSource: (
|
|
33
|
-
toolSource: CreateToolSourceRequest
|
|
34
|
-
) => Promise<{ created: true }>
|
|
35
|
-
updateToolSource: (toolSource: AgentToolSource) => Promise<AgentToolSource>
|
|
36
|
-
deleteToolSource: (toolSourceId: string) => Promise<{ deleted: true }>
|
|
27
|
+
fetchTools: () => Promise<ToolMetadata[]>
|
|
37
28
|
fetchAgents: () => Promise<FetchAgentsResponse>
|
|
38
29
|
createAgent: (agent: CreateAgentRequest) => Promise<CreateAgentResponse>
|
|
39
30
|
updateAgent: (agent: UpdateAgentRequest) => Promise<UpdateAgentResponse>
|
|
40
31
|
deleteAgent: (agentId: string) => Promise<{ deleted: true }>
|
|
41
32
|
}
|
|
42
33
|
|
|
34
|
+
const throwOnErrorChunk = () =>
|
|
35
|
+
new TransformStream<UIMessageChunk, UIMessageChunk>({
|
|
36
|
+
transform(chunk, controller) {
|
|
37
|
+
if (chunk.type === "error") {
|
|
38
|
+
throw new Error(chunk.errorText || "Agent action failed")
|
|
39
|
+
}
|
|
40
|
+
controller.enqueue(chunk)
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
|
|
43
44
|
export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
44
45
|
agentChatStream: async (chat, workspaceId) => {
|
|
45
46
|
const body: ChatAgentRequest = chat
|
|
@@ -69,8 +70,12 @@ export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
|
69
70
|
const chunkStream = response.body
|
|
70
71
|
.pipeThrough(new TextDecoderStream())
|
|
71
72
|
.pipeThrough(createSseToJsonTransformStream<UIMessageChunk>())
|
|
73
|
+
.pipeThrough(throwOnErrorChunk())
|
|
72
74
|
|
|
73
|
-
return readUIMessageStream({
|
|
75
|
+
return readUIMessageStream({
|
|
76
|
+
stream: chunkStream,
|
|
77
|
+
terminateOnError: true,
|
|
78
|
+
})
|
|
74
79
|
},
|
|
75
80
|
|
|
76
81
|
removeChat: async (chatId: string) => {
|
|
@@ -85,35 +90,9 @@ export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
|
85
90
|
})
|
|
86
91
|
},
|
|
87
92
|
|
|
88
|
-
|
|
93
|
+
fetchTools: async () => {
|
|
89
94
|
return await API.get({
|
|
90
|
-
url: `/api/agent
|
|
91
|
-
})
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
fetchAvailableTools: async (toolSourceType: string) => {
|
|
95
|
-
return await API.get({
|
|
96
|
-
url: `/api/agent/toolsource/${toolSourceType}/tools`,
|
|
97
|
-
})
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
createToolSource: async (toolSource: CreateToolSourceRequest) => {
|
|
101
|
-
return await API.post({
|
|
102
|
-
url: "/api/agent/toolsource",
|
|
103
|
-
body: toolSource as any,
|
|
104
|
-
})
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
updateToolSource: async (toolSource: AgentToolSource) => {
|
|
108
|
-
return await API.put({
|
|
109
|
-
url: "/api/agent/toolsource",
|
|
110
|
-
body: toolSource as any,
|
|
111
|
-
})
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
deleteToolSource: async (toolSourceId: string) => {
|
|
115
|
-
return await API.delete({
|
|
116
|
-
url: `/api/agent/toolsource/${toolSourceId}`,
|
|
95
|
+
url: `/api/agent/tools`,
|
|
117
96
|
})
|
|
118
97
|
},
|
|
119
98
|
|
package/src/api/automations.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
SearchAutomationLogsResponse,
|
|
11
11
|
TestAutomationRequest,
|
|
12
12
|
TestAutomationResponse,
|
|
13
|
+
TestProgressState,
|
|
13
14
|
TriggerAutomationRequest,
|
|
14
15
|
TriggerAutomationResponse,
|
|
15
16
|
UpdateAutomationRequest,
|
|
@@ -40,8 +41,10 @@ export interface AutomationEndpoints {
|
|
|
40
41
|
) => Promise<TriggerAutomationResponse>
|
|
41
42
|
testAutomation: (
|
|
42
43
|
automationdId: string,
|
|
43
|
-
data: TestAutomationRequest
|
|
44
|
+
data: TestAutomationRequest,
|
|
45
|
+
options?: { async?: boolean }
|
|
44
46
|
) => Promise<TestAutomationResponse>
|
|
47
|
+
getAutomationTestStatus: (automationId: string) => Promise<TestProgressState>
|
|
45
48
|
getAutomationDefinitions: () => Promise<GetAutomationStepDefinitionsResponse>
|
|
46
49
|
getAutomationLogs: (
|
|
47
50
|
options: SearchAutomationLogsRequest
|
|
@@ -69,13 +72,25 @@ export const buildAutomationEndpoints = (
|
|
|
69
72
|
* @param automationId the ID of the automation to test
|
|
70
73
|
* @param data the test data to run against the automation
|
|
71
74
|
*/
|
|
72
|
-
testAutomation: async (automationId, data) => {
|
|
75
|
+
testAutomation: async (automationId, data, options = {}) => {
|
|
76
|
+
const params = new URLSearchParams()
|
|
77
|
+
if (options.async) {
|
|
78
|
+
params.set("async", "true")
|
|
79
|
+
}
|
|
80
|
+
const qs = params.toString()
|
|
81
|
+
const url = `/api/automations/${automationId}/test${qs ? `?${qs}` : ""}`
|
|
73
82
|
return await API.post({
|
|
74
|
-
url
|
|
83
|
+
url,
|
|
75
84
|
body: data,
|
|
76
85
|
})
|
|
77
86
|
},
|
|
78
87
|
|
|
88
|
+
getAutomationTestStatus: async automationId => {
|
|
89
|
+
return await API.get({
|
|
90
|
+
url: `/api/automations/${automationId}/test/status`,
|
|
91
|
+
})
|
|
92
|
+
},
|
|
93
|
+
|
|
79
94
|
/**
|
|
80
95
|
* Gets a list of all automations.
|
|
81
96
|
*/
|
package/src/api/datasources.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
DeleteDatasourceResponse,
|
|
8
8
|
FetchDatasourceInfoRequest,
|
|
9
9
|
FetchDatasourceInfoResponse,
|
|
10
|
+
FetchDatasourceRelationshipInfoRequest,
|
|
11
|
+
FetchDatasourceRelationshipInfoResponse,
|
|
10
12
|
FetchDatasourceViewInfoRequest,
|
|
11
13
|
FetchDatasourceViewInfoResponse,
|
|
12
14
|
UpdateDatasourceRequest,
|
|
@@ -41,6 +43,9 @@ export interface DatasourceEndpoints {
|
|
|
41
43
|
fetchViewInfoForDatasource: (
|
|
42
44
|
datasource: Datasource
|
|
43
45
|
) => Promise<FetchDatasourceViewInfoResponse>
|
|
46
|
+
fetchRelationshipInfoForDatasource: (
|
|
47
|
+
datasource: Datasource
|
|
48
|
+
) => Promise<FetchDatasourceRelationshipInfoResponse>
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
export const buildDatasourceEndpoints = (
|
|
@@ -134,4 +139,17 @@ export const buildDatasourceEndpoints = (
|
|
|
134
139
|
body: { datasource },
|
|
135
140
|
})
|
|
136
141
|
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Fetch relationship names available within the datasource
|
|
145
|
+
*/
|
|
146
|
+
fetchRelationshipInfoForDatasource: async (datasource: Datasource) => {
|
|
147
|
+
return await API.post<
|
|
148
|
+
FetchDatasourceRelationshipInfoRequest,
|
|
149
|
+
FetchDatasourceRelationshipInfoResponse
|
|
150
|
+
>({
|
|
151
|
+
url: `/api/datasources/relationships`,
|
|
152
|
+
body: { datasource },
|
|
153
|
+
})
|
|
154
|
+
},
|
|
137
155
|
})
|
package/src/api/tables.ts
CHANGED
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
MigrateTableResponse,
|
|
19
19
|
MigrateTableRequest,
|
|
20
20
|
DeleteTableResponse,
|
|
21
|
+
PublishTableRequest,
|
|
22
|
+
PublishTableResponse,
|
|
21
23
|
} from "@budibase/types"
|
|
22
24
|
import { BaseAPIClient } from "./types"
|
|
23
25
|
|
|
@@ -52,6 +54,10 @@ export interface TableEndpoints {
|
|
|
52
54
|
oldColumn: string,
|
|
53
55
|
newColumn: string
|
|
54
56
|
) => Promise<MigrateTableResponse>
|
|
57
|
+
publishTable: (
|
|
58
|
+
tableId: string,
|
|
59
|
+
opts?: PublishTableRequest
|
|
60
|
+
) => Promise<PublishTableResponse>
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
export const buildTableEndpoints = (API: BaseAPIClient): TableEndpoints => ({
|
|
@@ -191,6 +197,13 @@ export const buildTableEndpoints = (API: BaseAPIClient): TableEndpoints => ({
|
|
|
191
197
|
})
|
|
192
198
|
},
|
|
193
199
|
|
|
200
|
+
publishTable: async (tableId, opts) => {
|
|
201
|
+
return await API.post<PublishTableRequest, PublishTableResponse>({
|
|
202
|
+
url: `/api/tables/${tableId}/publish`,
|
|
203
|
+
body: opts,
|
|
204
|
+
})
|
|
205
|
+
},
|
|
206
|
+
|
|
194
207
|
/**
|
|
195
208
|
* Duplicates a table without its data.
|
|
196
209
|
* @param tableId the ID of the table to duplicate
|
|
@@ -16,12 +16,16 @@
|
|
|
16
16
|
export let chat: AgentChat
|
|
17
17
|
export let loading: boolean = false
|
|
18
18
|
|
|
19
|
-
const dispatch = createEventDispatcher<{
|
|
19
|
+
const dispatch = createEventDispatcher<{
|
|
20
|
+
chatSaved: { chatId?: string; chat: AgentChat }
|
|
21
|
+
}>()
|
|
20
22
|
|
|
21
23
|
let inputValue = ""
|
|
22
24
|
let chatAreaElement: HTMLDivElement
|
|
23
25
|
let observer: MutationObserver
|
|
24
26
|
let textareaElement: HTMLTextAreaElement
|
|
27
|
+
let lastFocusedChatId: string | undefined
|
|
28
|
+
let lastFocusedNewChat: AgentChat | undefined
|
|
25
29
|
|
|
26
30
|
$: if (chat?.messages?.length) {
|
|
27
31
|
scrollToBottom()
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
loading = false
|
|
78
|
-
dispatch("chatSaved", { chatId: chat._id
|
|
82
|
+
dispatch("chatSaved", { chatId: chat._id, chat })
|
|
79
83
|
} catch (err: any) {
|
|
80
84
|
console.error(err)
|
|
81
85
|
notifications.error(err.message)
|
|
@@ -111,6 +115,22 @@
|
|
|
111
115
|
}
|
|
112
116
|
})
|
|
113
117
|
|
|
118
|
+
$: {
|
|
119
|
+
const currentId = chat?._id
|
|
120
|
+
const isNewChat =
|
|
121
|
+
!currentId && (!chat?.messages || chat.messages.length === 0)
|
|
122
|
+
const shouldFocus =
|
|
123
|
+
textareaElement &&
|
|
124
|
+
((currentId && currentId !== lastFocusedChatId) ||
|
|
125
|
+
(isNewChat && chat && chat !== lastFocusedNewChat))
|
|
126
|
+
|
|
127
|
+
if (shouldFocus) {
|
|
128
|
+
tick().then(() => textareaElement?.focus())
|
|
129
|
+
lastFocusedChatId = currentId
|
|
130
|
+
lastFocusedNewChat = isNewChat ? chat : undefined
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
114
134
|
onDestroy(() => {
|
|
115
135
|
observer.disconnect()
|
|
116
136
|
})
|
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
import { getColumnIcon } from "../../../utils/schema"
|
|
7
7
|
import MigrationModal from "../controls/MigrationModal.svelte"
|
|
8
8
|
import { debounce } from "../../../utils/utils"
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
FieldType,
|
|
11
|
+
FormulaType,
|
|
12
|
+
SortOrder,
|
|
13
|
+
isStaticFormula,
|
|
14
|
+
} from "@budibase/types"
|
|
10
15
|
import { TableNames } from "../../../constants"
|
|
11
16
|
import GridPopover from "../overlays/GridPopover.svelte"
|
|
12
17
|
|
|
@@ -73,7 +78,11 @@
|
|
|
73
78
|
descending: "high-low",
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
|
-
|
|
81
|
+
let schemaType = column.schema?.type
|
|
82
|
+
if (isStaticFormula(column.schema)) {
|
|
83
|
+
schemaType = column.schema.responseType
|
|
84
|
+
}
|
|
85
|
+
switch (schemaType) {
|
|
77
86
|
case FieldType.NUMBER:
|
|
78
87
|
case FieldType.BIGINT:
|
|
79
88
|
return {
|
|
@@ -11,10 +11,19 @@
|
|
|
11
11
|
|
|
12
12
|
let input
|
|
13
13
|
let active = false
|
|
14
|
+
let isComposing = false
|
|
14
15
|
|
|
15
16
|
$: editable = focused && !readonly
|
|
16
17
|
$: displayValue = format?.(value) ?? value ?? ""
|
|
17
18
|
|
|
19
|
+
const handleCompositionStart = () => {
|
|
20
|
+
isComposing = true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const handleCompositionEnd = () => {
|
|
24
|
+
isComposing = false
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
const handleChange = e => {
|
|
19
28
|
onChange(e.target.value)
|
|
20
29
|
}
|
|
@@ -23,6 +32,9 @@
|
|
|
23
32
|
if (!active) {
|
|
24
33
|
return false
|
|
25
34
|
}
|
|
35
|
+
if (e.key === "Enter" && (isComposing || e.isComposing)) {
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
26
38
|
if (e.key === "Enter") {
|
|
27
39
|
input?.blur()
|
|
28
40
|
const event = new KeyboardEvent("keydown", { key: "ArrowDown" })
|
|
@@ -46,6 +58,8 @@
|
|
|
46
58
|
bind:this={input}
|
|
47
59
|
on:focus={() => (active = true)}
|
|
48
60
|
on:blur={() => (active = false)}
|
|
61
|
+
on:compositionstart={handleCompositionStart}
|
|
62
|
+
on:compositionend={handleCompositionEnd}
|
|
49
63
|
{type}
|
|
50
64
|
value={value ?? ""}
|
|
51
65
|
on:change={handleChange}
|
|
@@ -35,6 +35,7 @@ interface RowStore {
|
|
|
35
35
|
interface RowDerivedStore {
|
|
36
36
|
rows: RowStore["rows"]
|
|
37
37
|
rowLookupMap: Readable<Record<string, IndexedUIRow>>
|
|
38
|
+
rowCount: Readable<number>
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
interface RowActionStore {
|
|
@@ -168,12 +169,15 @@ export const deriveStores = (context: StoreContext): RowDerivedStore => {
|
|
|
168
169
|
return map
|
|
169
170
|
})
|
|
170
171
|
|
|
172
|
+
const rowCount = derived(rows, $rows => $rows.length)
|
|
173
|
+
|
|
171
174
|
return {
|
|
172
175
|
rows: {
|
|
173
176
|
...rows,
|
|
174
177
|
subscribe: enrichedRows.subscribe,
|
|
175
178
|
},
|
|
176
179
|
rowLookupMap,
|
|
180
|
+
rowCount,
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
183
|
|
package/src/fetch/DataFetch.ts
CHANGED
|
@@ -241,6 +241,7 @@ export default abstract class BaseDataFetch<
|
|
|
241
241
|
if (
|
|
242
242
|
fieldSchema?.type === FieldType.NUMBER ||
|
|
243
243
|
fieldSchema?.type === FieldType.BIGINT ||
|
|
244
|
+
fieldSchema?.responseType === FieldType.NUMBER ||
|
|
244
245
|
("calculationType" in fieldSchema && fieldSchema?.calculationType)
|
|
245
246
|
) {
|
|
246
247
|
this.options.sortType = SortType.NUMBER
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as sharedCore from "@budibase/shared-core"
|
|
2
|
+
import { UIFieldSchema, isStaticFormula } from "@budibase/types"
|
|
2
3
|
|
|
3
|
-
export function canBeDisplayColumn(column) {
|
|
4
|
+
export function canBeDisplayColumn(column: UIFieldSchema) {
|
|
4
5
|
if (!sharedCore.canBeDisplayColumn(column.type)) {
|
|
5
6
|
return false
|
|
6
7
|
}
|
|
@@ -11,16 +12,20 @@ export function canBeDisplayColumn(column) {
|
|
|
11
12
|
return true
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export function canBeSortColumn(
|
|
15
|
+
export function canBeSortColumn(columnSchema: UIFieldSchema) {
|
|
15
16
|
// Allow sorting by calculation columns
|
|
16
|
-
if (
|
|
17
|
+
if (columnSchema.calculationType) {
|
|
17
18
|
return true
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
// Allow static-only formula columns to be sorted
|
|
21
|
+
if (isStaticFormula(columnSchema)) {
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
if (!sharedCore.canBeSortColumn(columnSchema.type)) {
|
|
20
25
|
return false
|
|
21
26
|
}
|
|
22
27
|
// If it's a related column (only available in the frontend), don't allow using it as display column
|
|
23
|
-
if (
|
|
28
|
+
if (columnSchema.related) {
|
|
24
29
|
return false
|
|
25
30
|
}
|
|
26
31
|
return true
|