Merge remote-tracking branch 'origin/master' into fix/inclusion-row-parsing
This commit is contained in:
commit
03c048f978
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": ["packages/*"],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/backend-core",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase backend core libraries used in server and worker",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
|
@ -24,7 +24,7 @@
|
|||
"dependencies": {
|
||||
"@budibase/nano": "10.1.2",
|
||||
"@budibase/pouchdb-replication-stream": "1.2.10",
|
||||
"@budibase/types": "^2.6.0",
|
||||
"@budibase/types": "^2.6.6",
|
||||
"@shopify/jest-koa-mocks": "5.0.1",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
"aws-cloudfront-sign": "2.2.0",
|
||||
|
|
|
@ -96,6 +96,7 @@ const environment = {
|
|||
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
||||
REDIS_URL: process.env.REDIS_URL || "localhost:6379",
|
||||
REDIS_PASSWORD: process.env.REDIS_PASSWORD || "budibase",
|
||||
REDIS_CLUSTERED: process.env.REDIS_CLUSTERED,
|
||||
MOCK_REDIS: process.env.MOCK_REDIS,
|
||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||
|
|
|
@ -40,6 +40,12 @@ function logging(queue: Queue, jobQueue: JobQueue) {
|
|||
case JobQueue.APP_BACKUP:
|
||||
eventType = "app-backup-event"
|
||||
break
|
||||
case JobQueue.AUDIT_LOG:
|
||||
eventType = "audit-log-event"
|
||||
break
|
||||
case JobQueue.SYSTEM_EVENT_QUEUE:
|
||||
eventType = "system-event"
|
||||
break
|
||||
}
|
||||
if (process.env.NODE_DEBUG?.includes("bull")) {
|
||||
queue
|
||||
|
|
|
@ -12,7 +12,7 @@ import * as timers from "../timers"
|
|||
|
||||
const RETRY_PERIOD_MS = 2000
|
||||
const STARTUP_TIMEOUT_MS = 5000
|
||||
const CLUSTERED = false
|
||||
const CLUSTERED = env.REDIS_CLUSTERED
|
||||
const DEFAULT_SELECT_DB = SelectableDatabase.DEFAULT
|
||||
|
||||
// for testing just generate the client once
|
||||
|
@ -81,7 +81,7 @@ function init(selectDb = DEFAULT_SELECT_DB) {
|
|||
if (client) {
|
||||
client.disconnect()
|
||||
}
|
||||
const { redisProtocolUrl, opts, host, port } = getRedisOptions(CLUSTERED)
|
||||
const { redisProtocolUrl, opts, host, port } = getRedisOptions()
|
||||
|
||||
if (CLUSTERED) {
|
||||
client = new Redis.Cluster([{ host, port }], opts)
|
||||
|
|
|
@ -57,7 +57,7 @@ export enum SelectableDatabase {
|
|||
UNUSED_14 = 15,
|
||||
}
|
||||
|
||||
export function getRedisOptions(clustered = false) {
|
||||
export function getRedisOptions() {
|
||||
let password = env.REDIS_PASSWORD
|
||||
let url: string[] | string = env.REDIS_URL.split("//")
|
||||
// get rid of the protocol
|
||||
|
@ -83,7 +83,7 @@ export function getRedisOptions(clustered = false) {
|
|||
const opts: any = {
|
||||
connectTimeout: CONNECT_TIMEOUT_MS,
|
||||
}
|
||||
if (clustered) {
|
||||
if (env.REDIS_CLUSTERED) {
|
||||
opts.redisOptions = {}
|
||||
opts.redisOptions.tls = {}
|
||||
opts.redisOptions.password = password
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
@ -38,8 +38,8 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||
"@budibase/shared-core": "^2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/shared-core": "^2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@spectrum-css/accordion": "3.0.24",
|
||||
"@spectrum-css/actionbutton": "1.0.1",
|
||||
"@spectrum-css/actiongroup": "1.0.1",
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
const ignoredClasses = [".flatpickr-calendar", ".spectrum-Popover"]
|
||||
const ignoredClasses = [
|
||||
".flatpickr-calendar",
|
||||
".spectrum-Popover",
|
||||
".download-js-link",
|
||||
]
|
||||
let clickHandlers = []
|
||||
|
||||
/**
|
||||
|
@ -22,8 +26,8 @@ const handleClick = event => {
|
|||
}
|
||||
|
||||
// Ignore clicks for modals, unless the handler is registered from a modal
|
||||
const sourceInModal = handler.anchor.closest(".spectrum-Modal") != null
|
||||
const clickInModal = event.target.closest(".spectrum-Modal") != null
|
||||
const sourceInModal = handler.anchor.closest(".spectrum-Underlay") != null
|
||||
const clickInModal = event.target.closest(".spectrum-Underlay") != null
|
||||
if (clickInModal && !sourceInModal) {
|
||||
return
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"> <g id="Make-App-Icon-Circle" transform="translate(3757 -1767)"> <circle id="Ellipse_10" data-name="Ellipse 10" cx="256" cy="256" r="256" transform="translate(-3757 1767)" fill="#6d00cc"/> <path id="Path_141560" data-name="Path 141560" d="M244.78,14.544a7.187,7.187,0,0,0-7.186,7.192V213.927a7.19,7.19,0,0,0,7.186,7.192h52.063a7.187,7.187,0,0,0,7.186-7.192V21.736a7.183,7.183,0,0,0-7.186-7.192ZM92.066,17.083,5.77,188.795a7.191,7.191,0,0,0,3.192,9.654l46.514,23.379a7.184,7.184,0,0,0,9.654-3.2l86.3-171.711a7.184,7.184,0,0,0-3.2-9.654L101.719,13.886a7.2,7.2,0,0,0-9.654,3.2m72.592.614L127.731,204.876a7.189,7.189,0,0,0,5.632,8.442l51.028,10.306a7.2,7.2,0,0,0,8.481-5.665L229.8,30.786a7.19,7.19,0,0,0-5.637-8.442L173.133,12.038a7.391,7.391,0,0,0-1.427-.144,7.194,7.194,0,0,0-7.048,5.8" transform="translate(-3676.356 1905.425)" fill="#fff"/> </g> </svg>
|
After Width: | Height: | Size: 951 B |
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -58,10 +58,10 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^2.6.0",
|
||||
"@budibase/frontend-core": "^2.6.0",
|
||||
"@budibase/shared-core": "^2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/bbui": "^2.6.6",
|
||||
"@budibase/frontend-core": "^2.6.6",
|
||||
"@budibase/shared-core": "^2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
/>
|
||||
<span class="icon-spacing">
|
||||
<Body size="XS">
|
||||
{idx.charAt(0).toUpperCase() + idx.slice(1)}
|
||||
{action.stepTitle || idx.charAt(0).toUpperCase() + idx.slice(1)}
|
||||
</Body>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import DiscordLogo from "assets/discord.svg"
|
||||
import ZapierLogo from "assets/zapier.png"
|
||||
import IntegromatLogo from "assets/integromat.png"
|
||||
import MakeLogo from "assets/make.svg"
|
||||
import SlackLogo from "assets/slack.svg"
|
||||
|
||||
export const externalActions = {
|
||||
zapier: { name: "zapier", icon: ZapierLogo },
|
||||
discord: { name: "discord", icon: DiscordLogo },
|
||||
slack: { name: "slack", icon: SlackLogo },
|
||||
integromat: { name: "integromat", icon: IntegromatLogo },
|
||||
integromat: { name: "integromat", icon: MakeLogo },
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
{#if datasource}
|
||||
<div>
|
||||
<ActionButton icon="DataCorrelated" primary quiet on:click={modal.show}>
|
||||
Define existing relationship
|
||||
Define relationship
|
||||
</ActionButton>
|
||||
</div>
|
||||
<Modal bind:this={modal}>
|
||||
|
|
|
@ -9,13 +9,21 @@
|
|||
$: selectedRowArray = Object.keys($selectedRows).map(id => ({ _id: id }))
|
||||
</script>
|
||||
|
||||
<ExportButton
|
||||
{disabled}
|
||||
view={$tableId}
|
||||
filters={$filter}
|
||||
sorting={{
|
||||
sortColumn: $sort.column,
|
||||
sortOrder: $sort.order,
|
||||
}}
|
||||
selectedRows={selectedRowArray}
|
||||
/>
|
||||
<span data-ignore-click-outside="true">
|
||||
<ExportButton
|
||||
{disabled}
|
||||
view={$tableId}
|
||||
filters={$filter}
|
||||
sorting={{
|
||||
sortColumn: $sort.column,
|
||||
sortOrder: $sort.order,
|
||||
}}
|
||||
selectedRows={selectedRowArray}
|
||||
/>
|
||||
</span>
|
||||
|
||||
<style>
|
||||
span {
|
||||
display: contents;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
import TableFilterButton from "../TableFilterButton.svelte"
|
||||
import { getContext } from "svelte"
|
||||
|
||||
const { columns, config, filter, table } = getContext("grid")
|
||||
const { columns, tableId, filter, table } = getContext("grid")
|
||||
|
||||
const onFilter = e => {
|
||||
filter.set(e.detail || [])
|
||||
}
|
||||
</script>
|
||||
|
||||
{#key $config.tableId}
|
||||
{#key $tableId}
|
||||
<TableFilterButton
|
||||
schema={$table?.schema}
|
||||
filters={$filter}
|
||||
on:change={onFilter}
|
||||
disabled={!$columns.length}
|
||||
tableId={$config.tableId}
|
||||
tableId={$tableId}
|
||||
/>
|
||||
{/key}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import ManageAccessButton from "../ManageAccessButton.svelte"
|
||||
import { getContext } from "svelte"
|
||||
|
||||
const { config } = getContext("grid")
|
||||
const { tableId } = getContext("grid")
|
||||
</script>
|
||||
|
||||
<ManageAccessButton resourceId={$config.tableId} />
|
||||
<ManageAccessButton resourceId={$tableId} />
|
||||
|
|
|
@ -147,6 +147,9 @@ const buildUsersAboveLimitBanner = EXPIRY_KEY => {
|
|||
return {
|
||||
key: EXPIRY_KEY,
|
||||
type: BANNER_TYPES.WARNING,
|
||||
onChange: () => {
|
||||
defaultCacheFn(EXPIRY_KEY)
|
||||
},
|
||||
criteria: () => {
|
||||
return userLicensing.warnUserLimit
|
||||
},
|
||||
|
|
|
@ -261,7 +261,7 @@
|
|||
header={`Users will soon be limited to ${staticUserLimit}`}
|
||||
message={`Our free plan is going to be limited to ${staticUserLimit} users in ${$licensing.userLimitDays}.
|
||||
|
||||
This means any users exceeding the limit have been de-activated.
|
||||
This means any users exceeding the limit will be de-activated.
|
||||
|
||||
De-activated users will not able to access the builder or any published apps until you upgrade to one of our paid plans.
|
||||
`}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/cli",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
|
@ -29,9 +29,9 @@
|
|||
"outputPath": "build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "^2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/types": "^2.6.0",
|
||||
"@budibase/backend-core": "^2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@budibase/types": "^2.6.6",
|
||||
"axios": "0.21.2",
|
||||
"chalk": "4.1.0",
|
||||
"cli-progress": "3.11.2",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/client",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"license": "MPL-2.0",
|
||||
"module": "dist/budibase-client.js",
|
||||
"main": "dist/budibase-client.js",
|
||||
|
@ -19,11 +19,11 @@
|
|||
"dev:builder": "rollup -cw"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^2.6.0",
|
||||
"@budibase/frontend-core": "^2.6.0",
|
||||
"@budibase/shared-core": "^2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/types": "^2.6.0",
|
||||
"@budibase/bbui": "^2.6.6",
|
||||
"@budibase/frontend-core": "^2.6.6",
|
||||
"@budibase/shared-core": "^2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@budibase/types": "^2.6.6",
|
||||
"@spectrum-css/button": "^3.0.3",
|
||||
"@spectrum-css/card": "^3.0.3",
|
||||
"@spectrum-css/divider": "^1.0.3",
|
||||
|
|
|
@ -384,7 +384,7 @@ const confirmTextMap = {
|
|||
["Save Row"]: "Are you sure you want to save this row?",
|
||||
["Execute Query"]: "Are you sure you want to execute this query?",
|
||||
["Trigger Automation"]: "Are you sure you want to trigger this automation?",
|
||||
["Prompt User"]: "Are you sure you want to contiune?",
|
||||
["Prompt User"]: "Are you sure you want to continue?",
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "@budibase/frontend-core",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase frontend core libraries used in builder and client",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^2.6.0",
|
||||
"@budibase/shared-core": "^2.6.0",
|
||||
"@budibase/bbui": "^2.6.6",
|
||||
"@budibase/shared-core": "^2.6.6",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash": "^4.17.21",
|
||||
"socket.io-client": "^4.6.1",
|
||||
|
|
|
@ -70,7 +70,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if $config.allowExpandRows}
|
||||
{#if rowSelected && $config.allowDeleteRows}
|
||||
<div class="delete" on:click={() => dispatch("request-bulk-delete")}>
|
||||
<Icon
|
||||
name="Delete"
|
||||
size="S"
|
||||
color="var(--spectrum-global-color-red-400)"
|
||||
/>
|
||||
</div>
|
||||
{:else if $config.allowExpandRows}
|
||||
<div
|
||||
class="expand"
|
||||
class:visible={!disableExpand && (rowFocused || rowHovered)}
|
||||
|
@ -111,9 +119,12 @@
|
|||
.number.visible {
|
||||
display: flex;
|
||||
}
|
||||
.delete,
|
||||
.expand {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.expand {
|
||||
opacity: 0;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.expand :global(.spectrum-Icon) {
|
||||
pointer-events: none;
|
||||
|
@ -124,4 +135,11 @@
|
|||
.expand.visible :global(.spectrum-Icon) {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.delete:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.delete:hover :global(.spectrum-Icon) {
|
||||
color: var(--spectrum-global-color-red-600) !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import { Modal, ModalContent, Button, notifications } from "@budibase/bbui"
|
||||
import { Modal, ModalContent, notifications } from "@budibase/bbui"
|
||||
import { getContext, onMount } from "svelte"
|
||||
|
||||
const { selectedRows, rows, config, subscribe } = getContext("grid")
|
||||
const { selectedRows, rows, subscribe } = getContext("grid")
|
||||
|
||||
let modal
|
||||
|
||||
|
@ -27,20 +27,6 @@
|
|||
onMount(() => subscribe("request-bulk-delete", () => modal?.show()))
|
||||
</script>
|
||||
|
||||
{#if selectedRowCount}
|
||||
<div class="delete-button" data-ignore-click-outside="true">
|
||||
<Button
|
||||
icon="Delete"
|
||||
size="M"
|
||||
on:click={modal.show}
|
||||
disabled={!$config.allowEditRows}
|
||||
cta
|
||||
>
|
||||
Delete {selectedRowCount} row{selectedRowCount === 1 ? "" : "s"}
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Modal bind:this={modal}>
|
||||
<ModalContent
|
||||
title="Delete rows"
|
||||
|
@ -53,14 +39,3 @@
|
|||
row{selectedRowCount === 1 ? "" : "s"}?
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.delete-button :global(.spectrum-Button:not(:disabled)) {
|
||||
background-color: var(--spectrum-global-color-red-400);
|
||||
border-color: var(--spectrum-global-color-red-400);
|
||||
}
|
||||
.delete-button :global(.spectrum-Button:not(:disabled):hover) {
|
||||
background-color: var(--spectrum-global-color-red-500);
|
||||
border-color: var(--spectrum-global-color-red-500);
|
||||
}
|
||||
</style>
|
|
@ -3,7 +3,7 @@
|
|||
import { ActionButton, Popover } from "@budibase/bbui"
|
||||
import { DefaultColumnWidth } from "../lib/constants"
|
||||
|
||||
const { stickyColumn, columns } = getContext("grid")
|
||||
const { stickyColumn, columns, compact } = getContext("grid")
|
||||
const smallSize = 120
|
||||
const mediumSize = DefaultColumnWidth
|
||||
const largeSize = DefaultColumnWidth * 1.5
|
||||
|
@ -59,12 +59,13 @@
|
|||
on:click={() => (open = !open)}
|
||||
selected={open}
|
||||
disabled={!allCols.length}
|
||||
tooltip={$compact ? "Width" : null}
|
||||
>
|
||||
Width
|
||||
{$compact ? "" : "Width"}
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<Popover bind:open {anchor} align="left">
|
||||
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
|
||||
<div class="content">
|
||||
{#each sizeOptions as option}
|
||||
<ActionButton
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<script>
|
||||
import { getContext } from "svelte"
|
||||
import { ActionButton, Popover, Toggle } from "@budibase/bbui"
|
||||
import { ActionButton, Popover, Toggle, Icon } from "@budibase/bbui"
|
||||
import { getColumnIcon } from "../lib/utils"
|
||||
|
||||
const { columns, stickyColumn } = getContext("grid")
|
||||
const { columns, stickyColumn, compact } = getContext("grid")
|
||||
|
||||
let open = false
|
||||
let anchor
|
||||
|
@ -47,25 +48,32 @@
|
|||
on:click={() => (open = !open)}
|
||||
selected={open || anyHidden}
|
||||
disabled={!$columns.length}
|
||||
tooltip={$compact ? "Columns" : ""}
|
||||
>
|
||||
Columns
|
||||
{$compact ? "" : "Columns"}
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<Popover bind:open {anchor} align="left">
|
||||
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
|
||||
<div class="content">
|
||||
<div class="columns">
|
||||
{#if $stickyColumn}
|
||||
<div class="column">
|
||||
<Icon size="S" name={getColumnIcon($stickyColumn)} />
|
||||
{$stickyColumn.label}
|
||||
</div>
|
||||
<Toggle disabled size="S" value={true} />
|
||||
<span>{$stickyColumn.label}</span>
|
||||
{/if}
|
||||
{#each $columns as column}
|
||||
<div class="column">
|
||||
<Icon size="S" name={getColumnIcon(column)} />
|
||||
{column.label}
|
||||
</div>
|
||||
<Toggle
|
||||
size="S"
|
||||
value={column.visible}
|
||||
on:change={e => toggleVisibility(column, e.detail)}
|
||||
/>
|
||||
<span>{column.label}</span>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
|
@ -90,6 +98,13 @@
|
|||
.columns {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-columns: 1fr auto;
|
||||
}
|
||||
.columns :global(.spectrum-Switch) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.column {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
SmallRowHeight,
|
||||
} from "../lib/constants"
|
||||
|
||||
const { rowHeight, columns, table } = getContext("grid")
|
||||
const { rowHeight, columns, table, compact } = getContext("grid")
|
||||
const sizeOptions = [
|
||||
{
|
||||
label: "Small",
|
||||
|
@ -41,12 +41,13 @@
|
|||
size="M"
|
||||
on:click={() => (open = !open)}
|
||||
selected={open}
|
||||
tooltip={$compact ? "Height" : null}
|
||||
>
|
||||
Height
|
||||
{$compact ? "" : "Height"}
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<Popover bind:open {anchor} align="left">
|
||||
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
|
||||
<div class="content">
|
||||
{#each sizeOptions as option}
|
||||
<ActionButton
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { getContext } from "svelte"
|
||||
import { ActionButton, Popover, Select } from "@budibase/bbui"
|
||||
|
||||
const { sort, columns, stickyColumn } = getContext("grid")
|
||||
const { sort, columns, stickyColumn, compact } = getContext("grid")
|
||||
|
||||
let open = false
|
||||
let anchor
|
||||
|
@ -90,12 +90,13 @@
|
|||
on:click={() => (open = !open)}
|
||||
selected={open}
|
||||
disabled={!columnOptions.length}
|
||||
tooltip={$compact ? "Sort" : ""}
|
||||
>
|
||||
Sort
|
||||
{$compact ? "" : "Sort"}
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<Popover bind:open {anchor} align="left">
|
||||
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
|
||||
<div class="content">
|
||||
<Select
|
||||
placeholder={null}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { createEventManagers } from "../lib/events"
|
||||
import { createAPIClient } from "../../../api"
|
||||
import { attachStores } from "../stores"
|
||||
import DeleteButton from "../controls/DeleteButton.svelte"
|
||||
import BulkDeleteHandler from "../controls/BulkDeleteHandler.svelte"
|
||||
import BetaButton from "../controls/BetaButton.svelte"
|
||||
import GridBody from "./GridBody.svelte"
|
||||
import ResizeOverlay from "../overlays/ResizeOverlay.svelte"
|
||||
|
@ -112,13 +112,12 @@
|
|||
<AddRowButton />
|
||||
<AddColumnButton />
|
||||
<slot name="controls" />
|
||||
<SortButton />
|
||||
<HideColumnsButton />
|
||||
<ColumnWidthButton />
|
||||
<RowHeightButton />
|
||||
<HideColumnsButton />
|
||||
<SortButton />
|
||||
</div>
|
||||
<div class="controls-right">
|
||||
<DeleteButton />
|
||||
<UserAvatars />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -131,7 +130,9 @@
|
|||
<GridBody />
|
||||
</div>
|
||||
<BetaButton />
|
||||
<NewRow />
|
||||
{#if allowAddRows}
|
||||
<NewRow />
|
||||
{/if}
|
||||
<div class="overlays">
|
||||
<ResizeOverlay />
|
||||
<ReorderOverlay />
|
||||
|
@ -146,6 +147,9 @@
|
|||
<ProgressCircle />
|
||||
</div>
|
||||
{/if}
|
||||
{#if allowDeleteRows}
|
||||
<BulkDeleteHandler />
|
||||
{/if}
|
||||
<KeyboardManager />
|
||||
</div>
|
||||
|
||||
|
@ -214,6 +218,7 @@
|
|||
padding: var(--cell-padding);
|
||||
gap: var(--cell-spacing);
|
||||
background: var(--background);
|
||||
z-index: 2;
|
||||
}
|
||||
.controls-left,
|
||||
.controls-right {
|
||||
|
@ -239,7 +244,7 @@
|
|||
height: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
z-index: 10;
|
||||
z-index: 100;
|
||||
}
|
||||
.grid-loading:before {
|
||||
content: "";
|
||||
|
|
|
@ -4,8 +4,14 @@
|
|||
import HeaderCell from "../cells/HeaderCell.svelte"
|
||||
import { Icon } from "@budibase/bbui"
|
||||
|
||||
const { renderedColumns, dispatch, scroll, hiddenColumnsWidth, width } =
|
||||
getContext("grid")
|
||||
const {
|
||||
renderedColumns,
|
||||
dispatch,
|
||||
scroll,
|
||||
hiddenColumnsWidth,
|
||||
width,
|
||||
config,
|
||||
} = getContext("grid")
|
||||
|
||||
$: columnsWidth = $renderedColumns.reduce(
|
||||
(total, col) => (total += col.width),
|
||||
|
@ -23,13 +29,15 @@
|
|||
{/each}
|
||||
</div>
|
||||
</GridScrollWrapper>
|
||||
<div
|
||||
class="add"
|
||||
style="left:{left}px"
|
||||
on:click={() => dispatch("add-column")}
|
||||
>
|
||||
<Icon name="Add" />
|
||||
</div>
|
||||
{#if $config.allowAddColumns}
|
||||
<div
|
||||
class="add"
|
||||
style="left:{left}px"
|
||||
on:click={() => dispatch("add-column")}
|
||||
>
|
||||
<Icon name="Add" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@ -38,7 +46,6 @@
|
|||
border-bottom: var(--cell-border);
|
||||
position: relative;
|
||||
height: var(--default-row-height);
|
||||
z-index: 1;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
|
@ -54,6 +61,7 @@
|
|||
border-right: var(--cell-border);
|
||||
border-bottom: var(--cell-border);
|
||||
background: var(--spectrum-global-color-gray-100);
|
||||
z-index: 20;
|
||||
}
|
||||
.add:hover {
|
||||
background: var(--spectrum-global-color-gray-200);
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
z-index: 3;
|
||||
position: absolute;
|
||||
top: calc(var(--row-height) + var(--offset) + 24px);
|
||||
left: var(--gutter-width);
|
||||
left: 18px;
|
||||
}
|
||||
.button-with-keys {
|
||||
display: flex;
|
||||
|
|
|
@ -21,6 +21,9 @@ const TypeIconMap = {
|
|||
}
|
||||
|
||||
export const getColumnIcon = column => {
|
||||
if (column.schema.autocolumn) {
|
||||
return "MagicWand"
|
||||
}
|
||||
const type = column.schema.type
|
||||
return TypeIconMap[type] || "Text"
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
clipboard,
|
||||
dispatch,
|
||||
selectedRows,
|
||||
config,
|
||||
} = getContext("grid")
|
||||
|
||||
const ignoredOriginSelectors = [
|
||||
|
@ -37,10 +38,12 @@
|
|||
e.preventDefault()
|
||||
focusFirstCell()
|
||||
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
dispatch("add-row-inline")
|
||||
if ($config.allowAddRows) {
|
||||
e.preventDefault()
|
||||
dispatch("add-row-inline")
|
||||
}
|
||||
} else if (e.key === "Delete" || e.key === "Backspace") {
|
||||
if (Object.keys($selectedRows).length) {
|
||||
if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
|
||||
dispatch("request-bulk-delete")
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +91,9 @@
|
|||
}
|
||||
break
|
||||
case "Enter":
|
||||
dispatch("add-row-inline")
|
||||
if ($config.allowAddRows) {
|
||||
dispatch("add-row-inline")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (e.key) {
|
||||
|
@ -106,7 +111,7 @@
|
|||
break
|
||||
case "Delete":
|
||||
case "Backspace":
|
||||
if (Object.keys($selectedRows).length) {
|
||||
if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
|
||||
dispatch("request-bulk-delete")
|
||||
} else {
|
||||
deleteSelectedCell()
|
||||
|
@ -117,7 +122,9 @@
|
|||
break
|
||||
case " ":
|
||||
case "Space":
|
||||
toggleSelectRow()
|
||||
if ($config.allowDeleteRows) {
|
||||
toggleSelectRow()
|
||||
}
|
||||
break
|
||||
default:
|
||||
startEnteringValue(e.key, e.which)
|
||||
|
|
|
@ -2,6 +2,7 @@ import { writable, get, derived } from "svelte/store"
|
|||
import { tick } from "svelte"
|
||||
import {
|
||||
DefaultRowHeight,
|
||||
GutterWidth,
|
||||
LargeRowHeight,
|
||||
MediumRowHeight,
|
||||
NewRowID,
|
||||
|
@ -43,6 +44,8 @@ export const deriveStores = context => {
|
|||
enrichedRows,
|
||||
rowLookupMap,
|
||||
rowHeight,
|
||||
stickyColumn,
|
||||
width,
|
||||
} = context
|
||||
|
||||
// Derive the row that contains the selected cell
|
||||
|
@ -70,6 +73,7 @@ export const deriveStores = context => {
|
|||
hoveredRowId.set(null)
|
||||
}
|
||||
|
||||
// Derive the amount of content lines to show in cells depending on row height
|
||||
const contentLines = derived(rowHeight, $rowHeight => {
|
||||
if ($rowHeight === LargeRowHeight) {
|
||||
return 3
|
||||
|
@ -79,9 +83,15 @@ export const deriveStores = context => {
|
|||
return 1
|
||||
})
|
||||
|
||||
// Derive whether we should use the compact UI, depending on width
|
||||
const compact = derived([stickyColumn, width], ([$stickyColumn, $width]) => {
|
||||
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
|
||||
})
|
||||
|
||||
return {
|
||||
focusedRow,
|
||||
contentLines,
|
||||
compact,
|
||||
ui: {
|
||||
actions: {
|
||||
blur,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/sdk",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase Public API SDK",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/server",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase Web Server",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -45,12 +45,12 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.3",
|
||||
"@budibase/backend-core": "^2.6.0",
|
||||
"@budibase/client": "^2.6.0",
|
||||
"@budibase/pro": "2.6.0",
|
||||
"@budibase/shared-core": "^2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/types": "^2.6.0",
|
||||
"@budibase/backend-core": "^2.6.6",
|
||||
"@budibase/client": "^2.6.6",
|
||||
"@budibase/pro": "2.6.6",
|
||||
"@budibase/shared-core": "^2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@budibase/types": "^2.6.6",
|
||||
"@bull-board/api": "3.7.0",
|
||||
"@bull-board/koa": "3.9.4",
|
||||
"@elastic/elasticsearch": "7.10.0",
|
||||
|
|
|
@ -69,9 +69,9 @@ export async function validate({
|
|||
if (type === FieldTypes.FORMULA || column.autocolumn) {
|
||||
continue
|
||||
}
|
||||
// special case for options, need to always allow unselected (null)
|
||||
// special case for options, need to always allow unselected (empty)
|
||||
if (type === FieldTypes.OPTIONS && constraints.inclusion) {
|
||||
constraints.inclusion.push(null)
|
||||
constraints.inclusion.push(null, "")
|
||||
}
|
||||
let res
|
||||
|
||||
|
|
|
@ -42,8 +42,14 @@ if (!env.isTest()) {
|
|||
host: REDIS_OPTS.host,
|
||||
port: REDIS_OPTS.port,
|
||||
},
|
||||
password: REDIS_OPTS.opts.password,
|
||||
database: 1,
|
||||
password:
|
||||
REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password,
|
||||
}
|
||||
|
||||
if (!env.REDIS_CLUSTERED) {
|
||||
// Can't set direct redis db in clustered env
|
||||
// @ts-ignore
|
||||
options.database = 1
|
||||
}
|
||||
}
|
||||
rateLimitStore = new Stores.Redis(options)
|
||||
|
|
|
@ -212,6 +212,7 @@ describe("/rows", () => {
|
|||
attachmentNull: attachment,
|
||||
attachmentUndefined: attachment,
|
||||
attachmentEmpty: attachment,
|
||||
attachmentEmptyArrayStr: attachment
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -239,6 +240,7 @@ describe("/rows", () => {
|
|||
attachmentNull: null,
|
||||
attachmentUndefined: undefined,
|
||||
attachmentEmpty: "",
|
||||
attachmentEmptyArrayStr: "[]",
|
||||
}
|
||||
|
||||
const id = (await config.createRow(row))._id
|
||||
|
@ -268,6 +270,7 @@ describe("/rows", () => {
|
|||
expect(saved.attachmentNull).toEqual([])
|
||||
expect(saved.attachmentUndefined).toBe(undefined)
|
||||
expect(saved.attachmentEmpty).toEqual([])
|
||||
expect(saved.attachmentEmptyArrayStr).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as serverLog from "./steps/serverLog"
|
|||
import * as discord from "./steps/discord"
|
||||
import * as slack from "./steps/slack"
|
||||
import * as zapier from "./steps/zapier"
|
||||
import * as integromat from "./steps/integromat"
|
||||
import * as make from "./steps/make"
|
||||
import * as filter from "./steps/filter"
|
||||
import * as delay from "./steps/delay"
|
||||
import * as queryRow from "./steps/queryRows"
|
||||
|
@ -43,7 +43,7 @@ const ACTION_IMPLS: Record<
|
|||
discord: discord.run,
|
||||
slack: slack.run,
|
||||
zapier: zapier.run,
|
||||
integromat: integromat.run,
|
||||
integromat: make.run,
|
||||
}
|
||||
export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
|
||||
{
|
||||
|
@ -63,7 +63,7 @@ export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
|
|||
discord: discord.definition,
|
||||
slack: slack.definition,
|
||||
zapier: zapier.definition,
|
||||
integromat: integromat.definition,
|
||||
integromat: make.definition,
|
||||
}
|
||||
|
||||
// don't add the bash script/definitions unless in self host
|
||||
|
|
|
@ -9,10 +9,11 @@ import {
|
|||
} from "@budibase/types"
|
||||
|
||||
export const definition: AutomationStepSchema = {
|
||||
name: "Integromat Integration",
|
||||
tagline: "Trigger an Integromat scenario",
|
||||
name: "Make Integration",
|
||||
stepTitle: "Make",
|
||||
tagline: "Trigger a Make scenario",
|
||||
description:
|
||||
"Performs a webhook call to Integromat and gets the response (if configured)",
|
||||
"Performs a webhook call to Make and gets the response (if configured)",
|
||||
icon: "ri-shut-down-line",
|
||||
stepId: AutomationActionStepId.integromat,
|
||||
type: AutomationStepType.ACTION,
|
|
@ -34,8 +34,6 @@ function parseIntSafe(number?: string) {
|
|||
}
|
||||
}
|
||||
|
||||
let inThread = false
|
||||
|
||||
const environment = {
|
||||
// important - prefer app port to generic port
|
||||
PORT: process.env.APP_PORT || process.env.PORT,
|
||||
|
@ -47,6 +45,7 @@ const environment = {
|
|||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||
REDIS_URL: process.env.REDIS_URL,
|
||||
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
|
||||
REDIS_CLUSTERED: process.env.REDIS_CLUSTERED,
|
||||
HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
|
||||
API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC,
|
||||
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
|
||||
|
@ -94,12 +93,8 @@ const environment = {
|
|||
isProd: () => {
|
||||
return !isDev()
|
||||
},
|
||||
// used to check if already in a thread, don't thread further
|
||||
setInThread: () => {
|
||||
inThread = true
|
||||
},
|
||||
isInThread: () => {
|
||||
return inThread
|
||||
return process.env.FORKED_PROCESS
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,12 @@ export class Thread {
|
|||
const workerOpts: any = {
|
||||
autoStart: true,
|
||||
maxConcurrentWorkers: this.count,
|
||||
workerOptions: {
|
||||
env: {
|
||||
...process.env,
|
||||
FORKED_PROCESS: "1",
|
||||
},
|
||||
},
|
||||
}
|
||||
if (opts.timeoutMs) {
|
||||
this.timeoutMs = opts.timeoutMs
|
||||
|
|
|
@ -25,11 +25,9 @@ function makeVariableKey(queryId: string, variable: string) {
|
|||
|
||||
export function threadSetup() {
|
||||
// don't run this if not threading
|
||||
if (env.isTest() || env.DISABLE_THREADING) {
|
||||
if (env.isTest() || env.DISABLE_THREADING || !env.isInThread()) {
|
||||
return
|
||||
}
|
||||
// when thread starts, make sure it is recorded
|
||||
env.setInThread()
|
||||
db.init()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// @ts-nocheck
|
||||
import { FieldTypes } from "../../constants"
|
||||
import { logging } from "@budibase/backend-core"
|
||||
|
||||
/**
|
||||
* A map of how we convert various properties in rows to each other based on the row type.
|
||||
|
@ -67,9 +68,23 @@ export const TYPE_TRANSFORM_MAP: any = {
|
|||
},
|
||||
},
|
||||
[FieldTypes.ATTACHMENT]: {
|
||||
"": [],
|
||||
[null]: [],
|
||||
[undefined]: undefined,
|
||||
parse: attachments => {
|
||||
if (typeof attachments === "string") {
|
||||
if (attachments === "") {
|
||||
return []
|
||||
}
|
||||
let result
|
||||
try {
|
||||
result = JSON.parse(attachments)
|
||||
} catch (e) {
|
||||
logging.logAlert("Could not parse attachments", e)
|
||||
}
|
||||
return result
|
||||
}
|
||||
return attachments
|
||||
},
|
||||
},
|
||||
[FieldTypes.BOOLEAN]: {
|
||||
"": null,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/shared-core",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Shared data utils",
|
||||
"main": "dist/cjs/src/index.js",
|
||||
"types": "dist/mjs/src/index.d.ts",
|
||||
|
@ -20,7 +20,7 @@
|
|||
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/types": "^2.6.0"
|
||||
"@budibase/types": "^2.6.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^7.6.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/string-templates",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Handlebars wrapper for Budibase templating.",
|
||||
"main": "src/index.cjs",
|
||||
"module": "dist/bundle.mjs",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/types",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase types",
|
||||
"main": "dist/cjs/index.js",
|
||||
"types": "dist/mjs/index.d.ts",
|
||||
|
|
|
@ -104,6 +104,7 @@ interface InputOutputBlock {
|
|||
|
||||
export interface AutomationStepSchema {
|
||||
name: string
|
||||
stepTitle?: string
|
||||
tagline: string
|
||||
icon: string
|
||||
description: string
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/worker",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.6",
|
||||
"description": "Budibase background service",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -37,10 +37,10 @@
|
|||
"author": "Budibase",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "^2.6.0",
|
||||
"@budibase/pro": "2.6.0",
|
||||
"@budibase/string-templates": "^2.6.0",
|
||||
"@budibase/types": "^2.6.0",
|
||||
"@budibase/backend-core": "^2.6.6",
|
||||
"@budibase/pro": "2.6.6",
|
||||
"@budibase/string-templates": "^2.6.6",
|
||||
"@budibase/types": "^2.6.6",
|
||||
"@koa/router": "8.0.8",
|
||||
"@sentry/node": "6.17.7",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -1486,15 +1486,15 @@
|
|||
pouchdb-promise "^6.0.4"
|
||||
through2 "^2.0.0"
|
||||
|
||||
"@budibase/pro@2.5.10":
|
||||
version "2.5.10"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.5.10.tgz#b7d81c1615df7ba51a199c29d5c87dadad3f004e"
|
||||
integrity sha512-c3uAYPyn3BXZyZc1940kIAbNoFOxWVJHQOCz+4AQLRUmMDznSNsOZGhzhdqlc2IL7xL51Oz3Ry5eAVhdPJWb7A==
|
||||
"@budibase/pro@2.6.5":
|
||||
version "2.6.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.6.5.tgz#93cababe9e5f846b85222c9b6b31138baeda76cb"
|
||||
integrity sha512-NHpwFKwTVOQ9xloiidvNgYf41xKYm6TmqJgt8xSO4R7Wbo/lGE4agDFjuivabiaVrnTYHm98heu0t+MFP9uZBg==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.5.10"
|
||||
"@budibase/backend-core" "2.6.5"
|
||||
"@budibase/shared-core" "2.5.9"
|
||||
"@budibase/string-templates" "2.5.9"
|
||||
"@budibase/types" "2.5.10"
|
||||
"@budibase/types" "2.6.5"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
joi "17.6.0"
|
||||
|
|
Loading…
Reference in New Issue