Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/metacore/src/metafilters/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type CustomFunction = Nullable<string>;
* LT - Less than
* LE - Less than or equal to
*/
export type Operator = Nullable<'EQ' | 'LIKE' | 'GT' | 'LT' | 'GE' | 'LE' | 'NE'>;
export type Operator = Nullable<'EQ' | 'LIKE' | 'GT' | 'LT' | 'GE' | 'LE' | 'NE' | 'EMPTY' | 'NONEMPTY'>;

export interface IBooleanInput {
type: 'boolean';
Expand Down
8 changes: 7 additions & 1 deletion packages/metacore/src/metaforms/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,17 @@ interface CommonProps {
visible?: { targetName: string, value: any };
}

export type MultiSelectParent = {children: MultiSelectOptions, label: string};
export type MultiSelectLeaf = { value: string | number; label: string };

export type MultiSelectOption = MultiSelectLeaf | MultiSelectParent;
export type MultiSelectOptions = Array<MultiSelectLeaf>

export interface MultiSelectMetaProps extends CommonProps {
type: 'multiselect';
disabled?: boolean;
placeholder?: string;
options?: Array<{ value: string | number; label: string }>;
options?: MultiSelectOptions;
showSelectedCounter?: boolean;
showFilterInput?: boolean;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/metafilters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"url": "https://github.com/flsy/meta/issues"
},
"scripts": {
"build": "rm -rf ./lib && tsc -b",
"build": "rimraf ./lib && tsc -b",
"test": "jest",
"prepare": "yarn build",
"prepublishOnly": "yarn test",
Expand All @@ -40,6 +40,7 @@
"@types/jest": "^29.0.0",
"@types/sqlite3": "^3.1.6",
"jest": "^27.0.6",
"rimraf": "^5.0.1",
"sqlite3": "^5.0.0",
"ts-jest": "^27.0.4"
},
Expand Down
8 changes: 5 additions & 3 deletions packages/metafilters/src/__tests__/common.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import metafilters from '../index';
import { all, close } from '../sqliteUtils';
import { exampleColumn, seed } from '../testData';
import { all, close } from '../testHelpers/sqliteUtils';
import { seed, exampleColumn } from '../testHelpers/testData';

describe('common code', () => {
it('map records to table column names', async () => {
Expand All @@ -20,7 +20,9 @@ describe('common code', () => {
{ id: 2, firstName: 'Alpha', lastName: 'Tree', age: 2, isValid: 1 },
{ id: 3, firstName: 'Beta', lastName: 'Woods', age: 30, isValid: 1 },
{ id: 5, firstName: 'Carol', lastName: 'RainForest', age: 18, isValid: 1 },
{ id: 6, firstName: '', lastName: 'FirstNameNull', age: 18, isValid: 1 },
{ id: 6, firstName: '', lastName: 'FirstNameEmptyStr', age: 18, isValid: 1 },
{ id: 7, firstName: null, lastName: 'FirstNameNull', age: 18, isValid: 1 },

]);
});
it('map use all columns if not provided', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/metafilters/src/__tests__/filters/combined.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exampleColumn, seed } from '../../testData';
import metafilters from '../../index';
import { all, close, get } from '../../sqliteUtils';
import { all, close, get } from '../../testHelpers/sqliteUtils';
import { seed, exampleColumn } from '../../testHelpers/testData';


describe('filters combined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exampleColumn, seed } from '../../testData';
import metafilters from '../../index';
import { all, get } from '../../sqliteUtils';
import { all, get } from '../../testHelpers/sqliteUtils';
import { seed, exampleColumn } from '../../testHelpers/testData';

describe('number filter', () => {
it('filter number by like operator', async () => {
Expand Down
63 changes: 52 additions & 11 deletions packages/metafilters/src/__tests__/filters/stringsFilter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exampleColumn, seed } from '../../testData';
import metafilters from '../../index';
import { all, close, get } from '../../sqliteUtils';
import { all, close, get } from '../../testHelpers/sqliteUtils';
import { seed, exampleColumn, seededData } from '../../testHelpers/testData';

describe('strings filter', () => {
it('should return all when empty filter', async () => {
Expand All @@ -23,8 +23,8 @@ describe('strings filter', () => {
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash";',
});

expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(seededData.length);
});

it('should filter', async () => {
Expand Down Expand Up @@ -196,8 +196,8 @@ describe('strings filter', () => {
const nodes = await all(db, filters.nodes);
await db.close();

expect(count).toEqual({ count: 4 });
expect(nodes.map(n => (n as any).lastName)).toMatchObject(['Tree', 'Woods', 'RainForest', 'FirstNameNull']);
expect(count).toEqual({ count: 5 });
expect(nodes.map(n => (n as any).lastName)).toMatchObject(['Tree', 'Woods', 'RainForest', 'FirstNameEmptyStr', 'FirstNameNull']);
});

it('filter by string default LIKE', async () => {
Expand All @@ -220,7 +220,7 @@ describe('strings filter', () => {
expect(nodes).toMatchObject([{ firstName: 'Alpha' }, { firstName: 'Beta' }, { firstName: 'Carol' }]);
});

it('filter by string with null value (which means: give me eerything)', async () => {
it('filter by string with null value (which means: give me everything)', async () => {
const db = await seed();
const response = await metafilters('person-dash', exampleColumn, {
filters: { firstName: { type: 'string', filters: [{ value: null }] } },
Expand All @@ -235,8 +235,8 @@ describe('strings filter', () => {
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash" WHERE coalesce("firstName", \'\') like \'%%\';',
});

expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(seededData.length);
});

it('handles undefined filters', async () => {
Expand All @@ -254,8 +254,8 @@ describe('strings filter', () => {
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash";',
});

expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(seededData.length);
});

it('filter by string with user defined function', async () => {
Expand All @@ -277,4 +277,45 @@ describe('strings filter', () => {
expect(nodes.length).toEqual(1);
expect(nodes).toMatchObject([{ firstName: 'Beta' }]);
});


it('filter by EMPTY operator', async () => {
const db = await seed();
const response = await metafilters('person-dash', exampleColumn, {
filters: { firstName: { type: 'string', filters: [{operator: 'EMPTY', value: null}] } },
});

const count = await get(db, response.count);
const nodes = await all(db, response.nodes);
await close(db);

expect(response).toMatchObject({
count: 'SELECT COUNT(*) as count FROM "person-dash" WHERE "firstName" is null;',
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash" WHERE "firstName" is null;'}
);

expect(count).toEqual({ count: 1 });
expect(nodes.length).toEqual(1);
expect(nodes).toMatchObject([{ firstName: null }]);
});

it('filter by NONEMPTY operator', async () => {
const db = await seed();
const response = await metafilters('person-dash', exampleColumn, {
filters: { firstName: { type: 'string', filters: [{operator: 'NONEMPTY', value: null}] } },
});

const count = await get(db, response.count);
const nodes = await all(db, response.nodes);
await close(db);

expect(response).toMatchObject({
count: 'SELECT COUNT(*) as count FROM "person-dash" WHERE "firstName" is not null;',
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash" WHERE "firstName" is not null;'}
);

expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
});

});
14 changes: 7 additions & 7 deletions packages/metafilters/src/__tests__/limit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import metafilters from '../index';
import { all, close, get } from '../sqliteUtils';
import { exampleColumn, seed } from '../testData';
import { all, close, get } from '../testHelpers/sqliteUtils';
import { seed, exampleColumn, seededData } from '../testHelpers/testData';

describe('limit', () => {
it('return all records when no limit specified', async () => {
Expand All @@ -11,9 +11,9 @@ describe('limit', () => {
const nodes = await all(db, response.nodes);
await close(db);

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
expect(nodes[0]).toEqual({ id: 1, firstName: 'Joe', lastName: 'Forest', age: 52, isValid: 0 });
expect(nodes.length).toEqual(5);
expect(nodes.length).toEqual(seededData.length);
});

it('return all records when limit is larger than record count', async () => {
Expand All @@ -22,8 +22,8 @@ describe('limit', () => {
const count = await get(db, response.count);
const nodes = await all(db, response.nodes);
await close(db);
expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(seededData.length);
});

it('limits returned records to 2', async () => {
Expand All @@ -34,7 +34,7 @@ describe('limit', () => {
const nodes = await all(db, response.nodes);
await close(db);

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(2);
});
});
33 changes: 18 additions & 15 deletions packages/metafilters/src/__tests__/pagination.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exampleColumn, seed } from '../testData';
import metafilters from '../index';
import { all, close, get } from '../sqliteUtils';
import { all, close, get } from '../testHelpers/sqliteUtils';
import { seed, exampleColumn, seededData } from '../testHelpers/testData';

describe('pagination', () => {
it('paginate sorted by keyColumn ASC', async () => {
Expand All @@ -10,7 +10,7 @@ describe('pagination', () => {
const count = await get(db, response1.count);
const nodes = await all(db, response1.nodes);

expect(count).toEqual({ count: 5});
expect(count).toEqual({ count: seededData.length});
expect(nodes.length).toEqual(3);

expect(nodes).toEqual([
Expand All @@ -22,8 +22,11 @@ describe('pagination', () => {
const response2 = await metafilters('person-dash', exampleColumn, { page: 1, limit: 3 });
const nodes2 = await all(db, response2.nodes);
await close(db);
expect(nodes2.length).toEqual(2);
expect(nodes2).toEqual([{ id: 5, firstName: 'Carol', lastName: 'RainForest', isValid: 1, age: 18 }, { id: 6, firstName: '', lastName: 'FirstNameNull', isValid: 1, age: 18 }]);
expect(nodes2.length).toEqual(3);
expect(nodes2).toEqual([
{ id: 5, firstName: 'Carol', lastName: 'RainForest', isValid: 1, age: 18 },
{ id: 6, firstName: '', lastName: 'FirstNameEmptyStr', isValid: 1, age: 18 },
{ id: 7, firstName: null, lastName: 'FirstNameNull', isValid: 1, age: 18 }]);
});

it('paginate sorted by keyColumn DESC', async () => {
Expand All @@ -33,21 +36,21 @@ describe('pagination', () => {
const count = await get(db, response1.count);
const nodes = await all(db, response1.nodes);

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(3);

expect(nodes).toEqual([
{ id: 6, firstName: '', lastName: 'FirstNameNull', isValid: 1, age: 18 },
{ id: 7, firstName: null, lastName: 'FirstNameNull', isValid: 1, age: 18 },
{ id: 6, firstName: '', lastName: 'FirstNameEmptyStr', isValid: 1, age: 18 },
{ id: 5, firstName: 'Carol', lastName: 'RainForest', isValid: 1, age: 18 },
{ id: 3, firstName: 'Beta', lastName: 'Woods', isValid: 1, age: 30 },
]);

const response2 = await metafilters( 'person-dash', exampleColumn, { page: 1, limit: 3, sort: { id: 'DESC' } });
const nodes2 = await all(db, response2.nodes);
await close(db);

expect(nodes2.length).toEqual(2);
expect(nodes2).toEqual([{ id: 2, age: 2, firstName: 'Alpha', isValid: 1, lastName: 'Tree' }, { id: 1, age: 52, firstName: 'Joe', isValid: 0, lastName: 'Forest' }]);
expect(nodes2.length).toEqual(3);
expect(nodes2).toEqual([{ id: 3, age: 30, firstName: 'Beta', isValid: 1, lastName: 'Woods' }, { id: 2, age: 2, firstName: 'Alpha', isValid: 1, lastName: 'Tree' }, { id: 1, age: 52, firstName: 'Joe', isValid: 0, lastName: 'Forest' }]);
});

it('return empty nodes with page number outside stored data', async () => {
Expand All @@ -57,7 +60,7 @@ describe('pagination', () => {
const count = await get(db, response1.count);
const nodes = await all(db, response1.nodes);

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(0);
expect(nodes).toEqual([]);
});
Expand All @@ -69,14 +72,14 @@ describe('pagination', () => {
const count = await get(db, response1.count);
const nodes = await all(db, response1.nodes);

expect(count).toEqual({ count: 5 });
expect(nodes.length).toEqual(5);
expect(count).toEqual({ count: seededData.length });
expect(nodes.length).toEqual(seededData.length);

const response2 = await metafilters( 'person-dash', exampleColumn, { page: 10, sort: { firstName: 'DESC' } });
const count2 = await get(db, response2.count);
const nodes2 = await all(db, response2.nodes);

expect(count2).toEqual({ count: 5 });
expect(nodes2.length).toEqual(5);
expect(count2).toEqual({ count: seededData.length });
expect(nodes2.length).toEqual(seededData.length);
});
});
8 changes: 4 additions & 4 deletions packages/metafilters/src/__tests__/sort.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import metafilters from '../index';
import { close, get } from '../sqliteUtils';
import { exampleColumn, seed } from '../testData';
import { close, get } from '../testHelpers/sqliteUtils';
import { seed, exampleColumn, seededData } from '../testHelpers/testData';

describe('sort', () => {
it('return records sorted by string DESC', async () => {
Expand All @@ -15,7 +15,7 @@ describe('sort', () => {
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash" ORDER BY "firstName" DESC;',
});

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
});
it('handles undefined sort', async () => {
const db = await seed();
Expand All @@ -29,6 +29,6 @@ describe('sort', () => {
nodes: 'SELECT "id", "firstName", "lastName", "age", "isValid" FROM "person-dash";',
});

expect(count).toEqual({ count: 5 });
expect(count).toEqual({ count: seededData.length });
});
});
12 changes: 12 additions & 0 deletions packages/metafilters/src/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const numberFilter = (name: string, filter: INumberInput): string[] =>
}
return [columnName, '!=', value].join(' ');
}
case 'EMPTY': {
return `${columnName} is null`;
}
case 'NONEMPTY': {
return `${columnName} is not null`;
}
case 'EQ':
default:
if (value === null) {
Expand Down Expand Up @@ -48,6 +54,12 @@ const stringOperator = (columnName: string, value: Nullable<string>, operator?:
}
return `${columnName} != '${value}'`;
}
case 'EMPTY': {
return `${columnName} is null`;
}
case 'NONEMPTY': {
return `${columnName} is not null`;
}
case 'LIKE':
default: {
// TODO Zde by měly být rozlišeny dva stavy.
Expand Down
Loading