@budibase/frontend-core 2.8.29-alpha.1 → 2.8.29

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,17 +1,17 @@
1
1
  {
2
2
  "name": "@budibase/frontend-core",
3
- "version": "2.8.29-alpha.1",
3
+ "version": "2.8.29",
4
4
  "description": "Budibase frontend core libraries used in builder and client",
5
5
  "author": "Budibase",
6
6
  "license": "MPL-2.0",
7
7
  "svelte": "src/index.js",
8
8
  "dependencies": {
9
- "@budibase/bbui": "2.8.29-alpha.1",
10
- "@budibase/shared-core": "2.8.29-alpha.1",
9
+ "@budibase/bbui": "2.8.29",
10
+ "@budibase/shared-core": "2.8.29",
11
11
  "dayjs": "^1.11.7",
12
12
  "lodash": "^4.17.21",
13
13
  "socket.io-client": "^4.6.1",
14
14
  "svelte": "^3.46.2"
15
15
  },
16
- "gitHead": "22e6d6f053f4ce55f24a07e86c7221f56c05f14c"
16
+ "gitHead": "c5b487659606add604ff3211f422c26c4924bc35"
17
17
  }
package/src/api/app.js CHANGED
@@ -123,15 +123,6 @@ export const buildAppEndpoints = API => ({
123
123
  })
124
124
  },
125
125
 
