Skip to content

Commit

Permalink
UIPQB-162: Errors when query includes a modified custom field
Browse files Browse the repository at this point in the history
  • Loading branch information
UladzislauKutarkin committed Dec 18, 2024
1 parent 1508bb8 commit e3f6cb2
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [UIPQB-168](https://folio-org.atlassian.net/browse/UIPQB-168) Allow editing queries containing no fields.
* [UIPQB-141](https://folio-org.atlassian.net/browse/UIPQB-141) Modal dialog focus inconsistencies across screenreaders.
* [UIPQB-162](https://folio-org.atlassian.net/browse/UIPQB-162) Errors when query includes a modified custom field.

## [1.2.6](https://github.com/folio-org/ui-plugin-query-builder/tree/v1.2.6) (2024-12-11)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo, useEffect, useRef } from 'react';
import {
IconButton,
RepeatableField,
Expand All @@ -8,9 +8,11 @@ import {
Row,
getFirstFocusable
} from '@folio/stripes/components';
import { useShowCallout } from "@folio/stripes-acq-components";
import {MESSAGE_TYPES} from "@folio/lists/src/hooks/useMessages/useMessages";

import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import {FormattedMessage, useIntl} from 'react-intl';
import { QueryBuilderTitle } from '../../QueryBuilderTitle';
import css from '../QueryBuilderModal.css';
import { COLUMN_KEYS } from '../../../../constants/columnKeys';
Expand All @@ -23,9 +25,12 @@ import {
} from '../../helpers/selectOptions';
import { BOOLEAN_OPERATORS } from '../../../../constants/operators';
import { DataTypeInput } from '../DataTypeInput';
import {findMissingValues} from "../../helpers/query";

export const RepeatableFields = ({ source, setSource, getParamsSource, columns }) => {
export const RepeatableFields = memo(({ source, setSource, getParamsSource, columns }) => {
const intl = useIntl();
const callout = useShowCallout();
const calloutCalledRef = useRef(false);

const fieldOptions = getFieldOptions(columns);

Expand Down Expand Up @@ -84,6 +89,7 @@ export const RepeatableFields = ({ source, setSource, getParamsSource, columns }
},
};
}

if (isOperator) {
return {
[COLUMN_KEYS.VALUE]: {
Expand Down Expand Up @@ -113,6 +119,27 @@ export const RepeatableFields = ({ source, setSource, getParamsSource, columns }
}));
};

useEffect(() => {
if (calloutCalledRef.current) return;

const deletedFields = findMissingValues(fieldOptions, source)

if(deletedFields.length >= 1) {
calloutCalledRef.current = true;

callout({
type: MESSAGE_TYPES.WARNING,
message: (
<FormattedMessage
id="ui-plugin-query-builder.warning.deletedField"
values={{value: deletedFields.join(',')}}
/>
),
timeout: 0,
})
}
}, []);

return (
<>
<QueryBuilderTitle results={source} />
Expand Down Expand Up @@ -201,7 +228,7 @@ export const RepeatableFields = ({ source, setSource, getParamsSource, columns }
/>
</>
);
};
});

RepeatableFields.propTypes = {
source: PropTypes.arrayOf(PropTypes.object),
Expand Down
17 changes: 17 additions & 0 deletions src/QueryBuilder/QueryBuilder/helpers/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,20 @@ export const mongoQueryToSource = async ({

return [singleItem];
};

export const findMissingValues = (
mainArray,
secondaryArray
) => {
const mainValues = new Set(mainArray?.map((item) => item.value));

const missingValues = [];
for (const secondaryItem of secondaryArray) {
const currentValue = secondaryItem.field.current;
if (currentValue && !mainValues.has(currentValue)) {
missingValues.push(currentValue);
}
}

return missingValues;
}
90 changes: 89 additions & 1 deletion src/QueryBuilder/QueryBuilder/helpers/query.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getTransformedValue, isQueryValid, mongoQueryToSource, sourceToMongoQuery } from './query';
import {findMissingValues, getTransformedValue, isQueryValid, mongoQueryToSource, sourceToMongoQuery} from './query';
import { booleanOptions } from './selectOptions';
import { OPERATORS } from '../../../constants/operators';
import { fieldOptions } from '../../../../test/jest/data/entityType';
Expand Down Expand Up @@ -372,3 +372,91 @@ describe('getTransformedValue', () => {
expect(actual).toEqual(expected);
});
});

describe('findMissingValues', () => {
it('should return missing values from secondaryArray that are not in mainArray', () => {
const mainArray = [
{ value: 'value1' },
{ value: 'value2' },
{ value: 'value3' },
];

const secondaryArray = [
{ field: { current: 'value2' } },
{ field: { current: 'value4' } },
{ field: { current: 'value5' } },
];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual(['value4', 'value5']);
});

it('should return an empty array when all values are present in mainArray', () => {
const mainArray = [
{ value: 'value1' },
{ value: 'value2' },
];

const secondaryArray = [
{ field: { current: 'value1' } },
{ field: { current: 'value2' } },
];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual([]);
});

it('should handle cases where mainArray is empty', () => {
const mainArray = [];

const secondaryArray = [
{ field: { current: 'value1' } },
{ field: { current: 'value2' } },
];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual(['value1', 'value2']);
});

it('should handle cases where secondaryArray is empty', () => {
const mainArray = [
{ value: 'value1' },
{ value: 'value2' },
];

const secondaryArray = [];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual([]);
});

it('should handle cases where both arrays are empty', () => {
const mainArray = [];
const secondaryArray = [];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual([]);
});

it('should ignore null or undefined values in secondaryArray', () => {
const mainArray = [
{ value: 'value1' },
{ value: 'value2' },
];

const secondaryArray = [
{ field: { current: 'value3' } },
{ field: { current: null } },
{ field: { current: undefined } },
];

const result = findMissingValues(mainArray, secondaryArray);

expect(result).toEqual(['value3']);
});
});
2 changes: 2 additions & 0 deletions translations/ui-plugin-query-builder/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@
"error.sww": "Something went wrong",
"error.occurredMessage": "An error occurred.",

"warning.deletedField": "{value} in your query is unavailable. Please revise your query. ",

"ariaLabel.columnFilter": "Column filter input"
}

0 comments on commit e3f6cb2

Please sign in to comment.