Browse Source
Merge pull request #3317 from Budibase/feature/switchable-types
Allow switching between string <-> options, number <-> boolean
pull/3389/head
Michael Drury
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with
75 additions and
6 deletions
-
packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
-
packages/builder/src/constants/backend/index.js
-
packages/builder/src/stores/backend/tables.js
-
packages/server/src/api/controllers/table/external.js
-
packages/server/src/api/controllers/table/internal.js
-
packages/server/src/api/controllers/table/utils.js
-
packages/server/src/constants/index.js
-
packages/server/src/integrations/base/sqlTable.ts
|
|
|
@ -18,6 +18,11 @@ |
|
|
|
FIELDS, |
|
|
|
AUTO_COLUMN_SUB_TYPES, |
|
|
|
RelationshipTypes, |
|
|
|
ALLOWABLE_STRING_OPTIONS, |
|
|
|
ALLOWABLE_NUMBER_OPTIONS, |
|
|
|
ALLOWABLE_STRING_TYPES, |
|
|
|
ALLOWABLE_NUMBER_TYPES, |
|
|
|
SWITCHABLE_TYPES, |
|
|
|
} from "constants/backend" |
|
|
|
import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils" |
|
|
|
import { notifications } from "@budibase/bbui" |
|
|
|
@ -92,6 +97,9 @@ |
|
|
|
opt.type === table.type && |
|
|
|
table.sourceId === opt.sourceId |
|
|
|
) |
|
|
|
$: typeEnabled = |
|
|
|
!originalName || |
|
|
|
(originalName && SWITCHABLE_TYPES.indexOf(field.type) !== -1) |
|
|
|
|
|
|
|
async function saveColumn() { |
|
|
|
if (field.type === AUTO_TYPE) { |
|
|
|
@ -204,7 +212,14 @@ |
|
|
|
} |
|
|
|
|
|
|
|
function getAllowedTypes() { |
|
|
|
if (!external) { |
|
|
|
if (originalName && ALLOWABLE_STRING_TYPES.indexOf(field.type) !== -1) { |
|
|
|
return ALLOWABLE_STRING_OPTIONS |
|
|
|
} else if ( |
|
|
|
originalName && |
|
|
|
ALLOWABLE_NUMBER_TYPES.indexOf(field.type) !== -1 |
|
|
|
) { |
|
|
|
return ALLOWABLE_NUMBER_OPTIONS |
|
|
|
} else if (!external) { |
|
|
|
return [ |
|
|
|
...Object.values(fieldDefinitions), |
|
|
|
{ name: "Auto Column", type: AUTO_TYPE }, |
|
|
|
@ -259,7 +274,7 @@ |
|
|
|
/> |
|
|
|
|
|
|
|
<Select |
|
|
|
disabled={originalName} |
|
|
|
disabled={!typeEnabled} |
|
|
|
label="Type" |
|
|
|
bind:value={field.type} |
|
|
|
on:change={handleTypeChange} |
|
|
|
|
|
|
|
@ -138,3 +138,19 @@ export const RelationshipTypes = { |
|
|
|
ONE_TO_MANY: "one-to-many", |
|
|
|
MANY_TO_ONE: "many-to-one", |
|
|
|
} |
|
|
|
|
|
|
|
export const ALLOWABLE_STRING_OPTIONS = [FIELDS.STRING, FIELDS.OPTIONS] |
|
|
|
|
|
|
|
export const ALLOWABLE_STRING_TYPES = ALLOWABLE_STRING_OPTIONS.map( |
|
|
|
opt => opt.type |
|
|
|
) |
|
|
|
|
|
|
|
export const ALLOWABLE_NUMBER_OPTIONS = [FIELDS.NUMBER, FIELDS.BOOLEAN] |
|
|
|
|
|
|
|
export const ALLOWABLE_NUMBER_TYPES = ALLOWABLE_NUMBER_OPTIONS.map( |
|
|
|
opt => opt.type |
|
|
|
) |
|
|
|
|
|
|
|
export const SWITCHABLE_TYPES = ALLOWABLE_NUMBER_TYPES.concat( |
|
|
|
ALLOWABLE_STRING_TYPES |
|
|
|
) |
|
|
|
|
|
|
|
@ -2,6 +2,7 @@ import { writable, get } from "svelte/store" |
|
|
|
import { views, queries, datasources } from "./" |
|
|
|
import { cloneDeep } from "lodash/fp" |
|
|
|
import api from "builderStore/api" |
|
|
|
import { SWITCHABLE_TYPES } from "../../constants/backend" |
|
|
|
|
|
|
|
export function createTablesStore() { |
|
|
|
const store = writable({}) |
|
|
|
@ -47,7 +48,11 @@ export function createTablesStore() { |
|
|
|
const field = updatedTable.schema[key] |
|
|
|
const oldField = oldTable?.schema[key] |
|
|
|
// if the type has changed then revert back to the old field
|
|
|
|
if (oldField != null && oldField?.type !== field.type) { |
|
|
|
if ( |
|
|
|
oldField != null && |
|
|
|
oldField?.type !== field.type && |
|
|
|
SWITCHABLE_TYPES.indexOf(oldField?.type) === -1 |
|
|
|
) { |
|
|
|
updatedTable.schema[key] = oldField |
|
|
|
} |
|
|
|
// field has been renamed
|
|
|
|
|
|
|
|
@ -8,6 +8,7 @@ const { |
|
|
|
generateForeignKey, |
|
|
|
generateJunctionTableName, |
|
|
|
foreignKeyStructure, |
|
|
|
hasTypeChanged, |
|
|
|
} = require("./utils") |
|
|
|
const { |
|
|
|
DataSourceOperation, |
|
|
|
@ -172,6 +173,10 @@ exports.save = async function (ctx) { |
|
|
|
oldTable = await getTable(appId, ctx.request.body._id) |
|
|
|
} |
|
|
|
|
|
|
|
if (hasTypeChanged(tableToSave, oldTable)) { |
|
|
|
ctx.throw(400, "A column type has changed.") |
|
|
|
} |
|
|
|
|
|
|
|
const db = new CouchDB(appId) |
|
|
|
const datasource = await db.get(datasourceId) |
|
|
|
const oldTables = cloneDeep(datasource.entities) |
|
|
|
|
|
|
|
@ -2,7 +2,7 @@ const CouchDB = require("../../../db") |
|
|
|
const linkRows = require("../../../db/linkedRows") |
|
|
|
const { getRowParams, generateTableID } = require("../../../db/utils") |
|
|
|
const { FieldTypes } = require("../../../constants") |
|
|
|
const { TableSaveFunctions } = require("./utils") |
|
|
|
const { TableSaveFunctions, hasTypeChanged } = require("./utils") |
|
|
|
|
|
|
|
exports.save = async function (ctx) { |
|
|
|
const appId = ctx.appId |
|
|
|
@ -21,6 +21,10 @@ exports.save = async function (ctx) { |
|
|
|
oldTable = await db.get(ctx.request.body._id) |
|
|
|
} |
|
|
|
|
|
|
|
if (hasTypeChanged(tableToSave, oldTable)) { |
|
|
|
ctx.throw(400, "A column type has changed.") |
|
|
|
} |
|
|
|
|
|
|
|
// saving a table is a complex operation, involving many different steps, this
|
|
|
|
// has been broken out into a utility to make it more obvious/easier to manipulate
|
|
|
|
const tableSaveFunctions = new TableSaveFunctions({ |
|
|
|
|
|
|
|
@ -8,7 +8,7 @@ const { |
|
|
|
const { isEqual } = require("lodash/fp") |
|
|
|
const { AutoFieldSubTypes, FieldTypes } = require("../../../constants") |
|
|
|
const { inputProcessing } = require("../../../utilities/rowProcessor") |
|
|
|
const { USERS_TABLE_SCHEMA } = require("../../../constants") |
|
|
|
const { USERS_TABLE_SCHEMA, SwitchableTypes } = require("../../../constants") |
|
|
|
const { |
|
|
|
isExternalTable, |
|
|
|
breakExternalTableId, |
|
|
|
@ -335,4 +335,21 @@ exports.foreignKeyStructure = (keyName, meta = null) => { |
|
|
|
return structure |
|
|
|
} |
|
|
|
|
|
|
|
exports.hasTypeChanged = (table, oldTable) => { |
|
|
|
if (!oldTable) { |
|
|
|
return false |
|
|
|
} |
|
|
|
for (let [key, field] of Object.entries(oldTable.schema)) { |
|
|
|
const oldType = field.type |
|
|
|
if (!table.schema[key]) { |
|
|
|
continue |
|
|
|
} |
|
|
|
const newType = table.schema[key].type |
|
|
|
if (oldType !== newType && SwitchableTypes.indexOf(oldType) === -1) { |
|
|
|
return true |
|
|
|
} |
|
|
|
} |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
exports.TableSaveFunctions = TableSaveFunctions |
|
|
|
|
|
|
|
@ -45,6 +45,13 @@ exports.FieldTypes = { |
|
|
|
INTERNAL: "internal", |
|
|
|
} |
|
|
|
|
|
|
|
exports.SwitchableTypes = [ |
|
|
|
exports.FieldTypes.STRING, |
|
|
|
exports.FieldTypes.OPTIONS, |
|
|
|
exports.FieldTypes.NUMBER, |
|
|
|
exports.FieldTypes.BOOLEAN, |
|
|
|
] |
|
|
|
|
|
|
|
exports.RelationshipTypes = { |
|
|
|
ONE_TO_MANY: "one-to-many", |
|
|
|
MANY_TO_ONE: "many-to-one", |
|
|
|
|
|
|
|
@ -30,7 +30,7 @@ function generateSchema( |
|
|
|
// skip things that are already correct
|
|
|
|
const oldColumn = oldTable ? oldTable.schema[key] : null |
|
|
|
if ( |
|
|
|
(oldColumn && oldColumn.type === column.type) || |
|
|
|
(oldColumn && oldColumn.type) || |
|
|
|
(primaryKey === key && !isJunction) |
|
|
|
) { |
|
|
|
continue |
|
|
|
|