@syncfusion/ej2-querybuilder 24.2.9 → 25.1.35

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/ej2-querybuilder.min.js +2 -2
  3. package/dist/ej2-querybuilder.umd.min.js +2 -2
  4. package/dist/ej2-querybuilder.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-querybuilder.es2015.js +1609 -159
  6. package/dist/es6/ej2-querybuilder.es2015.js.map +1 -1
  7. package/dist/es6/ej2-querybuilder.es5.js +1611 -159
  8. package/dist/es6/ej2-querybuilder.es5.js.map +1 -1
  9. package/dist/global/ej2-querybuilder.min.js +2 -2
  10. package/dist/global/ej2-querybuilder.min.js.map +1 -1
  11. package/dist/global/index.d.ts +1 -1
  12. package/package.json +12 -12
  13. package/src/global.js +2 -0
  14. package/src/query-builder/index.d.ts +1 -0
  15. package/src/query-builder/index.js +1 -0
  16. package/src/query-builder/query-builder-model.d.ts +69 -1
  17. package/src/query-builder/query-builder.d.ts +189 -4
  18. package/src/query-builder/query-builder.js +895 -130
  19. package/src/query-builder/query-library.d.ts +24 -0
  20. package/src/query-builder/query-library.js +689 -0
  21. package/styles/bootstrap-dark.css +29 -12
  22. package/styles/bootstrap.css +29 -12
  23. package/styles/bootstrap4.css +25 -12
  24. package/styles/bootstrap5-dark.css +35 -11
  25. package/styles/bootstrap5.css +35 -11
  26. package/styles/fabric-dark.css +25 -12
  27. package/styles/fabric.css +25 -12
  28. package/styles/fluent-dark.css +39 -11
  29. package/styles/fluent.css +39 -11
  30. package/styles/highcontrast-light.css +25 -12
  31. package/styles/highcontrast.css +25 -12
  32. package/styles/material-dark.css +25 -12
  33. package/styles/material.css +25 -12
  34. package/styles/material3-dark.css +25 -12
  35. package/styles/material3.css +25 -12
  36. package/styles/query-builder/_bds-definition.scss +107 -0
  37. package/styles/query-builder/_layout.scss +37 -7
  38. package/styles/query-builder/_theme.scss +16 -1
  39. package/styles/query-builder/bootstrap-dark.css +29 -12
  40. package/styles/query-builder/bootstrap.css +29 -12
  41. package/styles/query-builder/bootstrap4.css +25 -12
  42. package/styles/query-builder/bootstrap5-dark.css +35 -11
  43. package/styles/query-builder/bootstrap5.css +35 -11
  44. package/styles/query-builder/fabric-dark.css +25 -12
  45. package/styles/query-builder/fabric.css +25 -12
  46. package/styles/query-builder/fluent-dark.css +39 -11
  47. package/styles/query-builder/fluent.css +39 -11
  48. package/styles/query-builder/highcontrast-light.css +25 -12
  49. package/styles/query-builder/highcontrast.css +25 -12
  50. package/styles/query-builder/icons/_bds.scss +7 -0
  51. package/styles/query-builder/material-dark.css +25 -12
  52. package/styles/query-builder/material.css +25 -12
  53. package/styles/query-builder/material3-dark.css +25 -12
  54. package/styles/query-builder/material3.css +25 -12
  55. package/styles/query-builder/tailwind-dark.css +30 -11
  56. package/styles/query-builder/tailwind.css +30 -11
  57. package/styles/tailwind-dark.css +30 -11
  58. package/styles/tailwind.css +30 -11
