Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single attachment column type #13399

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a4c8fcb
Clean and populate url
adrinr Apr 3, 2024
7d0090a
Fix import/export
adrinr Apr 3, 2024
5437188
Revert "Revert "Single attachment column type""
mike12345567 Apr 3, 2024
dc18b55
Merge pull request #13397 from Budibase/BUDI-8122/dont-persist-url-on…
adrinr Apr 3, 2024
2cd3882
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 4, 2024
6d9d1ac
Update yarn.lock
adrinr Apr 4, 2024
0cb956a
Update submodules
adrinr Apr 4, 2024
c9c3a05
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 4, 2024
615e27c
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 4, 2024
28d10ec
Fix
adrinr Apr 4, 2024
b2ab4e0
Handle singleattachment on AttachmentCleanup
adrinr Apr 4, 2024
e584392
Add attachment_single tests
adrinr Apr 4, 2024
6928e74
Handle single files on imports
adrinr Apr 4, 2024
80dfef9
Test single attachment on outputProcessing
adrinr Apr 4, 2024
1bc5553
Lint
adrinr Apr 4, 2024
5b6c3d0
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 10, 2024
4ca090b
Add single attachment as component on "add component"
adrinr Apr 10, 2024
f69056c
PR comments
adrinr Apr 10, 2024
f6eb27c
Fix merge conflicts
adrinr Apr 10, 2024
8f9dea4
Merge pull request #13408 from Budibase/BUDI-8122/tests
adrinr Apr 10, 2024
b42cc88
Merge pull request #13407 from Budibase/BUDI-8122/attachment_cleanup
adrinr Apr 10, 2024
b4063fa
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 10, 2024
5a93f2b
Change icons to attach
adrinr Apr 10, 2024
38f5302
Revert check
adrinr Apr 10, 2024
e525e0d
Merge branch 'master' into revert-13398-revert-13356-BUDI-8122/single…
adrinr Apr 10, 2024
b707514
Update pro ref to fix flakiness
adrinr Apr 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const componentMap = {
"field/longform": FormFieldSelect,
"field/datetime": FormFieldSelect,
"field/attachment": FormFieldSelect,
"field/attachment_single": FormFieldSelect,
"field/s3": Input,
"field/link": FormFieldSelect,
"field/array": FormFieldSelect,
Expand Down
4 changes: 2 additions & 2 deletions packages/builder/src/constants/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ export const FIELDS = {
ATTACHMENT_SINGLE: {
name: "Attachment",
type: FieldType.ATTACHMENT_SINGLE,
icon: "Document",
icon: TypeIconMap[FieldType.ATTACHMENT_SINGLE],
constraints: {
presence: false,
},
},
ATTACHMENTS: {
name: "Attachment List",
type: FieldType.ATTACHMENTS,
icon: "AppleFiles",
icon: TypeIconMap[FieldType.ATTACHMENTS],
constraints: {
type: "array",
presence: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"optionsfield",
"booleanfield",
"longformfield",
"attachmentsinglefield",
"attachmentfield",
"jsonfield",
"relationshipfield",
Expand Down
6 changes: 0 additions & 6 deletions packages/client/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4354,12 +4354,6 @@
"label": "Extensions",
"key": "extensions"
},
{
"type": "number",
"label": "Max attachments",
"key": "maximum",
"min": 1
},
{
"type": "event",
"label": "On change",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
get: value => value,
set: value => value,
}
export let defaultValue = []

let fieldState
let fieldApi
Expand Down Expand Up @@ -88,7 +89,7 @@
{type}
bind:fieldState
bind:fieldApi
defaultValue={[]}
{defaultValue}
>
{#if fieldState}
<CoreDropzone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
{...$$restProps}
type={FieldType.ATTACHMENT_SINGLE}
maximum={1}
defaultValue={null}
{fieldApiMapper}
/>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

export let value
export let onChange
export let api

$: arrayValue = (!Array.isArray(value) && value ? [value] : value) || []

Expand All @@ -13,6 +14,7 @@
</script>

<AttachmentCell
bind:api
{...$$restProps}
maximum={1}
adrinr marked this conversation as resolved.
Show resolved Hide resolved
value={arrayValue}
Expand Down
21 changes: 0 additions & 21 deletions packages/frontend-core/src/components/grid/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,6 @@ export const getColor = (idx, opacity = 0.3) => {
return `hsla(${((idx + 1) * 222) % 360}, 90%, 75%, ${opacity})`
}

const TypeIconMap = {
[FieldType.STRING]: "Text",
[FieldType.OPTIONS]: "Dropdown",
[FieldType.DATETIME]: "Date",
[FieldType.BARCODEQR]: "Camera",
[FieldType.LONGFORM]: "TextAlignLeft",
[FieldType.ARRAY]: "Dropdown",
[FieldType.NUMBER]: "123",
[FieldType.BOOLEAN]: "Boolean",
[FieldType.ATTACHMENTS]: "AppleFiles",
[FieldType.ATTACHMENT_SINGLE]: "Document",
[FieldType.LINK]: "DataCorrelated",
[FieldType.FORMULA]: "Calculator",
[FieldType.JSON]: "Brackets",
[FieldType.BIGINT]: "TagBold",
[FieldType.BB_REFERENCE]: {
[FieldTypeSubtypes.BB_REFERENCE.USER]: "User",
[FieldTypeSubtypes.BB_REFERENCE.USERS]: "UserGroup",
},
}

export const getColumnIcon = column => {
if (column.schema.autocolumn) {
return "MagicWand"
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend-core/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ export const TypeIconMap = {
[FieldType.ARRAY]: "Duplicate",
[FieldType.NUMBER]: "123",
[FieldType.BOOLEAN]: "Boolean",
[FieldType.ATTACHMENT]: "AppleFiles",
[FieldType.ATTACHMENTS]: "Attach",
[FieldType.ATTACHMENT_SINGLE]: "Attach",
[FieldType.LINK]: "DataCorrelated",
[FieldType.FORMULA]: "Calculator",
[FieldType.JSON]: "Brackets",
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend-core/src/utils/rows.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const isBetterSample = (newValue, oldValue) => {
}
if (
newType === "object" &&
Array.isArray(newValue) &&
Array.isArray(oldValue) &&
adrinr marked this conversation as resolved.
Show resolved Hide resolved
Object.keys(newValue).length > Object.keys(oldValue).length
) {
return true
Expand Down
80 changes: 63 additions & 17 deletions packages/server/src/api/routes/tests/row.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import * as setup from "./utilities"
import { context, InternalTable, tenancy } from "@budibase/backend-core"
import { quotas } from "@budibase/pro"
import {
AttachmentFieldMetadata,
AutoFieldSubType,
Datasource,
DateFieldMetadata,
DeleteRow,
FieldSchema,
FieldType,
FieldTypeSubtypes,
FormulaType,
INTERNAL_TABLE_SOURCE_ID,
NumberFieldMetadata,
QuotaUsageType,
RelationshipType,
Row,
Expand Down Expand Up @@ -232,22 +235,27 @@ describe.each([
name: "str",
constraints: { type: "string", presence: false },
}
const attachment: FieldSchema = {
const singleAttachment: FieldSchema = {
type: FieldType.ATTACHMENT_SINGLE,
name: "single attachment",
constraints: { presence: false },
}
const attachmentList: AttachmentFieldMetadata = {
type: FieldType.ATTACHMENTS,
name: "attachment",
name: "attachments",
constraints: { type: "array", presence: false },
}
const bool: FieldSchema = {
type: FieldType.BOOLEAN,
name: "boolean",
constraints: { type: "boolean", presence: false },
}
const number: FieldSchema = {
const number: NumberFieldMetadata = {
type: FieldType.NUMBER,
name: "str",
constraints: { type: "number", presence: false },
}
const datetime: FieldSchema = {
const datetime: DateFieldMetadata = {
type: FieldType.DATETIME,
name: "datetime",
constraints: {
Expand Down Expand Up @@ -297,10 +305,12 @@ describe.each([
boolUndefined: bool,
boolString: bool,
boolBool: bool,
attachmentNull: attachment,
attachmentUndefined: attachment,
attachmentEmpty: attachment,
attachmentEmptyArrayStr: attachment,
singleAttachmentNull: singleAttachment,
singleAttachmentUndefined: singleAttachment,
attachmentListNull: attachmentList,
attachmentListUndefined: attachmentList,
attachmentListEmpty: attachmentList,
attachmentListEmptyArrayStr: attachmentList,
arrayFieldEmptyArrayStr: arrayField,
arrayFieldArrayStrKnown: arrayField,
arrayFieldNull: arrayField,
Expand Down Expand Up @@ -336,10 +346,12 @@ describe.each([
boolString: "true",
boolBool: true,
tableId: table._id,
attachmentNull: null,
attachmentUndefined: undefined,
attachmentEmpty: "",
attachmentEmptyArrayStr: "[]",
singleAttachmentNull: null,
singleAttachmentUndefined: undefined,
attachmentListNull: null,
attachmentListUndefined: undefined,
attachmentListEmpty: "",
attachmentListEmptyArrayStr: "[]",
arrayFieldEmptyArrayStr: "[]",
arrayFieldUndefined: undefined,
arrayFieldNull: null,
Expand Down Expand Up @@ -368,10 +380,12 @@ describe.each([
expect(row.boolUndefined).toBe(undefined)
expect(row.boolString).toBe(true)
expect(row.boolBool).toBe(true)
expect(row.attachmentNull).toEqual([])
expect(row.attachmentUndefined).toBe(undefined)
expect(row.attachmentEmpty).toEqual([])
expect(row.attachmentEmptyArrayStr).toEqual([])
expect(row.singleAttachmentNull).toEqual(null)
expect(row.singleAttachmentUndefined).toBe(undefined)
expect(row.attachmentListNull).toEqual([])
expect(row.attachmentListUndefined).toBe(undefined)
expect(row.attachmentListEmpty).toEqual([])
expect(row.attachmentListEmptyArrayStr).toEqual([])
expect(row.arrayFieldEmptyArrayStr).toEqual([])
expect(row.arrayFieldNull).toEqual([])
expect(row.arrayFieldUndefined).toEqual(undefined)
Expand Down Expand Up @@ -817,7 +831,39 @@ describe.each([

isInternal &&
describe("attachments", () => {
it("should allow enriching attachment rows", async () => {
it("should allow enriching single attachment rows", async () => {
const table = await config.api.table.save(
defaultTable({
schema: {
attachment: {
type: FieldType.ATTACHMENT_SINGLE,
name: "attachment",
constraints: { presence: false },
},
},
})
)
const attachmentId = `${uuid.v4()}.csv`
const row = await config.api.row.save(table._id!, {
name: "test",
description: "test",
attachment: {
key: `${config.getAppId()}/attachments/${attachmentId}`,
},

tableId: table._id,
})
await config.withEnv({ SELF_HOSTED: "true" }, async () => {
return context.doInAppContext(config.getAppId(), async () => {
const enriched = await outputProcessing(table, [row])
expect((enriched as Row[])[0].attachment.url).toBe(
`/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}`
)
})
})
})

it("should allow enriching attachment list rows", async () => {
const table = await config.api.table.save(
defaultTable({
schema: {
Expand Down
12 changes: 11 additions & 1 deletion packages/server/src/sdk/app/backups/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Automation,
AutomationTriggerStepId,
RowAttachment,
FieldType,
} from "@budibase/types"
import { getAutomationParams } from "../../../db/utils"
import { budibaseTempDir } from "../../../utilities/budibaseDir"
Expand Down Expand Up @@ -58,10 +59,19 @@ export async function updateAttachmentColumns(prodAppId: string, db: Database) {
updatedRows = updatedRows.concat(
rows.map(row => {
for (let column of columns) {
if (Array.isArray(row[column])) {
const columnType = table.schema[column].type
if (
columnType === FieldType.ATTACHMENTS &&
Array.isArray(row[column])
) {
row[column] = row[column].map((attachment: RowAttachment) =>
rewriteAttachmentUrl(prodAppId, attachment)
)
} else if (
columnType === FieldType.ATTACHMENT_SINGLE &&
row[column]
) {
row[column] = rewriteAttachmentUrl(prodAppId, row[column])
}
}
return row
Expand Down
5 changes: 4 additions & 1 deletion packages/server/src/sdk/app/rows/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export async function getRowsWithAttachments(appId: string, table: Table) {
const db = dbCore.getDB(appId)
const attachmentCols: string[] = []
for (let [key, column] of Object.entries(table.schema)) {
if (column.type === FieldType.ATTACHMENTS) {
if (
column.type === FieldType.ATTACHMENTS ||
column.type === FieldType.ATTACHMENT_SINGLE
) {
attachmentCols.push(key)
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/sdk/app/tables/internal/sqs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const FieldTypeMap: Record<FieldType, SQLiteType> = {
[FieldType.JSON]: SQLiteType.BLOB,
[FieldType.INTERNAL]: SQLiteType.BLOB,
[FieldType.BARCODEQR]: SQLiteType.BLOB,
[FieldType.ATTACHMENT]: SQLiteType.BLOB,
[FieldType.ATTACHMENTS]: SQLiteType.BLOB,
[FieldType.ATTACHMENT_SINGLE]: SQLiteType.BLOB,
[FieldType.ARRAY]: SQLiteType.BLOB,
[FieldType.LINK]: SQLiteType.BLOB,
[FieldType.BIGINT]: SQLiteType.REAL,
Expand Down
17 changes: 13 additions & 4 deletions packages/server/src/sdk/tests/attachments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ describe("should be able to re-write attachment URLs", () => {
sourceType: TableSourceType.INTERNAL,
schema: {
photo: {
type: FieldType.ATTACHMENTS,
type: FieldType.ATTACHMENT_SINGLE,
name: "photo",
},
gallery: {
type: FieldType.ATTACHMENTS,
name: "gallery",
},
otherCol: {
type: FieldType.STRING,
name: "otherCol",
Expand All @@ -43,7 +47,8 @@ describe("should be able to re-write attachment URLs", () => {

for (let i = 0; i < FIND_LIMIT * 4; i++) {
await config.api.row.save(table._id!, {
photo: [attachment],
photo: { ...attachment },
gallery: [{ ...attachment }, { ...attachment }],
otherCol: "string",
})
}
Expand All @@ -56,8 +61,12 @@ describe("should be able to re-write attachment URLs", () => {
)
for (const row of rows) {
expect(row.otherCol).toBe("string")
expect(row.photo[0].url).toBe("")
expect(row.photo[0].key).toBe(`${db.name}/attachments/a.png`)
expect(row.photo.url).toBe("")
expect(row.photo.key).toBe(`${db.name}/attachments/a.png`)
expect(row.gallery[0].url).toBe("")
expect(row.gallery[0].key).toBe(`${db.name}/attachments/a.png`)
expect(row.gallery[1].url).toBe("")
expect(row.gallery[1].key).toBe(`${db.name}/attachments/a.png`)
}
})
})