Merge pull request #10462 from Budibase/fix/budi-6789-import-data-empty-date-is-not-allowed
Fix - Budi 6789 import data empty date is not allowed
This commit is contained in:
commit
fa6e6b53f8
|
@ -37,7 +37,7 @@ import {
|
|||
Table,
|
||||
} from "@budibase/types"
|
||||
|
||||
const { cleanExportRows } = require("./utils")
|
||||
import { cleanExportRows } from "./utils"
|
||||
|
||||
const CALCULATION_TYPES = {
|
||||
SUM: "sum",
|
||||
|
@ -391,6 +391,9 @@ export async function exportRows(ctx: UserCtx) {
|
|||
const table = await db.get(ctx.params.tableId)
|
||||
const rowIds = ctx.request.body.rows
|
||||
let format = ctx.query.format
|
||||
if (typeof format !== "string") {
|
||||
ctx.throw(400, "Format parameter is not valid")
|
||||
}
|
||||
const { columns, query } = ctx.request.body
|
||||
|
||||
let result
|
||||
|
|
|
@ -137,8 +137,8 @@ export function cleanExportRows(
|
|||
delete schema[column]
|
||||
})
|
||||
|
||||
// Intended to avoid 'undefined' in export
|
||||
if (format === Format.CSV) {
|
||||
// Intended to append empty values in export
|
||||
const schemaKeys = Object.keys(schema)
|
||||
for (let key of schemaKeys) {
|
||||
if (columns?.length && columns.indexOf(key) > 0) {
|
||||
|
@ -146,7 +146,7 @@ export function cleanExportRows(
|
|||
}
|
||||
for (let row of cleanRows) {
|
||||
if (row[key] == null) {
|
||||
row[key] = ""
|
||||
row[key] = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { getDatasourceParams } from "../../../db/utils"
|
|||
import { context, events } from "@budibase/backend-core"
|
||||
import { Table, UserCtx } from "@budibase/types"
|
||||
import sdk from "../../../sdk"
|
||||
import csv from "csvtojson"
|
||||
import { jsonFromCsvString } from "../../../utilities/csv"
|
||||
|
||||
function pickApi({ tableId, table }: { tableId?: string; table?: Table }) {
|
||||
if (table && !tableId) {
|
||||
|
@ -104,7 +104,7 @@ export async function bulkImport(ctx: UserCtx) {
|
|||
export async function csvToJson(ctx: UserCtx) {
|
||||
const { csvString } = ctx.request.body
|
||||
|
||||
const result = await csv().fromString(csvString)
|
||||
const result = await jsonFromCsvString(csvString)
|
||||
|
||||
ctx.status = 200
|
||||
ctx.body = result
|
||||
|
|
|
@ -10,7 +10,9 @@ export function csv(headers: string[], rows: Row[]) {
|
|||
val =
|
||||
typeof val === "object" && !(val instanceof Date)
|
||||
? `"${JSON.stringify(val).replace(/"/g, "'")}"`
|
||||
: `"${val}"`
|
||||
: val !== undefined
|
||||
? `"${val}"`
|
||||
: ""
|
||||
return val.trim()
|
||||
})
|
||||
.join(",")}`
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import csv from "csvtojson"
|
||||
|
||||
export async function jsonFromCsvString(csvString: string) {
|
||||
const castedWithEmptyValues = await csv({ ignoreEmpty: true }).fromString(
|
||||
csvString
|
||||
)
|
||||
|
||||
// By default the csvtojson library casts empty values as empty strings. This is causing issues on conversion.
|
||||
// ignoreEmpty will remove the key completly if empty, so creating this empty object will ensure we return the values with the keys but empty values
|
||||
const result = await csv({ ignoreEmpty: false }).fromString(csvString)
|
||||
result.forEach((r, i) => {
|
||||
for (const [key] of Object.entries(r).filter(
|
||||
([key, value]) => value === ""
|
||||
)) {
|
||||
if (castedWithEmptyValues[i][key] === undefined) {
|
||||
r[key] = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
|
@ -4,6 +4,9 @@ interface SchemaColumn {
|
|||
readonly name: string
|
||||
readonly type: FieldTypes
|
||||
readonly autocolumn?: boolean
|
||||
readonly constraints?: {
|
||||
presence: boolean
|
||||
}
|
||||
}
|
||||
|
||||
interface Schema {
|
||||
|
@ -76,6 +79,11 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
|
|||
// If the columnType is not a string, then it's not present in the schema, and should be added to the invalid columns array
|
||||
if (typeof columnType !== "string") {
|
||||
results.invalidColumns.push(columnName)
|
||||
} else if (
|
||||
columnData == null &&
|
||||
!schema[columnName].constraints?.presence
|
||||
) {
|
||||
results.schemaValidation[columnName] = true
|
||||
} else if (
|
||||
// If there's no data for this field don't bother with further checks
|
||||
// If the field is already marked as invalid there's no need for further checks
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { jsonFromCsvString } from "../csv"
|
||||
|
||||
describe("csv", () => {
|
||||
describe("jsonFromCsvString", () => {
|
||||
test("multiple lines csv can be casted", async () => {
|
||||
const csvString = '"id","title"\n"1","aaa"\n"2","bbb"'
|
||||
|
||||
const result = await jsonFromCsvString(csvString)
|
||||
|
||||
expect(result).toEqual([
|
||||
{ id: "1", title: "aaa" },
|
||||
{ id: "2", title: "bbb" },
|
||||
])
|
||||
result.forEach(r => expect(Object.keys(r)).toEqual(["id", "title"]))
|
||||
})
|
||||
|
||||
test("empty values are casted as undefined", async () => {
|
||||
const csvString =
|
||||
'"id","optional","title"\n1,,"aaa"\n2,"value","bbb"\n3,,"ccc"'
|
||||
|
||||
const result = await jsonFromCsvString(csvString)
|
||||
|
||||
expect(result).toEqual([
|
||||
{ id: "1", optional: null, title: "aaa" },
|
||||
{ id: "2", optional: "value", title: "bbb" },
|
||||
{ id: "3", optional: null, title: "ccc" },
|
||||
])
|
||||
result.forEach(r =>
|
||||
expect(Object.keys(r)).toEqual(["id", "optional", "title"])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue