Merge branch 'develop' of github.com:Budibase/budibase into grid-all-datasources
This commit is contained in:
commit
922a851710
|
@ -14,7 +14,7 @@ jobs:
|
||||||
- uses: passeidireto/trigger-external-workflow-action@main
|
- uses: passeidireto/trigger-external-workflow-action@main
|
||||||
env:
|
env:
|
||||||
PAYLOAD_BRANCH: ${{ github.head_ref }}
|
PAYLOAD_BRANCH: ${{ github.head_ref }}
|
||||||
PAYLOAD_PR_NUMBER: ${{ github.ref }}
|
PAYLOAD_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
with:
|
with:
|
||||||
repository: budibase/budibase-deploys
|
repository: budibase/budibase-deploys
|
||||||
event: featurebranch-qa-close
|
event: featurebranch-qa-close
|
||||||
|
|
|
@ -13,7 +13,7 @@ jobs:
|
||||||
- uses: passeidireto/trigger-external-workflow-action@main
|
- uses: passeidireto/trigger-external-workflow-action@main
|
||||||
env:
|
env:
|
||||||
PAYLOAD_BRANCH: ${{ github.head_ref }}
|
PAYLOAD_BRANCH: ${{ github.head_ref }}
|
||||||
PAYLOAD_PR_NUMBER: ${{ github.ref }}
|
PAYLOAD_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
with:
|
with:
|
||||||
repository: budibase/budibase-deploys
|
repository: budibase/budibase-deploys
|
||||||
event: featurebranch-qa-deploy
|
event: featurebranch-qa-deploy
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.10.16-alpha.19",
|
"version": "2.11.5-alpha.4",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
AutomationStepIdArray,
|
AutomationStepIdArray,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
|
DatasourceFeature,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import joi from "joi"
|
import joi from "joi"
|
||||||
|
|
||||||
|
@ -67,9 +68,27 @@ function validateDatasource(schema: any) {
|
||||||
version: joi.string().optional(),
|
version: joi.string().optional(),
|
||||||
schema: joi.object({
|
schema: joi.object({
|
||||||
docs: joi.string(),
|
docs: joi.string(),
|
||||||
|
plus: joi.boolean().optional(),
|
||||||
|
isSQL: joi.boolean().optional(),
|
||||||
|
auth: joi
|
||||||
|
.object({
|
||||||
|
type: joi.string().required(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
features: joi
|
||||||
|
.object(
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.values(DatasourceFeature).map(key => [
|
||||||
|
key,
|
||||||
|
joi.boolean().optional(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
|
relationships: joi.boolean().optional(),
|
||||||
|
description: joi.string().required(),
|
||||||
friendlyName: joi.string().required(),
|
friendlyName: joi.string().required(),
|
||||||
type: joi.string().allow(...DATASOURCE_TYPES),
|
type: joi.string().allow(...DATASOURCE_TYPES),
|
||||||
description: joi.string().required(),
|
|
||||||
datasource: joi.object().pattern(joi.string(), fieldValidator).required(),
|
datasource: joi.object().pattern(joi.string(), fieldValidator).required(),
|
||||||
query: joi
|
query: joi
|
||||||
.object()
|
.object()
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import { Select, Checkbox } from "@budibase/bbui"
|
import { Select, Checkbox } from "@budibase/bbui"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import RowSelectorTypes from "./RowSelectorTypes.svelte"
|
import RowSelectorTypes from "./RowSelectorTypes.svelte"
|
||||||
|
import DrawerBindableSlot from "../../common/bindings/DrawerBindableSlot.svelte"
|
||||||
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -108,14 +110,29 @@
|
||||||
<div class="schema-fields">
|
<div class="schema-fields">
|
||||||
{#each schemaFields as [field, schema]}
|
{#each schemaFields as [field, schema]}
|
||||||
{#if !schema.autocolumn && schema.type !== "attachment"}
|
{#if !schema.autocolumn && schema.type !== "attachment"}
|
||||||
<RowSelectorTypes
|
<DrawerBindableSlot
|
||||||
{isTestModal}
|
fillWidth
|
||||||
{field}
|
title={value.title}
|
||||||
|
label={field}
|
||||||
|
panel={AutomationBindingPanel}
|
||||||
|
type={schema.type}
|
||||||
{schema}
|
{schema}
|
||||||
bindings={parsedBindings}
|
value={value[field]}
|
||||||
{value}
|
on:change={e => onChange(e, field)}
|
||||||
{onChange}
|
{bindings}
|
||||||
/>
|
allowJS={true}
|
||||||
|
updateOnChange={false}
|
||||||
|
drawerLeft="260px"
|
||||||
|
>
|
||||||
|
<RowSelectorTypes
|
||||||
|
{isTestModal}
|
||||||
|
{field}
|
||||||
|
{schema}
|
||||||
|
bindings={parsedBindings}
|
||||||
|
{value}
|
||||||
|
{onChange}
|
||||||
|
/>
|
||||||
|
</DrawerBindableSlot>
|
||||||
{/if}
|
{/if}
|
||||||
{#if isUpdateRow && schema.type === "link"}
|
{#if isUpdateRow && schema.type === "link"}
|
||||||
<div class="checkbox-field">
|
<div class="checkbox-field">
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
||||||
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
||||||
import DrawerBindableSlot from "../../common/bindings/DrawerBindableSlot.svelte"
|
|
||||||
import ModalBindableInput from "../../common/bindings/ModalBindableInput.svelte"
|
import ModalBindableInput from "../../common/bindings/ModalBindableInput.svelte"
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
import Editor from "components/integration/QueryEditor.svelte"
|
import Editor from "components/integration/QueryEditor.svelte"
|
||||||
|
@ -31,88 +30,73 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DrawerBindableSlot
|
{#if schemaHasOptions(schema) && schema.type !== "array"}
|
||||||
fillWidth
|
<Select
|
||||||
title={value.title}
|
on:change={e => onChange(e, field)}
|
||||||
label={field}
|
label={field}
|
||||||
panel={AutomationBindingPanel}
|
value={value[field]}
|
||||||
type={schema.type}
|
options={schema.constraints.inclusion}
|
||||||
{schema}
|
/>
|
||||||
value={value[field]}
|
{:else if schema.type === "datetime"}
|
||||||
on:change={e => onChange(e, field)}
|
<DatePicker
|
||||||
{bindings}
|
label={field}
|
||||||
allowJS={true}
|
value={value[field]}
|
||||||
updateOnChange={false}
|
on:change={e => onChange(e, field)}
|
||||||
drawerLeft="260px"
|
/>
|
||||||
>
|
{:else if schema.type === "boolean"}
|
||||||
{#if schemaHasOptions(schema) && schema.type !== "array"}
|
<Select
|
||||||
<Select
|
on:change={e => onChange(e, field)}
|
||||||
on:change={e => onChange(e, field)}
|
label={field}
|
||||||
label={field}
|
value={value[field]}
|
||||||
|
options={[
|
||||||
|
{ label: "True", value: "true" },
|
||||||
|
{ label: "False", value: "false" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "array"}
|
||||||
|
<Multiselect
|
||||||
|
bind:value={value[field]}
|
||||||
|
label={field}
|
||||||
|
options={schema.constraints.inclusion}
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "longform"}
|
||||||
|
<TextArea
|
||||||
|
label={field}
|
||||||
|
bind:value={value[field]}
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "json"}
|
||||||
|
<span>
|
||||||
|
<Label>{field}</Label>
|
||||||
|
<Editor
|
||||||
|
editorHeight="150"
|
||||||
|
mode="json"
|
||||||
|
on:change={e => {
|
||||||
|
if (e.detail?.value !== value[field]) {
|
||||||
|
onChange(e, field, schema.type)
|
||||||
|
}
|
||||||
|
}}
|
||||||
value={value[field]}
|
value={value[field]}
|
||||||
options={schema.constraints.inclusion}
|
|
||||||
/>
|
/>
|
||||||
{:else if schema.type === "datetime"}
|
</span>
|
||||||
<DatePicker
|
{:else if schema.type === "link"}
|
||||||
label={field}
|
<LinkedRowSelector
|
||||||
value={value[field]}
|
bind:linkedRows={value[field]}
|
||||||
on:change={e => onChange(e, field)}
|
{schema}
|
||||||
/>
|
on:change={e => onChange(e, field)}
|
||||||
{:else if schema.type === "boolean"}
|
/>
|
||||||
<Select
|
{:else if schema.type === "string" || schema.type === "number"}
|
||||||
on:change={e => onChange(e, field)}
|
<svelte:component
|
||||||
label={field}
|
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
||||||
value={value[field]}
|
panel={AutomationBindingPanel}
|
||||||
options={[
|
value={value[field]}
|
||||||
{ label: "True", value: "true" },
|
on:change={e => onChange(e, field)}
|
||||||
{ label: "False", value: "false" },
|
label={field}
|
||||||
]}
|
type="string"
|
||||||
/>
|
bindings={parsedBindings}
|
||||||
{:else if schema.type === "array"}
|
fillWidth={true}
|
||||||
<Multiselect
|
allowJS={true}
|
||||||
bind:value={value[field]}
|
updateOnChange={false}
|
||||||
label={field}
|
/>
|
||||||
options={schema.constraints.inclusion}
|
{/if}
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "longform"}
|
|
||||||
<TextArea
|
|
||||||
label={field}
|
|
||||||
bind:value={value[field]}
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "json"}
|
|
||||||
<span>
|
|
||||||
<Label>{field}</Label>
|
|
||||||
<Editor
|
|
||||||
editorHeight="150"
|
|
||||||
mode="json"
|
|
||||||
on:change={e => {
|
|
||||||
if (e.detail?.value !== value[field]) {
|
|
||||||
onChange(e, field, schema.type)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
value={value[field]}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
{:else if schema.type === "link"}
|
|
||||||
<LinkedRowSelector
|
|
||||||
bind:linkedRows={value[field]}
|
|
||||||
{schema}
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "string" || schema.type === "number"}
|
|
||||||
<svelte:component
|
|
||||||
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
|
||||||
panel={AutomationBindingPanel}
|
|
||||||
value={value[field]}
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
label={field}
|
|
||||||
type="string"
|
|
||||||
bindings={parsedBindings}
|
|
||||||
fillWidth={true}
|
|
||||||
allowJS={true}
|
|
||||||
updateOnChange={false}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</DrawerBindableSlot>
|
|
||||||
|
|
|
@ -277,10 +277,7 @@
|
||||||
dispatch("updatecolumns")
|
dispatch("updatecolumns")
|
||||||
gridDispatch("close-edit-column")
|
gridDispatch("close-edit-column")
|
||||||
|
|
||||||
if (
|
if (saveColumn.type === LINK_TYPE) {
|
||||||
saveColumn.type === LINK_TYPE &&
|
|
||||||
saveColumn.relationshipType === RelationshipType.MANY_TO_MANY
|
|
||||||
) {
|
|
||||||
// Fetching the new tables
|
// Fetching the new tables
|
||||||
tables.fetch()
|
tables.fetch()
|
||||||
// Fetching the new relationships
|
// Fetching the new relationships
|
||||||
|
@ -312,6 +309,11 @@
|
||||||
confirmDeleteDialog.hide()
|
confirmDeleteDialog.hide()
|
||||||
dispatch("updatecolumns")
|
dispatch("updatecolumns")
|
||||||
gridDispatch("close-edit-column")
|
gridDispatch("close-edit-column")
|
||||||
|
|
||||||
|
if (editableColumn.type === LINK_TYPE) {
|
||||||
|
// Updating the relationships
|
||||||
|
datasources.fetch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error(`Error deleting column: ${error.message}`)
|
notifications.error(`Error deleting column: ${error.message}`)
|
||||||
|
|
|
@ -57,7 +57,8 @@
|
||||||
label: table.name,
|
label: table.name,
|
||||||
value: table._id,
|
value: table._id,
|
||||||
}))
|
}))
|
||||||
$: valid = getErrorCount(errors) === 0 && allRequiredAttributesSet()
|
$: valid =
|
||||||
|
getErrorCount(errors) === 0 && allRequiredAttributesSet(relationshipType)
|
||||||
$: isManyToMany = relationshipType === RelationshipType.MANY_TO_MANY
|
$: isManyToMany = relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
$: isManyToOne = relationshipType === RelationshipType.MANY_TO_ONE
|
$: isManyToOne = relationshipType === RelationshipType.MANY_TO_ONE
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@
|
||||||
return Object.entries(errors).filter(entry => !!entry[1]).length
|
return Object.entries(errors).filter(entry => !!entry[1]).length
|
||||||
}
|
}
|
||||||
|
|
||||||
function allRequiredAttributesSet() {
|
function allRequiredAttributesSet(relationshipType) {
|
||||||
const base = getTable(fromId) && getTable(toId) && fromColumn && toColumn
|
const base = getTable(fromId) && getTable(toId) && fromColumn && toColumn
|
||||||
if (relationshipType === RelationshipType.MANY_TO_ONE) {
|
if (relationshipType === RelationshipType.MANY_TO_ONE) {
|
||||||
return base && fromPrimary && fromForeign
|
return base && fromPrimary && fromForeign
|
||||||
|
@ -124,9 +125,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
if (!allRequiredAttributesSet() && !hasValidated) {
|
if (!allRequiredAttributesSet(relationshipType) && !hasValidated) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hasValidated = true
|
hasValidated = true
|
||||||
errorChecker.setType(relationshipType)
|
errorChecker.setType(relationshipType)
|
||||||
const fromTable = getTable(fromId),
|
const fromTable = getTable(fromId),
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
const getSortableFields = schema => {
|
const getSortableFields = schema => {
|
||||||
return Object.entries(schema || {})
|
return Object.entries(schema || {})
|
||||||
.filter(entry => !UNSORTABLE_TYPES.includes(entry[1].type))
|
.filter(
|
||||||
|
entry => !UNSORTABLE_TYPES.includes(entry[1].type) && entry[1].sortable
|
||||||
|
)
|
||||||
.map(entry => entry[0])
|
.map(entry => entry[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,14 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
<Body>{getSubtitle(datasource)}</Body>
|
<Body>
|
||||||
|
{@const subtitle = getSubtitle(datasource)}
|
||||||
|
{#if subtitle}
|
||||||
|
{subtitle}
|
||||||
|
{:else}
|
||||||
|
{Object.values(datasource.config).join(" / ")}
|
||||||
|
{/if}
|
||||||
|
</Body>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
|
|
|
@ -21,15 +21,22 @@
|
||||||
function getRelationships(tables) {
|
function getRelationships(tables) {
|
||||||
const relatedColumns = {}
|
const relatedColumns = {}
|
||||||
|
|
||||||
tables.forEach(({ name: tableName, schema }) => {
|
tables.forEach(({ name: tableName, schema, _id: tableId }) => {
|
||||||
Object.values(schema).forEach(column => {
|
Object.values(schema).forEach(column => {
|
||||||
if (column.type !== "link") return
|
if (column.type !== "link") return
|
||||||
|
|
||||||
relatedColumns[column._id] ??= {}
|
const columnId =
|
||||||
relatedColumns[column._id].through =
|
column.through ||
|
||||||
relatedColumns[column._id].through || column.through
|
column._id ||
|
||||||
|
(column.main
|
||||||
|
? `${tableId}_${column.fieldName}__${column.tableId}_${column.foreignKey}`
|
||||||
|
: `${column.tableId}_${column.foreignKey}__${tableId}_${column.fieldName}`)
|
||||||
|
|
||||||
relatedColumns[column._id][column.main ? "from" : "to"] = {
|
relatedColumns[columnId] ??= {}
|
||||||
|
relatedColumns[columnId].through =
|
||||||
|
relatedColumns[columnId].through || column.through
|
||||||
|
|
||||||
|
relatedColumns[columnId][column.main ? "from" : "to"] = {
|
||||||
...column,
|
...column,
|
||||||
tableName,
|
tableName,
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ export function createDatasourcesStore() {
|
||||||
config,
|
config,
|
||||||
name: `${integration.friendlyName}${nameModifier}`,
|
name: `${integration.friendlyName}${nameModifier}`,
|
||||||
plus: integration.plus && integration.name !== IntegrationTypes.REST,
|
plus: integration.plus && integration.name !== IntegrationTypes.REST,
|
||||||
|
isSQL: integration.isSQL,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await checkDatasourceValidity(integration, datasource)) {
|
if (await checkDatasourceValidity(integration, datasource)) {
|
||||||
|
|
|
@ -5597,6 +5597,21 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"label": "On row click",
|
||||||
|
"key": "onRowClick",
|
||||||
|
"context": [
|
||||||
|
{
|
||||||
|
"label": "Clicked row",
|
||||||
|
"key": "row"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependsOn": {
|
||||||
|
"setting": "allowEditRows",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"label": "Add rows",
|
"label": "Add rows",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
export let initialSortOrder = null
|
export let initialSortOrder = null
|
||||||
export let fixedRowHeight = null
|
export let fixedRowHeight = null
|
||||||
export let columns = null
|
export let columns = null
|
||||||
|
export let onRowClick = null
|
||||||
|
|
||||||
// Legacy settings
|
// Legacy settings
|
||||||
export let table
|
export let table
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
|
|
||||||
$: columnWhitelist = columns?.map(col => col.name)
|
$: columnWhitelist = columns?.map(col => col.name)
|
||||||
$: schemaOverrides = getSchemaOverrides(columns)
|
$: schemaOverrides = getSchemaOverrides(columns)
|
||||||
|
$: handleRowClick = allowEditRows ? undefined : onRowClick
|
||||||
|
|
||||||
const getSchemaOverrides = columns => {
|
const getSchemaOverrides = columns => {
|
||||||
let overrides = {}
|
let overrides = {}
|
||||||
|
@ -59,6 +61,7 @@
|
||||||
showControls={false}
|
showControls={false}
|
||||||
notifySuccess={notificationStore.actions.success}
|
notifySuccess={notificationStore.actions.success}
|
||||||
notifyError={notificationStore.actions.error}
|
notifyError={notificationStore.actions.error}
|
||||||
|
on:rowclick={e => handleRowClick?.({ row: e.detail })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import RelationshipCell from "./RelationshipCell.svelte"
|
import RelationshipCell from "./RelationshipCell.svelte"
|
||||||
import { FieldSubtype } from "@budibase/types"
|
import { FieldSubtype } from "@budibase/types"
|
||||||
|
|
||||||
|
export let api
|
||||||
|
|
||||||
const { API } = getContext("grid")
|
const { API } = getContext("grid")
|
||||||
const { subtype } = $$props.schema
|
const { subtype } = $$props.schema
|
||||||
|
|
||||||
|
@ -17,8 +19,11 @@
|
||||||
throw `Search for '${subtype}' not implemented`
|
throw `Search for '${subtype}' not implemented`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As we are overriding the search function from RelationshipCell, we want to map one shape to the expected one for the specific API
|
||||||
|
const email = Object.values(searchParams.query.string)[0]
|
||||||
|
|
||||||
const results = await API.searchUsers({
|
const results = await API.searchUsers({
|
||||||
...searchParams,
|
email,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Mapping to the expected data within RelationshipCell
|
// Mapping to the expected data within RelationshipCell
|
||||||
|
@ -31,6 +36,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<RelationshipCell
|
<RelationshipCell
|
||||||
|
bind:api
|
||||||
{...$$props}
|
{...$$props}
|
||||||
{schema}
|
{schema}
|
||||||
{searchFunction}
|
{searchFunction}
|
||||||
|
|
|
@ -17,13 +17,24 @@
|
||||||
const { config, dispatch, selectedRows } = getContext("grid")
|
const { config, dispatch, selectedRows } = getContext("grid")
|
||||||
const svelteDispatch = createEventDispatcher()
|
const svelteDispatch = createEventDispatcher()
|
||||||
|
|
||||||
const select = () => {
|
const select = e => {
|
||||||
|
e.stopPropagation()
|
||||||
svelteDispatch("select")
|
svelteDispatch("select")
|
||||||
const id = row?._id
|
const id = row?._id
|
||||||
if (id) {
|
if (id) {
|
||||||
selectedRows.actions.toggleRow(id)
|
selectedRows.actions.toggleRow(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bulkDelete = e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
dispatch("request-bulk-delete")
|
||||||
|
}
|
||||||
|
|
||||||
|
const expand = e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
svelteDispatch("expand")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<GridCell
|
<GridCell
|
||||||
|
@ -56,7 +67,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if rowSelected && $config.canDeleteRows}
|
{#if rowSelected && $config.canDeleteRows}
|
||||||
<div class="delete" on:click={() => dispatch("request-bulk-delete")}>
|
<div class="delete" on:click={bulkDelete}>
|
||||||
<Icon
|
<Icon
|
||||||
name="Delete"
|
name="Delete"
|
||||||
size="S"
|
size="S"
|
||||||
|
@ -65,12 +76,7 @@
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="expand" class:visible={$config.canExpandRows && expandable}>
|
<div class="expand" class:visible={$config.canExpandRows && expandable}>
|
||||||
<Icon
|
<Icon size="S" name="Maximize" hoverable on:click={expand} />
|
||||||
size="S"
|
|
||||||
name="Maximize"
|
|
||||||
hoverable
|
|
||||||
on:click={() => svelteDispatch("expand")}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
columnHorizontalInversionIndex,
|
columnHorizontalInversionIndex,
|
||||||
contentLines,
|
contentLines,
|
||||||
isDragging,
|
isDragging,
|
||||||
|
dispatch,
|
||||||
} = getContext("grid")
|
} = getContext("grid")
|
||||||
|
|
||||||
$: rowSelected = !!$selectedRows[row._id]
|
$: rowSelected = !!$selectedRows[row._id]
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
on:focus
|
on:focus
|
||||||
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
||||||
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
||||||
|
on:click={() => dispatch("rowclick", row)}
|
||||||
>
|
>
|
||||||
{#each $renderedColumns as column, columnIdx (column.name)}
|
{#each $renderedColumns as column, columnIdx (column.name)}
|
||||||
{@const cellId = `${row._id}-${column.name}`}
|
{@const cellId = `${row._id}-${column.name}`}
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
class="row"
|
class="row"
|
||||||
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
||||||
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
||||||
|
on:click={() => dispatch("rowclick", row)}
|
||||||
>
|
>
|
||||||
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
||||||
{#if $stickyColumn}
|
{#if $stickyColumn}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7040ae5282cc23d7ae56ac1be8a369d1c32aab2f
|
Subproject commit 30385682141e5ba9d98de7d71d5be1672109cd15
|
|
@ -19,7 +19,7 @@ docker run --rm \
|
||||||
-v ${PWD}/generated:/generated \
|
-v ${PWD}/generated:/generated \
|
||||||
-v ${PWD}/config.json:/config.json \
|
-v ${PWD}/config.json:/config.json \
|
||||||
-u $(id -u):$(id -g) \
|
-u $(id -u):$(id -g) \
|
||||||
swaggerapi/swagger-codegen-cli-v3 generate \
|
swaggerapi/swagger-codegen-cli-v3:3.0.46 generate \
|
||||||
-i /openapi.yml \
|
-i /openapi.yml \
|
||||||
-l javascript \
|
-l javascript \
|
||||||
-o /generated \
|
-o /generated \
|
||||||
|
|
|
@ -14,5 +14,5 @@ export function isSQL(datasource: Datasource): boolean {
|
||||||
SourceName.MYSQL,
|
SourceName.MYSQL,
|
||||||
SourceName.ORACLE,
|
SourceName.ORACLE,
|
||||||
]
|
]
|
||||||
return SQL.indexOf(datasource.source) !== -1
|
return SQL.indexOf(datasource.source) !== -1 || datasource.isSQL === true
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ export interface Datasource extends Document {
|
||||||
// the config is defined by the schema
|
// the config is defined by the schema
|
||||||
config?: Record<string, any>
|
config?: Record<string, any>
|
||||||
plus?: boolean
|
plus?: boolean
|
||||||
|
isSQL?: boolean
|
||||||
entities?: {
|
entities?: {
|
||||||
[key: string]: Table
|
[key: string]: Table
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,7 @@ export interface DatasourceConfig {
|
||||||
export interface Integration {
|
export interface Integration {
|
||||||
docs: string
|
docs: string
|
||||||
plus?: boolean
|
plus?: boolean
|
||||||
|
isSQL?: boolean
|
||||||
auth?: { type: string }
|
auth?: { type: string }
|
||||||
features?: Partial<Record<DatasourceFeature, boolean>>
|
features?: Partial<Record<DatasourceFeature, boolean>>
|
||||||
relationships?: boolean
|
relationships?: boolean
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { TestConfiguration } from "../../../../tests"
|
||||||
import { events } from "@budibase/backend-core"
|
import { events } from "@budibase/backend-core"
|
||||||
|
|
||||||
// this test can 409 - retries reduce issues with this
|
// this test can 409 - retries reduce issues with this
|
||||||
jest.retryTimes(2)
|
jest.retryTimes(2, { logErrorsBeforeRetry: true })
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
mocks.licenses.useScimIntegration()
|
mocks.licenses.useScimIntegration()
|
||||||
|
|
Loading…
Reference in New Issue