First lot of work to update the auto fields into schema.

This commit is contained in:
mike12345567 2021-02-10 17:55:19 +00:00
parent fa921951a3
commit 7a2405c756
9 changed files with 73 additions and 40 deletions

View File

@ -14,6 +14,8 @@
import { NEW_ROW_TEMPLATE } from "builderStore/store/screenTemplates/newRowScreen" import { NEW_ROW_TEMPLATE } from "builderStore/store/screenTemplates/newRowScreen"
import { ROW_DETAIL_TEMPLATE } from "builderStore/store/screenTemplates/rowDetailScreen" import { ROW_DETAIL_TEMPLATE } from "builderStore/store/screenTemplates/rowDetailScreen"
import { ROW_LIST_TEMPLATE } from "builderStore/store/screenTemplates/rowListScreen" import { ROW_LIST_TEMPLATE } from "builderStore/store/screenTemplates/rowListScreen"
import { FIELDS } from "constants/backend"
import { cloneDeep } from "lodash/fp"
const defaultScreens = [ const defaultScreens = [
NEW_ROW_TEMPLATE, NEW_ROW_TEMPLATE,
@ -27,11 +29,22 @@
let error = "" let error = ""
let createAutoscreens = true let createAutoscreens = true
let autoColumns = { let autoColumns = {
createdBy: false, createdBy: true,
createdAt: false, createdAt: true,
updatedBy: false, updatedBy: true,
updatedAt: false, updatedAt: true,
autoNumber: false, autoID: true,
}
function addAutoColumns(schema) {
for (let [property, enabled] of Object.entries(autoColumns)) {
if (!enabled) {
continue
}
const autoColDef = cloneDeep(FIELDS.AUTO)
autoColDef.subtype = property
schema[property] = autoColDef
}
} }
function checkValid(evt) { function checkValid(evt) {
@ -46,8 +59,7 @@
async function saveTable() { async function saveTable() {
let newTable = { let newTable = {
name, name,
schema: dataImport.schema || {}, schema: addAutoColumns(dataImport.schema || {}),
autoColumns,
dataImport, dataImport,
} }
@ -100,7 +112,7 @@
bind:value={name} bind:value={name}
{error} /> {error} />
<div class="autocolumns"> <div class="autocolumns">
<label>Auto columns</label> <Label extraSmall grey>Auto Columns</Label>
<div class="toggles"> <div class="toggles">
<div class="toggle-1"> <div class="toggle-1">
<Toggle <Toggle
@ -110,8 +122,8 @@
text="Created at" text="Created at"
bind:checked={autoColumns.createdAt} /> bind:checked={autoColumns.createdAt} />
<Toggle <Toggle
text="Autonumber" text="Auto ID"
bind:checked={autoColumns.autoNumber} /> bind:checked={autoColumns.autoID} />
</div> </div>
<div class="toggle-2"> <div class="toggle-2">
<Toggle <Toggle
@ -142,14 +154,14 @@
display: flex; display: flex;
width: 100%; width: 100%;
margin-top: 6px; margin-top: 6px;
margin-bottom: 10px;
} }
.toggle-1 :global(> *) { .toggle-1 :global(> *) {
margin-top: 10px; margin-bottom: 10px;
} }
.toggle-2 :global(> *) { .toggle-2 :global(> *) {
margin-top: 10px; margin-bottom: 10px;
margin-left: 10px; margin-left: 20px;
} }
</style> </style>

View File

@ -80,6 +80,13 @@ export const FIELDS = {
presence: false, presence: false,
}, },
}, },
AUTO: {
name: "Auto Column",
icon: "ri-magic-line",
type: "auto",
// no constraints for auto-columns
// these are fully created serverside
}
} }
export const FILE_TYPES = { export const FILE_TYPES = {

View File

@ -13,6 +13,7 @@ const {
inputProcessing, inputProcessing,
outputProcessing, outputProcessing,
} = require("../../utilities/rowProcessor") } = require("../../utilities/rowProcessor")
const { FieldTypes } = require("../../constants")
const TABLE_VIEW_BEGINS_WITH = `all${SEPARATOR}${DocumentTypes.TABLE}${SEPARATOR}` const TABLE_VIEW_BEGINS_WITH = `all${SEPARATOR}${DocumentTypes.TABLE}${SEPARATOR}`
@ -261,7 +262,7 @@ exports.search = async function(ctx) {
const table = await db.get(ctx.params.tableId) const table = await db.get(ctx.params.tableId)
ctx.body = await enrichRows(appId, table, rows) ctx.body = await outputProcessing(appId, table, rows)
} }
exports.fetchTableRows = async function(ctx) { exports.fetchTableRows = async function(ctx) {
@ -384,7 +385,7 @@ exports.fetchEnrichedRow = async function(ctx) {
// insert the link rows in the correct place throughout the main row // insert the link rows in the correct place throughout the main row
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
let field = table.schema[fieldName] let field = table.schema[fieldName]
if (field.type === "link") { if (field.type === FieldTypes.LINK) {
row[fieldName] = linkedRows.filter( row[fieldName] = linkedRows.filter(
linkRow => linkRow.tableId === field.tableId linkRow => linkRow.tableId === field.tableId
) )

View File

@ -8,6 +8,7 @@ const {
generateRowID, generateRowID,
} = require("../../db/utils") } = require("../../db/utils")
const { isEqual } = require("lodash/fp") const { isEqual } = require("lodash/fp")
const { FieldTypes } = require("../../constants")
async function checkForColumnUpdates(db, oldTable, updatedTable) { async function checkForColumnUpdates(db, oldTable, updatedTable) {
let updatedRows let updatedRows
@ -91,7 +92,7 @@ exports.save = async function(ctx) {
} }
// rename row fields when table column is renamed // rename row fields when table column is renamed
if (_rename && tableToSave.schema[_rename.updated].type === "link") { if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
ctx.throw(400, "Cannot rename a linked column.") ctx.throw(400, "Cannot rename a linked column.")
} else if (_rename && tableToSave.primaryDisplay === _rename.old) { } else if (_rename && tableToSave.primaryDisplay === _rename.old) {
ctx.throw(400, "Cannot rename the display column.") ctx.throw(400, "Cannot rename the display column.")

View File

@ -22,12 +22,6 @@ function generateSaveValidator() {
schema: Joi.object().required(), schema: Joi.object().required(),
name: Joi.string().required(), name: Joi.string().required(),
views: Joi.object(), views: Joi.object(),
autoColumns: Joi.object({
createdBy: Joi.boolean(),
createdAt: Joi.boolean(),
updatedBy: Joi.boolean(),
updatedAt: Joi.boolean(),
}),
dataImport: Joi.object(), dataImport: Joi.object(),
}).unknown(true)) }).unknown(true))
} }

View File

@ -39,6 +39,18 @@ const USERS_TABLE_SCHEMA = {
primaryDisplay: "email", primaryDisplay: "email",
} }
exports.FieldTypes = {
STRING: "string",
LONGFORM: "longform",
OPTIONS: "options",
NUMBER: "number",
BOOLEAN: "boolean",
DATETIME: "datetime",
ATTACHMENT: "attachment",
LINK: "link",
AUTO: "auto",
}
exports.AuthTypes = AuthTypes exports.AuthTypes = AuthTypes
exports.USERS_TABLE_SCHEMA = USERS_TABLE_SCHEMA exports.USERS_TABLE_SCHEMA = USERS_TABLE_SCHEMA
exports.BUILDER_CONFIG_DB = "builder-config-db" exports.BUILDER_CONFIG_DB = "builder-config-db"

View File

@ -2,6 +2,7 @@ const CouchDB = require("../index")
const { IncludeDocs, getLinkDocuments } = require("./linkUtils") const { IncludeDocs, getLinkDocuments } = require("./linkUtils")
const { generateLinkID } = require("../utils") const { generateLinkID } = require("../utils")
const Sentry = require("@sentry/node") const Sentry = require("@sentry/node")
const { FieldTypes } = require("../../constants")
/** /**
* Creates a new link document structure which can be put to the database. It is important to * Creates a new link document structure which can be put to the database. It is important to
@ -26,7 +27,7 @@ function LinkDocument(
// build the ID out of unique references to this link document // build the ID out of unique references to this link document
this._id = generateLinkID(tableId1, tableId2, rowId1, rowId2) this._id = generateLinkID(tableId1, tableId2, rowId1, rowId2)
// required for referencing in view // required for referencing in view
this.type = "link" this.type = FieldTypes.LINK
this.doc1 = { this.doc1 = {
tableId: tableId1, tableId: tableId1,
fieldName: fieldName1, fieldName: fieldName1,
@ -75,7 +76,7 @@ class LinkController {
} }
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
const { type } = table.schema[fieldName] const { type } = table.schema[fieldName]
if (type === "link") { if (type === FieldTypes.LINK) {
return true return true
} }
} }
@ -123,7 +124,7 @@ class LinkController {
// get the links this row wants to make // get the links this row wants to make
const rowField = row[fieldName] const rowField = row[fieldName]
const field = table.schema[fieldName] const field = table.schema[fieldName]
if (field.type === "link" && rowField != null) { if (field.type === FieldTypes.LINK && rowField != null) {
// check which links actual pertain to the update in this row // check which links actual pertain to the update in this row
const thisFieldLinkDocs = linkDocs.filter( const thisFieldLinkDocs = linkDocs.filter(
linkDoc => linkDoc =>
@ -234,7 +235,7 @@ class LinkController {
const schema = table.schema const schema = table.schema
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
const field = schema[fieldName] const field = schema[fieldName]
if (field.type === "link") { if (field.type === FieldTypes.LINK) {
// handle this in a separate try catch, want // handle this in a separate try catch, want
// the put to bubble up as an error, if can't update // the put to bubble up as an error, if can't update
// table for some reason // table for some reason
@ -247,7 +248,7 @@ class LinkController {
// create the link field in the other table // create the link field in the other table
linkedTable.schema[field.fieldName] = { linkedTable.schema[field.fieldName] = {
name: field.fieldName, name: field.fieldName,
type: "link", type: FieldTypes.LINK,
// these are the props of the table that initiated the link // these are the props of the table that initiated the link
tableId: table._id, tableId: table._id,
fieldName: fieldName, fieldName: fieldName,
@ -274,7 +275,10 @@ class LinkController {
for (let fieldName of Object.keys(oldTable.schema)) { for (let fieldName of Object.keys(oldTable.schema)) {
const field = oldTable.schema[fieldName] const field = oldTable.schema[fieldName]
// this field has been removed from the table schema // this field has been removed from the table schema
if (field.type === "link" && newTable.schema[fieldName] == null) { if (
field.type === FieldTypes.LINK &&
newTable.schema[fieldName] == null
) {
await this.removeFieldFromTable(fieldName) await this.removeFieldFromTable(fieldName)
} }
} }
@ -295,7 +299,7 @@ class LinkController {
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
const field = schema[fieldName] const field = schema[fieldName]
try { try {
if (field.type === "link") { if (field.type === FieldTypes.LINK) {
const linkedTable = await this._db.get(field.tableId) const linkedTable = await this._db.get(field.tableId)
delete linkedTable.schema[field.fieldName] delete linkedTable.schema[field.fieldName]
await this._db.put(linkedTable) await this._db.put(linkedTable)

View File

@ -1,6 +1,7 @@
const CouchDB = require("../index") const CouchDB = require("../index")
const Sentry = require("@sentry/node") const Sentry = require("@sentry/node")
const { ViewNames, getQueryIndex } = require("../utils") const { ViewNames, getQueryIndex } = require("../utils")
const { FieldTypes } = require("../../constants")
/** /**
* Only needed so that boolean parameters are being used for includeDocs * Only needed so that boolean parameters are being used for includeDocs
@ -23,7 +24,7 @@ exports.createLinkView = async appId => {
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const view = { const view = {
map: function(doc) { map: function(doc) {
if (doc.type === "link") { if (doc.type === FieldTypes.LINK) {
let doc1 = doc.doc1 let doc1 = doc.doc1
let doc2 = doc.doc2 let doc2 = doc.doc2
emit([doc1.tableId, doc1.rowId], { emit([doc1.tableId, doc1.rowId], {

View File

@ -2,48 +2,49 @@ const env = require("../environment")
const { OBJ_STORE_DIRECTORY } = require("../constants") const { OBJ_STORE_DIRECTORY } = require("../constants")
const linkRows = require("../db/linkedRows") const linkRows = require("../db/linkedRows")
const { cloneDeep } = require("lodash/fp") const { cloneDeep } = require("lodash/fp")
const { FieldTypes } = require("../constants")
/** /**
* A map of how we convert various properties in rows to each other based on the row type. * A map of how we convert various properties in rows to each other based on the row type.
*/ */
const TYPE_TRANSFORM_MAP = { const TYPE_TRANSFORM_MAP = {
link: { [FieldTypes.LINK]: {
"": [], "": [],
[null]: [], [null]: [],
[undefined]: undefined, [undefined]: undefined,
}, },
options: { [FieldTypes.OPTIONS]: {
"": "", "": "",
[null]: "", [null]: "",
[undefined]: undefined, [undefined]: undefined,
}, },
string: { [FieldTypes.STRING]: {
"": "", "": "",
[null]: "", [null]: "",
[undefined]: undefined, [undefined]: undefined,
}, },
longform: { [FieldTypes.LONGFORM]: {
"": "", "": "",
[null]: "", [null]: "",
[undefined]: undefined, [undefined]: undefined,
}, },
number: { [FieldTypes.NUMBER]: {
"": null, "": null,
[null]: null, [null]: null,
[undefined]: undefined, [undefined]: undefined,
parse: n => parseFloat(n), parse: n => parseFloat(n),
}, },
datetime: { [FieldTypes.DATETIME]: {
"": null, "": null,
[undefined]: undefined, [undefined]: undefined,
[null]: null, [null]: null,
}, },
attachment: { [FieldTypes.ATTACHMENT]: {
"": [], "": [],
[null]: [], [null]: [],
[undefined]: undefined, [undefined]: undefined,
}, },
boolean: { [FieldTypes.BOOLEAN]: {
"": null, "": null,
[null]: null, [null]: null,
[undefined]: undefined, [undefined]: undefined,
@ -102,7 +103,7 @@ exports.outputProcessing = async (appId, table, rows) => {
// update the attachments URL depending on hosting // update the attachments URL depending on hosting
if (env.CLOUD && env.SELF_HOSTED) { if (env.CLOUD && env.SELF_HOSTED) {
for (let [property, column] of Object.entries(table.schema)) { for (let [property, column] of Object.entries(table.schema)) {
if (column.type === "attachment") { if (column.type === FieldTypes.ATTACHMENT) {
for (let row of outputRows) { for (let row of outputRows) {
if (row[property] == null || row[property].length === 0) { if (row[property] == null || row[property].length === 0) {
continue continue