Fixing #3182 so that sorting is disabled for certain column types that we cannot use, as well as fixing some issues with MS-SQL plus tables.
This commit is contained in:
parent
e6d05f1e90
commit
b310918ec4
|
@ -8,7 +8,11 @@
|
||||||
import CreateEditRow from "./modals/CreateEditRow.svelte"
|
import CreateEditRow from "./modals/CreateEditRow.svelte"
|
||||||
import CreateEditUser from "./modals/CreateEditUser.svelte"
|
import CreateEditUser from "./modals/CreateEditUser.svelte"
|
||||||
import CreateEditColumn from "./modals/CreateEditColumn.svelte"
|
import CreateEditColumn from "./modals/CreateEditColumn.svelte"
|
||||||
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
import {
|
||||||
|
TableNames,
|
||||||
|
UNEDITABLE_USER_FIELDS,
|
||||||
|
UNSORTABLE_TYPES,
|
||||||
|
} from "constants"
|
||||||
import RoleCell from "./cells/RoleCell.svelte"
|
import RoleCell from "./cells/RoleCell.svelte"
|
||||||
|
|
||||||
export let schema = {}
|
export let schema = {}
|
||||||
|
@ -33,6 +37,15 @@
|
||||||
$: isUsersTable = tableId === TableNames.USERS
|
$: isUsersTable = tableId === TableNames.USERS
|
||||||
$: data && resetSelectedRows()
|
$: data && resetSelectedRows()
|
||||||
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
|
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
|
||||||
|
$: {
|
||||||
|
UNSORTABLE_TYPES.forEach(type => {
|
||||||
|
Object.values(schema).forEach(col => {
|
||||||
|
if (col.type === type) {
|
||||||
|
col.sortable = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
$: {
|
$: {
|
||||||
if (isUsersTable) {
|
if (isUsersTable) {
|
||||||
customRenderers = [
|
customRenderers = [
|
||||||
|
|
|
@ -92,7 +92,6 @@
|
||||||
opt.type === table.type &&
|
opt.type === table.type &&
|
||||||
table.sourceId === opt.sourceId
|
table.sourceId === opt.sourceId
|
||||||
)
|
)
|
||||||
$: console.log(tableOptions)
|
|
||||||
|
|
||||||
async function saveColumn() {
|
async function saveColumn() {
|
||||||
if (field.type === AUTO_TYPE) {
|
if (field.type === AUTO_TYPE) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { FIELDS } from "constants/backend"
|
||||||
|
|
||||||
export const TableNames = {
|
export const TableNames = {
|
||||||
USERS: "ta_users",
|
USERS: "ta_users",
|
||||||
}
|
}
|
||||||
|
@ -39,6 +41,13 @@ export const UNEDITABLE_USER_FIELDS = [
|
||||||
"lastName",
|
"lastName",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const UNSORTABLE_TYPES = [
|
||||||
|
FIELDS.FORMULA.type,
|
||||||
|
FIELDS.ATTACHMENT.type,
|
||||||
|
FIELDS.ARRAY.type,
|
||||||
|
FIELDS.LINK.type,
|
||||||
|
]
|
||||||
|
|
||||||
export const LAYOUT_NAMES = {
|
export const LAYOUT_NAMES = {
|
||||||
MASTER: {
|
MASTER: {
|
||||||
PRIVATE: "layout_private_master",
|
PRIVATE: "layout_private_master",
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
try {
|
try {
|
||||||
// Create datasource
|
// Create datasource
|
||||||
await datasources.save(datasource)
|
await datasources.save(datasource)
|
||||||
|
if (datasource?.plus) {
|
||||||
|
await tables.fetch()
|
||||||
|
}
|
||||||
|
await datasources.fetch()
|
||||||
notifications.success(`Datasource ${name} updated successfully.`)
|
notifications.success(`Datasource ${name} updated successfully.`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifications.error(`Error saving datasource: ${err}`)
|
notifications.error(`Error saving datasource: ${err}`)
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { fetchTableData } from "./tables"
|
||||||
import { fetchViewData } from "./views"
|
import { fetchViewData } from "./views"
|
||||||
import { fetchRelationshipData } from "./relationships"
|
import { fetchRelationshipData } from "./relationships"
|
||||||
import { executeQuery } from "./queries"
|
import { executeQuery } from "./queries"
|
||||||
|
import { FieldTypes } from "../constants"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all rows for a particular Budibase data source.
|
* Fetches all rows for a particular Budibase data source.
|
||||||
|
@ -28,7 +29,7 @@ export const fetchDatasource = async dataSource => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rows = await executeQuery({ queryId: dataSource._id, parameters })
|
rows = await executeQuery({ queryId: dataSource._id, parameters })
|
||||||
} else if (type === "link") {
|
} else if (type === FieldTypes.LINK) {
|
||||||
rows = await fetchRelationshipData({
|
rows = await fetchRelationshipData({
|
||||||
rowId: dataSource.rowId,
|
rowId: dataSource.rowId,
|
||||||
tableId: dataSource.rowTableId,
|
tableId: dataSource.rowTableId,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { notificationStore, dataSourceStore } from "stores"
|
import { notificationStore, dataSourceStore } from "stores"
|
||||||
import API from "./api"
|
import API from "./api"
|
||||||
import { fetchTableDefinition } from "./tables"
|
import { fetchTableDefinition } from "./tables"
|
||||||
|
import { FieldTypes } from "../constants"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches data about a certain row in a table.
|
* Fetches data about a certain row in a table.
|
||||||
|
@ -129,7 +130,7 @@ export const enrichRows = async (rows, tableId) => {
|
||||||
const keys = Object.keys(schema)
|
const keys = Object.keys(schema)
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
const type = schema[key].type
|
const type = schema[key].type
|
||||||
if (type === "link" && Array.isArray(row[key])) {
|
if (type === FieldTypes.LINK && Array.isArray(row[key])) {
|
||||||
// Enrich row a string join of relationship fields
|
// Enrich row a string join of relationship fields
|
||||||
row[`${key}_text`] =
|
row[`${key}_text`] =
|
||||||
row[key]
|
row[key]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { Heading, Icon } from "@budibase/bbui"
|
import { Heading, Icon } from "@budibase/bbui"
|
||||||
|
import { FieldTypes } from "../../constants"
|
||||||
import active from "svelte-spa-router/active"
|
import active from "svelte-spa-router/active"
|
||||||
|
|
||||||
const { routeStore, styleable, linkable, builderStore } = getContext("sdk")
|
const { routeStore, styleable, linkable, builderStore } = getContext("sdk")
|
||||||
|
@ -108,7 +109,7 @@
|
||||||
{#each validLinks as { text, url }}
|
{#each validLinks as { text, url }}
|
||||||
{#if isInternal(url)}
|
{#if isInternal(url)}
|
||||||
<a
|
<a
|
||||||
class="link"
|
class={FieldTypes.LINK}
|
||||||
href={url}
|
href={url}
|
||||||
use:linkable
|
use:linkable
|
||||||
on:click={close}
|
on:click={close}
|
||||||
|
@ -117,7 +118,11 @@
|
||||||
{text}
|
{text}
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<a class="link" href={ensureExternal(url)} on:click={close}>
|
<a
|
||||||
|
class={FieldTypes.LINK}
|
||||||
|
href={ensureExternal(url)}
|
||||||
|
on:click={close}
|
||||||
|
>
|
||||||
{text}
|
{text}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { CoreSelect, CoreMultiselect } from "@budibase/bbui"
|
import { CoreSelect, CoreMultiselect } from "@budibase/bbui"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import Field from "./Field.svelte"
|
import Field from "./Field.svelte"
|
||||||
|
import { FieldTypes } from "../../../constants"
|
||||||
|
|
||||||
const { API } = getContext("sdk")
|
const { API } = getContext("sdk")
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@
|
||||||
{field}
|
{field}
|
||||||
{disabled}
|
{disabled}
|
||||||
{validation}
|
{validation}
|
||||||
type="link"
|
type={FieldTypes.LINK}
|
||||||
bind:fieldState
|
bind:fieldState
|
||||||
bind:fieldApi
|
bind:fieldApi
|
||||||
bind:fieldSchema
|
bind:fieldSchema
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import flatpickr from "flatpickr"
|
import flatpickr from "flatpickr"
|
||||||
|
import { FieldTypes } from "../../../constants"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a validation function from a combination of schema-level constraints
|
* Creates a validation function from a combination of schema-level constraints
|
||||||
|
@ -154,7 +155,7 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse as string
|
// Parse as string
|
||||||
if (type === "string") {
|
if (type === FieldTypes.STRING) {
|
||||||
if (typeof value === "string" || Array.isArray(value)) {
|
if (typeof value === "string" || Array.isArray(value)) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
@ -165,7 +166,7 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse as number
|
// Parse as number
|
||||||
if (type === "number") {
|
if (type === FieldTypes.NUMBER) {
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -173,7 +174,7 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse as date
|
// Parse as date
|
||||||
if (type === "datetime") {
|
if (type === FieldTypes.DATETIME) {
|
||||||
if (value instanceof Date) {
|
if (value instanceof Date) {
|
||||||
return value.getTime()
|
return value.getTime()
|
||||||
}
|
}
|
||||||
|
@ -182,7 +183,7 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse as boolean
|
// Parse as boolean
|
||||||
if (type === "boolean") {
|
if (type === FieldTypes.BOOLEAN) {
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
return value.toLowerCase() === "true"
|
return value.toLowerCase() === "true"
|
||||||
}
|
}
|
||||||
|
@ -190,7 +191,7 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse attachments, treating no elements as null
|
// Parse attachments, treating no elements as null
|
||||||
if (type === "attachment") {
|
if (type === FieldTypes.ATTACHMENT) {
|
||||||
if (!Array.isArray(value) || !value.length) {
|
if (!Array.isArray(value) || !value.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -198,14 +199,14 @@ const parseType = (value, type) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse links, treating no elements as null
|
// Parse links, treating no elements as null
|
||||||
if (type === "link") {
|
if (type === FieldTypes.LINK) {
|
||||||
if (!Array.isArray(value) || !value.length) {
|
if (!Array.isArray(value) || !value.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "array") {
|
if (type === FieldTypes.ARRAY) {
|
||||||
if (!Array.isArray(value) || !value.length) {
|
if (!Array.isArray(value) || !value.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { Table } from "@budibase/bbui"
|
import { Table } from "@budibase/bbui"
|
||||||
import SlotRenderer from "./SlotRenderer.svelte"
|
import SlotRenderer from "./SlotRenderer.svelte"
|
||||||
|
import { UnsortableTypes } from "../../../constants"
|
||||||
|
|
||||||
export let dataProvider
|
export let dataProvider
|
||||||
export let columns
|
export let columns
|
||||||
|
@ -65,8 +66,12 @@
|
||||||
divider: true,
|
divider: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.forEach(field => {
|
fields.forEach(field => {
|
||||||
newSchema[field] = schema[field]
|
newSchema[field] = schema[field]
|
||||||
|
if (schema[field] && UnsortableTypes.indexOf(schema[field].type) !== -1) {
|
||||||
|
newSchema[field].sortable = false
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return newSchema
|
return newSchema
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,26 @@ export const TableNames = {
|
||||||
USERS: "ta_users",
|
USERS: "ta_users",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const FieldTypes = {
|
||||||
|
STRING: "string",
|
||||||
|
LONGFORM: "longform",
|
||||||
|
OPTIONS: "options",
|
||||||
|
NUMBER: "number",
|
||||||
|
BOOLEAN: "boolean",
|
||||||
|
ARRAY: "array",
|
||||||
|
DATETIME: "datetime",
|
||||||
|
ATTACHMENT: "attachment",
|
||||||
|
LINK: "link",
|
||||||
|
FORMULA: "formula",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UnsortableTypes = [
|
||||||
|
FieldTypes.FORMULA,
|
||||||
|
FieldTypes.ATTACHMENT,
|
||||||
|
FieldTypes.ARRAY,
|
||||||
|
FieldTypes.LINK,
|
||||||
|
]
|
||||||
|
|
||||||
export const ActionTypes = {
|
export const ActionTypes = {
|
||||||
ValidateForm: "ValidateForm",
|
ValidateForm: "ValidateForm",
|
||||||
RefreshDatasource: "RefreshDatasource",
|
RefreshDatasource: "RefreshDatasource",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { writable, get } from "svelte/store"
|
import { writable, get } from "svelte/store"
|
||||||
import { fetchTableDefinition } from "../api"
|
import { fetchTableDefinition } from "../api"
|
||||||
|
import { FieldTypes } from "../constants"
|
||||||
|
|
||||||
export const createDataSourceStore = () => {
|
export const createDataSourceStore = () => {
|
||||||
const store = writable([])
|
const store = writable([])
|
||||||
|
@ -20,7 +21,7 @@ export const createDataSourceStore = () => {
|
||||||
|
|
||||||
// Only one side of the relationship is required as a trigger, as it will
|
// Only one side of the relationship is required as a trigger, as it will
|
||||||
// automatically invalidate related table IDs
|
// automatically invalidate related table IDs
|
||||||
else if (dataSource.type === "link") {
|
else if (dataSource.type === FieldTypes.LINK) {
|
||||||
dataSourceId = dataSource.tableId || dataSource.rowTableId
|
dataSourceId = dataSource.tableId || dataSource.rowTableId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ export const createDataSourceStore = () => {
|
||||||
if (schema) {
|
if (schema) {
|
||||||
Object.values(schema).forEach(fieldSchema => {
|
Object.values(schema).forEach(fieldSchema => {
|
||||||
if (
|
if (
|
||||||
fieldSchema.type === "link" &&
|
fieldSchema.type === FieldTypes.LINK &&
|
||||||
fieldSchema.tableId &&
|
fieldSchema.tableId &&
|
||||||
!fieldSchema.autocolumn
|
!fieldSchema.autocolumn
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -211,10 +211,10 @@ module MSSQLModule {
|
||||||
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
||||||
await this.connect()
|
await this.connect()
|
||||||
let tableNames = await this.runSQL(this.TABLES_SQL)
|
let tableNames = await this.runSQL(this.TABLES_SQL)
|
||||||
if (tableNames == null || !Array.isArray(tableNames.recordset)) {
|
if (tableNames == null || !Array.isArray(tableNames)) {
|
||||||
throw "Unable to get list of tables in database"
|
throw "Unable to get list of tables in database"
|
||||||
}
|
}
|
||||||
tableNames = tableNames.recordset
|
tableNames = tableNames
|
||||||
.map((record: any) => record.TABLE_NAME)
|
.map((record: any) => record.TABLE_NAME)
|
||||||
.filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
|
.filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,7 @@ exports.setInitInfo = ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getInitInfo = ctx => {
|
exports.getInitInfo = ctx => {
|
||||||
const initInfo = getCookie(ctx, Cookies.Init)
|
ctx.body = getCookie(ctx, Cookies.Init)
|
||||||
ctx.body = initInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue