Skip to content

Commit b06ddcb

Browse files
authored
Merge pull request #191 from devforth/next
Next
2 parents 4920ce8 + 96bc6ec commit b06ddcb

File tree

22 files changed

+470
-43
lines changed

22 files changed

+470
-43
lines changed

adminforth/dataConnectors/baseConnector.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,28 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
6868
// go through all filters in array and call validation+normalization for each
6969
// as soon as error is encountered, there is no point in calling validation for other filters
7070
// if error is not encountered all filters will be validated and normalized
71-
return filters.reduce((result, f) => {
71+
return filters.reduce((result, f, fIndex) => {
7272
if (!result.ok) {
7373
return result;
7474
}
7575

76-
return this.validateAndNormalizeFilters(f, resource);
76+
const filterValidation = this.validateAndNormalizeFilters(f, resource);
77+
78+
// in case column isArray and enumerator/foreign resource - IN filter must be transformed into OR filter
79+
if (filterValidation.ok && f.operator == AdminForthFilterOperators.IN) {
80+
const column = resource.dataSourceColumns.find((col) => col.name == (f as IAdminForthSingleFilter).field);
81+
// console.log(`\n~~~ column: ${JSON.stringify(column, null, 2)}\n~~~ resource.columns: ${JSON.stringify(resource.dataSourceColumns, null, 2)}\n~~~ filter: ${JSON.stringify(f, null, 2)}\n`);
82+
if (column.isArray?.enabled && (column.enum || column.foreignResource)) {
83+
filters[fIndex] = {
84+
operator: AdminForthFilterOperators.OR,
85+
subFilters: f.value.map((v: any) => {
86+
return { field: column.name, operator: AdminForthFilterOperators.LIKE, value: v };
87+
}),
88+
};
89+
}
90+
}
91+
92+
return filterValidation;
7793
}, { ok: true, error: '' });
7894
}
7995

adminforth/dataConnectors/clickhouse.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
107107
}
108108
return dayjs(value).toISOString().split('T')[0];
109109
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
110-
return !!value;
110+
return value === null ? null : !!value;
111111
} else if (field.type == AdminForthDataTypes.JSON) {
112112
if (field._underlineType.startsWith('String') || field._underlineType.startsWith('FixedString')) {
113113
try {
@@ -138,7 +138,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
138138
return iso;
139139
}
140140
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
141-
return value ? 1 : 0;
141+
return value === null ? null : (value ? 1 : 0);
142142
} else if (field.type == AdminForthDataTypes.JSON) {
143143
// check underline type is text or string
144144
if (field._underlineType.startsWith('String') || field._underlineType.startsWith('FixedString')) {
@@ -180,6 +180,19 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
180180
let operator = this.OperatorsMap[filter.operator];
181181
if (filter.operator == AdminForthFilterOperators.IN || filter.operator == AdminForthFilterOperators.NIN) {
182182
placeholder = `(${filter.value.map((_, j) => `{p$?:${column._underlineType}}`).join(', ')})`;
183+
} else if (filter.operator == AdminForthFilterOperators.EQ && filter.value === null) {
184+
operator = 'IS';
185+
placeholder = 'NULL';
186+
} else if (filter.operator == AdminForthFilterOperators.NE) {
187+
if (filter.value === null) {
188+
operator = 'IS NOT';
189+
placeholder = 'NULL';
190+
} else {
191+
// for not equal, we need to add a null check
192+
// because nullish field will not match != value
193+
placeholder = `${placeholder} OR ${field} IS NULL)`;
194+
field = `(${field}`;
195+
}
183196
}
184197

185198
return `${field} ${operator} ${placeholder}`;
@@ -209,6 +222,12 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
209222
return [{ 'f': `%${filter.value}%` }];
210223
} else if (filter.operator == AdminForthFilterOperators.IN || filter.operator == AdminForthFilterOperators.NIN) {
211224
return [{ 'p': filter.value }];
225+
} else if (filter.operator == AdminForthFilterOperators.EQ && filter.value === null) {
226+
// there is no param for IS NULL filter
227+
return [];
228+
} else if (filter.operator == AdminForthFilterOperators.NE && filter.value === null) {
229+
// there is no param for IS NOT NULL filter
230+
return [];
212231
} else {
213232
return [{ 'f': (filter as IAdminForthSingleFilter).value }];
214233
}

adminforth/dataConnectors/mongo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
8686
return dayjs(Date.parse(value)).toISOString().split('T')[0];
8787

8888
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
89-
return !!value;
89+
return value === null ? null : !!value;
9090
} else if (field.type == AdminForthDataTypes.DECIMAL) {
9191
return value?.toString();
9292
}
@@ -108,7 +108,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
108108
return dayjs(value).toISOString();
109109
}
110110
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
111-
return value ? true : false;
111+
return value === null ? null : (value ? true : false);
112112
} else if (field.type == AdminForthDataTypes.DECIMAL) {
113113
return Decimal128.fromString(value?.toString());
114114
}

