From 0ce0f5c823cffba2db2d700437820d6ec7c6da90 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 07:28:59 +0100 Subject: [PATCH 01/88] Add initial DND implementation with working functionality for dropping inside components --- .../AppPreview/CurrentItemPreview.svelte | 16 ++++ .../client/src/components/ClientApp.svelte | 2 + .../client/src/components/Component.svelte | 4 + .../src/components/preview/DNDHandler.svelte | 83 +++++++++++++++++++ packages/client/src/stores/builder.js | 9 +- packages/client/src/utils/styleable.js | 2 + 6 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 packages/client/src/components/preview/DNDHandler.svelte diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 494050f690..422eba73b0 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -1,5 +1,6 @@ + + diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 3f36af1d06..3a7eb1df61 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -64,13 +64,18 @@ const createBuilderStore = () => { dispatchEvent("preview-loaded") }, setSelectedPath: path => { - console.log("set to ") - console.log(path) writableStore.update(state => { state.selectedPath = path return state }) }, + moveComponent: (componentId, destinationComponentId, mode) => { + dispatchEvent("move-component", { + componentId, + destinationComponentId, + mode, + }) + }, } return { ...writableStore, diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index d9925af91a..32171b9478 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -23,6 +23,8 @@ export const styleable = (node, styles = {}) => { let applyHoverStyles let selectComponent + node.setAttribute("draggable", true) + // Creates event listeners and applies initial styles const setupStyles = (newStyles = {}) => { // Use empty state styles as base styles if required, but let them, get From d86e5718d56e58b0de7eba38c6ba89ea8bf02d7a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 07:35:19 +0100 Subject: [PATCH 02/88] Prevent DND if target is a child of source --- .../design/AppPreview/CurrentItemPreview.svelte | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 422eba73b0..a8f1b507f4 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -8,7 +8,7 @@ import ConfirmDialog from "components/common/ConfirmDialog.svelte" import { ProgressCircle, Layout, Heading, Body } from "@budibase/bbui" import ErrorSVG from "assets/error.svg?raw" - import { findComponent } from "builderStore/storeUtils" + import { findComponent, findComponentPath } from "builderStore/storeUtils" let iframe let layout @@ -123,6 +123,17 @@ get(currentAsset).props, data.destinationComponentId ) + + // Stop if the target is a child of source + const path = findComponentPath( + sourceComponent, + data.destinationComponentId + ) + const ids = path.map(component => component._id) + if (ids.includes(data.destinationComponentId)) { + return + } + if (sourceComponent && destinationComponent) { store.actions.components.copy(sourceComponent, true) store.actions.components.paste(destinationComponent, data.mode) From 97800563c4c3b0176424c9a365bf007afd5f726e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 07:52:49 +0100 Subject: [PATCH 03/88] Prevent dragging the screen or layout components, and prevent dragging any layout components when previewing a screen --- packages/client/src/components/ClientApp.svelte | 5 ++++- packages/client/src/components/Component.svelte | 7 +++++-- packages/client/src/components/Screen.svelte | 2 +- packages/client/src/utils/styleable.js | 6 +++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 5c46161577..fb9117832f 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -105,7 +105,10 @@
{#key $screenStore.activeLayout._id} - + {/key} diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 20d8b53609..414d87a0aa 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -11,6 +11,8 @@ import Placeholder from "components/app/Placeholder.svelte" export let instance = {} + export let isLayout = false + export let isScreen = false // The enriched component settings let enrichedSettings @@ -178,7 +180,8 @@ data-type={interactive ? "component" : ""} data-id={id} data-name={name} - data-droppable={definition?.hasChildren || false} + data-draggable={interactive && !isLayout && !isScreen ? "true" : "false"} + data-droppable={definition?.hasChildren ? "true" : "false"} > {#if children.length} @@ -197,7 +200,7 @@ .component { display: contents; } - .component > :global(*:hover) { + [data-draggable="true"] { cursor: pointer; } diff --git a/packages/client/src/components/Screen.svelte b/packages/client/src/components/Screen.svelte index a759119320..4878df157f 100644 --- a/packages/client/src/components/Screen.svelte +++ b/packages/client/src/components/Screen.svelte @@ -22,6 +22,6 @@ {#key screenDefinition?._id} - + {/key} diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 32171b9478..27f6c6a0f6 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -23,7 +23,11 @@ export const styleable = (node, styles = {}) => { let applyHoverStyles let selectComponent - node.setAttribute("draggable", true) + // Allow dragging if required + const parent = node.closest("[data-type='component']") + if (parent && parent.dataset.draggable === "true") { + node.setAttribute("draggable", true) + } // Creates event listeners and applies initial styles const setupStyles = (newStyles = {}) => { From 5c37238c8a0e8571eb592bd97d6ad9213e292d90 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 14:11:05 +0100 Subject: [PATCH 04/88] Fix progress circle never animating because of wrong default prop --- packages/bbui/src/ProgressCircle/ProgressCircle.svelte | 2 +- .../client/src/components/preview/DNDPositionIndicator.svelte | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 packages/client/src/components/preview/DNDPositionIndicator.svelte diff --git a/packages/bbui/src/ProgressCircle/ProgressCircle.svelte b/packages/bbui/src/ProgressCircle/ProgressCircle.svelte index a86de55423..0428263346 100644 --- a/packages/bbui/src/ProgressCircle/ProgressCircle.svelte +++ b/packages/bbui/src/ProgressCircle/ProgressCircle.svelte @@ -13,7 +13,7 @@ } } - export let value = false + export let value = null export let minValue = 0 export let maxValue = 100 diff --git a/packages/client/src/components/preview/DNDPositionIndicator.svelte b/packages/client/src/components/preview/DNDPositionIndicator.svelte new file mode 100644 index 0000000000..e69de29bb2 From bdc86e4c22c2eb98058384d06ad4a2e6473254f0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 14:28:44 +0100 Subject: [PATCH 05/88] Add above/below dnd and support for dropping above/below components which also allow dropping inside --- .../client/src/components/Component.svelte | 3 +- .../src/components/preview/DNDHandler.svelte | 106 ++++++++++++++++-- .../preview/DNDPositionIndicator.svelte | 33 ++++++ .../components/preview/HoverIndicator.svelte | 2 +- .../components/preview/IndicatorSet.svelte | 4 + packages/client/src/stores/builder.js | 8 ++ packages/client/src/utils/styleable.js | 3 +- 7 files changed, 144 insertions(+), 15 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 414d87a0aa..a7ac7b0cd0 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -181,7 +181,8 @@ data-id={id} data-name={name} data-draggable={interactive && !isLayout && !isScreen ? "true" : "false"} - data-droppable={definition?.hasChildren ? "true" : "false"} + data-droppable={interactive ? "true" : "false"} + data-droppable-inside={definition?.hasChildren ? "true" : "false"} > {#if children.length} diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 88b9176efb..c3630051ee 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -1,36 +1,116 @@ + +{#if dropMode !== "inside" && dropInfo} + +{/if} diff --git a/packages/client/src/components/preview/DNDPositionIndicator.svelte b/packages/client/src/components/preview/DNDPositionIndicator.svelte index e69de29bb2..d86b79b88f 100644 --- a/packages/client/src/components/preview/DNDPositionIndicator.svelte +++ b/packages/client/src/components/preview/DNDPositionIndicator.svelte @@ -0,0 +1,33 @@ + + +{#if valid} +
+{/if} + + diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 9518c6d101..3cae1e4c85 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -30,7 +30,7 @@ { theme: null, customTheme: null, previewDevice: "desktop", + showHoverIndicator: true, } const writableStore = writable(initialState) const derivedStore = derived(writableStore, $state => { @@ -76,9 +77,16 @@ const createBuilderStore = () => { mode, }) }, + showHoverIndicator: show => { + writableStore.update(state => { + state.showHoverIndicator = show + return state + }) + }, } return { ...writableStore, + set: state => writableStore.set({ ...initialState, ...state }), subscribe: derivedStore.subscribe, actions, } diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 27f6c6a0f6..899854ecc9 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -33,6 +33,7 @@ export const styleable = (node, styles = {}) => { const setupStyles = (newStyles = {}) => { // Use empty state styles as base styles if required, but let them, get // overridden by any user specified styles + const baseString = node.style.cssText let baseStyles = {} if (newStyles.empty) { baseStyles.border = "2px dashed var(--spectrum-global-color-gray-600)" @@ -50,7 +51,7 @@ export const styleable = (node, styles = {}) => { // Applies a style string to a DOM node const applyStyles = styleString => { - node.style = styleString + node.style = `${baseString}${styleString}` node.dataset.componentId = componentId } From 46867b8a198a28785aa7311b4526cec22a4253fd Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 15:08:42 +0100 Subject: [PATCH 06/88] Add labels to DND to describe where the component will be dropped --- .../src/components/preview/DNDHandler.svelte | 12 +++-- .../preview/DNDPositionIndicator.svelte | 53 +++++++++++-------- .../src/components/preview/Indicator.svelte | 8 ++- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index c3630051ee..d1a4934826 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -1,6 +1,7 @@ -{#if valid} -
-{/if} - - +{#key mode} + {#if dimensions} + + {/if} +{/key} diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 95364d0278..66363e3992 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -9,6 +9,9 @@ export let color export let zIndex export let transition = false + export let flip = false + + $: flipped = flip || top < 20
{#if text} -
+
{text}
{/if} @@ -63,6 +66,7 @@ } .text.flipped { border-top-left-radius: 4px; + border-bottom-left-radius: 4px; transform: translateY(0%); top: -2px; } From 601a4935a9a207a50925ebb7f04e9bcc797ab7e3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 15:49:58 +0100 Subject: [PATCH 07/88] Ensure transitions work properly when showing and hiding DND candidate positions --- packages/client/src/components/preview/DNDHandler.svelte | 5 ++--- .../src/components/preview/DNDPositionIndicator.svelte | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index d1a4934826..111c009a3a 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -25,9 +25,7 @@ // Highlight being dragged by setting opacity const child = getDOMNodeForComponent(e.target) - console.log(child) if (child) { - console.log("set opacity") child.style.opacity = "0.5" } } @@ -163,7 +161,8 @@ /> import Indicator from "./Indicator.svelte" + export let componentId export let dropInfo export let mode export let zIndex @@ -24,8 +25,8 @@ } -{#key mode} - {#if dimensions} +{#key `${componentId}-${mode}`} + {#if dimensions && mode !== "inside"} Date: Thu, 16 Sep 2021 16:02:45 +0100 Subject: [PATCH 08/88] Ensure hover indicator is correctly hidden when using DND and improve DND labels --- .../src/components/preview/DNDHandler.svelte | 10 ++++++++-- .../components/preview/DNDPositionIndicator.svelte | 3 +-- .../client/src/components/preview/Indicator.svelte | 14 +++++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 111c009a3a..409eeb2d8f 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -1,7 +1,7 @@
{#if text} -
+
{text}
{/if} @@ -45,6 +46,9 @@ .indicator.flipped { border-top-left-radius: 4px; } + .indicator.line { + border-radius: 4px !important; + } .text { background-color: var(--color); color: white; @@ -70,4 +74,8 @@ transform: translateY(0%); top: -2px; } + .text.line { + transform: translateY(-50%) !important; + border-radius: 4px !important; + } From e625d2e4a321a20ff62c1904c9e65ce4ec0df636 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 16 Sep 2021 17:39:39 +0100 Subject: [PATCH 09/88] Reduce duplication in move componment handler from dnd callback --- .../AppPreview/CurrentItemPreview.svelte | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 3901252ee9..4e51850fe1 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -125,29 +125,24 @@ // loading is supported loading = false } else if (type === "move-component") { - // Copy - const sourceComponent = findComponent( - get(currentAsset).props, - data.componentId - ) - const destinationComponent = findComponent( - get(currentAsset).props, - data.destinationComponentId - ) + const { componentId, destinationComponentId } = data + const rootComponent = get(currentAsset).props + + // Get source and destination components + const source = findComponent(rootComponent, componentId) + const destination = findComponent(rootComponent, destinationComponentId) // Stop if the target is a child of source - const path = findComponentPath( - sourceComponent, - data.destinationComponentId - ) + const path = findComponentPath(source, destinationComponentId) const ids = path.map(component => component._id) if (ids.includes(data.destinationComponentId)) { return } - if (sourceComponent && destinationComponent) { - store.actions.components.copy(sourceComponent, true) - store.actions.components.paste(destinationComponent, data.mode) + // Cut and paste the component to the new destination + if (source && destination) { + store.actions.components.copy(source, true) + store.actions.components.paste(destination, data.mode) } } else { console.warning(`Client sent unknown event type: ${type}`) From 7eeb215e51722e4afd42f034f3a973d764cb1034 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 17 Sep 2021 14:17:50 +0100 Subject: [PATCH 10/88] Refactor to use generic flag for dragging and hide settings bar when dragging --- .../client/src/components/preview/DNDHandler.svelte | 11 +++++------ .../src/components/preview/HoverIndicator.svelte | 2 +- .../client/src/components/preview/SettingsBar.svelte | 2 +- packages/client/src/stores/builder.js | 7 +++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 409eeb2d8f..c1a6a74465 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -21,6 +21,7 @@ // Update state dragTarget = e.target.dataset.componentId builderStore.actions.selectComponent(dragTarget) + builderStore.actions.setDragging(true) // Highlight being dragged by setting opacity const child = getDOMNodeForComponent(e.target) @@ -34,15 +35,13 @@ // Reset state and styles dropTarget = null dropInfo = null + builderStore.actions.setDragging(false) // Reset opacity style const child = getDOMNodeForComponent(e.target) if (child) { child.style.opacity = "" } - - // Re-enable the hover indicator - builderStore.actions.showHoverIndicator(true) } // Callback when on top of a component @@ -96,11 +95,11 @@ element.dataset.droppable && element.dataset.id !== dragTarget ) { - // Disable hover selection again to ensure it's always disabled. + // Ensure the dragging flag is always set. // There's a bit of a race condition between the app reinitialisation // after selecting the DND component and setting this the first time - if (get(builderStore).showHoverIndicator) { - builderStore.actions.showHoverIndicator(false) + if (!get(builderStore).isDragging) { + builderStore.actions.setDragging(true) } // Store target ID diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 3cae1e4c85..28109cb262 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -30,7 +30,7 @@ setting.showInBar) ?? [] const updatePosition = () => { diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index ce653a8fc1..0d738e4a11 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -23,7 +23,7 @@ const createBuilderStore = () => { theme: null, customTheme: null, previewDevice: "desktop", - showHoverIndicator: true, + isDragging: false, } const writableStore = writable(initialState) const derivedStore = derived(writableStore, $state => { @@ -77,16 +77,15 @@ const createBuilderStore = () => { mode, }) }, - showHoverIndicator: show => { + setDragging: dragging => { writableStore.update(state => { - state.showHoverIndicator = show + state.isDragging = dragging return state }) }, } return { ...writableStore, - set: state => writableStore.set({ ...initialState, ...state }), subscribe: derivedStore.subscribe, actions, } From 54bf420ef89b6fe7eb6ec2c43051ec22d49f4d34 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 17 Sep 2021 14:30:54 +0100 Subject: [PATCH 11/88] Apply grab cursor when hovering over a draggable component --- packages/client/src/components/Component.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index a7ac7b0cd0..980e7cd80b 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -201,7 +201,7 @@ .component { display: contents; } - [data-draggable="true"] { - cursor: pointer; + [data-draggable="true"] :global(*:hover) { + cursor: grab !important; } From f0dde4a4a425c625893b32a255d3ea02c5dc7027 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 08:06:01 +0100 Subject: [PATCH 12/88] Fix a few possible crashes by dragging in certain ways, and display on screen when an invalid drop target is hovered over --- .../src/components/preview/DNDHandler.svelte | 90 +++++++++++-------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index c1a6a74465..fe4d7f4d59 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -18,6 +18,10 @@ // Callback when initially starting a drag on a draggable component const onDragStart = e => { + if (!e.target?.dataset?.componentId) { + return + } + // Update state dragTarget = e.target.dataset.componentId builderStore.actions.selectComponent(dragTarget) @@ -32,63 +36,73 @@ // Callback when drag stops (whether dropped or not) const onDragEnd = e => { + // Reset opacity style + if (dragTarget) { + const child = getDOMNodeForComponent(e.target) + if (child) { + child.style.opacity = "" + } + } + // Reset state and styles + dragTarget = null dropTarget = null dropInfo = null builderStore.actions.setDragging(false) - - // Reset opacity style - const child = getDOMNodeForComponent(e.target) - if (child) { - child.style.opacity = "" - } } // Callback when on top of a component const onDragOver = e => { + // Skip if we aren't validly dragging currently + if (!dragTarget || !dropInfo) { + return + } + e.preventDefault() + const { droppableInside, bounds } = dropInfo + const { top, height } = bounds + const mouseY = e.clientY + const elTop = top + const elBottom = top + height - if (dropInfo) { - const { droppableInside, bounds } = dropInfo - const { top, height } = bounds - const mouseY = e.clientY - const elTop = top - const elBottom = top + height + // Determine which edge we're nearest as this is needed for potentially + // any drop mode + let nearestEdge + if (Math.abs(elTop - mouseY) < Math.abs(elBottom - mouseY)) { + nearestEdge = "above" + } else { + nearestEdge = "below" + } - // Determine which edge we're nearest as this is needed for potentially - // any drop mode - let nearestEdge - if (Math.abs(elTop - mouseY) < Math.abs(elBottom - mouseY)) { - nearestEdge = "above" + // If not available to drop inside, just check whether we are closer + // to the top or bottom + if (!droppableInside) { + dropMode = nearestEdge + } + + // Otherwise determine whether the user wants to drop inside or at + // either edge + else { + const edgeLimit = Math.min(40, height * 0.33) + const insideLimit = [ + Math.round(top + edgeLimit), + Math.round(top + height - edgeLimit), + ] + if (mouseY >= insideLimit[0] && mouseY <= insideLimit[1]) { + dropMode = "inside" } else { - nearestEdge = "below" - } - - // If not available to drop inside, just check whether we are closer - // to the top or bottom - if (!droppableInside) { dropMode = nearestEdge } - - // Otherwise determine whether the user wants to drop inside or at - // either edge - else { - const edgeLimit = Math.min(40, height * 0.33) - const insideLimit = [ - Math.round(top + edgeLimit), - Math.round(top + height - edgeLimit), - ] - if (mouseY >= insideLimit[0] && mouseY <= insideLimit[1]) { - dropMode = "inside" - } else { - dropMode = nearestEdge - } - } } } // Callback when entering a potential drop target const onDragEnter = e => { + // Skip if we aren't validly dragging currently + if (!dragTarget) { + return + } + const element = e.target.closest("[data-type='component']") if ( element && From 8cf3971b471a4c67a47de30f58702859f8148367 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 08:26:44 +0100 Subject: [PATCH 13/88] Only allow dropping inside empty components that accept children to massively reduce the amount of unwanted drop targets due to parent container components --- .../client/src/components/Component.svelte | 15 ++++-- .../src/components/preview/DNDHandler.svelte | 53 ++++++++++--------- .../preview/DNDPositionIndicator.svelte | 10 ++-- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 980e7cd80b..6192004b42 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -171,18 +171,23 @@ conditionalSettings = result.settingUpdates visible = nextVisible } + + // Drag and drop helper tags + $: draggable = interactive && !isLayout && !isScreen + $: droppable = interactive + $: dropInside = interactive && definition?.hasChildren && !children.length {#key propsHash} {#if constructor && componentSettings && (visible || inSelectedPath)}
{#if children.length} @@ -202,6 +207,6 @@ display: contents; } [data-draggable="true"] :global(*:hover) { - cursor: grab !important; + cursor: grab; } diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index fe4d7f4d59..2437386929 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -5,9 +5,7 @@ import DNDPositionIndicator from "./DNDPositionIndicator.svelte" import { builderStore } from "stores" - let dragTarget - let dropTarget - let dropMode + let dragInfo let dropInfo const getDOMNodeForComponent = component => { @@ -18,26 +16,28 @@ // Callback when initially starting a drag on a draggable component const onDragStart = e => { - if (!e.target?.dataset?.componentId) { + const parent = e.target.closest("[data-type='component']") + const child = getDOMNodeForComponent(e.target) + if (!parent?.dataset?.id || !child) { return } // Update state - dragTarget = e.target.dataset.componentId - builderStore.actions.selectComponent(dragTarget) + dragInfo = { + target: parent.dataset.id, + parent: parent.dataset.parent, + } + builderStore.actions.selectComponent(dragInfo.target) builderStore.actions.setDragging(true) // Highlight being dragged by setting opacity - const child = getDOMNodeForComponent(e.target) - if (child) { - child.style.opacity = "0.5" - } + child.style.opacity = "0.5" } // Callback when drag stops (whether dropped or not) const onDragEnd = e => { // Reset opacity style - if (dragTarget) { + if (dragInfo) { const child = getDOMNodeForComponent(e.target) if (child) { child.style.opacity = "" @@ -45,8 +45,7 @@ } // Reset state and styles - dragTarget = null - dropTarget = null + dragInfo = null dropInfo = null builderStore.actions.setDragging(false) } @@ -54,7 +53,7 @@ // Callback when on top of a component const onDragOver = e => { // Skip if we aren't validly dragging currently - if (!dragTarget || !dropInfo) { + if (!dragInfo || !dropInfo) { return } @@ -77,7 +76,7 @@ // If not available to drop inside, just check whether we are closer // to the top or bottom if (!droppableInside) { - dropMode = nearestEdge + dropInfo.mode = nearestEdge } // Otherwise determine whether the user wants to drop inside or at @@ -89,9 +88,9 @@ Math.round(top + height - edgeLimit), ] if (mouseY >= insideLimit[0] && mouseY <= insideLimit[1]) { - dropMode = "inside" + dropInfo.mode = "inside" } else { - dropMode = nearestEdge + dropInfo.mode = nearestEdge } } } @@ -99,7 +98,7 @@ // Callback when entering a potential drop target const onDragEnter = e => { // Skip if we aren't validly dragging currently - if (!dragTarget) { + if (!dragInfo) { return } @@ -107,7 +106,7 @@ if ( element && element.dataset.droppable && - element.dataset.id !== dragTarget + element.dataset.id !== dragInfo.target ) { // Ensure the dragging flag is always set. // There's a bit of a race condition between the app reinitialisation @@ -117,20 +116,20 @@ } // Store target ID - dropTarget = element.dataset.id + const target = element.dataset.id // Precompute and store some info to avoid recalculating everything in // dragOver const child = getDOMNodeForComponent(e.target) const bounds = child.getBoundingClientRect() dropInfo = { + target, name: element.dataset.name, droppableInside: element.dataset.droppableInside === "true", bounds, } } else { dropInfo = null - dropTarget = null } } @@ -141,8 +140,12 @@ // Callback when dropping a drag on top of some component const onDrop = e => { e.preventDefault() - if (dropTarget && dropMode) { - builderStore.actions.moveComponent(dragTarget, dropTarget, dropMode) + if (dropInfo) { + builderStore.actions.moveComponent( + dragInfo.target, + dropInfo.target, + dropInfo.mode + ) } } @@ -172,7 +175,7 @@ import Indicator from "./Indicator.svelte" - export let componentId export let dropInfo - export let mode export let zIndex export let color export let transition - $: dimensions = getDimensions(dropInfo?.bounds, mode) - $: prefix = mode === "above" ? "Above" : "Below" + $: dimensions = getDimensions(dropInfo?.bounds, dropInfo?.mode) + $: prefix = dropInfo?.mode === "above" ? "Above" : "Below" $: text = `${prefix} ${dropInfo?.name}` const getDimensions = (bounds, mode) => { @@ -25,8 +23,8 @@ } -{#key `${componentId}-${mode}`} - {#if dimensions && mode !== "inside"} +{#key `${dropInfo?.target}-${dropInfo?.mode}`} + {#if dimensions && dropInfo?.mode !== "inside"} Date: Mon, 20 Sep 2021 09:12:35 +0100 Subject: [PATCH 14/88] Prevent DND targetting either above or below the screen/layout, and fix bug determinging whether a drop target is valid --- packages/client/src/components/Component.svelte | 2 +- packages/client/src/components/preview/DNDHandler.svelte | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 6192004b42..5e02e345d4 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -174,7 +174,7 @@ // Drag and drop helper tags $: draggable = interactive && !isLayout && !isScreen - $: droppable = interactive + $: droppable = interactive && !isLayout && !isScreen $: dropInside = interactive && definition?.hasChildren && !children.length diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 2437386929..90e2a55ca4 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -105,9 +105,14 @@ const element = e.target.closest("[data-type='component']") if ( element && - element.dataset.droppable && + element.dataset.droppable === "true" && element.dataset.id !== dragInfo.target ) { + // Do nothing if this is the same target + if (element.dataset.id === dropInfo?.target) { + return + } + // Ensure the dragging flag is always set. // There's a bit of a race condition between the app reinitialisation // after selecting the DND component and setting this the first time From 9ca0aeae8e23ce22e846b78b09bc6224d08eec00 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 12:14:40 +0100 Subject: [PATCH 15/88] Fix spectrum button not being able to be dragged --- packages/client/src/components/app/Button.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/client/src/components/app/Button.svelte b/packages/client/src/components/app/Button.svelte index ed465e3e66..9900c740d2 100644 --- a/packages/client/src/components/app/Button.svelte +++ b/packages/client/src/components/app/Button.svelte @@ -31,4 +31,7 @@ .spectrum-Button--overBackground:hover { color: #555; } + .spectrum-Button::after { + display: none; + } From 10f754a9ad52982a3322afdc8350477d5b8aa947 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 12:16:23 +0100 Subject: [PATCH 16/88] Remove preview specific data tags from components when running real apps --- packages/client/src/components/Component.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 5e02e345d4..f590e2aa9f 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -63,7 +63,9 @@ $builderStore.inBuilder && $builderStore.selectedComponentId === instance._id $: inSelectedPath = $builderStore.selectedComponentPath?.includes(id) - $: interactive = $builderStore.previewType === "layout" || insideScreenslot + $: interactive = + $builderStore.inBuilder && + ($builderStore.previewType === "layout" || insideScreenslot) $: evaluateConditions(enrichedSettings?._conditions) $: componentSettings = { ...enrichedSettings, ...conditionalSettings } From 07e0cbb210c5357f83b3e5532b39b86ac3b5fed6 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 12:20:34 +0100 Subject: [PATCH 17/88] Remove old and no longer needed component-id data tag applied by styleable helper --- packages/builder/cypress/support/commands.js | 2 +- packages/client/src/utils/styleable.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index ea6ca81e66..dbfabeda3f 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -145,7 +145,7 @@ Cypress.Commands.add("getComponent", componentId => { .its("body") .should("not.be.null") .then(cy.wrap) - .find(`[data-component-id=${componentId}]`) + .find(`[data-id=${componentId}]`) }) Cypress.Commands.add("navigateToFrontend", () => { diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 899854ecc9..3fce1bcf26 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -52,7 +52,6 @@ export const styleable = (node, styles = {}) => { // Applies a style string to a DOM node const applyStyles = styleString => { node.style = `${baseString}${styleString}` - node.dataset.componentId = componentId } // Applies the "normal" style definition From 488ec4d988686899650a48b53e6badeac1ecdbfa Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 15:34:51 +0100 Subject: [PATCH 18/88] Refactor client app data tags to be classnames and simplify logic --- .../client/src/components/Component.svelte | 69 ++++++++++--------- .../src/components/app/Container.svelte | 4 +- .../src/components/preview/DNDHandler.svelte | 18 ++--- .../components/preview/HoverIndicator.svelte | 2 +- packages/client/src/utils/styleable.js | 4 +- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index f590e2aa9f..3d863c276e 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -51,11 +51,11 @@ $: children = instance._children || [] $: id = instance._id $: name = instance._instanceName - $: empty = - !children.length && - definition?.hasChildren && - definition?.showEmptyState !== false && - $builderStore.inBuilder + $: interactive = + $builderStore.inBuilder && + ($builderStore.previewType === "layout" || insideScreenslot) + $: empty = interactive && !children.length && definition?.hasChildren + $: emptyState = empty && definition?.showEmptyState !== false $: rawProps = getRawProps(instance) $: instanceKey = JSON.stringify(rawProps) $: updateComponentProps(rawProps, instanceKey, $context) @@ -63,9 +63,6 @@ $builderStore.inBuilder && $builderStore.selectedComponentId === instance._id $: inSelectedPath = $builderStore.selectedComponentPath?.includes(id) - $: interactive = - $builderStore.inBuilder && - ($builderStore.previewType === "layout" || insideScreenslot) $: evaluateConditions(enrichedSettings?._conditions) $: componentSettings = { ...enrichedSettings, ...conditionalSettings } @@ -73,8 +70,8 @@ $: componentStore.set({ id, children: children.length, - styles: { ...instance._styles, id, empty, interactive }, - empty, + styles: { ...instance._styles, id, empty: emptyState, interactive }, + empty: emptyState, selected, name, }) @@ -177,38 +174,44 @@ // Drag and drop helper tags $: draggable = interactive && !isLayout && !isScreen $: droppable = interactive && !isLayout && !isScreen - $: dropInside = interactive && definition?.hasChildren && !children.length {#key propsHash} - {#if constructor && componentSettings && (visible || inSelectedPath)} -
- - {#if children.length} - {#each children as child (child._id)} - - {/each} - {:else if empty} - - {/if} - -
- {/if} + {#key empty} + {#if constructor && componentSettings && (visible || inSelectedPath)} + + +
+ + {#if children.length} + {#each children as child (child._id)} + + {/each} + {:else if emptyState} + + {/if} + +
+ {/if} + {/key} {/key} diff --git a/packages/client/src/components/app/Container.svelte b/packages/client/src/components/app/Container.svelte index 5b2f951c8d..148179c98f 100644 --- a/packages/client/src/components/app/Container.svelte +++ b/packages/client/src/components/app/Container.svelte @@ -34,7 +34,7 @@ display: flex; max-width: 100%; } - .valid-container :global([data-type="component"] > *) { + .valid-container :global(.component > *) { max-width: 100%; } .direction-row { @@ -46,7 +46,7 @@ /* Grow containers inside a row need 0 width 0 so that they ignore content */ /* The nested selector for data-type is the wrapper around all components */ - .direction-row :global(> [data-type="component"] > .size-grow) { + .direction-row :global(> .component > .size-grow) { width: 0; } diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 90e2a55ca4..d7d2d94793 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -9,16 +9,15 @@ let dropInfo const getDOMNodeForComponent = component => { - const parent = component.closest("[data-type='component']") + const parent = component.closest(".component") const children = Array.from(parent.childNodes) return children?.find(node => node?.nodeType === 1) } // Callback when initially starting a drag on a draggable component const onDragStart = e => { - const parent = e.target.closest("[data-type='component']") - const child = getDOMNodeForComponent(e.target) - if (!parent?.dataset?.id || !child) { + const parent = e.target.closest(".component") + if (!parent?.classList.contains("draggable")) { return } @@ -31,7 +30,10 @@ builderStore.actions.setDragging(true) // Highlight being dragged by setting opacity - child.style.opacity = "0.5" + const child = getDOMNodeForComponent(e.target) + if (child) { + child.style.opacity = "0.5" + } } // Callback when drag stops (whether dropped or not) @@ -102,10 +104,10 @@ return } - const element = e.target.closest("[data-type='component']") + const element = e.target.closest(".component") if ( element && - element.dataset.droppable === "true" && + element.classList.contains("droppable") && element.dataset.id !== dragInfo.target ) { // Do nothing if this is the same target @@ -130,7 +132,7 @@ dropInfo = { target, name: element.dataset.name, - droppableInside: element.dataset.droppableInside === "true", + droppableInside: element.classList.contains("empty"), bounds, } } else { diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 28109cb262..1a9e6477ac 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -7,7 +7,7 @@ $: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920 const onMouseOver = e => { - const element = e.target.closest("[data-type='component']") + const element = e.target.closest(".interactive.component") const newId = element?.dataset?.id if (newId !== componentId) { componentId = newId diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 3fce1bcf26..89d983d73b 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -24,8 +24,8 @@ export const styleable = (node, styles = {}) => { let selectComponent // Allow dragging if required - const parent = node.closest("[data-type='component']") - if (parent && parent.dataset.draggable === "true") { + const parent = node.closest(".component") + if (parent && parent.classList.contains("draggable")) { node.setAttribute("draggable", true) } From 9febe391bb96f9cba99d5c1c63f750a2433f2898 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 15:35:27 +0100 Subject: [PATCH 19/88] Refactor DND labels to before and after rather then above and below --- .../client/src/components/preview/DNDPositionIndicator.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/preview/DNDPositionIndicator.svelte b/packages/client/src/components/preview/DNDPositionIndicator.svelte index 8565d42f9e..19a44cfccc 100644 --- a/packages/client/src/components/preview/DNDPositionIndicator.svelte +++ b/packages/client/src/components/preview/DNDPositionIndicator.svelte @@ -7,7 +7,7 @@ export let transition $: dimensions = getDimensions(dropInfo?.bounds, dropInfo?.mode) - $: prefix = dropInfo?.mode === "above" ? "Above" : "Below" + $: prefix = dropInfo?.mode === "above" ? "Before" : "After" $: text = `${prefix} ${dropInfo?.name}` const getDimensions = (bounds, mode) => { From 495c20f85173899c2859fa6176c98e0782e89e3d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Sep 2021 15:41:20 +0100 Subject: [PATCH 20/88] Simplify client app component re-render keying --- .../client/src/components/Component.svelte | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 3d863c276e..faf0226604 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -65,6 +65,7 @@ $: inSelectedPath = $builderStore.selectedComponentPath?.includes(id) $: evaluateConditions(enrichedSettings?._conditions) $: componentSettings = { ...enrichedSettings, ...conditionalSettings } + $: renderKey = `${propsHash}-${emptyState}` // Update component context $: componentStore.set({ @@ -176,32 +177,30 @@ $: droppable = interactive && !isLayout && !isScreen -{#key propsHash} - {#key empty} - {#if constructor && componentSettings && (visible || inSelectedPath)} - - -
- - {#if children.length} - {#each children as child (child._id)} - - {/each} - {:else if emptyState} - - {/if} - -
- {/if} - {/key} +{#key renderKey} + {#if constructor && componentSettings && (visible || inSelectedPath)} + + +
+ + {#if children.length} + {#each children as child (child._id)} + + {/each} + {:else if emptyState} + + {/if} + +
+ {/if} {/key} From 0297b3de3fa604bdbeef377fb50c4b1c9b1befdd Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 21 Sep 2021 08:47:43 +0100 Subject: [PATCH 24/88] Simplify some DND style rules --- .../client/src/components/preview/Indicator.svelte | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 212cd1671d..5f3a4b70c7 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -70,18 +70,18 @@ justify-content: flex-start; align-items: center; } + .text.line { + transform: translateY(-50%); + border-radius: 4px; + } .text.flipped { border-top-left-radius: 4px; border-bottom-left-radius: 4px; transform: translateY(0%); top: -2px; } - .text.line { - transform: translateY(-50%) !important; - border-radius: 4px !important; - } .text.right { - right: -2px !important; - left: auto !important; + right: -2px; + left: auto; } From b5ff5a7f7647ee96544054e1d336f2f7984f0f6e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Sep 2021 16:06:57 +0100 Subject: [PATCH 25/88] Remove duplicate routes which are never used --- .../table/[selectedTable]/_layout.svelte | 13 ------------ .../table/[selectedTable]/index.svelte | 16 -------------- .../[selectedField]/index.svelte | 10 --------- .../relationship/[selectedRow]/index.svelte | 6 ------ .../[selectedTable]/relationship/index.svelte | 6 ------ .../bb_internal/table/_layout.svelte | 19 ----------------- .../datasource/bb_internal/table/index.svelte | 21 ------------------- 7 files changed, 91 deletions(-) delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/_layout.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/[selectedField]/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/_layout.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/index.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/_layout.svelte deleted file mode 100644 index 14f6303e5f..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/_layout.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/index.svelte deleted file mode 100644 index a68c0dc651..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/index.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - -{#if $database?._id && $tables?.selected?.name} - -{:else}Create your first table to start building{/if} - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/[selectedField]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/[selectedField]/index.svelte deleted file mode 100644 index eddb5ab598..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/[selectedField]/index.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/index.svelte deleted file mode 100644 index 8e195ddb12..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/[selectedRow]/index.svelte +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/index.svelte deleted file mode 100644 index 7d081b6976..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/[selectedTable]/relationship/index.svelte +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/_layout.svelte deleted file mode 100644 index f957355c5c..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/_layout.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/index.svelte deleted file mode 100644 index 6d61614145..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/bb_internal/table/index.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -{#if $tables.list.length === 0} - Create your first table to start building -{:else}Select a table to edit{/if} - - From 05cfd87613799c471318c738e9efab913af190c8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Sep 2021 16:08:09 +0100 Subject: [PATCH 26/88] Broadcast a sort event from BBUI table, and add prop to disable table sorting of data --- packages/bbui/src/Table/Table.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/bbui/src/Table/Table.svelte b/packages/bbui/src/Table/Table.svelte index 11284b8917..63f20ac1ff 100644 --- a/packages/bbui/src/Table/Table.svelte +++ b/packages/bbui/src/Table/Table.svelte @@ -27,6 +27,7 @@ export let selectedRows = [] export let editColumnTitle = "Edit" export let customRenderers = [] + export let disableSorting = false const dispatch = createEventDispatcher() @@ -107,7 +108,7 @@ } const sortRows = (rows, sortColumn, sortOrder) => { - if (!sortColumn || !sortOrder) { + if (!sortColumn || !sortOrder || disableSorting) { return rows } return rows.slice().sort((a, b) => { @@ -131,6 +132,7 @@ sortColumn = fieldSchema.name sortOrder = "Descending" } + dispatch("sort", { column: sortColumn, order: sortOrder }) } const getDisplayName = schema => { From 7ac4144903661cac7e9853b7373827f673c67159 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Sep 2021 16:08:47 +0100 Subject: [PATCH 27/88] Add new core implementation of fetching paginated table data and enable pagination in backend UI for tables --- .../backend/DataTable/DataTable.svelte | 121 ++++++----- .../components/backend/DataTable/Table.svelte | 76 +++---- .../builder/src/helpers/fetchTableData.js | 192 ++++++++++++++++++ 3 files changed, 301 insertions(+), 88 deletions(-) create mode 100644 packages/builder/src/helpers/fetchTableData.js diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 3293c694b6..88f754b254 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -1,6 +1,5 @@ - - {#if isInternal} - - {/if} - {#if schema && Object.keys(schema).length > 0} - {#if !isUsersTable} - - {/if} +
+
{#if isInternal} - + {/if} - - {#if isUsersTable} - + {#if schema && Object.keys(schema).length > 0} + {#if !isUsersTable} + + {/if} + {#if isInternal} + + {/if} + + {#if isUsersTable} + + {/if} + + + {/if} - - - - {/if} -
+ + +
+ + diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index fcb17a774d..38d580e273 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -1,8 +1,7 @@ -
-
- {#if title} - {title} - {/if} - {#if loading} -
- -
- {/if} + +
+
+ {#if title} + {title} + {/if} + {#if loading} +
+ +
+ {/if} +
+
+ + {#if !isUsersTable && selectedRows.length > 0} + + {/if} +
-
- - {#if !isUsersTable && selectedRows.length > 0} - - {/if} -
-
-{#key tableId} - editColumn(e.detail)} - on:editrow={e => editRow(e.detail)} - on:clickrelationship={e => selectRelationship(e.detail)} - /> -{/key} + {#key tableId} +
editColumn(e.detail)} + on:editrow={e => editRow(e.detail)} + on:clickrelationship={e => selectRelationship(e.detail)} + on:sort + /> + {/key} + diff --git a/packages/builder/src/helpers/fetchTableData.js b/packages/builder/src/helpers/fetchTableData.js new file mode 100644 index 0000000000..ff7d61519f --- /dev/null +++ b/packages/builder/src/helpers/fetchTableData.js @@ -0,0 +1,192 @@ +import { writable, derived, get } from "svelte/store" +import * as API from "builderStore/api" +import { buildLuceneQuery } from "../../../client/src/utils/lucene" + +const defaultOptions = { + tableId: null, + filter: null, + limit: 10, + sortColumn: null, + sortOrder: "ascending", + paginate: true, + schema: null, +} + +export const fetchTableData = opts => { + // Save option set so we can override it later rather than relying on params + let options = { + ...defaultOptions, + ...opts, + } + + // Local non-observable state + let query + let sortType + + // Local observable state + const store = writable({ + rows: [], + schema: null, + loading: false, + loaded: false, + bookmarks: [], + pageNumber: 0, + }) + + // Derive certain properties to return + const derivedStore = derived(store, $store => { + return { + ...$store, + hasNextPage: $store.bookmarks[$store.pageNumber + 1] != null, + hasPrevPage: $store.pageNumber > 0, + } + }) + + const fetchPage = async bookmark => { + const { tableId, limit, sortColumn, sortOrder, paginate } = options + store.update($store => ({ ...$store, loading: true })) + const res = await API.post(`/api/${options.tableId}/search`, { + tableId, + query, + limit, + sort: sortColumn, + sortOrder: sortOrder?.toLowerCase() ?? "ascending", + sortType, + paginate, + bookmark, + }) + store.update($store => ({ ...$store, loading: false, loaded: true })) + return await res.json() + } + + // Fetches a fresh set of results from the server + const fetchData = async () => { + const { tableId, schema, sortColumn, filter } = options + + // Ensure table ID exists + if (!tableId) { + return + } + + // Get and enrich schema. + // Ensure there are "name" properties for all fields and that field schema + // are objects + let enrichedSchema = schema + if (!enrichedSchema) { + const definition = await API.get(`/api/tables/${tableId}`) + enrichedSchema = definition?.schema ?? null + } + if (enrichedSchema) { + Object.entries(schema).forEach(([fieldName, fieldSchema]) => { + if (typeof fieldSchema === "string") { + enrichedSchema[fieldName] = { + type: fieldSchema, + name: fieldName, + } + } else { + enrichedSchema[fieldName] = { + ...fieldSchema, + name: fieldName, + } + } + }) + + // Save fixed schema so we can provide it later + options.schema = enrichedSchema + } + + // Ensure schema exists + if (!schema) { + return + } + store.update($store => ({ ...$store, schema })) + + // Work out what sort type to use + if (!sortColumn || !schema[sortColumn]) { + sortType = "string" + } + const type = schema?.[sortColumn]?.type + sortType = type === "number" ? "number" : "string" + + // Build the lucene query + query = buildLuceneQuery(filter) + + // Actually fetch data + const page = await fetchPage() + store.update($store => ({ + ...$store, + loading: false, + loaded: true, + pageNumber: 0, + rows: page.rows, + bookmarks: page.hasNextPage ? [null, page.bookmark] : [null], + })) + } + + // Fetches the next page of data + const nextPage = async () => { + const state = get(derivedStore) + if (!options.paginate || !state.hasNextPage) { + return + } + + // Fetch next page + const page = await fetchPage(state.bookmarks[state.pageNumber + 1]) + + // Update state + store.update($store => { + let { bookmarks, pageNumber } = $store + if (page.hasNextPage) { + bookmarks[pageNumber + 2] = page.bookmark + } + return { + ...$store, + pageNumber: pageNumber + 1, + rows: page.rows, + bookmarks, + } + }) + } + + // Fetches the previous page of data + const prevPage = async () => { + const state = get(derivedStore) + if (!options.paginate || !state.hasPrevPage) { + return + } + + // Fetch previous page + const page = await fetchPage(state.bookmarks[state.pageNumber - 1]) + + // Update state + store.update($store => { + return { + ...$store, + pageNumber: $store.pageNumber - 1, + rows: page.rows, + } + }) + } + + // Resets the data set and updates options + const update = async newOptions => { + if (newOptions) { + options = { + ...options, + ...newOptions, + } + } + await fetchData() + } + + // Initially fetch data but don't bother waiting for the result + fetchData() + + // Return our derived store which will be updated over time + return { + subscribe: derivedStore.subscribe, + nextPage, + prevPage, + update, + } +} From 890749ee3ea5142540e0607853e31077eff473f8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Sep 2021 17:04:12 +0100 Subject: [PATCH 28/88] Only refresh tables when table ID changes --- .../backend/DataTable/DataTable.svelte | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 88f754b254..e822692da5 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -13,22 +13,24 @@ import { fetchTableData } from "helpers/fetchTableData" import { Pagination } from "@budibase/bbui" - let hideAutocolumns = true const data = fetchTableData() + let hideAutocolumns = true $: isUsersTable = $tables.selected?._id === TableNames.USERS $: title = $tables.selected?.name $: schema = $tables.selected?.schema $: type = $tables.selected?.type $: isInternal = type !== "external" + $: fetchTable($tables.selected?._id) - // Fetch data whenever table changes - $: data.update({ - tableId: $tables.selected?._id, - schema, - limit: 10, - paginate: true, - }) + const fetchTable = tableId => { + data.update({ + tableId, + schema, + limit: 10, + paginate: true, + }) + } // Fetch data whenever sorting option changes const onSort = e => { From 39192e4e7f71df44dd01d76475ded1980aa74424 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 23 Sep 2021 21:47:22 +0100 Subject: [PATCH 29/88] add base wizard for datasources --- .../modals/CreateDatasourceModal.svelte | 207 ++++++++++++------ .../modals/DatasourceDetailsModal.svelte | 51 +++++ packages/builder/src/constants/index.js | 14 ++ .../app/[application]/data/_layout.svelte | 8 +- .../app/[application]/data/index.svelte | 11 +- 5 files changed, 224 insertions(+), 67 deletions(-) create mode 100644 packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte index 9cdd893230..bf8585d401 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte @@ -1,74 +1,159 @@ - - + + - - - - - + + + + + + + { + chooseNextModal() + }} + > + All apps need data. You can connect to a data source below, or add data + to your app using Budibase's built-in database - it's simple! + + + +
selectIntegration(INTERNAL)} + class="item hoverable" + > +
+ + + Budibase DB (no prior data required) +
+
+ + +
+ {#each Object.entries(integrations).filter(([key]) => key !== INTERNAL) as [integrationType, schema]} +
selectIntegration(integrationType)} + class="item hoverable" + > +
+ + + + {schema.name || IntegrationNames[integrationType]} +
+
+ {/each} +
+
+
+
+ + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte new file mode 100644 index 0000000000..dcdd2da497 --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte @@ -0,0 +1,51 @@ + + + saveDatasource()} + confirmText="Continue" + cancelText="Start from scratch" + size="M" +> + + + + diff --git a/packages/builder/src/constants/index.js b/packages/builder/src/constants/index.js index a892eb2129..c0d283b0ea 100644 --- a/packages/builder/src/constants/index.js +++ b/packages/builder/src/constants/index.js @@ -15,6 +15,20 @@ export const AppStatus = { DEPLOYED: "published", } +export const IntegrationNames = { + POSTGRES: "PostgreSQL", + MONGODB: "MongoDB", + COUCHDB: "CouchDB", + S3: "S3", + MYSQL: "MySQL", + REST: "REST", + DYNAMODB: "DynamoDB", + ELASTICSEARCH: "ElasticSearch", + SQL_SERVER: "SQL Server", + AIRTABLE: "Airtable", + ARANGODB: "ArangoDB", +} + // fields on the user table that cannot be edited export const UNEDITABLE_USER_FIELDS = [ "email", diff --git a/packages/builder/src/pages/builder/app/[application]/data/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/_layout.svelte index 5202bd45f2..f321a2c422 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/_layout.svelte @@ -1,12 +1,14 @@ +{#if !setupComplete} + +{/if} From 468a7caa07386f2aef45f22b0d124eea8e416cd0 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 23 Sep 2021 22:02:35 +0100 Subject: [PATCH 30/88] fix flow of wizard --- .../app/[application]/data/index.svelte | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/data/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/index.svelte index d3b5cff4f2..2d1d94d267 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/index.svelte @@ -1,13 +1,25 @@ -{#if !setupComplete} - -{/if} + From af5280fa363a98e33058e3094d553b09ef918608 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 24 Sep 2021 10:01:53 +0100 Subject: [PATCH 31/88] fetch tables for datasource plus --- .../modals/DatasourceDetailsModal.svelte | 28 +++++++++++++++---- .../app/[application]/data/index.svelte | 5 +--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte index dcdd2da497..6d494378b3 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte @@ -1,11 +1,10 @@ saveDatasource()} - confirmText="Continue" - cancelText="Start from scratch" + confirmText={integration.plus + ? "Fetch tables from database" + : "Save and continue to query"} + cancelText="Back" size="M" > (x._id = "bb_internal")).entities.length > 1 || $datasources.list.length >= 1 - $: console.log($datasources.list.length >= 1) - $: console.log( - $datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 - ) + onMount(() => { if (!setupComplete) { modal.show() From 29551c4621bb70d7a6666be29679ec93446ae00d Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 24 Sep 2021 10:12:30 +0100 Subject: [PATCH 32/88] fix naming of datasources --- .../DatasourceNavigator/modals/DatasourceDetailsModal.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte index 6d494378b3..74c176c534 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte @@ -8,7 +8,7 @@ function prepareData() { let datasource = {} let existingTypeCount = $datasources.list.filter( - ds => ds.type == integration.type + ds => ds.source == integration.type ).length let baseName = IntegrationNames[integration.type] @@ -31,8 +31,8 @@ if (integration.plus) { updateDatasourceSchema(resp) } - await datasources.fetch() await datasources.select(resp["_id"]) + console.log($datasources) notifications.success(`Datasource updated successfully.`) } catch (err) { notifications.error(`Error saving datasource: ${err}`) From a833df7771cc359920d7fde31de28f15ac9d1954 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 24 Sep 2021 10:19:48 +0100 Subject: [PATCH 33/88] redirect to created datasource --- .../modals/DatasourceDetailsModal.svelte | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte index 74c176c534..130037ac23 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte @@ -1,10 +1,12 @@ saveDatasource()} confirmText={integration.plus ? "Fetch tables from database" @@ -65,6 +65,12 @@ cancelText="Back" size="M" > + + Connect your database to Budibase using the config below. + + + Date: Fri, 24 Sep 2021 16:13:25 +0100 Subject: [PATCH 36/88] Add a refresh action to common table searching logic --- .../backend/DataTable/DataTable.svelte | 3 ++- packages/builder/src/helpers/fetchTableData.js | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index e822692da5..308a57c394 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -21,7 +21,8 @@ $: schema = $tables.selected?.schema $: type = $tables.selected?.type $: isInternal = type !== "external" - $: fetchTable($tables.selected?._id) + $: id = $tables.selected?._id + $: fetchTable(id) const fetchTable = tableId => { data.update({ diff --git a/packages/builder/src/helpers/fetchTableData.js b/packages/builder/src/helpers/fetchTableData.js index ff7d61519f..76bd43d89f 100644 --- a/packages/builder/src/helpers/fetchTableData.js +++ b/packages/builder/src/helpers/fetchTableData.js @@ -22,6 +22,7 @@ export const fetchTableData = opts => { // Local non-observable state let query let sortType + let lastBookmark // Local observable state const store = writable({ @@ -43,6 +44,7 @@ export const fetchTableData = opts => { }) const fetchPage = async bookmark => { + lastBookmark = bookmark const { tableId, limit, sortColumn, sortOrder, paginate } = options store.update($store => ({ ...$store, loading: true })) const res = await API.post(`/api/${options.tableId}/search`, { @@ -126,7 +128,7 @@ export const fetchTableData = opts => { // Fetches the next page of data const nextPage = async () => { const state = get(derivedStore) - if (!options.paginate || !state.hasNextPage) { + if (state.loading || !options.paginate || !state.hasNextPage) { return } @@ -151,7 +153,7 @@ export const fetchTableData = opts => { // Fetches the previous page of data const prevPage = async () => { const state = get(derivedStore) - if (!options.paginate || !state.hasPrevPage) { + if (state.loading || !options.paginate || !state.hasPrevPage) { return } @@ -179,6 +181,16 @@ export const fetchTableData = opts => { await fetchData() } + // Loads the same page again + const refresh = async () => { + if (get(store).loading) { + return + } + console.log("refresh") + const page = await fetchPage(lastBookmark) + store.update($store => ({ ...$store, rows: page.rows })) + } + // Initially fetch data but don't bother waiting for the result fetchData() @@ -188,5 +200,6 @@ export const fetchTableData = opts => { nextPage, prevPage, update, + refresh, } } From dad6412271d37e2359efa1d640a5514f7d85eab5 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 27 Sep 2021 09:59:56 +0100 Subject: [PATCH 37/88] trigger internal table modal on modal cancel --- packages/bbui/src/Modal/ModalContent.svelte | 11 ++++++++++- .../modals/CreateDatasourceModal.svelte | 5 ++--- .../modals/DatasourceConfigModal.svelte | 12 ++++++++++-- .../builder/app/[application]/data/index.svelte | 8 +++++++- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/packages/bbui/src/Modal/ModalContent.svelte b/packages/bbui/src/Modal/ModalContent.svelte index 678a813a61..09cc4f6c52 100644 --- a/packages/bbui/src/Modal/ModalContent.svelte +++ b/packages/bbui/src/Modal/ModalContent.svelte @@ -14,6 +14,7 @@ export let showConfirmButton = true export let showCloseIcon = true export let onConfirm = undefined + export let onCancel = undefined export let disabled = false export let showDivider = true @@ -28,6 +29,14 @@ } loading = false } + + async function close() { + loading = true + if (!onCancel || (await onCancel()) !== false) { + cancel() + } + loading = false + }
{#if showCancelButton} - + {/if} {#if showConfirmButton}
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 9221cbf083..e29d7d5232 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -27,15 +27,20 @@ return datasource } async function saveDatasource() { + let success = true try { // Create datasource const resp = await datasources.save(prepareData()) if (integration.plus) { - updateDatasourceSchema(resp) + fetchedSchema = updateDatasourceSchema(resp) } + + if (!fetchedSchema) { + return false + } + await datasources.select(resp._id) - $goto(`./datasource/${resp._id}`) notifications.success(`Datasource updated successfully.`) analytics.captureEvent(Events.DATASOURCE.CREATED, { name: resp.name, @@ -43,6 +48,7 @@ }) } catch (err) { notifications.error(`Error saving datasource: ${err}`) + return false } } @@ -50,8 +56,10 @@ try { await datasources.updateSchema(datasourceJson) await tables.fetch() + return true } catch (err) { notifications.error(`Error updating datasource schema: ${err}`) + return false } } diff --git a/packages/builder/src/pages/builder/app/[application]/data/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/index.svelte index ca457cd1aa..873f721a59 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/index.svelte @@ -7,7 +7,13 @@ let modal $: setupComplete = $datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 || - $datasources.list.length >= 1 + $datasources.list.length > 1 + + $: console.log( + $datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 + ) + $: console.log($datasources.list.length >= 1) + $: console.log($datasources.list) onMount(() => { if (!setupComplete) { From 7121b0a7c83e228e63376c3e2526c5476a7497e2 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 27 Sep 2021 10:04:01 +0100 Subject: [PATCH 38/88] fix layout of config modal --- .../modals/DatasourceConfigModal.svelte | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index e29d7d5232..9221cbf083 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -27,20 +27,15 @@ return datasource } async function saveDatasource() { - let success = true try { // Create datasource const resp = await datasources.save(prepareData()) if (integration.plus) { - fetchedSchema = updateDatasourceSchema(resp) + updateDatasourceSchema(resp) } - - if (!fetchedSchema) { - return false - } - await datasources.select(resp._id) + $goto(`./datasource/${resp._id}`) notifications.success(`Datasource updated successfully.`) analytics.captureEvent(Events.DATASOURCE.CREATED, { name: resp.name, @@ -48,7 +43,6 @@ }) } catch (err) { notifications.error(`Error saving datasource: ${err}`) - return false } } @@ -56,10 +50,8 @@ try { await datasources.updateSchema(datasourceJson) await tables.fetch() - return true } catch (err) { notifications.error(`Error updating datasource schema: ${err}`) - return false } } From 496e079d8334c1c88418e2e6ec54984ae1f5f675 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 27 Sep 2021 12:51:32 +0100 Subject: [PATCH 39/88] Remove log statement --- packages/builder/src/helpers/fetchTableData.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/builder/src/helpers/fetchTableData.js b/packages/builder/src/helpers/fetchTableData.js index 76bd43d89f..8c9e9f1ea7 100644 --- a/packages/builder/src/helpers/fetchTableData.js +++ b/packages/builder/src/helpers/fetchTableData.js @@ -186,7 +186,6 @@ export const fetchTableData = opts => { if (get(store).loading) { return } - console.log("refresh") const page = await fetchPage(lastBookmark) store.update($store => ({ ...$store, rows: page.rows })) } From ec7cf96fd9ceccfa003f151c1ce1fdbdaa675232 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 27 Sep 2021 12:59:49 +0100 Subject: [PATCH 40/88] Move all lucene logic into central builder helpers file --- .../SetupPanel/AutomationBlockSetup.svelte | 2 +- .../builder/src/helpers/fetchTableData.js | 2 +- packages/builder/src/helpers/lucene.js | 187 ++++++++++++++++++ packages/client/rollup.config.js | 4 + .../client/src/components/ClientApp.svelte | 2 +- .../src/components/app/DataProvider.svelte | 2 +- packages/client/src/stores/state.js | 2 +- packages/client/src/utils/conditions.js | 2 +- packages/client/src/utils/lucene.js | 179 ----------------- 9 files changed, 197 insertions(+), 185 deletions(-) delete mode 100644 packages/client/src/utils/lucene.js diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index adc22e5daf..ff52c7d11a 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -24,7 +24,7 @@ import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" import FilterDrawer from "components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte" // need the client lucene builder to convert to the structure API expects - import { buildLuceneQuery } from "../../../../../client/src/utils/lucene" + import { buildLuceneQuery } from "helpers/lucene" export let block export let webhookModal diff --git a/packages/builder/src/helpers/fetchTableData.js b/packages/builder/src/helpers/fetchTableData.js index 8c9e9f1ea7..43ecd464c9 100644 --- a/packages/builder/src/helpers/fetchTableData.js +++ b/packages/builder/src/helpers/fetchTableData.js @@ -1,6 +1,6 @@ import { writable, derived, get } from "svelte/store" import * as API from "builderStore/api" -import { buildLuceneQuery } from "../../../client/src/utils/lucene" +import { buildLuceneQuery } from "helpers/lucene" const defaultOptions = { tableId: null, diff --git a/packages/builder/src/helpers/lucene.js b/packages/builder/src/helpers/lucene.js index 18692359e4..5225467d7b 100644 --- a/packages/builder/src/helpers/lucene.js +++ b/packages/builder/src/helpers/lucene.js @@ -1,3 +1,186 @@ +/** + * Builds a lucene JSON query from the filter structure generated in the builder + * @param filter the builder filter structure + */ +export const buildLuceneQuery = filter => { + let query = { + string: {}, + fuzzy: {}, + range: {}, + equal: {}, + notEqual: {}, + empty: {}, + notEmpty: {}, + contains: {}, + notContains: {}, + } + if (Array.isArray(filter)) { + filter.forEach(expression => { + let { operator, field, type, value } = expression + // Parse all values into correct types + if (type === "datetime" && value) { + value = new Date(value).toISOString() + } + if (type === "number") { + value = parseFloat(value) + } + if (type === "boolean") { + value = `${value}`?.toLowerCase() === "true" + } + if (operator.startsWith("range")) { + if (!query.range[field]) { + query.range[field] = { + low: + type === "number" + ? Number.MIN_SAFE_INTEGER + : "0000-00-00T00:00:00.000Z", + high: + type === "number" + ? Number.MAX_SAFE_INTEGER + : "9999-00-00T00:00:00.000Z", + } + } + if (operator === "rangeLow" && value != null && value !== "") { + query.range[field].low = value + } else if (operator === "rangeHigh" && value != null && value !== "") { + query.range[field].high = value + } + } else if (query[operator]) { + if (type === "boolean") { + // Transform boolean filters to cope with null. + // "equals false" needs to be "not equals true" + // "not equals false" needs to be "equals true" + if (operator === "equal" && value === false) { + query.notEqual[field] = true + } else if (operator === "notEqual" && value === false) { + query.equal[field] = true + } else { + query[operator][field] = value + } + } else { + query[operator][field] = value + } + } + }) + } + + return query +} + +/** + * Performs a client-side lucene search on an array of data + * @param docs the data + * @param query the JSON lucene query + */ +export const luceneQuery = (docs, query) => { + if (!query) { + return docs + } + + // Iterates over a set of filters and evaluates a fail function against a doc + const match = (type, failFn) => doc => { + const filters = Object.entries(query[type] || {}) + for (let i = 0; i < filters.length; i++) { + if (failFn(filters[i][0], filters[i][1], doc)) { + return false + } + } + return true + } + + // Process a string match (fails if the value does not start with the string) + const stringMatch = match("string", (key, value, doc) => { + return !doc[key] || !doc[key].startsWith(value) + }) + + // Process a fuzzy match (treat the same as starts with when running locally) + const fuzzyMatch = match("fuzzy", (key, value, doc) => { + return !doc[key] || !doc[key].startsWith(value) + }) + + // Process a range match + const rangeMatch = match("range", (key, value, doc) => { + return !doc[key] || doc[key] < value.low || doc[key] > value.high + }) + + // Process an equal match (fails if the value is different) + const equalMatch = match("equal", (key, value, doc) => { + return value != null && value !== "" && doc[key] !== value + }) + + // Process a not-equal match (fails if the value is the same) + const notEqualMatch = match("notEqual", (key, value, doc) => { + return value != null && value !== "" && doc[key] === value + }) + + // Process an empty match (fails if the value is not empty) + const emptyMatch = match("empty", (key, value, doc) => { + return doc[key] != null && doc[key] !== "" + }) + + // Process a not-empty match (fails is the value is empty) + const notEmptyMatch = match("notEmpty", (key, value, doc) => { + return doc[key] == null || doc[key] === "" + }) + + // Match a document against all criteria + const docMatch = doc => { + return ( + stringMatch(doc) && + fuzzyMatch(doc) && + rangeMatch(doc) && + equalMatch(doc) && + notEqualMatch(doc) && + emptyMatch(doc) && + notEmptyMatch(doc) + ) + } + + // Process all docs + return docs.filter(docMatch) +} + +/** + * Performs a client-side sort from the equivalent server-side lucene sort + * parameters. + * @param docs the data + * @param sort the sort column + * @param sortOrder the sort order ("ascending" or "descending") + * @param sortType the type of sort ("string" or "number") + */ +export const luceneSort = (docs, sort, sortOrder, sortType = "string") => { + if (!sort || !sortOrder || !sortType) { + return docs + } + const parse = sortType === "string" ? x => `${x}` : x => parseFloat(x) + return docs.slice().sort((a, b) => { + const colA = parse(a[sort]) + const colB = parse(b[sort]) + if (sortOrder === "Descending") { + return colA > colB ? -1 : 1 + } else { + return colA > colB ? 1 : -1 + } + }) +} + +/** + * Limits the specified docs to the specified number of rows from the equivalent + * server-side lucene limit parameters. + * @param docs the data + * @param limit the number of docs to limit to + */ +export const luceneLimit = (docs, limit) => { + const numLimit = parseFloat(limit) + if (isNaN(numLimit)) { + return docs + } + return docs.slice(0, numLimit) +} + +/** + * Operator options for lucene queries + */ export const OperatorOptions = { Equals: { value: "equal", @@ -41,6 +224,10 @@ export const OperatorOptions = { }, } +/** + * Returns the valid operator options for a certain data type + * @param type the data type + */ export const getValidOperatorsForType = type => { const Op = OperatorOptions if (type === "string") { diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js index f404f93c4c..a814303069 100644 --- a/packages/client/rollup.config.js +++ b/packages/client/rollup.config.js @@ -58,6 +58,10 @@ export default { find: "sdk", replacement: path.resolve("./src/sdk"), }, + { + find: "builder", + replacement: path.resolve("../builder"), + }, ], }), svelte({ diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 5890c0e2a9..c9c033caa3 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -23,7 +23,7 @@ import SelectionIndicator from "components/preview/SelectionIndicator.svelte" import HoverIndicator from "components/preview/HoverIndicator.svelte" import CustomThemeWrapper from "./CustomThemeWrapper.svelte" - import ErrorSVG from "../../../builder/assets/error.svg" + import ErrorSVG from "builder/assets/error.svg" // Provide contexts setContext("sdk", SDK) diff --git a/packages/client/src/components/app/DataProvider.svelte b/packages/client/src/components/app/DataProvider.svelte index bdc9001445..991c41b77d 100644 --- a/packages/client/src/components/app/DataProvider.svelte +++ b/packages/client/src/components/app/DataProvider.svelte @@ -6,7 +6,7 @@ luceneQuery, luceneSort, luceneLimit, - } from "utils/lucene" + } from "builder/src/helpers/lucene" import Placeholder from "./Placeholder.svelte" export let dataSource diff --git a/packages/client/src/stores/state.js b/packages/client/src/stores/state.js index cb20149de8..ce977c4333 100644 --- a/packages/client/src/stores/state.js +++ b/packages/client/src/stores/state.js @@ -1,5 +1,5 @@ import { writable, get, derived } from "svelte/store" -import { localStorageStore } from "../../../builder/src/builderStore/store/localStorage" +import { localStorageStore } from "builder/src/builderStore/store/localStorage" import { appStore } from "./app" const createStateStore = () => { diff --git a/packages/client/src/utils/conditions.js b/packages/client/src/utils/conditions.js index 964a63d3fd..2791fa169e 100644 --- a/packages/client/src/utils/conditions.js +++ b/packages/client/src/utils/conditions.js @@ -1,4 +1,4 @@ -import { buildLuceneQuery, luceneQuery } from "./lucene" +import { buildLuceneQuery, luceneQuery } from "builder/src/helpers/lucene" export const getActiveConditions = conditions => { if (!conditions?.length) { diff --git a/packages/client/src/utils/lucene.js b/packages/client/src/utils/lucene.js deleted file mode 100644 index 03baa751cc..0000000000 --- a/packages/client/src/utils/lucene.js +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Builds a lucene JSON query from the filter structure generated in the builder - * @param filter the builder filter structure - */ -export const buildLuceneQuery = filter => { - let query = { - string: {}, - fuzzy: {}, - range: {}, - equal: {}, - notEqual: {}, - empty: {}, - notEmpty: {}, - contains: {}, - notContains: {}, - } - if (Array.isArray(filter)) { - filter.forEach(expression => { - let { operator, field, type, value } = expression - // Parse all values into correct types - if (type === "datetime" && value) { - value = new Date(value).toISOString() - } - if (type === "number") { - value = parseFloat(value) - } - if (type === "boolean") { - value = `${value}`?.toLowerCase() === "true" - } - if (operator.startsWith("range")) { - if (!query.range[field]) { - query.range[field] = { - low: - type === "number" - ? Number.MIN_SAFE_INTEGER - : "0000-00-00T00:00:00.000Z", - high: - type === "number" - ? Number.MAX_SAFE_INTEGER - : "9999-00-00T00:00:00.000Z", - } - } - if (operator === "rangeLow" && value != null && value !== "") { - query.range[field].low = value - } else if (operator === "rangeHigh" && value != null && value !== "") { - query.range[field].high = value - } - } else if (query[operator]) { - if (type === "boolean") { - // Transform boolean filters to cope with null. - // "equals false" needs to be "not equals true" - // "not equals false" needs to be "equals true" - if (operator === "equal" && value === false) { - query.notEqual[field] = true - } else if (operator === "notEqual" && value === false) { - query.equal[field] = true - } else { - query[operator][field] = value - } - } else { - query[operator][field] = value - } - } - }) - } - - return query -} - -/** - * Performs a client-side lucene search on an array of data - * @param docs the data - * @param query the JSON lucene query - */ -export const luceneQuery = (docs, query) => { - if (!query) { - return docs - } - - // Iterates over a set of filters and evaluates a fail function against a doc - const match = (type, failFn) => doc => { - const filters = Object.entries(query[type] || {}) - for (let i = 0; i < filters.length; i++) { - if (failFn(filters[i][0], filters[i][1], doc)) { - return false - } - } - return true - } - - // Process a string match (fails if the value does not start with the string) - const stringMatch = match("string", (key, value, doc) => { - return !doc[key] || !doc[key].startsWith(value) - }) - - // Process a fuzzy match (treat the same as starts with when running locally) - const fuzzyMatch = match("fuzzy", (key, value, doc) => { - return !doc[key] || !doc[key].startsWith(value) - }) - - // Process a range match - const rangeMatch = match("range", (key, value, doc) => { - return !doc[key] || doc[key] < value.low || doc[key] > value.high - }) - - // Process an equal match (fails if the value is different) - const equalMatch = match("equal", (key, value, doc) => { - return value != null && value !== "" && doc[key] !== value - }) - - // Process a not-equal match (fails if the value is the same) - const notEqualMatch = match("notEqual", (key, value, doc) => { - return value != null && value !== "" && doc[key] === value - }) - - // Process an empty match (fails if the value is not empty) - const emptyMatch = match("empty", (key, value, doc) => { - return doc[key] != null && doc[key] !== "" - }) - - // Process a not-empty match (fails is the value is empty) - const notEmptyMatch = match("notEmpty", (key, value, doc) => { - return doc[key] == null || doc[key] === "" - }) - - // Match a document against all criteria - const docMatch = doc => { - return ( - stringMatch(doc) && - fuzzyMatch(doc) && - rangeMatch(doc) && - equalMatch(doc) && - notEqualMatch(doc) && - emptyMatch(doc) && - notEmptyMatch(doc) - ) - } - - // Process all docs - return docs.filter(docMatch) -} - -/** - * Performs a client-side sort from the equivalent server-side lucene sort - * parameters. - * @param docs the data - * @param sort the sort column - * @param sortOrder the sort order ("ascending" or "descending") - * @param sortType the type of sort ("string" or "number") - */ -export const luceneSort = (docs, sort, sortOrder, sortType = "string") => { - if (!sort || !sortOrder || !sortType) { - return docs - } - const parse = sortType === "string" ? x => `${x}` : x => parseFloat(x) - return docs.slice().sort((a, b) => { - const colA = parse(a[sort]) - const colB = parse(b[sort]) - if (sortOrder === "Descending") { - return colA > colB ? -1 : 1 - } else { - return colA > colB ? 1 : -1 - } - }) -} - -/** - * Limits the specified docs to the specified number of rows from the equivalent - * server-side lucene limit parameters. - * @param docs the data - * @param limit the number of docs to limit to - */ -export const luceneLimit = (docs, limit) => { - const numLimit = parseFloat(limit) - if (isNaN(numLimit)) { - return docs - } - return docs.slice(0, numLimit) -} From 705088362b5b87a85bb74e230fc66dc016ba812b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 27 Sep 2021 15:36:18 +0100 Subject: [PATCH 41/88] Move lucene logic into builder --- .../backend/DataTable/DataTable.svelte | 20 ++-- .../ConditionalUIDrawer.svelte | 2 +- .../FilterEditor/FilterDrawer.svelte | 2 +- packages/builder/src/constants/lucene.js | 97 ++++++++++++++++++ .../builder/src/helpers/fetchTableData.js | 6 +- packages/builder/src/helpers/lucene.js | 98 ------------------- 6 files changed, 113 insertions(+), 112 deletions(-) create mode 100644 packages/builder/src/constants/lucene.js diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 308a57c394..f8b5abc4cd 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -13,7 +13,7 @@ import { fetchTableData } from "helpers/fetchTableData" import { Pagination } from "@budibase/bbui" - const data = fetchTableData() + const search = fetchTableData() let hideAutocolumns = true $: isUsersTable = $tables.selected?._id === TableNames.USERS @@ -25,7 +25,7 @@ $: fetchTable(id) const fetchTable = tableId => { - data.update({ + search.update({ tableId, schema, limit: 10, @@ -35,7 +35,7 @@ // Fetch data whenever sorting option changes const onSort = e => { - data.update({ + search.update({ sortColumn: e.detail.column, sortOrder: e.detail.order, }) @@ -48,9 +48,9 @@ {schema} {type} tableId={$tables.selected?._id} - data={$data.rows} + data={$search.rows} bind:hideAutocolumns - loading={$data.loading} + loading={$search.loading} on:sort={onSort} allowEditing disableSorting @@ -79,11 +79,11 @@
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte index 638fd44de6..9f0d5086f6 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte @@ -12,7 +12,7 @@ import { dndzone } from "svelte-dnd-action" import { generate } from "shortid" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" - import { OperatorOptions, getValidOperatorsForType } from "helpers/lucene" + import { OperatorOptions, getValidOperatorsForType } from "constants/lucene" import { selectedComponent, store } from "builderStore" import { getComponentForSettingType } from "./componentSettings" import PropertyControl from "./PropertyControl.svelte" diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte index d6bfadb150..eddfd9b997 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte @@ -13,7 +13,7 @@ import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import BindingPanel from "components/common/bindings/BindingPanel.svelte" import { generate } from "shortid" - import { getValidOperatorsForType, OperatorOptions } from "helpers/lucene" + import { getValidOperatorsForType, OperatorOptions } from "constants/lucene" export let schemaFields export let filters = [] diff --git a/packages/builder/src/constants/lucene.js b/packages/builder/src/constants/lucene.js new file mode 100644 index 0000000000..00da0c29bc --- /dev/null +++ b/packages/builder/src/constants/lucene.js @@ -0,0 +1,97 @@ +/** + * Operator options for lucene queries + */ +export const OperatorOptions = { + Equals: { + value: "equal", + label: "Equals", + }, + NotEquals: { + value: "notEqual", + label: "Not equals", + }, + Empty: { + value: "empty", + label: "Is empty", + }, + NotEmpty: { + value: "notEmpty", + label: "Is not empty", + }, + StartsWith: { + value: "string", + label: "Starts with", + }, + Like: { + value: "fuzzy", + label: "Like", + }, + MoreThan: { + value: "rangeLow", + label: "More than", + }, + LessThan: { + value: "rangeHigh", + label: "Less than", + }, + Contains: { + value: "equal", + label: "Contains", + }, + NotContains: { + value: "notEqual", + label: "Does Not Contain", + }, +} + +/** + * Returns the valid operator options for a certain data type + * @param type the data type + */ +export const getValidOperatorsForType = type => { + const Op = OperatorOptions + if (type === "string") { + return [ + Op.Equals, + Op.NotEquals, + Op.StartsWith, + Op.Like, + Op.Empty, + Op.NotEmpty, + ] + } else if (type === "number") { + return [ + Op.Equals, + Op.NotEquals, + Op.MoreThan, + Op.LessThan, + Op.Empty, + Op.NotEmpty, + ] + } else if (type === "options") { + return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] + } else if (type === "array") { + return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty] + } else if (type === "boolean") { + return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] + } else if (type === "longform") { + return [ + Op.Equals, + Op.NotEquals, + Op.StartsWith, + Op.Like, + Op.Empty, + Op.NotEmpty, + ] + } else if (type === "datetime") { + return [ + Op.Equals, + Op.NotEquals, + Op.MoreThan, + Op.LessThan, + Op.Empty, + Op.NotEmpty, + ] + } + return [] +} diff --git a/packages/builder/src/helpers/fetchTableData.js b/packages/builder/src/helpers/fetchTableData.js index 43ecd464c9..5ef3bc1076 100644 --- a/packages/builder/src/helpers/fetchTableData.js +++ b/packages/builder/src/helpers/fetchTableData.js @@ -1,6 +1,8 @@ +// Do not use any aliased imports in common files, as these will be bundled +// by multiple bundlers which may not be able to resolve them import { writable, derived, get } from "svelte/store" -import * as API from "builderStore/api" -import { buildLuceneQuery } from "helpers/lucene" +import * as API from "../builderStore/api" +import { buildLuceneQuery } from "./lucene" const defaultOptions = { tableId: null, diff --git a/packages/builder/src/helpers/lucene.js b/packages/builder/src/helpers/lucene.js index 5225467d7b..03baa751cc 100644 --- a/packages/builder/src/helpers/lucene.js +++ b/packages/builder/src/helpers/lucene.js @@ -177,101 +177,3 @@ export const luceneLimit = (docs, limit) => { } return docs.slice(0, numLimit) } - -/** - * Operator options for lucene queries - */ -export const OperatorOptions = { - Equals: { - value: "equal", - label: "Equals", - }, - NotEquals: { - value: "notEqual", - label: "Not equals", - }, - Empty: { - value: "empty", - label: "Is empty", - }, - NotEmpty: { - value: "notEmpty", - label: "Is not empty", - }, - StartsWith: { - value: "string", - label: "Starts with", - }, - Like: { - value: "fuzzy", - label: "Like", - }, - MoreThan: { - value: "rangeLow", - label: "More than", - }, - LessThan: { - value: "rangeHigh", - label: "Less than", - }, - Contains: { - value: "equal", - label: "Contains", - }, - NotContains: { - value: "notEqual", - label: "Does Not Contain", - }, -} - -/** - * Returns the valid operator options for a certain data type - * @param type the data type - */ -export const getValidOperatorsForType = type => { - const Op = OperatorOptions - if (type === "string") { - return [ - Op.Equals, - Op.NotEquals, - Op.StartsWith, - Op.Like, - Op.Empty, - Op.NotEmpty, - ] - } else if (type === "number") { - return [ - Op.Equals, - Op.NotEquals, - Op.MoreThan, - Op.LessThan, - Op.Empty, - Op.NotEmpty, - ] - } else if (type === "options") { - return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] - } else if (type === "array") { - return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty] - } else if (type === "boolean") { - return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] - } else if (type === "longform") { - return [ - Op.Equals, - Op.NotEquals, - Op.StartsWith, - Op.Like, - Op.Empty, - Op.NotEmpty, - ] - } else if (type === "datetime") { - return [ - Op.Equals, - Op.NotEquals, - Op.MoreThan, - Op.LessThan, - Op.Empty, - Op.NotEmpty, - ] - } - return [] -} From f5f8e25c9f58b743b6de4e879ada342520d6f319 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 27 Sep 2021 18:25:19 +0100 Subject: [PATCH 42/88] Fix huge amount of bugs with data UI state, URL parameters and state/URL sync --- .../DatasourceNavigator.svelte | 76 ++++++++++++++----- .../[query]/_layout.svelte | 12 +++ .../[selectedDatasource]/_layout.svelte | 2 +- .../data/datasource/_layout.svelte | 13 ---- .../builder/src/stores/backend/queries.js | 9 +-- packages/builder/src/stores/backend/views.js | 1 + 6 files changed, 76 insertions(+), 37 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index 6ba8e4042f..3c6fa83c01 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -1,9 +1,9 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte index 4fa864ce7a..6d802df2e9 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte @@ -1 +1,13 @@ + + diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/_layout.svelte index 13f8719594..f48be08fd6 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/_layout.svelte @@ -2,7 +2,7 @@ import { params } from "@roxi/routify" import { datasources } from "stores/backend" - if ($params.selectedDatasource) { + if ($params.selectedDatasource && !$params.query) { const datasource = $datasources.list.find( m => m._id === $params.selectedDatasource ) diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/_layout.svelte index d05aa882ad..4fa864ce7a 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/_layout.svelte @@ -1,14 +1 @@ - - diff --git a/packages/builder/src/stores/backend/queries.js b/packages/builder/src/stores/backend/queries.js index 2eeae29b9d..020a0c9420 100644 --- a/packages/builder/src/stores/backend/queries.js +++ b/packages/builder/src/stores/backend/queries.js @@ -1,5 +1,5 @@ import { writable, get } from "svelte/store" -import { datasources, integrations, tables } from "./" +import { datasources, integrations, tables, views } from "./" import api from "builderStore/api" export function createQueriesStore() { @@ -55,10 +55,9 @@ export function createQueriesStore() { }, select: query => { update(state => ({ ...state, selected: query._id })) - tables.update(state => ({ - ...state, - selected: null, - })) + views.unselect() + tables.unselect() + datasources.unselect() }, unselect: () => { update(state => ({ ...state, selected: null })) diff --git a/packages/builder/src/stores/backend/views.js b/packages/builder/src/stores/backend/views.js index 0b15d18fa5..14c7bf92a4 100644 --- a/packages/builder/src/stores/backend/views.js +++ b/packages/builder/src/stores/backend/views.js @@ -16,6 +16,7 @@ export function createViewsStore() { ...state, selected: view, })) + tables.unselect() queries.unselect() datasources.unselect() }, From 9f0d8a91b71e0df6ca86187b51e9c80568b67b16 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 27 Sep 2021 19:12:41 +0100 Subject: [PATCH 43/88] Putting together cloud export and import functionality, still need to test, but basic concept there. --- packages/auth/src/tenancy/tenancy.js | 7 +- packages/client/yarn.lock | 975 +----------------- packages/server/package.json | 1 + .../server/src/api/controllers/application.js | 12 +- packages/server/src/api/controllers/cloud.js | 69 ++ packages/server/src/api/routes/cloud.js | 13 + .../server/src/utilities/fileSystem/index.js | 65 +- packages/server/yarn.lock | 459 ++------- 8 files changed, 256 insertions(+), 1345 deletions(-) create mode 100644 packages/server/src/api/controllers/cloud.js create mode 100644 packages/server/src/api/routes/cloud.js diff --git a/packages/auth/src/tenancy/tenancy.js b/packages/auth/src/tenancy/tenancy.js index ebd573496c..668bc010ba 100644 --- a/packages/auth/src/tenancy/tenancy.js +++ b/packages/auth/src/tenancy/tenancy.js @@ -73,7 +73,7 @@ exports.tryAddTenant = async (tenantId, userId, email) => { await Promise.all(promises) } -exports.getGlobalDB = (tenantId = null) => { +exports.getGlobalDBName = (tenantId = null) => { // tenant ID can be set externally, for example user API where // new tenants are being created, this may be the case if (!tenantId) { @@ -81,13 +81,16 @@ exports.getGlobalDB = (tenantId = null) => { } let dbName - if (tenantId === DEFAULT_TENANT_ID) { dbName = StaticDatabases.GLOBAL.name } else { dbName = `${tenantId}${SEPARATOR}${StaticDatabases.GLOBAL.name}` } + return dbName +} +exports.getGlobalDB = (tenantId = null) => { + const dbName = exports.getGlobalDBName(tenantId) return getDB(dbName) } diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index 1e2c654b21..635f97b107 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -28,10 +28,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@budibase/bbui@^0.9.125-alpha.17": - version "0.9.133" - resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.133.tgz#91a2fb24abaaf91d2cb1e00eb51c493c1290f9ad" - integrity sha512-xbMmc/hee1QRNW7TrbGUBmLr1hMHXqUDA6rdl9N2PGfHFuFWbqlD8PWYanHmLevVet+CjkuKGPSbBghFK2pQyQ== +"@budibase/bbui@^0.9.139": + version "0.9.142" + resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.142.tgz#7edbda7967c9e5dfc96e5be5231656e5aab8d0e3" + integrity sha512-m2YlqqH87T4RwqD/oGhH6twHIgvFv4oUMEhKpkgLsbxjXVLVD0OOF7WqjpDnSa4khVQaixjdkI/Jiw2qhBUSaA== dependencies: "@adobe/spectrum-css-workflow-icons" "^1.2.1" "@spectrum-css/actionbutton" "^1.0.1" @@ -77,44 +77,23 @@ svelte-flatpickr "^3.1.0" svelte-portal "^1.0.0" -"@budibase/handlebars-helpers@^0.11.4": - version "0.11.5" - resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.5.tgz#e9cc90a44e94ad536992cf10906829b633e94bc5" - integrity sha512-ZxpyNtTHxS8Y+yTicbgWvYDAydooUSjOf3Y+wmTE2d4NpDgO0g0IjepLfZV+KASv9XBr//ylJdjE4hClX9NTFw== +"@budibase/standard-components@^0.9.139": + version "0.9.139" + resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.139.tgz#cf8e2b759ae863e469e50272b3ca87f2827e66e3" + integrity sha512-Av0u9Eq2jerjhG6Atta+c0mOQGgE5K0QI3cm+8s/3Vki6/PXkO1YL5Alo3BOn9ayQAVZ/xp4rtZPuN/rzRibHw== dependencies: - array-sort "^1.0.0" - define-property "^2.0.2" - extend-shallow "^3.0.2" - "falsey" "^1.0.0" - for-in "^1.0.2" - get-object "^0.2.0" - get-value "^3.0.1" - handlebars "^4.7.7" - handlebars-utils "^1.0.6" - has-value "^2.0.2" - helper-date "^1.0.1" - helper-markdown "^1.0.0" - helper-md "^0.2.2" - html-tag "^2.0.0" - is-even "^1.0.0" - is-glob "^4.0.1" - kind-of "^6.0.3" - micromatch "^3.1.5" - relative "^3.0.2" - striptags "^3.1.1" - to-gfm-code-block "^0.1.1" - year "^0.2.1" - -"@budibase/string-templates@^0.9.125-alpha.17": - version "0.9.133" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.133.tgz#221d81e080dc4485dcffa989d16e2bbed39f9055" - integrity sha512-SMHcSPwHYdAqol9YCcMoYawp5/ETr9TqGZCUsL+hUUq+LritPwu/miQ++SVvRTQbOR7Mker0S9LO3H8mwYkW8w== - dependencies: - "@budibase/handlebars-helpers" "^0.11.4" - dayjs "^1.10.4" - handlebars "^4.7.6" - handlebars-utils "^1.0.6" - lodash "^4.17.20" + "@budibase/bbui" "^0.9.139" + "@spectrum-css/button" "^3.0.3" + "@spectrum-css/card" "^3.0.3" + "@spectrum-css/divider" "^1.0.3" + "@spectrum-css/link" "^3.1.3" + "@spectrum-css/page" "^3.0.1" + "@spectrum-css/typography" "^3.0.2" + "@spectrum-css/vars" "^3.0.1" + apexcharts "^3.22.1" + dayjs "^1.10.5" + svelte-apexcharts "^1.0.2" + svelte-flatpickr "^3.1.0" "@rollup/plugin-alias@^3.1.5": version "3.1.5" @@ -474,42 +453,13 @@ apexcharts@^3.19.2, apexcharts@^3.22.1: svg.resize.js "^1.4.3" svg.select.js "^3.0.1" -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-sort@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" - integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== - dependencies: - default-compare "^1.0.0" - get-value "^2.0.6" - kind-of "^5.0.2" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -532,28 +482,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autolinker@~0.28.0: - version "0.28.1" - resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.28.1.tgz#0652b491881879f0775dace0cdca3233942a4e47" - integrity sha1-BlK0kYgYefB3XazgzcoyM5QqTkc= - dependencies: - gulp-header "^1.7.1" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -569,19 +502,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -624,22 +544,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -744,21 +648,6 @@ builtin-modules@^3.1.0: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -836,16 +725,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - clone@~0.1.9: version "0.1.19" resolved "https://registry.yarnpkg.com/clone/-/clone-0.1.19.tgz#613fb68639b26a494ac53253e15b1a6bd88ada85" @@ -860,14 +739,6 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -930,11 +801,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -950,18 +816,13 @@ concat-stream@^1.4.4: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-with-sourcemaps@*, concat-with-sourcemaps@^1.1.0: +concat-with-sourcemaps@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== dependencies: source-map "^0.6.1" -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1198,13 +1059,6 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date.js@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda" - integrity sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw== - dependencies: - debug "~3.1.0" - dayjs@^1.10.4: version "1.10.7" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" @@ -1215,30 +1069,11 @@ dayjs@^1.10.5: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== -debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - decimal.js@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1249,13 +1084,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -default-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - deferred-leveldown@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-0.2.0.tgz#2cef1f111e1c57870d8bbb8af2650e587cd2f5b4" @@ -1270,28 +1098,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1385,11 +1191,6 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -ent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -1515,53 +1316,11 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -1572,11 +1331,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -"falsey@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/falsey/-/falsey-1.0.0.tgz#71bdd775c24edad9f2f5c015ce8be24400bb5d7d" - integrity sha512-zMDNZ/Ipd8MY0+346CPvhzP1AsiVyNfTOayJza4reAIWf72xbkuFUDcJNxSAsQE1b9Bu0wijKb8Ngnh/a7fI5w== - fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1592,26 +1346,11 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - flatpickr@^4.5.2: version "4.6.9" resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.9.tgz#9a13383e8a6814bda5d232eae3fcdccb97dc1499" integrity sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - foreach@~2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -1631,18 +1370,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -1690,26 +1417,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-object@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/get-object/-/get-object-0.2.0.tgz#d92ff7d5190c64530cda0543dac63a3d47fe8c0c" - integrity sha1-2S/31RkMZFMM2gVD2sY6PUf+jAw= - dependencies: - is-number "^2.0.2" - isobject "^0.2.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -get-value@^3.0.0, get-value@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-3.0.1.tgz#5efd2a157f1d6a516d7524e124ac52d0a39ef5a8" - integrity sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA== - dependencies: - isobject "^3.0.1" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1734,35 +1441,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -gulp-header@^1.7.1: - version "1.8.12" - resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" - integrity sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ== - dependencies: - concat-with-sourcemaps "*" - lodash.template "^4.4.0" - through2 "^2.0.0" - -handlebars-utils@^1.0.2, handlebars-utils@^1.0.4, handlebars-utils@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/handlebars-utils/-/handlebars-utils-1.0.6.tgz#cb9db43362479054782d86ffe10f47abc76357f9" - integrity sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw== - dependencies: - kind-of "^6.0.0" - typeof-article "^0.1.1" - -handlebars@^4.7.6, handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -1796,52 +1474,6 @@ has-symbols@^1.0.1, has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-value@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-2.0.2.tgz#d0f12e8780ba8e90e66ad1a21c707fdb67c25658" - integrity sha512-ybKOlcRsK2MqrM3Hmz/lQxXHZ6ejzSPzpNabKB45jb5qDgJvKPa3SdapTsTLwEb9WltgWpOmNax7i+DzNOk4TA== - dependencies: - get-value "^3.0.0" - has-values "^2.0.1" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has-values@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-2.0.1.tgz#3876200ff86d8a8546a9264a952c17d5fc17579d" - integrity sha512-+QdH3jOmq9P8GfdjFg0eJudqx1FqU62NQJ4P16rOEHeRdl7ckgwn6uqQjzYE0ZoHVV/e5E2esuJ5Gl5+HUW19w== - dependencies: - kind-of "^6.0.2" - has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1866,44 +1498,11 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -helper-date@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/helper-date/-/helper-date-1.0.1.tgz#12fedea3ad8e44a7ca4c4efb0ff4104a5120cffb" - integrity sha512-wU3VOwwTJvGr/w5rZr3cprPHO+hIhlblTJHD6aFBrKLuNbf4lAmkawd2iK3c6NbJEvY7HAmDpqjOFSI5/+Ey2w== - dependencies: - date.js "^0.3.1" - handlebars-utils "^1.0.4" - moment "^2.18.1" - -helper-markdown@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/helper-markdown/-/helper-markdown-1.0.0.tgz#ee7e9fc554675007d37eb90f7853b13ce74f3e10" - integrity sha512-AnDqMS4ejkQK0MXze7pA9TM3pu01ZY+XXsES6gEE0RmCGk5/NIfvTn0NmItfyDOjRAzyo9z6X7YHbHX4PzIvOA== - dependencies: - handlebars-utils "^1.0.2" - highlight.js "^9.12.0" - remarkable "^1.7.1" - -helper-md@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/helper-md/-/helper-md-0.2.2.tgz#c1f59d7e55bbae23362fd8a0e971607aec69d41f" - integrity sha1-wfWdflW7riM2L9ig6XFgeuxp1B8= - dependencies: - ent "^2.2.0" - extend-shallow "^2.0.1" - fs-exists-sync "^0.1.0" - remarkable "^1.6.2" - hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^9.12.0: - version "9.18.5" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" - integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1935,14 +1534,6 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -html-tag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tag/-/html-tag-2.0.0.tgz#36c3bc8d816fd30b570d5764a497a641640c2fed" - integrity sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g== - dependencies: - is-self-closing "^1.0.1" - kind-of "^6.0.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -2037,20 +1628,6 @@ is-absolute-url@^2.0.0: resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -2073,11 +1650,6 @@ is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-callable@^1.1.4, is-callable@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" @@ -2102,79 +1674,16 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-even@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-even/-/is-even-1.0.0.tgz#76b5055fbad8d294a86b6a949015e1c97b717c06" - integrity sha1-drUFX7rY0pSoa2qUkBXhyXtxfAY= - dependencies: - is-odd "^0.1.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" @@ -2190,20 +1699,6 @@ is-number-object@^1.0.4: resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== -is-number@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -2214,20 +1709,6 @@ is-object@~0.1.2: resolved "https://registry.yarnpkg.com/is-object/-/is-object-0.1.2.tgz#00efbc08816c33cfc4ac8251d132e10dc65098d7" integrity sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc= -is-odd@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-0.1.2.tgz#bc573b5ce371ef2aad6e6f49799b72bef13978a7" - integrity sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc= - dependencies: - is-number "^3.0.0" - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - is-potential-custom-element-name@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" @@ -2253,13 +1734,6 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-self-closing@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4" - integrity sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg== - dependencies: - self-closing-tags "^1.0.1" - is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" @@ -2284,11 +1758,6 @@ is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - is@~0.2.6: version "0.2.7" resolved "https://registry.yarnpkg.com/is/-/is-0.2.7.tgz#3b34a2c48f359972f35042849193ae7264b63562" @@ -2299,7 +1768,7 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -2309,23 +1778,6 @@ isbuffer@~0.0.0: resolved "https://registry.yarnpkg.com/isbuffer/-/isbuffer-0.0.0.tgz#38c146d9df528b8bf9b0701c3d43cf12df3fc39b" integrity sha1-OMFG2d9Si4v5sHAcPUPPEt8/w5s= -isobject@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" - integrity sha1-o0MhkvObkQtfAsyYlIeDbscKqF4= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -2439,30 +1891,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0, kind-of@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - level-blobs@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/level-blobs/-/level-blobs-0.1.7.tgz#9ab9b97bb99f1edbf9f78a3433e21ed56386bdaf" @@ -2570,11 +1998,6 @@ loader-utils@^1.1.0: emojis-list "^3.0.0" json5 "^1.0.1" -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -2590,27 +2013,12 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.19, lodash@^4.17.20: +lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2634,18 +2042,6 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.4" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -2670,25 +2066,6 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -micromatch@^3.1.5: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -2731,14 +2108,6 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -2746,16 +2115,6 @@ mkdirp@~0.5.1: dependencies: minimist "^1.2.5" -moment@^2.18.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - nanoid@^2.1.0: version "2.1.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" @@ -2766,28 +2125,6 @@ nanoid@^3.1.22: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - node-releases@^1.1.71: version "1.1.73" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" @@ -2815,15 +2152,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" @@ -2848,13 +2176,6 @@ object-keys@~0.4.0: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -2874,13 +2195,6 @@ object.getownpropertydescriptors@^2.1.0: define-properties "^1.1.3" es-abstract "^1.18.0-next.2" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - object.values@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" @@ -2976,11 +2290,6 @@ parse5@5.1.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -3022,11 +2331,6 @@ pify@^5.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - postcss-calc@^7.0.1: version "7.0.5" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" @@ -3458,7 +2762,7 @@ readable-stream@^1.0.26-4: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.2.2, readable-stream@~2.3.6: +readable-stream@^2.2.2: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -3490,44 +2794,11 @@ readable-stream@~1.0.26, readable-stream@~1.0.26-4: isarray "0.0.1" string_decoder "~0.10.x" -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - regexparam@1.3.0, regexparam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== -relative@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/relative/-/relative-3.0.2.tgz#0dcd8ec54a5d35a3c15e104503d65375b5a5367f" - integrity sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8= - dependencies: - isobject "^2.0.0" - -remarkable@^1.6.2, remarkable@^1.7.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" - integrity sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg== - dependencies: - argparse "^1.0.10" - autolinker "~0.28.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - request-promise-core@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" @@ -3590,11 +2861,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - resolve@^1.17.0, resolve@^1.19.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" @@ -3603,11 +2869,6 @@ resolve@^1.17.0, resolve@^1.19.0: is-core-module "^2.2.0" path-parse "^1.0.6" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" @@ -3736,13 +2997,6 @@ safe-identifier@^0.4.2: resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3760,11 +3014,6 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -self-closing-tags@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" - integrity sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA== - semver@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" @@ -3777,16 +3026,6 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -3814,47 +3053,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -3863,16 +3061,6 @@ source-map-support@~0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -3888,13 +3076,6 @@ sourcemap-codec@^1.4.4: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3920,14 +3101,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -3978,11 +3151,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -striptags@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" - integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== - style-inject@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3" @@ -4137,49 +3305,11 @@ terser@^5.0.0: source-map "~0.7.2" source-map-support "~0.5.19" -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -to-gfm-code-block@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82" - integrity sha1-JdBFpfrlUxielje1kJANpzLYqoI= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -4233,18 +3363,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typeof-article@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/typeof-article/-/typeof-article-0.1.1.tgz#9f07e733c3fbb646ffa9e61c08debacd460e06af" - integrity sha1-nwfnM8P7tkb/qeYcCN66zUYOBq8= - dependencies: - kind-of "^3.1.0" - -uglify-js@^3.1.4: - version "3.14.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.2.tgz#d7dd6a46ca57214f54a2d0a43cad0f35db82ac99" - integrity sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A== - unbox-primitive@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -4255,16 +3373,6 @@ unbox-primitive@^1.0.0: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" @@ -4285,14 +3393,6 @@ unquote@~1.1.1: resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - uri-js@^4.2.2: version "4.4.0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" @@ -4300,16 +3400,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -4410,11 +3500,6 @@ word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4460,17 +3545,7 @@ xtend@~3.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -year@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" - integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A= diff --git a/packages/server/package.json b/packages/server/package.json index 1e2dc602ae..45124aaa98 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -94,6 +94,7 @@ "koa-session": "5.12.0", "koa-static": "5.0.0", "lodash": "4.17.21", + "memorystream": "^0.3.1", "mongodb": "3.6.3", "mssql": "6.2.3", "mysql": "2.18.1", diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index 76675116c2..a6e05ff002 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -114,8 +114,13 @@ async function createInstance(template) { // replicate the template data to the instance DB // this is currently very hard to test, downloading and importing template files - /* istanbul ignore next */ - if (template && template.useTemplate === "true") { + if (template && template.templateString) { + const { ok } = await db.load(template.templateString) + if (!ok) { + throw "Error loading database dump from memory." + } + } else if (template && template.useTemplate === "true") { + /* istanbul ignore next */ const { ok } = await db.load(await getTemplateStream(template)) if (!ok) { throw "Error loading database dump from template." @@ -191,10 +196,11 @@ exports.fetchAppPackage = async function (ctx) { } exports.create = async function (ctx) { - const { useTemplate, templateKey } = ctx.request.body + const { useTemplate, templateKey, templateString } = ctx.request.body const instanceConfig = { useTemplate, key: templateKey, + templateString, } if (ctx.request.files && ctx.request.files.templateFile) { instanceConfig.file = ctx.request.files.templateFile diff --git a/packages/server/src/api/controllers/cloud.js b/packages/server/src/api/controllers/cloud.js new file mode 100644 index 0000000000..d08efbef94 --- /dev/null +++ b/packages/server/src/api/controllers/cloud.js @@ -0,0 +1,69 @@ +const env = require("../../environment") +const { getAllApps } = require("@budibase/auth/db") +const CouchDB = require("../../db") +const { + exportDB, + sendTempFile, + readFileSync, +} = require("../../utilities/fileSystem") +const { getGlobalDBName, getGlobalDB } = require("@budibase/auth/tenancy") +const { create } = require("./application") + +async function createApp(appName, appImport) { + const ctx = { + request: { + body: { + templateString: appImport, + name: appName, + }, + }, + } + return create(ctx) +} + +exports.exportApps = async ctx => { + if (env.SELF_HOSTED || !env.MULTI_TENANCY) { + ctx.throw(400, "Exporting only allowed in multi-tenant cloud environments.") + } + const apps = await getAllApps(CouchDB, { all: true }) + const globalDBString = await exportDB(getGlobalDBName()) + let allDBs = { + global: globalDBString, + } + for (let app of apps) { + allDBs[app.name] = await exportDB(app._id) + } + const filename = `cloud-export-${new Date().getTime()}.txt` + ctx.attachment(filename) + ctx.body = sendTempFile(JSON.stringify(allDBs)) +} + +exports.importApps = async ctx => { + if (!env.SELF_HOSTED || env.MULTI_TENANCY) { + ctx.throw(400, "Importing only allowed in self hosted environments.") + } + const apps = await getAllApps(CouchDB, { all: true }) + if ( + apps.length !== 0 || + !ctx.request.files || + !ctx.request.files.importFile + ) { + ctx.throw( + 400, + "Import file is required and environment must be fresh to import apps." + ) + } + const importFile = ctx.request.files.importFile + const importString = readFileSync(importFile.file.path) + const dbs = JSON.parse(importString) + const globalDb = dbs.global + const db = getGlobalDB() + // load the global db first + await db.load(globalDb) + for (let [appName, appImport] of Object.values(dbs)) { + await createApp(appName, appImport) + } + ctx.body = { + message: "Apps successfully imported.", + } +} diff --git a/packages/server/src/api/routes/cloud.js b/packages/server/src/api/routes/cloud.js new file mode 100644 index 0000000000..214473f43f --- /dev/null +++ b/packages/server/src/api/routes/cloud.js @@ -0,0 +1,13 @@ +const Router = require("@koa/router") +const controller = require("../controllers/cloud") +const authorized = require("../../middleware/authorized") +const { BUILDER } = require("@budibase/auth/permissions") + +const router = Router() + +router + .get("/api/cloud/export", authorized(BUILDER), controller.exportApps) + // has to be public, only run if apps don't exist + .post("/api/cloud/import", controller.importApps) + +module.exports = router diff --git a/packages/server/src/utilities/fileSystem/index.js b/packages/server/src/utilities/fileSystem/index.js index 172afaf609..e3798192b7 100644 --- a/packages/server/src/utilities/fileSystem/index.js +++ b/packages/server/src/utilities/fileSystem/index.js @@ -19,6 +19,7 @@ const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, } = require("../../db/utils") +const MemoryStream = require("memorystream") const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..") const NODE_MODULES_PATH = join(TOP_LEVEL_PATH, "node_modules") @@ -111,29 +112,79 @@ exports.apiFileReturn = contents => { * to the temporary backup file (to return via API if required). */ exports.performBackup = async (appId, backupName) => { - const path = join(budibaseTempDir(), backupName) - const writeStream = fs.createWriteStream(path) - // perform couch dump - const instanceDb = new CouchDB(appId) - await instanceDb.dump(writeStream, { - // filter out anything that has a user metadata structure in its ID + return exports.exportDB(appId, { + exportName: backupName, filter: doc => !( doc._id.includes(USER_METDATA_PREFIX) || doc.includes(LINK_USER_METADATA_PREFIX) ), }) +} + +/** + * exports a DB to either file or a variable (memory). + * @param {string} dbName the DB which is to be exported. + * @param {string} exportName optional - the file name to export to, if not in memory. + * @param {function} filter optional - a filter function to clear out any un-wanted docs. + * @return Either the file stream or the variable (if no export name provided). + */ +exports.exportDB = async ( + dbName, + { exportName, filter } = { exportName: undefined, filter: undefined } +) => { + let stream, + appString = "", + path = null + if (exportName) { + path = join(budibaseTempDir(), exportName) + stream = fs.createWriteStream(path) + } else { + stream = new MemoryStream() + stream.on("data", chunk => { + appString += chunk.toString() + }) + } + // perform couch dump + const instanceDb = new CouchDB(dbName) + await instanceDb.dump(stream, { + filter, + }) + // just in memory, return the final string + if (!exportName) { + return appString + } // write the file to the object store if (env.SELF_HOSTED) { await streamUpload( ObjectStoreBuckets.BACKUPS, - join(appId, backupName), + join(dbName, exportName), fs.createReadStream(path) ) } return fs.createReadStream(path) } +/** + * Writes the provided contents to a temporary file, which can be used briefly. + * @param {string} fileContents contents which will be written to a temp file. + * @return {string} the path to the temp file. + */ +exports.storeTempFile = fileContents => { + const path = join(budibaseTempDir(), uuid()) + fs.writeFileSync(path, fileContents) + return path +} + +/** + * Creates a temp file and returns it from the API. + * @param {string} fileContents the contents to be returned in file. + */ +exports.sendTempFile = fileContents => { + const path = exports.storeTempFile(fileContents) + return fs.createReadStream(path) +} + /** * Uploads the latest client library to the object store. * @param {string} appId The ID of the app which is being created. diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 8062860f7f..3c0655f89f 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -943,29 +943,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/auth@^0.9.139": - version "0.9.139" - resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.139.tgz#0610582800df062372582f9139c7aa99606af3e1" - integrity sha512-2JUAKC3AA74O3TXHjoGCoXkDxXqUS1K8KGFrJtrUQQrVq1YeQGSjD6Km+Ho8PqUaNdpEfZinBS1/3qFUqaQbuQ== - dependencies: - "@techpass/passport-openidconnect" "^0.3.0" - aws-sdk "^2.901.0" - bcryptjs "^2.4.3" - cls-hooked "^4.2.2" - ioredis "^4.27.1" - jsonwebtoken "^8.5.1" - koa-passport "^4.1.4" - lodash "^4.17.21" - node-fetch "^2.6.1" - passport-google-auth "^1.0.2" - passport-google-oauth "^2.0.0" - passport-jwt "^4.0.0" - passport-local "^1.0.0" - sanitize-s3-objectkey "^0.0.1" - tar-fs "^2.1.1" - uuid "^8.3.2" - zlib "^1.0.5" - "@budibase/bbui@^0.9.139": version "0.9.139" resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.139.tgz#e6cfc90e8f6c2aa3526fc6a7bef251bccdaf51bb" @@ -1015,14 +992,63 @@ svelte-flatpickr "^3.1.0" svelte-portal "^1.0.0" -"@budibase/client@^0.9.139": - version "0.9.139" - resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.139.tgz#acec8dc746295f7793b188f4950ab2268170366c" - integrity sha512-PSSSaWjUrY/C4kG8r46aOVfq0aCEZGuI2Uv4jkqmk1zgt0GTXiJ+iQBkg7WZqTDBm7JIUzYUzV1T102tN4L1Jg== +"@budibase/bbui@^0.9.142": + version "0.9.142" + resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.142.tgz#7edbda7967c9e5dfc96e5be5231656e5aab8d0e3" + integrity sha512-m2YlqqH87T4RwqD/oGhH6twHIgvFv4oUMEhKpkgLsbxjXVLVD0OOF7WqjpDnSa4khVQaixjdkI/Jiw2qhBUSaA== dependencies: - "@budibase/bbui" "^0.9.139" + "@adobe/spectrum-css-workflow-icons" "^1.2.1" + "@spectrum-css/actionbutton" "^1.0.1" + "@spectrum-css/actiongroup" "^1.0.1" + "@spectrum-css/avatar" "^3.0.2" + "@spectrum-css/button" "^3.0.1" + "@spectrum-css/buttongroup" "^3.0.2" + "@spectrum-css/checkbox" "^3.0.2" + "@spectrum-css/dialog" "^3.0.1" + "@spectrum-css/divider" "^1.0.3" + "@spectrum-css/dropzone" "^3.0.2" + "@spectrum-css/fieldgroup" "^3.0.2" + "@spectrum-css/fieldlabel" "^3.0.1" + "@spectrum-css/icon" "^3.0.1" + "@spectrum-css/illustratedmessage" "^3.0.2" + "@spectrum-css/inputgroup" "^3.0.2" + "@spectrum-css/label" "^2.0.10" + "@spectrum-css/link" "^3.1.1" + "@spectrum-css/menu" "^3.0.1" + "@spectrum-css/modal" "^3.0.1" + "@spectrum-css/pagination" "^3.0.3" + "@spectrum-css/picker" "^1.0.1" + "@spectrum-css/popover" "^3.0.1" + "@spectrum-css/progressbar" "^1.0.2" + "@spectrum-css/progresscircle" "^1.0.2" + "@spectrum-css/radio" "^3.0.2" + "@spectrum-css/search" "^3.0.2" + "@spectrum-css/sidenav" "^3.0.2" + "@spectrum-css/statuslight" "^3.0.2" + "@spectrum-css/stepper" "^3.0.3" + "@spectrum-css/switch" "^1.0.2" + "@spectrum-css/table" "^3.0.1" + "@spectrum-css/tabs" "^3.0.1" + "@spectrum-css/tags" "^3.0.2" + "@spectrum-css/textfield" "^3.0.1" + "@spectrum-css/toast" "^3.0.1" + "@spectrum-css/tooltip" "^3.0.3" + "@spectrum-css/treeview" "^3.0.2" + "@spectrum-css/typography" "^3.0.1" + "@spectrum-css/underlay" "^2.0.9" + "@spectrum-css/vars" "^3.0.1" + dayjs "^1.10.4" + svelte-flatpickr "^3.1.0" + svelte-portal "^1.0.0" + +"@budibase/client@^0.9.140-alpha.11": + version "0.9.142" + resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.142.tgz#bfc3374b1414651cab799305def3e03354f070d0" + integrity sha512-/iT0pAanwljWo9R5fD6YkkUC8OePGUiMwNzaxLlXkda+qrop3SZFGcbPlNGYA81jUQq1O4L39RON7wqLSiJ2oQ== + dependencies: + "@budibase/bbui" "^0.9.142" "@budibase/standard-components" "^0.9.139" - "@budibase/string-templates" "^0.9.139" + "@budibase/string-templates" "^0.9.142" regexparam "^1.3.0" shortid "^2.2.15" svelte-spa-router "^3.0.5" @@ -1073,10 +1099,10 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/string-templates@^0.9.139": - version "0.9.139" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.139.tgz#f87de1d7382a81164bb734ef62ba552839805134" - integrity sha512-T7FR3GSmc/3vs6bynYrL/POjGP/z4pjlwjI4P6b2u10Fg2HWtI0QPZ+ifnOUf53Ry2r/PvDELATqkElpKh9Spg== +"@budibase/string-templates@^0.9.140-alpha.11", "@budibase/string-templates@^0.9.142": + version "0.9.142" + resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.142.tgz#2c026580edcc7e32c017b537921d06a1ad1148f5" + integrity sha512-7nGzVaOtOugwC/8NMoQ90B/L6Q/IzFub5Xws4r7tAeqZ5WUb1ITVDrNJ+w/PhzeVT6IdkXEUyMdkKBnJTmCD8g== dependencies: "@budibase/handlebars-helpers" "^0.11.4" dayjs "^1.10.4" @@ -2097,17 +2123,6 @@ dependencies: defer-to-connect "^1.0.1" -"@techpass/passport-openidconnect@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.2.tgz#f8fd5d97256286665dbf26dac92431f977ab1e63" - integrity sha512-fnCtEiexXSHA029B//hJcCJlLJrT3lhpNCyA0rnz58Qttz0BLGCVv6yMT8HmOnGThH6vcDOVwdgKM3kbCQtEhw== - dependencies: - base64url "^3.0.1" - oauth "^0.9.15" - passport-strategy "^1.0.0" - request "^2.88.0" - webfinger "^0.4.2" - "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -2852,13 +2867,6 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async-hook-jl@^1.7.6: - version "1.7.6" - resolved "https://registry.yarnpkg.com/async-hook-jl/-/async-hook-jl-1.7.6.tgz#4fd25c2f864dbaf279c610d73bf97b1b28595e68" - integrity sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg== - dependencies: - stack-chain "^1.3.7" - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -2876,13 +2884,6 @@ async@^2.6.3: dependencies: lodash "^4.17.14" -async@~2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" - integrity sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw= - dependencies: - lodash "^4.14.0" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2920,21 +2921,6 @@ aws-sdk@^2.767.0: uuid "3.3.2" xml2js "0.4.19" -aws-sdk@^2.901.0: - version "2.989.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.989.0.tgz#ed3cce6b94856b469784bc3312a0b64438b9fe67" - integrity sha512-sMjvqeF9mEOxXkhOAUjCrBt2iYafclkmaIbgSdjJ+te7zKXeReqrc6P3VgIGUxU8kwmdSro0n1NjrXbzKQJhcw== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.15.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - uuid "3.3.2" - xml2js "0.4.19" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -3102,11 +3088,6 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64url@3.x.x, base64url@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" - integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== - base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -3127,7 +3108,7 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bcryptjs@2.4.3, bcryptjs@^2.4.3: +bcryptjs@2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= @@ -3172,15 +3153,6 @@ bl@^3.0.0: dependencies: readable-stream "^3.0.1" -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - bluebird@^3.5.1: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3545,11 +3517,6 @@ chokidar@^3.2.2: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -3622,15 +3589,6 @@ clone-response@1.0.2, clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -cls-hooked@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" - integrity sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw== - dependencies: - async-hook-jl "^1.7.6" - emitter-listener "^1.0.1" - semver "^5.4.1" - cluster-key-slot@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" @@ -4361,13 +4319,6 @@ electron-to-chromium@^1.3.811: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.827.tgz#c725e8db8c5be18b472a919e5f57904512df0fc1" integrity sha512-ye+4uQOY/jbjRutMcE/EmOcNwUeo1qo9aKL2tPyb09cU3lmxNeyDF4RWiemmkknW+p29h7dyDqy02higTxc9/A== -emitter-listener@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8" - integrity sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ== - dependencies: - shimmer "^1.2.0" - emittery@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" @@ -4398,7 +4349,7 @@ encoding-down@^6.3.0: level-codec "^9.0.0" level-errors "^2.0.0" -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -5454,32 +5405,6 @@ globby@^11.0.3: merge2 "^1.3.0" slash "^3.0.0" -google-auth-library@~0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-0.10.0.tgz#6e15babee85fd1dd14d8d128a295b6838d52136e" - integrity sha1-bhW6vuhf0d0U2NEoopW2g41SE24= - dependencies: - gtoken "^1.2.1" - jws "^3.1.4" - lodash.noop "^3.0.1" - request "^2.74.0" - -google-p12-pem@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-0.1.2.tgz#33c46ab021aa734fa0332b3960a9a3ffcb2f3177" - integrity sha1-M8RqsCGqc0+gMys5YKmj/8svMXc= - dependencies: - node-forge "^0.7.1" - -googleapis@^16.0.0: - version "16.1.0" - resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-16.1.0.tgz#0f19f2d70572d918881a0f626e3b1a2fa8629576" - integrity sha1-Dxny1wVy2RiIGg9ibjsaL6hilXY= - dependencies: - async "~2.1.4" - google-auth-library "~0.10.0" - string-template "~1.0.0" - got@^8.3.1: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" @@ -5525,16 +5450,6 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1. resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== -gtoken@^1.2.1: - version "1.2.3" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-1.2.3.tgz#5509571b8afd4322e124cf66cf68115284c476d8" - integrity sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w== - dependencies: - google-p12-pem "^0.1.0" - jws "^3.0.0" - mime "^1.4.1" - request "^2.72.0" - gulp-header@^1.7.1: version "1.8.12" resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" @@ -6010,7 +5925,7 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ioredis@^4.27.0, ioredis@^4.27.1: +ioredis@^4.27.0: version "4.27.9" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.9.tgz#c27bbade9724f0b8f84c279fb1d567be785ba33d" integrity sha512-hAwrx9F+OQ0uIvaJefuS3UTqW+ByOLyLIV+j0EH8ClNVxvFyH9Vmb08hCL4yje6mDYT5zMquShhypkd50RRzkg== @@ -7407,22 +7322,6 @@ jsonschema@1.4.0: resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== -jsonwebtoken@^8.2.0, jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^5.6.0" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -7462,7 +7361,7 @@ jwa@^1.4.1: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jws@3.x.x, jws@^3.0.0, jws@^3.1.4, jws@^3.2.2: +jws@3.x.x: version "3.2.2" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== @@ -7587,13 +7486,6 @@ koa-is-json@^1.0.0: resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14" integrity sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ= -koa-passport@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-4.1.4.tgz#5f1665c1c2a37ace79af9f970b770885ca30ccfa" - integrity sha512-dJBCkl4X+zdYxbI2V2OtoGy0PUenpvp2ZLLWObc8UJhsId0iQpTFT8RVcuA0709AL2txGwRHnSPoT1bYNGa6Kg== - dependencies: - passport "^0.4.0" - koa-pino-logger@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#27600b4f3639e8767dfc6b66493109c5457f53ba" @@ -7895,46 +7787,16 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= - lodash.isarguments@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= - lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= - lodash.keys@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" @@ -7945,21 +7807,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.noop@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" - integrity sha1-OBiPTWUKOkdCWEObluxFsyYXEzw= - lodash.omit@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA= -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - lodash.pick@^4.0.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -7995,7 +7847,7 @@ lodash.xor@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6" integrity sha1-TUjtfpgJWwYyWCunFNP/iuj7HbY= -lodash@4.17.21, lodash@4.x, lodash@^4.14.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0: +lodash@4.17.21, lodash@4.x, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8131,6 +7983,11 @@ memory-pager@^1.0.2: resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -8240,11 +8097,6 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -8334,7 +8186,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -mysql@^2.18.1: +mysql@2.18.1: version "2.18.1" resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717" integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig== @@ -8435,11 +8287,6 @@ node-fetch@^2.6.0, node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-forge@^0.7.1: - version "0.7.6" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" - integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== - node-gyp-build@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" @@ -8551,11 +8398,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -oauth@0.9.x, oauth@^0.9.15: - version "0.9.15" - resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" - integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= - object-assign@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" @@ -8853,84 +8695,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -passport-google-auth@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/passport-google-auth/-/passport-google-auth-1.0.2.tgz#8b300b5aa442ef433de1d832ed3112877d0b2938" - integrity sha1-izALWqRC70M94dgy7TESh30LKTg= - dependencies: - googleapis "^16.0.0" - passport-strategy "1.x" - -passport-google-oauth1@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz#af74a803df51ec646f66a44d82282be6f108e0cc" - integrity sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw= - dependencies: - passport-oauth1 "1.x.x" - -passport-google-oauth20@2.x.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" - integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== - dependencies: - passport-oauth2 "1.x.x" - -passport-google-oauth@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz#f6eb4bc96dd6c16ec0ecfdf4e05ec48ca54d4dae" - integrity sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA== - dependencies: - passport-google-oauth1 "1.x.x" - passport-google-oauth20 "2.x.x" - -passport-jwt@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065" - integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg== - dependencies: - jsonwebtoken "^8.2.0" - passport-strategy "^1.0.0" - -passport-local@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" - integrity sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4= - dependencies: - passport-strategy "1.x.x" - -passport-oauth1@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.2.0.tgz#5229d431781bf5b265bec86ce9a9cce58a756cf9" - integrity sha512-Sv2YWodC6jN12M/OXwmR4BIXeeIHjjbwYTQw4kS6tHK4zYzSEpxBgSJJnknBjICA5cj0ju3FSnG1XmHgIhYnLg== - dependencies: - oauth "0.9.x" - passport-strategy "1.x.x" - utils-merge "1.x.x" - -passport-oauth2@1.x.x: - version "1.6.0" - resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.6.0.tgz#5f599735e0ea40ea3027643785f81a3a9b4feb50" - integrity sha512-emXPLqLcVEcLFR/QvQXZcwLmfK8e9CqvMgmOFJxcNT3okSFMtUbRRKpY20x5euD+01uHsjjCa07DYboEeLXYiw== - dependencies: - base64url "3.x.x" - oauth "0.9.x" - passport-strategy "1.x.x" - uid2 "0.0.x" - utils-merge "1.x.x" - -passport-strategy@1.x, passport-strategy@1.x.x, passport-strategy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" - integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= - -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -8985,11 +8749,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pause@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" - integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -9688,7 +9447,7 @@ readable-stream@1.1.14, readable-stream@^1.0.27-1: isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -9921,7 +9680,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.72.0, request@^2.74.0, request@^2.87.0, request@^2.88.0: +request@^2.87.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10113,11 +9872,6 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sanitize-s3-objectkey@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/sanitize-s3-objectkey/-/sanitize-s3-objectkey-0.0.1.tgz#efa9887cd45275b40234fb4bb12fc5754fe64e7e" - integrity sha512-ZTk7aqLxy4sD40GWcYWoLfbe05XLmkKvh6vGKe13ADlei24xlezcvjgKy1qRArlaIbIMYaqK7PCalvZtulZlaQ== - saslprep@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" @@ -10130,7 +9884,7 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= -sax@>=0.1.1, sax@>=0.6.0, sax@^1.2.4: +sax@>=0.6.0, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -10166,7 +9920,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -10292,11 +10046,6 @@ shell-path@^2.1.0: dependencies: shell-env "^0.3.0" -shimmer@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" - integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== - shortid@^2.2.15: version "2.2.16" resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.16.tgz#b742b8f0cb96406fd391c76bfc18a67a57fe5608" @@ -10548,11 +10297,6 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stack-chain@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" - integrity sha1-0ZLJ/06moiyUxN1FkXHj8AzqEoU= - stack-utils@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b" @@ -10595,11 +10339,6 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -step@0.0.x: - version "0.0.6" - resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2" - integrity sha1-FD54SaXX0/SgiP4pr5SRUhbu7eI= - strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -10613,11 +10352,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-template@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" - integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -10919,16 +10653,6 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tar-fs@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -10942,17 +10666,6 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - tarn@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.5.tgz#7be88622e951738b9fa3fb77477309242cdddc2d" @@ -11357,11 +11070,6 @@ uglify-js@^3.1.4: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.2.tgz#d7dd6a46ca57214f54a2d0a43cad0f35db82ac99" integrity sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A== -uid2@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" - integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== - unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -11553,7 +11261,7 @@ util.promisify@^1.0.0, util.promisify@^1.0.1: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.1" -utils-merge@1.0.1, utils-merge@1.x.x: +utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= @@ -11650,14 +11358,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -webfinger@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d" - integrity sha1-NHem2XeZRhiWA5/P/GULc0aO520= - dependencies: - step "0.0.x" - xml2js "0.1.x" - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -11857,13 +11557,6 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= -xml2js@0.1.x: - version "0.1.14" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" - integrity sha1-UnTmf1pkxfkpdM2FE54DMq3GuQw= - dependencies: - sax ">=0.1.1" - xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -12017,7 +11710,7 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== -zlib@1.0.5, zlib@^1.0.5: +zlib@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0" integrity sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA= From 1a1c0f2892d77384920b451011615a2507c1d221 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 28 Sep 2021 12:25:57 +0100 Subject: [PATCH 44/88] check tables can be fetched before saving config --- .../modals/DatasourceConfigModal.svelte | 19 +++-------- .../app/[application]/data/index.svelte | 6 ---- .../builder/src/stores/backend/datasources.js | 7 ++-- .../server/src/api/controllers/datasource.js | 32 +++++++++++++------ 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 9221cbf083..56fa26ee0a 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -3,7 +3,7 @@ import { ModalContent, notifications, Body, Layout } from "@budibase/bbui" import analytics, { Events } from "analytics" import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte" - import { datasources, tables } from "stores/backend" + import { datasources } from "stores/backend" import { IntegrationNames } from "constants" export let integration @@ -27,13 +27,11 @@ return datasource } async function saveDatasource() { + const datasource = prepareData() try { // Create datasource - const resp = await datasources.save(prepareData()) + const resp = await datasources.save(datasource, datasource.plus) - if (integration.plus) { - updateDatasourceSchema(resp) - } await datasources.select(resp._id) $goto(`./datasource/${resp._id}`) notifications.success(`Datasource updated successfully.`) @@ -41,17 +39,10 @@ name: resp.name, source: resp.source, }) + return true } catch (err) { notifications.error(`Error saving datasource: ${err}`) - } - } - - async function updateDatasourceSchema(datasourceJson) { - try { - await datasources.updateSchema(datasourceJson) - await tables.fetch() - } catch (err) { - notifications.error(`Error updating datasource schema: ${err}`) + return false } } diff --git a/packages/builder/src/pages/builder/app/[application]/data/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/index.svelte index 873f721a59..c27ee7b342 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/index.svelte @@ -9,12 +9,6 @@ $datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 || $datasources.list.length > 1 - $: console.log( - $datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 - ) - $: console.log($datasources.list.length >= 1) - $: console.log($datasources.list) - onMount(() => { if (!setupComplete) { modal.show() diff --git a/packages/builder/src/stores/backend/datasources.js b/packages/builder/src/stores/backend/datasources.js index 5c6ed3f2cb..f7e689d8ad 100644 --- a/packages/builder/src/stores/backend/datasources.js +++ b/packages/builder/src/stores/backend/datasources.js @@ -58,7 +58,7 @@ export function createDatasourcesStore() { }) return json }, - save: async datasource => { + save: async (datasource, fetchSchema = false) => { let response if (datasource._id) { response = await api.put( @@ -66,7 +66,10 @@ export function createDatasourcesStore() { datasource ) } else { - response = await api.post("/api/datasources", datasource) + response = await api.post("/api/datasources", { + datasource: datasource, + fetchSchema, + }) } const json = await response.json() diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 4a2fd7d86a..2ff7c7f9b8 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -41,15 +41,10 @@ exports.fetch = async function (ctx) { exports.buildSchemaFromDb = async function (ctx) { const db = new CouchDB(ctx.appId) - const datasourceId = ctx.params.datasourceId - const datasource = await db.get(datasourceId) + const datasource = await db.get(ctx.params.datasourceId) - const Connector = integrations[datasource.source] - - // Connect to the DB and build the schema - const connector = new Connector(datasource.config) - await connector.buildSchema(datasource._id, datasource.entities) - datasource.entities = connector.tables + const tables = await buildSchemaHelper(datasource) + datasource.entities = tables const response = await db.put(datasource) datasource._rev = response.rev @@ -81,12 +76,18 @@ exports.update = async function (ctx) { exports.save = async function (ctx) { const db = new CouchDB(ctx.appId) - const plus = ctx.request.body.plus + const plus = ctx.request.body.datasource.plus + const fetchSchema = ctx.request.body.fetchSchema const datasource = { _id: generateDatasourceID({ plus }), type: plus ? DocumentTypes.DATASOURCE_PLUS : DocumentTypes.DATASOURCE, - ...ctx.request.body, + ...ctx.request.body.datasource, + } + + if (fetchSchema) { + let tables = await buildSchemaHelper(datasource) + datasource.entities = tables } const response = await db.put(datasource) @@ -133,3 +134,14 @@ exports.query = async function (ctx) { ctx.throw(400, err) } } + +const buildSchemaHelper = async datasource => { + const Connector = integrations[datasource.source] + + // Connect to the DB and build the schema + const connector = new Connector(datasource.config) + await connector.buildSchema(datasource._id, datasource.entities) + datasource.entities = connector.tables + + return connector.tables +} From a117f3542c7f4a32ec2a89e4297a147ee73b0178 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 28 Sep 2021 12:26:38 +0100 Subject: [PATCH 45/88] update cypress tests to account for new modal --- packages/builder/cypress.json | 4 ++-- .../cypress/integration/createTable.spec.js | 6 ++--- packages/builder/cypress/support/commands.js | 22 ++++++++++++++++++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index 0908f2c839..669ee5af34 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,9 +1,9 @@ { - "baseUrl": "http://localhost:10001/builder/", + "baseUrl": "http://localhost:10000/builder/", "video": true, "projectId": "bmbemn", "env": { - "PORT": "10001", + "PORT": "10000", "JWT_SECRET": "test" } } diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js index eda72ba36d..a0d741910c 100644 --- a/packages/builder/cypress/integration/createTable.spec.js +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -6,7 +6,7 @@ context("Create a Table", () => { it("should create a new Table", () => { cy.createTable("dog") - + cy.wait(1000) // Check if Table exists cy.get(".table-title h1").should("have.text", "dog") }) @@ -36,7 +36,7 @@ context("Create a Table", () => { it("edits a row", () => { cy.contains("button", "Edit").click({ force: true }) cy.wait(1000) - cy.get(".spectrum-Modal input").type("Updated") + cy.get(".spectrum-Modal input").type("RoverUpdated") cy.contains("Save").click() cy.contains("RoverUpdated").should("have.text", "RoverUpdated") }) @@ -62,7 +62,7 @@ context("Create a Table", () => { it("deletes a table", () => { cy.get(".actions > :nth-child(1) > .icon > .spectrum-Icon > use") - .first() + .eq(1) .click({ force: true }) cy.get(".spectrum-Menu > :nth-child(2)").click() cy.contains("Delete Table").click() diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index ea6ca81e66..d681fda8ad 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -35,8 +35,11 @@ Cypress.Commands.add("createApp", name => { .within(() => { cy.get("input").eq(0).type(name).should("have.value", name).blur() cy.get(".spectrum-ButtonGroup").contains("Create app").click() + cy.wait(7000) }) .then(() => { + // Because we show the datasource modal on entry, we need to create a table to get rid of the modal in the future + cy.createInitialDatasource("initialTable") cy.expandBudibaseConnection() cy.get(".nav-item.selected > .content").should("be.visible") }) @@ -69,11 +72,28 @@ Cypress.Commands.add("createTestTableWithData", () => { cy.addColumn("dog", "age", "Number") }) -Cypress.Commands.add("createTable", tableName => { +Cypress.Commands.add("createInitialDatasource", tableName => { // Enter table name + cy.get(".spectrum-Modal").within(() => { + cy.contains("Budibase DB").trigger("mouseover").click().click() + cy.wait(1000) + cy.contains("Continue").click() + }) + + cy.get(".spectrum-Modal").within(() => { + cy.wait(1000) + cy.get("input").first().type(tableName).blur() + cy.get(".spectrum-ButtonGroup").contains("Create").click() + }) + cy.contains(tableName).should("be.visible") +}) + +Cypress.Commands.add("createTable", tableName => { cy.contains("Budibase DB").click() cy.contains("Create new table").click() + cy.get(".spectrum-Modal").within(() => { + cy.wait(1000) cy.get("input").first().type(tableName).blur() cy.get(".spectrum-ButtonGroup").contains("Create").click() }) From a24f2e4142fa09fb739d9b5a778151f252eb7086 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 28 Sep 2021 12:29:54 +0100 Subject: [PATCH 46/88] update modal button text --- .../DatasourceNavigator/modals/CreateDatasourceModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte index bbf3ec22ee..be0e83f80c 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte @@ -68,7 +68,7 @@ disabled={!Object.keys(integration).length} title="Data" confirmText="Continue" - cancelText="Start from scratch" + cancelText="Create a new table with Budibase DB" size="M" onCancel={() => internalTableModal.show()} onConfirm={() => { From 7527c19a8c8bb121b4da1f937d9c9284fce8c64d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 28 Sep 2021 15:29:15 +0100 Subject: [PATCH 47/88] Add basic search implementation to data UI tables --- .../backend/DataTable/DataTable.svelte | 95 ++++++++++++++----- .../components/backend/DataTable/Table.svelte | 2 +- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index f8b5abc4cd..d145b3136c 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -11,10 +11,13 @@ import { TableNames } from "constants" import CreateEditRow from "./modals/CreateEditRow.svelte" import { fetchTableData } from "helpers/fetchTableData" - import { Pagination } from "@budibase/bbui" + import { Layout, Pagination, Select, Input } from "@budibase/bbui" + import { OperatorOptions } from "constants/lucene" const search = fetchTableData() let hideAutocolumns = true + let searchColumn + let searchValue $: isUsersTable = $tables.selected?._id === TableNames.USERS $: title = $tables.selected?.name @@ -22,12 +25,16 @@ $: type = $tables.selected?.type $: isInternal = type !== "external" $: id = $tables.selected?._id - $: fetchTable(id) + $: columnOptions = Object.keys($search.schema || {}) + $: filter = buildFilter(searchColumn, searchValue) + $: fetchTable(id, filter) - const fetchTable = tableId => { + // Fetches new data whenever the table changes + const fetchTable = (tableId, filter) => { search.update({ tableId, schema, + filter, limit: 10, paginate: true, }) @@ -40,6 +47,23 @@ sortOrder: e.detail.order, }) } + + // Builds a filter expression to search with + const buildFilter = (column, value) => { + if (!column || !value) { + return null + } + return [ + { + type: "string", + field: column, + operator: OperatorOptions.StartsWith.value, + value, + }, + ] + } + + $: console.log(filter)
@@ -55,27 +79,39 @@ allowEditing disableSorting > - {#if isInternal} - - {/if} - {#if schema && Object.keys(schema).length > 0} - {#if !isUsersTable} - +
+ {#if isInternal} + + {/if} + {#if schema && Object.keys(schema).length > 0} + {#if !isUsersTable} + + {/if} + {#if isInternal} + + {/if} + + {#if isUsersTable} + + {/if} + + + + {/if} +
+ +