Merge branch 'master' into allow-public-view-attachment-uploads
This commit is contained in:
commit
17614e8aad
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"version": "3.4.24",
|
"version": "3.5.0",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"concurrency": 20,
|
"concurrency": 20,
|
||||||
"command": {
|
"command": {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
"eslint-plugin-jest": "28.9.0",
|
"eslint-plugin-jest": "28.9.0",
|
||||||
"eslint-plugin-local-rules": "3.0.2",
|
"eslint-plugin-local-rules": "3.0.2",
|
||||||
"eslint-plugin-svelte": "2.46.1",
|
"eslint-plugin-svelte": "2.46.1",
|
||||||
"svelte-preprocess": "^6.0.3",
|
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"kill-port": "^1.6.1",
|
"kill-port": "^1.6.1",
|
||||||
"lerna": "7.4.2",
|
"lerna": "7.4.2",
|
||||||
|
@ -29,7 +28,9 @@
|
||||||
"prettier-plugin-svelte": "^2.3.0",
|
"prettier-plugin-svelte": "^2.3.0",
|
||||||
"proper-lockfile": "^4.1.2",
|
"proper-lockfile": "^4.1.2",
|
||||||
"svelte": "4.2.19",
|
"svelte": "4.2.19",
|
||||||
|
"svelte-check": "^4.1.5",
|
||||||
"svelte-eslint-parser": "0.43.0",
|
"svelte-eslint-parser": "0.43.0",
|
||||||
|
"svelte-preprocess": "^6.0.3",
|
||||||
"typescript": "5.7.2",
|
"typescript": "5.7.2",
|
||||||
"typescript-eslint": "8.17.0",
|
"typescript-eslint": "8.17.0",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/textfield/dist/index-vars.css"
|
import "@spectrum-css/textfield/dist/index-vars.css"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let value = ""
|
export let value = ""
|
||||||
export let placeholder = null
|
export let placeholder: string | undefined = undefined
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
export let id = null
|
export let id: string | undefined = undefined
|
||||||
export let height = null
|
export let height: string | number | undefined = undefined
|
||||||
export let minHeight = null
|
export let minHeight: string | number | undefined = undefined
|
||||||
export const getCaretPosition = () => ({
|
export const getCaretPosition = () => ({
|
||||||
start: textarea.selectionStart,
|
start: textarea.selectionStart,
|
||||||
end: textarea.selectionEnd,
|
end: textarea.selectionEnd,
|
||||||
|
@ -16,18 +16,21 @@
|
||||||
export let align = null
|
export let align = null
|
||||||
|
|
||||||
let focus = false
|
let focus = false
|
||||||
let textarea
|
let textarea: any
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = event => {
|
const onChange = (event: any) => {
|
||||||
dispatch("change", event.target.value)
|
dispatch("change", event.target.value)
|
||||||
focus = false
|
focus = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyleString = (attribute, value) => {
|
const getStyleString = (
|
||||||
|
attribute: string,
|
||||||
|
value: string | number | undefined
|
||||||
|
) => {
|
||||||
if (!attribute || value == null) {
|
if (!attribute || value == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if (isNaN(value)) {
|
if (typeof value === "number" && isNaN(value)) {
|
||||||
return `${attribute}:${value};`
|
return `${attribute}:${value};`
|
||||||
}
|
}
|
||||||
return `${attribute}:${value}px;`
|
return `${attribute}:${value}px;`
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Field from "./Field.svelte"
|
import Field from "./Field.svelte"
|
||||||
import TextArea from "./Core/TextArea.svelte"
|
import TextArea from "./Core/TextArea.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let value = null
|
export let value: string | undefined = undefined
|
||||||
export let label = null
|
export let label: string | undefined = undefined
|
||||||
export let labelPosition = "above"
|
export let labelPosition: string = "above"
|
||||||
export let placeholder = null
|
export let placeholder: string | undefined = undefined
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let error = null
|
export let error: string | undefined = undefined
|
||||||
export let getCaretPosition = null
|
export let getCaretPosition: any = undefined
|
||||||
export let height = null
|
export let height: string | number | undefined = undefined
|
||||||
export let minHeight = null
|
export let minHeight: string | number | undefined = undefined
|
||||||
export let helpText = null
|
export let helpText: string | undefined = undefined
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = e => {
|
const onChange = (e: any) => {
|
||||||
value = e.detail
|
value = e.detail
|
||||||
dispatch("change", e.detail)
|
dispatch("change", e.detail)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
<Field {helpText} {label} {labelPosition} {error}>
|
<Field {helpText} {label} {labelPosition} {error}>
|
||||||
<TextArea
|
<TextArea
|
||||||
bind:getCaretPosition
|
bind:getCaretPosition
|
||||||
{error}
|
|
||||||
{disabled}
|
{disabled}
|
||||||
{value}
|
{value}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import "@spectrum-css/inlinealert/dist/index-vars.css"
|
import "@spectrum-css/inlinealert/dist/index-vars.css"
|
||||||
import Button from "../Button/Button.svelte"
|
import Button from "../Button/Button.svelte"
|
||||||
|
import Icon from "../Icon/Icon.svelte"
|
||||||
|
|
||||||
export let type = "info"
|
export let type = "info"
|
||||||
export let header = ""
|
export let header = ""
|
||||||
|
@ -8,6 +9,8 @@
|
||||||
export let onConfirm = undefined
|
export let onConfirm = undefined
|
||||||
export let buttonText = ""
|
export let buttonText = ""
|
||||||
export let cta = false
|
export let cta = false
|
||||||
|
export let link = ""
|
||||||
|
export let linkText = ""
|
||||||
|
|
||||||
$: icon = selectIcon(type)
|
$: icon = selectIcon(type)
|
||||||
// if newlines used, convert them to different elements
|
// if newlines used, convert them to different elements
|
||||||
|
@ -49,6 +52,19 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if link && linkText}
|
||||||
|
<div id="docs-link">
|
||||||
|
<a
|
||||||
|
href={link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="docs-link"
|
||||||
|
>
|
||||||
|
{linkText}
|
||||||
|
<Icon name="LinkOut" size="XS" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -64,4 +80,21 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docs-link {
|
||||||
|
padding-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docs-link > * {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
export let title
|
export let title
|
||||||
export let icon = ""
|
export let icon = ""
|
||||||
export let id
|
export let id = undefined
|
||||||
export let href = "#"
|
export let href = "#"
|
||||||
export let link = false
|
export let link = false
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,6 @@
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jsdom": "^21.1.1",
|
"jsdom": "^21.1.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"svelte-check": "^4.1.0",
|
|
||||||
"svelte-jester": "^1.3.2",
|
"svelte-jester": "^1.3.2",
|
||||||
"vite": "^4.5.0",
|
"vite": "^4.5.0",
|
||||||
"vite-plugin-static-copy": "^0.17.0",
|
"vite-plugin-static-copy": "^0.17.0",
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
<script>
|
|
||||||
import { goto } from "@roxi/routify"
|
|
||||||
import {
|
|
||||||
keepOpen,
|
|
||||||
ModalContent,
|
|
||||||
notifications,
|
|
||||||
Body,
|
|
||||||
Layout,
|
|
||||||
Tabs,
|
|
||||||
Tab,
|
|
||||||
Heading,
|
|
||||||
TextArea,
|
|
||||||
Dropzone,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { datasources, queries } from "@/stores/builder"
|
|
||||||
import { writable } from "svelte/store"
|
|
||||||
|
|
||||||
export let navigateDatasource = false
|
|
||||||
export let datasourceId
|
|
||||||
export let createDatasource = false
|
|
||||||
export let onCancel
|
|
||||||
|
|
||||||
const data = writable({
|
|
||||||
url: "",
|
|
||||||
raw: "",
|
|
||||||
file: undefined,
|
|
||||||
})
|
|
||||||
|
|
||||||
let lastTouched = "url"
|
|
||||||
|
|
||||||
const getData = async () => {
|
|
||||||
let dataString
|
|
||||||
|
|
||||||
// parse the file into memory and send as string
|
|
||||||
if (lastTouched === "file") {
|
|
||||||
dataString = await $data.file.text()
|
|
||||||
} else if (lastTouched === "url") {
|
|
||||||
const response = await fetch($data.url)
|
|
||||||
dataString = await response.text()
|
|
||||||
} else if (lastTouched === "raw") {
|
|
||||||
dataString = $data.raw
|
|
||||||
}
|
|
||||||
|
|
||||||
return dataString
|
|
||||||
}
|
|
||||||
|
|
||||||
async function importQueries() {
|
|
||||||
try {
|
|
||||||
const dataString = await getData()
|
|
||||||
|
|
||||||
if (!datasourceId && !createDatasource) {
|
|
||||||
throw new Error("No datasource id")
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
data: dataString,
|
|
||||||
datasourceId,
|
|
||||||
}
|
|
||||||
|
|
||||||
const importResult = await queries.import(body)
|
|
||||||
if (!datasourceId) {
|
|
||||||
datasourceId = importResult.datasourceId
|
|
||||||
}
|
|
||||||
|
|
||||||
// reload
|
|
||||||
await datasources.fetch()
|
|
||||||
await queries.fetch()
|
|
||||||
|
|
||||||
if (navigateDatasource) {
|
|
||||||
$goto(`./datasource/${datasourceId}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
notifications.success(`Imported successfully.`)
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error importing queries")
|
|
||||||
return keepOpen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ModalContent
|
|
||||||
onConfirm={() => importQueries()}
|
|
||||||
{onCancel}
|
|
||||||
confirmText={"Import"}
|
|
||||||
cancelText="Back"
|
|
||||||
size="L"
|
|
||||||
>
|
|
||||||
<Layout noPadding>
|
|
||||||
<Heading size="S">Import</Heading>
|
|
||||||
<Body size="XS"
|
|
||||||
>Import your rest collection using one of the options below</Body
|
|
||||||
>
|
|
||||||
<Tabs selected="File">
|
|
||||||
<!-- Commenting until nginx csp issue resolved -->
|
|
||||||
<!-- <Tab title="Link">
|
|
||||||
<Input
|
|
||||||
bind:value={$data.url}
|
|
||||||
on:change={() => (lastTouched = "url")}
|
|
||||||
label="Enter a URL"
|
|
||||||
placeholder="e.g. https://petstore.swagger.io/v2/swagger.json"
|
|
||||||
/>
|
|
||||||
</Tab> -->
|
|
||||||
<Tab title="File">
|
|
||||||
<Dropzone
|
|
||||||
gallery={false}
|
|
||||||
value={$data.file ? [$data.file] : []}
|
|
||||||
on:change={e => {
|
|
||||||
$data.file = e.detail?.[0]
|
|
||||||
lastTouched = "file"
|
|
||||||
}}
|
|
||||||
fileTags={[
|
|
||||||
"OpenAPI 3.0",
|
|
||||||
"OpenAPI 2.0",
|
|
||||||
"Swagger 2.0",
|
|
||||||
"cURL",
|
|
||||||
"YAML",
|
|
||||||
"JSON",
|
|
||||||
]}
|
|
||||||
maximum={1}
|
|
||||||
/>
|
|
||||||
</Tab>
|
|
||||||
<Tab title="Raw Text">
|
|
||||||
<TextArea
|
|
||||||
bind:value={$data.raw}
|
|
||||||
on:change={() => (lastTouched = "raw")}
|
|
||||||
label={"Paste raw text"}
|
|
||||||
placeholder={'e.g. curl --location --request GET "https://example.com"'}
|
|
||||||
/>
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
|
||||||
</Layout>
|
|
||||||
</ModalContent>
|
|
|
@ -280,16 +280,15 @@
|
||||||
EditorView.inputHandler.of((view, from, to, insert) => {
|
EditorView.inputHandler.of((view, from, to, insert) => {
|
||||||
if (jsBindingWrapping && insert === "$") {
|
if (jsBindingWrapping && insert === "$") {
|
||||||
let { text } = view.state.doc.lineAt(from)
|
let { text } = view.state.doc.lineAt(from)
|
||||||
|
|
||||||
const left = from ? text.substring(0, from) : ""
|
const left = from ? text.substring(0, from) : ""
|
||||||
const right = to ? text.substring(to) : ""
|
const right = to ? text.substring(to) : ""
|
||||||
const wrap = !left.includes('$("') || !right.includes('")')
|
const wrap =
|
||||||
|
(!left.includes('$("') || !right.includes('")')) &&
|
||||||
|
!(left.includes("`") && right.includes("`"))
|
||||||
|
const anchor = from + (wrap ? 3 : 1)
|
||||||
const tr = view.state.update(
|
const tr = view.state.update(
|
||||||
{
|
{
|
||||||
changes: [{ from, insert: wrap ? '$("")' : "$" }],
|
changes: [{ from, insert: wrap ? '$("")' : "$" }],
|
||||||
selection: {
|
|
||||||
anchor: from + (wrap ? 3 : 1),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scrollIntoView: true,
|
scrollIntoView: true,
|
||||||
|
@ -297,6 +296,19 @@
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
view.dispatch(tr)
|
view.dispatch(tr)
|
||||||
|
// the selection needs to fired after the dispatch - this seems
|
||||||
|
// to fix an issue with the cursor not moving when the editor is
|
||||||
|
// first loaded, the first usage of the editor is not ready
|
||||||
|
// for the anchor to move as well as perform a change
|
||||||
|
setTimeout(() => {
|
||||||
|
view.dispatch(
|
||||||
|
view.state.update({
|
||||||
|
selection: {
|
||||||
|
anchor,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}, 1)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -421,6 +433,7 @@
|
||||||
.code-editor {
|
.code-editor {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
.code-editor :global(.cm-editor) {
|
.code-editor :global(.cm-editor) {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { Label, Select, Body } from "@budibase/bbui"
|
import { Label, Select, Body } from "@budibase/bbui"
|
||||||
import { findAllMatchingComponents } from "@/helpers/components"
|
import { findAllMatchingComponents } from "@/helpers/components"
|
||||||
import { selectedScreen } from "@/stores/builder"
|
import { selectedScreen } from "@/stores/builder"
|
||||||
|
import { InlineAlert } from "@budibase/bbui"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
|
|
||||||
|
@ -27,6 +28,12 @@
|
||||||
<Label small>Table</Label>
|
<Label small>Table</Label>
|
||||||
<Select bind:value={parameters.componentId} options={componentOptions} />
|
<Select bind:value={parameters.componentId} options={componentOptions} />
|
||||||
</div>
|
</div>
|
||||||
|
<InlineAlert
|
||||||
|
header="Legacy action"
|
||||||
|
message="This action is only compatible with the (deprecated) Table Block. Please see the documentation for further info."
|
||||||
|
link="https://docs.budibase.com/docs/data-actions#clear-row-selection"
|
||||||
|
linkText="Budibase Documentation"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import {
|
import {
|
||||||
keepOpen,
|
keepOpen,
|
||||||
|
@ -14,13 +14,14 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { datasources, queries } from "@/stores/builder"
|
import { datasources, queries } from "@/stores/builder"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
|
import type { Datasource } from "@budibase/types"
|
||||||
|
|
||||||
export let navigateDatasource = false
|
export let navigateDatasource = false
|
||||||
export let datasourceId
|
export let datasourceId: string | undefined = undefined
|
||||||
export let createDatasource = false
|
export let createDatasource = false
|
||||||
export let onCancel
|
export let onCancel: (() => void) | undefined = undefined
|
||||||
|
|
||||||
const data = writable({
|
const data = writable<{ url: string; raw: string; file?: any }>({
|
||||||
url: "",
|
url: "",
|
||||||
raw: "",
|
raw: "",
|
||||||
file: undefined,
|
file: undefined,
|
||||||
|
@ -28,12 +29,14 @@
|
||||||
|
|
||||||
let lastTouched = "url"
|
let lastTouched = "url"
|
||||||
|
|
||||||
const getData = async () => {
|
$: datasource = $datasources.selected as Datasource
|
||||||
|
|
||||||
|
const getData = async (): Promise<string> => {
|
||||||
let dataString
|
let dataString
|
||||||
|
|
||||||
// parse the file into memory and send as string
|
// parse the file into memory and send as string
|
||||||
if (lastTouched === "file") {
|
if (lastTouched === "file") {
|
||||||
dataString = await $data.file.text()
|
dataString = await $data.file?.text()
|
||||||
} else if (lastTouched === "url") {
|
} else if (lastTouched === "url") {
|
||||||
const response = await fetch($data.url)
|
const response = await fetch($data.url)
|
||||||
dataString = await response.text()
|
dataString = await response.text()
|
||||||
|
@ -55,9 +58,9 @@
|
||||||
const body = {
|
const body = {
|
||||||
data: dataString,
|
data: dataString,
|
||||||
datasourceId,
|
datasourceId,
|
||||||
|
datasource,
|
||||||
}
|
}
|
||||||
|
const importResult = await queries.importQueries(body)
|
||||||
const importResult = await queries.import(body)
|
|
||||||
if (!datasourceId) {
|
if (!datasourceId) {
|
||||||
datasourceId = importResult.datasourceId
|
datasourceId = importResult.datasourceId
|
||||||
}
|
}
|
||||||
|
@ -71,8 +74,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications.success("Imported successfully")
|
notifications.success("Imported successfully")
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
notifications.error("Error importing queries")
|
notifications.error(`Error importing queries - ${error.message}`)
|
||||||
|
|
||||||
return keepOpen
|
return keepOpen
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite build --watch --mode=dev"
|
"dev": "vite build --watch --mode=dev",
|
||||||
|
"check:types": "yarn svelte-check"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "*",
|
"@budibase/bbui": "*",
|
||||||
|
|
|
@ -10,7 +10,9 @@ export const API = createAPIClient({
|
||||||
// Attach client specific headers
|
// Attach client specific headers
|
||||||
attachHeaders: headers => {
|
attachHeaders: headers => {
|
||||||
// Attach app ID header
|
// Attach app ID header
|
||||||
|
if (window["##BUDIBASE_APP_ID##"]) {
|
||||||
headers["x-budibase-app-id"] = window["##BUDIBASE_APP_ID##"]
|
headers["x-budibase-app-id"] = window["##BUDIBASE_APP_ID##"]
|
||||||
|
}
|
||||||
|
|
||||||
// Attach client header if not inside the builder preview
|
// Attach client header if not inside the builder preview
|
||||||
if (!window["##BUDIBASE_IN_BUILDER##"]) {
|
if (!window["##BUDIBASE_IN_BUILDER##"]) {
|
||||||
|
|
|
@ -141,6 +141,7 @@
|
||||||
var(--spectrum-global-dimension-size-300)
|
var(--spectrum-global-dimension-size-300)
|
||||||
);
|
);
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
line-clamp: 2;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import { isGridEvent } from "@/utils/grid"
|
import { isGridEvent } from "@/utils/grid"
|
||||||
import { DNDPlaceholderID } from "@/constants"
|
import { DNDPlaceholderID } from "@/constants"
|
||||||
import type { Component } from "@budibase/types"
|
import type { Component } from "@budibase/types"
|
||||||
|
import { DropPosition } from "@budibase/types"
|
||||||
|
|
||||||
type ChildCoords = {
|
type ChildCoords = {
|
||||||
placeholder: boolean
|
placeholder: boolean
|
||||||
|
@ -287,7 +288,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert parent + index into target + mode
|
// Convert parent + index into target + mode
|
||||||
let legacyDropTarget, legacyDropMode
|
let legacyDropTarget, legacyDropMode: DropPosition
|
||||||
const parent: Component | null = findComponentById(
|
const parent: Component | null = findComponentById(
|
||||||
get(screenStore).activeScreen?.props,
|
get(screenStore).activeScreen?.props,
|
||||||
drop.parent
|
drop.parent
|
||||||
|
@ -309,16 +310,16 @@
|
||||||
// Use inside if no existing children
|
// Use inside if no existing children
|
||||||
if (!children?.length) {
|
if (!children?.length) {
|
||||||
legacyDropTarget = parent._id
|
legacyDropTarget = parent._id
|
||||||
legacyDropMode = "inside"
|
legacyDropMode = DropPosition.INSIDE
|
||||||
} else if (drop.index === 0) {
|
} else if (drop.index === 0) {
|
||||||
legacyDropTarget = children[0]?._id
|
legacyDropTarget = children[0]?._id
|
||||||
legacyDropMode = "above"
|
legacyDropMode = DropPosition.ABOVE
|
||||||
} else {
|
} else {
|
||||||
legacyDropTarget = children[drop.index - 1]?._id
|
legacyDropTarget = children[drop.index - 1]?._id
|
||||||
legacyDropMode = "below"
|
legacyDropMode = DropPosition.BELOW
|
||||||
}
|
}
|
||||||
|
|
||||||
if (legacyDropTarget && legacyDropMode) {
|
if (legacyDropTarget && legacyDropMode && source.id) {
|
||||||
dropping = true
|
dropping = true
|
||||||
await builderStore.actions.moveComponent(
|
await builderStore.actions.moveComponent(
|
||||||
source.id,
|
source.id,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
Devices,
|
Devices,
|
||||||
GridDragMode,
|
GridDragMode,
|
||||||
} from "@/utils/grid"
|
} from "@/utils/grid"
|
||||||
|
import { DropPosition } from "@budibase/types"
|
||||||
|
|
||||||
type GridDragSide =
|
type GridDragSide =
|
||||||
| "top"
|
| "top"
|
||||||
|
@ -222,7 +223,7 @@
|
||||||
|
|
||||||
// If holding ctrl/cmd then leave behind a duplicate of this component
|
// If holding ctrl/cmd then leave behind a duplicate of this component
|
||||||
if (mode === GridDragMode.Move && (e.ctrlKey || e.metaKey)) {
|
if (mode === GridDragMode.Move && (e.ctrlKey || e.metaKey)) {
|
||||||
builderStore.actions.duplicateComponent(id, "above", false)
|
builderStore.actions.duplicateComponent(id, DropPosition.ABOVE, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find grid parent and read from DOM
|
// Find grid parent and read from DOM
|
||||||
|
|
|
@ -115,7 +115,7 @@ const createBuilderStore = () => {
|
||||||
component: string,
|
component: string,
|
||||||
parent: string,
|
parent: string,
|
||||||
index: number,
|
index: number,
|
||||||
props: Record<string, any>
|
props?: Record<string, any>
|
||||||
) => {
|
) => {
|
||||||
eventStore.actions.dispatchEvent("drop-new-component", {
|
eventStore.actions.dispatchEvent("drop-new-component", {
|
||||||
component,
|
component,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@budibase/*": [
|
"@budibase/*": [
|
||||||
"../*/src/index.ts",
|
"../*/src/index.ts",
|
||||||
|
|
|
@ -16,8 +16,5 @@
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"shortid": "2.2.15",
|
"shortid": "2.2.15",
|
||||||
"socket.io-client": "^4.7.5"
|
"socket.io-client": "^4.7.5"
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"svelte-check": "^4.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
Row,
|
Row,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
SortType,
|
|
||||||
TableSchema,
|
TableSchema,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { APIClient } from "../api/types"
|
import { APIClient } from "../api/types"
|
||||||
|
@ -72,8 +71,6 @@ export default abstract class BaseDataFetch<
|
||||||
options: DataFetchOptions<TQuery> & {
|
options: DataFetchOptions<TQuery> & {
|
||||||
datasource: TDatasource
|
datasource: TDatasource
|
||||||
|
|
||||||
sortType: SortType | null
|
|
||||||
|
|
||||||
// Client side feature customisation
|
// Client side feature customisation
|
||||||
clientSideSearching: boolean
|
clientSideSearching: boolean
|
||||||
clientSideSorting: boolean
|
clientSideSorting: boolean
|
||||||
|
@ -106,7 +103,6 @@ export default abstract class BaseDataFetch<
|
||||||
// Sorting config
|
// Sorting config
|
||||||
sortColumn: null,
|
sortColumn: null,
|
||||||
sortOrder: SortOrder.ASCENDING,
|
sortOrder: SortOrder.ASCENDING,
|
||||||
sortType: null,
|
|
||||||
|
|
||||||
// Pagination config
|
// Pagination config
|
||||||
paginate: true,
|
paginate: true,
|
||||||
|
@ -227,31 +223,12 @@ export default abstract class BaseDataFetch<
|
||||||
this.options.sortColumn = this.getDefaultSortColumn(definition, schema)
|
this.options.sortColumn = this.getDefaultSortColumn(definition, schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have a sort column specified then just ensure we don't set
|
|
||||||
// any sorting params
|
|
||||||
if (!this.options.sortColumn) {
|
|
||||||
this.options.sortOrder = SortOrder.ASCENDING
|
|
||||||
this.options.sortType = null
|
|
||||||
} else {
|
|
||||||
// Otherwise determine what sort type to use base on sort column
|
|
||||||
this.options.sortType = SortType.STRING
|
|
||||||
const fieldSchema = schema?.[this.options.sortColumn]
|
|
||||||
if (
|
|
||||||
fieldSchema?.type === FieldType.NUMBER ||
|
|
||||||
fieldSchema?.type === FieldType.BIGINT ||
|
|
||||||
("calculationType" in fieldSchema && fieldSchema?.calculationType)
|
|
||||||
) {
|
|
||||||
this.options.sortType = SortType.NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no sort order, default to ascending
|
// If no sort order, default to ascending
|
||||||
if (!this.options.sortOrder) {
|
if (!this.options.sortOrder) {
|
||||||
this.options.sortOrder = SortOrder.ASCENDING
|
this.options.sortOrder = SortOrder.ASCENDING
|
||||||
} else {
|
} else {
|
||||||
// Ensure sortOrder matches the enum
|
// Ensure sortOrder matches the enum
|
||||||
this.options.sortOrder =
|
this.options.sortOrder = this.options.sortOrder.toLowerCase() as SortOrder
|
||||||
this.options.sortOrder.toLowerCase() as SortOrder
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the query
|
// Build the query
|
||||||
|
@ -294,7 +271,6 @@ export default abstract class BaseDataFetch<
|
||||||
const {
|
const {
|
||||||
sortColumn,
|
sortColumn,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
sortType,
|
|
||||||
limit,
|
limit,
|
||||||
clientSideSearching,
|
clientSideSearching,
|
||||||
clientSideSorting,
|
clientSideSorting,
|
||||||
|
@ -311,8 +287,8 @@ export default abstract class BaseDataFetch<
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't support sorting, do a client-side sort
|
// If we don't support sorting, do a client-side sort
|
||||||
if (!this.features.supportsSort && clientSideSorting && sortType) {
|
if (!this.features.supportsSort && clientSideSorting && sortColumn) {
|
||||||
rows = sort(rows, sortColumn as any, sortOrder, sortType)
|
rows = sort(rows, sortColumn, sortOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't support pagination, do a client-side limit
|
// If we don't support pagination, do a client-side limit
|
||||||
|
|
|
@ -29,8 +29,7 @@ export default class TableFetch extends BaseDataFetch<TableDatasource, Table> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getData() {
|
async getData() {
|
||||||
const { datasource, limit, sortColumn, sortOrder, sortType, paginate } =
|
const { datasource, limit, sortColumn, sortOrder, paginate } = this.options
|
||||||
this.options
|
|
||||||
const { tableId } = datasource
|
const { tableId } = datasource
|
||||||
const { cursor, query } = get(this.store)
|
const { cursor, query } = get(this.store)
|
||||||
|
|
||||||
|
@ -41,7 +40,6 @@ export default class TableFetch extends BaseDataFetch<TableDatasource, Table> {
|
||||||
limit,
|
limit,
|
||||||
sort: sortColumn,
|
sort: sortColumn,
|
||||||
sortOrder: sortOrder ?? SortOrder.ASCENDING,
|
sortOrder: sortOrder ?? SortOrder.ASCENDING,
|
||||||
sortType,
|
|
||||||
paginate,
|
paginate,
|
||||||
bookmark: cursor,
|
bookmark: cursor,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
SearchViewRowRequest,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
ViewDatasource,
|
ViewDatasource,
|
||||||
ViewV2Enriched,
|
ViewV2Enriched,
|
||||||
|
@ -40,8 +41,7 @@ export default class ViewV2Fetch extends BaseDataFetch<
|
||||||
}
|
}
|
||||||
|
|
||||||
async getData() {
|
async getData() {
|
||||||
const { datasource, limit, sortColumn, sortOrder, sortType, paginate } =
|
const { datasource, limit, sortColumn, sortOrder, paginate } = this.options
|
||||||
this.options
|
|
||||||
const { cursor, query, definition } = get(this.store)
|
const { cursor, query, definition } = get(this.store)
|
||||||
|
|
||||||
// If this is a calculation view and we have no calculations, return nothing
|
// If this is a calculation view and we have no calculations, return nothing
|
||||||
|
@ -68,14 +68,13 @@ export default class ViewV2Fetch extends BaseDataFetch<
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const request = {
|
const request: SearchViewRowRequest = {
|
||||||
query,
|
query,
|
||||||
paginate,
|
paginate,
|
||||||
limit,
|
limit,
|
||||||
bookmark: cursor,
|
bookmark: cursor,
|
||||||
sort: sortColumn,
|
sort: sortColumn,
|
||||||
sortOrder: sortOrder,
|
sortOrder: sortOrder,
|
||||||
sortType,
|
|
||||||
}
|
}
|
||||||
if (paginate) {
|
if (paginate) {
|
||||||
const res = await this.API.viewV2.fetch(datasource.id, {
|
const res = await this.API.viewV2.fetch(datasource.id, {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export { createAPIClient } from "./api"
|
export { createAPIClient } from "./api"
|
||||||
export type { APIClient } from "./api"
|
export type { APIClient } from "./api"
|
||||||
export { fetchData, DataFetchMap } from "./fetch"
|
export { fetchData, DataFetchMap, type DataFetchType } from "./fetch"
|
||||||
export * as Constants from "./constants"
|
export * as Constants from "./constants"
|
||||||
export * from "./stores"
|
export * from "./stores"
|
||||||
export * from "./utils"
|
export * from "./utils"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config
|
|
@ -263,7 +263,6 @@ export async function search(ctx: Ctx<SearchRowRequest, SearchRowResponse>) {
|
||||||
limit: searchRequest.limit,
|
limit: searchRequest.limit,
|
||||||
sort: searchRequest.sort ?? undefined,
|
sort: searchRequest.sort ?? undefined,
|
||||||
sortOrder: searchRequest.sortOrder,
|
sortOrder: searchRequest.sortOrder,
|
||||||
sortType: searchRequest.sortType ?? undefined,
|
|
||||||
countRows: searchRequest.countRows,
|
countRows: searchRequest.countRows,
|
||||||
version: searchRequest.version,
|
version: searchRequest.version,
|
||||||
disableEscaping: searchRequest.disableEscaping,
|
disableEscaping: searchRequest.disableEscaping,
|
||||||
|
|
|
@ -63,14 +63,12 @@ function getSortOptions(request: SearchViewRowRequest, view: ViewV2) {
|
||||||
return {
|
return {
|
||||||
sort: request.sort,
|
sort: request.sort,
|
||||||
sortOrder: request.sortOrder,
|
sortOrder: request.sortOrder,
|
||||||
sortType: request.sortType ?? undefined,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (view.sort) {
|
if (view.sort) {
|
||||||
return {
|
return {
|
||||||
sort: view.sort.field,
|
sort: view.sort.field,
|
||||||
sortOrder: view.sort.order,
|
sortOrder: view.sort.order,
|
||||||
sortType: view.sort.type,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ import {
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
import tk from "timekeeper"
|
import tk from "timekeeper"
|
||||||
import { encodeJSBinding } from "@budibase/string-templates"
|
import { encodeJSBinding } from "@budibase/string-templates"
|
||||||
import { dataFilters } from "@budibase/shared-core"
|
import { dataFilters, InMemorySearchQuery } from "@budibase/shared-core"
|
||||||
import { Knex } from "knex"
|
import { Knex } from "knex"
|
||||||
import { generator, structures, mocks } from "@budibase/backend-core/tests"
|
import { generator, structures, mocks } from "@budibase/backend-core/tests"
|
||||||
import { DEFAULT_EMPLOYEE_TABLE_SCHEMA } from "../../../db/defaultData/datasource_bb_default"
|
import { DEFAULT_EMPLOYEE_TABLE_SCHEMA } from "../../../db/defaultData/datasource_bb_default"
|
||||||
|
@ -200,31 +200,26 @@ if (descriptions.length) {
|
||||||
const isView = sourceType === "view"
|
const isView = sourceType === "view"
|
||||||
|
|
||||||
class SearchAssertion {
|
class SearchAssertion {
|
||||||
constructor(private readonly query: SearchRowRequest) {}
|
constructor(
|
||||||
|
private readonly query: SearchRowRequest & {
|
||||||
|
sortType?: SortType
|
||||||
|
}
|
||||||
|
) {}
|
||||||
|
|
||||||
private async performSearch(): Promise<SearchResponse<Row>> {
|
private async performSearch(): Promise<SearchResponse<Row>> {
|
||||||
if (isInMemory) {
|
if (isInMemory) {
|
||||||
const inMemoryQuery: RequiredKeys<
|
const inMemoryQuery: RequiredKeys<InMemorySearchQuery> = {
|
||||||
Omit<RowSearchParams, "tableId">
|
|
||||||
> = {
|
|
||||||
sort: this.query.sort ?? undefined,
|
sort: this.query.sort ?? undefined,
|
||||||
query: { ...this.query.query },
|
query: { ...this.query.query },
|
||||||
paginate: this.query.paginate,
|
|
||||||
bookmark: this.query.bookmark ?? undefined,
|
|
||||||
limit: this.query.limit,
|
limit: this.query.limit,
|
||||||
sortOrder: this.query.sortOrder,
|
sortOrder: this.query.sortOrder,
|
||||||
sortType: this.query.sortType ?? undefined,
|
sortType: this.query.sortType ?? undefined,
|
||||||
version: this.query.version,
|
|
||||||
disableEscaping: this.query.disableEscaping,
|
|
||||||
countRows: this.query.countRows,
|
countRows: this.query.countRows,
|
||||||
viewId: undefined,
|
|
||||||
fields: undefined,
|
|
||||||
indexer: undefined,
|
|
||||||
rows: undefined,
|
|
||||||
}
|
}
|
||||||
return dataFilters.search(_.cloneDeep(rows), inMemoryQuery)
|
return dataFilters.search(_.cloneDeep(rows), inMemoryQuery)
|
||||||
} else {
|
} else {
|
||||||
return config.api.row.search(tableOrViewId, this.query)
|
const { sortType, ...query } = this.query
|
||||||
|
return config.api.row.search(tableOrViewId, query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +395,9 @@ if (descriptions.length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectSearch(query: SearchRowRequest) {
|
function expectSearch(
|
||||||
|
query: SearchRowRequest & { sortType?: SortType }
|
||||||
|
) {
|
||||||
return new SearchAssertion(query)
|
return new SearchAssertion(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,6 +1116,7 @@ if (descriptions.length) {
|
||||||
}).toMatchExactly([{ name: "foo" }, { name: "bar" }])
|
}).toMatchExactly([{ name: "foo" }, { name: "bar" }])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
isInMemory &&
|
||||||
describe("sortType STRING", () => {
|
describe("sortType STRING", () => {
|
||||||
it("sorts ascending", async () => {
|
it("sorts ascending", async () => {
|
||||||
await expectSearch({
|
await expectSearch({
|
||||||
|
@ -1319,6 +1317,7 @@ if (descriptions.length) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
isInMemory &&
|
||||||
describe("sortType NUMBER", () => {
|
describe("sortType NUMBER", () => {
|
||||||
it("sorts ascending", async () => {
|
it("sorts ascending", async () => {
|
||||||
await expectSearch({
|
await expectSearch({
|
||||||
|
@ -1473,6 +1472,7 @@ if (descriptions.length) {
|
||||||
}).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }])
|
}).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
isInMemory &&
|
||||||
describe("sortType STRING", () => {
|
describe("sortType STRING", () => {
|
||||||
it("sorts ascending", async () => {
|
it("sorts ascending", async () => {
|
||||||
await expectSearch({
|
await expectSearch({
|
||||||
|
@ -1639,6 +1639,7 @@ if (descriptions.length) {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
isInMemory &&
|
||||||
describe("sortType STRING", () => {
|
describe("sortType STRING", () => {
|
||||||
it("sorts ascending", async () => {
|
it("sorts ascending", async () => {
|
||||||
await expectSearch({
|
await expectSearch({
|
||||||
|
@ -1675,6 +1676,7 @@ if (descriptions.length) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
!isInMemory &&
|
||||||
describe("datetime - date only", () => {
|
describe("datetime - date only", () => {
|
||||||
describe.each([true, false])(
|
describe.each([true, false])(
|
||||||
"saved with timestamp: %s",
|
"saved with timestamp: %s",
|
||||||
|
@ -1847,6 +1849,7 @@ if (descriptions.length) {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
isInMemory &&
|
||||||
describe("sortType STRING", () => {
|
describe("sortType STRING", () => {
|
||||||
it("sorts ascending", async () => {
|
it("sorts ascending", async () => {
|
||||||
await expectSearch({
|
await expectSearch({
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {
|
||||||
SearchResponse,
|
SearchResponse,
|
||||||
SearchViewRowRequest,
|
SearchViewRowRequest,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
SortType,
|
|
||||||
StaticQuotaName,
|
StaticQuotaName,
|
||||||
Table,
|
Table,
|
||||||
TableSchema,
|
TableSchema,
|
||||||
|
@ -154,7 +153,6 @@ if (descriptions.length) {
|
||||||
sort: {
|
sort: {
|
||||||
field: "fieldToSort",
|
field: "fieldToSort",
|
||||||
order: SortOrder.DESCENDING,
|
order: SortOrder.DESCENDING,
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
id: { visible: true },
|
id: { visible: true },
|
||||||
|
@ -217,7 +215,6 @@ if (descriptions.length) {
|
||||||
sort: {
|
sort: {
|
||||||
field: "fieldToSort",
|
field: "fieldToSort",
|
||||||
order: SortOrder.DESCENDING,
|
order: SortOrder.DESCENDING,
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
id: { visible: true },
|
id: { visible: true },
|
||||||
|
@ -1147,7 +1144,6 @@ if (descriptions.length) {
|
||||||
sort: {
|
sort: {
|
||||||
field: generator.word(),
|
field: generator.word(),
|
||||||
order: SortOrder.DESCENDING,
|
order: SortOrder.DESCENDING,
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
id: { visible: true },
|
id: { visible: true },
|
||||||
|
@ -3153,7 +3149,6 @@ if (descriptions.length) {
|
||||||
{
|
{
|
||||||
field: string
|
field: string
|
||||||
order?: SortOrder
|
order?: SortOrder
|
||||||
type?: SortType
|
|
||||||
},
|
},
|
||||||
string[]
|
string[]
|
||||||
][] = [
|
][] = [
|
||||||
|
@ -3161,7 +3156,6 @@ if (descriptions.length) {
|
||||||
{
|
{
|
||||||
field: "name",
|
field: "name",
|
||||||
order: SortOrder.ASCENDING,
|
order: SortOrder.ASCENDING,
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
},
|
||||||
["Alice", "Bob", "Charly", "Danny"],
|
["Alice", "Bob", "Charly", "Danny"],
|
||||||
],
|
],
|
||||||
|
@ -3178,22 +3172,6 @@ if (descriptions.length) {
|
||||||
},
|
},
|
||||||
["Danny", "Charly", "Bob", "Alice"],
|
["Danny", "Charly", "Bob", "Alice"],
|
||||||
],
|
],
|
||||||
[
|
|
||||||
{
|
|
||||||
field: "name",
|
|
||||||
order: SortOrder.DESCENDING,
|
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
|
||||||
["Danny", "Charly", "Bob", "Alice"],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
field: "age",
|
|
||||||
order: SortOrder.ASCENDING,
|
|
||||||
type: SortType.NUMBER,
|
|
||||||
},
|
|
||||||
["Danny", "Alice", "Charly", "Bob"],
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
field: "age",
|
field: "age",
|
||||||
|
@ -3204,15 +3182,13 @@ if (descriptions.length) {
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
field: "age",
|
field: "age",
|
||||||
order: SortOrder.DESCENDING,
|
|
||||||
},
|
},
|
||||||
["Bob", "Charly", "Alice", "Danny"],
|
["Danny", "Alice", "Charly", "Bob"],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
field: "age",
|
field: "age",
|
||||||
order: SortOrder.DESCENDING,
|
order: SortOrder.DESCENDING,
|
||||||
type: SortType.NUMBER,
|
|
||||||
},
|
},
|
||||||
["Bob", "Charly", "Alice", "Danny"],
|
["Bob", "Charly", "Alice", "Danny"],
|
||||||
],
|
],
|
||||||
|
@ -3299,7 +3275,6 @@ if (descriptions.length) {
|
||||||
sort: {
|
sort: {
|
||||||
field: "name",
|
field: "name",
|
||||||
order: SortOrder.ASCENDING,
|
order: SortOrder.ASCENDING,
|
||||||
type: SortType.STRING,
|
|
||||||
},
|
},
|
||||||
schema: viewSchema,
|
schema: viewSchema,
|
||||||
})
|
})
|
||||||
|
@ -3307,7 +3282,6 @@ if (descriptions.length) {
|
||||||
const response = await config.api.viewV2.search(view.id, {
|
const response = await config.api.viewV2.search(view.id, {
|
||||||
sort: sortParams.field,
|
sort: sortParams.field,
|
||||||
sortOrder: sortParams.order,
|
sortOrder: sortParams.order,
|
||||||
sortType: sortParams.type,
|
|
||||||
query: {},
|
query: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,7 @@ class S3Integration implements IntegrationBase {
|
||||||
secretAccessKey: config.secretAccessKey,
|
secretAccessKey: config.secretAccessKey,
|
||||||
},
|
},
|
||||||
region: config.region,
|
region: config.region,
|
||||||
|
endpoint: config.endpoint,
|
||||||
}
|
}
|
||||||
if (config.endpoint) {
|
if (config.endpoint) {
|
||||||
this.config.forcePathStyle = true
|
this.config.forcePathStyle = true
|
||||||
|
|
|
@ -46,7 +46,6 @@ export async function search(
|
||||||
query: options.query,
|
query: options.query,
|
||||||
sort: options.sort,
|
sort: options.sort,
|
||||||
sortOrder: options.sortOrder,
|
sortOrder: options.sortOrder,
|
||||||
sortType: options.sortType,
|
|
||||||
limit: options.limit,
|
limit: options.limit,
|
||||||
bookmark: options.bookmark,
|
bookmark: options.bookmark,
|
||||||
paginate: options.paginate,
|
paginate: options.paginate,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
Aggregation,
|
Aggregation,
|
||||||
|
AutoFieldSubType,
|
||||||
CalculationType,
|
CalculationType,
|
||||||
DocumentType,
|
DocumentType,
|
||||||
EnrichedQueryJson,
|
EnrichedQueryJson,
|
||||||
|
@ -420,7 +421,11 @@ export async function search(
|
||||||
}
|
}
|
||||||
} else if (sortField) {
|
} else if (sortField) {
|
||||||
const sortType =
|
const sortType =
|
||||||
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
|
sortField.type === FieldType.NUMBER ||
|
||||||
|
(sortField.type === FieldType.AUTO &&
|
||||||
|
sortField.subtype === AutoFieldSubType.AUTO_ID)
|
||||||
|
? SortType.NUMBER
|
||||||
|
: SortType.STRING
|
||||||
request.sort = {
|
request.sort = {
|
||||||
[mapToUserColumn(sortField.name)]: {
|
[mapToUserColumn(sortField.name)]: {
|
||||||
direction: params.sortOrder || SortOrder.ASCENDING,
|
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {
|
||||||
SortType,
|
SortType,
|
||||||
FieldConstraints,
|
FieldConstraints,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
RowSearchParams,
|
|
||||||
EmptyFilterOption,
|
EmptyFilterOption,
|
||||||
SearchResponse,
|
SearchResponse,
|
||||||
Table,
|
Table,
|
||||||
|
@ -25,6 +24,8 @@ import {
|
||||||
isArraySearchOperator,
|
isArraySearchOperator,
|
||||||
isRangeSearchOperator,
|
isRangeSearchOperator,
|
||||||
SearchFilter,
|
SearchFilter,
|
||||||
|
WithRequired,
|
||||||
|
SearchParams,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
import { OperatorOptions, SqlNumberTypeRangeMap } from "./constants"
|
import { OperatorOptions, SqlNumberTypeRangeMap } from "./constants"
|
||||||
|
@ -521,9 +522,19 @@ export function fixupFilterArrays(filters: SearchFilters) {
|
||||||
return filters
|
return filters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SearchQuery = WithRequired<
|
||||||
|
Pick<
|
||||||
|
SearchParams,
|
||||||
|
"query" | "sort" | "sortOrder" | "sortType" | "limit" | "countRows"
|
||||||
|
>,
|
||||||
|
"query"
|
||||||
|
>
|
||||||
|
|
||||||
|
export type InMemorySearchQuery = SearchQuery
|
||||||
|
|
||||||
export function search<T extends Record<string, any>>(
|
export function search<T extends Record<string, any>>(
|
||||||
docs: T[],
|
docs: T[],
|
||||||
query: Omit<RowSearchParams, "tableId">
|
query: SearchQuery
|
||||||
): SearchResponse<T> {
|
): SearchResponse<T> {
|
||||||
let result = runQuery(docs, query.query)
|
let result = runQuery(docs, query.query)
|
||||||
if (query.sort) {
|
if (query.sort) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export * from "./constants"
|
export * from "./constants"
|
||||||
export * as dataFilters from "./filters"
|
export * as dataFilters from "./filters"
|
||||||
|
export type * from "./filters"
|
||||||
export * as helpers from "./helpers"
|
export * as helpers from "./helpers"
|
||||||
export * as utils from "./utils"
|
export * as utils from "./utils"
|
||||||
export * as sdk from "./sdk"
|
export * as sdk from "./sdk"
|
||||||
|
|
|
@ -11,7 +11,7 @@ export interface SaveQueryRequest extends Query {}
|
||||||
export interface SaveQueryResponse extends Query {}
|
export interface SaveQueryResponse extends Query {}
|
||||||
|
|
||||||
export interface ImportRestQueryRequest {
|
export interface ImportRestQueryRequest {
|
||||||
datasourceId: string
|
datasourceId?: string
|
||||||
data: string
|
data: string
|
||||||
datasource: Datasource
|
datasource: Datasource
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,7 @@ import {
|
||||||
SearchFilterKey,
|
SearchFilterKey,
|
||||||
} from "../../../../sdk"
|
} from "../../../../sdk"
|
||||||
import { Row } from "../../../../documents"
|
import { Row } from "../../../../documents"
|
||||||
import {
|
import { PaginationResponse, SortOrder } from "../../../../api/web/pagination"
|
||||||
PaginationResponse,
|
|
||||||
SortOrder,
|
|
||||||
SortType,
|
|
||||||
} from "../../../../api/web/pagination"
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
const fieldKey = z
|
const fieldKey = z
|
||||||
|
@ -70,7 +66,6 @@ const searchRowRequest = z.object({
|
||||||
limit: z.number().optional(),
|
limit: z.number().optional(),
|
||||||
sort: z.string().nullish(),
|
sort: z.string().nullish(),
|
||||||
sortOrder: z.nativeEnum(SortOrder).optional(),
|
sortOrder: z.nativeEnum(SortOrder).optional(),
|
||||||
sortType: z.nativeEnum(SortType).nullish(),
|
|
||||||
version: z.string().optional(),
|
version: z.string().optional(),
|
||||||
disableEscaping: z.boolean().optional(),
|
disableEscaping: z.boolean().optional(),
|
||||||
countRows: z.boolean().optional(),
|
countRows: z.boolean().optional(),
|
||||||
|
@ -83,7 +78,6 @@ export type SearchViewRowRequest = Pick<
|
||||||
SearchRowRequest,
|
SearchRowRequest,
|
||||||
| "sort"
|
| "sort"
|
||||||
| "sortOrder"
|
| "sortOrder"
|
||||||
| "sortType"
|
|
||||||
| "limit"
|
| "limit"
|
||||||
| "bookmark"
|
| "bookmark"
|
||||||
| "paginate"
|
| "paginate"
|
||||||
|
|
|
@ -50,7 +50,7 @@ export interface SearchParams {
|
||||||
|
|
||||||
// when searching for rows we want a more extensive search type that requires certain properties
|
// when searching for rows we want a more extensive search type that requires certain properties
|
||||||
export interface RowSearchParams
|
export interface RowSearchParams
|
||||||
extends WithRequired<SearchParams, "tableId" | "query"> {}
|
extends WithRequired<Omit<SearchParams, "sortType">, "tableId" | "query"> {}
|
||||||
|
|
||||||
export interface SearchResponse<T> {
|
export interface SearchResponse<T> {
|
||||||
rows: T[]
|
rows: T[]
|
||||||
|
|
|
@ -20499,10 +20499,10 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
svelte-check@^4.1.0:
|
svelte-check@^4.1.5:
|
||||||
version "4.1.0"
|
version "4.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-4.1.0.tgz#4389c1c88aa24f3d06fe0df94f9075a55017256d"
|
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-4.1.5.tgz#afdb3f8050c123064124d5aa7821365c7befa7a4"
|
||||||
integrity sha512-AflEZYqI578KuDZcpcorPSf597LStxlkN7XqXi38u09zlHODVKd7c+7OuubGzbhgGRUqNTdQCZ+Ga96iRXEf2g==
|
integrity sha512-Gb0T2IqBNe1tLB9EB1Qh+LOe+JB8wt2/rNBDGvkxQVvk8vNeAoG+vZgFB/3P5+zC7RWlyBlzm9dVjZFph/maIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/trace-mapping" "^0.3.25"
|
"@jridgewell/trace-mapping" "^0.3.25"
|
||||||
chokidar "^4.0.1"
|
chokidar "^4.0.1"
|
||||||
|
|
Loading…
Reference in New Issue