adminforth/dataConnectors/mysql.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
130130
} else if (field.type == AdminForthDataTypes.TIME) {
131131
return value || null;
132132
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
133-
return !!value;
133+
return value === null ? null : !!value;
134134
} else if (field.type == AdminForthDataTypes.JSON) {
135135
if (typeof value === 'string') {
136136
try {
@@ -158,7 +158,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
158158
}
159159
return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
160160
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
161-
return value ? 1 : 0;
161+
return value === null ? null : (value ? 1 : 0);
162162
} else if (field.type == AdminForthDataTypes.JSON) {
163163
if (field._underlineType === 'json') {
164164
return value;
@@ -182,6 +182,19 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
182182
placeholder = `LOWER(?)`;
183183
field = `LOWER(${field})`;
184184
operator = 'LIKE';
185+
} else if (filter.operator == AdminForthFilterOperators.NE) {
186+
if (filter.value === null) {
187+
operator = 'IS NOT';
188+
placeholder = 'NULL';
189+
} else {
190+
// for not equal, we need to add a null check
191+
// because nullish field will not match != value
192+
placeholder = `${placeholder} OR ${field} IS NULL)`;
193+
field = `(${field}`;
194+
}
195+
} else if (filter.operator == AdminForthFilterOperators.EQ && filter.value === null) {
196+
operator = 'IS';
197+
placeholder = 'NULL';
185198
}
186199
return `${field} ${operator} ${placeholder}`;
187200
}
@@ -209,6 +222,10 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
209222
return [`%${filter.value}%`];
210223
} else if (filter.operator == AdminForthFilterOperators.IN || filter.operator == AdminForthFilterOperators.NIN) {
211224
return filter.value;
225+
} else if (filter.operator == AdminForthFilterOperators.EQ && (filter as IAdminForthSingleFilter).value === null) {
226+
return [];
227+
} else if (filter.operator == AdminForthFilterOperators.NE && (filter as IAdminForthSingleFilter).value === null) {
228+
return [];
212229
} else {
213230
return [(filter as IAdminForthSingleFilter).value];
214231
}

adminforth/dataConnectors/postgres.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
157157
return dayjs(value).toISOString().split('T')[0];
158158
}
159159

160+
if (field.type == AdminForthDataTypes.BOOLEAN) {
161+
return value === null ? null : !!value;
162+
}
163+
160164
if (field.type == AdminForthDataTypes.JSON) {
161165
if (typeof value == 'string') {
162166
try {
@@ -188,7 +192,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
188192
return dayjs(value).toISOString();
189193
}
190194
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
191-
return value ? 1 : 0;
195+
return value === null ? null : (value ? 1 : 0);
192196
} else if (field.type == AdminForthDataTypes.JSON) {
193197
if (field._underlineType == 'json') {
194198
return value;
@@ -213,6 +217,9 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
213217
(filter.operator == AdminForthFilterOperators.ILIKE || filter.operator == AdminForthFilterOperators.LIKE)
214218
) {
215219
field = `cast("${field}" as text)`
220+
} else if (filter.operator == AdminForthFilterOperators.EQ && filter.value === null) {
221+
operator = 'IS';
222+
placeholder = 'NULL';
216223
} else {
217224
field = `"${field}"`
218225
}
@@ -243,6 +250,8 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
243250
return [`%${filter.value}%`];
244251
} else if (filter.operator == AdminForthFilterOperators.IN || filter.operator == AdminForthFilterOperators.NIN) {
245252
return filter.value;
253+
} else if (filter.operator == AdminForthFilterOperators.EQ && filter.value === null) {
254+
return [];
246255
} else {
247256
return [(filter as IAdminForthSingleFilter).value];
248257
}

adminforth/dataConnectors/sqlite.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
8181
return dayjs(value).toISOString().split('T')[0];
8282

8383
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
84-
return !!value;
84+
return value === null ? null : !!value;
8585
} else if (field.type == AdminForthDataTypes.JSON) {
8686
if (field._underlineType == 'text' || field._underlineType == 'varchar') {
8787
try {
@@ -112,7 +112,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
112112
return value;
113113
}
114114
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
115-
return value ? 1 : 0;
115+
return value === null ? null : (value ? 1 : 0);
116116
} else if (field.type == AdminForthDataTypes.JSON) {
117117
// check underline type is text or string
118118
if (field._underlineType == 'text' || field._underlineType == 'varchar') {

0 commit comments

Comments
 (0)