@@ -89,6 +89,9 @@ __decorate([
89
89
  __decorate([
90
90
  Property(false)
91
91
  ], Rule.prototype, "not", void 0);
92
+ __decorate([
93
+ Property(false)
94
+ ], Rule.prototype, "isLocked", void 0);
92
95
  /**
93
96
  * Defines the property for value.
94
97
  */
@@ -114,6 +117,18 @@ __decorate([
114
117
  */
115
118
  class ShowButtons extends ChildProperty {
116
119
  }
120
+ __decorate([
121
+ Property(false)
122
+ ], ShowButtons.prototype, "cloneRule", void 0);
123
+ __decorate([
124
+ Property(false)
125
+ ], ShowButtons.prototype, "cloneGroup", void 0);
126
+ __decorate([
127
+ Property(false)
128
+ ], ShowButtons.prototype, "lockRule", void 0);
129
+ __decorate([
130
+ Property(false)
131
+ ], ShowButtons.prototype, "lockGroup", void 0);
117
132
  __decorate([
118
133
  Property(true)
119
134
  ], ShowButtons.prototype, "ruleDelete", void 0);
@@ -128,7 +143,7 @@ let QueryBuilder = class QueryBuilder extends Component {
128
143
  super(options, element);
129
144
  this.isReadonly = true;
130
145
  this.fields = { text: 'label', value: 'field' };
131
- this.updatedRule = { not: false, condition: 'and' };
146
+ this.updatedRule = { not: false, condition: 'and', isLocked: false };
132
147
  this.isLocale = false;
133
148
  this.isRefreshed = false;
134
149
  this.isNotified = false;
@@ -139,6 +154,14 @@ let QueryBuilder = class QueryBuilder extends Component {
139
154
  this.isDestroy = false;
140
155
  this.isGetNestedData = false;
141
156
  this.isCustomOprCols = [];
157
+ this.groupCounter = 0;
158
+ this.lockItems = [];
159
+ this.groupIndex = -1;
160
+ this.ruleIndex = -1;
161
+ this.isLastGroup = false;
162
+ this.cloneGrpBtnClick = false;
163
+ this.isMiddleGroup = false;
164
+ this.cloneRuleBtnClick = false;
142
165
  MultiSelect.Inject(CheckBoxSelection);
143
166
  }
144
167
  getPersistData() {
@@ -190,6 +213,14 @@ let QueryBuilder = class QueryBuilder extends Component {
190
213
  getModuleName() {
191
214
  return 'query-builder';
192
215
  }
216
+ requiredModules() {
217
+ const modules = [];
218
+ modules.push({
219
+ member: 'query-library',
220
+ args: [this]
221
+ });
222
+ return modules;
223
+ }
193
224
  GetRootColumnName(field) {
194
225
  return this.separator ? field.split(this.separator)[0] : field;
195
226
  }
@@ -378,31 +409,51 @@ let QueryBuilder = class QueryBuilder extends Component {
378
409
  txtareaElem.style.height = txtareaElem.scrollHeight + 'px';
379
410
  }
380
411
  if (target.tagName === 'BUTTON' && target.className.indexOf('e-qb-toggle') < 0) {
381
- if (target.className.indexOf('e-removerule') > -1) {
382
- this.actionButton = target;
383
- this.deleteRule(target);
384
- }
385
- else if (target.className.indexOf('e-deletegroup') > -1) {
386
- this.actionButton = target;
387
- this.deleteGroup(closest(target, '.e-group-container'));
388
- }
389
- else if (target.className.indexOf('e-edit-rule') > -1) {
390
- const animation = new Animation({ duration: 1000, delay: 0 });
391
- animation.animate('.e-query-builder', { name: 'SlideLeftIn' });
392
- document.getElementById(this.element.id + '_summary_content').style.display = 'none';
393
- if (this.element.querySelectorAll('.e-group-container').length < 1) {
394
- this.addGroupElement(false, this.element, this.rule.condition, false, this.rule.not);
395
- const mRules = extend({}, this.rule, {}, true);
396
- this.setGroupRules(mRules);
397
- this.renderSummaryCollapse();
398
- }
399
- else {
400
- const groupElem = this.element.querySelector('.e-group-container');
401
- if (groupElem.querySelectorAll('.e-collapse-rule').length < 1) {
412
+ switch (true) {
413
+ case target.className.indexOf('e-removerule') > -1:
414
+ this.actionButton = target;
415
+ this.deleteRule(target);
416
+ break;
417
+ case target.className.indexOf('e-clone-rule-btn') > -1:
418
+ this.actionButton = target;
419
+ this.cloneRuleBtnClick = true;
420
+ this.ruleClone(target);
421
+ break;
422
+ case target.className.indexOf('e-lock-rule-btn') > -1:
423
+ this.actionButton = target;
424
+ this.ruleLock(target);
425
+ break;
426
+ case target.className.indexOf('e-lock-grp-btn') > -1:
427
+ this.actionButton = target;
428
+ this.groupLock(target);
429
+ break;
430
+ case target.className.indexOf('e-clone-grp-btn') > -1:
431
+ this.actionButton = target;
432
+ this.cloneGrpBtnClick = true;
433
+ this.groupClone(closest(target, '.e-group-container'));
434
+ break;
435
+ case target.className.indexOf('e-deletegroup') > -1:
436
+ this.actionButton = target;
437
+ this.deleteGroup(closest(target, '.e-group-container'));
438
+ break;
439
+ case target.className.indexOf('e-edit-rule') > -1:
440
+ const animation = new Animation({ duration: 1000, delay: 0 });
441
+ animation.animate('.e-query-builder', { name: 'SlideLeftIn' });
442
+ document.getElementById(this.element.id + '_summary_content').style.display = 'none';
443
+ if (this.element.querySelectorAll('.e-group-container').length < 1) {
444
+ this.addGroupElement(false, this.element, this.rule.condition, false, this.rule.not);
445
+ const mRules = extend({}, this.rule, {}, true);
446
+ this.setGroupRules(mRules);
402
447
  this.renderSummaryCollapse();
403
448
  }
404
- groupElem.style.display = 'block';
405
- }
449
+ else {
450
+ const groupElem = this.element.querySelector('.e-group-container');
451
+ if (groupElem.querySelectorAll('.e-collapse-rule').length < 1) {
452
+ this.renderSummaryCollapse();
453
+ }
454
+ groupElem.style.display = 'block';
455
+ }
456
+ break;
406
457
  }
407
458
  }
408
459
  else if ((target.tagName === 'LABEL' && target.parentElement.className.indexOf('e-btn-group') > -1) ||
@@ -502,7 +553,18 @@ let QueryBuilder = class QueryBuilder extends Component {
502
553
  else {
503
554
  ruleElem = this.createElement('div', { attrs: { class: 'e-rule-container' } });
504
555
  ruleElem.setAttribute('id', target.id + '_rule' + this.ruleIdCounter);
505
- ruleListElem.appendChild(ruleElem);
556
+ if (this.showButtons.cloneRule && this.cloneRuleBtnClick) {
557
+ if (this.ruleIndex < 0) {
558
+ ruleListElem.appendChild(ruleElem);
559
+ }
560
+ else {
561
+ ruleListElem.insertBefore(ruleElem, ruleListElem.children[this.ruleIndex + 1]); // added clone rule to next position
562
+ }
563
+ this.cloneRuleBtnClick = false;
564
+ }
565
+ else {
566
+ ruleListElem.appendChild(ruleElem);
567
+ }
506
568
  this.ruleIdCounter++;
507
569
  }
508
570
  if (column && column.ruleTemplate && rule) {
@@ -552,6 +614,21 @@ let QueryBuilder = class QueryBuilder extends Component {
552
614
  elem = this.ruleElem.querySelector('.e-rule-field').cloneNode(true);
553
615
  ruleElem.appendChild(elem);
554
616
  }
617
+ if (this.showButtons.lockGroup) {
618
+ removeClass(ruleElem.querySelectorAll('.e-lock-grp-btn'), 'e-button-hide');
619
+ }
620
+ if (this.showButtons.lockRule) {
621
+ removeClass(ruleElem.querySelectorAll('.e-lock-rule-btn'), 'e-button-hide');
622
+ }
623
+ if (this.showButtons.cloneGroup) {
624
+ removeClass(ruleElem.querySelectorAll('.e-clone-grp-btn'), 'e-button-hide');
625
+ }
626
+ if (this.showButtons.cloneRule) {
627
+ removeClass(ruleElem.querySelectorAll('.e-clone-rule-btn'), 'e-button-hide');
628
+ }
629
+ if (this.showButtons.ruleDelete) {
630
+ removeClass(ruleElem.querySelectorAll('.e-lock-grp-btn'), 'e-button-hide');
631
+ }
555
632
  if (column && column.ruleTemplate && rule) {
556
633
  this.renderReactTemplates();
557
634
  }
@@ -594,7 +671,7 @@ let QueryBuilder = class QueryBuilder extends Component {
594
671
  else {
595
672
  ruleElem = this.appendRuleElem(trgt, column, act, pId, 'field');
596
673
  ruleElem.querySelector('.e-filter-input').setAttribute('id', ruleElem.id + '_filterkey');
597
- let element = ruleElem.querySelector('button');
674
+ const element = ruleElem.querySelector('.e-rule-delete');
598
675
  if (this.element.className.indexOf('e-device') > -1 || this.displayMode === 'Vertical') {
599
676
  element.textContent = this.l10n.getConstant('Remove');
600
677
  addClass([element], 'e-flat');
@@ -604,8 +681,11 @@ let QueryBuilder = class QueryBuilder extends Component {
604
681
  addClass([element], 'e-round');
605
682
  addClass([element], 'e-icon-btn');
606
683
  element.setAttribute('title', this.l10n.getConstant('DeleteRule'));
607
- element = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-delete-icon' } });
608
- ruleElem.querySelector('button').appendChild(element);
684
+ const spanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-delete-icon' } });
685
+ ruleElem.querySelector('.e-rule-delete').appendChild(spanElement);
686
+ }
687
+ if (!this.showButtons.ruleDelete) {
688
+ element.classList.add('e-button-hide');
609
689
  }
610
690
  }
611
691
  if (this.displayMode === 'Vertical' || this.element.className.indexOf('e-device') > -1) {
@@ -636,6 +716,9 @@ let QueryBuilder = class QueryBuilder extends Component {
636
716
  if (this.separator && rule.field) {
637
717
  ddlValue = this.GetRootColumnName(rule.field);
638
718
  }
719
+ else if (this.autoSelectField) {
720
+ ddlValue = this.GetRootColumnName(rule.field);
721
+ }
639
722
  else {
640
723
  ddlValue = this.isImportRules ? this.GetRootColumnName(rule.field) : rule.field;
641
724
  }
@@ -643,8 +726,7 @@ let QueryBuilder = class QueryBuilder extends Component {
643
726
  dataSource: this.columns,
644
727
  fields: this.fields, placeholder: this.l10n.getConstant('SelectField'),
645
728
  popupHeight: ((this.columns.length > 5) ? height : 'auto'), close: this.fieldClose.bind(this, ruleElem.id + '_filterkey'),
646
- change: this.changeField.bind(this), value: rule ? ddlValue : null, open: this.popupOpen.bind(this, true),
647
- cssClass: 'qb-dropdownlist'
729
+ change: this.changeField.bind(this), value: rule ? ddlValue : null, open: this.popupOpen.bind(this, true), cssClass: 'qb-dropdownlist'
648
730
  };
649
731
  if (this.fieldModel) {
650
732
  ddlField = Object.assign({}, ddlField, this.fieldModel);
@@ -734,12 +816,23 @@ let QueryBuilder = class QueryBuilder extends Component {
734
816
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
735
817
  const custom = rule.custom;
736
818
  if (Object.keys(rule).length) {
737
- rules.rules.push({
738
- 'field': rule.field, 'type': rule.type, 'label': rule.label, 'operator': rule.operator, value: rule.value
739
- });
740
- if (custom) {
741
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
742
- rules.rules[rules.rules.length - 1].custom = custom;
819
+ if (this.ruleIndex < 0) {
820
+ rules.rules.push({
821
+ 'field': rule.field, 'type': rule.type, 'label': rule.label, 'operator': rule.operator, value: rule.value
822
+ });
823
+ if (custom) {
824
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
825
+ rules.rules[rules.rules.length - 1].custom = custom;
826
+ }
827
+ }
828
+ else {
829
+ rules.rules.splice(this.ruleIndex + 1, 0, {
830
+ 'field': rule.field, 'type': rule.type, 'label': rule.label, 'operator': rule.operator, value: rule.value
831
+ });
832
+ if (custom) {
833
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
834
+ rules.rules[this.ruleIndex + 1].custom = custom;
835
+ }
743
836
  }
744
837
  }
745
838
  else {
@@ -747,6 +840,9 @@ let QueryBuilder = class QueryBuilder extends Component {
747
840
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
748
841
  newRule.custom = custom;
749
842
  }
843
+ if (this.autoSelectField) {
844
+ rule.field = newRule.field = this.rule.rules[0].field;
845
+ }
750
846
  rules.rules.push(newRule);
751
847
  }
752
848
  }
@@ -946,6 +1042,8 @@ let QueryBuilder = class QueryBuilder extends Component {
946
1042
  ruleTemplate() {
947
1043
  let tempElem;
948
1044
  let clsName;
1045
+ let cloneClsName;
1046
+ let lockClsName;
949
1047
  const ruleElem = this.createElement('div');
950
1048
  const fieldElem = this.createElement('div', { attrs: { class: 'e-rule-field' } });
951
1049
  tempElem = this.createElement('div', { attrs: { class: 'e-rule-filter' } });
@@ -957,6 +1055,24 @@ let QueryBuilder = class QueryBuilder extends Component {
957
1055
  tempElem = this.createElement('div', { attrs: { class: 'e-rule-value' } });
958
1056
  fieldElem.appendChild(tempElem);
959
1057
  tempElem = this.createElement('div', { attrs: { class: 'e-rule-value-delete' } });
1058
+ if (this.showButtons.cloneRule) {
1059
+ cloneClsName = 'e-clone-rule-btn e-clone-rule e-css e-btn e-small e-round e-icon-btn';
1060
+ }
1061
+ else {
1062
+ cloneClsName = 'e-clone-rule-btn e-clone-rule e-css e-btn e-small e-round e-icon-btn e-button-hide';
1063
+ }
1064
+ if (this.showButtons.lockRule) {
1065
+ lockClsName = 'e-lock-rule-btn e-lock-rule e-css e-btn e-small e-round e-icons e-icon-btn';
1066
+ }
1067
+ else {
1068
+ lockClsName = 'e-lock-rule-btn e-lock-rule e-css e-btn e-small e-round e-icons e-icon-btn e-button-hide';
1069
+ }
1070
+ const cloneRuleBtnElem = this.createElement('button', { attrs: { title: this.l10n.getConstant('CloneRule'), type: 'button', class: cloneClsName } });
1071
+ let spanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-copy' } });
1072
+ cloneRuleBtnElem.appendChild(spanElement);
1073
+ const cloneLockBtnElem = this.createElement('button', { attrs: { title: this.l10n.getConstant('LockRule'), type: 'button', class: lockClsName } });
1074
+ spanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-unlock' } });
1075
+ cloneLockBtnElem.appendChild(spanElement);
960
1076
  if (this.showButtons.ruleDelete || isNullOrUndefined(this.showButtons.ruleDelete)) {
961
1077
  clsName = 'e-removerule e-rule-delete e-css e-btn e-small';
962
1078
  }
@@ -964,6 +1080,8 @@ let QueryBuilder = class QueryBuilder extends Component {
964
1080
  clsName = 'e-removerule e-rule-delete e-css e-btn e-small e-button-hide';
965
1081
  }
966
1082
  const delBtnElem = this.createElement('button', { attrs: { type: 'button', class: clsName } });
1083
+ tempElem.appendChild(cloneRuleBtnElem);
1084
+ tempElem.appendChild(cloneLockBtnElem);
967
1085
  tempElem.appendChild(delBtnElem);
968
1086
  fieldElem.appendChild(tempElem);
969
1087
  ruleElem.appendChild(fieldElem);
@@ -1032,9 +1150,6 @@ let QueryBuilder = class QueryBuilder extends Component {
1032
1150
  button.appendTo(dltGroupBtn);
1033
1151
  dltGroupBtn.setAttribute('title', this.l10n.getConstant('DeleteGroup'));
1034
1152
  rippleEffect(dltGroupBtn, { selector: '.deletegroup' });
1035
- if (!this.headerTemplate) {
1036
- groupElem.querySelector('.e-group-action').appendChild(dltGroupBtn);
1037
- }
1038
1153
  const ruleList = target.querySelector('.e-rule-list');
1039
1154
  const childElems = ruleList.children;
1040
1155
  let grpLen = 0;
@@ -1043,20 +1158,72 @@ let QueryBuilder = class QueryBuilder extends Component {
1043
1158
  grpLen += 1;
1044
1159
  }
1045
1160
  }
1046
- ruleList.appendChild(groupElem);
1161
+ if (this.showButtons.cloneGroup && this.cloneGrpBtnClick) {
1162
+ if (this.groupIndex === (childElems.length - 1)) {
1163
+ ruleList.appendChild(groupElem);
1164
+ this.isLastGroup = true;
1165
+ }
1166
+ else {
1167
+ childElems[this.groupIndex + 1].parentNode.insertBefore(groupElem, childElems[this.groupIndex + 1]); // clone the element to nxt element
1168
+ this.isMiddleGroup = true;
1169
+ }
1170
+ }
1171
+ else {
1172
+ ruleList.appendChild(groupElem);
1173
+ }
1047
1174
  const level = this.levelColl[target.id].slice(0);
1048
1175
  level.push(grpLen);
1049
1176
  this.levelColl[groupElem.id] = level;
1177
+ if (this.groupIndex > -1) {
1178
+ this.refreshLevelColl();
1179
+ }
1050
1180
  if (!this.isImportRules) {
1051
1181
  this.isAddSuccess = true;
1052
1182
  this.addGroups([], target.id.replace(this.element.id + '_', ''));
1053
1183
  this.isAddSuccess = false;
1054
- if (isBtnClick) {
1184
+ if (isBtnClick && this.addRuleToNewGroups) {
1055
1185
  this.addRuleElement(groupElem, {});
1056
1186
  }
1057
1187
  }
1188
+ if (!this.headerTemplate) {
1189
+ let lockClsName = '';
1190
+ if (this.showButtons.cloneGroup) {
1191
+ lockClsName = 'e-clone-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn';
1192
+ }
1193
+ else {
1194
+ lockClsName = 'e-clone-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn e-button-hide';
1195
+ }
1196
+ const cloneBtnElem = this.createElement('button', { attrs: { title: this.l10n.getConstant('CloneGroup'), type: 'button', class: lockClsName } });
1197
+ const spanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-copy' } });
1198
+ cloneBtnElem.appendChild(spanElement);
1199
+ groupElem.querySelector('.e-group-action').appendChild(cloneBtnElem);
1200
+ if (this.showButtons.lockGroup) {
1201
+ lockClsName = 'e-lock-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn';
1202
+ }
1203
+ else {
1204
+ lockClsName = 'e-lock-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn e-button-hide';
1205
+ }
1206
+ const lockBtnElem = this.createElement('button', { attrs: { title: this.l10n.getConstant('LockGroup'), type: 'button', class: lockClsName } });
1207
+ const lockSpanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-unlock' } });
1208
+ lockBtnElem.appendChild(lockSpanElement);
1209
+ groupElem.querySelector('.e-group-action').appendChild(lockBtnElem);
1210
+ groupElem.querySelector('.e-group-action').appendChild(dltGroupBtn);
1211
+ }
1058
1212
  }
1059
1213
  else {
1214
+ if (!this.headerTemplate) {
1215
+ let lockClsName = '';
1216
+ if (this.showButtons.lockGroup) {
1217
+ lockClsName = 'e-lock-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn';
1218
+ }
1219
+ else {
1220
+ lockClsName = 'e-lock-grp-btn e-css e-btn e-small e-round e-icons e-icon-btn e-button-hide';
1221
+ }
1222
+ const lockBtnElem = this.createElement('button', { attrs: { title: this.l10n.getConstant('LockGroup'), type: 'button', class: lockClsName } });
1223
+ const spanElement = this.createElement('span', { attrs: { class: 'e-btn-icon e-icons e-unlock' } });
1224
+ lockBtnElem.appendChild(spanElement);
1225
+ groupElem.querySelector('.e-group-action').appendChild(lockBtnElem);
1226
+ }
1060
1227
  target.appendChild(groupElem);
1061
1228
  this.levelColl[groupElem.id] = [0];
1062
1229
  }
@@ -1390,7 +1557,7 @@ let QueryBuilder = class QueryBuilder extends Component {
1390
1557
  this.prevItemData = args.itemData;
1391
1558
  const fieldElem = closest(args.element, '.e-rule-filter') || closest(args.element, '.e-rule-sub-filter');
1392
1559
  const column = this.fieldMode === 'DropdownTree' ? this.getColumn(args.value[0]) : this.getColumn(args.value);
1393
- if (this.fieldMode === 'DropdownTree' && fieldElem != null) {
1560
+ if (this.fieldMode === 'DropdownTree' && fieldElem !== null) {
1394
1561
  const ddtElem = fieldElem.querySelector('.e-dropdowntree.e-control');
1395
1562
  const ddt = getComponent(ddtElem, 'dropdowntree');
1396
1563
  if (column) {
@@ -1462,7 +1629,7 @@ let QueryBuilder = class QueryBuilder extends Component {
1462
1629
  let filterElem = closest(ddlArgs.element, '.e-rule-filter');
1463
1630
  filterElem = filterElem ? filterElem : closest(ddlArgs.element, '.e-rule-sub-filter');
1464
1631
  let ddlObj = getComponent(ddlArgs.element, 'dropdownlist');
1465
- if (this.fieldMode === 'DropdownTree' && filterElem != null) {
1632
+ if (this.fieldMode === 'DropdownTree' && filterElem !== null) {
1466
1633
  ddlObj = getComponent(ddlArgs.element, 'dropdowntree');
1467
1634
  }
1468
1635
  const element = closest(ddlArgs.element, '.e-group-container');
@@ -1589,7 +1756,7 @@ let QueryBuilder = class QueryBuilder extends Component {
1589
1756
  this.GetRootColumnName(rule.field) === this.GetRootColumnName(this.previousColumn.field))) {
1590
1757
  const subField = this.selectedColumn.columns;
1591
1758
  for (let i = 0; i < subField.length; i++) {
1592
- if (rule.field === subField[i].field || rule.field.indexOf(subField[i].field) > -1) {
1759
+ if (rule.field === subField[i].field) {
1593
1760
  dropDownList.value = subField[i].field;
1594
1761
  this.selectedColumn = subField[i];
1595
1762
  subFieldValue = true;
@@ -1628,7 +1795,7 @@ let QueryBuilder = class QueryBuilder extends Component {
1628
1795
  rule.value = [];
1629
1796
  }
1630
1797
  }
1631
- else if (typeof rule.value === 'object' && rule.value != null) {
1798
+ else if (typeof rule.value === 'object' && rule.value !== null) {
1632
1799
  rule.value = rule.value.length > 0 ? rule.value[0] : rule.type === 'number' ? 0 : '';
1633
1800
  }
1634
1801
  if (ddlArgs.previousItemData) {
@@ -1655,6 +1822,9 @@ let QueryBuilder = class QueryBuilder extends Component {
1655
1822
  if (valElem && this.getColumn(rule.field).template) {
1656
1823
  filterElem = operatorElem.previousElementSibling;
1657
1824
  }
1825
+ if (valElem.children.length == 0) {
1826
+ filterElem = operatorElem.previousElementSibling;
1827
+ }
1658
1828
  this.changeRuleValues(filterElem, rule, tempRule, ddlArgs);
1659
1829
  }
1660
1830
  }
@@ -1685,7 +1855,9 @@ let QueryBuilder = class QueryBuilder extends Component {
1685
1855
  tempRule.type = this.fieldMode === 'DropdownTree' ? this.getColumn(fieldObj.value[0]).type :
1686
1856
  this.getColumn(fieldObj.value).type;
1687
1857
  const itemData = ddlArgs.itemData;
1688
- this.renderValues(operatorElem, itemData, ddlArgs.previousItemData, true, rule, tempRule, ddlArgs.element);
1858
+ if (ddlObj.value !== '') {
1859
+ this.renderValues(operatorElem, itemData, ddlArgs.previousItemData, true, rule, tempRule, ddlArgs.element);
1860
+ }
1689
1861
  }
1690
1862
  else {
1691
1863
  const ruleId = closest(operatorElem, '.e-rule-container').id;
@@ -1699,7 +1871,14 @@ let QueryBuilder = class QueryBuilder extends Component {
1699
1871
  }
1700
1872
  const height = (this.element.className.indexOf('e-device') > -1) ? '250px' : '200px';
1701
1873
  let value = operatorList[0].value;
1702
- value = rule ? (rule.operator !== '' ? rule.operator : value) : value;
1874
+ let ddlIdx = 0;
1875
+ if (!this.autoSelectOperator) {
1876
+ value = '';
1877
+ ddlIdx = -1;
1878
+ }
1879
+ if (this.isImportRules || (this.ruleIndex > -1 || this.groupIndex > -1)) {
1880
+ value = rule ? (rule.operator ? rule.operator : value) : value;
1881
+ }
1703
1882
  let ddlOperator;
1704
1883
  ddlOperator = {
1705
1884
  dataSource: operatorList,
@@ -1707,7 +1886,7 @@ let QueryBuilder = class QueryBuilder extends Component {
1707
1886
  placeholder: this.l10n.getConstant('SelectOperator'),
1708
1887
  popupHeight: ((operatorList.length > 5) ? height : 'auto'),
1709
1888
  change: this.changeField.bind(this),
1710
- index: 0,
1889
+ index: ddlIdx,
1711
1890
  value: value,
1712
1891
  open: this.popupOpen.bind(this, false)
1713
1892
  };
@@ -1721,7 +1900,12 @@ let QueryBuilder = class QueryBuilder extends Component {
1721
1900
  tempRule.type = this.selectedColumn.type;
1722
1901
  tempRule.operator = rule.operator;
1723
1902
  }
1724
- this.renderValues(operatorElem, this.selectedColumn, ddlArgs.previousItemData, false, rule, tempRule, ddlArgs.element);
1903
+ if (!isNullOrUndefined(value) && value !== '') {
1904
+ this.renderValues(operatorElem, this.selectedColumn, ddlArgs.previousItemData, false, rule, tempRule, ddlArgs.element);
1905
+ }
1906
+ else if (this.autoSelectField && this.autoSelectOperator) {
1907
+ this.renderValues(operatorElem, this.selectedColumn, ddlArgs.previousItemData, false, rule, tempRule, ddlArgs.element);
1908
+ }
1725
1909
  }
1726
1910
  }
1727
1911
  if (!this.isImportRules) {
@@ -2078,14 +2262,14 @@ let QueryBuilder = class QueryBuilder extends Component {
2078
2262
  const columnData = this.getItemData(parentId);
2079
2263
  let selectedValue;
2080
2264
  const isTemplate = (typeof columnData.template === 'string');
2081
- if (this.isImportRules || this.isPublic || isTemplate) {
2265
+ if (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1 || this.isPublic || isTemplate) {
2082
2266
  selectedValue = rule.value;
2083
2267
  }
2084
2268
  else {
2085
2269
  selectedValue = this.setDefaultValue(parentId, false, false);
2086
2270
  }
2087
2271
  if ((operator === 'in' || operator === 'notin') && (this.dataColl.length || columnData.values)) {
2088
- selectedVal = this.isImportRules ? rule.value : this.setDefaultValue(parentId, true, false);
2272
+ selectedVal = (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1) ? rule.value : this.setDefaultValue(parentId, true, false);
2089
2273
  this.renderMultiSelect(columnData, parentId, idx, selectedVal, columnData.values);
2090
2274
  if (this.displayMode === 'Vertical' || this.element.className.indexOf('e-device') > -1) {
2091
2275
  ruleValElem.style.width = '100%';
@@ -2097,7 +2281,7 @@ let QueryBuilder = class QueryBuilder extends Component {
2097
2281
  }
2098
2282
  else {
2099
2283
  if (operator === 'in' || operator === 'notin') {
2100
- selectedVal = this.isImportRules ? rule.value : this.setDefaultValue(parentId, true, false);
2284
+ selectedVal = (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1) ? rule.value : this.setDefaultValue(parentId, true, false);
2101
2285
  selectedValue = selectedVal.join(',');
2102
2286
  }
2103
2287
  let txtBox;
@@ -2117,9 +2301,9 @@ let QueryBuilder = class QueryBuilder extends Component {
2117
2301
  renderNumberValue(parentId, rule, operator, idx, ruleValElem, itemData, length) {
2118
2302
  const columnData = this.getItemData(parentId);
2119
2303
  const isTemplate = (typeof columnData.template === 'string');
2120
- let selectedVal = (this.isImportRules || this.isPublic || isTemplate) ? rule.value : this.setDefaultValue(parentId, false, true);
2304
+ let selectedVal = (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1 || this.isPublic || isTemplate) ? rule.value : this.setDefaultValue(parentId, false, true);
2121
2305
  if ((operator === 'in' || operator === 'notin') && (this.dataColl.length || columnData.values)) {
2122
- selectedVal = this.isImportRules ? rule.value : this.setDefaultValue(parentId, true, false);
2306
+ selectedVal = (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1) ? rule.value : this.setDefaultValue(parentId, true, false);
2123
2307
  this.renderMultiSelect(columnData, parentId, idx, selectedVal, columnData.values);
2124
2308
  if (this.element.className.indexOf('e-device') > -1 || this.displayMode === 'Vertical') {
2125
2309
  ruleValElem.style.width = '100%';
@@ -2130,7 +2314,7 @@ let QueryBuilder = class QueryBuilder extends Component {
2130
2314
  }
2131
2315
  }
2132
2316
  else if (operator === 'in' || operator === 'notin') {
2133
- selectedVal = this.isImportRules ? rule.value : this.setDefaultValue(parentId, true, false);
2317
+ selectedVal = (this.isImportRules || this.ruleIndex > -1 || this.groupIndex > -1) ? rule.value : this.setDefaultValue(parentId, true, false);
2134
2318
  const selVal = selectedVal.join(',');
2135
2319
  let txtInp;
2136
2320
  txtInp = {
@@ -2403,8 +2587,8 @@ let QueryBuilder = class QueryBuilder extends Component {
2403
2587
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2404
2588
  : this.getColumn(filtObj.value);
2405
2589
  this.selectedRule = column;
2590
+ const ddlObj = getComponent(target.querySelector('input'), 'dropdownlist');
2406
2591
  if (isRender) {
2407
- const ddlObj = getComponent(target.querySelector('input'), 'dropdownlist');
2408
2592
  itemData = element.id.indexOf('operator') > -1 ? itemData : this.selectedRule;
2409
2593
  if (itemData.operators) {
2410
2594
  ddlObj.value = null;
@@ -2412,7 +2596,13 @@ let QueryBuilder = class QueryBuilder extends Component {
2412
2596
  ddlObj.dataSource = itemData.operators;
2413
2597
  ddlObj.index = this.getOperatorIndex(ddlObj, rule);
2414
2598
  ddlObj.value = tempRule.operator = ddlObj.dataSource[ddlObj.index].value;
2415
- ddlObj.dataBind();
2599
+ if (!this.autoSelectOperator) {
2600
+ ddlObj.index = -1;
2601
+ tempRule.operator = ddlObj.value = '';
2602
+ }
2603
+ else {
2604
+ ddlObj.dataBind();
2605
+ }
2416
2606
  }
2417
2607
  }
2418
2608
  const operator = tempRule.operator.toString();
@@ -2445,39 +2635,41 @@ let QueryBuilder = class QueryBuilder extends Component {
2445
2635
  this.validateValue(rule, closest(target, '.e-rule-container'));
2446
2636
  this.destroyControls(target);
2447
2637
  }
2448
- if (column) {
2449
- itemData.template = column.template;
2450
- }
2451
- if (itemData.template) {
2452
- addClass([target.nextElementSibling], 'e-template-value');
2453
- itemData.template = column.template;
2454
- isTempRendered = this.setColumnTemplate(itemData, parentId, column.field, itemData.value ||
2455
- operator, target, rule);
2456
- }
2457
- if (isTempRendered) {
2458
- const parentElem = target.parentElement.querySelector('.e-rule-value');
2459
- if (this.element.className.indexOf('e-device') > -1 || this.displayMode === 'Vertical') {
2460
- parentElem.style.width = '100%';
2461
- }
2462
- else {
2463
- parentElem.style.width = '200px';
2464
- }
2465
- }
2466
- else {
2467
- removeClass([target.nextElementSibling], 'e-template-value');
2468
- let inputLen = 1;
2469
- if (tempRule.type === 'boolean') {
2470
- inputLen = this.selectedColumn.values ? this.selectedColumn.values.length : 2;
2638
+ if (this.isImportRules || (ddlObj && ddlObj.value !== '')) {
2639
+ if (column) {
2640
+ itemData.template = column.template;
2641
+ }
2642
+ if (itemData.template) {
2643
+ addClass([target.nextElementSibling], 'e-template-value');
2644
+ itemData.template = column.template;
2645
+ isTempRendered = this.setColumnTemplate(itemData, parentId, column.field, itemData.value ||
2646
+ operator, target, rule);
2647
+ }
2648
+ if (isTempRendered) {
2649
+ const parentElem = target.parentElement.querySelector('.e-rule-value');
2650
+ if (this.element.className.indexOf('e-device') > -1 || this.displayMode === 'Vertical') {
2651
+ parentElem.style.width = '100%';
2652
+ }
2653
+ else {
2654
+ parentElem.style.width = '200px';
2655
+ }
2471
2656
  }
2472
2657
  else {
2473
- inputLen = (operator && operator.toLowerCase().indexOf('between') > -1) ? 2 : 1;
2474
- }
2475
- for (let i = 0; i < inputLen; i++) {
2476
- const valElem = this.createElement('input', { attrs: { type: 'text', id: parentId + '_valuekey' + i } });
2477
- target.nextElementSibling.appendChild(valElem);
2658
+ removeClass([target.nextElementSibling], 'e-template-value');
2659
+ let inputLen = 1;
2660
+ if (tempRule.type === 'boolean') {
2661
+ inputLen = this.selectedColumn.values ? this.selectedColumn.values.length : 2;
2662
+ }
2663
+ else {
2664
+ inputLen = (operator && operator.toLowerCase().indexOf('between') > -1) ? 2 : 1;
2665
+ }
2666
+ for (let i = 0; i < inputLen; i++) {
2667
+ const valElem = this.createElement('input', { attrs: { type: 'text', id: parentId + '_valuekey' + i } });
2668
+ target.nextElementSibling.appendChild(valElem);
2669
+ }
2478
2670
  }
2671
+ this.renderControls(target, itemData, rule, tempRule, isTempRendered);
2479
2672
  }
2480
- this.renderControls(target, itemData, rule, tempRule, isTempRendered);
2481
2673
  }
2482
2674
  else {
2483
2675
  const parentElem = target.parentElement.querySelector('.e-rule-value');
@@ -2910,8 +3102,8 @@ let QueryBuilder = class QueryBuilder extends Component {
2910
3102
  let i;
2911
3103
  let len;
2912
3104
  let tooltip;
2913
- let popupElement;
2914
3105
  super.destroy();
3106
+ let popupElement;
2915
3107
  element = this.element.querySelectorAll('.e-addrulegroup');
2916
3108
  len = element.length;
2917
3109
  for (i = 0; i < len; i++) {
@@ -2997,7 +3189,8 @@ let QueryBuilder = class QueryBuilder extends Component {
2997
3189
  if (grouplen) {
2998
3190
  this.isPublic = true;
2999
3191
  for (let i = 0, len = groups.length; i < len; i++) {
3000
- this.updatedRule = { condition: groups[i].condition, not: groups[i].not };
3192
+ this.updatedRule = { isLocked: groups[i].isLocked, condition: groups[i].condition,
3193
+ not: groups[i].not };
3001
3194
  this.importRules(groups[i], groupElem, false, groups[i].not);
3002
3195
  }
3003
3196
  this.isPublic = false;
@@ -3005,15 +3198,27 @@ let QueryBuilder = class QueryBuilder extends Component {
3005
3198
  else {
3006
3199
  let condition = 'and';
3007
3200
  let not = false;
3201
+ let isLocked = false;
3008
3202
  if (this.updatedRule) {
3009
3203
  condition = this.updatedRule.condition;
3010
3204
  not = this.updatedRule.not;
3205
+ isLocked = this.updatedRule.isLocked;
3011
3206
  }
3012
- if (this.enableNotCondition) {
3013
- rule.rules.push({ 'condition': condition, 'not': not, rules: [] });
3207
+ if (this.groupIndex < 0) {
3208
+ if (this.enableNotCondition) {
3209
+ rule.rules.push({ 'condition': condition, 'not': not, rules: [] });
3210
+ }
3211
+ else {
3212
+ rule.rules.push({ 'condition': condition, rules: [] });
3213
+ }
3014
3214
  }
3015
3215
  else {
3016
- rule.rules.push({ 'condition': condition, rules: [] });
3216
+ if (this.enableNotCondition) {
3217
+ rule.rules.splice(this.groupIndex + 1, 0, { condition: condition, not: not, rules: [], isLocked: isLocked });
3218
+ }
3219
+ else {
3220
+ rule.rules.splice(this.groupIndex + 1, 0, { condition: condition, rules: [], isLocked: isLocked });
3221
+ }
3017
3222
  }
3018
3223
  }
3019
3224
  if (!this.headerTemplate) {
@@ -3195,17 +3400,53 @@ let QueryBuilder = class QueryBuilder extends Component {
3195
3400
  this.refresh();
3196
3401
  break;
3197
3402
  case 'showButtons':
3198
- if (newProp.showButtons.ruleDelete) {
3199
- removeClass(this.element.querySelectorAll('.e-rule-delete'), 'e-button-hide');
3403
+ if (!isNullOrUndefined(newProp.showButtons.lockGroup)) {
3404
+ if (newProp.showButtons.lockGroup) {
3405
+ removeClass(this.element.querySelectorAll('.e-lock-grp-btn'), 'e-button-hide');
3406
+ }
3407
+ else {
3408
+ addClass(this.element.querySelectorAll('.e-lock-grp-btn'), 'e-button-hide');
3409
+ }
3200
3410
  }
3201
- else {
3202
- addClass(this.element.querySelectorAll('.e-rule-delete'), 'e-button-hide');
3411
+ if (!isNullOrUndefined(newProp.showButtons.lockRule)) {
3412
+ if (newProp.showButtons.lockRule) {
3413
+ removeClass(this.element.querySelectorAll('.e-lock-rule-btn'), 'e-button-hide');
3414
+ }
3415
+ else {
3416
+ addClass(this.element.querySelectorAll('.e-lock-rule-btn'), 'e-button-hide');
3417
+ }
3203
3418
  }
3204
- if (newProp.showButtons.groupDelete) {
3205
- removeClass(this.element.querySelectorAll('.e-deletegroup'), 'e-button-hide');
3419
+ if (!isNullOrUndefined(newProp.showButtons.cloneGroup)) {
3420
+ if (newProp.showButtons.cloneGroup) {
3421
+ removeClass(this.element.querySelectorAll('.e-clone-grp-btn'), 'e-button-hide');
3422
+ }
3423
+ else {
3424
+ addClass(this.element.querySelectorAll('.e-clone-grp-btn'), 'e-button-hide');
3425
+ }
3206
3426
  }
3207
- else {
3208
- addClass(this.element.querySelectorAll('.e-deletegroup'), 'e-button-hide');
3427
+ if (!isNullOrUndefined(newProp.showButtons.cloneRule)) {
3428
+ if (newProp.showButtons.cloneRule) {
3429
+ removeClass(this.element.querySelectorAll('.e-clone-rule-btn'), 'e-button-hide');
3430
+ }
3431
+ else {
3432
+ addClass(this.element.querySelectorAll('.e-clone-rule-btn'), 'e-button-hide');
3433
+ }
3434
+ }
3435
+ if (!isNullOrUndefined(newProp.showButtons.ruleDelete)) {
3436
+ if (newProp.showButtons.ruleDelete) {
3437
+ removeClass(this.element.querySelectorAll('.e-rule-delete'), 'e-button-hide');
3438
+ }
3439
+ else {
3440
+ addClass(this.element.querySelectorAll('.e-rule-delete'), 'e-button-hide');
3441
+ }
3442
+ }
3443
+ if (!isNullOrUndefined(newProp.showButtons.groupDelete)) {
3444
+ if (newProp.showButtons.groupDelete) {
3445
+ removeClass(this.element.querySelectorAll('.e-deletegroup'), 'e-button-hide');
3446
+ }
3447
+ else {
3448
+ addClass(this.element.querySelectorAll('.e-deletegroup'), 'e-button-hide');
3449
+ }
3209
3450
  }
3210
3451
  break;
3211
3452
  case 'cssClass':
@@ -3282,8 +3523,11 @@ let QueryBuilder = class QueryBuilder extends Component {
3282
3523
  this.element.id = this.element.id || getUniqueID('ej2-querybuilder');
3283
3524
  this.defaultLocale = {
3284
3525
  StartsWith: 'Starts With',
3526
+ DoesNotStartWith: 'Does Not Start With',
3285
3527
  EndsWith: 'Ends With',
3528
+ DoesNotEndWith: 'Does Not End With',
3286
3529
  Contains: 'Contains',
3530
+ DoesNotContain: 'Does Not Contain',
3287
3531
  NotLike: 'Not Like',
3288
3532
  Like: 'Like',
3289
3533
  Equal: 'Equal',
@@ -3317,7 +3561,13 @@ let QueryBuilder = class QueryBuilder extends Component {
3317
3561
  IsNotNull: 'Is Not Null',
3318
3562
  True: 'true',
3319
3563
  False: 'false',
3320
- AddButton: 'Add Group/Condition'
3564
+ AddButton: 'Add Group/Condition',
3565
+ CloneGroup: 'Clone Group',
3566
+ LockGroup: 'Lock Group',
3567
+ CloneRule: 'Clone Rule',
3568
+ LockRule: 'Lock Rule',
3569
+ UnlockRule: 'Unlock Rule',
3570
+ UnlockGroup: 'Unlock Group'
3321
3571
  };
3322
3572
  this.l10n = new L10n('querybuilder', this.defaultLocale, this.locale);
3323
3573
  this.intl = new Internationalization(this.locale);
@@ -3330,8 +3580,11 @@ let QueryBuilder = class QueryBuilder extends Component {
3330
3580
  this.customOperators = {
3331
3581
  stringOperator: [
3332
3582
  { value: 'startswith', key: this.l10n.getConstant('StartsWith') },
3583
+ { value: 'notstartswith', key: this.l10n.getConstant('DoesNotStartWith') },
3333
3584
  { value: 'endswith', key: this.l10n.getConstant('EndsWith') },
3585
+ { value: 'notendswith', key: this.l10n.getConstant('DoesNotEndWith') },
3334
3586
  { value: 'contains', key: this.l10n.getConstant('Contains') },
3587
+ { value: 'notcontains', key: this.l10n.getConstant('DoesNotContain') },
3335
3588
  { value: 'equal', key: this.l10n.getConstant('Equal') },
3336
3589
  { value: 'notequal', key: this.l10n.getConstant('NotEqual') },
3337
3590
  { value: 'in', key: this.l10n.getConstant('In') },
@@ -3345,7 +3598,9 @@ let QueryBuilder = class QueryBuilder extends Component {
3345
3598
  { value: 'greaterthanorequal', key: this.l10n.getConstant('GreaterThanOrEqual') },
3346
3599
  { value: 'lessthan', key: this.l10n.getConstant('LessThan') },
3347
3600
  { value: 'lessthanorequal', key: this.l10n.getConstant('LessThanOrEqual') },
3348
- { value: 'notequal', key: this.l10n.getConstant('NotEqual') }
3601
+ { value: 'notequal', key: this.l10n.getConstant('NotEqual') },
3602
+ { value: 'between', key: this.l10n.getConstant('Between') },
3603
+ { value: 'notbetween', key: this.l10n.getConstant('NotBetween') }
3349
3604
  ],
3350
3605
  booleanOperator: [
3351
3606
  { value: 'equal', key: this.l10n.getConstant('Equal') },
@@ -3667,6 +3922,10 @@ let QueryBuilder = class QueryBuilder extends Component {
3667
3922
  this.setProperties({ rule: rule }, true);
3668
3923
  rule = this.getRuleCollection(this.rule, false);
3669
3924
  this.importRules(this.rule, this.element.querySelector('.e-group-container'), true, this.rule.not, isRoot);
3925
+ if (rule.isLocked) {
3926
+ const lockGrpTarget = this.element.querySelector('.e-group-container').querySelector('.e-lock-grp-btn');
3927
+ this.groupLock(lockGrpTarget);
3928
+ }
3670
3929
  this.isImportRules = false;
3671
3930
  }
3672
3931
  keyBoardHandler(e) {
@@ -3762,7 +4021,8 @@ let QueryBuilder = class QueryBuilder extends Component {
3762
4021
  rule.value !== undefined)) || (customObj && customObj.isQuestion)) {
3763
4022
  const condition = rule.condition;
3764
4023
  rule = {
3765
- 'label': rule.label, 'field': rule.field, 'operator': rule.operator, 'type': rule.type, 'value': rule.value
4024
+ 'label': rule.label, 'field': rule.field, 'operator': rule.operator, 'type': rule.type, 'value': rule.value,
4025
+ 'isLocked': rule.isLocked
3766
4026
  };
3767
4027
  if (condition) {
3768
4028
  rule.condition = condition;
@@ -3771,6 +4031,7 @@ let QueryBuilder = class QueryBuilder extends Component {
3771
4031
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3772
4032
  rule.custom = customObj;
3773
4033
  }
4034
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3774
4035
  if ((rule.operator === 'in' || rule.operator === 'notin') && rule.value && rule.value.length === 0) {
3775
4036
  rule = {};
3776
4037
  }
@@ -3796,10 +4057,10 @@ let QueryBuilder = class QueryBuilder extends Component {
3796
4057
  }
3797
4058
  else {
3798
4059
  if (this.enableNotCondition) {
3799
- rule = { 'condition': rule.condition, 'rules': rule.rules, 'not': rule.not };
4060
+ rule = { 'condition': rule.condition, 'rules': rule.rules, 'not': rule.not, 'isLocked': rule.isLocked };
3800
4061
  }
3801
4062
  else {
3802
- rule = { 'condition': rule.condition, 'rules': rule.rules };
4063
+ rule = { 'condition': rule.condition, 'rules': rule.rules, 'isLocked': rule.isLocked };
3803
4064
  }
3804
4065
  if (customObj) {
3805
4066
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -3964,11 +4225,20 @@ let QueryBuilder = class QueryBuilder extends Component {
3964
4225
  let ruleValue;
3965
4226
  let ignoreCase = false;
3966
4227
  let column;
3967
- const ignoreOper = ['notcontains', 'notstartswith', 'notendswith'];
3968
4228
  if (!ruleColl) {
3969
4229
  return pred;
3970
4230
  }
3971
4231
  for (let i = 0, len = ruleColl.length; i < len; i++) {
4232
+ let operator = ruleColl[i].operator;
4233
+ if (operator === 'notstartswith') {
4234
+ operator = 'doesnotstartwith';
4235
+ }
4236
+ else if (operator === 'notendswith') {
4237
+ operator = 'doesnotendwith';
4238
+ }
4239
+ else if (operator === 'notcontains') {
4240
+ operator = 'doesnotcontain';
4241
+ }
3972
4242
  const keys = Object.keys(ruleColl[i]);
3973
4243
  ignoreCase = false;
3974
4244
  if (keys.indexOf('rules') > -1 && ruleColl[i].rules) {
@@ -3987,7 +4257,7 @@ let QueryBuilder = class QueryBuilder extends Component {
3987
4257
  }
3988
4258
  }
3989
4259
  }
3990
- else if (!isNullOrUndefined(ruleColl[i].operator) && !isNullOrUndefined(ruleColl[i].operator.length)) {
4260
+ else if (!isNullOrUndefined(operator) && !isNullOrUndefined(operator.length)) {
3991
4261
  const oper = ruleColl[i].operator.toLowerCase();
3992
4262
  let isDateFilter = false;
3993
4263
  const dateOperColl = ['equal', 'notequal', 'greaterthan', 'greaterthanorequal', 'lessthan', 'lessthanorequal'];
@@ -4018,23 +4288,20 @@ let QueryBuilder = class QueryBuilder extends Component {
4018
4288
  }
4019
4289
  if (i === 0) {
4020
4290
  if (isDateFilter || (oper.indexOf('in') > -1 || oper.indexOf('between') > -1 || oper.indexOf('null') > -1 ||
4021
- oper.indexOf('empty') > -1) && oper.indexOf('contains') < 0) {
4291
+ oper.indexOf('empty') > -1) && (oper.indexOf('contain') < 0)) {
4022
4292
  pred = isDateFilter ? this.datePredicate(ruleColl[i], ruleValue) :
4023
4293
  this.arrayPredicate(ruleColl[i]);
4024
4294
  }
4025
4295
  else {
4026
4296
  const value = ruleValue;
4027
- if (value !== '' && ignoreOper.indexOf(oper) < 0) {
4028
- pred = new Predicate(ruleColl[i].field, ruleColl[i].operator, ruleValue, ignoreCase);
4297
+ if (value !== '') {
4298
+ pred = new Predicate(ruleColl[i].field, operator, ruleValue, ignoreCase);
4029
4299
  }
4030
4300
  }
4031
4301
  }
4032
4302
  else {
4033
- if (ignoreOper.indexOf(oper) > -1) {
4034
- continue;
4035
- }
4036
4303
  if (isDateFilter || (oper.indexOf('in') > -1 || oper.indexOf('between') > -1 ||
4037
- oper.indexOf('null') > -1 || oper.indexOf('empty') > -1) && oper.indexOf('contains') < 0) {
4304
+ oper.indexOf('null') > -1 || oper.indexOf('empty') > -1) && oper.indexOf('contain') < 0) {
4038
4305
  pred = isDateFilter ? this.datePredicate(ruleColl[i], ruleValue, pred, rule.condition) :
4039
4306
  this.arrayPredicate(ruleColl[i], pred, rule.condition);
4040
4307
  }
@@ -4043,19 +4310,19 @@ let QueryBuilder = class QueryBuilder extends Component {
4043
4310
  const value = ruleValue;
4044
4311
  if (pred && value !== '') {
4045
4312
  pred
4046
- = pred.and(ruleColl[i].field, ruleColl[i].operator, ruleValue, ignoreCase);
4313
+ = pred.and(ruleColl[i].field, operator, ruleValue, ignoreCase);
4047
4314
  }
4048
4315
  else if (value !== '') {
4049
- pred = new Predicate(ruleColl[i].field, ruleColl[i].operator, ruleValue, ignoreCase);
4316
+ pred = new Predicate(ruleColl[i].field, operator, ruleValue, ignoreCase);
4050
4317
  }
4051
4318
  }
4052
4319
  else {
4053
4320
  const value = ruleValue;
4054
4321
  if (pred && value !== '') {
4055
- pred = pred.or(ruleColl[i].field, ruleColl[i].operator, ruleValue, ignoreCase);
4322
+ pred = pred.or(ruleColl[i].field, operator, ruleValue, ignoreCase);
4056
4323
  }
4057
4324
  else if (value !== '') {
4058
- pred = new Predicate(ruleColl[i].field, ruleColl[i].operator, ruleValue, ignoreCase);
4325
+ pred = new Predicate(ruleColl[i].field, operator, ruleValue, ignoreCase);
4059
4326
  }
4060
4327
  }
4061
4328
  }
@@ -4335,15 +4602,28 @@ let QueryBuilder = class QueryBuilder extends Component {
4335
4602
  for (let i = 0, len = ruleColl.length; i < len; i++) {
4336
4603
  const keys = Object.keys(ruleColl[i]);
4337
4604
  if (!isNullOrUndefined(ruleColl[i].rules) && keys.indexOf('rules') > -1 && (ruleColl[i].rules.length !== 0)) {
4605
+ if (this.element.querySelectorAll('.e-group-container').length > this.maxGroupCount) {
4606
+ return null;
4607
+ }
4338
4608
  parentElem = this.renderGroup(ruleColl[i], ruleColl[i].condition, parentElem, ruleColl[i].not);
4339
4609
  parentElem = this.importRules(ruleColl[i], parentElem, true);
4340
4610
  }
4341
4611
  else {
4342
4612
  this.renderRule(ruleColl[i], parentElem);
4343
4613
  }
4614
+ if (!isNullOrUndefined(ruleColl[i].rules) && ruleColl[i].isLocked) {
4615
+ const lockGrpTarget = parentElem.querySelector('.e-rule-list').children[i].querySelector('.e-lock-grp-btn');
4616
+ this.groupLock(lockGrpTarget);
4617
+ }
4618
+ if (isNullOrUndefined(ruleColl[i].rules) && ruleColl[i].isLocked) {
4619
+ const lockRuleTarget = parentElem.querySelector('.e-rule-list').children[i].querySelector('.e-lock-rule-btn');
4620
+ this.ruleLock(lockRuleTarget);
4621
+ }
4344
4622
  }
4345
4623
  }
4346
- parentElem = closest(parentElem, '.e-rule-list');
4624
+ if (parentElem) {
4625
+ parentElem = closest(parentElem, '.e-rule-list');
4626
+ }
4347
4627
  if (parentElem) {
4348
4628
  parentElem = closest(parentElem, '.e-group-container');
4349
4629
  }
@@ -4352,7 +4632,20 @@ let QueryBuilder = class QueryBuilder extends Component {
4352
4632
  renderGroup(rule, condition, parentElem, not, isRoot) {
4353
4633
  this.addGroupElement(true, parentElem, condition, false, not, isRoot, rule); //Child group
4354
4634
  const element = parentElem.querySelectorAll('.e-group-container');
4355
- return element[element.length - 1];
4635
+ const cloneElem = parentElem.querySelector('.e-rule-list').children;
4636
+ if (this.showButtons.cloneGroup && this.cloneGrpBtnClick && this.isMiddleGroup) {
4637
+ this.isMiddleGroup = false;
4638
+ this.cloneGrpBtnClick = false;
4639
+ return cloneElem[this.groupIndex + 1]; // group added in the middle
4640
+ }
4641
+ else if (this.showButtons.cloneGroup && this.cloneGrpBtnClick && this.isLastGroup) {
4642
+ this.isLastGroup = false;
4643
+ this.cloneGrpBtnClick = false;
4644
+ return cloneElem[cloneElem.length - 1]; // group added in the end
4645
+ }
4646
+ else {
4647
+ return element[element.length - 1];
4648
+ }
4356
4649
  }
4357
4650
  renderRule(rule, parentElem) {
4358
4651
  if (parentElem.className.indexOf('e-group-container') > -1) {
@@ -4550,15 +4843,19 @@ let QueryBuilder = class QueryBuilder extends Component {
4550
4843
  valueStr += rule.value ? '("%' + rule.value + '%")' : '(' + rule.value + ')';
4551
4844
  }
4552
4845
  else {
4553
- if (rule.type === 'number' || typeof rule.value === 'boolean' || rule.value === null) {
4846
+ if (rule.type === 'number' || typeof rule.value === 'boolean' ||
4847
+ (rule.value === null && (rule.operator.toString().indexOf('empty') < -1))) {
4554
4848
  valueStr += rule.value;
4555
4849
  }
4850
+ else if (rule.operator.toString().indexOf('empty') > -1) {
4851
+ valueStr += '""';
4852
+ }
4556
4853
  else {
4557
4854
  valueStr += '"' + rule.value + '"';
4558
4855
  }
4559
4856
  }
4560
4857
  }
4561
- if (rule.operator.toString().indexOf('null') > -1 || (rule.operator.toString().indexOf('empty') > -1)) {
4858
+ if (rule.operator.toString().indexOf('null') > -1) {
4562
4859
  if (enableEscape) {
4563
4860
  rule.field = '`' + rule.field + '`';
4564
4861
  }
@@ -4570,6 +4867,13 @@ let QueryBuilder = class QueryBuilder extends Component {
4570
4867
  queryStr += rule.field + ' ' + ruleOpertor;
4571
4868
  }
4572
4869
  else {
4870
+ let custOper = ruleOpertor;
4871
+ if (rule.operator === 'isempty') {
4872
+ custOper = '=';
4873
+ }
4874
+ else if (rule.operator === 'isnotempty') {
4875
+ custOper = '!=';
4876
+ }
4573
4877
  if (enableEscape) {
4574
4878
  rule.field = '`' + rule.field + '`';
4575
4879
  }
@@ -4578,7 +4882,7 @@ let QueryBuilder = class QueryBuilder extends Component {
4578
4882
  rule.field = '"' + rule.field + '"';
4579
4883
  }
4580
4884
  }
4581
- queryStr += rule.field + ' ' + ruleOpertor + ' ' + valueStr;
4885
+ queryStr += rule.field + ' ' + custOper + ' ' + valueStr;
4582
4886
  }
4583
4887
  if (rule.condition && rule.condition !== '') {
4584
4888
  condition = rule.condition;
@@ -4608,7 +4912,7 @@ let QueryBuilder = class QueryBuilder extends Component {
4608
4912
  * Sets the rules from the sql query.
4609
4913
  *
4610
4914
  * @param {string} sqlString - 'sql String' to be passed to set the rule.
4611
- * @param {boolean} sqlLocale - Set `true` if Localization for Sql query.
4915
+ * @param {boolean} sqlLocale - Optional. Set `true` if Localization for Sql query.
4612
4916
  * @returns {void}
4613
4917
  */
4614
4918
  setRulesFromSql(sqlString, sqlLocale) {
@@ -4640,15 +4944,163 @@ let QueryBuilder = class QueryBuilder extends Component {
4640
4944
  *
4641
4945
  * @param {RuleModel} rule - 'rule' to be passed to get the sql.
4642
4946
  * @param {boolean} allowEscape - Set `true` if it exclude the escape character.
4643
- * @param {boolean} sqlLocale - Set `true` if Localization for Sql query.
4644
- * @returns {object} - Sql query from rules.
4947
+ * @param {boolean} sqlLocale - Set `true` if Localization for Sql query.
4948
+ * @returns {string} - Sql query from rules.
4645
4949
  */
4646
4950
  getSqlFromRules(rule, allowEscape, sqlLocale) {
4647
4951
  if (!rule) {
4648
4952
  rule = this.getValidRules();
4649
4953
  }
4650
4954
  rule = this.getRuleCollection(rule, false);
4651
- return this.getSqlString(this.getValidRules(rule), allowEscape, null, sqlLocale).replace(/"/g, '\'');
4955
+ const sqlString = this.getSqlString(this.getValidRules(rule), allowEscape, null, sqlLocale).replace(/"/g, '\'');
4956
+ return sqlString;
4957
+ }
4958
+ /**
4959
+ * Gets the parameter SQL query from rules.
4960
+ *
4961
+ * @param {RuleModel} rule – Specify the rule to be passed to get the parameter sql string.
4962
+ * @returns {ParameterizedSql} – Parameterized SQL query from rules.
4963
+ */
4964
+ getParameterizedSql(rule) {
4965
+ if (!rule) {
4966
+ rule = this.getValidRules();
4967
+ }
4968
+ const obj = { sql: null };
4969
+ this.notify('query-library', { prop: 'getParameterSql', onPropertyChange: false, value: { rule: rule, obj: obj } });
4970
+ return obj['sql'];
4971
+ }
4972
+ /**
4973
+ * Sets the rules from the parameter sql query.
4974
+ *
4975
+ * @param { ParameterizedSql} sqlQuery – Specifies the parameter SQL to be passed to set the rule and load it to the query builder.
4976
+ * @returns {void}
4977
+ */
4978
+ setParameterizedSql(sqlQuery) {
4979
+ const obj = { sql: null };
4980
+ this.notify('query-library', { prop: 'convertParamSqlToSql', onPropertyChange: false, value: { sql: sqlQuery, obj: obj } });
4981
+ let sql = obj['sql'];
4982
+ if (sql) {
4983
+ sql = sql.replace(/`/g, '');
4984
+ const ruleModel = this.getRulesFromSql(sql);
4985
+ this.setRules({ condition: ruleModel.condition, not: ruleModel.not, rules: ruleModel.rules });
4986
+ }
4987
+ }
4988
+ /**
4989
+ * Gets the named parameter SQL query from rules.
4990
+ *
4991
+ * @param {RuleModel} rule – Specify the rule to be passed to get the named parameter SQL string.
4992
+ * @returns {ParameterizedNamedSql} – Parameterized Named SQL query from rules.
4993
+ */
4994
+ getParameterizedNamedSql(rule) {
4995
+ if (!rule) {
4996
+ rule = this.getValidRules();
4997
+ }
4998
+ const obj = { sql: null };
4999
+ this.notify('query-library', { prop: 'getNamedParameterSql', onPropertyChange: false, value: { rule: rule, obj: obj } });
5000
+ return obj['sql'];
5001
+ }
5002
+ /**
5003
+ * Sets the rules from the named parameter SQL query.
5004
+ *
5005
+ * @param { ParameterizedNamedSql } sqlQuery – Specifies the named parameter SQL to be passed to set the rule and load it to the query builder.
5006
+ * @returns {void}
5007
+ */
5008
+ setParameterizedNamedSql(sqlQuery) {
5009
+ const obj = { sql: null };
5010
+ this.notify('query-library', { prop: 'convertNamedParamSqlToSql', onPropertyChange: false, value: { sql: sqlQuery, obj: obj } });
5011
+ let sql = obj['sql'];
5012
+ if (sql) {
5013
+ sql = sql.replace(/`/g, '');
5014
+ const ruleModel = this.getRulesFromSql(sql);
5015
+ this.setRules({ condition: ruleModel.condition, not: ruleModel.not, rules: ruleModel.rules });
5016
+ }
5017
+ }
5018
+ /**
5019
+ * Set the rules from Mongo query.
5020
+ *
5021
+ * @param {string} mongoQuery - 'sql String' to be passed to get the rule.
5022
+ * @param {boolean} mongoLocale - Set `true` if Localization for Mongo query.
5023
+ * @returns {void}
5024
+ */
5025
+ setMongoQuery(mongoQuery, mongoLocale) {
5026
+ this.rule = { condition: 'and', not: false, rules: [] };
5027
+ this.notify('query-library', { prop: 'mongoParser', onPropertyChange: false, value: { mongoQuery: JSON.parse(mongoQuery), rule: this.rule, mongoLocale: mongoLocale } });
5028
+ }
5029
+ /**
5030
+ * Gets the Mongo query from rules.
5031
+ *
5032
+ * @param {RuleModel} rule - 'rule' to be passed to get the sql.
5033
+ * @returns {object} - Sql query from rules.
5034
+ */
5035
+ getMongoQuery(rule) {
5036
+ if (!rule) {
5037
+ rule = this.getValidRules();
5038
+ }
5039
+ const obj = { mongoQuery: null };
5040
+ this.notify('query-library', { prop: 'getMongoFromRules', onPropertyChange: false, value: { rule: rule, mongoQuery: '', obj: obj } });
5041
+ return obj['mongoQuery'];
5042
+ }
5043
+ /**
5044
+ * Clones the rule based on the rule ID to the specific group.
5045
+ *
5046
+ * @param {string} ruleID - Specifies the ruleID that needs to be cloned.
5047
+ * @param {string} groupID - Specifies the groupID in which the rule to be cloned.
5048
+ * @param {number} index - Specifies the index to insert the cloned rule inside the group.
5049
+ * @returns {void}
5050
+ */
5051
+ cloneRule(ruleID, groupID, index) {
5052
+ const getRule = this.getRule(ruleID.replace(this.element.id + '_', ''));
5053
+ groupID = groupID.replace(this.element.id + '_', '');
5054
+ this.ruleIndex = index;
5055
+ this.cloneRuleBtnClick = true;
5056
+ this.showButtons.cloneRule = true;
5057
+ this.addRules([{
5058
+ 'label': getRule.label, 'field': getRule.field, 'type': getRule.type, 'operator': getRule.operator,
5059
+ 'value': getRule.value
5060
+ }], groupID);
5061
+ this.ruleIndex = -1;
5062
+ this.cloneRuleBtnClick = false;
5063
+ this.showButtons.cloneRule = false;
5064
+ }
5065
+ /**
5066
+ * Clones the group based on the group ID to the specific group.
5067
+ *
5068
+ * @param {string} groupID - Specifies the groupID that needs to be cloned.
5069
+ * @param {string} parentGroupID - Specifies the parentGroupID in which the group to be cloned.
5070
+ * @param {number} index - Specifies the index to insert the cloned group inside the parent group.
5071
+ * @returns {void}
5072
+ */
5073
+ cloneGroup(groupID, parentGroupID, index) {
5074
+ parentGroupID = parentGroupID.replace(this.element.id + '_', '');
5075
+ const group = this.getGroup(parentGroupID);
5076
+ groupID = groupID.replace(this.element.id + '_', '');
5077
+ this.groupIndex = index;
5078
+ this.cloneGrpBtnClick = true;
5079
+ this.showButtons.cloneGroup = true;
5080
+ this.addGroups([{ 'condition': group.condition, 'not': group.not, 'rules': group.rules }], groupID);
5081
+ this.groupIndex = -1;
5082
+ this.cloneGrpBtnClick = false;
5083
+ this.showButtons.cloneGroup = false;
5084
+ }
5085
+ /**
5086
+ * Locks the rule based on the rule ID.
5087
+ *
5088
+ * @param {string} ruleID - Specifies the ruleID that needs to be locked.
5089
+ * @returns {void}
5090
+ */
5091
+ lockRule(ruleID) {
5092
+ const target = document.getElementById(ruleID).querySelectorAll('.e-lock-rule-btn')[0];
5093
+ this.ruleLock(target);
5094
+ }
5095
+ /**
5096
+ * Locks the group based on the group ID
5097
+ *
5098
+ * @param {string} groupID - Specifies the groupID that needs to be locked.
5099
+ * @returns {void}
5100
+ */
5101
+ lockGroup(groupID) {
5102
+ const target = document.getElementById(groupID).querySelectorAll('.e-lock-grp-btn')[0];
5103
+ this.groupLock(target);
4652
5104
  }
4653
5105
  sqlParser(sqlString, sqlLocale) {
4654
5106
  let st = 0;
@@ -4850,13 +5302,13 @@ let QueryBuilder = class QueryBuilder extends Component {
4850
5302
  for (let i = 0; i < localeOperator.length; i++) {
4851
5303
  if (this.sqlOperators[localeOperator[i]] === operator.toUpperCase()) {
4852
5304
  if (value && value.indexOf('%') === 0 && value[value.length - 1] === '%') {
4853
- return (localeOperator[i] === 'notcontains') ? 'notcontains' : 'contains';
5305
+ return (operator.toUpperCase() === 'NOT LIKE') ? 'notcontains' : 'contains';
4854
5306
  }
4855
5307
  else if (value && value.indexOf('%') !== 0 && value.indexOf('%') === value.length - 1) {
4856
- return (localeOperator[i] === 'notstartswith') ? 'notstartswith' : 'startswith';
5308
+ return (operator.toUpperCase() === 'NOT LIKE') ? 'notstartswith' : 'startswith';
4857
5309
  }
4858
5310
  else if (value && value.indexOf('%') === 0 && value.indexOf('%') !== value.length - 1) {
4859
- return (localeOperator[i] === 'notendswith') ? 'notendswith' : 'endswith';
5311
+ return (operator.toUpperCase() === 'NOT LIKE') ? 'notendswith' : 'endswith';
4860
5312
  }
4861
5313
  return localeOperator[i];
4862
5314
  }
@@ -5041,6 +5493,14 @@ let QueryBuilder = class QueryBuilder extends Component {
5041
5493
  }
5042
5494
  else if (parser[i + 1][0] === 'Operators') {
5043
5495
  rule.operator = this.getOperator(parser[i + 2][1], parser[i + 1][1], sqlLocale);
5496
+ if (rule.operator == "equal" && parser[i + 2][0] === "String" && parser[i + 2][1] === "''") {
5497
+ rule.operator = "isempty";
5498
+
5499
+ }
5500
+ else if (rule.operator == "notequal" && parser[i + 2][0] === "String" && parser[i + 2][1] === "''") {
5501
+ rule.operator = "isnotempty";
5502
+
5503
+ }
5044
5504
  if (parser[i + 2][0] === 'Number') {
5045
5505
  rule.type = 'number';
5046
5506
  rule.value = Number(parser[i + 2][1]);
@@ -5097,35 +5557,330 @@ let QueryBuilder = class QueryBuilder extends Component {
5097
5557
  }
5098
5558
  return rules;
5099
5559
  }
5100
- };
5101
- __decorate([
5102
- Event()
5103
- ], QueryBuilder.prototype, "created", void 0);
5104
- __decorate([
5105
- Event()
5106
- ], QueryBuilder.prototype, "actionBegin", void 0);
5107
- __decorate([
5108
- Event()
5109
- ], QueryBuilder.prototype, "beforeChange", void 0);
5110
- __decorate([
5111
- Event()
5112
- ], QueryBuilder.prototype, "change", void 0);
5113
- __decorate([
5114
- Event()
5115
- ], QueryBuilder.prototype, "dataBound", void 0);
5116
- __decorate([
5117
- Event()
5118
- ], QueryBuilder.prototype, "ruleChange", void 0);
5119
- __decorate([
5120
- Property({ ruleDelete: true, groupInsert: true, groupDelete: true })
5121
- ], QueryBuilder.prototype, "showButtons", void 0);
5122
- __decorate([
5123
- Property(false)
5124
- ], QueryBuilder.prototype, "summaryView", void 0);
5125
- __decorate([
5126
- Property(false)
5127
- ], QueryBuilder.prototype, "allowValidation", void 0);
5128
- __decorate([
5560
+ /**
5561
+ * Clone the Group
5562
+ *
5563
+ * @param {Element | string} target - 'target' to be passed to clone the group.
5564
+ * @returns {void}
5565
+ */
5566
+ groupClone(target) {
5567
+ const groupElem = target.closest('.e-rule-list').closest('.e-group-container');
5568
+ let targetGrpId;
5569
+ let groupId;
5570
+ if (typeof target === 'string') {
5571
+ groupId = this.element.id + '_' + target;
5572
+ target = document.getElementById(groupId);
5573
+ }
5574
+ else {
5575
+ targetGrpId = target.id.replace(this.element.id + '_', '');
5576
+ groupId = groupElem.id.replace(this.element.id + '_', '');
5577
+ }
5578
+ const group = this.getGroup(targetGrpId);
5579
+ this.groupIndex = Array.prototype.indexOf.call(target.closest('.e-rule-list').children, target.closest('.e-group-container'));
5580
+ this.addGroups([{ 'condition': group.condition, 'not': group.not, 'rules': group.rules }], groupId);
5581
+ this.groupIndex = -1;
5582
+ }
5583
+ ruleClone(target) {
5584
+ const ruleElem = closest(target, '.e-rule-container');
5585
+ const groupElem = target.closest('.e-rule-list').closest('.e-group-container');
5586
+ const getRule = this.getRule(target);
5587
+ const groupId = groupElem.id.replace(this.element.id + '_', '');
5588
+ const ruleElemColl = groupElem.querySelectorAll('.e-rule-container');
5589
+ for (let i = 0, iLen = ruleElemColl.length; i < iLen; i++) {
5590
+ if (ruleElem.id === ruleElemColl[i].id) {
5591
+ this.ruleIndex = i;
5592
+ }
5593
+ }
5594
+ this.addRules([{ 'label': getRule.label, 'field': getRule.field, 'type': getRule.type, 'operator': getRule.operator,
5595
+ 'value': getRule.value }], groupId);
5596
+ this.ruleIndex = -1;
5597
+ }
5598
+ ruleLock(target) {
5599
+ const ruleElem = closest(target, '.e-rule-container');
5600
+ const rule = this.getRule(ruleElem.id.replace(this.element.id + '_', ''));
5601
+ if (ruleElem.classList.contains('e-disable')) {
5602
+ rule.isLocked = false;
5603
+ this.lockItems = this.lockItems.filter(lockItem => lockItem !== ruleElem.id);
5604
+ ruleElem.classList.remove('e-disable');
5605
+ this.disableRuleControls(target, ruleElem, false);
5606
+ target.children[0].classList.add('e-unlock');
5607
+ target.children[0].classList.remove('e-lock');
5608
+ target.setAttribute('title', this.l10n.getConstant('LockRule'));
5609
+ }
5610
+ else {
5611
+ rule.isLocked = true;
5612
+ if (this.lockItems.indexOf(ruleElem.id) < 0) {
5613
+ this.lockItems.splice(this.lockItems.length - 1, 0, ruleElem.id);
5614
+ }
5615
+ ruleElem.classList.add('e-disable');
5616
+ this.disableRuleControls(target, ruleElem, true);
5617
+ target.children[0].classList.add('e-lock');
5618
+ target.children[0].classList.remove('e-unlock');
5619
+ target.setAttribute('title', this.l10n.getConstant('UnlockRule'));
5620
+ }
5621
+ }
5622
+ groupLock(target) {
5623
+ const groupElem = closest(target, '.e-group-container');
5624
+ let group = this.getGroup(groupElem.id.replace(this.element.id + '_', ''));
5625
+ const isRoot = groupElem.id.indexOf('group0') > -1;
5626
+ if (groupElem.classList.contains('e-disable')) {
5627
+ if (isRoot) {
5628
+ const newGroup = {};
5629
+ newGroup.condition = group.condition;
5630
+ newGroup.not = group.not;
5631
+ newGroup.isLocked = false;
5632
+ this.setProperties({ rule: newGroup }, true);
5633
+ }
5634
+ else {
5635
+ group.isLocked = false;
5636
+ }
5637
+ this.lockItems = this.lockItems.filter(lockItem => lockItem !== groupElem.id);
5638
+ groupElem.classList.remove('e-disable');
5639
+ this.disableHeaderControls(target, groupElem, false);
5640
+ target.children[0].classList.add('e-unlock');
5641
+ target.children[0].classList.remove('e-lock');
5642
+ target.setAttribute('title', this.l10n.getConstant('LockGroup'));
5643
+ this.updateLockItems();
5644
+ }
5645
+ else {
5646
+ if (isRoot) {
5647
+ const newGroup = {};
5648
+ newGroup.condition = group.condition;
5649
+ newGroup.not = group.not;
5650
+ newGroup.isLocked = true;
5651
+ this.setProperties({ rule: newGroup }, true);
5652
+ }
5653
+ else {
5654
+ group.isLocked = true;
5655
+ }
5656
+ if (this.lockItems.indexOf(groupElem.id) < 0) {
5657
+ this.lockItems.splice(this.lockItems.length - 1, 0, groupElem.id);
5658
+ }
5659
+ groupElem.classList.add('e-disable');
5660
+ this.disableHeaderControls(target, groupElem, true);
5661
+ target.children[0].classList.add('e-lock');
5662
+ target.children[0].classList.remove('e-unlock');
5663
+ target.setAttribute('title', this.l10n.getConstant('UnlockGroup'));
5664
+ }
5665
+ }
5666
+ updateLockItems() {
5667
+ for (let i = 0; i < this.lockItems.length; i++) {
5668
+ const idColl = this.lockItems[i].split('_');
5669
+ if (idColl.length > 2) {
5670
+ let ruleElem = this.element.querySelector('#' + this.lockItems[i]);
5671
+ const target = ruleElem.querySelector('.e-lock-rule-btn');
5672
+ ruleElem = closest(target, '.e-rule-container');
5673
+ if (!ruleElem.classList.contains('e-disable')) {
5674
+ this.ruleLock(target);
5675
+ }
5676
+ }
5677
+ else {
5678
+ let groupElem = this.element.querySelector('#' + this.lockItems[i]);
5679
+ const target = groupElem.querySelector('.e-lock-grp-btn');
5680
+ groupElem = closest(target, '.e-group-container');
5681
+ if (!groupElem.classList.contains('e-disable')) {
5682
+ this.groupLock(target);
5683
+ }
5684
+ }
5685
+ }
5686
+ }
5687
+ disableHeaderControls(target, groupElem, isDisabled) {
5688
+ const andElem = groupElem.querySelectorAll('.e-btngroup-and');
5689
+ const orElem = groupElem.querySelectorAll('.e-btngroup-or');
5690
+ const notElem = groupElem.querySelectorAll('.e-qb-toggle');
5691
+ const addElem = groupElem.querySelectorAll('.e-add-btn');
5692
+ const deleteGrpElem = groupElem.querySelectorAll('.e-deletegroup');
5693
+ const lockElem = groupElem.querySelectorAll('.e-lock-grp-btn');
5694
+ const cloneElem = groupElem.querySelectorAll('.e-clone-grp-btn');
5695
+ const groupContElem = groupElem.querySelectorAll('.e-group-container');
5696
+ for (let i = 0; i < andElem.length; i++) {
5697
+ if (isDisabled) {
5698
+ if (groupContElem[i] && groupContElem[i].classList.contains('e-disable')) {
5699
+ groupContElem[i].classList.add('e-disable');
5700
+ }
5701
+ andElem[i].disabled = true;
5702
+ orElem[i].disabled = true;
5703
+ addElem[i].disabled = true;
5704
+ if (notElem[i]) {
5705
+ notElem[i].disabled = true;
5706
+ }
5707
+ if (deleteGrpElem[i]) {
5708
+ deleteGrpElem[i].disabled = true;
5709
+ }
5710
+ if (cloneElem[i]) {
5711
+ cloneElem[i].disabled = true;
5712
+ }
5713
+ andElem[i].parentElement.classList.add('e-disabled');
5714
+ if (lockElem[i] !== target) {
5715
+ lockElem[i].disabled = true;
5716
+ lockElem[i].children[0].classList.remove('e-unlock');
5717
+ lockElem[i].children[0].classList.add('e-lock');
5718
+ }
5719
+ }
5720
+ else {
5721
+ if (groupContElem[i]) {
5722
+ groupContElem[i].classList.remove('e-disable');
5723
+ }
5724
+ andElem[i].disabled = false;
5725
+ orElem[i].disabled = false;
5726
+ addElem[i].disabled = false;
5727
+ lockElem[i].disabled = false;
5728
+ if (notElem[i]) {
5729
+ notElem[i].disabled = false;
5730
+ }
5731
+ if (deleteGrpElem[i]) {
5732
+ deleteGrpElem[i].disabled = false;
5733
+ }
5734
+ if (cloneElem[i]) {
5735
+ cloneElem[i].disabled = false;
5736
+ }
5737
+ andElem[i].parentElement.classList.remove('e-disabled');
5738
+ lockElem[i].children[0].classList.remove('e-lock');
5739
+ lockElem[i].children[0].classList.add('e-unlock');
5740
+ }
5741
+ }
5742
+ this.disableRuleControls(target, groupElem, isDisabled);
5743
+ }
5744
+ disableRuleControls(target, groupElem, isDisabled) {
5745
+ const ddlElement = groupElem.querySelectorAll('.e-control.e-dropdownlist');
5746
+ const numericElement = groupElem.querySelectorAll('.e-control.e-numerictextbox');
5747
+ const textElement = groupElem.querySelectorAll('.e-control.e-textbox');
5748
+ const dateElement = groupElem.querySelectorAll('.e-control.e-datepicker');
5749
+ const checkboxElement = groupElem.querySelectorAll('.e-control.e-checkbox');
5750
+ const radioBtnElement = groupElem.querySelectorAll('.e-control.e-radio');
5751
+ const multiSelectElement = groupElem.querySelectorAll('.e-control.e-multiselect');
5752
+ const deleteElem = groupElem.querySelectorAll('.e-rule-delete');
5753
+ const lockElem = groupElem.querySelectorAll('.e-lock-rule');
5754
+ const cloneElem = groupElem.querySelectorAll('.e-clone-rule');
5755
+ const ruleElem = groupElem.querySelectorAll('.e-rule-container');
5756
+ for (let i = 0; i < deleteElem.length; i++) {
5757
+ if (isDisabled) {
5758
+ if (ruleElem[i] && ruleElem[i].classList.contains('e-disable')) {
5759
+ ruleElem[i].classList.add('e-disable');
5760
+ }
5761
+ deleteElem[i].disabled = true;
5762
+ if (cloneElem[i]) {
5763
+ cloneElem[i].disabled = true;
5764
+ }
5765
+ if (lockElem[i] !== target) {
5766
+ lockElem[i].disabled = true;
5767
+ lockElem[i].children[0].classList.remove('e-unlock');
5768
+ lockElem[i].children[0].classList.add('e-lock');
5769
+ }
5770
+ }
5771
+ else {
5772
+ if (ruleElem[i]) {
5773
+ ruleElem[i].classList.remove('e-disable');
5774
+ }
5775
+ if (cloneElem[i]) {
5776
+ cloneElem[i].disabled = false;
5777
+ }
5778
+ deleteElem[i].disabled = false;
5779
+ lockElem[i].disabled = false;
5780
+ lockElem[i].children[0].classList.remove('e-lock');
5781
+ lockElem[i].children[0].classList.add('e-unlock');
5782
+ }
5783
+ }
5784
+ let dropDownObj;
5785
+ let numericObj;
5786
+ let textObj;
5787
+ let dateObj;
5788
+ let checkBoxObj;
5789
+ let radioBtnObj;
5790
+ let multiSelectObj;
5791
+ for (let i = 0; i < ddlElement.length; i++) {
5792
+ dropDownObj = getComponent(ddlElement[i], 'dropdownlist');
5793
+ if (isDisabled) {
5794
+ dropDownObj.enabled = false;
5795
+ }
5796
+ else {
5797
+ dropDownObj.enabled = true;
5798
+ }
5799
+ }
5800
+ for (let i = 0; i < numericElement.length; i++) {
5801
+ numericObj = getComponent(numericElement[i], 'numerictextbox');
5802
+ if (isDisabled) {
5803
+ numericObj.enabled = false;
5804
+ }
5805
+ else {
5806
+ numericObj.enabled = true;
5807
+ }
5808
+ }
5809
+ for (let i = 0; i < textElement.length; i++) {
5810
+ textObj = getComponent(textElement[i], 'textbox');
5811
+ if (isDisabled) {
5812
+ textObj.enabled = false;
5813
+ }
5814
+ else {
5815
+ textObj.enabled = true;
5816
+ }
5817
+ }
5818
+ for (let i = 0; i < dateElement.length; i++) {
5819
+ dateObj = getComponent(dateElement[i], 'datepicker');
5820
+ if (isDisabled) {
5821
+ dateObj.enabled = false;
5822
+ }
5823
+ else {
5824
+ dateObj.enabled = true;
5825
+ }
5826
+ }
5827
+ for (let i = 0; i < checkboxElement.length; i++) {
5828
+ checkBoxObj = getComponent(checkboxElement[i], 'checkbox');
5829
+ if (isDisabled) {
5830
+ checkBoxObj.disabled = true;
5831
+ }
5832
+ else {
5833
+ checkBoxObj.disabled = false;
5834
+ }
5835
+ }
5836
+ for (let i = 0; i < radioBtnElement.length; i++) {
5837
+ radioBtnObj = getComponent(radioBtnElement[i], 'radio');
5838
+ if (isDisabled) {
5839
+ radioBtnObj.disabled = true;
5840
+ }
5841
+ else {
5842
+ radioBtnObj.disabled = false;
5843
+ }
5844
+ }
5845
+ for (let i = 0; i < multiSelectElement.length; i++) {
5846
+ multiSelectObj = getComponent(multiSelectElement[i], 'multiselect');
5847
+ if (isDisabled) {
5848
+ multiSelectObj.enabled = false;
5849
+ }
5850
+ else {
5851
+ multiSelectObj.enabled = true;
5852
+ }
5853
+ }
5854
+ }
5855
+ };
5856
+ __decorate([
5857
+ Event()
5858
+ ], QueryBuilder.prototype, "created", void 0);
5859
+ __decorate([
5860
+ Event()
5861
+ ], QueryBuilder.prototype, "actionBegin", void 0);
5862
+ __decorate([
5863
+ Event()
5864
+ ], QueryBuilder.prototype, "beforeChange", void 0);
5865
+ __decorate([
5866
+ Event()
5867
+ ], QueryBuilder.prototype, "change", void 0);
5868
+ __decorate([
5869
+ Event()
5870
+ ], QueryBuilder.prototype, "dataBound", void 0);
5871
+ __decorate([
5872
+ Event()
5873
+ ], QueryBuilder.prototype, "ruleChange", void 0);
5874
+ __decorate([
5875
+ Complex({}, ShowButtons)
5876
+ ], QueryBuilder.prototype, "showButtons", void 0);
5877
+ __decorate([
5878
+ Property(false)
5879
+ ], QueryBuilder.prototype, "summaryView", void 0);
5880
+ __decorate([
5881
+ Property(false)
5882
+ ], QueryBuilder.prototype, "allowValidation", void 0);
5883
+ __decorate([
5129
5884
  Property('Default')
5130
5885
  ], QueryBuilder.prototype, "fieldMode", void 0);
5131
5886
  __decorate([
@@ -5179,6 +5934,15 @@ __decorate([
5179
5934
  __decorate([
5180
5935
  Property(false)
5181
5936
  ], QueryBuilder.prototype, "readonly", void 0);
5937
+ __decorate([
5938
+ Property(true)
5939
+ ], QueryBuilder.prototype, "addRuleToNewGroups", void 0);
5940
+ __decorate([
5941
+ Property(false)
5942
+ ], QueryBuilder.prototype, "autoSelectField", void 0);
5943
+ __decorate([
5944
+ Property(true)
5945
+ ], QueryBuilder.prototype, "autoSelectOperator", void 0);
5182
5946
  __decorate([
5183
5947
  Property('')
5184
5948
  ], QueryBuilder.prototype, "separator", void 0);
@@ -5189,6 +5953,692 @@ QueryBuilder = __decorate([
5189
5953
  NotifyPropertyChanges
5190
5954
  ], QueryBuilder);
5191
5955
 
5956
+ class QueryLibrary {
5957
+ constructor(parent) {
5958
+ this.parent = parent;
5959
+ this.addEventListener();
5960
+ }
5961
+ destroy() {
5962
+ if (this.parent.isDestroyed) {
5963
+ return;
5964
+ }
5965
+ this.removeEventListener();
5966
+ }
5967
+ addEventListener() {
5968
+ if (this.parent.isDestroyed) {
5969
+ return;
5970
+ }
5971
+ this.parent.on('query-library', this.queryLibrary, this);
5972
+ this.parent.on('destroyed', this.destroy, this);
5973
+ }
5974
+ removeEventListener() {
5975
+ this.parent.off('query-library', this.queryLibrary);
5976
+ this.parent.off('destroyed', this.destroy);
5977
+ }
5978
+ queryLibrary(args) {
5979
+ switch (args.prop) {
5980
+ case 'getMongoFromRules':
5981
+ args.value['obj']['mongoQuery'] = this.getMongoFromRules(args.value['rule'], args.value['mongoQuery']);
5982
+ break;
5983
+ case 'mongoParser':
5984
+ this.mongoParser(args.value['mongoQuery'], args.value['rule'], args.value['mongoLocale']);
5985
+ break;
5986
+ case 'getParameterSql':
5987
+ args.value['obj']['sql'] = this.getParameterSql(args.value['rule']);
5988
+ break;
5989
+ case 'getNamedParameterSql':
5990
+ args.value['obj']['sql'] = this.getNamedParameterSql(args.value['rule']);
5991
+ break;
5992
+ case 'convertParamSqlToSql':
5993
+ args.value['obj']['sql'] = this.convertParamSqlToSql(args.value['sql']);
5994
+ break;
5995
+ case 'convertNamedParamSqlToSql':
5996
+ args.value['obj']['sql'] = this.convertNamedParamSqlToSql(args.value['sql']);
5997
+ break;
5998
+ }
5999
+ }
6000
+ getMongoFromRules(rule, mongoQuery) {
6001
+ mongoQuery = '{';
6002
+ if (rule.condition === 'or') {
6003
+ mongoQuery += '"$or":[';
6004
+ mongoQuery = this.convertMongoQuery(rule.rules, mongoQuery) + ']';
6005
+ }
6006
+ else {
6007
+ mongoQuery += '"$and":[';
6008
+ mongoQuery = this.convertMongoQuery(rule.rules, mongoQuery) + ']';
6009
+ }
6010
+ mongoQuery += '}';
6011
+ return mongoQuery;
6012
+ }
6013
+ getOperatorFromMongoOperator(operator) {
6014
+ let operatorValue;
6015
+ switch (operator) {
6016
+ case '$ne':
6017
+ operatorValue = 'notequal';
6018
+ break;
6019
+ case '$gt':
6020
+ operatorValue = 'greaterthan';
6021
+ break;
6022
+ case '$gte':
6023
+ operatorValue = 'greaterthanorequal';
6024
+ break;
6025
+ case '$lt':
6026
+ operatorValue = 'lessthan';
6027
+ break;
6028
+ case '$lte':
6029
+ operatorValue = 'lessthanorequal';
6030
+ break;
6031
+ case '$nin':
6032
+ operatorValue = 'notin';
6033
+ break;
6034
+ }
6035
+ return operatorValue;
6036
+ }
6037
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6038
+ convertMongoQuery(rules, mongoQuery) {
6039
+ let i = 0;
6040
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6041
+ rules.forEach((item) => {
6042
+ i++;
6043
+ mongoQuery += '{';
6044
+ if (item.rules !== undefined) {
6045
+ if (item.condition === 'or') {
6046
+ mongoQuery += ' "$or":[';
6047
+ mongoQuery = this.convertMongoQuery(item.rules, mongoQuery) + ']';
6048
+ }
6049
+ else {
6050
+ mongoQuery += ' "$and":[';
6051
+ mongoQuery = this.convertMongoQuery(item.rules, mongoQuery) + ']';
6052
+ }
6053
+ }
6054
+ let itVal = item.type === 'string' && item.operator !== 'in' && item.operator !== 'notin' && item.value && item.value.trim() !== '' ? item.value.replace(/'/g, '\\') : '';
6055
+ if (item.type === 'string' && (item.operator === 'in' || item.operator === 'notin') && item.value && item.value.length === 1) {
6056
+ itVal = item.value[0].replace(/'/g, '\\');
6057
+ }
6058
+ const field = item.field ? item.field.substring(0) : '';
6059
+ switch (item.operator) {
6060
+ case 'contains':
6061
+ mongoQuery += '"' + field + '":{"$regex":"' + itVal + '"}';
6062
+ break;
6063
+ case 'notcontains':
6064
+ mongoQuery += '"' + field + '":{"$not":{"$regex":"' + item.value + '"}}';
6065
+ break;
6066
+ case 'startswith':
6067
+ mongoQuery += '"' + field + '":{"$regex":"^' + itVal + '"}';
6068
+ break;
6069
+ case 'notstartswith':
6070
+ mongoQuery += '"' + field + '":{"$not":{"$regex":"^' + item.value + '"}}';
6071
+ break;
6072
+ case 'endswith':
6073
+ mongoQuery += '"' + field + '":{"$regex":"' + itVal + '$"}';
6074
+ break;
6075
+ case 'notendswith':
6076
+ mongoQuery += '"' + field + '":{"$not":{"$regex":"' + item.value + '$"}}';
6077
+ break;
6078
+ case 'isnull':
6079
+ mongoQuery += '"' + field + '": null';
6080
+ break;
6081
+ case 'isnotnull':
6082
+ mongoQuery += '"' + field + '":{"$ne": null}';
6083
+ break;
6084
+ case 'isempty':
6085
+ mongoQuery += '"' + field + '": ""';
6086
+ break;
6087
+ case 'isnotempty':
6088
+ mongoQuery += '"' + field + '":{"$ne": ""}';
6089
+ break;
6090
+ case 'equal':
6091
+ if (item.type === 'string') {
6092
+ mongoQuery += '"' + field + '":"' + itVal + '"';
6093
+ }
6094
+ else if (item.type === 'date') {
6095
+ mongoQuery += '"' + field + '":"' + item.value + '"';
6096
+ }
6097
+ else if (item.type === 'boolean') {
6098
+ mongoQuery += '"' + field + '":' + item.value + '';
6099
+ }
6100
+ else {
6101
+ mongoQuery += '"' + field + '":' + item.value + '';
6102
+ }
6103
+ break;
6104
+ case 'notequal':
6105
+ if (item.type === 'string') {
6106
+ mongoQuery += '"' + field + '":{"$ne":"' + itVal + '"}';
6107
+ }
6108
+ else if (item.type === 'date') {
6109
+ mongoQuery += '"' + field + '":{"$ne":"' + item.value + '"}';
6110
+ }
6111
+ else {
6112
+ mongoQuery += '"' + field + '":{"$ne":' + item.value + '}';
6113
+ }
6114
+ break;
6115
+ case 'in':
6116
+ if (item.type === 'string') {
6117
+ if (item.value.length > 1) {
6118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6119
+ let s = item.value.map((x, j) => (j < item.value.length ? `"${x}"` : '')).toString();
6120
+ s = s.endsWith(',') ? s.substring(0, s.length - 1) : s;
6121
+ mongoQuery += '"' + field + '": { "$in": [' + s + ']}';
6122
+ }
6123
+ else {
6124
+ mongoQuery += '"' + field + '": { "$in": ["' + itVal + '"]}';
6125
+ }
6126
+ }
6127
+ else if (item.type === 'number') {
6128
+ if (item.value.length > 1) {
6129
+ mongoQuery += '"' + field + '": { "$in": [' + item.value.toString() + ']}';
6130
+ }
6131
+ else {
6132
+ mongoQuery += '"' + field + '": { "$in": [' + item.value + ']}';
6133
+ }
6134
+ }
6135
+ break;
6136
+ case 'notin':
6137
+ if (item.type === 'string') {
6138
+ if (item.value.length > 1) {
6139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6140
+ let s = item.value.map((x, j) => (j < item.value.length ? `"${x}"` : '')).toString();
6141
+ s = s.endsWith(',') ? s.substring(0, s.length - 1) : s;
6142
+ mongoQuery += '"' + field + '": { "$nin": [' + s + ']}';
6143
+ }
6144
+ else {
6145
+ mongoQuery += '"' + field + '": { "$nin": ["' + itVal + '"]}';
6146
+ }
6147
+ }
6148
+ else if (item.type === 'number') {
6149
+ if (item.value.length > 1) {
6150
+ mongoQuery += '"' + field + '": { "$nin": [' + item.value.toString() + ']}';
6151
+ }
6152
+ else {
6153
+ mongoQuery += '"' + field + '": { "$nin": [' + item.value + ']}';
6154
+ }
6155
+ }
6156
+ break;
6157
+ case 'greaterthan':
6158
+ if (item.type === 'number') {
6159
+ mongoQuery += '"' + field + '": { "$gt": ' + item.value + '}';
6160
+ }
6161
+ else {
6162
+ mongoQuery += '"' + field + '": { "$gt": "' + item.value + '"}';
6163
+ }
6164
+ break;
6165
+ case 'greaterthanorequal':
6166
+ if (item.type === 'number') {
6167
+ mongoQuery += '"' + field + '": { "$gte": ' + item.value + '}';
6168
+ }
6169
+ else {
6170
+ mongoQuery += '"' + field + '": { "$gte": "' + item.value + '"}';
6171
+ }
6172
+ break;
6173
+ case 'between':
6174
+ if (item.type === 'number') {
6175
+ mongoQuery += '"' + field + '": {"$gte":' + item.value[0] + ', "$lte":' + item.value[1] + '}';
6176
+ }
6177
+ else {
6178
+ mongoQuery += '"' + field + '": {"$gte": "' + item.value[0] + '", "$lte": "' + item.value[1] + '"}';
6179
+ }
6180
+ break;
6181
+ case 'notbetween':
6182
+ if (item.type === 'number') {
6183
+ mongoQuery += '"$or":[{"' + field + '": {"$lt":' + item.value[0] + '}}, {"' + field + '": {"$gt":' + item.value[1] + '}}]';
6184
+ }
6185
+ else {
6186
+ mongoQuery += '"$or":[{"' + field + '": {"$lt": "' + item.value[0] + '"}}, {"' + field + '": {"$gt": "' + item.value[1] + '"}}]';
6187
+ }
6188
+ break;
6189
+ case 'lessthan':
6190
+ if (item.type === 'number') {
6191
+ mongoQuery += '"' + field + '": { "$lt": ' + item.value + '}';
6192
+ }
6193
+ else {
6194
+ mongoQuery += '"' + field + '": { "$lt": "' + item.value + '"}';
6195
+ }
6196
+ break;
6197
+ case 'lessthanorequal':
6198
+ if (item.type === 'number') {
6199
+ mongoQuery += '"' + field + '": { "$lte": ' + item.value + '}';
6200
+ }
6201
+ else {
6202
+ mongoQuery += '"' + field + '": { "$lte": "' + item.value + '"}';
6203
+ }
6204
+ break;
6205
+ }
6206
+ mongoQuery += '}';
6207
+ if (rules.length !== i) {
6208
+ mongoQuery += ',';
6209
+ }
6210
+ });
6211
+ return mongoQuery;
6212
+ }
6213
+ mongoParser(mongoQuery, rule, mongoLocale) {
6214
+ let mongoList;
6215
+ if (Object.keys(mongoQuery).indexOf('$and') > -1) {
6216
+ mongoList = mongoQuery['$and'];
6217
+ rule.condition = 'and';
6218
+ }
6219
+ else if (Object.keys(mongoQuery).indexOf('$or') > -1) {
6220
+ mongoList = mongoQuery['$or'];
6221
+ rule.condition = 'or';
6222
+ }
6223
+ rule.rules = [];
6224
+ this.mongoRecursion(mongoList, rule.rules, mongoLocale);
6225
+ }
6226
+ mongoRecursion(mongoList, rules, mongoLocale) {
6227
+ let operatorValue;
6228
+ let type;
6229
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6230
+ let stringValue;
6231
+ let key;
6232
+ let betweenValue;
6233
+ let condition;
6234
+ let value;
6235
+ let subRules;
6236
+ let rule;
6237
+ let keyObj;
6238
+ let ruleValue;
6239
+ for (let i = 0, len = mongoList.length; i < len; i++) {
6240
+ const betweenOperatorArray = [];
6241
+ let inOperatorArray = [];
6242
+ condition = Object.keys(mongoList[i])[0];
6243
+ value = mongoList[i][condition];
6244
+ if (condition === '$and') {
6245
+ if (this.parent.enableNotCondition) {
6246
+ subRules = { condition: condition.replace('$', ''), rules: [], not: false };
6247
+ }
6248
+ else {
6249
+ subRules = { condition: condition.replace('$', ''), rules: [] };
6250
+ }
6251
+ rules.push(subRules);
6252
+ this.mongoRecursion(mongoList[i][condition], rules[rules.length - 1].rules, mongoLocale);
6253
+ }
6254
+ else if (condition === '$or') {
6255
+ let notBetween;
6256
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, max-len
6257
+ let innerObject = [];
6258
+ let keys = [];
6259
+ let firstKey = [];
6260
+ let secondKey = [];
6261
+ let innerKeys = [];
6262
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, max-len
6263
+ let firstValue = [];
6264
+ let secondValue = [];
6265
+ let innerFirstValue = [];
6266
+ let innerSecondValue = [];
6267
+ if (Array.isArray(value) && value.length === 2) {
6268
+ keys = Object.keys(value);
6269
+ innerFirstValue = value[keys[0]];
6270
+ innerSecondValue = value[keys[1]];
6271
+ if (typeof innerFirstValue === 'object') {
6272
+ innerObject = Object.keys(innerFirstValue)[0];
6273
+ innerKeys = Object.keys(innerFirstValue[Object.keys(innerFirstValue)[0]]);
6274
+ firstKey = innerKeys[0];
6275
+ secondKey = Object.keys(innerSecondValue[Object.keys(innerSecondValue)[0]])[0];
6276
+ if (firstKey === '$lt' && secondKey === '$gt') {
6277
+ operatorValue = 'notbetween';
6278
+ // eslint-disable-next-line security/detect-object-injection
6279
+ firstValue = innerFirstValue[innerObject][firstKey];
6280
+ // eslint-disable-next-line security/detect-object-injection
6281
+ secondValue = innerSecondValue[innerObject][secondKey];
6282
+ type = typeof firstValue === 'number' ? 'number' : 'date';
6283
+ ruleValue = [firstValue, secondValue];
6284
+ rule = { field: innerObject, label: innerObject, value: ruleValue, operator: operatorValue, type: type };
6285
+ rules.push(rule);
6286
+ notBetween = true;
6287
+ }
6288
+ }
6289
+ }
6290
+ if (!notBetween) {
6291
+ if (this.parent.enableNotCondition) {
6292
+ subRules = { condition: condition.replace('$', ''), rules: [], not: false };
6293
+ }
6294
+ else {
6295
+ subRules = { condition: condition.replace('$', ''), rules: [] };
6296
+ }
6297
+ rules.push(subRules);
6298
+ this.mongoRecursion(mongoList[i][condition], rules[rules.length - 1].rules, mongoLocale);
6299
+ }
6300
+ }
6301
+ else {
6302
+ value = mongoList[i][condition];
6303
+ if (value === null) { // isnull operator
6304
+ operatorValue = 'isnull';
6305
+ }
6306
+ if (typeof value === 'boolean') { // boolean type values
6307
+ operatorValue = 'equal';
6308
+ type = 'boolean';
6309
+ ruleValue = value;
6310
+ }
6311
+ if (typeof (value) === 'number') {
6312
+ ruleValue = value;
6313
+ type = 'number';
6314
+ operatorValue = 'equal';
6315
+ }
6316
+ else if (typeof (value) === 'object' && value !== null) {
6317
+ keyObj = Object.keys(value);
6318
+ for (let i = 0; i < keyObj.length; i++) {
6319
+ key = keyObj[i];
6320
+ stringValue = (value)[keyObj[i]];
6321
+ if (key === '$ne' && isNullOrUndefined(stringValue)) { // not null operator
6322
+ operatorValue = 'isnotnull';
6323
+ ruleValue = null;
6324
+ }
6325
+ if (key === '$ne' && typeof stringValue === 'boolean') { // not equal operator for boolean
6326
+ operatorValue = 'notequal';
6327
+ ruleValue = stringValue;
6328
+ type = 'boolean';
6329
+ }
6330
+ if (keyObj.length >= 2 && keyObj[i]) {
6331
+ if (typeof (stringValue) == 'object') { // between and notbetween operators
6332
+ operatorValue = 'notbetween';
6333
+ condition = Object.keys(stringValue)[0];
6334
+ betweenValue = [Object.keys(stringValue[condition])[0]];
6335
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6336
+ betweenOperatorArray.push(stringValue[condition][betweenValue]);
6337
+ type = 'number';
6338
+ }
6339
+ else {
6340
+ operatorValue = 'between';
6341
+ betweenOperatorArray.push(stringValue);
6342
+ }
6343
+ if (typeof (stringValue) === 'number') {
6344
+ type = 'number';
6345
+ }
6346
+ }
6347
+ else if (typeof (stringValue) === 'object' && stringValue !== null) { // "in" and "notin" operator
6348
+ if (key === '$not' && Object.keys(stringValue)[0] === '$regex') {
6349
+ if (stringValue['$regex'].indexOf('^') > -1) {
6350
+ operatorValue = 'notstartswith';
6351
+ ruleValue = stringValue['$regex'].replace('^', '');
6352
+ }
6353
+ else if (stringValue['$regex'].indexOf('$') > -1) {
6354
+ operatorValue = 'notendswith';
6355
+ ruleValue = stringValue['$regex'].replace('$', '');
6356
+ }
6357
+ else {
6358
+ operatorValue = 'notcontains';
6359
+ ruleValue = stringValue['$regex'];
6360
+ }
6361
+ }
6362
+ else {
6363
+ operatorValue = key === '$in' ? 'in' : 'notin';
6364
+ inOperatorArray = stringValue;
6365
+ type = typeof (stringValue[0]) === 'number' ? 'number' : 'string';
6366
+ }
6367
+ }
6368
+ else if (typeof (stringValue) === 'number') { // number type values
6369
+ operatorValue = this.getOperatorFromMongoOperator(key);
6370
+ type = 'number';
6371
+ ruleValue = stringValue;
6372
+ }
6373
+ if (typeof (stringValue) === 'string') { // string type values
6374
+ if (key === '$regex') {
6375
+ operatorValue = 'contains';
6376
+ ruleValue = stringValue;
6377
+ type = 'string';
6378
+ }
6379
+ if (key === '$ne') { // not equal
6380
+ if (stringValue !== null && stringValue.length > 0 && isNaN(Date.parse(stringValue))) {
6381
+ operatorValue = 'notequal';
6382
+ ruleValue = stringValue;
6383
+ }
6384
+ else if (isNullOrUndefined(stringValue)) { // is not null operator
6385
+ operatorValue = 'isnotnull';
6386
+ ruleValue = stringValue;
6387
+ }
6388
+ else if (stringValue === '') { // is not empty operator
6389
+ operatorValue = 'isnotempty';
6390
+ ruleValue = stringValue;
6391
+ }
6392
+ type = 'string';
6393
+ }
6394
+ if (stringValue.indexOf('^') > -1) {
6395
+ operatorValue = 'startswith';
6396
+ ruleValue = stringValue.replace('^', '');
6397
+ type = 'string';
6398
+ }
6399
+ if (stringValue.indexOf('$') > -1 && key !== '$not') {
6400
+ operatorValue = 'endswith';
6401
+ ruleValue = stringValue.replace('$', '');
6402
+ type = 'string';
6403
+ }
6404
+ if (!isNaN(Date.parse(stringValue))) { // Date type operators
6405
+ operatorValue = operatorValue || this.getOperatorFromMongoOperator(key);
6406
+ type = 'date';
6407
+ ruleValue = stringValue;
6408
+ }
6409
+ }
6410
+ }
6411
+ }
6412
+ else if (value && typeof (value) === 'string' && !isNaN(Date.parse(value))) {
6413
+ operatorValue = 'equal';
6414
+ ruleValue = value;
6415
+ type = 'date';
6416
+ }
6417
+ else if (typeof (value) === 'string' && value !== '' && value !== 'true' && value !== 'false') {
6418
+ operatorValue = 'equal';
6419
+ ruleValue = value;
6420
+ type = 'string';
6421
+ }
6422
+ else if (typeof (value) === 'string' && value === '') {
6423
+ operatorValue = 'isempty';
6424
+ ruleValue = value;
6425
+ type = 'string';
6426
+ }
6427
+ if (betweenOperatorArray && betweenOperatorArray.length > 1) { // between opertor value
6428
+ rule = { field: condition, label: condition, value: betweenOperatorArray, operator: operatorValue, type: type };
6429
+ }
6430
+ else if (inOperatorArray && inOperatorArray.length > 1) { // in operator value
6431
+ rule = { field: condition, label: condition, value: inOperatorArray, operator: operatorValue, type: type };
6432
+ }
6433
+ else {
6434
+ rule = { field: condition, label: condition, value: ruleValue, operator: operatorValue, type: type };
6435
+ }
6436
+ rules.push(rule);
6437
+ operatorValue = '';
6438
+ }
6439
+ }
6440
+ }
6441
+ convertParamSqlToSql(sql) {
6442
+ const paramSql = sql.sql;
6443
+ const paramValues = sql.params;
6444
+ const parts = paramSql.split('?');
6445
+ let normalSql = parts[0];
6446
+ for (let i = 0; i < paramValues.length; i++) {
6447
+ normalSql += (typeof (paramValues[i]) === 'string' ? `'${paramValues[i]}'` + parts[i + 1] : paramValues[i] + parts[i + 1]);
6448
+ }
6449
+ if (normalSql.length >= 2 && normalSql[0] === '(' && normalSql[normalSql.length - 1] === ')') {
6450
+ normalSql = normalSql.slice(1, -1);
6451
+ }
6452
+ normalSql = normalSql.replace(/!= ''(?! =)/g, 'IS NOT EMPTY').replace(/= ''/g, 'IS EMPTY');
6453
+ return normalSql;
6454
+ }
6455
+ convertNamedParamSqlToSql(sql) {
6456
+ const namedParamSql = sql.sql;
6457
+ const params = sql.params;
6458
+ let normalSql = namedParamSql;
6459
+ Object.keys(params).forEach((paramName) => {
6460
+ const paramValue = params[paramName];
6461
+ paramName = ':' + paramName;
6462
+ normalSql = normalSql.replace(paramName, typeof (paramValue) === 'string' ? `'${paramValue}'` : String(paramValue));
6463
+ });
6464
+ if (normalSql.length >= 2 && normalSql[0] === '(' && normalSql[normalSql.length - 1] === ')') {
6465
+ normalSql = normalSql.slice(1, -1);
6466
+ }
6467
+ normalSql = normalSql.replace(/!= ''(?! =)/g, 'IS NOT EMPTY').replace(/= ''/g, 'IS EMPTY');
6468
+ return normalSql;
6469
+ }
6470
+ getParameterSql(qbrule) {
6471
+ const qbRule = extend({}, qbrule, null, true);
6472
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6473
+ const value = this.updateRuleValue(qbRule, false);
6474
+ return this.getParameterSQLVal(this.parent.getSqlFromRules(qbRule), value['ruleVal']);
6475
+ }
6476
+ getNamedParameterSql(qbrule) {
6477
+ const qbRule = extend({}, qbrule, null, true);
6478
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6479
+ const value = this.updateRuleValue(qbRule, true);
6480
+ return this.getNamedParameterSQLVal(this.parent.getSqlFromRules(qbRule), value['namedRuleVal']);
6481
+ }
6482
+ getParameterSQLVal(content, ruleValue) {
6483
+ const replacedString = content.replace(/[%']/g, '');
6484
+ return { sql: '(' + replacedString + ')', params: ruleValue };
6485
+ }
6486
+ getNamedParameterSQLVal(content, ruleValue) {
6487
+ const replacedString = content.replace(/[%']/g, '');
6488
+ return { sql: '(' + replacedString + ')', params: ruleValue };
6489
+ }
6490
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6491
+ updateRuleValue(rule, isNamedParameter) {
6492
+ const ruleVal = [];
6493
+ const namedRuleVal = {};
6494
+ const namedParameters = [];
6495
+ return this.updateValue(rule.rules, isNamedParameter, ruleVal, namedRuleVal, namedParameters);
6496
+ }
6497
+ updateValue(rules, isNamedParameter, ruleVal,
6498
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6499
+ namedRuleVal, namedParameters) {
6500
+ if (isNullOrUndefined(rules)) {
6501
+ return { ruleVal, namedRuleVal };
6502
+ }
6503
+ for (let i = 0; i < rules.length; i++) {
6504
+ if (rules[i].rules) {
6505
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6506
+ const value = this.updateValue(rules[i].rules, isNamedParameter, ruleVal, namedRuleVal, namedParameters);
6507
+ ruleVal = value['ruleVal'];
6508
+ namedRuleVal = value['namedRuleVal'];
6509
+ }
6510
+ else {
6511
+ let namedField;
6512
+ if (rules[i].value instanceof Array) {
6513
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6514
+ for (let j = 0; j < (rules[i].value).length; j++) {
6515
+ if (isNamedParameter) {
6516
+ namedField = this.getNamedParameter(rules[i].field, namedParameters);
6517
+ }
6518
+ if (!isNullOrUndefined(rules[i].value[j])) {
6519
+ if (rules[i].type === 'string' || rules[i].type === 'date') {
6520
+ if (isNamedParameter) {
6521
+ namedRuleVal[namedField] = rules[i].value[j];
6522
+ }
6523
+ else {
6524
+ ruleVal.push(rules[i].value[j]);
6525
+ }
6526
+ }
6527
+ else {
6528
+ if (isNamedParameter) {
6529
+ namedRuleVal[namedField] = rules[i].value[j];
6530
+ }
6531
+ else {
6532
+ ruleVal.push(rules[i].value[j]);
6533
+ }
6534
+ }
6535
+ }
6536
+ if (isNamedParameter) {
6537
+ rules[i].value[j] = ':' + namedField;
6538
+ }
6539
+ else {
6540
+ rules[i].value[j] = '?';
6541
+ }
6542
+ }
6543
+ }
6544
+ else {
6545
+ if (isNamedParameter) {
6546
+ namedField = this.getNamedParameter(rules[i].field, namedParameters);
6547
+ }
6548
+ if (rules[i].operator.indexOf('null') < 1) {
6549
+ if (rules[i].type !== 'string' || (rules[i].type === 'string' && (rules[i].value !== '' || rules[i].value === 0))) {
6550
+ if (rules[i].type === 'string' || rules[i].type === 'date') {
6551
+ if (rules[i].operator.indexOf('empty') < 1) {
6552
+ let value = rules[i].value.toString();
6553
+ switch (rules[i].operator) {
6554
+ case 'startswith':
6555
+ case 'notstartswith':
6556
+ value = value + '%';
6557
+ break;
6558
+ case 'endswith':
6559
+ case 'notendswith':
6560
+ value = '%' + value;
6561
+ break;
6562
+ case 'contains':
6563
+ case 'notcontains':
6564
+ value = '%' + value + '%';
6565
+ break;
6566
+ }
6567
+ if (isNamedParameter) {
6568
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6569
+ namedRuleVal[namedField] = value;
6570
+ }
6571
+ else {
6572
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6573
+ ruleVal.push(value);
6574
+ }
6575
+ }
6576
+ else {
6577
+ if (isNamedParameter) {
6578
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6579
+ namedRuleVal[namedField] = '';
6580
+ }
6581
+ else {
6582
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6583
+ ruleVal.push('');
6584
+ }
6585
+ if (rules[i].operator === 'isempty') {
6586
+ rules[i].operator = 'equal';
6587
+ }
6588
+ else {
6589
+ rules[i].operator = 'notequal';
6590
+ }
6591
+ }
6592
+ }
6593
+ else {
6594
+ if (!isNullOrUndefined(rules[i].value)) {
6595
+ if (isNamedParameter) {
6596
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6597
+ namedRuleVal[namedField] = rules[i].value;
6598
+ }
6599
+ else {
6600
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6601
+ ruleVal.push(rules[i].value);
6602
+ }
6603
+ }
6604
+ }
6605
+ if (isNamedParameter) {
6606
+ rules[i].value = ':' + namedField;
6607
+ }
6608
+ else {
6609
+ rules[i].value = '?';
6610
+ }
6611
+ }
6612
+ }
6613
+ }
6614
+ }
6615
+ }
6616
+ return { ruleVal, namedRuleVal };
6617
+ }
6618
+ getNamedParameter(field, namedParameters) {
6619
+ let newField = null;
6620
+ if (namedParameters.length > 0) {
6621
+ for (let i = namedParameters.length - 1; i >= 0; i--) {
6622
+ const currField = namedParameters[i];
6623
+ if (currField.indexOf(field) > -1) {
6624
+ const idx = parseInt(currField.split('_')[1], 10) + 1;
6625
+ newField = field + '_' + idx;
6626
+ namedParameters.push(newField);
6627
+ break;
6628
+ }
6629
+ }
6630
+ }
6631
+ if (!newField) {
6632
+ newField = field + '_1';
6633
+ namedParameters.push(newField);
6634
+ }
6635
+ return newField;
6636
+ }
6637
+ getModuleName() {
6638
+ return 'query-library';
6639
+ }
6640
+ }
6641
+
5192
6642
  /**
5193
6643
  * QueryBuilder modules
5194
6644
  */
@@ -5197,5 +6647,5 @@ QueryBuilder = __decorate([
5197
6647
  * QueryBuilder all modules
5198
6648
  */
5199
6649
 
5200
- export { Columns, Rule, Value, ShowButtons, QueryBuilder };
6650
+ export { Columns, Rule, Value, ShowButtons, QueryBuilder, QueryLibrary };
5201
6651
  //# sourceMappingURL=ej2-querybuilder.es2015.js.map