126
- /**
127
- * Gets budibase platform debug information.
128
- */
129
- fetchSystemDebugInfo: async () => {
130
- return await API.get({
131
- url: `/api/debug/diagnostics`,
132
- })
133
- },
134
-
135
126
  /**
136
127
  * Syncs an app with the production database.
137
128
  * @param appId the ID of the app to sync
package/src/api/index.js CHANGED
@@ -30,7 +30,6 @@ import { buildBackupsEndpoints } from "./backups"
30
30
  import { buildEnvironmentVariableEndpoints } from "./environmentVariables"
31
31
  import { buildEventEndpoints } from "./events"
32
32
  import { buildAuditLogsEndpoints } from "./auditLogs"
33
- import { buildLogsEndpoints } from "./logs"
34
33
 
35
34
  /**
36
35
  * Random identifier to uniquely identify a session in a tab. This is
@@ -278,6 +277,5 @@ export const createAPIClient = config => {
278
277
  ...buildEnvironmentVariableEndpoints(API),
279
278
  ...buildEventEndpoints(API),
280
279
  ...buildAuditLogsEndpoints(API),
281
- ...buildLogsEndpoints(API),
282
280
  }
283
281
  }
@@ -1,23 +1,58 @@
1
1
  <script>
2
- import { Avatar, AbsTooltip, TooltipPosition } from "@budibase/bbui"
2
+ import { Avatar, Tooltip } from "@budibase/bbui"
3
3
  import { helpers } from "@budibase/shared-core"
4
4
 
5
5
  export let user
6
- export let size = "S"
7
- export let tooltipPosition = TooltipPosition.Top
6
+ export let size
7
+ export let tooltipDirection = "top"
8
8
  export let showTooltip = true
9
+
10
+ $: tooltipStyle = getTooltipStyle(tooltipDirection)
11
+
12
+ const getTooltipStyle = direction => {
13
+ if (!direction) {
14
+ return ""
15
+ }
16
+ if (direction === "top") {
17
+ return "transform: translateX(-50%) translateY(-100%);"
18
+ } else if (direction === "bottom") {
19
+ return "transform: translateX(-50%) translateY(100%);"
20
+ }
21
+ }
9
22
  </script>
10
23
 
11
24
  {#if user}
12
- <AbsTooltip
13
- text={showTooltip ? helpers.getUserLabel(user) : null}
14
- position={tooltipPosition}
15
- color={helpers.getUserColor(user)}
16
- >
25
+ <div class="user-avatar">
17
26
  <Avatar
18
27
  {size}
19
28
  initials={helpers.getUserInitials(user)}
20
29
  color={helpers.getUserColor(user)}
21
30
  />
22
- </AbsTooltip>
31
+ {#if showTooltip}
32
+ <div class="tooltip" style={tooltipStyle}>
33
+ <Tooltip
34
+ direction={tooltipDirection}
35
+ textWrapping
36
+ text={user.email}
37
+ size="S"
38
+ />
39
+ </div>
40
+ {/if}
41
+ </div>
23
42
  {/if}
43
+
44
+ <style>
45
+ .user-avatar {
46
+ position: relative;
47
+ }
48
+ .tooltip {
49
+ display: none;
50
+ position: absolute;
51
+ top: 0;
52
+ left: 50%;
53
+ white-space: nowrap;
54
+ }
55
+ .user-avatar:hover .tooltip {
56
+ display: block;
57
+ }
58
+ </style>
@@ -258,7 +258,7 @@
258
258
  class:wrap={editable || contentLines > 1}
259
259
  on:wheel={e => (focused ? e.stopPropagation() : null)}
260
260
  >
261
- {#each value || [] as relationship}
261
+ {#each value || [] as relationship, idx}
262
262
  {#if relationship.primaryDisplay}
263
263
  <div class="badge">
264
264
  <span
@@ -0,0 +1,16 @@
1
+ <script>
2
+ import { ActionButton } from "@budibase/bbui"
3
+ import { getContext } from "svelte"
4
+
5
+ const { config, dispatch } = getContext("grid")
6
+ </script>
7
+
8
+ <ActionButton
9
+ icon="TableColumnAddRight"
10
+ quiet
11
+ size="M"
12
+ on:click={() => dispatch("add-column")}
13
+ disabled={!$config.allowSchemaChanges}
14
+ >
15
+ Add column
16
+ </ActionButton>
@@ -0,0 +1,18 @@
1
+ <script>
2
+ import { ActionButton } from "@budibase/bbui"
3
+ import { getContext } from "svelte"
4
+
5
+ const { dispatch, columns, stickyColumn, config, loaded } = getContext("grid")
6
+ </script>
7
+
8
+ <ActionButton
9
+ icon="TableRowAddBottom"
10
+ quiet
11
+ size="M"
12
+ on:click={() => dispatch("add-row-inline")}
13
+ disabled={!loaded ||
14
+ !$config.allowAddRows ||
15
+ (!$columns.length && !$stickyColumn)}
16
+ >
17
+ Add row
18
+ </ActionButton>
@@ -71,7 +71,6 @@
71
71
  contentLines,
72
72
  gridFocused,
73
73
  error,
74
- canAddRows,
75
74
  } = context
76
75
 
77
76
  // Keep config store up to date with props
@@ -144,7 +143,7 @@
144
143
  <HeaderRow />
145
144
  <GridBody />
146
145
  </div>
147
- {#if $canAddRows}
146
+ {#if allowAddRows}
148
147
  <NewRow />
149
148
  {/if}
150
149
  <div class="overlays">
@@ -9,7 +9,7 @@
9
9
  renderedRows,
10
10
  renderedColumns,
11
11
  rowVerticalInversionIndex,
12
- canAddRows,
12
+ config,
13
13
  hoveredRowId,
14
14
  dispatch,
15
15
  isDragging,
@@ -43,7 +43,7 @@
43
43
  invertY={idx >= $rowVerticalInversionIndex}
44
44
  />
45
45
  {/each}
46
- {#if $canAddRows}
46
+ {#if $config.allowAddRows && $renderedColumns.length}
47
47
  <div
48
48
  class="blank"
49
49
  class:highlighted={$hoveredRowId === BlankRowID}
@@ -2,7 +2,7 @@
2
2
  import { getContext } from "svelte"
3
3
  import GridScrollWrapper from "./GridScrollWrapper.svelte"
4
4
  import HeaderCell from "../cells/HeaderCell.svelte"
5
- import { Icon, TempTooltip, TooltipType } from "@budibase/bbui"
5
+ import { Icon } from "@budibase/bbui"
6
6
 
7
7
  const {
8
8
  renderedColumns,
@@ -11,13 +11,10 @@
11
11
  hiddenColumnsWidth,
12
12
  width,
13
13
  config,
14
- hasNonAutoColumn,
15
- tableId,
16
- loading,
17
14
  } = getContext("grid")
18
15
 
19
16
  $: columnsWidth = $renderedColumns.reduce(
20
- (total, col) => total + col.width,
17
+ (total, col) => (total += col.width),
21
18
  0
22
19
  )
23
20
  $: end = $hiddenColumnsWidth + columnsWidth - 1 - $scroll.left
@@ -33,21 +30,13 @@
33
30
  </div>
34
31
  </GridScrollWrapper>
35
32
  {#if $config.allowSchemaChanges}
36
- {#key $tableId}
37
- <TempTooltip
38
- text="Click here to create your first column"
39
- type={TooltipType.Info}
40
- condition={!$hasNonAutoColumn && !$loading}
41
- >
42
- <div
43
- class="add"
44
- style="left:{left}px;"
45
- on:click={() => dispatch("add-column")}
46
- >
47
- <Icon name="Add" />
48
- </div>
49
- </TempTooltip>
50
- {/key}
33
+ <div
34
+ class="add"
35
+ style="left:{left}px"
36
+ on:click={() => dispatch("add-column")}
37
+ >
38
+ <Icon name="Add" />
39
+ </div>
51
40
  {/if}
52
41
  </div>
53
42
 
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { getContext, onDestroy, onMount, tick } from "svelte"
3
- import { Icon, Button, TempTooltip, TooltipType } from "@budibase/bbui"
3
+ import { Icon, Button } from "@budibase/bbui"
4
4
  import GridScrollWrapper from "./GridScrollWrapper.svelte"
5
5
  import DataCell from "../cells/DataCell.svelte"
6
6
  import { fade } from "svelte/transition"
@@ -27,8 +27,7 @@
27
27
  rowVerticalInversionIndex,
28
28
  columnHorizontalInversionIndex,
29
29
  selectedRows,
30
- loading,
31
- canAddRows,
30
+ config,
32
31
  } = getContext("grid")
33
32
 
34
33
  let visible = false
@@ -41,7 +40,6 @@
41
40
  $: $tableId, (visible = false)
42
41
  $: invertY = shouldInvertY(offset, $rowVerticalInversionIndex, $renderedRows)
43
42
  $: selectedRowCount = Object.values($selectedRows).length
44
- $: hasNoRows = !$rows.length
45
43
 
46
44
  const shouldInvertY = (offset, inversionIndex, rows) => {
47
45
  if (offset === 0) {
@@ -149,22 +147,16 @@
149
147
  </script>
150
148
 
151
149
  <!-- New row FAB -->
152
- <TempTooltip
153
- text="Click here to create your first row"
154
- condition={hasNoRows && !$loading}
155
- type={TooltipType.Info}
156
- >
157
- {#if !visible && !selectedRowCount && $canAddRows}
158
- <div
159
- class="new-row-fab"
160
- on:click={() => dispatch("add-row-inline")}
161
- transition:fade|local={{ duration: 130 }}
162
- class:offset={!$stickyColumn}
163
- >
164
- <Icon name="Add" size="S" />
165
- </div>
166
- {/if}
167
- </TempTooltip>
150
+ {#if !visible && !selectedRowCount && $config.allowAddRows && firstColumn}
151
+ <div
152
+ class="new-row-fab"
153
+ on:click={() => dispatch("add-row-inline")}
154
+ transition:fade|local={{ duration: 130 }}
155
+ class:offset={!$stickyColumn}
156
+ >
157
+ <Icon name="Add" size="S" />
158
+ </div>
159
+ {/if}
168
160
 
169
161
  <!-- Only show new row functionality if we have any columns -->
170
162
  {#if visible}
@@ -13,10 +13,11 @@
13
13
  rows,
14
14
  selectedRows,
15
15
  stickyColumn,
16
+ renderedColumns,
16
17
  renderedRows,
17
18
  focusedCellId,
18
19
  hoveredRowId,
19
- canAddRows,
20
+ config,
20
21
  selectedCellMap,
21
22
  focusedRow,
22
23
  scrollLeft,
@@ -92,7 +93,7 @@
92
93
  {/if}
93
94
  </div>
94
95
  {/each}
95
- {#if $canAddRows}
96
+ {#if $config.allowAddRows && ($renderedColumns.length || $stickyColumn)}
96
97
  <div
97
98
  class="row new"
98
99
  on:mouseenter={$isDragging
@@ -16,7 +16,6 @@
16
16
  config,
17
17
  menu,
18
18
  gridFocused,
19
- canAddRows,
20
19
  } = getContext("grid")
21
20
 
22
21
  const ignoredOriginSelectors = [
@@ -46,7 +45,7 @@
46
45
  e.preventDefault()
47
46
  focusFirstCell()
48
47
  } else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
49
- if ($canAddRows) {
48
+ if ($config.allowAddRows) {
50
49
  e.preventDefault()
51
50
  dispatch("add-row-inline")
52
51
  }
@@ -100,7 +99,7 @@
100
99
  }
101
100
  break
102
101
  case "Enter":
103
- if ($canAddRows) {
102
+ if ($config.allowAddRows) {
104
103
  dispatch("add-row-inline")
105
104
  }
106
105
  }
@@ -17,7 +17,6 @@
17
17
  focusedCellAPI,
18
18
  focusedRowId,
19
19
  notifications,
20
- canAddRows,
21
20
  } = getContext("grid")
22
21
 
23
22
  $: style = makeStyle($menu)
@@ -94,7 +93,7 @@
94
93
  </MenuItem>
95
94
  <MenuItem
96
95
  icon="Duplicate"
97
- disabled={isNewRow || !$canAddRows}
96
+ disabled={isNewRow || !$config.allowAddRows}
98
97
  on:click={duplicate}
99
98
  >
100
99
  Duplicate row
@@ -2,9 +2,16 @@
2
2
  import { getContext } from "svelte"
3
3
  import { GutterWidth } from "../lib/constants"
4
4
 
5
- const { resize, renderedColumns, stickyColumn, isReordering, scrollLeft } =
6
- getContext("grid")
5
+ const {
6
+ columns,
7
+ resize,
8
+ renderedColumns,
9
+ stickyColumn,
10
+ isReordering,
11
+ scrollLeft,
12
+ } = getContext("grid")
7
13
 
14
+ $: cutoff = $scrollLeft + GutterWidth + ($columns[0]?.width || 0)
8
15
  $: offset = GutterWidth + ($stickyColumn?.width || 0)
9
16
  $: activeColumn = $resize.column
10
17
 
@@ -83,21 +83,6 @@ export const deriveStores = context => {
83
83
  await saveChanges()
84
84
  }
85
85
 
86
- // Derive if we have any normal columns
87
- const hasNonAutoColumn = derived(
88
- [columns, stickyColumn],
89
- ([$columns, $stickyColumn]) => {
90
- let allCols = $columns || []
91
- if ($stickyColumn) {
92
- allCols = [...allCols, $stickyColumn]
93
- }
94
- const normalCols = allCols.filter(column => {
95
- return !column.schema?.autocolumn
96
- })
97
- return normalCols.length > 0
98
- }
99
- )
100
-
101
86
  // Persists column changes by saving metadata against table schema
102
87
  const saveChanges = async () => {
103
88
  const $columns = get(columns)
@@ -143,7 +128,6 @@ export const deriveStores = context => {
143
128
  }
144
129
 
145
130
  return {
146
- hasNonAutoColumn,
147
131
  columns: {
148
132
  ...columns,
149
133
  actions: {
@@ -70,8 +70,6 @@ export const deriveStores = context => {
70
70
  rowHeight,
71
71
  stickyColumn,
72
72
  width,
73
- hasNonAutoColumn,
74
- config,
75
73
  } = context
76
74
 
77
75
  // Derive the row that contains the selected cell
@@ -114,16 +112,7 @@ export const deriveStores = context => {
114
112
  return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
115
113
  })
116
114
 
117
- // Derive if we're able to add rows
118
- const canAddRows = derived(
119
- [config, hasNonAutoColumn],
120
- ([$config, $hasNonAutoColumn]) => {
121
- return $config.allowAddRows && $hasNonAutoColumn
122
- }
123
- )
124
-
125
115
  return {
126
- canAddRows,
127
116
  focusedRow,
128
117
  contentLines,
129
118
  compact,
@@ -30,9 +30,8 @@ export const deriveStores = context => {
30
30
  ([$users, $focusedCellId]) => {
31
31
  let map = {}
32
32
  $users.forEach(user => {
33
- const cellId = user.gridMetadata?.focusedCellId
34
- if (cellId && cellId !== $focusedCellId) {
35
- map[cellId] = user
33
+ if (user.focusedCellId && user.focusedCellId !== $focusedCellId) {
34
+ map[user.focusedCellId] = user
36
35
  }
37
36
  })
38
37
  return map
@@ -2,5 +2,4 @@ export { default as SplitPage } from "./SplitPage.svelte"
2
2
  export { default as TestimonialPage } from "./TestimonialPage.svelte"
3
3
  export { default as Testimonial } from "./Testimonial.svelte"
4
4
  export { default as UserAvatar } from "./UserAvatar.svelte"
5
- export { default as UserAvatars } from "./UserAvatars.svelte"
6
5
  export { Grid } from "./grid"
@@ -11,26 +11,3 @@ export function downloadText(filename, text) {
11
11
 
12
12
  URL.revokeObjectURL(url)
13
13
  }
14
-
15
- export async function downloadStream(streamResponse) {
16
- const blob = await streamResponse.blob()
17
-
18
- const contentDisposition = streamResponse.headers.get("Content-Disposition")
19
-
20
- const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(
21
- contentDisposition
22
- )
23
-
24
- const filename = matches[1].replace(/['"]/g, "")
25
-
26
- const resBlob = new Blob([blob])
27
-
28
- const blobUrl = URL.createObjectURL(resBlob)
29
-
30
- const link = document.createElement("a")
31
- link.href = blobUrl
32
- link.download = filename
33
- link.click()
34
-
35
- URL.revokeObjectURL(blobUrl)
36
- }
@@ -5,4 +5,4 @@ export * as RoleUtils from "./roles"
5
5
  export * as Utils from "./utils"
6
6
  export { memo, derivedMemo } from "./memo"
7
7
  export { createWebsocket } from "./websocket"
8
- export * from "./download"
8
+ export { downloadText } from "./download"
package/src/api/logs.js DELETED
@@ -1,14 +0,0 @@
1
- export const buildLogsEndpoints = API => ({
2
- /**
3
- * Gets a stream for the system logs.
4
- */
5
- getSystemLogs: async () => {
6
- return await API.get({
7
- url: "/api/system/logs",
8
- json: false,
9
- parseResponse: async response => {
10
- return response
11
- },
12
- })
13
- },
14
- })
@@ -1,67 +0,0 @@
1
- <script>
2
- import { UserAvatar } from "@budibase/frontend-core"
3
- import { TooltipPosition, Avatar } from "@budibase/bbui"
4
-
5
- export let users = []
6
- export let order = "ltr"
7
- export let size = "S"
8
- export let tooltipPosition = TooltipPosition.Top
9
-
10
- $: uniqueUsers = unique(users, order)
11
- $: avatars = getAvatars(uniqueUsers, order)
12
-
13
- const unique = users => {
14
- let uniqueUsers = {}
15
- users?.forEach(user => {
16
- uniqueUsers[user.email] = user
17
- })
18
- return Object.values(uniqueUsers)
19
- }
20
-
21
- const getAvatars = (users, order) => {
22
- const avatars = users.slice(0, 3)
23
- if (users.length > 3) {
24
- const overflow = {
25
- _id: "overflow",
26
- label: `+${users.length - 3}`,
27
- }
28
- if (order === "ltr") {
29
- avatars.push(overflow)
30
- } else {
31
- avatars.unshift(overflow)
32
- }
33
- }
34
- return avatars.map((user, idx) => ({
35
- ...user,
36
- zIndex: order === "ltr" ? idx : uniqueUsers.length - idx,
37
- }))
38
- }
39
- </script>
40
-
41
- <div class="avatars">
42
- {#each avatars as user}
43
- <span style="z-index:{user.zIndex};">
44
- {#if user._id === "overflow"}
45
- <Avatar
46
- {size}
47
- initials={user.label}
48
- color="var(--spectrum-global-color-gray-500)"
49
- />
50
- {:else}
51
- <UserAvatar {size} {user} {tooltipPosition} />
52
- {/if}
53
- </span>
54
- {/each}
55
- </div>
56
-
57
- <style>
58
- .avatars {
59
- display: flex;
60
- }
61
- span:not(:first-of-type) {
62
- margin-left: -6px;
63
- }
64
- .avatars :global(.spectrum-Avatar) {
65
- border: 2px solid var(--avatars-background, var(--background));
66
- }
67
- </style>