-
+
+
+ {{ localState ? checkedIcon :uncheckedIcon }}
+
@@ -8,10 +10,19 @@
export default {
name: 'BooleanCell',
props: {
+ column: Object,
value: [String, Number, Boolean],
- isForm: Boolean
+ isForm: Boolean,
+ readOnly: Boolean
},
computed: {
+
+ checkedIcon() {
+ return (this.checkboxMeta && this.checkboxMeta.icon && this.checkboxMeta.icon.checked) || 'mdi-check-bold'
+ },
+ uncheckedIcon() {
+ return (this.checkboxMeta && this.checkboxMeta.icon && this.checkboxMeta.icon.unchecked) || 'mdi-crop-square'
+ },
localState: {
get() {
return this.value
@@ -20,14 +31,27 @@ export default {
this.$emit('input', val)
}
},
-
parentListeners() {
const $listeners = {}
return $listeners
+ },
+ checkboxMeta() {
+ return {
+ icon: {
+ checked: 'mdi-check-circle-outline',
+ unchecked: 'mdi-checkbox-blank-circle-outline'
+ },
+ color: 'primary',
+ ...(this.column && this.column.meta
+ ? this.column.meta
+ : {})
+ }
}
},
- mounted() {
- this.$el.focus()
+ methods: {
+ toggle() {
+ this.localState = !this.localState
+ }
}
}
diff --git a/packages/nc-gui/components/project/spreadsheet/components/editableCell/EditableUrlCell.vue b/packages/nc-gui/components/project/spreadsheet/components/editableCell/EditableUrlCell.vue
index c6bbfc18ae..78d1670b88 100644
--- a/packages/nc-gui/components/project/spreadsheet/components/editableCell/EditableUrlCell.vue
+++ b/packages/nc-gui/components/project/spreadsheet/components/editableCell/EditableUrlCell.vue
@@ -8,7 +8,8 @@ import { isValidURL } from '@/helpers'
export default {
name: 'EditableUrlCell',
props: {
- value: String
+ value: String,
+ column: Object
},
computed: {
localState: {
@@ -16,7 +17,11 @@ export default {
return this.value
},
set(val) {
- if (isValidURL(val)) { this.$emit('input', val) }
+ if (!(
+ this.column &&
+ this.column.meta &&
+ this.column.meta.validate
+ ) || isValidURL(val)) { this.$emit('input', val) }
}
},
parentListeners() {
diff --git a/packages/nc-gui/components/project/spreadsheet/components/editableCell/RatingCell.vue b/packages/nc-gui/components/project/spreadsheet/components/editableCell/RatingCell.vue
new file mode 100644
index 0000000000..003c172d0d
--- /dev/null
+++ b/packages/nc-gui/components/project/spreadsheet/components/editableCell/RatingCell.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+ {{ fullIcon }}
+
+
+ {{ emptyIcon }}
+
+
+
+
+
+
+
+
+
diff --git a/packages/nc-gui/components/project/spreadsheet/mixins/cell.js b/packages/nc-gui/components/project/spreadsheet/mixins/cell.js
index c6fbccca6e..57880fd019 100644
--- a/packages/nc-gui/components/project/spreadsheet/mixins/cell.js
+++ b/packages/nc-gui/components/project/spreadsheet/mixins/cell.js
@@ -56,9 +56,15 @@ export default {
isURL() {
return this.uiDatatype === 'URL'
},
+ isEmail() {
+ return this.uiDatatype === UITypes.Email
+ },
isAttachment() {
return this.uiDatatype === 'Attachment'
},
+ isRating() {
+ return this.uiDatatype === UITypes.Rating
+ },
isCurrency() {
return this.column.uidt == 'Currency'
}
diff --git a/packages/nc-gui/components/project/spreadsheet/views/GridView.vue b/packages/nc-gui/components/project/spreadsheet/views/GridView.vue
index 87416c0d18..54987b88a5 100644
--- a/packages/nc-gui/components/project/spreadsheet/views/GridView.vue
+++ b/packages/nc-gui/components/project/spreadsheet/views/GridView.vue
@@ -139,7 +139,7 @@
v-show="!rowMeta || !rowMeta.selected"
class="ml-2 grey--text"
:class="{ 'row-no': !isPublicView }"
- >{{ row + 1 }}
+ >{{ row + 1 }}
.v-input__control {
+ > .v-input__control {
min-height: auto;
}
@@ -1163,4 +1163,18 @@ td:first-child {
.has-many-icon {
transform: rotate(90deg);
}
+
+::v-deep {
+ tr {
+ .nc-cell-hover-show {
+ opacity: 0;
+ transition: .3s opacity;
+ }
+
+ &:hover .nc-cell-hover-show {
+ opacity: .7;
+ }
+ }
+}
+
diff --git a/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts
index ea52649575..a9ed5d0bd2 100644
--- a/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts
+++ b/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts
@@ -1,4 +1,4 @@
-import UITypes from "../UITypes";
+import UITypes from '../UITypes';
const dbTypes = [
'bigint',
@@ -35,15 +35,15 @@ const dbTypes = [
'uniqueidentifier',
'varbinary',
'xml',
- 'varchar'
+ 'varchar',
];
export class MssqlUi {
static getNewTableColumns() {
return [
{
- column_name: 'id',
- title: 'Id',
+ column_name: 'id',
+ title: 'Id',
dt: 'int',
dtx: 'integer',
ct: 'int(11)',
@@ -62,11 +62,11 @@ export class MssqlUi {
altered: 1,
uidt: 'ID',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'title',
- title: 'Title',
+ column_name: 'title',
+ title: 'Title',
dt: 'varchar',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -85,11 +85,11 @@ export class MssqlUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'created_at',
- title: 'CreatedAt',
+ column_name: 'created_at',
+ title: 'CreatedAt',
dt: 'datetime',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -108,11 +108,11 @@ export class MssqlUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'updated_at',
- title: 'UpdatedAt',
+ column_name: 'updated_at',
+ title: 'UpdatedAt',
dt: 'datetime',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -131,8 +131,8 @@ export class MssqlUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
- }
+ uicn: '',
+ },
];
}
@@ -157,7 +157,7 @@ export class MssqlUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
};
}
@@ -741,13 +741,15 @@ export class MssqlUi {
}
static extractFunctionName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
@@ -808,7 +810,7 @@ export class MssqlUi {
const column = {
dp: null,
tn,
- column_name: keys[i],
+ column_name: keys[i],
cno: keys[i],
np: 10,
ns: 0,
@@ -827,7 +829,7 @@ export class MssqlUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
};
switch (typeof json[keys[i]]) {
@@ -835,13 +837,13 @@ export class MssqlUi {
if (Number.isInteger(json[keys[i]])) {
if (MssqlUi.isValidTimestamp(keys[i], json[keys[i]])) {
Object.assign(column, {
- dt: 'timestamp'
+ dt: 'timestamp',
});
} else {
Object.assign(column, {
dt: 'int',
np: 10,
- ns: 0
+ ns: 0,
});
}
} else {
@@ -850,25 +852,25 @@ export class MssqlUi {
np: 10,
ns: 2,
dtxp: '11',
- dtxs: 2
+ dtxs: 2,
});
}
break;
case 'string':
if (MssqlUi.isValidDate(json[keys[i]])) {
Object.assign(column, {
- dt: 'datetime'
+ dt: 'datetime',
});
} else if (json[keys[i]].length <= 255) {
Object.assign(column, {
dt: 'varchar',
np: 255,
ns: 0,
- dtxp: '255'
+ dtxp: '255',
});
} else {
Object.assign(column, {
- dt: 'text'
+ dt: 'text',
});
}
break;
@@ -876,7 +878,7 @@ export class MssqlUi {
Object.assign(column, {
dt: 'bit',
np: null,
- ns: 0
+ ns: 0,
});
break;
case 'object':
@@ -884,7 +886,7 @@ export class MssqlUi {
dt: 'varchar',
np: 255,
ns: 0,
- dtxp: '255'
+ dtxp: '255',
});
break;
default:
@@ -1043,9 +1045,7 @@ export class MssqlUi {
}
}
- static getDataTypeForUiType(
- col
- ): {
+ static getDataTypeForUiType(col): {
readonly dt: string;
readonly [key: string]: any;
} {
@@ -1098,7 +1098,7 @@ export class MssqlUi {
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
- msg: ['Validation failed : isMobilePhone']
+ msg: ['Validation failed : isMobilePhone'],
};
break;
case 'Email':
@@ -1106,7 +1106,7 @@ export class MssqlUi {
colProp.validate = {
func: ['isEmail'],
args: [''],
- msg: ['Validation failed : isEmail']
+ msg: ['Validation failed : isEmail'],
};
break;
case 'URL':
@@ -1114,7 +1114,7 @@ export class MssqlUi {
colProp.validate = {
func: ['isURL'],
args: [''],
- msg: ['Validation failed : isURL']
+ msg: ['Validation failed : isURL'],
};
break;
case 'Number':
@@ -1128,7 +1128,7 @@ export class MssqlUi {
colProp.validate = {
func: ['isCurrency'],
args: [''],
- msg: ['Validation failed : isCurrency']
+ msg: ['Validation failed : isCurrency'],
};
break;
case 'Percent':
@@ -1138,7 +1138,7 @@ export class MssqlUi {
colProp.dt = 'int';
break;
case 'Rating':
- colProp.dt = 'float';
+ colProp.dt = 'int';
break;
case 'Formula':
colProp.dt = 'varchar';
@@ -1224,7 +1224,7 @@ export class MssqlUi {
'numeric',
'real',
'smallint',
- 'tinyint'
+ 'tinyint',
];
case 'Decimal':
@@ -1240,7 +1240,7 @@ export class MssqlUi {
'numeric',
'real',
'smallint',
- 'tinyint'
+ 'tinyint',
];
case 'Percent':
@@ -1253,7 +1253,7 @@ export class MssqlUi {
'numeric',
'real',
'smallint',
- 'tinyint'
+ 'tinyint',
];
case 'Duration':
@@ -1266,7 +1266,7 @@ export class MssqlUi {
'numeric',
'real',
'smallint',
- 'tinyint'
+ 'tinyint',
];
case 'Rating':
@@ -1279,7 +1279,7 @@ export class MssqlUi {
'numeric',
'real',
'smallint',
- 'tinyint'
+ 'tinyint',
];
case 'Formula':
@@ -1302,7 +1302,7 @@ export class MssqlUi {
case 'LastModifiedTime':
return [
'datetimeoffset',
- 'datetime2'
+ 'datetime2',
// 'datetime'
];
diff --git a/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts
index f639e8a2a4..18063917d2 100644
--- a/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts
+++ b/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts
@@ -1,4 +1,4 @@
-import UITypes from "../UITypes";
+import UITypes from '../UITypes';
const dbTypes = [
'int',
@@ -39,7 +39,7 @@ const dbTypes = [
'multipoint',
'multilinestring',
'multipolygon',
- 'json'
+ 'json',
];
export class MysqlUi {
@@ -66,7 +66,7 @@ export class MysqlUi {
altered: 1,
uidt: 'ID',
uip: '',
- uicn: ''
+ uicn: '',
},
{
column_name: 'title',
@@ -89,7 +89,7 @@ export class MysqlUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
},
{
column_name: 'created_at',
@@ -112,7 +112,7 @@ export class MysqlUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
+ uicn: '',
},
{
column_name: 'updated_at',
@@ -135,8 +135,8 @@ export class MysqlUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
- }
+ uicn: '',
+ },
];
}
@@ -161,7 +161,7 @@ export class MysqlUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
};
}
@@ -659,13 +659,15 @@ export class MysqlUi {
}
static extractFunctionName(query) {
- const reg = /^\s*CREATE\s+.*?(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:`?[\w\d_]+`?\.)?`?([\w_\d]+)`?/i;
+ const reg =
+ /^\s*CREATE\s+.*?(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:`?[\w\d_]+`?\.)?`?([\w_\d]+)`?/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
- const reg = /^\s*CREATE.*?\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE.*?\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
@@ -677,14 +679,14 @@ export class MysqlUi {
// set headers before settings result
for (let i = 0; i < keys.length; i++) {
const text = keys[i];
- headers.push({text, value: text, sortable: false});
+ headers.push({ text, value: text, sortable: false });
}
} else {
const keys = Object.keys(result);
for (let i = 0; i < keys.length; i++) {
const text = keys[i];
if (typeof text !== 'function') {
- headers.push({text, value: text, sortable: false});
+ headers.push({ text, value: text, sortable: false });
}
}
result = [result];
@@ -750,7 +752,7 @@ export class MysqlUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
};
switch (typeof json[keys[i]]) {
@@ -758,13 +760,13 @@ export class MysqlUi {
if (Number.isInteger(json[keys[i]])) {
if (MysqlUi.isValidTimestamp(keys[i], json[keys[i]])) {
Object.assign(column, {
- dt: 'timestamp'
+ dt: 'timestamp',
});
} else {
Object.assign(column, {
dt: 'int',
np: 10,
- ns: 0
+ ns: 0,
});
}
} else {
@@ -773,25 +775,25 @@ export class MysqlUi {
np: 10,
ns: 2,
dtxp: '11',
- dtxs: 2
+ dtxs: 2,
});
}
break;
case 'string':
if (MysqlUi.isValidDate(json[keys[i]])) {
Object.assign(column, {
- dt: 'datetime'
+ dt: 'datetime',
});
} else if (json[keys[i]].length <= 255) {
Object.assign(column, {
dt: 'varchar',
np: 255,
ns: 0,
- dtxp: '255'
+ dtxp: '255',
});
} else {
Object.assign(column, {
- dt: 'text'
+ dt: 'text',
});
}
break;
@@ -799,14 +801,14 @@ export class MysqlUi {
Object.assign(column, {
dt: 'boolean',
np: 3,
- ns: 0
+ ns: 0,
});
break;
case 'object':
Object.assign(column, {
dt: 'json',
np: 3,
- ns: 0
+ ns: 0,
});
break;
default:
@@ -991,7 +993,7 @@ export class MysqlUi {
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
- msg: ['Validation failed : isMobilePhone ({cn})']
+ msg: ['Validation failed : isMobilePhone ({cn})'],
};
break;
case 'Email':
@@ -999,7 +1001,7 @@ export class MysqlUi {
colProp.validate = {
func: ['isEmail'],
args: [''],
- msg: ['Validation failed : isEmail ({cn})']
+ msg: ['Validation failed : isEmail ({cn})'],
};
break;
case 'URL':
@@ -1007,7 +1009,7 @@ export class MysqlUi {
colProp.validate = {
func: ['isURL'],
args: [''],
- msg: ['Validation failed : isURL ({cn})']
+ msg: ['Validation failed : isURL ({cn})'],
};
break;
case 'Number':
@@ -1021,7 +1023,7 @@ export class MysqlUi {
colProp.validate = {
func: ['isCurrency'],
args: [''],
- msg: ['Validation failed : isCurrency']
+ msg: ['Validation failed : isCurrency'],
};
break;
case 'Percent':
@@ -1031,7 +1033,7 @@ export class MysqlUi {
colProp.dt = 'int';
break;
case 'Rating':
- colProp.dt = 'float';
+ colProp.dt = 'int';
break;
case 'Formula':
colProp.dt = 'varchar';
@@ -1089,7 +1091,7 @@ export class MysqlUi {
'text',
'tinytext',
'mediumtext',
- 'longtext'
+ 'longtext',
];
case 'Attachment':
@@ -1101,7 +1103,7 @@ export class MysqlUi {
'text',
'tinytext',
'mediumtext',
- 'longtext'
+ 'longtext',
];
case 'JSON':
@@ -1116,7 +1118,7 @@ export class MysqlUi {
'bit',
'boolean',
'serial',
- 'tinyint'
+ 'tinyint',
];
case 'MultiSelect':
@@ -1148,7 +1150,7 @@ export class MysqlUi {
'float',
'decimal',
'double',
- 'serial'
+ 'serial',
];
case 'Decimal':
@@ -1164,7 +1166,7 @@ export class MysqlUi {
'smallint',
'mediumint',
'bigint',
- 'bit'
+ 'bit',
];
case 'Percent':
@@ -1177,7 +1179,7 @@ export class MysqlUi {
'smallint',
'mediumint',
'bigint',
- 'bit'
+ 'bit',
];
case 'Duration':
@@ -1190,7 +1192,7 @@ export class MysqlUi {
'smallint',
'mediumint',
'bigint',
- 'bit'
+ 'bit',
];
case 'Rating':
@@ -1203,7 +1205,7 @@ export class MysqlUi {
'smallint',
'mediumint',
'bigint',
- 'bit'
+ 'bit',
];
case 'Formula':
@@ -1214,7 +1216,7 @@ export class MysqlUi {
'text',
'tinytext',
'mediumtext',
- 'longtext'
+ 'longtext',
];
case 'Rollup':
@@ -1248,7 +1250,7 @@ export class MysqlUi {
'polygon',
'multipoint',
'multilinestring',
- 'multipolygon'
+ 'multipolygon',
];
case 'Button':
diff --git a/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts
index 3f1b14ac2a..f8fe150422 100644
--- a/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts
+++ b/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts
@@ -22,7 +22,7 @@ export class OracleUi {
altered: 1,
uidt: 'ID',
uip: '',
- uicn: ''
+ uicn: '',
},
{
column_name: 'title',
@@ -45,8 +45,8 @@ export class OracleUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
- }
+ uicn: '',
+ },
// {
// column_name: "created_at",
// dt: "timestamp",
@@ -107,7 +107,7 @@ export class OracleUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
};
}
@@ -435,13 +435,15 @@ export class OracleUi {
}
static extractFunctionName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
@@ -522,7 +524,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: '11',
dtxs: 0,
- altered: 1
+ altered: 1,
});
} else {
columns.push({
@@ -548,7 +550,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: '11',
dtxs: 2,
- altered: 1
+ altered: 1,
});
}
@@ -579,7 +581,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: '45',
dtxs: 0,
- altered: 1
+ altered: 1,
});
} else {
columns.push({
@@ -605,7 +607,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
});
}
@@ -635,7 +637,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: '1',
dtxs: 0,
- altered: 1
+ altered: 1,
});
break;
@@ -663,7 +665,7 @@ export class OracleUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
});
break;
@@ -839,7 +841,7 @@ export class OracleUi {
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
- msg: ['Validation failed : isMobilePhone']
+ msg: ['Validation failed : isMobilePhone'],
};
break;
case 'Email':
@@ -847,7 +849,7 @@ export class OracleUi {
colProp.validate = {
func: ['isEmail'],
args: [''],
- msg: ['Validation failed : isEmail']
+ msg: ['Validation failed : isEmail'],
};
break;
case 'URL':
@@ -855,7 +857,7 @@ export class OracleUi {
colProp.validate = {
func: ['isURL'],
args: [''],
- msg: ['Validation failed : isURL']
+ msg: ['Validation failed : isURL'],
};
break;
case 'Number':
@@ -869,7 +871,7 @@ export class OracleUi {
colProp.validate = {
func: ['isCurrency'],
args: [''],
- msg: ['Validation failed : isCurrency']
+ msg: ['Validation failed : isCurrency'],
};
break;
case 'Percent':
@@ -879,7 +881,7 @@ export class OracleUi {
colProp.dt = 'integer';
break;
case 'Rating':
- colProp.dt = 'float';
+ colProp.dt = 'integer';
break;
case 'Formula':
colProp.dt = 'varchar';
diff --git a/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts
index 49b695a0f5..ecea78b096 100644
--- a/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts
+++ b/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts
@@ -1,4 +1,4 @@
-import UITypes from "../UITypes";
+import UITypes from '../UITypes';
const dbTypes = [
'int',
@@ -98,15 +98,15 @@ const dbTypes = [
'unknown',
'void',
'xid',
- 'xml'
+ 'xml',
];
export class PgUi {
static getNewTableColumns() {
return [
{
- column_name: 'id',
- title: 'Id',
+ column_name: 'id',
+ title: 'Id',
dt: 'int4',
dtx: 'integer',
ct: 'int(11)',
@@ -125,11 +125,11 @@ export class PgUi {
altered: 1,
uidt: 'ID',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'title',
- title: 'Title',
+ column_name: 'title',
+ title: 'Title',
dt: 'character varying',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -148,11 +148,11 @@ export class PgUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'created_at',
- title: 'CreatedAt',
+ column_name: 'created_at',
+ title: 'CreatedAt',
dt: 'timestamp',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -171,11 +171,11 @@ export class PgUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'updated_at',
- title: 'UpdatedAt',
+ column_name: 'updated_at',
+ title: 'UpdatedAt',
dt: 'timestamp',
dtx: 'specificType',
ct: 'varchar(45)',
@@ -195,8 +195,8 @@ export class PgUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
- }
+ uicn: '',
+ },
];
}
@@ -221,7 +221,7 @@ export class PgUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
};
}
@@ -1160,13 +1160,15 @@ export class PgUi {
}
static extractFunctionName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
@@ -1176,8 +1178,8 @@ export class PgUi {
headers.push({ text: 'Row count', value: 'rowCount', sortable: false });
result = [
{
- rowCount: result.rowCount
- }
+ rowCount: result.rowCount,
+ },
];
} else {
result = result.rows;
@@ -1232,7 +1234,7 @@ export class PgUi {
const column = {
dp: null,
tn,
- column_name: keys[i],
+ column_name: keys[i],
cno: keys[i],
np: 10,
ns: 0,
@@ -1251,7 +1253,7 @@ export class PgUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
};
switch (typeof json[keys[i]]) {
@@ -1259,13 +1261,13 @@ export class PgUi {
if (Number.isInteger(json[keys[i]])) {
if (PgUi.isValidTimestamp(keys[i], json[keys[i]])) {
Object.assign(column, {
- dt: 'timestamp'
+ dt: 'timestamp',
});
} else {
Object.assign(column, {
dt: 'int',
np: 10,
- ns: 0
+ ns: 0,
});
}
} else {
@@ -1274,25 +1276,25 @@ export class PgUi {
np: null,
ns: null,
dtxp: null,
- dtxs: null
+ dtxs: null,
});
}
break;
case 'string':
if (PgUi.isValidDate(json[keys[i]])) {
Object.assign(column, {
- dt: 'date'
+ dt: 'date',
});
} else if (json[keys[i]].length <= 255) {
Object.assign(column, {
dt: 'character varying',
np: null,
ns: 0,
- dtxp: null
+ dtxp: null,
});
} else {
Object.assign(column, {
- dt: 'text'
+ dt: 'text',
});
}
break;
@@ -1300,14 +1302,14 @@ export class PgUi {
Object.assign(column, {
dt: 'boolean',
np: 3,
- ns: 0
+ ns: 0,
});
break;
case 'object':
Object.assign(column, {
dt: 'json',
np: 3,
- ns: 0
+ ns: 0,
});
break;
default:
@@ -1521,7 +1523,6 @@ export class PgUi {
case 'longblob':
return 'blob';
case 'enum':
-
return 'enum';
case 'set':
return 'set';
@@ -1616,7 +1617,7 @@ export class PgUi {
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
- msg: ['Validation failed : isMobilePhone']
+ msg: ['Validation failed : isMobilePhone'],
};
break;
case 'Email':
@@ -1624,7 +1625,7 @@ export class PgUi {
colProp.validate = {
func: ['isEmail'],
args: [''],
- msg: ['Validation failed : isEmail']
+ msg: ['Validation failed : isEmail'],
};
break;
case 'URL':
@@ -1632,7 +1633,7 @@ export class PgUi {
colProp.validate = {
func: ['isURL'],
args: [''],
- msg: ['Validation failed : isURL']
+ msg: ['Validation failed : isURL'],
};
break;
case 'Number':
@@ -1646,7 +1647,7 @@ export class PgUi {
colProp.validate = {
func: ['isCurrency'],
args: [''],
- msg: ['Validation failed : isCurrency']
+ msg: ['Validation failed : isCurrency'],
};
break;
case 'Percent':
@@ -1656,7 +1657,7 @@ export class PgUi {
colProp.dt = 'int8';
break;
case 'Rating':
- colProp.dt = 'float8';
+ colProp.dt = 'smallint';
break;
case 'Formula':
colProp.dt = 'character varying';
@@ -1732,7 +1733,7 @@ export class PgUi {
'int8range',
'serial',
'serial2',
- 'serial8'
+ 'serial8',
];
case 'MultiSelect':
@@ -1753,7 +1754,7 @@ export class PgUi {
'timestamptz',
'timestamp with time zone',
'timetz',
- 'time with time zone'
+ 'time with time zone',
];
case 'PhoneNumber':
@@ -1780,7 +1781,7 @@ export class PgUi {
'float8',
'smallint',
'smallserial',
- 'numeric'
+ 'numeric',
];
case 'Decimal':
@@ -1802,7 +1803,7 @@ export class PgUi {
'money',
'float4',
'float8',
- 'numeric'
+ 'numeric',
];
case 'Percent':
@@ -1822,7 +1823,7 @@ export class PgUi {
'float8',
'smallint',
'smallserial',
- 'numeric'
+ 'numeric',
];
case 'Duration':
@@ -1842,7 +1843,7 @@ export class PgUi {
'float8',
'smallint',
'smallserial',
- 'numeric'
+ 'numeric',
];
case 'Rating':
@@ -1862,7 +1863,7 @@ export class PgUi {
'float8',
'smallint',
'smallserial',
- 'numeric'
+ 'numeric',
];
case 'Formula':
@@ -1884,7 +1885,7 @@ export class PgUi {
'serial2',
'serial8',
'smallint',
- 'smallserial'
+ 'smallserial',
];
case 'Lookup':
@@ -1896,7 +1897,7 @@ export class PgUi {
'timestamp',
'timestamp without time zone',
'timestamptz',
- 'timestamp with time zone'
+ 'timestamp with time zone',
];
case 'DateTime':
@@ -1906,7 +1907,7 @@ export class PgUi {
'timestamp',
'timestamp without time zone',
'timestamptz',
- 'timestamp with time zone'
+ 'timestamp with time zone',
];
case 'AutoNumber':
@@ -1922,7 +1923,7 @@ export class PgUi {
'serial2',
'serial8',
'smallint',
- 'smallserial'
+ 'smallserial',
];
case 'Barcode':
@@ -1937,7 +1938,7 @@ export class PgUi {
'line',
'lseg',
'path',
- 'circle'
+ 'circle',
];
case 'Button':
diff --git a/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts
index f2dfb426ec..905ae534a4 100644
--- a/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts
+++ b/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts
@@ -1,4 +1,4 @@
-import UITypes from "../UITypes";
+import UITypes from '../UITypes';
const dbTypes = [
'int',
@@ -22,15 +22,15 @@ const dbTypes = [
'datetime',
'text',
'varchar',
- 'timestamp'
+ 'timestamp',
];
export class SqliteUi {
static getNewTableColumns() {
return [
{
- column_name: 'id',
- title: 'Id',
+ column_name: 'id',
+ title: 'Id',
dt: 'integer',
dtx: 'integer',
ct: 'int(11)',
@@ -49,11 +49,11 @@ export class SqliteUi {
altered: 1,
uidt: 'ID',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'title',
- title: 'Title',
+ column_name: 'title',
+ title: 'Title',
dt: 'varchar',
dtx: 'specificType',
ct: 'varchar',
@@ -72,11 +72,11 @@ export class SqliteUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'created_at',
- title: 'CreatedAt',
+ column_name: 'created_at',
+ title: 'CreatedAt',
dt: 'datetime',
dtx: 'specificType',
ct: 'varchar',
@@ -95,11 +95,11 @@ export class SqliteUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
+ uicn: '',
},
{
- column_name: 'updated_at',
- title: 'UpdatedAt',
+ column_name: 'updated_at',
+ title: 'UpdatedAt',
dt: 'datetime',
dtx: 'specificType',
ct: 'varchar',
@@ -118,8 +118,8 @@ export class SqliteUi {
altered: 1,
uidt: UITypes.DateTime,
uip: '',
- uicn: ''
- }
+ uicn: '',
+ },
];
}
@@ -144,7 +144,7 @@ export class SqliteUi {
altered: 1,
uidt: 'SingleLineText',
uip: '',
- uicn: ''
+ uicn: '',
};
}
@@ -498,13 +498,15 @@ export class SqliteUi {
}
static extractFunctionName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
- const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
+ const reg =
+ /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
@@ -565,7 +567,7 @@ export class SqliteUi {
const column = {
dp: null,
tn,
- column_name: keys[i],
+ column_name: keys[i],
cno: keys[i],
np: null,
ns: null,
@@ -584,7 +586,7 @@ export class SqliteUi {
dtx: 'specificType',
dtxp: null,
dtxs: 0,
- altered: 1
+ altered: 1,
};
switch (typeof json[keys[i]]) {
@@ -592,16 +594,16 @@ export class SqliteUi {
if (Number.isInteger(json[keys[i]])) {
if (SqliteUi.isValidTimestamp(keys[i], json[keys[i]])) {
Object.assign(column, {
- dt: 'timestamp'
+ dt: 'timestamp',
});
} else {
Object.assign(column, {
- dt: 'integer'
+ dt: 'integer',
});
}
} else {
Object.assign(column, {
- dt: 'real'
+ dt: 'real',
});
}
break;
@@ -613,24 +615,24 @@ export class SqliteUi {
// } else
if (json[keys[i]].length <= 255) {
Object.assign(column, {
- dt: 'varchar'
+ dt: 'varchar',
});
} else {
Object.assign(column, {
- dt: 'text'
+ dt: 'text',
});
}
break;
case 'boolean':
Object.assign(column, {
- dt: 'integer'
+ dt: 'integer',
});
break;
case 'object':
Object.assign(column, {
dt: 'text',
np: null,
- dtxp: null
+ dtxp: null,
});
break;
default:
@@ -807,7 +809,7 @@ export class SqliteUi {
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
- msg: ['Validation failed : isMobilePhone']
+ msg: ['Validation failed : isMobilePhone'],
};
break;
case 'Email':
@@ -815,7 +817,7 @@ export class SqliteUi {
colProp.validate = {
func: ['isEmail'],
args: [''],
- msg: ['Validation failed : isEmail']
+ msg: ['Validation failed : isEmail'],
};
break;
case 'URL':
@@ -823,7 +825,7 @@ export class SqliteUi {
colProp.validate = {
func: ['isURL'],
args: [''],
- msg: ['Validation failed : isURL']
+ msg: ['Validation failed : isURL'],
};
break;
case 'Number':
@@ -837,7 +839,7 @@ export class SqliteUi {
colProp.validate = {
func: ['isCurrency'],
args: [''],
- msg: ['Validation failed : isCurrency']
+ msg: ['Validation failed : isCurrency'],
};
break;
case 'Percent':
@@ -847,7 +849,7 @@ export class SqliteUi {
colProp.dt = 'integer';
break;
case 'Rating':
- colProp.dt = 'float';
+ colProp.dt = 'integer';
break;
case 'Formula':
colProp.dt = 'varchar';
@@ -911,7 +913,7 @@ export class SqliteUi {
'bigint',
'int2',
'int8',
- 'boolean'
+ 'boolean',
];
case 'MultiSelect':
@@ -929,7 +931,7 @@ export class SqliteUi {
'mediumint',
'bigint',
'int2',
- 'int8'
+ 'int8',
];
case 'Time':
@@ -941,7 +943,7 @@ export class SqliteUi {
'mediumint',
'bigint',
'int2',
- 'int8'
+ 'int8',
];
case 'PhoneNumber':
@@ -965,7 +967,7 @@ export class SqliteUi {
'real',
'double',
'double precision',
- 'float'
+ 'float',
];
case 'Decimal':
@@ -985,7 +987,7 @@ export class SqliteUi {
'bigint',
'int2',
'int8',
- 'numeric'
+ 'numeric',
];
case 'Percent':
@@ -1002,7 +1004,7 @@ export class SqliteUi {
'bigint',
'int2',
'int8',
- 'numeric'
+ 'numeric',
];
case 'Duration':
@@ -1014,15 +1016,11 @@ export class SqliteUi {
'mediumint',
'bigint',
'int2',
- 'int8'
+ 'int8',
];
case 'Rating':
return [
- 'real',
- 'double',
- 'double precision',
- 'float',
'int',
'integer',
'tinyint',
@@ -1031,7 +1029,11 @@ export class SqliteUi {
'bigint',
'int2',
'int8',
- 'numeric'
+ 'numeric',
+ 'real',
+ 'double',
+ 'double precision',
+ 'float',
];
case 'Formula':
@@ -1049,7 +1051,7 @@ export class SqliteUi {
'mediumint',
'bigint',
'int2',
- 'int8'
+ 'int8',
];
case 'Lookup':
@@ -1072,7 +1074,7 @@ export class SqliteUi {
'mediumint',
'bigint',
'int2',
- 'int8'
+ 'int8',
];
case 'Barcode':
diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
index f9e67c6222..e9f781fb10 100644
--- a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
+++ b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
@@ -1776,6 +1776,9 @@ class BaseModelSqlv2 {
// let cols = Object.keys(this.columns);
for (let i = 0; i < this.model.columns.length; ++i) {
const column = this.model.columns[i];
+ // skip validation if `validate` is undefined or false
+ if (!column?.meta?.validate) continue;
+
const validate = column.getValidators();
const cn = column.column_name;
if (!validate) continue;
diff --git a/packages/nocodb/src/lib/noco-models/Column.ts b/packages/nocodb/src/lib/noco-models/Column.ts
index 3c3de4f6b6..63d942599f 100644
--- a/packages/nocodb/src/lib/noco-models/Column.ts
+++ b/packages/nocodb/src/lib/noco-models/Column.ts
@@ -56,6 +56,7 @@ export default class Column implements ColumnType {
public order: number;
public validate: any;
+ public meta: any;
constructor(data: Partial) {
Object.assign(this, data);
@@ -106,7 +107,11 @@ export default class Column implements ColumnType {
order: column.order,
project_id: column.project_id,
base_id: column.base_id,
- system: column.system
+ system: column.system,
+ meta:
+ column.meta && typeof column.meta === 'object'
+ ? JSON.stringify(column.meta)
+ : column.meta
};
if (column.validate) {
@@ -375,6 +380,17 @@ export default class Column implements ColumnType {
order: 'asc'
}
});
+
+ columnsList.forEach(column => {
+ if (column.meta && typeof column.meta === 'string') {
+ try {
+ column.meta = JSON.parse(column.meta);
+ } catch {
+ column.meta = {};
+ }
+ }
+ });
+
await NocoCache.setList(CacheScope.COLUMN, [fk_model_id], columnsList);
}
columnsList.sort(
@@ -452,6 +468,11 @@ export default class Column implements ColumnType {
MetaTable.COLUMNS,
colId
);
+ try {
+ colData.meta = JSON.parse(colData.meta);
+ } catch {
+ colData.meta = {};
+ }
await NocoCache.set(`${CacheScope.COLUMN}:${colId}`, colData);
}
if (colData) {
@@ -783,7 +804,8 @@ export default class Column implements ColumnType {
au: column.au,
pv: column.pv,
system: column.system,
- validate: null
+ validate: null,
+ meta: column.meta
};
if (column.validate) {
@@ -801,7 +823,19 @@ export default class Column implements ColumnType {
await NocoCache.set(key, o);
}
// set meta
- await ncMeta.metaUpdate(null, null, MetaTable.COLUMNS, updateObj, colId);
+ await ncMeta.metaUpdate(
+ null,
+ null,
+ MetaTable.COLUMNS,
+ {
+ ...updateObj,
+ meta:
+ updateObj.meta && typeof updateObj.meta === 'object'
+ ? JSON.stringify(updateObj.meta)
+ : updateObj.meta
+ },
+ colId
+ );
await this.insertColOption(column, colId, ncMeta);
}
diff --git a/packages/nocodb/src/lib/noco/common/XcMigrationSourcev2.ts b/packages/nocodb/src/lib/noco/common/XcMigrationSourcev2.ts
index eeca1fae48..63405c2084 100644
--- a/packages/nocodb/src/lib/noco/common/XcMigrationSourcev2.ts
+++ b/packages/nocodb/src/lib/noco/common/XcMigrationSourcev2.ts
@@ -2,6 +2,7 @@ import * as nc_011 from '../migrationsv2/nc_011';
import * as nc_012_alter_column_data_types from '../migrationsv2/nc_012_alter_column_data_types';
import * as nc_013_sync_source from '../migrationsv2/nc_013_sync_source';
import * as nc_014_alter_column_data_types from '../migrationsv2/nc_014_alter_column_data_types';
+import * as nc_015_add_meta_col_in_column_table from '../migrationsv2/nc_015_add_meta_col_in_column_table';
// Create a custom migration source class
export default class XcMigrationSourcev2 {
@@ -14,7 +15,8 @@ export default class XcMigrationSourcev2 {
'nc_011',
'nc_012_alter_column_data_types',
'nc_013_sync_source',
- 'nc_014_alter_column_data_types'
+ 'nc_014_alter_column_data_types',
+ 'nc_015_add_meta_col_in_column_table'
]);
}
@@ -32,6 +34,8 @@ export default class XcMigrationSourcev2 {
return nc_013_sync_source;
case 'nc_014_alter_column_data_types':
return nc_014_alter_column_data_types;
+ case 'nc_015_add_meta_col_in_column_table':
+ return nc_015_add_meta_col_in_column_table;
}
}
}
diff --git a/packages/nocodb/src/lib/noco/migrationsv2/nc_015_add_meta_col_in_column_table.ts b/packages/nocodb/src/lib/noco/migrationsv2/nc_015_add_meta_col_in_column_table.ts
new file mode 100644
index 0000000000..aeb1d9f9d4
--- /dev/null
+++ b/packages/nocodb/src/lib/noco/migrationsv2/nc_015_add_meta_col_in_column_table.ts
@@ -0,0 +1,38 @@
+import Knex from 'knex';
+import { MetaTable } from '../../utils/globals';
+
+const up = async (knex: Knex) => {
+ await knex.schema.alterTable(MetaTable.COLUMNS, table => {
+ table.text('meta');
+ });
+};
+
+const down = async knex => {
+ await knex.schema.alterTable(MetaTable.COLUMNS, table => {
+ table.dropColumn('meta');
+ });
+};
+
+export { up, down };
+
+/**
+ * @copyright Copyright (c) 2022, Xgene Cloud Ltd
+ *
+ * @author Wing-Kam Wong
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
diff --git a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts
index 5a8439a7f3..d2765134af 100644
--- a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts
+++ b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts
@@ -436,6 +436,10 @@ async function migrateProjectModels(
columnMeta.uidt = UITypes.ForeignKey;
}
+ if (columnMeta.uidt === UITypes.Rating) {
+ columnMeta.uidt = UITypes.Number;
+ }
+
const column = await Column.insert(
{
...columnMeta,