Browse Source

Merge pull request #4506 from nocodb/develop

pull/4507/head 0.99.2
github-actions[bot] 2 years ago committed by GitHub
parent
commit
6d53af2f16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/nc-gui/app.vue
  2. 1
      packages/nc-gui/components/smartsheet/header/CellIcon.ts
  3. 21
      packages/nc-gui/components/virtual-cell/Lookup.vue
  4. 2
      packages/nc-gui/layouts/default.vue
  5. 52
      packages/nc-gui/package-lock.json
  6. 2
      packages/nc-gui/package.json
  7. 4
      packages/nocodb-sdk/package-lock.json
  8. 30
      packages/nocodb/package-lock.json
  9. 2
      packages/nocodb/package.json
  10. 80
      packages/nocodb/src/lib/db/sql-client/lib/mssql/MssqlClient.ts
  11. 37
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts
  12. 9
      packages/nocodb/src/lib/meta/helpers/populateSamplePayload.ts

2
packages/nc-gui/app.vue

@ -36,7 +36,7 @@ if (typeof window !== 'undefined') {
<template> <template>
<a-config-provider> <a-config-provider>
<NuxtLayout :name="disableBaseLayout ? false : 'base'"> <NuxtLayout :name="disableBaseLayout ? false : 'base'">
<NuxtPage :transition="false" :key="key" /> <NuxtPage :key="key" :transition="false" />
</NuxtLayout> </NuxtLayout>
</a-config-provider> </a-config-provider>
</template> </template>

1
packages/nc-gui/components/smartsheet/header/CellIcon.ts

@ -19,7 +19,6 @@ import {
isJSON, isJSON,
isPercent, isPercent,
isPhoneNumber, isPhoneNumber,
isPrimary,
isRating, isRating,
isSet, isSet,
isSingleSelect, isSingleSelect,

21
packages/nc-gui/components/virtual-cell/Lookup.vue

@ -27,14 +27,6 @@ const meta = inject(MetaInj, ref())
const cellValue = inject(CellValueInj, ref()) const cellValue = inject(CellValueInj, ref())
const arrValue = computed(() => {
if (!cellValue.value) return []
if (Array.isArray(cellValue.value)) return cellValue.value
return [cellValue.value]
})
const relationColumn = computed( const relationColumn = computed(
() => () =>
meta.value?.columns?.find((c) => c.id === (column.value?.colOptions as LookupType)?.fk_relation_column_id) as meta.value?.columns?.find((c) => c.id === (column.value?.colOptions as LookupType)?.fk_relation_column_id) as
@ -66,6 +58,19 @@ const lookupColumn = computed(
| undefined, | undefined,
) )
const arrValue = computed(() => {
if (!cellValue.value) return []
// if lookup column is Attachment and relation type is Belongs to wrap the value in an array
// since the attachment component expects an array or JSON string array
if (lookupColumn.value?.uidt === UITypes.Attachment && relationColumn.value?.colOptions?.type === RelationTypes.BELONGS_TO)
return [cellValue.value]
if (Array.isArray(cellValue.value)) return cellValue.value
return [cellValue.value]
})
provide(MetaInj, lookupTableMeta) provide(MetaInj, lookupTableMeta)
provide(CellUrlDisableOverlayInj, ref(true)) provide(CellUrlDisableOverlayInj, ref(true))

2
packages/nc-gui/layouts/default.vue

@ -20,7 +20,7 @@ export default {
<template> <template>
<div class="w-full h-full"> <div class="w-full h-full">
<Teleport :to="hasSidebar ? '#nc-sidebar-left' : null" :disabled="!hasSidebar"> <Teleport :to="hasSidebar ? '#nc-sidebar-left' : null" :disabled="!hasSidebar">
<slot name="sidebar" /> <slot :key="$route.name" name="sidebar" />
</Teleport> </Teleport>
<a-layout-content> <a-layout-content>

52
packages/nc-gui/package-lock.json generated

@ -26,7 +26,7 @@
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"locale-codes": "^1.3.1", "locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
"nocodb-sdk": "0.99.1", "nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2", "papaparse": "^5.3.2",
"socket.io-client": "^4.5.1", "socket.io-client": "^4.5.1",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
@ -86,7 +86,6 @@
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.99.1", "version": "0.99.1",
"extraneous": true,
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -8391,6 +8390,7 @@
"version": "1.15.1", "version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@ -11748,21 +11748,8 @@
} }
}, },
"node_modules/nocodb-sdk": { "node_modules/nocodb-sdk": {
"version": "0.99.1", "resolved": "../nocodb-sdk",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.99.1.tgz", "link": true
"integrity": "sha512-CfaYgqi4m5jFWaRazsshvLN468Trfq/DxXVAzLz9hIZv88urYbXJaAwbXTNR8q+CTpACabkN9NW02HL6Jr1LQQ==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
},
"node_modules/nocodb-sdk/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
}, },
"node_modules/node-abi": { "node_modules/node-abi": {
"version": "3.23.0", "version": "3.23.0",
@ -23377,7 +23364,8 @@
"follow-redirects": { "follow-redirects": {
"version": "1.15.1", "version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true
}, },
"form-data": { "form-data": {
"version": "4.0.0", "version": "4.0.0",
@ -25847,22 +25835,22 @@
} }
}, },
"nocodb-sdk": { "nocodb-sdk": {
"version": "0.99.1", "version": "file:../nocodb-sdk",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.99.1.tgz",
"integrity": "sha512-CfaYgqi4m5jFWaRazsshvLN468Trfq/DxXVAzLz9hIZv88urYbXJaAwbXTNR8q+CTpACabkN9NW02HL6Jr1LQQ==",
"requires": { "requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1", "axios": "^0.21.1",
"jsep": "^1.3.6" "cspell": "^4.1.0",
}, "eslint": "^7.8.0",
"dependencies": { "eslint-config-prettier": "^6.11.0",
"axios": { "eslint-plugin-eslint-comments": "^3.2.0",
"version": "0.21.4", "eslint-plugin-functional": "^3.0.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", "eslint-plugin-import": "^2.22.0",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "eslint-plugin-prettier": "^4.0.0",
"requires": { "jsep": "^1.3.6",
"follow-redirects": "^1.14.0" "npm-run-all": "^4.1.5",
} "prettier": "^2.1.1",
} "typescript": "^4.0.2"
} }
}, },
"node-abi": { "node-abi": {

2
packages/nc-gui/package.json

@ -49,7 +49,7 @@
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"locale-codes": "^1.3.1", "locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
"nocodb-sdk": "0.99.1", "nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2", "papaparse": "^5.3.2",
"socket.io-client": "^4.5.1", "socket.io-client": "^4.5.1",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",

4
packages/nocodb-sdk/package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.99.0", "version": "0.99.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.99.0", "version": "0.99.1",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",

30
packages/nocodb/package-lock.json generated

@ -67,7 +67,7 @@
"nc-lib-gui": "0.99.1", "nc-lib-gui": "0.99.1",
"nc-plugin": "0.1.2", "nc-plugin": "0.1.2",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"nocodb-sdk": "0.99.1", "nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10", "nodemailer": "^6.4.10",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"os-locale": "^5.0.0", "os-locale": "^5.0.0",
@ -153,7 +153,6 @@
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.99.1", "version": "0.99.1",
"extraneous": true,
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -10686,13 +10685,8 @@
"dev": true "dev": true
}, },
"node_modules/nocodb-sdk": { "node_modules/nocodb-sdk": {
"version": "0.99.1", "resolved": "../nocodb-sdk",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.99.1.tgz", "link": true
"integrity": "sha512-CfaYgqi4m5jFWaRazsshvLN468Trfq/DxXVAzLz9hIZv88urYbXJaAwbXTNR8q+CTpACabkN9NW02HL6Jr1LQQ==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
}, },
"node_modules/node-abort-controller": { "node_modules/node-abort-controller": {
"version": "3.0.1", "version": "3.0.1",
@ -26114,12 +26108,22 @@
"dev": true "dev": true
}, },
"nocodb-sdk": { "nocodb-sdk": {
"version": "0.99.1", "version": "file:../nocodb-sdk",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.99.1.tgz",
"integrity": "sha512-CfaYgqi4m5jFWaRazsshvLN468Trfq/DxXVAzLz9hIZv88urYbXJaAwbXTNR8q+CTpACabkN9NW02HL6Jr1LQQ==",
"requires": { "requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1", "axios": "^0.21.1",
"jsep": "^1.3.6" "cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
} }
}, },
"node-abort-controller": { "node-abort-controller": {

2
packages/nocodb/package.json

@ -107,7 +107,7 @@
"nc-lib-gui": "0.99.1", "nc-lib-gui": "0.99.1",
"nc-plugin": "0.1.2", "nc-plugin": "0.1.2",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"nocodb-sdk": "0.99.1", "nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10", "nodemailer": "^6.4.10",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"os-locale": "^5.0.0", "os-locale": "^5.0.0",

80
packages/nocodb/src/lib/db/sql-client/lib/mssql/MssqlClient.ts

@ -356,12 +356,14 @@ class MssqlClient extends KnexClient {
try { try {
/** ************** START : create _evolution table if not exists *************** */ /** ************** START : create _evolution table if not exists *************** */
const exists = await this.sqlClient.schema.withSchema(this.schema).hasTable(args.tn); const exists = await this.sqlClient.schema
.withSchema(this.schema)
.hasTable(args.tn);
if (!exists) { if (!exists) {
await this.sqlClient.schema.withSchema(this.schema).createTable( await this.sqlClient.schema
args.tn, .withSchema(this.schema)
function (table) { .createTable(args.tn, function (table) {
table.increments(); table.increments();
table.string('title').notNullable(); table.string('title').notNullable();
table.string('titleDown').nullable(); table.string('titleDown').nullable();
@ -371,8 +373,7 @@ class MssqlClient extends KnexClient {
table.integer('status').nullable(); table.integer('status').nullable();
table.dateTime('created'); table.dateTime('created');
table.timestamps(); table.timestamps();
} });
);
log.debug('Table created:', `${this.getTnPath(args.tn)}`); log.debug('Table created:', `${this.getTnPath(args.tn)}`);
} else { } else {
log.debug(`${this.getTnPath(args.tn)} tables exists`); log.debug(`${this.getTnPath(args.tn)} tables exists`);
@ -394,7 +395,9 @@ class MssqlClient extends KnexClient {
log.api(`${_func}:args:`, args); log.api(`${_func}:args:`, args);
try { try {
result.data.value = await this.sqlClient.schema.withSchema(this.schema).hasTable(args.tn); result.data.value = await this.sqlClient.schema
.withSchema(this.schema)
.hasTable(args.tn);
} catch (e) { } catch (e) {
log.ppe(e, _func); log.ppe(e, _func);
throw e; throw e;
@ -1343,7 +1346,8 @@ class MssqlClient extends KnexClient {
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);
// `DROP TRIGGER ${args.trigger_name}` // `DROP TRIGGER ${args.trigger_name}`
try { try {
const query = `${this.querySeparator()}DROP TRIGGER IF EXISTS ${args.trigger_name const query = `${this.querySeparator()}DROP TRIGGER IF EXISTS ${
args.trigger_name
}`; }`;
await this.sqlClient.raw(query); await this.sqlClient.raw(query);
@ -1474,7 +1478,8 @@ class MssqlClient extends KnexClient {
{ {
sql: sql:
this.querySeparator() + this.querySeparator() +
`DROP FUNCTION IF EXISTS ${args.function_name `DROP FUNCTION IF EXISTS ${
args.function_name
};${this.querySeparator()}\n${args.create_function}`, };${this.querySeparator()}\n${args.create_function}`,
}, },
], ],
@ -1482,7 +1487,8 @@ class MssqlClient extends KnexClient {
{ {
sql: sql:
this.querySeparator() + this.querySeparator() +
`DROP FUNCTION IF EXISTS ${args.function_name `DROP FUNCTION IF EXISTS ${
args.function_name
};${this.querySeparator()} ${args.oldCreateFunction}`, };${this.querySeparator()} ${args.oldCreateFunction}`,
}, },
], ],
@ -1554,7 +1560,8 @@ class MssqlClient extends KnexClient {
{ {
sql: sql:
this.querySeparator() + this.querySeparator() +
`DROP PROCEDURE IF EXISTS ${args.procedure_name `DROP PROCEDURE IF EXISTS ${
args.procedure_name
};${this.querySeparator()}\n${args.create_procedure}`, };${this.querySeparator()}\n${args.create_procedure}`,
}, },
], ],
@ -1562,7 +1569,8 @@ class MssqlClient extends KnexClient {
{ {
sql: sql:
this.querySeparator() + this.querySeparator() +
`DROP PROCEDURE IF EXISTS ${args.procedure_name `DROP PROCEDURE IF EXISTS ${
args.procedure_name
};${this.querySeparator()}${args.oldCreateProcedure}`, };${this.querySeparator()}${args.oldCreateProcedure}`,
}, },
], ],
@ -1627,7 +1635,8 @@ class MssqlClient extends KnexClient {
try { try {
// await this.sqlClient.raw(`DROP TRIGGER ${args.trigger_name}`); // await this.sqlClient.raw(`DROP TRIGGER ${args.trigger_name}`);
await this.sqlClient.raw( await this.sqlClient.raw(
`ALTER TRIGGER ${args.trigger_name} ON ${this.getTnPath(args.tn)} \n${args.timing `ALTER TRIGGER ${args.trigger_name} ON ${this.getTnPath(args.tn)} \n${
args.timing
} ${args.event}\n AS\n${args.statement}` } ${args.event}\n AS\n${args.statement}`
); );
@ -1712,7 +1721,8 @@ class MssqlClient extends KnexClient {
{ {
sql: sql:
this.querySeparator() + this.querySeparator() +
`DROP VIEW ${args.view_name} ; ${this.querySeparator()}${args.oldViewDefination `DROP VIEW ${args.view_name} ; ${this.querySeparator()}${
args.oldViewDefination
};`, };`,
}, },
], ],
@ -1807,7 +1817,10 @@ class MssqlClient extends KnexClient {
const downStatement = const downStatement =
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema.withSchema(this.schema).dropTable(args.table).toString(); this.sqlClient.schema
.withSchema(this.schema)
.dropTable(args.table)
.toString();
this.emit(`Success : ${upQuery}`); this.emit(`Success : ${upQuery}`);
@ -1849,7 +1862,15 @@ class MssqlClient extends KnexClient {
BEGIN BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
UPDATE ?? Set ?? = GetDate() WHERE ?? in (SELECT ?? FROM Inserted) UPDATE ?? Set ?? = GetDate() WHERE ?? in (SELECT ?? FROM Inserted)
END;`, [triggerName, this.getTnPath(args.table_name), this.getTnPath(args.table_name), column.column_name, pk.column_name, pk.column_name] END;`,
[
triggerName,
this.getTnPath(args.table_name),
this.getTnPath(args.table_name),
column.column_name,
pk.column_name,
pk.column_name,
]
); );
upQuery += triggerCreateQuery; upQuery += triggerCreateQuery;
@ -2051,7 +2072,10 @@ class MssqlClient extends KnexClient {
/** ************** create up & down statements *************** */ /** ************** create up & down statements *************** */
const upStatement = const upStatement =
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema.withSchema(this.schema).dropTable(args.tn).toString(); this.sqlClient.schema
.withSchema(this.schema)
.dropTable(args.tn)
.toString();
let downQuery = this.querySeparator() + this.createTable(args.tn, args); let downQuery = this.querySeparator() + this.createTable(args.tn, args);
this.emit(`Success : ${upStatement}`); this.emit(`Success : ${upStatement}`);
@ -2065,8 +2089,9 @@ class MssqlClient extends KnexClient {
for (const relation of relationsList) { for (const relation of relationsList) {
downQuery += downQuery +=
this.querySeparator() + this.querySeparator() +
(await this.sqlClient.withSchema(this.schema).schema (await this.sqlClient
.table(relation.tn, (table) => { .withSchema(this.schema)
.schema.table(relation.tn, (table) => {
table = table table = table
.foreign(relation.cn, null) .foreign(relation.cn, null)
.references(relation.rcn) .references(relation.rcn)
@ -2109,7 +2134,8 @@ class MssqlClient extends KnexClient {
)) { )) {
downQuery += downQuery +=
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema.withSchema(this.schema) this.sqlClient.schema
.withSchema(this.schema)
.table(tn, function (table) { .table(tn, function (table) {
if (non_unique) { if (non_unique) {
table.index(columns, key_name); table.index(columns, key_name);
@ -2154,7 +2180,9 @@ class MssqlClient extends KnexClient {
try { try {
const self = this; const self = this;
await this.sqlClient.schema.table(this.getTnPath(args.childTable), function (table) { await this.sqlClient.schema.table(
this.getTnPath(args.childTable),
function (table) {
table = table table = table
.foreign(args.childColumn, foreignKeyName) .foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn) .references(args.parentColumn)
@ -2166,7 +2194,8 @@ class MssqlClient extends KnexClient {
if (args.onDelete) { if (args.onDelete) {
table = table.onDelete(args.onDelete); table = table.onDelete(args.onDelete);
} }
}); }
);
const upStatement = const upStatement =
this.querySeparator() + this.querySeparator() +
@ -2227,9 +2256,12 @@ class MssqlClient extends KnexClient {
try { try {
const self = this; const self = this;
await this.sqlClient.schema.table(this.getTnPath(args.childTable), function (table) { await this.sqlClient.schema.table(
this.getTnPath(args.childTable),
function (table) {
table.dropForeign(args.childColumn, foreignKeyName); table.dropForeign(args.childColumn, foreignKeyName);
}); }
);
const upStatement = const upStatement =
this.querySeparator() + this.querySeparator() +

37
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts

@ -158,9 +158,10 @@ class BaseModelSqlv2 {
qb.orderBy(this.model.primaryKey.column_name); qb.orderBy(this.model.primaryKey.column_name);
} }
const data = await qb.first(); let data = await qb.first();
if (data) { if (data) {
data = this.convertAttachmentType(data);
const proto = await this.getProto(); const proto = await this.getProto();
data.__proto__ = proto; data.__proto__ = proto;
} }
@ -365,8 +366,7 @@ class BaseModelSqlv2 {
qb.groupBy(args.column_name); qb.groupBy(args.column_name);
if (sorts) await sortV2(sorts, qb, this.dbDriver); if (sorts) await sortV2(sorts, qb, this.dbDriver);
applyPaginate(qb, rest); applyPaginate(qb, rest);
const data = await qb; return this.convertAttachmentType(await qb);
return data;
} }
async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) { async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) {
@ -672,10 +672,10 @@ class BaseModelSqlv2 {
); );
let children = await this.extractRawQueryAndExec(finalQb); let children = await this.extractRawQueryAndExec(finalQb);
children = this.convertAttachmentType(children);
if (this.isMySQL) { if (this.isMySQL) {
children = children[0]; children = children[0];
} }
children = this.convertAttachmentType(children);
const proto = await ( const proto = await (
await Model.getBaseModelSQL({ await Model.getBaseModelSQL({
id: rtnId, id: rtnId,
@ -967,8 +967,8 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest); applyPaginate(qb, rest);
const proto = await childModel.getProto(); const proto = await childModel.getProto();
const data = await qb; let data = await qb;
data = this.convertAttachmentType(data);
return data.map((c) => { return data.map((c) => {
c.__proto__ = proto; c.__proto__ = proto;
return c; return c;
@ -2737,6 +2737,15 @@ class BaseModelSqlv2 {
: await this.dbDriver.raw(query); : await this.dbDriver.raw(query);
} }
private _convertAttachmentType(attachmentColumns, d) {
attachmentColumns.forEach((col) => {
if (d[col.title] && typeof d[col.title] === 'string') {
d[col.title] = JSON.parse(d[col.title]);
}
});
return d;
}
private convertAttachmentType(data) { private convertAttachmentType(data) {
// attachment is stored in text and parse in UI // attachment is stored in text and parse in UI
// convertAttachmentType is used to convert the response in string to array of object in API response // convertAttachmentType is used to convert the response in string to array of object in API response
@ -2745,17 +2754,13 @@ class BaseModelSqlv2 {
(c) => c.uidt === UITypes.Attachment (c) => c.uidt === UITypes.Attachment
); );
if (attachmentColumns.length) { if (attachmentColumns.length) {
if (!Array.isArray(data)) { if (Array.isArray(data)) {
data = [data]; data = data.map((d) =>
} this._convertAttachmentType(attachmentColumns, d)
data = data.map((d) => { );
attachmentColumns.forEach((col) => { } else {
if (d[col.title] && typeof d[col.title] === 'string') { this._convertAttachmentType(attachmentColumns, data);
d[col.title] = JSON.parse(d[col.title]);
} }
});
return d;
});
} }
} }
return data; return data;

9
packages/nocodb/src/lib/meta/helpers/populateSamplePayload.ts

@ -94,7 +94,14 @@ async function getSampleColumnValue(column: Column): Promise<any> {
break; break;
case UITypes.Attachment: case UITypes.Attachment:
{ {
return '[{"url":"https://nocodb.com/dummy.png","title":"image.png","mimetype":"image/png","size":0}]'; return [
{
url: 'https://nocodb.com/dummy.png',
title: 'image.png',
mimetype: 'image/png',
size: 0,
},
];
} }
break; break;
case UITypes.Checkbox: case UITypes.Checkbox:

Loading…
Cancel
Save