Skip to content

Commit

Permalink
Merge branch 'master' into UIPQB-175
Browse files Browse the repository at this point in the history
  • Loading branch information
UladzislauKutarkin authored Dec 24, 2024
2 parents fd827fd + 3c7f980 commit dc853a5
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

* [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.
* [UIPQB-175](https://folio-org.atlassian.net/browse/UIPQB-175) Displays the "Smth went wrong" page, when the user clicks on "Select operator" dropdown and selects any of them, if there are deleted custom fields.


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

* [UIPQB-128](https://folio-org.atlassian.net/browse/UIPQB-128) Invalid fields handling > Errors when query includes a deleted custom field.
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,10 @@ import {
Row,
getFirstFocusable,
} from '@folio/stripes/components';
import { useShowCallout } from '@folio/stripes-acq-components';

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 +24,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 @@ -85,6 +89,7 @@ export const RepeatableFields = ({ source, setSource, getParamsSource, columns }
},
};
}

if (isOperator) {
return {
[COLUMN_KEYS.VALUE]: {
Expand Down Expand Up @@ -114,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: 'warning',
message: (
<FormattedMessage
id="ui-plugin-query-builder.warning.deletedField"
values={{ value: intl.formatList(deletedFields) }}
/>
),
timeout: 0,
});
}
}, []);

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

RepeatableFields.propTypes = {
source: PropTypes.arrayOf(PropTypes.object),
Expand Down
19 changes: 19 additions & 0 deletions src/QueryBuilder/QueryBuilder/helpers/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,22 @@ 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 @@ -367,3 +367,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 dc853a5

Please sign in to comment.