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:
mike12345567 2021-11-08 17:25:05 +00:00
parent e6d05f1e90
commit b310918ec4
14 changed files with 79 additions and 20 deletions

View File

@ -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 = [

View File

@ -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) {

View File

@ -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",

View File

@ -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}`)

View File

@ -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,

View File

@ -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]

View File

@ -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}

View File

@ -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

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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",

View File

@ -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
) { ) {

View File

@ -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)

View File

@ -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
} }
/** /**