@oat-sa/tao-core-ui 3.23.0 → 3.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/figure/FigureStateActive.js +64 -32
- package/dist/image/ImgStateActive/initHelper.js +64 -32
- package/dist/image/ImgStateActive.js +64 -32
- package/dist/previewer.js +1 -1
- package/dist/resourcemgr/assetSearch.js +793 -0
- package/dist/resourcemgr/assetSearchContract.js +477 -0
- package/dist/resourcemgr/css/resourcemgr.css +1137 -97
- package/dist/resourcemgr/css/resourcemgr.css.map +1 -1
- package/dist/resourcemgr/fileBrowser.js +456 -79
- package/dist/resourcemgr/filePreview.js +40 -4
- package/dist/resourcemgr/fileSelector.js +362 -92
- package/dist/resourcemgr.js +309 -57
- package/dist/searchModal/advancedSearch.js +233 -31
- package/package.json +15 -6
- package/src/image/ImgStateActive/initHelper.js +69 -31
- package/src/previewer.js +1 -1
- package/src/resourcemgr/assetSearch.js +847 -0
- package/src/resourcemgr/assetSearchContract.js +489 -0
- package/src/resourcemgr/css/resourcemgr.css +1137 -97
- package/src/resourcemgr/css/resourcemgr.css.map +1 -1
- package/src/resourcemgr/fileBrowser.js +470 -91
- package/src/resourcemgr/filePreview.js +46 -4
- package/src/resourcemgr/fileSelector.js +338 -46
- package/src/resourcemgr/scss/resourcemgr.scss +1351 -88
- package/src/resourcemgr/tpl/advanced-search.tpl +10 -0
- package/src/resourcemgr/tpl/fileSelect.tpl +25 -28
- package/src/resourcemgr/tpl/folder.tpl +4 -1
- package/src/resourcemgr/tpl/layout.tpl +113 -54
- package/src/resourcemgr/tpl/rootFolder.tpl +3 -1
- package/src/resourcemgr.js +289 -47
- package/src/searchModal/advancedSearch.js +242 -31
|
@@ -33,6 +33,7 @@ import 'ui/modal';
|
|
|
33
33
|
import 'ui/datatable';
|
|
34
34
|
import 'select2';
|
|
35
35
|
import request from 'core/dataProvider/request';
|
|
36
|
+
import __ from 'i18n';
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Sort an array by a particular property.
|
|
@@ -67,6 +68,7 @@ export default function advancedSearchFactory(config) {
|
|
|
67
68
|
let $addCriteriaInput = null;
|
|
68
69
|
let $criteriaSelect = null;
|
|
69
70
|
let $advancedCriteriaContainer = null;
|
|
71
|
+
let $appliedFiltersSummary = null;
|
|
70
72
|
let criteriaState = null;
|
|
71
73
|
let criteriaMapping = {};
|
|
72
74
|
const criteriaTypes = {
|
|
@@ -80,7 +82,6 @@ export default function advancedSearchFactory(config) {
|
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
let isAdvancedSearchStatusEnabled;
|
|
83
|
-
let isCriteriaListUpdated = false;
|
|
84
85
|
|
|
85
86
|
// Creates new component
|
|
86
87
|
const instance = component({
|
|
@@ -102,18 +103,22 @@ export default function advancedSearchFactory(config) {
|
|
|
102
103
|
return Promise.resolve();
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
const $criteriaIcon = $('
|
|
106
|
-
$criteriaIcon.
|
|
106
|
+
const $criteriaIcon = $addCriteria ? $('a span', $addCriteria).eq(0) : $();
|
|
107
|
+
const idleIconClass = $criteriaIcon.hasClass('icon-plus') ? 'icon-plus' : 'icon-add';
|
|
108
|
+
$criteriaIcon.removeClass('icon-add icon-plus').addClass('icon-loop');
|
|
107
109
|
return request(route)
|
|
108
110
|
.then(response => {
|
|
109
111
|
criteriaMapping = response.criteriaMapping || {};
|
|
110
112
|
const classTree = response.classDefinition ? response.classDefinition : response;
|
|
111
113
|
const criteria = formatCriteria(classTree);
|
|
112
114
|
updateCriteria(criteria);
|
|
113
|
-
|
|
114
|
-
$criteriaIcon.toggleClass('icon-add').toggleClass('icon-loop');
|
|
115
|
+
$criteriaIcon.removeClass('icon-loop').addClass(idleIconClass);
|
|
115
116
|
})
|
|
116
|
-
.catch(e =>
|
|
117
|
+
.catch(e => {
|
|
118
|
+
$criteriaIcon.removeClass('icon-loop').addClass(idleIconClass);
|
|
119
|
+
instance.trigger('error', e);
|
|
120
|
+
throw e;
|
|
121
|
+
});
|
|
117
122
|
},
|
|
118
123
|
/**
|
|
119
124
|
* Access to component state
|
|
@@ -129,10 +134,19 @@ export default function advancedSearchFactory(config) {
|
|
|
129
134
|
clear() {
|
|
130
135
|
$advancedCriteriaContainer.removeClass(['scrollable', 'scroll-separator-top', 'scroll-separator-bottom']);
|
|
131
136
|
$advancedCriteriaContainer.empty();
|
|
137
|
+
updateAppliedFiltersSummary(0);
|
|
138
|
+
// Rebuild selectable options: adding a criterion removes its <option>,
|
|
139
|
+
// so Clear must restore them (searchModal recovers via class re-select + updateCriteria).
|
|
140
|
+
if ($criteriaSelect && $criteriaSelect.length) {
|
|
141
|
+
$criteriaSelect.find('option:not(:first-child)').remove();
|
|
142
|
+
}
|
|
132
143
|
_.forEach(criteriaState, criterion => {
|
|
133
144
|
criterion.rendered = false;
|
|
134
145
|
criterion.value = null;
|
|
135
146
|
criterion.logic = null;
|
|
147
|
+
if ($criteriaSelect && $criteriaSelect.length) {
|
|
148
|
+
$criteriaSelect.append(createCriteriaOption(criterion));
|
|
149
|
+
}
|
|
136
150
|
});
|
|
137
151
|
},
|
|
138
152
|
/**
|
|
@@ -170,7 +184,7 @@ export default function advancedSearchFactory(config) {
|
|
|
170
184
|
return query;
|
|
171
185
|
}
|
|
172
186
|
})
|
|
173
|
-
.setTemplate(advancedSearchTpl)
|
|
187
|
+
.setTemplate(config.layoutTemplate || advancedSearchTpl)
|
|
174
188
|
.on('render', () => {
|
|
175
189
|
initUiSelectors();
|
|
176
190
|
initAddCriteriaSelector()
|
|
@@ -191,6 +205,14 @@ export default function advancedSearchFactory(config) {
|
|
|
191
205
|
$addCriteriaInput = $('.add-criteria-container a', $container);
|
|
192
206
|
$criteriaSelect = $('.add-criteria-container select', $container);
|
|
193
207
|
$advancedCriteriaContainer = $('.advanced-criteria-container', $container);
|
|
208
|
+
$appliedFiltersSummary = $('.applied-filters-summary', $container);
|
|
209
|
+
|
|
210
|
+
if (config.collapsibleCriteria && $appliedFiltersSummary.length) {
|
|
211
|
+
$appliedFiltersSummary.off('click.advancedSearch').on('click.advancedSearch', function (e) {
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
togglePreviousFilters();
|
|
214
|
+
});
|
|
215
|
+
}
|
|
194
216
|
|
|
195
217
|
$advancedCriteriaContainer.on('scroll', _.throttle(animateScroll, 100));
|
|
196
218
|
}
|
|
@@ -252,15 +274,24 @@ export default function advancedSearchFactory(config) {
|
|
|
252
274
|
});
|
|
253
275
|
|
|
254
276
|
// open dropdown when user clicks on add criteria input
|
|
255
|
-
$addCriteriaInput.on('click', ()
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
277
|
+
$addCriteriaInput.on('click', function (e) {
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
e.stopPropagation();
|
|
280
|
+
const hasOptions =
|
|
281
|
+
$criteriaSelect.find('option').filter(function () {
|
|
282
|
+
return Boolean(this.value);
|
|
283
|
+
}).length > 0;
|
|
284
|
+
// Never open an empty select2 (mask-only / no results). Wait for ClassMetadata options.
|
|
285
|
+
if (!hasOptions) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
$criteriaSelect.select2('open');
|
|
289
|
+
// if dropdown is opened above addCriteria input, top property is slightly decreased to avoid overlapping with addCriteria icon
|
|
290
|
+
const $dropdown = $('.criteria-dropdown-select2');
|
|
291
|
+
if ($dropdown.hasClass('select2-drop-above')) {
|
|
292
|
+
const top = parseFloat($dropdown.css('top'));
|
|
293
|
+
if (!Number.isNaN(top)) {
|
|
294
|
+
$dropdown.css('top', `${top - 10}px`);
|
|
264
295
|
}
|
|
265
296
|
}
|
|
266
297
|
});
|
|
@@ -325,8 +356,12 @@ export default function advancedSearchFactory(config) {
|
|
|
325
356
|
const criterion = criteriaState[criterionToAdd];
|
|
326
357
|
const $criterionContainer = renderCriterion(criterion);
|
|
327
358
|
|
|
359
|
+
if (config.collapsibleCriteria) {
|
|
360
|
+
wrapCriterionAsSpoiler($criterionContainer, criterion);
|
|
361
|
+
}
|
|
362
|
+
|
|
328
363
|
// set logic to remove criterion
|
|
329
|
-
$('.icon-result-nok
|
|
364
|
+
$criterionContainer.find('.icon-result-nok, .filter-spoiler-delete').on('click', { criterion }, removeCriterion);
|
|
330
365
|
|
|
331
366
|
// set initial value and manage value changes
|
|
332
367
|
bindCriterionValue(criterion, $criterionContainer);
|
|
@@ -337,6 +372,109 @@ export default function advancedSearchFactory(config) {
|
|
|
337
372
|
}
|
|
338
373
|
|
|
339
374
|
criterion.rendered = true;
|
|
375
|
+
|
|
376
|
+
if (config.collapsibleCriteria) {
|
|
377
|
+
reorganizeFilterLayout();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @returns {jQuery}
|
|
383
|
+
*/
|
|
384
|
+
function getAllRenderedFilters() {
|
|
385
|
+
return $advancedCriteriaContainer.children('.filter-container').not('.invalid-criteria-warning-container');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @param {jQuery} $filter
|
|
390
|
+
* @param {boolean} open
|
|
391
|
+
*/
|
|
392
|
+
function setFilterSpoilerOpen($filter, open) {
|
|
393
|
+
const $spoiler = $filter.find('.filter-spoiler').first();
|
|
394
|
+
if (!$spoiler.length) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
$spoiler.toggleClass('is-open', open);
|
|
398
|
+
$filter.find('.filter-spoiler-toggle').attr('aria-expanded', open);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @param {number} appliedCount
|
|
403
|
+
* @returns {string}
|
|
404
|
+
*/
|
|
405
|
+
function getAppliedFiltersSummaryText(appliedCount) {
|
|
406
|
+
if (appliedCount === 1) {
|
|
407
|
+
return __('1 filter applied');
|
|
408
|
+
}
|
|
409
|
+
return __('%s filters applied').replace('%s', String(appliedCount));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Keeps each filter as its own spoiler card: newest expanded, previous collapsed (headers stay visible).
|
|
414
|
+
* With collapsibleCriteria, newest is prepended (index 0); otherwise newest is last.
|
|
415
|
+
*/
|
|
416
|
+
function reorganizeFilterLayout() {
|
|
417
|
+
const $filters = getAllRenderedFilters();
|
|
418
|
+
const count = $filters.length;
|
|
419
|
+
|
|
420
|
+
updateAppliedFiltersSummary(count);
|
|
421
|
+
|
|
422
|
+
if (count === 0) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const openIndex = config.collapsibleCriteria ? 0 : count - 1;
|
|
427
|
+
$filters.each(function (index) {
|
|
428
|
+
setFilterSpoilerOpen($(this), index === openIndex);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
if ($appliedFiltersSummary && $appliedFiltersSummary.length) {
|
|
432
|
+
$appliedFiltersSummary.attr('aria-expanded', 'false');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Updates the "N filters applied" summary next to Add filter.
|
|
438
|
+
* @param {number} appliedCount
|
|
439
|
+
*/
|
|
440
|
+
function updateAppliedFiltersSummary(appliedCount) {
|
|
441
|
+
if ($appliedFiltersSummary && $appliedFiltersSummary.length) {
|
|
442
|
+
if (appliedCount > 0) {
|
|
443
|
+
$appliedFiltersSummary
|
|
444
|
+
.text(getAppliedFiltersSummaryText(appliedCount))
|
|
445
|
+
.removeClass('hidden')
|
|
446
|
+
.prop('hidden', false);
|
|
447
|
+
} else {
|
|
448
|
+
$appliedFiltersSummary.addClass('hidden').prop('hidden', true).text('').attr('aria-expanded', 'false');
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
instance.trigger('criteriachange', { count: appliedCount });
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Toggles expand/collapse for all filters except the newest one.
|
|
457
|
+
* With collapsibleCriteria (prepend), newest is first; otherwise newest is last.
|
|
458
|
+
*/
|
|
459
|
+
function togglePreviousFilters() {
|
|
460
|
+
const $filters = getAllRenderedFilters();
|
|
461
|
+
if ($filters.length <= 1) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const $previous = config.collapsibleCriteria ? $filters.slice(1) : $filters.slice(0, -1);
|
|
466
|
+
const anyOpen = $previous.filter(function () {
|
|
467
|
+
return $(this).find('.filter-spoiler').first().hasClass('is-open');
|
|
468
|
+
}).length > 0;
|
|
469
|
+
const open = !anyOpen;
|
|
470
|
+
|
|
471
|
+
$previous.each(function () {
|
|
472
|
+
setFilterSpoilerOpen($(this), open);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
if ($appliedFiltersSummary && $appliedFiltersSummary.length) {
|
|
476
|
+
$appliedFiltersSummary.attr('aria-expanded', open);
|
|
477
|
+
}
|
|
340
478
|
}
|
|
341
479
|
|
|
342
480
|
/**
|
|
@@ -355,7 +493,11 @@ export default function advancedSearchFactory(config) {
|
|
|
355
493
|
templateToUse = listCheckboxCriterionTpl;
|
|
356
494
|
}
|
|
357
495
|
|
|
358
|
-
|
|
496
|
+
if (config.collapsibleCriteria) {
|
|
497
|
+
$advancedCriteriaContainer.prepend(templateToUse({ criterion }));
|
|
498
|
+
} else {
|
|
499
|
+
$advancedCriteriaContainer.append(templateToUse({ criterion }));
|
|
500
|
+
}
|
|
359
501
|
|
|
360
502
|
const $criterionContainer = $(`.${criterion.id}-filter`, $container);
|
|
361
503
|
const valueMapping = criteriaMapping[criterion.type];
|
|
@@ -432,15 +574,18 @@ export default function advancedSearchFactory(config) {
|
|
|
432
574
|
* @param {object} $criterionContainer - rendered criterion
|
|
433
575
|
*/
|
|
434
576
|
function bindCriterionValue(criterion, $criterionContainer) {
|
|
577
|
+
if (criterion.type === criteriaTypes.text) {
|
|
578
|
+
// Bind synchronously so typing / Search right after Add filter is not lost
|
|
579
|
+
// (getInitialCriterionLabel resolves on a microtask).
|
|
580
|
+
$('input', $criterionContainer).val(criterion.value);
|
|
581
|
+
$('input', $criterionContainer).on('input change', function () {
|
|
582
|
+
criterion.value = $(this).val() || null;
|
|
583
|
+
});
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
|
|
435
587
|
getInitialCriterionLabel(criterion).then(initialCriterion => {
|
|
436
|
-
if (criterion.type === criteriaTypes.
|
|
437
|
-
// set initial value
|
|
438
|
-
$('input', $criterionContainer).val(criterion.value);
|
|
439
|
-
// set event to bind input value to critariaState
|
|
440
|
-
$('input', $criterionContainer).on('change', function () {
|
|
441
|
-
criterion.value = $(this).val() || null;
|
|
442
|
-
});
|
|
443
|
-
} else if (criterion.type === criteriaTypes.list && criterion.uri) {
|
|
588
|
+
if (criterion.type === criteriaTypes.list && criterion.uri) {
|
|
444
589
|
// set initial value
|
|
445
590
|
if (criterion.value) {
|
|
446
591
|
$(`input[name=${criterion.id}-select]`, $criterionContainer).select2('data', initialCriterion);
|
|
@@ -477,6 +622,57 @@ export default function advancedSearchFactory(config) {
|
|
|
477
622
|
});
|
|
478
623
|
}
|
|
479
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Wraps a rendered criterion in a collapsible spoiler (Resource Manager UX).
|
|
627
|
+
* @param {jQuery} $criterionContainer
|
|
628
|
+
* @param {object} criterion
|
|
629
|
+
*/
|
|
630
|
+
function wrapCriterionAsSpoiler($criterionContainer, criterion) {
|
|
631
|
+
let $deleteBtn = $criterionContainer.find('.icon-result-nok').first();
|
|
632
|
+
if (!$deleteBtn.length) {
|
|
633
|
+
$deleteBtn = $('<button>', {
|
|
634
|
+
type: 'button',
|
|
635
|
+
class: 'filter-spoiler-delete icon-bin',
|
|
636
|
+
'aria-label': __('Remove criteria')
|
|
637
|
+
});
|
|
638
|
+
} else {
|
|
639
|
+
$deleteBtn
|
|
640
|
+
.attr('type', 'button')
|
|
641
|
+
.removeClass('icon-result-nok')
|
|
642
|
+
.addClass('filter-spoiler-delete icon-bin')
|
|
643
|
+
.attr('aria-label', __('Remove criteria'));
|
|
644
|
+
}
|
|
645
|
+
const $title = $('<span>', { class: 'filter-spoiler-title', text: criterion.label });
|
|
646
|
+
const $toggle = $('<button>', {
|
|
647
|
+
type: 'button',
|
|
648
|
+
class: 'filter-spoiler-toggle',
|
|
649
|
+
'aria-expanded': 'true'
|
|
650
|
+
}).append($title);
|
|
651
|
+
|
|
652
|
+
const $header = $('<div>', { class: 'filter-spoiler-header' }).append($toggle, $deleteBtn);
|
|
653
|
+
|
|
654
|
+
const $body = $('<div>', { class: 'filter-spoiler-body' });
|
|
655
|
+
$criterionContainer.children().appendTo($body);
|
|
656
|
+
|
|
657
|
+
const $spoiler = $('<div>', { class: 'filter-spoiler is-open' }).append($header, $body);
|
|
658
|
+
$criterionContainer.empty().append($spoiler);
|
|
659
|
+
$criterionContainer.addClass('filter-spoiler-wrapper');
|
|
660
|
+
|
|
661
|
+
$toggle.on('click', function (e) {
|
|
662
|
+
e.preventDefault();
|
|
663
|
+
const $spoilerEl = $criterionContainer.find('.filter-spoiler').first();
|
|
664
|
+
const willOpen = !$spoilerEl.hasClass('is-open');
|
|
665
|
+
if (willOpen && config.collapsibleCriteria) {
|
|
666
|
+
getAllRenderedFilters().each(function () {
|
|
667
|
+
if (this !== $criterionContainer.get(0)) {
|
|
668
|
+
setFilterSpoilerOpen($(this), false);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
setFilterSpoilerOpen($criterionContainer, willOpen);
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
480
676
|
/**
|
|
481
677
|
* Removes a criterion from advanced criteria container when user clicks on the criterion close icon.
|
|
482
678
|
* It also adds the option element to criteria select so removed criterion can be rendered again
|
|
@@ -488,7 +684,7 @@ export default function advancedSearchFactory(config) {
|
|
|
488
684
|
const criterionKey = getCriterionStateId(criterion);
|
|
489
685
|
|
|
490
686
|
// remove criterion and append new criterion to select options
|
|
491
|
-
$(this).
|
|
687
|
+
$(this).closest('.filter-container').remove();
|
|
492
688
|
$criteriaSelect.append(newOption);
|
|
493
689
|
|
|
494
690
|
// reset criterion values on criteriaState
|
|
@@ -499,6 +695,10 @@ export default function advancedSearchFactory(config) {
|
|
|
499
695
|
if ($advancedCriteriaContainer.get(0).scrollHeight <= $advancedCriteriaContainer.outerHeight()) {
|
|
500
696
|
$advancedCriteriaContainer.removeClass('scrollable');
|
|
501
697
|
}
|
|
698
|
+
|
|
699
|
+
if (config.collapsibleCriteria) {
|
|
700
|
+
reorganizeFilterLayout();
|
|
701
|
+
}
|
|
502
702
|
}
|
|
503
703
|
|
|
504
704
|
/**
|
|
@@ -512,16 +712,24 @@ export default function advancedSearchFactory(config) {
|
|
|
512
712
|
let criteria = [];
|
|
513
713
|
|
|
514
714
|
_.forEach(classTree, classInstance => {
|
|
515
|
-
|
|
715
|
+
const metadata = classInstance && classInstance.metadata;
|
|
716
|
+
if (Array.isArray(metadata) && metadata.length) {
|
|
717
|
+
criteria.push(...metadata);
|
|
718
|
+
}
|
|
516
719
|
});
|
|
517
720
|
|
|
518
721
|
// extends each criterion with an id that can be use as a valid css class
|
|
519
|
-
|
|
722
|
+
criteria = criteria.filter(criterion => {
|
|
723
|
+
const id = String((criterion && criterion.propertyUri) || '').replace(/^[^a-zA-Z]*|[^a-zA-Z0-9]*/g, '');
|
|
724
|
+
if (!id) {
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
520
727
|
criterion.label = getCriterionLabel(criterion);
|
|
521
|
-
criterion.id =
|
|
728
|
+
criterion.id = id;
|
|
729
|
+
return true;
|
|
522
730
|
});
|
|
523
731
|
|
|
524
|
-
return criteria;
|
|
732
|
+
return _.uniqBy(criteria, 'propertyUri');
|
|
525
733
|
}
|
|
526
734
|
|
|
527
735
|
/**
|
|
@@ -537,6 +745,9 @@ export default function advancedSearchFactory(config) {
|
|
|
537
745
|
const invalidCriteria = deleteDeprecatedCriteria(criteria);
|
|
538
746
|
extendCriteria(criteria);
|
|
539
747
|
renderWarningMessage(invalidCriteria);
|
|
748
|
+
if (config.collapsibleCriteria) {
|
|
749
|
+
reorganizeFilterLayout();
|
|
750
|
+
}
|
|
540
751
|
}
|
|
541
752
|
|
|
542
753
|
/**
|