@budibase/frontend-core 2.6.22 → 2.6.24-alpha.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 +4 -4
- package/src/api/app.js +6 -0
- package/src/api/automations.js +2 -2
- package/src/api/datasources.js +11 -0
- package/src/api/groups.js +17 -0
- package/src/api/index.js +10 -0
- package/src/api/tables.js +4 -2
- package/src/components/Testimonial.svelte +67 -0
- package/src/components/TestimonialPage.svelte +2 -61
- package/src/components/UserAvatar.svelte +58 -0
- package/src/components/grid/cells/BooleanCell.svelte +3 -0
- package/src/components/grid/cells/DataCell.svelte +3 -0
- package/src/components/grid/cells/DateCell.svelte +46 -4
- package/src/components/grid/cells/GridCell.svelte +36 -16
- package/src/components/grid/cells/GutterCell.svelte +2 -10
- package/src/components/grid/cells/HeaderCell.svelte +5 -1
- package/src/components/grid/layout/Grid.svelte +22 -5
- package/src/components/grid/layout/GridBody.svelte +5 -1
- package/src/components/grid/layout/GridRow.svelte +3 -2
- package/src/components/grid/layout/HeaderRow.svelte +1 -1
- package/src/components/grid/layout/KeyboardShortcut.svelte +1 -1
- package/src/components/grid/layout/NewRow.svelte +3 -3
- package/src/components/grid/layout/StickyColumn.svelte +2 -1
- package/src/components/grid/layout/UserAvatars.svelte +14 -4
- package/src/components/grid/lib/constants.js +1 -1
- package/src/components/grid/lib/websocket.js +40 -36
- package/src/components/grid/overlays/KeyboardManager.svelte +3 -4
- package/src/components/grid/overlays/MenuOverlay.svelte +34 -4
- package/src/components/grid/stores/columns.js +2 -2
- package/src/components/grid/stores/reorder.js +77 -9
- package/src/components/grid/stores/rows.js +27 -19
- package/src/components/grid/stores/ui.js +20 -1
- package/src/components/grid/stores/users.js +18 -63
- package/src/components/index.js +2 -0
- package/src/constants.js +1 -0
- package/src/fetch/DataFetch.js +23 -1
- package/src/fetch/GroupUserFetch.js +51 -0
- package/src/fetch/fetchData.js +2 -0
- package/src/utils/index.js +1 -0
- package/src/utils/websocket.js +60 -0
- package/src/components/grid/controls/BetaButton.svelte +0 -46
- package/src/components/grid/layout/Avatar.svelte +0 -24
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.24-alpha.0",
|
|
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": "
|
|
10
|
-
"@budibase/shared-core": "
|
|
9
|
+
"@budibase/bbui": "2.6.24-alpha.0",
|
|
10
|
+
"@budibase/shared-core": "2.6.24-alpha.0",
|
|
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": "
|
|
16
|
+
"gitHead": "71a9558d12c55e7d9ef87b82995c62497662acf8"
|
|
17
17
|
}
|
package/src/api/app.js
CHANGED
package/src/api/automations.js
CHANGED
|
@@ -4,10 +4,10 @@ export const buildAutomationEndpoints = API => ({
|
|
|
4
4
|
* @param automationId the ID of the automation to trigger
|
|
5
5
|
* @param fields the fields to trigger the automation with
|
|
6
6
|
*/
|
|
7
|
-
triggerAutomation: async ({ automationId, fields }) => {
|
|
7
|
+
triggerAutomation: async ({ automationId, fields, timeout }) => {
|
|
8
8
|
return await API.post({
|
|
9
9
|
url: `/api/automations/${automationId}/trigger`,
|
|
10
|
-
body: { fields },
|
|
10
|
+
body: { fields, timeout },
|
|
11
11
|
})
|
|
12
12
|
},
|
|
13
13
|
|
package/src/api/datasources.js
CHANGED
|
@@ -58,4 +58,15 @@ export const buildDatasourceEndpoints = API => ({
|
|
|
58
58
|
url: `/api/datasources/${datasourceId}/${datasourceRev}`,
|
|
59
59
|
})
|
|
60
60
|
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validate a datasource configuration
|
|
64
|
+
* @param datasource the datasource configuration to validate
|
|
65
|
+
*/
|
|
66
|
+
validateDatasource: async datasource => {
|
|
67
|
+
return await API.post({
|
|
68
|
+
url: `/api/datasources/verify`,
|
|
69
|
+
body: { datasource },
|
|
70
|
+
})
|
|
71
|
+
},
|
|
61
72
|
})
|
package/src/api/groups.js
CHANGED
|
@@ -52,6 +52,23 @@ export const buildGroupsEndpoints = API => {
|
|
|
52
52
|
})
|
|
53
53
|
},
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Gets a group users by the group id
|
|
57
|
+
*/
|
|
58
|
+
getGroupUsers: async ({ id, bookmark, emailSearch }) => {
|
|
59
|
+
let url = `/api/global/groups/${id}/users?`
|
|
60
|
+
if (bookmark) {
|
|
61
|
+
url += `bookmark=${bookmark}&`
|
|
62
|
+
}
|
|
63
|
+
if (emailSearch) {
|
|
64
|
+
url += `emailSearch=${emailSearch}&`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return await API.get({
|
|
68
|
+
url,
|
|
69
|
+
})
|
|
70
|
+
},
|
|
71
|
+
|
|
55
72
|
/**
|
|
56
73
|
* Adds users to a group
|
|
57
74
|
* @param groupId The group to update
|
package/src/api/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Helpers } from "@budibase/bbui"
|
|
1
2
|
import { ApiVersion } from "../constants"
|
|
2
3
|
import { buildAnalyticsEndpoints } from "./analytics"
|
|
3
4
|
import { buildAppEndpoints } from "./app"
|
|
@@ -30,6 +31,14 @@ import { buildEnvironmentVariableEndpoints } from "./environmentVariables"
|
|
|
30
31
|
import { buildEventEndpoints } from "./events"
|
|
31
32
|
import { buildAuditLogsEndpoints } from "./auditLogs"
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Random identifier to uniquely identify a session in a tab. This is
|
|
36
|
+
* used to determine the originator of calls to the API, which is in
|
|
37
|
+
* turn used to determine who caused a websocket message to be sent, so
|
|
38
|
+
* that we can ignore events caused by ourselves.
|
|
39
|
+
*/
|
|
40
|
+
export const APISessionID = Helpers.uuid()
|
|
41
|
+
|
|
33
42
|
const defaultAPIClientConfig = {
|
|
34
43
|
/**
|
|
35
44
|
* Certain definitions can't change at runtime for client apps, such as the
|
|
@@ -116,6 +125,7 @@ export const createAPIClient = config => {
|
|
|
116
125
|
|
|
117
126
|
// Build headers
|
|
118
127
|
let headers = { Accept: "application/json" }
|
|
128
|
+
headers["x-budibase-session-id"] = APISessionID
|
|
119
129
|
if (!external) {
|
|
120
130
|
headers["x-budibase-api-version"] = ApiVersion
|
|
121
131
|
}
|
package/src/api/tables.js
CHANGED
|
@@ -62,13 +62,15 @@ export const buildTableEndpoints = API => ({
|
|
|
62
62
|
/**
|
|
63
63
|
* Imports data into an existing table
|
|
64
64
|
* @param tableId the table ID to import to
|
|
65
|
-
* @param
|
|
65
|
+
* @param rows the data import object
|
|
66
|
+
* @param identifierFields column names to be used as keys for overwriting existing rows
|
|
66
67
|
*/
|
|
67
|
-
importTableData: async ({ tableId, rows }) => {
|
|
68
|
+
importTableData: async ({ tableId, rows, identifierFields }) => {
|
|
68
69
|
return await API.post({
|
|
69
70
|
url: `/api/tables/${tableId}/import`,
|
|
70
71
|
body: {
|
|
71
72
|
rows,
|
|
73
|
+
identifierFields,
|
|
72
74
|
},
|
|
73
75
|
})
|
|
74
76
|
},
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Layout } from "@budibase/bbui"
|
|
3
|
+
import Bulgaria from "../../assets/bulgaria.png"
|
|
4
|
+
import Covanta from "../../assets/covanta.png"
|
|
5
|
+
import Schnellecke from "../../assets/schnellecke.png"
|
|
6
|
+
|
|
7
|
+
const testimonials = [
|
|
8
|
+
{
|
|
9
|
+
text: "Budibase was the only solution that checked all the boxes for Covanta. Covanta expects to realize $3.2MM in savings due to the elimination of redundant data entry.",
|
|
10
|
+
name: "Charles Link",
|
|
11
|
+
role: "Senior Director, Data and Analytics",
|
|
12
|
+
image: Covanta,
|
|
13
|
+
imageSize: 105,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
text: "Budibase was mission-critical for us and went a long way in preventing what could have become a humanitarian crisis here in Bulgaria.",
|
|
17
|
+
name: "Bozhidar Bozhanov",
|
|
18
|
+
role: "Government of Bulgaria",
|
|
19
|
+
image: Bulgaria,
|
|
20
|
+
imageSize: 49,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
text: "Centralization of authentication, quick turnaround time for requests, integration with different database systems has given it the edge and it’s now used daily for internal development for those apps that you know you need but don’t feel value in losing days of development to reinvent the wheel.",
|
|
24
|
+
name: "Davide Lenzarini",
|
|
25
|
+
role: "IT manager",
|
|
26
|
+
image: Schnellecke,
|
|
27
|
+
imageSize: 141,
|
|
28
|
+
},
|
|
29
|
+
]
|
|
30
|
+
const testimonial = testimonials[Math.floor(Math.random() * 3)]
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class="testimonial">
|
|
34
|
+
<Layout noPadding gap="S">
|
|
35
|
+
<img
|
|
36
|
+
width={testimonial.imageSize}
|
|
37
|
+
alt="a-happy-budibase-user"
|
|
38
|
+
src={testimonial.image}
|
|
39
|
+
/>
|
|
40
|
+
<div class="text">
|
|
41
|
+
"{testimonial.text}"
|
|
42
|
+
</div>
|
|
43
|
+
<div class="author">
|
|
44
|
+
<div class="name">{testimonial.name}</div>
|
|
45
|
+
<div class="company">{testimonial.role}</div>
|
|
46
|
+
</div>
|
|
47
|
+
</Layout>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<style>
|
|
51
|
+
.testimonial {
|
|
52
|
+
width: 380px;
|
|
53
|
+
padding: 40px;
|
|
54
|
+
}
|
|
55
|
+
.text {
|
|
56
|
+
font-size: var(--font-size-l);
|
|
57
|
+
font-style: italic;
|
|
58
|
+
}
|
|
59
|
+
.name {
|
|
60
|
+
font-weight: bold;
|
|
61
|
+
color: var(--spectrum-global-color-gray-900);
|
|
62
|
+
font-size: var(--font-size-l);
|
|
63
|
+
}
|
|
64
|
+
.company {
|
|
65
|
+
color: var(--spectrum-global-color-gray-700);
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -1,58 +1,15 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import SplitPage from "./SplitPage.svelte"
|
|
3
|
-
import
|
|
4
|
-
import Bulgaria from "../../assets/bulgaria.png"
|
|
5
|
-
import Covanta from "../../assets/covanta.png"
|
|
6
|
-
import Schnellecke from "../../assets/schnellecke.png"
|
|
3
|
+
import Testimonial from "./Testimonial.svelte"
|
|
7
4
|
|
|
8
5
|
export let enabled = true
|
|
9
|
-
|
|
10
|
-
const testimonials = [
|
|
11
|
-
{
|
|
12
|
-
text: "Budibase was the only solution that checked all the boxes for Covanta. Covanta expects to realize $3.2MM in savings due to the elimination of redundant data entry.",
|
|
13
|
-
name: "Charles Link",
|
|
14
|
-
role: "Senior Director, Data and Analytics",
|
|
15
|
-
image: Covanta,
|
|
16
|
-
imageSize: 105,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
text: "Budibase was mission-critical for us and went a long way in preventing what could have become a humanitarian crisis here in Bulgaria.",
|
|
20
|
-
name: "Bozhidar Bozhanov",
|
|
21
|
-
role: "Government of Bulgaria",
|
|
22
|
-
image: Bulgaria,
|
|
23
|
-
imageSize: 49,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
text: "Centralization of authentication, quick turnaround time for requests, integration with different database systems has given it the edge and it’s now used daily for internal development for those apps that you know you need but don’t feel value in losing days of development to reinvent the wheel.",
|
|
27
|
-
name: "Davide Lenzarini",
|
|
28
|
-
role: "IT manager",
|
|
29
|
-
image: Schnellecke,
|
|
30
|
-
imageSize: 141,
|
|
31
|
-
},
|
|
32
|
-
]
|
|
33
|
-
const testimonial = testimonials[Math.floor(Math.random() * 3)]
|
|
34
6
|
</script>
|
|
35
7
|
|
|
36
8
|
<SplitPage>
|
|
37
9
|
<slot />
|
|
38
10
|
<div class:wrapper={enabled} slot="right">
|
|
39
11
|
{#if enabled}
|
|
40
|
-
<
|
|
41
|
-
<Layout noPadding gap="S">
|
|
42
|
-
<img
|
|
43
|
-
width={testimonial.imageSize}
|
|
44
|
-
alt="a-happy-budibase-user"
|
|
45
|
-
src={testimonial.image}
|
|
46
|
-
/>
|
|
47
|
-
<div class="text">
|
|
48
|
-
"{testimonial.text}"
|
|
49
|
-
</div>
|
|
50
|
-
<div class="author">
|
|
51
|
-
<div class="name">{testimonial.name}</div>
|
|
52
|
-
<div class="company">{testimonial.role}</div>
|
|
53
|
-
</div>
|
|
54
|
-
</Layout>
|
|
55
|
-
</div>
|
|
12
|
+
<Testimonial />
|
|
56
13
|
{/if}
|
|
57
14
|
</div>
|
|
58
15
|
</SplitPage>
|
|
@@ -64,20 +21,4 @@
|
|
|
64
21
|
display: grid;
|
|
65
22
|
place-items: center;
|
|
66
23
|
}
|
|
67
|
-
.testimonial {
|
|
68
|
-
width: 380px;
|
|
69
|
-
padding: 40px;
|
|
70
|
-
}
|
|
71
|
-
.text {
|
|
72
|
-
font-size: var(--font-size-l);
|
|
73
|
-
font-style: italic;
|
|
74
|
-
}
|
|
75
|
-
.name {
|
|
76
|
-
font-weight: bold;
|
|
77
|
-
color: var(--spectrum-global-color-gray-900);
|
|
78
|
-
font-size: var(--font-size-l);
|
|
79
|
-
}
|
|
80
|
-
.company {
|
|
81
|
-
color: var(--spectrum-global-color-gray-700);
|
|
82
|
-
}
|
|
83
24
|
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Avatar, Tooltip } from "@budibase/bbui"
|
|
3
|
+
import { helpers } from "@budibase/shared-core"
|
|
4
|
+
|
|
5
|
+
export let user
|
|
6
|
+
export let size
|
|
7
|
+
export let tooltipDirection = "top"
|
|
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
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{#if user}
|
|
25
|
+
<div class="user-avatar">
|
|
26
|
+
<Avatar
|
|
27
|
+
{size}
|
|
28
|
+
initials={helpers.getUserInitials(user)}
|
|
29
|
+
color={helpers.getUserColor(user)}
|
|
30
|
+
/>
|
|
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>
|
|
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>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
export let selected
|
|
12
12
|
export let rowFocused
|
|
13
13
|
export let rowIdx
|
|
14
|
+
export let topRow = false
|
|
14
15
|
export let focused
|
|
15
16
|
export let selectedUser
|
|
16
17
|
export let column
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
$: readonly =
|
|
33
34
|
column.schema.autocolumn ||
|
|
34
35
|
column.schema.disabled ||
|
|
36
|
+
column.schema.type === "formula" ||
|
|
35
37
|
(!$config.allowEditRows && row._id)
|
|
36
38
|
|
|
37
39
|
// Register this cell API if the row is focused
|
|
@@ -67,6 +69,7 @@
|
|
|
67
69
|
{highlighted}
|
|
68
70
|
{selected}
|
|
69
71
|
{rowIdx}
|
|
72
|
+
{topRow}
|
|
70
73
|
{focused}
|
|
71
74
|
{selectedUser}
|
|
72
75
|
{readonly}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import dayjs from "dayjs"
|
|
3
3
|
import { CoreDatePicker, Icon } from "@budibase/bbui"
|
|
4
|
+
import { onMount } from "svelte"
|
|
4
5
|
|
|
5
6
|
export let value
|
|
6
7
|
export let schema
|
|
7
8
|
export let onChange
|
|
8
9
|
export let focused = false
|
|
9
10
|
export let readonly = false
|
|
11
|
+
export let api
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
let flatpickr
|
|
14
|
+
let isOpen
|
|
15
|
+
|
|
16
|
+
// Adding the 0- will turn a string like 00:00:00 into a valid ISO
|
|
12
17
|
// date, but will make actual ISO dates invalid
|
|
13
|
-
$:
|
|
14
|
-
$: timeOnly =
|
|
18
|
+
$: isTimeValue = !isNaN(new Date(`0-${value}`))
|
|
19
|
+
$: timeOnly = isTimeValue || schema?.timeOnly
|
|
15
20
|
$: dateOnly = schema?.dateOnly
|
|
16
21
|
$: format = timeOnly
|
|
17
22
|
? "HH:mm:ss"
|
|
@@ -19,12 +24,45 @@
|
|
|
19
24
|
? "MMM D YYYY"
|
|
20
25
|
: "MMM D YYYY, HH:mm"
|
|
21
26
|
$: editable = focused && !readonly
|
|
27
|
+
$: displayValue = getDisplayValue(value, format, timeOnly, isTimeValue)
|
|
28
|
+
|
|
29
|
+
const getDisplayValue = (value, format, timeOnly, isTimeValue) => {
|
|
30
|
+
if (!value) {
|
|
31
|
+
return ""
|
|
32
|
+
}
|
|
33
|
+
// Parse full date strings
|
|
34
|
+
if (!timeOnly || !isTimeValue) {
|
|
35
|
+
return dayjs(value).format(format)
|
|
36
|
+
}
|
|
37
|
+
// Otherwise must be a time string
|
|
38
|
+
return dayjs(`0-${value}`).format(format)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Ensure we close flatpickr when unselected
|
|
42
|
+
$: {
|
|
43
|
+
if (!focused) {
|
|
44
|
+
flatpickr?.close()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const onKeyDown = () => {
|
|
49
|
+
return isOpen
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onMount(() => {
|
|
53
|
+
api = {
|
|
54
|
+
onKeyDown,
|
|
55
|
+
focus: () => flatpickr?.open(),
|
|
56
|
+
blur: () => flatpickr?.close(),
|
|
57
|
+
isActive: () => isOpen,
|
|
58
|
+
}
|
|
59
|
+
})
|
|
22
60
|
</script>
|
|
23
61
|
|
|
24
62
|
<div class="container">
|
|
25
63
|
<div class="value">
|
|
26
64
|
{#if value}
|
|
27
|
-
{
|
|
65
|
+
{displayValue}
|
|
28
66
|
{/if}
|
|
29
67
|
</div>
|
|
30
68
|
{#if editable}
|
|
@@ -42,6 +80,10 @@
|
|
|
42
80
|
{timeOnly}
|
|
43
81
|
time24hr
|
|
44
82
|
ignoreTimezones={schema.ignoreTimezones}
|
|
83
|
+
bind:flatpickr
|
|
84
|
+
on:open={() => (isOpen = true)}
|
|
85
|
+
on:close={() => (isOpen = false)}
|
|
86
|
+
useKeyboardShortcuts={false}
|
|
45
87
|
/>
|
|
46
88
|
</div>
|
|
47
89
|
{/if}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export let selectedUser = null
|
|
7
7
|
export let error = null
|
|
8
8
|
export let rowIdx
|
|
9
|
+
export let topRow = false
|
|
9
10
|
export let defaultHeight = false
|
|
10
11
|
export let center = false
|
|
11
12
|
export let readonly = false
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
const getStyle = (width, selectedUser) => {
|
|
16
17
|
let style = `flex: 0 0 ${width}px;`
|
|
17
18
|
if (selectedUser) {
|
|
18
|
-
style += `--
|
|
19
|
+
style += `--user-color:${selectedUser.color};`
|
|
19
20
|
}
|
|
20
21
|
return style
|
|
21
22
|
}
|
|
@@ -31,13 +32,14 @@
|
|
|
31
32
|
class:readonly
|
|
32
33
|
class:default-height={defaultHeight}
|
|
33
34
|
class:selected-other={selectedUser != null}
|
|
35
|
+
class:alt={rowIdx % 2 === 1}
|
|
36
|
+
class:top={topRow}
|
|
34
37
|
on:focus
|
|
35
38
|
on:mousedown
|
|
36
39
|
on:mouseup
|
|
37
40
|
on:click
|
|
38
41
|
on:contextmenu
|
|
39
42
|
{style}
|
|
40
|
-
data-row={rowIdx}
|
|
41
43
|
>
|
|
42
44
|
{#if error}
|
|
43
45
|
<div class="label">
|
|
@@ -70,6 +72,9 @@
|
|
|
70
72
|
width: 0;
|
|
71
73
|
--cell-color: transparent;
|
|
72
74
|
}
|
|
75
|
+
.cell.alt {
|
|
76
|
+
--cell-background: var(--cell-background-alt);
|
|
77
|
+
}
|
|
73
78
|
.cell.default-height {
|
|
74
79
|
height: var(--default-row-height);
|
|
75
80
|
}
|
|
@@ -94,14 +99,15 @@
|
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
/* Cell border for cells with labels */
|
|
97
|
-
.cell.error:after
|
|
98
|
-
.cell.selected-other:not(.focused):after {
|
|
102
|
+
.cell.error:after {
|
|
99
103
|
border-radius: 0 2px 2px 2px;
|
|
100
104
|
}
|
|
101
|
-
.cell
|
|
102
|
-
.cell[data-row="0"].selected-other:not(.focused):after {
|
|
105
|
+
.cell.top.error:after {
|
|
103
106
|
border-radius: 2px 2px 2px 0;
|
|
104
107
|
}
|
|
108
|
+
.cell.selected-other:not(.focused):after {
|
|
109
|
+
border-radius: 2px;
|
|
110
|
+
}
|
|
105
111
|
|
|
106
112
|
/* Cell z-index */
|
|
107
113
|
.cell.error,
|
|
@@ -111,21 +117,30 @@
|
|
|
111
117
|
.cell.focused {
|
|
112
118
|
z-index: 2;
|
|
113
119
|
}
|
|
120
|
+
.cell.selected-other:hover {
|
|
121
|
+
z-index: 2;
|
|
122
|
+
}
|
|
123
|
+
.cell:not(.focused) {
|
|
124
|
+
user-select: none;
|
|
125
|
+
}
|
|
126
|
+
.cell:hover {
|
|
127
|
+
cursor: default;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Cell color overrides */
|
|
131
|
+
.cell.selected-other {
|
|
132
|
+
--cell-color: var(--user-color);
|
|
133
|
+
}
|
|
114
134
|
.cell.focused {
|
|
115
135
|
--cell-color: var(--spectrum-global-color-blue-400);
|
|
116
136
|
}
|
|
117
137
|
.cell.error {
|
|
118
138
|
--cell-color: var(--spectrum-global-color-red-500);
|
|
119
139
|
}
|
|
120
|
-
.cell.readonly {
|
|
140
|
+
.cell.focused.readonly {
|
|
121
141
|
--cell-color: var(--spectrum-global-color-gray-600);
|
|
122
142
|
}
|
|
123
|
-
|
|
124
|
-
user-select: none;
|
|
125
|
-
}
|
|
126
|
-
.cell:hover {
|
|
127
|
-
cursor: default;
|
|
128
|
-
}
|
|
143
|
+
|
|
129
144
|
.cell.highlighted:not(.focused),
|
|
130
145
|
.cell.focused.readonly {
|
|
131
146
|
--cell-background: var(--cell-background-hover);
|
|
@@ -141,7 +156,7 @@
|
|
|
141
156
|
left: 0;
|
|
142
157
|
padding: 1px 4px 3px 4px;
|
|
143
158
|
margin: 0 0 -2px 0;
|
|
144
|
-
background: var(--
|
|
159
|
+
background: var(--cell-color);
|
|
145
160
|
border-radius: 2px;
|
|
146
161
|
display: block;
|
|
147
162
|
color: white;
|
|
@@ -152,14 +167,19 @@
|
|
|
152
167
|
overflow: hidden;
|
|
153
168
|
user-select: none;
|
|
154
169
|
}
|
|
155
|
-
.cell
|
|
170
|
+
.cell.top .label {
|
|
156
171
|
bottom: auto;
|
|
157
172
|
top: 100%;
|
|
158
|
-
border-radius: 0 2px 2px 2px;
|
|
159
173
|
padding: 2px 4px 2px 4px;
|
|
160
174
|
margin: -2px 0 0 0;
|
|
161
175
|
}
|
|
162
176
|
.error .label {
|
|
163
177
|
background: var(--spectrum-global-color-red-500);
|
|
164
178
|
}
|
|
179
|
+
.selected-other:not(.error) .label {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
.selected-other:not(.error):hover .label {
|
|
183
|
+
display: block;
|
|
184
|
+
}
|
|
165
185
|
</style>
|
|
@@ -21,16 +21,7 @@
|
|
|
21
21
|
svelteDispatch("select")
|
|
22
22
|
const id = row?._id
|
|
23
23
|
if (id) {
|
|
24
|
-
selectedRows.
|
|
25
|
-
let newState = {
|
|
26
|
-
...state,
|
|
27
|
-
[id]: !state[id],
|
|
28
|
-
}
|
|
29
|
-
if (!newState[id]) {
|
|
30
|
-
delete newState[id]
|
|
31
|
-
}
|
|
32
|
-
return newState
|
|
33
|
-
})
|
|
24
|
+
selectedRows.actions.toggleRow(id)
|
|
34
25
|
}
|
|
35
26
|
}
|
|
36
27
|
|
|
@@ -47,6 +38,7 @@
|
|
|
47
38
|
highlighted={rowFocused || rowHovered}
|
|
48
39
|
selected={rowSelected}
|
|
49
40
|
{defaultHeight}
|
|
41
|
+
rowIdx={row?.__idx}
|
|
50
42
|
>
|
|
51
43
|
<div class="gutter">
|
|
52
44
|
{#if $$slots.default}
|
|
@@ -196,7 +196,11 @@
|
|
|
196
196
|
<MenuItem disabled={!canMoveRight} icon="ChevronRight" on:click={moveRight}>
|
|
197
197
|
Move right
|
|
198
198
|
</MenuItem>
|
|
199
|
-
<MenuItem
|
|
199
|
+
<MenuItem
|
|
200
|
+
disabled={idx === "sticky"}
|
|
201
|
+
icon="VisibilityOff"
|
|
202
|
+
on:click={hideColumn}>Hide column</MenuItem
|
|
203
|
+
>
|
|
200
204
|
</Menu>
|
|
201
205
|
</Popover>
|
|
202
206
|
|