Merge remote-tracking branch 'origin/develop' into feature/binding-ux-update
This commit is contained in:
commit
f4a5715461
66 changed files with 1084 additions and 529 deletions
10
.github/workflows/deploy-release.yml
vendored
10
.github/workflows/deploy-release.yml
vendored
|
@ -68,6 +68,16 @@ jobs:
|
||||||
]
|
]
|
||||||
env:
|
env:
|
||||||
KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}'
|
KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}'
|
||||||
|
|
||||||
|
- name: Set the base64 kubeconfig
|
||||||
|
run: echo 'RELEASE_KUBECONFIG=${{ secrets.RELEASE_KUBECONFIG }}' | base64
|
||||||
|
|
||||||
|
- name: Re roll the services
|
||||||
|
uses: actions-hub/kubectl@master
|
||||||
|
env:
|
||||||
|
KUBE_CONFIG: ${{ env.RELEASE_KUBECONFIG }}
|
||||||
|
with:
|
||||||
|
args: rollout restart deployment proxy-service -n budibase && kubectl rollout restart deployment app-service -n budibase && kubectl rollout restart deployment worker-service -n budibase
|
||||||
|
|
||||||
- name: Discord Webhook Action
|
- name: Discord Webhook Action
|
||||||
uses: tsickert/discord-webhook@v4.0.0
|
uses: tsickert/discord-webhook@v4.0.0
|
||||||
|
|
10
.github/workflows/release-develop.yml
vendored
10
.github/workflows/release-develop.yml
vendored
|
@ -120,6 +120,16 @@ jobs:
|
||||||
]
|
]
|
||||||
env:
|
env:
|
||||||
KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}'
|
KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}'
|
||||||
|
|
||||||
|
- name: Set the base64 kubeconfig
|
||||||
|
run: echo 'RELEASE_KUBECONFIG=${{ secrets.RELEASE_KUBECONFIG }}' | base64
|
||||||
|
|
||||||
|
- name: Re roll the services
|
||||||
|
uses: actions-hub/kubectl@master
|
||||||
|
env:
|
||||||
|
KUBE_CONFIG: ${{ env.RELEASE_KUBECONFIG }}
|
||||||
|
with:
|
||||||
|
args: rollout restart deployment proxy-service -n budibase && kubectl rollout restart deployment app-service -n budibase && kubectl rollout restart deployment worker-service -n budibase
|
||||||
|
|
||||||
- name: Discord Webhook Action
|
- name: Discord Webhook Action
|
||||||
uses: tsickert/discord-webhook@v4.0.0
|
uses: tsickert/discord-webhook@v4.0.0
|
||||||
|
|
|
@ -62,6 +62,10 @@ http {
|
||||||
proxy_pass http://{{ address }}:4001;
|
proxy_pass http://{{ address }}:4001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /preview {
|
||||||
|
proxy_pass http://{{ address }}:4001;
|
||||||
|
}
|
||||||
|
|
||||||
location /builder {
|
location /builder {
|
||||||
proxy_pass http://{{ address }}:3000;
|
proxy_pass http://{{ address }}:3000;
|
||||||
rewrite ^/builder(.*)$ /builder/$1 break;
|
rewrite ^/builder(.*)$ /builder/$1 break;
|
||||||
|
|
|
@ -11,6 +11,10 @@ if [[ "${TARGETBUILD}" = "aas" ]]; then
|
||||||
apt-get install -y openssh-server
|
apt-get install -y openssh-server
|
||||||
sed -i "s/#Port 22/Port 2222/" /etc/ssh/sshd_config
|
sed -i "s/#Port 22/Port 2222/" /etc/ssh/sshd_config
|
||||||
/etc/init.d/ssh restart
|
/etc/init.d/ssh restart
|
||||||
fi
|
sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini
|
||||||
|
sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini
|
||||||
|
else
|
||||||
|
sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini
|
||||||
|
sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini
|
||||||
|
|
||||||
sed -i 's#DATA_DIR#$DATA_DIR#' /opt/clouseau/clouseau.ini /opt/couchdb/etc/local.ini
|
fi
|
|
@ -1,5 +1,5 @@
|
||||||
; CouchDB Configuration Settings
|
; CouchDB Configuration Settings
|
||||||
|
|
||||||
[couchdb]
|
[couchdb]
|
||||||
database_dir = DATA_DIR/couch/dbs
|
database_dir = DATA_DIR/couchdb/dbs
|
||||||
view_index_dir = DATA_DIR/couch/views
|
view_index_dir = DATA_DIR/couchdb/views
|
||||||
|
|
|
@ -3,6 +3,11 @@ healthy=true
|
||||||
|
|
||||||
if [ -f "/data/.env" ]; then
|
if [ -f "/data/.env" ]; then
|
||||||
export $(cat /data/.env | xargs)
|
export $(cat /data/.env | xargs)
|
||||||
|
elif [ -f "/home/.env" ]; then
|
||||||
|
export $(cat /home/.env | xargs)
|
||||||
|
else
|
||||||
|
echo "No .env file found"
|
||||||
|
healthy=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(curl -Lfk -s -w "%{http_code}\n" http://localhost/ -o /dev/null) -ne 200 ]]; then
|
if [[ $(curl -Lfk -s -w "%{http_code}\n" http://localhost/ -o /dev/null) -ne 200 ]]; then
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts",
|
"types": "dist/src/index.d.ts",
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
"test:watch": "jest --watchAll"
|
"test:watch": "jest --watchAll"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/types": "1.2.39-alpha.6",
|
"@budibase/types": "1.2.44-alpha.1",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
"aws-sdk": "2.1030.0",
|
"aws-sdk": "2.1030.0",
|
||||||
"bcrypt": "5.0.1",
|
"bcrypt": "5.0.1",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
||||||
"@budibase/string-templates": "1.2.39-alpha.6",
|
"@budibase/string-templates": "1.2.44-alpha.1",
|
||||||
"@spectrum-css/actionbutton": "^1.0.1",
|
"@spectrum-css/actionbutton": "^1.0.1",
|
||||||
"@spectrum-css/actiongroup": "^1.0.1",
|
"@spectrum-css/actiongroup": "^1.0.1",
|
||||||
"@spectrum-css/avatar": "^3.0.2",
|
"@spectrum-css/avatar": "^3.0.2",
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let fileSizeLimit = BYTES_IN_MB * 20
|
export let fileSizeLimit = BYTES_IN_MB * 20
|
||||||
export let processFiles = null
|
export let processFiles = null
|
||||||
|
export let deleteAttachments = null
|
||||||
export let handleFileTooLarge = null
|
export let handleFileTooLarge = null
|
||||||
export let handleTooManyFiles = null
|
export let handleTooManyFiles = null
|
||||||
export let gallery = true
|
export let gallery = true
|
||||||
|
@ -94,6 +95,11 @@
|
||||||
"change",
|
"change",
|
||||||
value.filter((x, idx) => idx !== selectedImageIdx)
|
value.filter((x, idx) => idx !== selectedImageIdx)
|
||||||
)
|
)
|
||||||
|
if (deleteAttachments) {
|
||||||
|
await deleteAttachments(
|
||||||
|
value.filter((x, idx) => idx === selectedImageIdx).map(item => item.key)
|
||||||
|
)
|
||||||
|
}
|
||||||
selectedImageIdx = 0
|
selectedImageIdx = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
export let error = null
|
export let error = null
|
||||||
export let fileSizeLimit = undefined
|
export let fileSizeLimit = undefined
|
||||||
export let processFiles = undefined
|
export let processFiles = undefined
|
||||||
|
export let deleteAttachments = undefined
|
||||||
export let handleFileTooLarge = undefined
|
export let handleFileTooLarge = undefined
|
||||||
export let handleTooManyFiles = undefined
|
export let handleTooManyFiles = undefined
|
||||||
export let gallery = true
|
export let gallery = true
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
{value}
|
{value}
|
||||||
{fileSizeLimit}
|
{fileSizeLimit}
|
||||||
{processFiles}
|
{processFiles}
|
||||||
|
{deleteAttachments}
|
||||||
{handleFileTooLarge}
|
{handleFileTooLarge}
|
||||||
{handleTooManyFiles}
|
{handleTooManyFiles}
|
||||||
{gallery}
|
{gallery}
|
||||||
|
|
|
@ -83,4 +83,9 @@
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spectrum-Icon--sizeXS {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher, getContext } from "svelte"
|
import { createEventDispatcher, getContext } from "svelte"
|
||||||
|
import Icon from "../Icon/Icon.svelte"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const actionMenu = getContext("actionMenu")
|
const actionMenu = getContext("actionMenu")
|
||||||
|
@ -8,6 +9,22 @@
|
||||||
export let icon = undefined
|
export let icon = undefined
|
||||||
export let disabled = undefined
|
export let disabled = undefined
|
||||||
export let noClose = false
|
export let noClose = false
|
||||||
|
export let keyBind = undefined
|
||||||
|
|
||||||
|
$: keys = getKeys(keyBind)
|
||||||
|
|
||||||
|
const getKeys = keyBind => {
|
||||||
|
let keys = keyBind?.split("+") || []
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (
|
||||||
|
keys[i].toLowerCase() === "ctrl" &&
|
||||||
|
navigator.platform.startsWith("Mac")
|
||||||
|
) {
|
||||||
|
keys[i] = "⌘"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
if (actionMenu && !noClose) {
|
if (actionMenu && !noClose) {
|
||||||
|
@ -26,20 +43,54 @@
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<svg
|
<div class="icon">
|
||||||
class="spectrum-Icon spectrum-Icon--sizeS spectrum-Menu-itemIcon"
|
<Icon name={icon} size="S" />
|
||||||
focusable="false"
|
</div>
|
||||||
aria-hidden="true"
|
|
||||||
aria-label={icon}
|
|
||||||
>
|
|
||||||
<use xlink:href="#spectrum-icon-18-{icon}" />
|
|
||||||
</svg>
|
|
||||||
{/if}
|
{/if}
|
||||||
<span class="spectrum-Menu-itemLabel"><slot /></span>
|
<span class="spectrum-Menu-itemLabel"><slot /></span>
|
||||||
|
{#if keys?.length}
|
||||||
|
<div class="keys">
|
||||||
|
{#each keys as key}
|
||||||
|
<div class="key">
|
||||||
|
{#if key.startsWith("!")}
|
||||||
|
<Icon size="XS" name={key.split("!")[1]} />
|
||||||
|
{:else}
|
||||||
|
{key}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.spectrum-Menu-itemIcon {
|
.icon {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
margin-right: var(--spacing-s);
|
||||||
|
}
|
||||||
|
.keys {
|
||||||
|
margin-left: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.key {
|
||||||
|
color: var(--spectrum-global-color-gray-900);
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: var(--spectrum-global-color-gray-300);
|
||||||
|
border-radius: 4px;
|
||||||
|
min-width: 12px;
|
||||||
|
height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
margin: -1px 0;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
.is-disabled .key {
|
||||||
|
color: var(--spectrum-global-color-gray-600);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let visible = fixed || inline
|
let visible = fixed || inline
|
||||||
|
let modal
|
||||||
|
|
||||||
$: dispatch(visible ? "show" : "hide")
|
$: dispatch(visible ? "show" : "hide")
|
||||||
|
|
||||||
export function show() {
|
export function show() {
|
||||||
|
@ -41,12 +43,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function focusFirstInput(node) {
|
async function focusModal(node) {
|
||||||
|
await tick()
|
||||||
|
|
||||||
|
// Try to focus first input
|
||||||
const inputs = node.querySelectorAll("input")
|
const inputs = node.querySelectorAll("input")
|
||||||
if (inputs?.length) {
|
if (inputs?.length) {
|
||||||
await tick()
|
|
||||||
inputs[0].focus()
|
inputs[0].focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise try to focus confirmation button
|
||||||
|
else if (modal) {
|
||||||
|
const confirm = modal.querySelector(".confirm-wrap .spectrum-Button")
|
||||||
|
if (confirm) {
|
||||||
|
confirm.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext(Context.Modal, { show, hide, cancel })
|
setContext(Context.Modal, { show, hide, cancel })
|
||||||
|
@ -56,7 +68,7 @@
|
||||||
|
|
||||||
{#if inline}
|
{#if inline}
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<div use:focusFirstInput class="spectrum-Modal inline is-open">
|
<div use:focusModal bind:this={modal} class="spectrum-Modal inline is-open">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -70,17 +82,18 @@
|
||||||
-->
|
-->
|
||||||
<Portal target=".modal-container">
|
<Portal target=".modal-container">
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<div
|
<div class="spectrum-Underlay is-open" on:mousedown|self={cancel}>
|
||||||
class="spectrum-Underlay is-open"
|
<div
|
||||||
in:fade={{ duration: 200 }}
|
class="background"
|
||||||
out:fade|local={{ duration: 200 }}
|
in:fade={{ duration: 200 }}
|
||||||
on:mousedown|self={cancel}
|
out:fade|local={{ duration: 200 }}
|
||||||
>
|
/>
|
||||||
<div class="modal-wrapper" on:mousedown|self={cancel}>
|
<div class="modal-wrapper" on:mousedown|self={cancel}>
|
||||||
<div class="modal-inner-wrapper" on:mousedown|self={cancel}>
|
<div class="modal-inner-wrapper" on:mousedown|self={cancel}>
|
||||||
<slot name="outside" />
|
<slot name="outside" />
|
||||||
<div
|
<div
|
||||||
use:focusFirstInput
|
use:focusModal
|
||||||
|
bind:this={modal}
|
||||||
class="spectrum-Modal is-open"
|
class="spectrum-Modal is-open"
|
||||||
in:fly={{ y: 30, duration: 200 }}
|
in:fly={{ y: 30, duration: 200 }}
|
||||||
out:fly|local={{ y: 30, duration: 200 }}
|
out:fly|local={{ y: 30, duration: 200 }}
|
||||||
|
@ -103,7 +116,17 @@
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
background: rgba(0, 0, 0, 0.75);
|
background: transparent;
|
||||||
|
}
|
||||||
|
.background {
|
||||||
|
background: var(--modal-background, rgba(0, 0, 0, 0.75));
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
opacity: 0.65;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-wrapper {
|
.modal-wrapper {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -69,10 +69,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "1.2.39-alpha.6",
|
"@budibase/bbui": "1.2.44-alpha.1",
|
||||||
"@budibase/client": "1.2.39-alpha.6",
|
"@budibase/client": "1.2.44-alpha.1",
|
||||||
"@budibase/frontend-core": "1.2.39-alpha.6",
|
"@budibase/frontend-core": "1.2.44-alpha.1",
|
||||||
"@budibase/string-templates": "1.2.39-alpha.6",
|
"@budibase/string-templates": "1.2.44-alpha.1",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -510,11 +510,11 @@ const getRoleBindings = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all bindable properties exposed in a button actions flow up until
|
* Gets all bindable properties exposed in an event action flow up until
|
||||||
* the specified action ID, as well as context provided for the action
|
* the specified action ID, as well as context provided for the action
|
||||||
* setting as a whole by the component.
|
* setting as a whole by the component.
|
||||||
*/
|
*/
|
||||||
export const getButtonContextBindings = (
|
export const getEventContextBindings = (
|
||||||
asset,
|
asset,
|
||||||
componentId,
|
componentId,
|
||||||
settingKey,
|
settingKey,
|
||||||
|
@ -528,10 +528,7 @@ export const getButtonContextBindings = (
|
||||||
const component = findComponent(asset.props, componentId)
|
const component = findComponent(asset.props, componentId)
|
||||||
const settings = getComponentSettings(component?._component)
|
const settings = getComponentSettings(component?._component)
|
||||||
const eventSetting = settings.find(setting => setting.key === settingKey)
|
const eventSetting = settings.find(setting => setting.key === settingKey)
|
||||||
if (!eventSetting) {
|
if (eventSetting?.context?.length) {
|
||||||
return bindings
|
|
||||||
}
|
|
||||||
if (eventSetting.context?.length) {
|
|
||||||
eventSetting.context.forEach(contextEntry => {
|
eventSetting.context.forEach(contextEntry => {
|
||||||
bindings.push({
|
bindings.push({
|
||||||
readableBinding: contextEntry.label,
|
readableBinding: contextEntry.label,
|
||||||
|
|
|
@ -534,7 +534,16 @@ export const getFrontendStore = () => {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let parentId
|
|
||||||
|
// Determine the next component to select after deletion
|
||||||
|
const state = get(store)
|
||||||
|
let nextSelectedComponentId
|
||||||
|
if (state.selectedComponentId === component._id) {
|
||||||
|
nextSelectedComponentId = store.actions.components.getNext()
|
||||||
|
if (!nextSelectedComponentId) {
|
||||||
|
nextSelectedComponentId = store.actions.components.getPrevious()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Patch screen
|
// Patch screen
|
||||||
await store.actions.screens.patch(screen => {
|
await store.actions.screens.patch(screen => {
|
||||||
|
@ -549,17 +558,18 @@ export const getFrontendStore = () => {
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
parentId = parent._id
|
|
||||||
parent._children = parent._children.filter(
|
parent._children = parent._children.filter(
|
||||||
child => child._id !== component._id
|
child => child._id !== component._id
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Select the deleted component's parent
|
// Update selected component if required
|
||||||
store.update(state => {
|
if (nextSelectedComponentId) {
|
||||||
state.selectedComponentId = parentId
|
store.update(state => {
|
||||||
return state
|
state.selectedComponentId = nextSelectedComponentId
|
||||||
})
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
copy: (component, cut = false, selectParent = true) => {
|
copy: (component, cut = false, selectParent = true) => {
|
||||||
// Update store with copied component
|
// Update store with copied component
|
||||||
|
@ -618,6 +628,16 @@ export const getFrontendStore = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check inside is valid
|
||||||
|
if (mode === "inside") {
|
||||||
|
const definition = store.actions.components.getDefinition(
|
||||||
|
targetComponent._component
|
||||||
|
)
|
||||||
|
if (!definition.hasChildren) {
|
||||||
|
mode = "below"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Paste new component
|
// Paste new component
|
||||||
if (mode === "inside") {
|
if (mode === "inside") {
|
||||||
// Paste inside target component if chosen
|
// Paste inside target component if chosen
|
||||||
|
@ -654,46 +674,193 @@ export const getFrontendStore = () => {
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
getPrevious: () => {
|
||||||
|
const state = get(store)
|
||||||
|
const componentId = state.selectedComponentId
|
||||||
|
const screen = get(selectedScreen)
|
||||||
|
const parent = findComponentParent(screen.props, componentId)
|
||||||
|
|
||||||
|
// Check we aren't right at the top of the tree
|
||||||
|
const index = parent?._children.findIndex(x => x._id === componentId)
|
||||||
|
if (!parent || componentId === screen.props._id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have siblings above us, choose the sibling or a descendant
|
||||||
|
if (index > 0) {
|
||||||
|
// If sibling before us accepts children, select a descendant
|
||||||
|
const previousSibling = parent._children[index - 1]
|
||||||
|
if (previousSibling._children?.length) {
|
||||||
|
let target = previousSibling
|
||||||
|
while (target._children?.length) {
|
||||||
|
target = target._children[target._children.length - 1]
|
||||||
|
}
|
||||||
|
return target._id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise just select sibling
|
||||||
|
return previousSibling._id
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no siblings above us, select the parent
|
||||||
|
return parent._id
|
||||||
|
},
|
||||||
|
getNext: () => {
|
||||||
|
const component = get(selectedComponent)
|
||||||
|
const componentId = component?._id
|
||||||
|
const screen = get(selectedScreen)
|
||||||
|
const parent = findComponentParent(screen.props, componentId)
|
||||||
|
const index = parent?._children.findIndex(x => x._id === componentId)
|
||||||
|
|
||||||
|
// If we have children, select first child
|
||||||
|
if (component._children?.length) {
|
||||||
|
return component._children[0]._id
|
||||||
|
} else if (!parent) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise select the next sibling if we have one
|
||||||
|
if (index < parent._children.length - 1) {
|
||||||
|
const nextSibling = parent._children[index + 1]
|
||||||
|
return nextSibling._id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last child, select our parents next sibling
|
||||||
|
let target = parent
|
||||||
|
let targetParent = findComponentParent(screen.props, target._id)
|
||||||
|
let targetIndex = targetParent?._children.findIndex(
|
||||||
|
child => child._id === target._id
|
||||||
|
)
|
||||||
|
while (
|
||||||
|
targetParent != null &&
|
||||||
|
targetIndex === targetParent._children?.length - 1
|
||||||
|
) {
|
||||||
|
target = targetParent
|
||||||
|
targetParent = findComponentParent(screen.props, target._id)
|
||||||
|
targetIndex = targetParent?._children.findIndex(
|
||||||
|
child => child._id === target._id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (targetParent) {
|
||||||
|
return targetParent._children[targetIndex + 1]._id
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectPrevious: () => {
|
||||||
|
const previousId = store.actions.components.getPrevious()
|
||||||
|
if (previousId) {
|
||||||
|
store.update(state => {
|
||||||
|
state.selectedComponentId = previousId
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectNext: () => {
|
||||||
|
const nextId = store.actions.components.getNext()
|
||||||
|
if (nextId) {
|
||||||
|
store.update(state => {
|
||||||
|
state.selectedComponentId = nextId
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
moveUp: async component => {
|
moveUp: async component => {
|
||||||
await store.actions.screens.patch(screen => {
|
await store.actions.screens.patch(screen => {
|
||||||
const componentId = component?._id
|
const componentId = component?._id
|
||||||
const parent = findComponentParent(screen.props, componentId)
|
const parent = findComponentParent(screen.props, componentId)
|
||||||
if (!parent?._children?.length) {
|
|
||||||
return false
|
// Check we aren't right at the top of the tree
|
||||||
|
const index = parent?._children.findIndex(x => x._id === componentId)
|
||||||
|
if (!parent || (index === 0 && parent._id === screen.props._id)) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
const currentIndex = parent._children.findIndex(
|
|
||||||
child => child._id === componentId
|
// Copy original component and remove it from the parent
|
||||||
)
|
const originalComponent = cloneDeep(parent._children[index])
|
||||||
if (currentIndex === 0) {
|
parent._children = parent._children.filter(
|
||||||
return false
|
|
||||||
}
|
|
||||||
const originalComponent = cloneDeep(parent._children[currentIndex])
|
|
||||||
const newChildren = parent._children.filter(
|
|
||||||
component => component._id !== componentId
|
component => component._id !== componentId
|
||||||
)
|
)
|
||||||
newChildren.splice(currentIndex - 1, 0, originalComponent)
|
|
||||||
parent._children = newChildren
|
// If we have siblings above us, move up
|
||||||
|
if (index > 0) {
|
||||||
|
// If sibling before us accepts children, move to last child of
|
||||||
|
// sibling
|
||||||
|
const previousSibling = parent._children[index - 1]
|
||||||
|
const definition = store.actions.components.getDefinition(
|
||||||
|
previousSibling._component
|
||||||
|
)
|
||||||
|
if (definition.hasChildren) {
|
||||||
|
previousSibling._children.push(originalComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise just move component above sibling
|
||||||
|
else {
|
||||||
|
parent._children.splice(index - 1, 0, originalComponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no siblings above us, go above the parent as long as it isn't
|
||||||
|
// the screen
|
||||||
|
else if (parent._id !== screen.props._id) {
|
||||||
|
const grandParent = findComponentParent(screen.props, parent._id)
|
||||||
|
const parentIndex = grandParent._children.findIndex(
|
||||||
|
child => child._id === parent._id
|
||||||
|
)
|
||||||
|
grandParent._children.splice(parentIndex, 0, originalComponent)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
moveDown: async component => {
|
moveDown: async component => {
|
||||||
await store.actions.screens.patch(screen => {
|
await store.actions.screens.patch(screen => {
|
||||||
const componentId = component?._id
|
const componentId = component?._id
|
||||||
const parent = findComponentParent(screen.props, componentId)
|
const parent = findComponentParent(screen.props, componentId)
|
||||||
|
|
||||||
|
// Sanity check parent is found
|
||||||
if (!parent?._children?.length) {
|
if (!parent?._children?.length) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const currentIndex = parent._children.findIndex(
|
|
||||||
child => child._id === componentId
|
// Check we aren't right at the bottom of the tree
|
||||||
)
|
const index = parent._children.findIndex(x => x._id === componentId)
|
||||||
if (currentIndex === parent._children.length - 1) {
|
if (
|
||||||
return false
|
index === parent._children.length - 1 &&
|
||||||
|
parent._id === screen.props._id
|
||||||
|
) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
const originalComponent = cloneDeep(parent._children[currentIndex])
|
|
||||||
const newChildren = parent._children.filter(
|
// Copy the original component and remove from parent
|
||||||
|
const originalComponent = cloneDeep(parent._children[index])
|
||||||
|
parent._children = parent._children.filter(
|
||||||
component => component._id !== componentId
|
component => component._id !== componentId
|
||||||
)
|
)
|
||||||
newChildren.splice(currentIndex + 1, 0, originalComponent)
|
|
||||||
parent._children = newChildren
|
// Move below the next sibling if we are not the last sibling
|
||||||
|
if (index < parent._children.length) {
|
||||||
|
// If the next sibling has children, become the first child
|
||||||
|
const nextSibling = parent._children[index]
|
||||||
|
const definition = store.actions.components.getDefinition(
|
||||||
|
nextSibling._component
|
||||||
|
)
|
||||||
|
if (definition.hasChildren) {
|
||||||
|
nextSibling._children.splice(0, 0, originalComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise move below next sibling
|
||||||
|
else {
|
||||||
|
parent._children.splice(index + 1, 0, originalComponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last child, so move below our parent
|
||||||
|
else {
|
||||||
|
const grandParent = findComponentParent(screen.props, parent._id)
|
||||||
|
const parentIndex = grandParent._children.findIndex(
|
||||||
|
child => child._id === parent._id
|
||||||
|
)
|
||||||
|
grandParent._children.splice(parentIndex + 1, 0, originalComponent)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateStyle: async (name, value) => {
|
updateStyle: async (name, value) => {
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
width="28px"
|
width="28px"
|
||||||
height="28px"
|
height="28px"
|
||||||
class="spectrum-Icon"
|
class="spectrum-Icon"
|
||||||
style="color:grey;"
|
style="color:var(--spectrum-global-color-gray-700);"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
>
|
>
|
||||||
<use xlink:href="#spectrum-icon-18-Reuse" />
|
<use xlink:href="#spectrum-icon-18-Reuse" />
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
width="28px"
|
width="28px"
|
||||||
height="28px"
|
height="28px"
|
||||||
class="spectrum-Icon"
|
class="spectrum-Icon"
|
||||||
style="color:grey;"
|
style="color:var(--spectrum-global-color-gray-700);"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
>
|
>
|
||||||
<use xlink:href="#spectrum-icon-18-{block.icon}" />
|
<use xlink:href="#spectrum-icon-18-{block.icon}" />
|
||||||
|
|
|
@ -167,6 +167,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
<HideAutocolumnButton bind:hideAutocolumns />
|
<HideAutocolumnButton bind:hideAutocolumns />
|
||||||
<ImportButton
|
<ImportButton
|
||||||
|
disabled={$tables.selected?._id === "ta_users"}
|
||||||
tableId={$tables.selected?._id}
|
tableId={$tables.selected?._id}
|
||||||
on:updaterows={onUpdateRows}
|
on:updaterows={onUpdateRows}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
import ImportModal from "../modals/ImportModal.svelte"
|
import ImportModal from "../modals/ImportModal.svelte"
|
||||||
|
|
||||||
export let tableId
|
export let tableId
|
||||||
|
export let disabled
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionButton icon="DataUpload" size="S" quiet on:click={modal.show}>
|
<ActionButton icon="DataUpload" size="S" quiet on:click={modal.show} {disabled}>
|
||||||
Import
|
Import
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
|
|
|
@ -27,6 +27,14 @@
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteAttachments(fileList) {
|
||||||
|
try {
|
||||||
|
return await API.deleteBuilderAttachments(fileList)
|
||||||
|
} catch (error) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Dropzone
|
<Dropzone
|
||||||
|
@ -34,5 +42,6 @@
|
||||||
{label}
|
{label}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
{processFiles}
|
{processFiles}
|
||||||
|
{deleteAttachments}
|
||||||
{handleFileTooLarge}
|
{handleFileTooLarge}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { getAvailableActions } from "./index"
|
import { getAvailableActions } from "./index"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import { getButtonContextBindings } from "builderStore/dataBinding"
|
import { getEventContextBindings } from "builderStore/dataBinding"
|
||||||
import { currentAsset, store } from "builderStore"
|
import { currentAsset, store } from "builderStore"
|
||||||
|
|
||||||
const flipDurationMs = 150
|
const flipDurationMs = 150
|
||||||
|
@ -41,14 +41,14 @@
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
// These are ephemeral bindings which only exist while executing actions
|
// These are ephemeral bindings which only exist while executing actions
|
||||||
$: buttonContextBindings = getButtonContextBindings(
|
$: eventContexBindings = getEventContextBindings(
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
$store.selectedComponentId,
|
$store.selectedComponentId,
|
||||||
key,
|
key,
|
||||||
actions,
|
actions,
|
||||||
selectedAction?.id
|
selectedAction?.id
|
||||||
)
|
)
|
||||||
$: allBindings = buttonContextBindings.concat(bindings)
|
$: allBindings = eventContexBindings.concat(bindings)
|
||||||
|
|
||||||
// Assign a unique ID to each action
|
// Assign a unique ID to each action
|
||||||
$: {
|
$: {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
selectedLayout,
|
selectedLayout,
|
||||||
currentAsset,
|
currentAsset,
|
||||||
} from "builderStore"
|
} from "builderStore"
|
||||||
import iframeTemplate from "./iframeTemplate"
|
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import {
|
import {
|
||||||
ProgressCircle,
|
ProgressCircle,
|
||||||
|
@ -40,12 +39,6 @@
|
||||||
BUDIBASE: "type",
|
BUDIBASE: "type",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct iframe template
|
|
||||||
$: template = iframeTemplate.replace(
|
|
||||||
/\{\{ CLIENT_LIB_PATH }}/,
|
|
||||||
$store.clientLibPath
|
|
||||||
)
|
|
||||||
|
|
||||||
const placeholderScreen = new Screen()
|
const placeholderScreen = new Screen()
|
||||||
.name("Screen Placeholder")
|
.name("Screen Placeholder")
|
||||||
.route("/")
|
.route("/")
|
||||||
|
@ -151,7 +144,11 @@
|
||||||
} else if (type === "update-prop") {
|
} else if (type === "update-prop") {
|
||||||
await store.actions.components.updateSetting(data.prop, data.value)
|
await store.actions.components.updateSetting(data.prop, data.value)
|
||||||
} else if (type === "delete-component" && data.id) {
|
} else if (type === "delete-component" && data.id) {
|
||||||
|
// Legacy type, can be deleted in future
|
||||||
confirmDeleteComponent(data.id)
|
confirmDeleteComponent(data.id)
|
||||||
|
} else if (type === "key-down") {
|
||||||
|
const { key, ctrlKey } = data
|
||||||
|
document.dispatchEvent(new KeyboardEvent("keydown", { key, ctrlKey }))
|
||||||
} else if (type === "duplicate-component" && data.id) {
|
} else if (type === "duplicate-component" && data.id) {
|
||||||
const rootComponent = get(currentAsset).props
|
const rootComponent = get(currentAsset).props
|
||||||
const component = findComponent(rootComponent, data.id)
|
const component = findComponent(rootComponent, data.id)
|
||||||
|
@ -294,7 +291,7 @@
|
||||||
<iframe
|
<iframe
|
||||||
title="componentPreview"
|
title="componentPreview"
|
||||||
bind:this={iframe}
|
bind:this={iframe}
|
||||||
srcdoc={template}
|
src="/preview"
|
||||||
class:hidden={loading || error}
|
class:hidden={loading || error}
|
||||||
class:tablet={$store.previewDevice === "tablet"}
|
class:tablet={$store.previewDevice === "tablet"}
|
||||||
class:mobile={$store.previewDevice === "mobile"}
|
class:mobile={$store.previewDevice === "mobile"}
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
export default `
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<style>
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
html {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script src='{{ CLIENT_LIB_PATH }}'></script>
|
|
||||||
<script>
|
|
||||||
function receiveMessage(event) {
|
|
||||||
if (!event.data) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse received message
|
|
||||||
// If parsing fails, just ignore and wait for the next message
|
|
||||||
let parsed
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(event.data)
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Client received invalid JSON")
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
if (!parsed || !parsed.isBudibaseEvent) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract data from message
|
|
||||||
const {
|
|
||||||
selectedComponentId,
|
|
||||||
layout,
|
|
||||||
screen,
|
|
||||||
appId,
|
|
||||||
theme,
|
|
||||||
customTheme,
|
|
||||||
previewDevice,
|
|
||||||
navigation,
|
|
||||||
hiddenComponentIds
|
|
||||||
} = parsed
|
|
||||||
|
|
||||||
// Set some flags so the app knows we're in the builder
|
|
||||||
window["##BUDIBASE_IN_BUILDER##"] = true
|
|
||||||
window["##BUDIBASE_APP_ID##"] = appId
|
|
||||||
window["##BUDIBASE_PREVIEW_LAYOUT##"] = layout
|
|
||||||
window["##BUDIBASE_PREVIEW_SCREEN##"] = screen
|
|
||||||
window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId
|
|
||||||
window["##BUDIBASE_PREVIEW_ID##"] = Math.random()
|
|
||||||
window["##BUDIBASE_PREVIEW_THEME##"] = theme
|
|
||||||
window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
|
|
||||||
window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
|
|
||||||
window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
|
|
||||||
window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
|
|
||||||
|
|
||||||
// Initialise app
|
|
||||||
try {
|
|
||||||
if (window.loadBudibase) {
|
|
||||||
window.loadBudibase()
|
|
||||||
document.documentElement.classList.add("loaded")
|
|
||||||
} else {
|
|
||||||
throw "The client library couldn't be loaded"
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
window.parent.postMessage({ type: "error", error })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("message", receiveMessage)
|
|
||||||
window.parent.postMessage({ type: "ready" })
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body/>
|
|
||||||
</html>
|
|
||||||
`
|
|
|
@ -1,117 +1,69 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import { ActionMenu, MenuItem, Icon } from "@budibase/bbui"
|
||||||
import { ActionMenu, MenuItem, Icon, notifications } from "@budibase/bbui"
|
|
||||||
|
|
||||||
export let component
|
|
||||||
|
|
||||||
let confirmDeleteDialog
|
|
||||||
|
|
||||||
$: definition = store.actions.components.getDefinition(component?._component)
|
|
||||||
$: noChildrenAllowed = !component || !definition?.hasChildren
|
|
||||||
$: noPaste = !$store.componentToPaste
|
$: noPaste = !$store.componentToPaste
|
||||||
|
|
||||||
// "editable" has been repurposed for inline text editing.
|
const keyboardEvent = (key, ctrlKey = false) => {
|
||||||
// It remains here for legacy compatibility.
|
document.dispatchEvent(new KeyboardEvent("keydown", { key, ctrlKey }))
|
||||||
// Future components should define "static": true for indicate they should
|
|
||||||
// not show a context menu.
|
|
||||||
$: showMenu = definition?.editable !== false && definition?.static !== true
|
|
||||||
|
|
||||||
const moveUpComponent = async () => {
|
|
||||||
try {
|
|
||||||
await store.actions.components.moveUp(component)
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error moving component up")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const moveDownComponent = async () => {
|
|
||||||
try {
|
|
||||||
await store.actions.components.moveDown(component)
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error moving component down")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const duplicateComponent = () => {
|
|
||||||
storeComponentForCopy(false)
|
|
||||||
pasteComponent("below")
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteComponent = async () => {
|
|
||||||
try {
|
|
||||||
await store.actions.components.delete(component)
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error deleting component")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const storeComponentForCopy = (cut = false) => {
|
|
||||||
store.actions.components.copy(component, cut)
|
|
||||||
}
|
|
||||||
|
|
||||||
const pasteComponent = mode => {
|
|
||||||
try {
|
|
||||||
store.actions.components.paste(component, mode)
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error saving component")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showMenu}
|
<ActionMenu>
|
||||||
<ActionMenu>
|
<div slot="control" class="icon">
|
||||||
<div slot="control" class="icon">
|
<Icon size="S" hoverable name="MoreSmallList" />
|
||||||
<Icon size="S" hoverable name="MoreSmallList" />
|
</div>
|
||||||
</div>
|
<MenuItem
|
||||||
<MenuItem icon="Delete" on:click={confirmDeleteDialog.show}>
|
icon="Delete"
|
||||||
Delete
|
keyBind="!BackAndroid"
|
||||||
</MenuItem>
|
on:click={() => keyboardEvent("Delete")}
|
||||||
<MenuItem noClose icon="ChevronUp" on:click={moveUpComponent}>
|
>
|
||||||
Move up
|
Delete
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem noClose icon="ChevronDown" on:click={moveDownComponent}>
|
<MenuItem
|
||||||
Move down
|
icon="ChevronUp"
|
||||||
</MenuItem>
|
keyBind="Ctrl+!ArrowUp"
|
||||||
<MenuItem noClose icon="Duplicate" on:click={duplicateComponent}>
|
on:click={() => keyboardEvent("ArrowUp", true)}
|
||||||
Duplicate
|
>
|
||||||
</MenuItem>
|
Move up
|
||||||
<MenuItem icon="Cut" on:click={() => storeComponentForCopy(true)}>
|
</MenuItem>
|
||||||
Cut
|
<MenuItem
|
||||||
</MenuItem>
|
icon="ChevronDown"
|
||||||
<MenuItem icon="Copy" on:click={() => storeComponentForCopy(false)}>
|
keyBind="Ctrl+!ArrowDown"
|
||||||
Copy
|
on:click={() => keyboardEvent("ArrowDown", true)}
|
||||||
</MenuItem>
|
>
|
||||||
<MenuItem
|
Move down
|
||||||
icon="LayersBringToFront"
|
</MenuItem>
|
||||||
on:click={() => pasteComponent("above")}
|
<MenuItem
|
||||||
disabled={noPaste}
|
icon="Duplicate"
|
||||||
>
|
keyBind="Ctrl+D"
|
||||||
Paste above
|
on:click={() => keyboardEvent("d", true)}
|
||||||
</MenuItem>
|
>
|
||||||
<MenuItem
|
Duplicate
|
||||||
icon="LayersSendToBack"
|
</MenuItem>
|
||||||
on:click={() => pasteComponent("below")}
|
<MenuItem
|
||||||
disabled={noPaste}
|
icon="Cut"
|
||||||
>
|
keyBind="Ctrl+X"
|
||||||
Paste below
|
on:click={() => keyboardEvent("x", true)}
|
||||||
</MenuItem>
|
>
|
||||||
<MenuItem
|
Cut
|
||||||
icon="ShowOneLayer"
|
</MenuItem>
|
||||||
on:click={() => pasteComponent("inside")}
|
<MenuItem
|
||||||
disabled={noPaste || noChildrenAllowed}
|
icon="Copy"
|
||||||
>
|
keyBind="Ctrl+C"
|
||||||
Paste inside
|
on:click={() => keyboardEvent("c", true)}
|
||||||
</MenuItem>
|
>
|
||||||
</ActionMenu>
|
Copy
|
||||||
<ConfirmDialog
|
</MenuItem>
|
||||||
bind:this={confirmDeleteDialog}
|
<MenuItem
|
||||||
title="Confirm Deletion"
|
icon="LayersSendToBack"
|
||||||
body={`Are you sure you wish to delete this '${definition?.name}' component?`}
|
keyBind="Ctrl+V"
|
||||||
okText="Delete Component"
|
on:click={() => keyboardEvent("v", true)}
|
||||||
onOk={deleteComponent}
|
disabled={noPaste}
|
||||||
/>
|
>
|
||||||
{/if}
|
Paste
|
||||||
|
</MenuItem>
|
||||||
|
</ActionMenu>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.icon {
|
.icon {
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
import Panel from "components/design/Panel.svelte"
|
import Panel from "components/design/Panel.svelte"
|
||||||
import ComponentTree from "./ComponentTree.svelte"
|
import ComponentTree from "./ComponentTree.svelte"
|
||||||
import { dndStore } from "./dndStore.js"
|
import { dndStore } from "./dndStore.js"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto, isActive } from "@roxi/routify"
|
||||||
import { store, selectedScreen } from "builderStore"
|
import { store, selectedScreen, selectedComponent } from "builderStore"
|
||||||
import NavItem from "components/common/NavItem.svelte"
|
import NavItem from "components/common/NavItem.svelte"
|
||||||
import ScreenslotDropdownMenu from "./ScreenslotDropdownMenu.svelte"
|
import ScreenslotDropdownMenu from "./ScreenslotDropdownMenu.svelte"
|
||||||
import { setContext } from "svelte"
|
import { setContext, onMount } from "svelte"
|
||||||
|
import { get } from "svelte/store"
|
||||||
import DNDPositionIndicator from "./DNDPositionIndicator.svelte"
|
import DNDPositionIndicator from "./DNDPositionIndicator.svelte"
|
||||||
import { DropPosition } from "./dndStore"
|
import { DropPosition } from "./dndStore"
|
||||||
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import { notifications, Button } from "@budibase/bbui"
|
import { notifications, Button } from "@budibase/bbui"
|
||||||
|
|
||||||
let scrollRef
|
let scrollRef
|
||||||
|
let confirmDeleteDialog
|
||||||
|
|
||||||
const scrollTo = bounds => {
|
const scrollTo = bounds => {
|
||||||
if (!bounds) {
|
if (!bounds) {
|
||||||
|
@ -69,6 +72,76 @@
|
||||||
setContext("scroll", {
|
setContext("scroll", {
|
||||||
scrollTo,
|
scrollTo,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const deleteComponent = async () => {
|
||||||
|
await store.actions.components.delete(get(selectedComponent))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyPress = async e => {
|
||||||
|
// Ignore repeating events
|
||||||
|
if (e.repeat) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Ignore events when typing
|
||||||
|
const activeTag = document.activeElement?.tagName.toLowerCase()
|
||||||
|
if (["input", "textarea"].indexOf(activeTag) !== -1 && e.key !== "Escape") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const component = get(selectedComponent)
|
||||||
|
try {
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
if (e.key === "ArrowUp") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.moveUp(component)
|
||||||
|
} else if (e.key === "ArrowDown") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.moveDown(component)
|
||||||
|
} else if (e.key === "c") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.copy(component, false)
|
||||||
|
} else if (e.key === "x") {
|
||||||
|
e.preventDefault()
|
||||||
|
store.actions.components.copy(component, true)
|
||||||
|
} else if (e.key === "v") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.paste(component, "inside")
|
||||||
|
} else if (e.key === "d") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.copy(component)
|
||||||
|
await store.actions.components.paste(component, "below")
|
||||||
|
} else if (e.key === "Enter") {
|
||||||
|
e.preventDefault()
|
||||||
|
$goto("./new")
|
||||||
|
}
|
||||||
|
} else if (e.key === "Backspace" || e.key === "Delete") {
|
||||||
|
// Don't show confirmation for the screen itself
|
||||||
|
if (component._id === get(selectedScreen).props._id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
confirmDeleteDialog.show()
|
||||||
|
} else if (e.key === "ArrowUp") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.selectPrevious()
|
||||||
|
} else if (e.key === "ArrowDown") {
|
||||||
|
e.preventDefault()
|
||||||
|
await store.actions.components.selectNext()
|
||||||
|
} else if (e.key === "Escape" && $isActive("./new")) {
|
||||||
|
e.preventDefault()
|
||||||
|
$goto("./")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
notifications.error("Error handling key press")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
document.addEventListener("keydown", handleKeyPress)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("keydown", handleKeyPress)
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Panel title="Components" showExpandIcon borderRight>
|
<Panel title="Components" showExpandIcon borderRight>
|
||||||
|
@ -116,6 +189,13 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
<ConfirmDialog
|
||||||
|
bind:this={confirmDeleteDialog}
|
||||||
|
title="Confirm Deletion"
|
||||||
|
body={`Are you sure you want to delete "${$selectedComponent?._instanceName}"?`}
|
||||||
|
okText="Delete Component"
|
||||||
|
onOk={deleteComponent}
|
||||||
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.add-component {
|
.add-component {
|
||||||
|
|
|
@ -31,15 +31,20 @@
|
||||||
<div slot="control" class="icon">
|
<div slot="control" class="icon">
|
||||||
<Icon size="S" hoverable name="MoreSmallList" />
|
<Icon size="S" hoverable name="MoreSmallList" />
|
||||||
</div>
|
</div>
|
||||||
<MenuItem icon="Copy" on:click={() => storeComponentForCopy(false)}>
|
<MenuItem
|
||||||
|
icon="Copy"
|
||||||
|
keyBind="Ctrl+C"
|
||||||
|
on:click={() => storeComponentForCopy(false)}
|
||||||
|
>
|
||||||
Copy
|
Copy
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon="ShowOneLayer"
|
icon="LayersSendToBack"
|
||||||
|
keyBind="Ctrl+V"
|
||||||
on:click={() => pasteComponent("inside")}
|
on:click={() => pasteComponent("inside")}
|
||||||
disabled={noPaste}
|
disabled={noPaste}
|
||||||
>
|
>
|
||||||
Paste inside
|
Paste
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</ActionMenu>
|
</ActionMenu>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -36,7 +36,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const canRenderControl = setting => {
|
const canRenderControl = (setting, isScreen) => {
|
||||||
|
// Prevent rendering on click setting for screens
|
||||||
|
if (setting?.type === "event" && isScreen) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const control = getComponentForSetting(setting)
|
const control = getComponentForSetting(setting)
|
||||||
if (!control) {
|
if (!control) {
|
||||||
return false
|
return false
|
||||||
|
@ -87,7 +92,7 @@
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#each section.settings as setting (setting.key)}
|
{#each section.settings as setting (setting.key)}
|
||||||
{#if canRenderControl(setting)}
|
{#if canRenderControl(setting, isScreen)}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
type={setting.type}
|
type={setting.type}
|
||||||
control={getComponentForSetting(setting)}
|
control={getComponentForSetting(setting)}
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
Constants.OperatorOptions.NotEmpty.value,
|
Constants.OperatorOptions.NotEmpty.value,
|
||||||
]
|
]
|
||||||
condition.noValue = noValueOptions.includes(newOperator)
|
condition.noValue = noValueOptions.includes(newOperator)
|
||||||
if (condition.noValue) {
|
if (condition.noValue || newOperator === "oneOf") {
|
||||||
condition.referenceValue = null
|
condition.referenceValue = null
|
||||||
condition.valueType = "string"
|
condition.valueType = "string"
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@
|
||||||
on:change={e => onOperatorChange(condition, e.detail)}
|
on:change={e => onOperatorChange(condition, e.detail)}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
disabled={condition.noValue}
|
disabled={condition.noValue || condition.operator === "oneOf"}
|
||||||
options={valueTypeOptions}
|
options={valueTypeOptions}
|
||||||
bind:value={condition.valueType}
|
bind:value={condition.valueType}
|
||||||
placeholder={null}
|
placeholder={null}
|
||||||
|
|
|
@ -1,20 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { notifications, Slider, Icon } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
|
import { Constants } from "@budibase/frontend-core"
|
||||||
|
|
||||||
const ThemeOptions = [
|
const onChangeTheme = async theme => {
|
||||||
"spectrum--darkest",
|
|
||||||
"spectrum--dark",
|
|
||||||
"spectrum--light",
|
|
||||||
"spectrum--lightest",
|
|
||||||
]
|
|
||||||
|
|
||||||
$: themeIndex = ThemeOptions.indexOf($store.theme) ?? 2
|
|
||||||
|
|
||||||
const onChangeTheme = async e => {
|
|
||||||
try {
|
try {
|
||||||
const theme = ThemeOptions[e.detail] ?? ThemeOptions[2]
|
await store.actions.theme.save(`spectrum--${theme}`)
|
||||||
await store.actions.theme.save(theme)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error updating theme")
|
notifications.error("Error updating theme")
|
||||||
}
|
}
|
||||||
|
@ -22,26 +13,52 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Icon name="Moon" />
|
{#each Constants.Themes as theme}
|
||||||
<Slider
|
<div
|
||||||
min={0}
|
class="theme"
|
||||||
max={3}
|
class:selected={`spectrum--${theme.class}` === $store.theme}
|
||||||
step={1}
|
on:click={() => onChangeTheme(theme.class)}
|
||||||
value={themeIndex}
|
>
|
||||||
on:change={onChangeTheme}
|
<div
|
||||||
/>
|
style="background: {theme.preview}"
|
||||||
<Icon name="Light" />
|
class="color spectrum--{theme.class}"
|
||||||
|
/>
|
||||||
|
{theme.name}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div {
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
.color {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50px;
|
||||||
|
background: var(--spectrum-global-color-gray-200);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.theme {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-xl);
|
||||||
|
transition: background 130ms ease-out;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--spectrum-global-color-gray-900);
|
||||||
}
|
}
|
||||||
div :global(.spectrum-Form-item) {
|
.theme:hover {
|
||||||
flex: 1 1 auto;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.theme.selected,
|
||||||
|
.theme:hover {
|
||||||
|
background: var(--spectrum-global-color-gray-50);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
import { Slider, Button } from "@budibase/bbui"
|
||||||
|
|
||||||
|
export let customTheme
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
const options = ["0", "4px", "8px", "16px"]
|
||||||
|
|
||||||
|
$: index = options.indexOf(customTheme.buttonBorderRadius) ?? 2
|
||||||
|
|
||||||
|
const onChange = async e => {
|
||||||
|
dispatch("change", options[e.detail])
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<Slider min={0} max={3} step={1} value={index} on:change={onChange} />
|
||||||
|
<div class="button" style="--radius: {customTheme.buttonBorderRadius};">
|
||||||
|
<Button primary newStyles>Button</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
.container :global(.spectrum-Form-item) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
.button :global(.spectrum-Button) {
|
||||||
|
border-radius: var(--radius) !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,35 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import Panel from "components/design/Panel.svelte"
|
import Panel from "components/design/Panel.svelte"
|
||||||
import {
|
import { Layout, Label, ColorPicker, notifications } from "@budibase/bbui"
|
||||||
Layout,
|
|
||||||
Label,
|
|
||||||
ColorPicker,
|
|
||||||
Button,
|
|
||||||
notifications,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { DefaultAppTheme } from "constants"
|
import { DefaultAppTheme } from "constants"
|
||||||
import AppThemeSelect from "./AppThemeSelect.svelte"
|
import AppThemeSelect from "./AppThemeSelect.svelte"
|
||||||
|
import ButtonRoundnessSelect from "./ButtonRoundnessSelect.svelte"
|
||||||
const ButtonBorderRadiusOptions = [
|
|
||||||
{
|
|
||||||
label: "Square",
|
|
||||||
value: "0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Soft edge",
|
|
||||||
value: "4px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Curved",
|
|
||||||
value: "8px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Round",
|
|
||||||
value: "16px",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
$: customTheme = $store.customTheme || {}
|
$: customTheme = $store.customTheme || {}
|
||||||
|
|
||||||
|
@ -52,22 +28,11 @@
|
||||||
<AppThemeSelect />
|
<AppThemeSelect />
|
||||||
</Layout>
|
</Layout>
|
||||||
<Layout noPadding gap="XS">
|
<Layout noPadding gap="XS">
|
||||||
<Label>Buttons</Label>
|
<Label>Button roundness</Label>
|
||||||
<div class="buttons">
|
<ButtonRoundnessSelect
|
||||||
{#each ButtonBorderRadiusOptions as option}
|
{customTheme}
|
||||||
<div
|
on:change={e => update("buttonBorderRadius", e.detail)}
|
||||||
class:active={customTheme.buttonBorderRadius === option.value}
|
/>
|
||||||
style={`--radius: ${option.value}`}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
secondary
|
|
||||||
on:click={() => update("buttonBorderRadius", option.value)}
|
|
||||||
>
|
|
||||||
{option.label}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
<Layout noPadding gap="XS">
|
<Layout noPadding gap="XS">
|
||||||
<Label>Accent color</Label>
|
<Label>Accent color</Label>
|
||||||
|
@ -88,29 +53,3 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
<style>
|
|
||||||
.buttons {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 100px 100px;
|
|
||||||
gap: var(--spacing-m);
|
|
||||||
}
|
|
||||||
.buttons > div {
|
|
||||||
display: contents;
|
|
||||||
}
|
|
||||||
.buttons > div :global(.spectrum-Button) {
|
|
||||||
border-radius: var(--radius) !important;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--spectrum-global-color-gray-400);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.buttons > div:hover :global(.spectrum-Button) {
|
|
||||||
background: var(--spectrum-global-color-gray-700);
|
|
||||||
border-color: var(--spectrum-global-color-gray-700);
|
|
||||||
}
|
|
||||||
.buttons > div.active :global(.spectrum-Button) {
|
|
||||||
background: var(--spectrum-global-color-gray-200);
|
|
||||||
color: var(--spectrum-global-color-gray-800);
|
|
||||||
border-color: var(--spectrum-global-color-gray-600);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { Layout, Heading, Body, Button, notifications } from "@budibase/bbui"
|
import { Layout, Heading, Body, Button, notifications } from "@budibase/bbui"
|
||||||
import { goto, params } from "@roxi/routify"
|
import { goto, params } from "@roxi/routify"
|
||||||
import { users } from "stores/portal"
|
import { users, organisation } from "stores/portal"
|
||||||
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
|
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
|
||||||
import Logo from "assets/bb-emblem.svg"
|
import Logo from "assets/bb-emblem.svg"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
const inviteCode = $params["?code"]
|
const inviteCode = $params["?code"]
|
||||||
let password, error
|
let password, error
|
||||||
|
|
||||||
|
$: company = $organisation.company || "Budibase"
|
||||||
|
|
||||||
async function acceptInvite() {
|
async function acceptInvite() {
|
||||||
try {
|
try {
|
||||||
await users.acceptInvite(inviteCode, password)
|
await users.acceptInvite(inviteCode, password)
|
||||||
|
@ -17,16 +20,24 @@
|
||||||
notifications.error(error.message)
|
notifications.error(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
await organisation.init()
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error("Error getting org config")
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Layout>
|
<Layout>
|
||||||
<img src={Logo} alt="logo" />
|
<img alt="logo" src={$organisation.logoUrl || Logo} />
|
||||||
<Layout gap="XS" justifyItems="center" noPadding>
|
<Layout gap="XS" justifyItems="center" noPadding>
|
||||||
<Heading size="M">Accept Invitation</Heading>
|
<Heading size="M">Invitation to {company}</Heading>
|
||||||
<Body textAlign="center" size="M">
|
<Body textAlign="center" size="M">
|
||||||
Please enter a password to set up your user.
|
Please enter a password to get started.
|
||||||
</Body>
|
</Body>
|
||||||
</Layout>
|
</Layout>
|
||||||
<PasswordRepeatInput bind:error bind:password />
|
<PasswordRepeatInput bind:error bind:password />
|
||||||
|
@ -46,7 +57,7 @@
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 260px;
|
width: 300px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
if (!detail) return
|
if (!detail) return
|
||||||
|
|
||||||
const groupSelected = $groups.find(x => x._id === detail)
|
const groupSelected = $groups.find(x => x._id === detail)
|
||||||
const appIds = groupSelected?.apps.map(x => x.appId) || null
|
const appIds = groupSelected?.apps || null
|
||||||
dispatch("change", appIds)
|
dispatch("change", appIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
import { store, automationStore } from "builderStore"
|
import { store, automationStore } from "builderStore"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { apps, auth, admin, templates, groups } from "stores/portal"
|
import { apps, auth, admin, templates } from "stores/portal"
|
||||||
import download from "downloadjs"
|
import download from "downloadjs"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import AppRow from "components/start/AppRow.svelte"
|
import AppRow from "components/start/AppRow.svelte"
|
||||||
|
@ -355,7 +355,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="filter">
|
<div class="filter">
|
||||||
{#if $auth.groupsEnabled && $groups.length}
|
{#if $auth.groupsEnabled}
|
||||||
<AccessFilter on:change={accessFilterAction} />
|
<AccessFilter on:change={accessFilterAction} />
|
||||||
{/if}
|
{/if}
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
"outputPath": "build"
|
"outputPath": "build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "1.1.32-alpha.6",
|
"@budibase/backend-core": "1.2.41-alpha.5",
|
||||||
"axios": "0.21.2",
|
"axios": "0.21.2",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
"cli-progress": "3.11.2",
|
"cli-progress": "3.11.2",
|
||||||
|
|
|
@ -48,18 +48,19 @@
|
||||||
"@babel/helper-validator-identifier" "^7.16.7"
|
"@babel/helper-validator-identifier" "^7.16.7"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@budibase/backend-core@1.1.32-alpha.6":
|
"@budibase/backend-core@1.2.41-alpha.5":
|
||||||
version "1.1.32-alpha.6"
|
version "1.2.41-alpha.5"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.32-alpha.6.tgz#e9dc1a1989a2a6952f5ce002fcdfef66625f3de8"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.41-alpha.5.tgz#e03c9970f9eadcdfe9146ffe4d7f29174648675a"
|
||||||
integrity sha512-8oT6veeSmymuJfnu1jAkDAWD4fLj5W0KxNq6GlC+eMWWDZloDF4fMWDpuYTFBeinq1z1GeSFXc9Ak6u+1Z7LtQ==
|
integrity sha512-kB+S3pu4F9wNMwzdBSF4auZEAqQ05VlhEA/cjLyb54zjxrJmpGv761I6vAM4BptvjpSNCGtiv6HrpGaOILRDDQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/types" "1.1.32-alpha.6"
|
"@budibase/types" "1.2.41-alpha.5"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-sdk "2.1030.0"
|
aws-sdk "2.1030.0"
|
||||||
bcrypt "5.0.1"
|
bcrypt "5.0.1"
|
||||||
dotenv "16.0.1"
|
dotenv "16.0.1"
|
||||||
emitter-listener "1.1.2"
|
emitter-listener "1.1.2"
|
||||||
ioredis "4.28.0"
|
ioredis "4.28.0"
|
||||||
|
joi "17.6.0"
|
||||||
jsonwebtoken "8.5.1"
|
jsonwebtoken "8.5.1"
|
||||||
koa-passport "4.1.4"
|
koa-passport "4.1.4"
|
||||||
lodash "4.17.21"
|
lodash "4.17.21"
|
||||||
|
@ -81,10 +82,10 @@
|
||||||
uuid "8.3.2"
|
uuid "8.3.2"
|
||||||
zlib "1.0.5"
|
zlib "1.0.5"
|
||||||
|
|
||||||
"@budibase/types@1.1.32-alpha.6":
|
"@budibase/types@1.2.41-alpha.5":
|
||||||
version "1.1.32-alpha.6"
|
version "1.2.41-alpha.5"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.32-alpha.6.tgz#95d8d73c7ed6ebc22ff26a44365127a478e19409"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.41-alpha.5.tgz#0ade282c2e4ec3e4a1a4212403a1d0c3da80521b"
|
||||||
integrity sha512-AKKxrzVqGtcSzZZ2fP6i2Vgv6ICN9NEEE1dmzRk9AImZS+XKQ9VgVpdE+4gHgFK7L0gBYAsiaoEpCbbrI/+NoQ==
|
integrity sha512-Awya83t8bDeavc0XSglYVc4sStDheUKsAQWzTpgcRaB5l7NwhHQG5xlWsbFT8glolYY96ogLZJjLFTzIur3iDQ==
|
||||||
|
|
||||||
"@eslint/eslintrc@^0.4.3":
|
"@eslint/eslintrc@^0.4.3":
|
||||||
version "0.4.3"
|
version "0.4.3"
|
||||||
|
@ -101,6 +102,18 @@
|
||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
|
"@hapi/hoek@^9.0.0":
|
||||||
|
version "9.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
|
||||||
|
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
|
||||||
|
|
||||||
|
"@hapi/topo@^5.0.0":
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
|
||||||
|
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek" "^9.0.0"
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.5.0":
|
"@humanwhocodes/config-array@^0.5.0":
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz"
|
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz"
|
||||||
|
@ -151,6 +164,23 @@
|
||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
|
"@sideway/address@^4.1.3":
|
||||||
|
version "4.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
|
||||||
|
integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek" "^9.0.0"
|
||||||
|
|
||||||
|
"@sideway/formula@^3.0.0":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c"
|
||||||
|
integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==
|
||||||
|
|
||||||
|
"@sideway/pinpoint@^2.0.0":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
|
||||||
|
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
||||||
|
|
||||||
"@techpass/passport-openidconnect@0.3.2":
|
"@techpass/passport-openidconnect@0.3.2":
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.2.tgz#f8fd5d97256286665dbf26dac92431f977ab1e63"
|
resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.2.tgz#f8fd5d97256286665dbf26dac92431f977ab1e63"
|
||||||
|
@ -1626,6 +1656,17 @@ jmespath@0.15.0:
|
||||||
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
|
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
|
||||||
integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==
|
integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==
|
||||||
|
|
||||||
|
joi@17.6.0:
|
||||||
|
version "17.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2"
|
||||||
|
integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek" "^9.0.0"
|
||||||
|
"@hapi/topo" "^5.0.0"
|
||||||
|
"@sideway/address" "^4.1.3"
|
||||||
|
"@sideway/formula" "^3.0.0"
|
||||||
|
"@sideway/pinpoint" "^2.0.0"
|
||||||
|
|
||||||
join-component@^1.1.0:
|
join-component@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz"
|
||||||
|
|
|
@ -237,6 +237,11 @@
|
||||||
"showInBar": true,
|
"showInBar": true,
|
||||||
"barIcon": "ModernGridView",
|
"barIcon": "ModernGridView",
|
||||||
"barTitle": "Wrap"
|
"barTitle": "Wrap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"label": "On Click",
|
||||||
|
"key": "onClick"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "1.2.39-alpha.6",
|
"@budibase/bbui": "1.2.44-alpha.1",
|
||||||
"@budibase/frontend-core": "1.2.39-alpha.6",
|
"@budibase/frontend-core": "1.2.44-alpha.1",
|
||||||
"@budibase/string-templates": "1.2.39-alpha.6",
|
"@budibase/string-templates": "1.2.44-alpha.1",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.3",
|
||||||
"@spectrum-css/card": "^3.0.3",
|
"@spectrum-css/card": "^3.0.3",
|
||||||
"@spectrum-css/divider": "^1.0.3",
|
"@spectrum-css/divider": "^1.0.3",
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
id="spectrum-root"
|
id="spectrum-root"
|
||||||
lang="en"
|
lang="en"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
class="spectrum spectrum--medium spectrum--darkest {$themeStore.theme}"
|
class="spectrum spectrum--medium {$themeStore.baseTheme} {$themeStore.theme}"
|
||||||
>
|
>
|
||||||
<DeviceBindingsProvider>
|
<DeviceBindingsProvider>
|
||||||
<UserBindingsProvider>
|
<UserBindingsProvider>
|
||||||
|
|
|
@ -17,10 +17,16 @@
|
||||||
--spectrum-semantic-cta-color-background-default: var(--primaryColor);
|
--spectrum-semantic-cta-color-background-default: var(--primaryColor);
|
||||||
--spectrum-semantic-cta-color-background-hover: var(--primaryColorHover);
|
--spectrum-semantic-cta-color-background-hover: var(--primaryColorHover);
|
||||||
--spectrum-semantic-cta-color-background-down: var(--primaryColorHover);
|
--spectrum-semantic-cta-color-background-down: var(--primaryColorHover);
|
||||||
--spectrum-button-primary-s-border-radius: var(--buttonBorderRadius);
|
--spectrum-button-primary-s-border-radius: calc(
|
||||||
|
var(--buttonBorderRadius) * 0.9
|
||||||
|
);
|
||||||
--spectrum-button-primary-m-border-radius: var(--buttonBorderRadius);
|
--spectrum-button-primary-m-border-radius: var(--buttonBorderRadius);
|
||||||
--spectrum-button-primary-l-border-radius: var(--buttonBorderRadius);
|
--spectrum-button-primary-l-border-radius: calc(
|
||||||
--spectrum-button-primary-xl-border-radius: var(--buttonBorderRadius);
|
var(--buttonBorderRadius) * 1.25
|
||||||
|
);
|
||||||
|
--spectrum-button-primary-xl-border-radius: calc(
|
||||||
|
var(--buttonBorderRadius) * 1.5
|
||||||
|
);
|
||||||
|
|
||||||
/* Loading spinners */
|
/* Loading spinners */
|
||||||
--spectrum-progresscircle-medium-track-fill-color: var(--primaryColor);
|
--spectrum-progresscircle-medium-track-fill-color: var(--primaryColor);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
export let size
|
export let size
|
||||||
export let gap
|
export let gap
|
||||||
export let wrap
|
export let wrap
|
||||||
|
export let onClick
|
||||||
|
|
||||||
$: directionClass = direction ? `valid-container direction-${direction}` : ""
|
$: directionClass = direction ? `valid-container direction-${direction}` : ""
|
||||||
$: hAlignClass = hAlign ? `hAlign-${hAlign}` : ""
|
$: hAlignClass = hAlign ? `hAlign-${hAlign}` : ""
|
||||||
|
@ -25,7 +26,13 @@
|
||||||
].join(" ")
|
].join(" ")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={classNames} use:styleable={$component.styles} class:wrap>
|
<div
|
||||||
|
class={classNames}
|
||||||
|
class:clickable={!!onClick}
|
||||||
|
use:styleable={$component.styles}
|
||||||
|
class:wrap
|
||||||
|
on:click={onClick}
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -104,4 +111,10 @@
|
||||||
.wrap {
|
.wrap {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.clickable :global(*) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -47,6 +47,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteAttachments = async fileList => {
|
||||||
|
try {
|
||||||
|
return await API.deleteAttachments({
|
||||||
|
keys: fileList,
|
||||||
|
tableId: formContext?.dataSource?.tableId,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleChange = e => {
|
const handleChange = e => {
|
||||||
fieldApi.setValue(e.detail)
|
fieldApi.setValue(e.detail)
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
|
@ -72,6 +83,7 @@
|
||||||
error={fieldState.error}
|
error={fieldState.error}
|
||||||
on:change={handleChange}
|
on:change={handleChange}
|
||||||
{processFiles}
|
{processFiles}
|
||||||
|
{deleteAttachments}
|
||||||
{handleFileTooLarge}
|
{handleFileTooLarge}
|
||||||
{handleTooManyFiles}
|
{handleTooManyFiles}
|
||||||
{maximum}
|
{maximum}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import "@spectrum-css/vars/dist/spectrum-darkest.css"
|
||||||
import "@spectrum-css/vars/dist/spectrum-dark.css"
|
import "@spectrum-css/vars/dist/spectrum-dark.css"
|
||||||
import "@spectrum-css/vars/dist/spectrum-light.css"
|
import "@spectrum-css/vars/dist/spectrum-light.css"
|
||||||
import "@spectrum-css/vars/dist/spectrum-lightest.css"
|
import "@spectrum-css/vars/dist/spectrum-lightest.css"
|
||||||
|
import "@budibase/frontend-core/src/themes/nord.css"
|
||||||
|
import "@budibase/frontend-core/src/themes/midnight.css"
|
||||||
import "@spectrum-css/page/dist/index-vars.css"
|
import "@spectrum-css/page/dist/index-vars.css"
|
||||||
|
|
||||||
// Non user-facing components
|
// Non user-facing components
|
||||||
|
|
|
@ -16,20 +16,20 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
const onKeyDown = e => {
|
const onKeyDown = e => {
|
||||||
if (e.key === "Delete" || e.key === "Backspace") {
|
|
||||||
deleteSelectedComponent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteSelectedComponent = () => {
|
|
||||||
const state = get(builderStore)
|
const state = get(builderStore)
|
||||||
if (!state.inBuilder || !state.selectedComponentId || state.editMode) {
|
if (!state.inBuilder || state.editMode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const activeTag = document.activeElement?.tagName.toLowerCase()
|
const activeTag = document.activeElement?.tagName.toLowerCase()
|
||||||
if (["input", "textarea"].indexOf(activeTag) !== -1) {
|
if (["input", "textarea"].indexOf(activeTag) !== -1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
builderStore.actions.deleteComponent(state.selectedComponentId)
|
|
||||||
|
// Need to manually block certain keys from propagating to the browser
|
||||||
|
if (e.ctrlKey && e.key === "d") {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
builderStore.actions.keyDown(e.key, e.ctrlKey)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -40,8 +40,8 @@ const createBuilderStore = () => {
|
||||||
updateProp: (prop, value) => {
|
updateProp: (prop, value) => {
|
||||||
dispatchEvent("update-prop", { prop, value })
|
dispatchEvent("update-prop", { prop, value })
|
||||||
},
|
},
|
||||||
deleteComponent: id => {
|
keyDown: (key, ctrlKey) => {
|
||||||
dispatchEvent("delete-component", { id })
|
dispatchEvent("key-down", { key, ctrlKey })
|
||||||
},
|
},
|
||||||
duplicateComponent: id => {
|
duplicateComponent: id => {
|
||||||
dispatchEvent("duplicate-component", { id })
|
dispatchEvent("duplicate-component", { id })
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { derived } from "svelte/store"
|
import { derived } from "svelte/store"
|
||||||
import { appStore } from "./app"
|
import { appStore } from "./app"
|
||||||
import { builderStore } from "./builder"
|
import { builderStore } from "./builder"
|
||||||
|
import { Constants } from "@budibase/frontend-core"
|
||||||
|
|
||||||
// This is the good old acorn bug where having the word "g l o b a l" makes it
|
// This is the good old acorn bug where having the word "g l o b a l" makes it
|
||||||
// think that this is not ES6 compatible and starts throwing errors when using
|
// think that this is not ES6 compatible and starts throwing errors when using
|
||||||
|
@ -28,6 +29,13 @@ const createThemeStore = () => {
|
||||||
// Ensure theme is set
|
// Ensure theme is set
|
||||||
theme = theme || defaultTheme
|
theme = theme || defaultTheme
|
||||||
|
|
||||||
|
// Get base theme
|
||||||
|
let base =
|
||||||
|
Constants.Themes.find(x => `spectrum--${x.class}` === theme)?.base || ""
|
||||||
|
if (base) {
|
||||||
|
base = `spectrum--${base}`
|
||||||
|
}
|
||||||
|
|
||||||
// Delete and nullish keys from the custom theme
|
// Delete and nullish keys from the custom theme
|
||||||
if (customTheme) {
|
if (customTheme) {
|
||||||
Object.entries(customTheme).forEach(([key, value]) => {
|
Object.entries(customTheme).forEach(([key, value]) => {
|
||||||
|
@ -51,6 +59,7 @@ const createThemeStore = () => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme,
|
theme,
|
||||||
|
baseTheme: base,
|
||||||
customTheme,
|
customTheme,
|
||||||
customThemeCss,
|
customThemeCss,
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,8 +334,8 @@ const confirmTextMap = {
|
||||||
*/
|
*/
|
||||||
export const enrichButtonActions = (actions, context) => {
|
export const enrichButtonActions = (actions, context) => {
|
||||||
// Prevent button actions in the builder preview
|
// Prevent button actions in the builder preview
|
||||||
if (!actions || get(builderStore).inBuilder) {
|
if (!actions?.length || get(builderStore).inBuilder) {
|
||||||
return () => {}
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a function then it has already been enriched
|
// If this is a function then it has already been enriched
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "1.2.39-alpha.6",
|
"@budibase/bbui": "1.2.44-alpha.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,5 +61,32 @@ export const buildAttachmentEndpoints = API => {
|
||||||
})
|
})
|
||||||
return { publicUrl }
|
return { publicUrl }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes attachments from the bucket.
|
||||||
|
* @param keys the attachments to delete
|
||||||
|
* @param tableId the associated table ID
|
||||||
|
*/
|
||||||
|
deleteAttachments: async ({ keys, tableId }) => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/attachments/${tableId}/delete`,
|
||||||
|
body: {
|
||||||
|
keys,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes attachments from the builder bucket.
|
||||||
|
* @param keys the attachments to delete
|
||||||
|
*/
|
||||||
|
deleteBuilderAttachments: async keys => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/attachments/delete`,
|
||||||
|
body: {
|
||||||
|
keys,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,7 @@
|
||||||
--spectrum-global-color-gray-700: hsl(var(--hue), var(--sat), 70%);
|
--spectrum-global-color-gray-700: hsl(var(--hue), var(--sat), 70%);
|
||||||
--spectrum-global-color-gray-800: hsl(var(--hue), var(--sat), 80%);
|
--spectrum-global-color-gray-800: hsl(var(--hue), var(--sat), 80%);
|
||||||
--spectrum-global-color-gray-900: hsl(var(--hue), var(--sat), 95%);
|
--spectrum-global-color-gray-900: hsl(var(--hue), var(--sat), 95%);
|
||||||
|
|
||||||
|
--modal-background: var(--spectrum-global-color-gray-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,4 +43,7 @@
|
||||||
|
|
||||||
--spectrum-alias-highlight-hover: rgba(169, 177, 193, 0.1);
|
--spectrum-alias-highlight-hover: rgba(169, 177, 193, 0.1);
|
||||||
--spectrum-alias-highlight-active: rgba(169, 177, 193, 0.1);
|
--spectrum-alias-highlight-active: rgba(169, 177, 193, 0.1);
|
||||||
|
--spectrum-alias-background-color-hover-overlay: rgba(169, 177, 193, 0.1);
|
||||||
|
|
||||||
|
--modal-background: var(--spectrum-global-color-gray-50);
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ export const buildLuceneQuery = filter => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === "number" && !Array.isArray(value)) {
|
if (type === "number" && typeof value === "string") {
|
||||||
if (operator === "oneOf") {
|
if (operator === "oneOf") {
|
||||||
value = value.split(",").map(item => parseFloat(item))
|
value = value.split(",").map(item => parseFloat(item))
|
||||||
} else if (!isHbs) {
|
} else if (!isHbs) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -77,11 +77,11 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.0.3",
|
"@apidevtools/swagger-parser": "10.0.3",
|
||||||
"@budibase/backend-core": "1.2.39-alpha.6",
|
"@budibase/backend-core": "1.2.44-alpha.1",
|
||||||
"@budibase/client": "1.2.39-alpha.6",
|
"@budibase/client": "1.2.44-alpha.1",
|
||||||
"@budibase/pro": "1.2.39-alpha.6",
|
"@budibase/pro": "1.2.44-alpha.1",
|
||||||
"@budibase/string-templates": "1.2.39-alpha.6",
|
"@budibase/string-templates": "1.2.44-alpha.1",
|
||||||
"@budibase/types": "1.2.39-alpha.6",
|
"@budibase/types": "1.2.44-alpha.1",
|
||||||
"@bull-board/api": "3.7.0",
|
"@bull-board/api": "3.7.0",
|
||||||
"@bull-board/koa": "3.9.4",
|
"@bull-board/koa": "3.9.4",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
"arangojs": "7.2.0",
|
"arangojs": "7.2.0",
|
||||||
"aws-sdk": "2.1030.0",
|
"aws-sdk": "2.1030.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bull": "3.29.3",
|
"bull": "4.8.5",
|
||||||
"chmodr": "1.2.0",
|
"chmodr": "1.2.0",
|
||||||
"csvtojson": "2.0.10",
|
"csvtojson": "2.0.10",
|
||||||
"curlconverter": "3.21.0",
|
"curlconverter": "3.21.0",
|
||||||
|
|
|
@ -12,7 +12,7 @@ const {
|
||||||
} = require("../../../utilities/fileSystem")
|
} = require("../../../utilities/fileSystem")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
const { clientLibraryPath } = require("../../../utilities")
|
const { clientLibraryPath } = require("../../../utilities")
|
||||||
const { upload } = require("../../../utilities/fileSystem")
|
const { upload, deleteFiles } = require("../../../utilities/fileSystem")
|
||||||
const { attachmentsRelativeURL } = require("../../../utilities")
|
const { attachmentsRelativeURL } = require("../../../utilities")
|
||||||
const { DocumentType } = require("../../../db/utils")
|
const { DocumentType } = require("../../../db/utils")
|
||||||
const { getAppDB, getAppId } = require("@budibase/backend-core/context")
|
const { getAppDB, getAppId } = require("@budibase/backend-core/context")
|
||||||
|
@ -97,6 +97,10 @@ export const uploadFile = async function (ctx: any) {
|
||||||
ctx.body = await Promise.all(uploads)
|
ctx.body = await Promise.all(uploads)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteObjects = async function (ctx: any) {
|
||||||
|
ctx.body = await deleteFiles(ObjectStoreBuckets.APPS, ctx.request.body.keys)
|
||||||
|
}
|
||||||
|
|
||||||
export const serveApp = async function (ctx: any) {
|
export const serveApp = async function (ctx: any) {
|
||||||
const db = getAppDB({ skip_setup: true })
|
const db = getAppDB({ skip_setup: true })
|
||||||
const appInfo = await db.get(DocumentType.APP_METADATA)
|
const appInfo = await db.get(DocumentType.APP_METADATA)
|
||||||
|
@ -124,6 +128,22 @@ export const serveApp = async function (ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const serveBuilderPreview = async function (ctx: any) {
|
||||||
|
const db = getAppDB({ skip_setup: true })
|
||||||
|
const appInfo = await db.get(DocumentType.APP_METADATA)
|
||||||
|
|
||||||
|
if (!env.isJest()) {
|
||||||
|
let appId = getAppId()
|
||||||
|
const previewHbs = loadHandlebarsFile(`${__dirname}/templates/preview.hbs`)
|
||||||
|
ctx.body = await processString(previewHbs, {
|
||||||
|
clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// just return the app info for jest to assert on
|
||||||
|
ctx.body = { ...appInfo, builderPreview: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const serveClientLibrary = async function (ctx: any) {
|
export const serveClientLibrary = async function (ctx: any) {
|
||||||
return send(ctx, "budibase-client.js", {
|
return send(ctx, "budibase-client.js", {
|
||||||
root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
|
root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
|
||||||
|
|
103
packages/server/src/api/controllers/static/templates/preview.hbs
Normal file
103
packages/server/src/api/controllers/static/templates/preview.hbs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Budibase Builder Preview</title>
|
||||||
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src='{{ clientLibPath }}'></script>
|
||||||
|
<script>
|
||||||
|
function receiveMessage(event) {
|
||||||
|
if (!event.data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse received message
|
||||||
|
// If parsing fails, just ignore and wait for the next message
|
||||||
|
let parsed
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(event.data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Client received invalid JSON")
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
if (!parsed || !parsed.isBudibaseEvent) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract data from message
|
||||||
|
const {
|
||||||
|
selectedComponentId,
|
||||||
|
layout,
|
||||||
|
screen,
|
||||||
|
appId,
|
||||||
|
theme,
|
||||||
|
customTheme,
|
||||||
|
previewDevice,
|
||||||
|
navigation,
|
||||||
|
hiddenComponentIds
|
||||||
|
} = parsed
|
||||||
|
|
||||||
|
// Set some flags so the app knows we're in the builder
|
||||||
|
window["##BUDIBASE_IN_BUILDER##"] = true
|
||||||
|
window["##BUDIBASE_APP_ID##"] = appId
|
||||||
|
window["##BUDIBASE_PREVIEW_LAYOUT##"] = layout
|
||||||
|
window["##BUDIBASE_PREVIEW_SCREEN##"] = screen
|
||||||
|
window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId
|
||||||
|
window["##BUDIBASE_PREVIEW_ID##"] = Math.random()
|
||||||
|
window["##BUDIBASE_PREVIEW_THEME##"] = theme
|
||||||
|
window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
|
||||||
|
window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
|
||||||
|
window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
|
||||||
|
window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
|
||||||
|
|
||||||
|
// Initialise app
|
||||||
|
try {
|
||||||
|
if (window.loadBudibase) {
|
||||||
|
window.loadBudibase()
|
||||||
|
document.documentElement.classList.add("loaded")
|
||||||
|
} else {
|
||||||
|
throw "The client library couldn't be loaded"
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
window.parent.postMessage({ type: "error", error })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("message", receiveMessage)
|
||||||
|
window.parent.postMessage({ type: "ready" })
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
|
@ -20,8 +20,17 @@ exports.getView = async viewName => {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewDoc = await db.get(generateMemoryViewID(viewName))
|
try {
|
||||||
return viewDoc.view
|
const viewDoc = await db.get(generateMemoryViewID(viewName))
|
||||||
|
return viewDoc.view
|
||||||
|
} catch (err) {
|
||||||
|
// Return null when PouchDB doesn't found the view
|
||||||
|
if (err.status === 404) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,11 @@ router
|
||||||
// TODO: for now this builder endpoint is not authorized/secured, will need to be
|
// TODO: for now this builder endpoint is not authorized/secured, will need to be
|
||||||
.get("/builder/:file*", controller.serveBuilder)
|
.get("/builder/:file*", controller.serveBuilder)
|
||||||
.post("/api/attachments/process", authorized(BUILDER), controller.uploadFile)
|
.post("/api/attachments/process", authorized(BUILDER), controller.uploadFile)
|
||||||
|
.post(
|
||||||
|
"/api/attachments/delete",
|
||||||
|
authorized(BUILDER),
|
||||||
|
controller.deleteObjects
|
||||||
|
)
|
||||||
.post("/api/beta/:feature", controller.toggleBetaUiFeature)
|
.post("/api/beta/:feature", controller.toggleBetaUiFeature)
|
||||||
.post(
|
.post(
|
||||||
"/api/attachments/:tableId/upload",
|
"/api/attachments/:tableId/upload",
|
||||||
|
@ -45,6 +50,13 @@ router
|
||||||
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||||
controller.uploadFile
|
controller.uploadFile
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
"/api/attachments/:tableId/delete",
|
||||||
|
paramResource("tableId"),
|
||||||
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||||
|
controller.deleteObjects
|
||||||
|
)
|
||||||
|
.get("/preview", authorized(BUILDER), controller.serveBuilderPreview)
|
||||||
.get("/:appId/:path*", controller.serveApp)
|
.get("/:appId/:path*", controller.serveApp)
|
||||||
.get("/app/:appUrl/:path*", controller.serveApp)
|
.get("/app/:appUrl/:path*", controller.serveApp)
|
||||||
.post(
|
.post(
|
||||||
|
|
|
@ -40,7 +40,6 @@ describe("/static", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("/app", () => {
|
describe("/app", () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
@ -60,7 +59,7 @@ describe("/static", () => {
|
||||||
it("should serve the app by url", async () => {
|
it("should serve the app by url", async () => {
|
||||||
const headers = config.defaultHeaders()
|
const headers = config.defaultHeaders()
|
||||||
delete headers[constants.Headers.APP_ID]
|
delete headers[constants.Headers.APP_ID]
|
||||||
|
|
||||||
const res = await request
|
const res = await request
|
||||||
.get(`/app${config.prodApp.url}`)
|
.get(`/app${config.prodApp.url}`)
|
||||||
.set(headers)
|
.set(headers)
|
||||||
|
@ -82,7 +81,7 @@ describe("/static", () => {
|
||||||
describe("/attachments", () => {
|
describe("/attachments", () => {
|
||||||
describe("generateSignedUrls", () => {
|
describe("generateSignedUrls", () => {
|
||||||
let datasource
|
let datasource
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
datasource = await config.createDatasource({
|
datasource = await config.createDatasource({
|
||||||
datasource: {
|
datasource: {
|
||||||
|
@ -93,7 +92,7 @@ describe("/static", () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should be able to generate a signed upload URL", async () => {
|
it("should be able to generate a signed upload URL", async () => {
|
||||||
const bucket = "foo"
|
const bucket = "foo"
|
||||||
const key = "bar"
|
const key = "bar"
|
||||||
|
@ -108,7 +107,7 @@ describe("/static", () => {
|
||||||
`https://${bucket}.s3.eu-west-1.amazonaws.com/${key}`
|
`https://${bucket}.s3.eu-west-1.amazonaws.com/${key}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should handle an invalid datasource ID", async () => {
|
it("should handle an invalid datasource ID", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
.post(`/api/attachments/foo/url`)
|
.post(`/api/attachments/foo/url`)
|
||||||
|
@ -123,7 +122,7 @@ describe("/static", () => {
|
||||||
"The specified datasource could not be found"
|
"The specified datasource could not be found"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should require a bucket parameter", async () => {
|
it("should require a bucket parameter", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
.post(`/api/attachments/${datasource._id}/url`)
|
.post(`/api/attachments/${datasource._id}/url`)
|
||||||
|
@ -136,7 +135,7 @@ describe("/static", () => {
|
||||||
.expect(400)
|
.expect(400)
|
||||||
expect(res.body.message).toEqual("bucket and key values are required")
|
expect(res.body.message).toEqual("bucket and key values are required")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should require a key parameter", async () => {
|
it("should require a key parameter", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
.post(`/api/attachments/${datasource._id}/url`)
|
.post(`/api/attachments/${datasource._id}/url`)
|
||||||
|
@ -151,4 +150,17 @@ describe("/static", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("/preview", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should serve the builder preview", async () => {
|
||||||
|
const headers = config.defaultHeaders()
|
||||||
|
const res = await request.get(`/preview`).set(headers).expect(200)
|
||||||
|
|
||||||
|
expect(res.body.appId).toBe(config.appId)
|
||||||
|
expect(res.body.builderPreview).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,6 +15,7 @@ const {
|
||||||
streamUpload,
|
streamUpload,
|
||||||
deleteFolder,
|
deleteFolder,
|
||||||
downloadTarball,
|
downloadTarball,
|
||||||
|
deleteFiles,
|
||||||
} = require("./utilities")
|
} = require("./utilities")
|
||||||
const { updateClientLibrary } = require("./clientLibrary")
|
const { updateClientLibrary } = require("./clientLibrary")
|
||||||
const env = require("../../environment")
|
const env = require("../../environment")
|
||||||
|
@ -327,5 +328,6 @@ exports.cleanup = appIds => {
|
||||||
exports.upload = upload
|
exports.upload = upload
|
||||||
exports.retrieve = retrieve
|
exports.retrieve = retrieve
|
||||||
exports.retrieveToTmp = retrieveToTmp
|
exports.retrieveToTmp = retrieveToTmp
|
||||||
|
exports.deleteFiles = deleteFiles
|
||||||
exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH
|
exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH
|
||||||
exports.NODE_MODULES_PATH = NODE_MODULES_PATH
|
exports.NODE_MODULES_PATH = NODE_MODULES_PATH
|
||||||
|
|
|
@ -1094,12 +1094,12 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.2.39-alpha.6":
|
"@budibase/backend-core@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.6.tgz#ebfddd4fa74fff043a60df7cba335b5fcdb84d51"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.44-alpha.1.tgz#255c8550302ea0d4b10b231519e12021d008ad33"
|
||||||
integrity sha512-1kz9K3MSe5E4d/dSm6jD4BMIX/SSW58d8U787N+1BfzvSkIEd32j7HFs5ij0w9sromvK9FEjpFBfZKqSDRp+5g==
|
integrity sha512-9ceN00ioBD5iUc2Wbcs9Pyvh5gaSfkg1v4Qn9QdRwAG36eo3XVK8kiYWF0q0hkzgcTViJw6xq/1jqMa2InKv6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/types" "1.2.39-alpha.6"
|
"@budibase/types" "1.2.44-alpha.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-sdk "2.1030.0"
|
aws-sdk "2.1030.0"
|
||||||
bcrypt "5.0.1"
|
bcrypt "5.0.1"
|
||||||
|
@ -1178,13 +1178,13 @@
|
||||||
svelte-flatpickr "^3.2.3"
|
svelte-flatpickr "^3.2.3"
|
||||||
svelte-portal "^1.0.0"
|
svelte-portal "^1.0.0"
|
||||||
|
|
||||||
"@budibase/pro@1.2.39-alpha.6":
|
"@budibase/pro@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.6.tgz#94a19338c6f59755f34b4bf181ba15ac5eba5404"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.44-alpha.1.tgz#d9e919b1df96f3d3d5cf37753721d41348279f59"
|
||||||
integrity sha512-l5IcibGGpd9VCIzY5vZU6rYeJa+1AYNCsWWKMnm7ZeZQgiD62Hyus53pv9GvT4pwpUF60pxybAoTWhbbityCPQ==
|
integrity sha512-KaclS4qv4+hWenvuVwF2HxcPWkrDyR7IVyLKLMVUqCnaMoXMvEOe9KuQ+lXLbsLIBsCsCFkzE/WHsdmoaGqa0g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.2.39-alpha.6"
|
"@budibase/backend-core" "1.2.44-alpha.1"
|
||||||
"@budibase/types" "1.2.39-alpha.6"
|
"@budibase/types" "1.2.44-alpha.1"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
@ -1207,10 +1207,10 @@
|
||||||
svelte-apexcharts "^1.0.2"
|
svelte-apexcharts "^1.0.2"
|
||||||
svelte-flatpickr "^3.1.0"
|
svelte-flatpickr "^3.1.0"
|
||||||
|
|
||||||
"@budibase/types@1.2.39-alpha.6":
|
"@budibase/types@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.6.tgz#5c6dc1a130913fb1c7ac6999fc6e03d970d0142f"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.44-alpha.1.tgz#6150d4494326438b46dd7354e5dd0fc7fdbfcc49"
|
||||||
integrity sha512-0FHmwsfvAL80PGQM0OSJ6n9CDCtQQrbX8PRdcWOSIhRNlJXNcTsPcBsPbQpZPbgT57GHX/86Fo1rljiMWDwNpw==
|
integrity sha512-1eLGH5ym4oYbuRZRkD0slNqHlZ1EV0JHLkmoA47i7L/u8E8QRIyDIHyeZKC8ben33oQS4NX3IebD7zZ2JFhgcA==
|
||||||
|
|
||||||
"@bull-board/api@3.7.0":
|
"@bull-board/api@3.7.0":
|
||||||
version "3.7.0"
|
version "3.7.0"
|
||||||
|
@ -2026,6 +2026,36 @@
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
tar "^6.1.11"
|
tar "^6.1.11"
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-arm64@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.1.2.tgz#9571b87be3a3f2c46de05585470bc4f3af2f6f00"
|
||||||
|
integrity sha512-TyVLn3S/+ikMDsh0gbKv2YydKClN8HaJDDpONlaZR+LVJmsxLFUgA+O7zu59h9+f9gX1aj/ahw9wqa6rosmrYQ==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-x64@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.1.2.tgz#bfbc6936ede2955218f5621a675679a5fe8e6f4c"
|
||||||
|
integrity sha512-YPXtcVkhmVNoMGlqp81ZHW4dMxK09msWgnxtsDpSiZwTzUBG2N+No2bsr7WMtBKCVJMSD6mbAl7YhKUqkp/Few==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm64@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.1.2.tgz#22555e28382af2922e7450634c8a2f240bb9eb82"
|
||||||
|
integrity sha512-vHZ2JiOWF2+DN9lzltGbhtQNzDo8fKFGrf37UJrgqxU0yvtERrzUugnfnX1wmVfFhSsF8OxrfqiNOUc5hko1Zg==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.1.2.tgz#ffb6ae1beea7ac572b6be6bf2a8e8162ebdd8be7"
|
||||||
|
integrity sha512-42R4MAFeIeNn+L98qwxAt360bwzX2Kf0ZQkBBucJ2Ircza3asoY4CDbgiu9VWklq8gWJVSJSJBwDI+c/THiWkA==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-x64@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.1.2.tgz#7caf62eebbfb1345de40f75e89666b3d4194755f"
|
||||||
|
integrity sha512-RjRoRxg7Q3kPAdUSC5EUUPlwfMkIVhmaRTIe+cqHbKrGZ4M6TyCA/b5qMaukQ/1CHWrqYY2FbKOAU8Hg0pQFzg==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-win32-x64@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.1.2.tgz#f2d8b9ddd8d191205ed26ce54aba3dfc5ae3e7c9"
|
||||||
|
integrity sha512-rIZVR48zA8hGkHIK7ED6+ZiXsjRCcAVBJbm8o89OKAMTmEAQ2QvoOxoiu3w2isAaWwzgtQIOFIqHwvZDyLKCvw==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.5":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||||
|
@ -4246,20 +4276,19 @@ buffer@^5.1.0, buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0:
|
||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.1.13"
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
bull@3.29.3:
|
bull@4.8.5:
|
||||||
version "3.29.3"
|
version "4.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/bull/-/bull-3.29.3.tgz#5b0059b172685b0d6f011d56214e1898ff3a7a0b"
|
resolved "https://registry.yarnpkg.com/bull/-/bull-4.8.5.tgz#eebafddc3249d6d5e8ced1c42b8bfa8efcc274aa"
|
||||||
integrity sha512-MOqV1dKLy1YQgP9m3lFolyMxaU+1+o4afzYYf0H4wNM+x/S0I1QPQfkgGlLiH00EyFrvSmeubeCYFP47rTfpjg==
|
integrity sha512-2Z630e4f6VsLJnWMAtfEHwIqJYmND4W3dcG48RIbXeWpvb4UnYtpe/zxEdslJu0PKrltB4IkFj5YtBsdeQRn8w==
|
||||||
dependencies:
|
dependencies:
|
||||||
cron-parser "^2.13.0"
|
cron-parser "^4.2.1"
|
||||||
debuglog "^1.0.0"
|
debuglog "^1.0.0"
|
||||||
get-port "^5.1.1"
|
get-port "^5.1.1"
|
||||||
ioredis "^4.27.0"
|
ioredis "^4.28.5"
|
||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
|
msgpackr "^1.5.2"
|
||||||
p-timeout "^3.2.0"
|
p-timeout "^3.2.0"
|
||||||
promise.prototype.finally "^3.1.2"
|
|
||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
util.promisify "^1.0.1"
|
|
||||||
uuid "^8.3.0"
|
uuid "^8.3.0"
|
||||||
|
|
||||||
bytes@3.1.2, bytes@^3.0.0:
|
bytes@3.1.2, bytes@^3.0.0:
|
||||||
|
@ -4826,13 +4855,12 @@ create-require@^1.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||||
|
|
||||||
cron-parser@^2.13.0:
|
cron-parser@^4.2.1:
|
||||||
version "2.18.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.18.0.tgz#de1bb0ad528c815548371993f81a54e5a089edcf"
|
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.6.0.tgz#404c3fdbff10ae80eef6b709555d577ef2fd2e0d"
|
||||||
integrity sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==
|
integrity sha512-guZNLMGUgg6z4+eGhmHGw7ft+v6OQeuHzd1gcLxCo9Yg/qoxmG3nindp2/uwGCLizEisf2H0ptqeVXeoCpP6FA==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-nan "^1.3.0"
|
luxon "^3.0.1"
|
||||||
moment-timezone "^0.5.31"
|
|
||||||
|
|
||||||
cross-spawn@^4.0.0:
|
cross-spawn@^4.0.0:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
|
@ -5483,7 +5511,7 @@ error-inject@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
|
resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
|
||||||
integrity sha512-JM8N6PytDbmIYm1IhPWlo8vr3NtfjhDY/1MhD/a5b/aad/USE8a0+NsqE9d5n+GVGmuNkPQWm4bFQWv18d8tMg==
|
integrity sha512-JM8N6PytDbmIYm1IhPWlo8vr3NtfjhDY/1MhD/a5b/aad/USE8a0+NsqE9d5n+GVGmuNkPQWm4bFQWv18d8tMg==
|
||||||
|
|
||||||
es-abstract@^1.17.5, es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.0, es-abstract@^1.20.1:
|
es-abstract@^1.17.5, es-abstract@^1.19.0, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.0, es-abstract@^1.20.1:
|
||||||
version "1.20.1"
|
version "1.20.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
||||||
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
|
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
|
||||||
|
@ -7397,7 +7425,7 @@ ioredis@4.28.0:
|
||||||
redis-parser "^3.0.0"
|
redis-parser "^3.0.0"
|
||||||
standard-as-callback "^2.1.0"
|
standard-as-callback "^2.1.0"
|
||||||
|
|
||||||
ioredis@^4.27.0:
|
ioredis@^4.28.5:
|
||||||
version "4.28.5"
|
version "4.28.5"
|
||||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f"
|
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f"
|
||||||
integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==
|
integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==
|
||||||
|
@ -7605,14 +7633,6 @@ is-installed-globally@^0.4.0:
|
||||||
global-dirs "^3.0.0"
|
global-dirs "^3.0.0"
|
||||||
is-path-inside "^3.0.2"
|
is-path-inside "^3.0.2"
|
||||||
|
|
||||||
is-nan@^1.3.0:
|
|
||||||
version "1.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
|
|
||||||
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.0"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
|
|
||||||
is-natural-number@^4.0.1:
|
is-natural-number@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
|
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
|
||||||
|
@ -9653,6 +9673,11 @@ ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5"
|
resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5"
|
||||||
integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==
|
integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==
|
||||||
|
|
||||||
|
luxon@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.0.1.tgz#6901111d10ad06fd267ad4e4128a84bef8a77299"
|
||||||
|
integrity sha512-hF3kv0e5gwHQZKz4wtm4c+inDtyc7elkanAsBq+fundaCdUBNJB1dHEGUZIM6SfSBUlbVFduPwEtNjFK8wLtcw==
|
||||||
|
|
||||||
make-dir@^1.0.0:
|
make-dir@^1.0.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
||||||
|
@ -9935,7 +9960,7 @@ mock-require@^3.0.3:
|
||||||
get-caller-file "^1.0.2"
|
get-caller-file "^1.0.2"
|
||||||
normalize-path "^2.1.1"
|
normalize-path "^2.1.1"
|
||||||
|
|
||||||
moment-timezone@^0.5.15, moment-timezone@^0.5.31:
|
moment-timezone@^0.5.15:
|
||||||
version "0.5.34"
|
version "0.5.34"
|
||||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
||||||
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
||||||
|
@ -9985,6 +10010,27 @@ ms@^2.1.1, ms@^2.1.3:
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
|
msgpackr-extract@^2.0.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.1.2.tgz#56272030f3e163e1b51964ef8b1cd5e7240c03ed"
|
||||||
|
integrity sha512-cmrmERQFb19NX2JABOGtrKdHMyI6RUyceaPBQ2iRz9GnDkjBWFjNJC0jyyoOfZl2U/LZE3tQCCQc4dlRyA8mcA==
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build-optional-packages "5.0.3"
|
||||||
|
optionalDependencies:
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.1.2"
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-x64" "2.1.2"
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm" "2.1.2"
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm64" "2.1.2"
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-x64" "2.1.2"
|
||||||
|
"@msgpackr-extract/msgpackr-extract-win32-x64" "2.1.2"
|
||||||
|
|
||||||
|
msgpackr@^1.5.2:
|
||||||
|
version "1.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.6.2.tgz#176cd9f6b4437dad87a839b37f23c2dfee408d9a"
|
||||||
|
integrity sha512-bqSQ0DYJbXbrJcrZFmMygUZmqQiDfI2ewFVWcrZY12w5XHWtPuW4WppDT/e63Uu311ajwkRRXSoF0uILroBeTA==
|
||||||
|
optionalDependencies:
|
||||||
|
msgpackr-extract "^2.0.2"
|
||||||
|
|
||||||
mssql@6.2.3:
|
mssql@6.2.3:
|
||||||
version "6.2.3"
|
version "6.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/mssql/-/mssql-6.2.3.tgz#1d15bbe8c3057e32ee6e98596b6c323b097a6cba"
|
resolved "https://registry.yarnpkg.com/mssql/-/mssql-6.2.3.tgz#1d15bbe8c3057e32ee6e98596b6c323b097a6cba"
|
||||||
|
@ -10131,6 +10177,11 @@ node-forge@^1.3.1:
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
||||||
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
||||||
|
|
||||||
|
node-gyp-build-optional-packages@5.0.3:
|
||||||
|
version "5.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz#92a89d400352c44ad3975010368072b41ad66c17"
|
||||||
|
integrity sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==
|
||||||
|
|
||||||
node-gyp-build@~4.1.0:
|
node-gyp-build@~4.1.0:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb"
|
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb"
|
||||||
|
@ -11354,15 +11405,6 @@ progress@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||||
|
|
||||||
promise.prototype.finally@^3.1.2:
|
|
||||||
version "3.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz#d3186e58fcf4df1682a150f934ccc27b7893389c"
|
|
||||||
integrity sha512-EXRF3fC9/0gz4qkt/f5EP5iW4kj9oFpBICNpCNOb/52+8nlHIX07FPLbi/q4qYBQ1xZqivMzTpNQSnArVASolQ==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.19.1"
|
|
||||||
|
|
||||||
prompts@^2.0.1:
|
prompts@^2.0.1:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
||||||
|
@ -13733,7 +13775,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
util.promisify@^1.0.0, util.promisify@^1.0.1:
|
util.promisify@^1.0.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b"
|
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b"
|
||||||
integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==
|
integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/types",
|
"name": "@budibase/types",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase types",
|
"description": "Budibase types",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.2.39-alpha.6",
|
"version": "1.2.44-alpha.1",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -35,10 +35,10 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "1.2.39-alpha.6",
|
"@budibase/backend-core": "1.2.44-alpha.1",
|
||||||
"@budibase/pro": "1.2.39-alpha.6",
|
"@budibase/pro": "1.2.44-alpha.1",
|
||||||
"@budibase/string-templates": "1.2.39-alpha.6",
|
"@budibase/string-templates": "1.2.44-alpha.1",
|
||||||
"@budibase/types": "1.2.39-alpha.6",
|
"@budibase/types": "1.2.44-alpha.1",
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
|
|
|
@ -291,12 +291,12 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.2.39-alpha.6":
|
"@budibase/backend-core@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.6.tgz#ebfddd4fa74fff043a60df7cba335b5fcdb84d51"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.44-alpha.1.tgz#255c8550302ea0d4b10b231519e12021d008ad33"
|
||||||
integrity sha512-1kz9K3MSe5E4d/dSm6jD4BMIX/SSW58d8U787N+1BfzvSkIEd32j7HFs5ij0w9sromvK9FEjpFBfZKqSDRp+5g==
|
integrity sha512-9ceN00ioBD5iUc2Wbcs9Pyvh5gaSfkg1v4Qn9QdRwAG36eo3XVK8kiYWF0q0hkzgcTViJw6xq/1jqMa2InKv6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/types" "1.2.39-alpha.6"
|
"@budibase/types" "1.2.44-alpha.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-sdk "2.1030.0"
|
aws-sdk "2.1030.0"
|
||||||
bcrypt "5.0.1"
|
bcrypt "5.0.1"
|
||||||
|
@ -325,21 +325,21 @@
|
||||||
uuid "8.3.2"
|
uuid "8.3.2"
|
||||||
zlib "1.0.5"
|
zlib "1.0.5"
|
||||||
|
|
||||||
"@budibase/pro@1.2.39-alpha.6":
|
"@budibase/pro@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.6.tgz#94a19338c6f59755f34b4bf181ba15ac5eba5404"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.44-alpha.1.tgz#d9e919b1df96f3d3d5cf37753721d41348279f59"
|
||||||
integrity sha512-l5IcibGGpd9VCIzY5vZU6rYeJa+1AYNCsWWKMnm7ZeZQgiD62Hyus53pv9GvT4pwpUF60pxybAoTWhbbityCPQ==
|
integrity sha512-KaclS4qv4+hWenvuVwF2HxcPWkrDyR7IVyLKLMVUqCnaMoXMvEOe9KuQ+lXLbsLIBsCsCFkzE/WHsdmoaGqa0g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.2.39-alpha.6"
|
"@budibase/backend-core" "1.2.44-alpha.1"
|
||||||
"@budibase/types" "1.2.39-alpha.6"
|
"@budibase/types" "1.2.44-alpha.1"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@budibase/types@1.2.39-alpha.6":
|
"@budibase/types@1.2.44-alpha.1":
|
||||||
version "1.2.39-alpha.6"
|
version "1.2.44-alpha.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.6.tgz#5c6dc1a130913fb1c7ac6999fc6e03d970d0142f"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.44-alpha.1.tgz#6150d4494326438b46dd7354e5dd0fc7fdbfcc49"
|
||||||
integrity sha512-0FHmwsfvAL80PGQM0OSJ6n9CDCtQQrbX8PRdcWOSIhRNlJXNcTsPcBsPbQpZPbgT57GHX/86Fo1rljiMWDwNpw==
|
integrity sha512-1eLGH5ym4oYbuRZRkD0slNqHlZ1EV0JHLkmoA47i7L/u8E8QRIyDIHyeZKC8ben33oQS4NX3IebD7zZ2JFhgcA==
|
||||||
|
|
||||||
"@cspotcode/source-map-consumer@0.8.0":
|
"@cspotcode/source-map-consumer@0.8.0":
|
||||||
version "0.8.0"
|
version "0.8.0"
|
||||||
|
|
Loading…
Reference in a new issue