diff --git a/src/searchModal/advancedSearch.js b/src/searchModal/advancedSearch.js index 293fd964..98fd0d62 100644 --- a/src/searchModal/advancedSearch.js +++ b/src/searchModal/advancedSearch.js @@ -73,6 +73,11 @@ export default function advancedSearchFactory(config) { text: 'text', list: 'list' }; + const criteriaLogic = { + and: 'LOGIC_AND', + or: 'LOGIC_OR', + not: 'LOGIC_NOT', + } let isAdvancedSearchStatusEnabled; let isCriteriaListUpdated = false; @@ -127,6 +132,7 @@ export default function advancedSearchFactory(config) { _.forEach(criteriaState, criterion => { criterion.rendered = false; criterion.value = null; + criterion.logic = null; }); }, /** @@ -147,8 +153,11 @@ export default function advancedSearchFactory(config) { } } else if (renderedCriterion.type === criteriaTypes.list) { if (renderedCriterion.value && renderedCriterion.value.length > 0) { - /* Temp replaced OR with AND. See ADF-7 for details */ - query += `${queryParam}:${renderedCriterion.value.join(' AND ')}`; + if(renderedCriterion.value.length === 1 && renderedCriterion.logic === criteriaLogic.not) { + //we have to pass NOT logic anyways, so add empty member to have NOT logic modifier in the query + renderedCriterion.value.push(''); + } + query += renderedCriterion.value.map(value=>`${queryParam}:${value}`).join(` ${renderedCriterion.logic} `); } } }); @@ -431,10 +440,16 @@ export default function advancedSearchFactory(config) { if (criterion.value) { $(`input[name=${criterion.id}-select]`, $criterionContainer).select2('data', initialCriterion); } + criterion.logic = criterion.logic || criteriaLogic.and; + $(`input[name="${criterion.id}-logic"][value="${criterion.logic}"]`, $criterionContainer).prop('checked', true); // set event to bind input value to critariaState $(`input[name=${criterion.id}-select]`, $criterionContainer).on('change', event => { criterion.value = event.val; }); + // set event to bind logic selector to critariaState + $(`input[name="${criterion.id}-logic"]`, $criterionContainer).on('change', event => { + criterion.logic = event.target.value; + }); } else { // set initial value if (criterion.value) { diff --git a/src/searchModal/scss/advancedSearch.scss b/src/searchModal/scss/advancedSearch.scss index f1cac783..b0628c2d 100644 --- a/src/searchModal/scss/advancedSearch.scss +++ b/src/searchModal/scss/advancedSearch.scss @@ -78,7 +78,7 @@ $invalidCriteriaBorder: #266d9c; margin-left: 0; } } - label { + div.criterion-container { width: 100%; padding: 0; margin: 0; @@ -111,6 +111,12 @@ $invalidCriteriaBorder: #266d9c; width: 100%; } } + .logic-radio-group { + display: flex; + justify-content: flex-start; + gap: 16px; + } + } .invalid-criteria-warning-container { background-color: $invalidCriteriaBackground; diff --git a/src/searchModal/tpl/list-select-criterion.tpl b/src/searchModal/tpl/list-select-criterion.tpl index 14922ee6..d2c315cd 100644 --- a/src/searchModal/tpl/list-select-criterion.tpl +++ b/src/searchModal/tpl/list-select-criterion.tpl @@ -1,12 +1,23 @@
-
diff --git a/test/searchModal/advancedSearch/test.js b/test/searchModal/advancedSearch/test.js index 8102650d..159e41b2 100644 --- a/test/searchModal/advancedSearch/test.js +++ b/test/searchModal/advancedSearch/test.js @@ -301,7 +301,7 @@ define([ statusUrl: 'undefined/tao/AdvancedSearch/status' }); const ready = assert.async(); - assert.expect(9); + assert.expect(11); instance.on('ready', function () { assert.ok(instance.isEnabled(), 'the advanced search is enabled'); @@ -326,19 +326,12 @@ define([ const $criterionTextInput = $criteriaContainer.find('.inBothTextParentUri-filter input'); const $criterionSelectInput = $criteriaContainer.find('.inBothSelectParentUri-filter input'); - // Checkboxes are temporary replaced with select2 - // const $criterionListSelected = $criteriaContainer - // .find('.-filter input[type=checkbox]:checked') - // .get() - // .map(checkbox => { - // return checkbox.value; - // }); - const $criterionListSelected = $criteriaContainer.find('.inBothListParentUri-filter input'); // check default value on each criterion type await nextTick(); assert.equal($criterionTextInput.val(), 'default value0', 'text criterion correctly initialized'); + await nextTick(); assert.deepEqual( $criterionSelectInput.select2('val'), ['value0'], @@ -354,11 +347,6 @@ define([ // update value on each criterion $criterionTextInput.val('foo0').trigger('change'); - // Checkboxes are temporary replaced with select2 - // $criteriaContainer - // .find('.inBothListParentUri-filter input[type=checkbox][value=value2]') - // .prop('checked', true) - // .trigger('change'); $criteriaContainer.find('.inBothListParentUri-filter .select2-choices').click(); await nextTick(200); $('.select2-results .select2-selected + * .select2-result-label').mouseup(); @@ -374,14 +362,32 @@ define([ ['value1', 'value2'], 'list criteria correctly updated' ); - + const query = instance.getAdvancedCriteriaQuery(); assert.equal( query, - // TODO: change 2nd AND to OR when functionality is developed on BE - 'inBothTextParentUri:foo0 AND inBothListParentUri:value1 AND value2 AND inBothSelectParentUri:value0', + 'inBothTextParentUri:foo0 AND inBothListParentUri:value1 LOGIC_AND inBothListParentUri:value2 AND inBothSelectParentUri:value0', 'advanced search query is correctly built' ); + + $criteriaContainer.find('input[name="inBothListParentUri-logic"][value="LOGIC_OR"]').prop('checked', true).change(); + await nextTick(200); + const queryOr = instance.getAdvancedCriteriaQuery(); + assert.equal( + queryOr, + 'inBothTextParentUri:foo0 AND inBothListParentUri:value1 LOGIC_OR inBothListParentUri:value2 AND inBothSelectParentUri:value0', + 'advanced search query with OR logic is correctly built' + ); + + $criteriaContainer.find('input[name="inBothListParentUri-logic"][value="LOGIC_NOT"]').prop('checked', true).change(); + await nextTick(200); + const queryNot = instance.getAdvancedCriteriaQuery(); + assert.equal( + queryNot, + 'inBothTextParentUri:foo0 AND inBothListParentUri:value1 LOGIC_NOT inBothListParentUri:value2 AND inBothSelectParentUri:value0', + 'advanced search query with NOT logic is correctly built' + ); + instance.destroy(); ready(); });