mirror of
https://github.com/lingble/twenty.git
synced 2025-11-01 05:07:56 +00:00
Fix CSV export missing last page (#7167)
This commit is contained in:
@@ -142,10 +142,6 @@ export const useTableData = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const MAXIMUM_REQUESTS = isDefined(totalCount)
|
|
||||||
? Math.min(maximumRequests, totalCount / pageSize)
|
|
||||||
: maximumRequests;
|
|
||||||
|
|
||||||
const fetchNextPage = async () => {
|
const fetchNextPage = async () => {
|
||||||
setInflight(true);
|
setInflight(true);
|
||||||
setPreviousRecordCount(records.length);
|
setPreviousRecordCount(records.length);
|
||||||
@@ -167,8 +163,8 @@ export const useTableData = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
pageCount >= MAXIMUM_REQUESTS ||
|
pageCount >= maximumRequests ||
|
||||||
(isDefined(totalCount) && records.length === totalCount)
|
(isDefined(totalCount) && records.length >= totalCount)
|
||||||
) {
|
) {
|
||||||
setPageCount(0);
|
setPageCount(0);
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { FindOperator, Not } from 'typeorm';
|
|
||||||
|
|
||||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
|
||||||
|
|
||||||
import { GraphqlQueryFilterFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser';
|
|
||||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
|
||||||
|
|
||||||
describe('GraphqlQueryFilterFieldParser', () => {
|
|
||||||
let parser: GraphqlQueryFilterFieldParser;
|
|
||||||
let mockFieldMetadataMap: Record<string, FieldMetadataInterface>;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockFieldMetadataMap = {
|
|
||||||
simpleField: {
|
|
||||||
id: '1',
|
|
||||||
name: 'simpleField',
|
|
||||||
type: FieldMetadataType.TEXT,
|
|
||||||
label: 'Simple Field',
|
|
||||||
objectMetadataId: 'obj1',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
parser = new GraphqlQueryFilterFieldParser(mockFieldMetadataMap);
|
|
||||||
});
|
|
||||||
it('should parse simple field correctly', () => {
|
|
||||||
const result = parser.parse('simpleField', 'value', false);
|
|
||||||
|
|
||||||
expect(result).toEqual({ simpleField: 'value' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should negate simple field correctly', () => {
|
|
||||||
const result = parser.parse('simpleField', 'value', true);
|
|
||||||
|
|
||||||
expect(result).toEqual({ simpleField: Not('value') });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse object value using operator parser', () => {
|
|
||||||
const result = parser.parse('simpleField', { like: '%value%' }, false);
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
|
||||||
simpleField: new FindOperator('like', '%%value%%'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
import {
|
|
||||||
FindOperator,
|
|
||||||
ILike,
|
|
||||||
In,
|
|
||||||
IsNull,
|
|
||||||
LessThan,
|
|
||||||
LessThanOrEqual,
|
|
||||||
Like,
|
|
||||||
MoreThan,
|
|
||||||
MoreThanOrEqual,
|
|
||||||
Not,
|
|
||||||
} from 'typeorm';
|
|
||||||
|
|
||||||
import { GraphqlQueryRunnerException } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
|
|
||||||
import { GraphqlQueryFilterOperatorParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-operator.parser';
|
|
||||||
|
|
||||||
describe('GraphqlQueryFilterOperatorParser', () => {
|
|
||||||
let parser: GraphqlQueryFilterOperatorParser;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
parser = new GraphqlQueryFilterOperatorParser();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parseOperator', () => {
|
|
||||||
it('should parse eq operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ eq: 'value' }, false);
|
|
||||||
|
|
||||||
expect(result).toBe('value');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse neq operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ neq: 'value' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(Not('value'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse gt operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ gt: 5 }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(MoreThan(5));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse gte operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ gte: 5 }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(MoreThanOrEqual(5));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse lt operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ lt: 5 }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(LessThan(5));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse lte operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ lte: 5 }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(LessThanOrEqual(5));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse in operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ in: [1, 2, 3] }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(In([1, 2, 3]));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse is operator with NULL correctly', () => {
|
|
||||||
const result = parser.parseOperator({ is: 'NULL' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(IsNull());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse is operator with non-NULL value correctly', () => {
|
|
||||||
const result = parser.parseOperator({ is: 'NOT_NULL' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(Not(IsNull()));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse like operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ like: 'test' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(Like('%test%'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse ilike operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ ilike: 'test' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(ILike('%test%'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse startsWith operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ startsWith: 'test' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(ILike('test%'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse endsWith operator correctly', () => {
|
|
||||||
const result = parser.parseOperator({ endsWith: 'test' }, false);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(ILike('%test'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should negate the operator when isNegated is true', () => {
|
|
||||||
const result = parser.parseOperator({ eq: 'value' }, true);
|
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(FindOperator);
|
|
||||||
expect(result).toEqual(Not('value'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an exception for unsupported operator', () => {
|
|
||||||
expect(() =>
|
|
||||||
parser.parseOperator({ unsupported: 'value' }, false),
|
|
||||||
).toThrow(GraphqlQueryRunnerException);
|
|
||||||
expect(() =>
|
|
||||||
parser.parseOperator({ unsupported: 'value' }, false),
|
|
||||||
).toThrow('Operator "unsupported" is not supported');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isArray } from 'class-validator';
|
||||||
import { ObjectLiteral, WhereExpressionBuilder } from 'typeorm';
|
import { ObjectLiteral, WhereExpressionBuilder } from 'typeorm';
|
||||||
|
|
||||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||||
@@ -48,6 +49,10 @@ export class GraphqlQueryFilterFieldParser {
|
|||||||
}
|
}
|
||||||
const [[operator, value]] = Object.entries(filterValue);
|
const [[operator, value]] = Object.entries(filterValue);
|
||||||
|
|
||||||
|
if (operator === 'in' && (!isArray(value) || value.length === 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { sql, params } = this.computeWhereConditionParts(
|
const { sql, params } = this.computeWhereConditionParts(
|
||||||
fieldMetadata,
|
fieldMetadata,
|
||||||
operator,
|
operator,
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
|
||||||
|
|
||||||
import { GraphqlQueryOrderFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser';
|
|
||||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
|
||||||
import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util';
|
|
||||||
|
|
||||||
describe('GraphqlQueryOrderFieldParser', () => {
|
|
||||||
let parser: GraphqlQueryOrderFieldParser;
|
|
||||||
const fieldMetadataMap: FieldMetadataMap = {};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fieldMetadataMap['name'] = {
|
|
||||||
id: 'name-id',
|
|
||||||
name: 'name',
|
|
||||||
type: FieldMetadataType.TEXT,
|
|
||||||
label: 'Name',
|
|
||||||
objectMetadataId: 'object-id',
|
|
||||||
};
|
|
||||||
fieldMetadataMap['age'] = {
|
|
||||||
id: 'age-id',
|
|
||||||
name: 'age',
|
|
||||||
type: FieldMetadataType.NUMBER,
|
|
||||||
label: 'Age',
|
|
||||||
objectMetadataId: 'object-id',
|
|
||||||
};
|
|
||||||
fieldMetadataMap['address'] = {
|
|
||||||
id: 'address-id',
|
|
||||||
name: 'address',
|
|
||||||
type: FieldMetadataType.ADDRESS,
|
|
||||||
label: 'Address',
|
|
||||||
objectMetadataId: 'object-id',
|
|
||||||
};
|
|
||||||
|
|
||||||
parser = new GraphqlQueryOrderFieldParser(fieldMetadataMap);
|
|
||||||
});
|
|
||||||
describe('parse', () => {
|
|
||||||
it('should parse simple order by fields', () => {
|
|
||||||
const orderBy = [
|
|
||||||
{ name: OrderByDirection.AscNullsFirst },
|
|
||||||
{ age: OrderByDirection.DescNullsLast },
|
|
||||||
];
|
|
||||||
const result = parser.parse(orderBy);
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
|
||||||
name: { direction: 'ASC', nulls: 'FIRST' },
|
|
||||||
age: { direction: 'DESC', nulls: 'LAST' },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user