@zeedhi/common 1.105.0 → 1.106.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { AccessorManager, Event, KeyMap, MethodNotAssignedError, Metadata, Accessor, I18n, FormatterParserProvider, Validation, Mask, DatasourceFactory, Loader, Config, dayjs, Utils, DateHelper, Router, InstanceNotFoundError, ViewService, MemoryDatasource, URL as URL$1, Http, Cookie, VersionService } from '@zeedhi/core';
1
+ import { AccessorManager, Event, KeyMap, MethodNotAssignedError, Metadata, Accessor, I18n, FormatterParserProvider, Validation, Mask, DatasourceFactory, Loader, Config, dayjs, Utils, DateHelper, Router, InstanceNotFoundError, ViewService, MemoryDatasource, URL as URL$1, Http, Messages, Cookie, VersionService } from '@zeedhi/core';
2
2
  import merge from 'lodash.merge';
3
3
  import cloneDeep from 'lodash.clonedeep';
4
4
  import debounce from 'lodash.debounce';
@@ -1914,7 +1914,7 @@ class Input extends ComponentRender {
1914
1914
  this.internalDisplayValue = '';
1915
1915
  this.internalValue = null;
1916
1916
  this.formParent = this.getFormParent();
1917
- this.lastInputValue = undefined;
1917
+ this.lastInputValue = '';
1918
1918
  this.callInputEvent = debounce(({ event, element, component }) => {
1919
1919
  this.callEvent('input', { event, element, component });
1920
1920
  }, 50);
@@ -5396,6 +5396,8 @@ class Column extends Component {
5396
5396
  this.actionFactoredConditions = {};
5397
5397
  this.helperText = '';
5398
5398
  this.defaultData = [];
5399
+ /* Column search mode */
5400
+ this.searchMode = 'any';
5399
5401
  this.lookup = debounce((lookupColumn) => {
5400
5402
  this.loading = true;
5401
5403
  const dataToLookup = Array.from(new Set(this.dataToLookup)); // remove duplicates
@@ -5426,6 +5428,7 @@ class Column extends Component {
5426
5428
  this.componentProps = this.getInitValue('componentProps', props.componentProps, this.componentProps);
5427
5429
  this.xlsType = this.getInitValue('xlsType', props.xlsType, this.xlsType);
5428
5430
  this.conditions = this.getInitValue('conditions', props.conditions, this.conditions);
5431
+ this.searchMode = this.getInitValue('searchMode', props.searchMode, this.searchMode);
5429
5432
  this.helperText = this.getInitValue('', props.helperText, this.helperText);
5430
5433
  this.createConditions();
5431
5434
  this.createActionConditions();
@@ -5586,6 +5589,7 @@ class ColumnNotFoundError extends Error {
5586
5589
  class IterableController {
5587
5590
  constructor(iterable) {
5588
5591
  this.searchInValue = undefined;
5592
+ this.searchInParamsValue = undefined;
5589
5593
  this.iterable = iterable;
5590
5594
  }
5591
5595
  get searchIn() {
@@ -5598,6 +5602,16 @@ class IterableController {
5598
5602
  set searchIn(value) {
5599
5603
  this.searchInValue = value;
5600
5604
  }
5605
+ get searchInParams() {
5606
+ return this.searchInParamsValue || this.iterable.columns.reduce((result, column) => {
5607
+ if (!!column.searchMode && column.searchMode !== 'any')
5608
+ result[column.name] = column.searchMode;
5609
+ return result;
5610
+ }, {});
5611
+ }
5612
+ set searchInParams(value) {
5613
+ this.searchInParamsValue = value;
5614
+ }
5601
5615
  }
5602
5616
 
5603
5617
  /**
@@ -5646,12 +5660,13 @@ class Iterable extends ComponentRender {
5646
5660
  this.searchVisibleOnly = this.getInitValue('searchVisibleOnly', props.searchVisibleOnly, this.defaultSearchVisibleOnly);
5647
5661
  this.virtualScroll = this.getInitValue('virtualScroll', props.virtualScroll, this.virtualScroll);
5648
5662
  this.virtualScrollCache = this.getInitValue('virtualScrollCache', props.virtualScrollCache, this.virtualScrollCache);
5663
+ this.searchIn = this.getInitValue('searchIn', props.searchIn, this.searchIn);
5649
5664
  }
5650
5665
  getDatasourceDefaults() {
5651
5666
  return {};
5652
5667
  }
5653
5668
  initializeDatasource(props) {
5654
- var _a;
5669
+ var _a, _b;
5655
5670
  let datasourceProps = props.datasource;
5656
5671
  // if using accessor, get props from the controller
5657
5672
  if (typeof props.datasource === 'string' && Accessor.isAccessorDefinition(props.datasource)) {
@@ -5659,7 +5674,7 @@ class Iterable extends ComponentRender {
5659
5674
  const instance = Loader.getInstance(controller);
5660
5675
  datasourceProps = instance[accessor];
5661
5676
  }
5662
- this.datasource = DatasourceFactory.factory(Object.assign(Object.assign(Object.assign({}, datasourceProps), this.getDatasourceDefaults()), { searchIn: ((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.searchIn) || `{{IterableController_${this.name}.searchIn}}` }));
5677
+ this.datasource = DatasourceFactory.factory(Object.assign(Object.assign(Object.assign({}, datasourceProps), this.getDatasourceDefaults()), { searchIn: ((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.searchIn) || `{{IterableController_${this.name}.searchIn}}`, searchInParams: ((_b = props.datasource) === null || _b === void 0 ? void 0 : _b.searchInParams) || `{{IterableController_${this.name}.searchInParams}}` }));
5663
5678
  }
5664
5679
  createController() {
5665
5680
  const controller = new IterableController(this);
@@ -5762,7 +5777,7 @@ class Iterable extends ComponentRender {
5762
5777
  });
5763
5778
  }
5764
5779
  isColumnSearchable(column) {
5765
- return !this.searchVisibleOnly || column.isVisible;
5780
+ return (!this.searchVisibleOnly || column.isVisible) && (this.searchIn === undefined || this.searchIn === column.name);
5766
5781
  }
5767
5782
  }
5768
5783
 
@@ -5897,7 +5912,7 @@ FormatterParserProvider.registerFormatter('column_ZdSelect', ({ column, value, r
5897
5912
  });
5898
5913
  }
5899
5914
  }
5900
- const textColumn = formatterDataText || dataTextDiscrete || dataTextForeign;
5915
+ const textColumn = dataTextDiscrete || formatterDataText || dataTextForeign;
5901
5916
  if (!textColumn)
5902
5917
  return value;
5903
5918
  if (typeof textColumn === 'string') {
@@ -7175,10 +7190,7 @@ class GridEditable extends Grid {
7175
7190
  }
7176
7191
  let allValid = true;
7177
7192
  this.datasource.data.forEach((row) => this.columns.forEach((column) => {
7178
- const rowKey = row[this.datasource.uniqueKey];
7179
- const cellsApplied = (this.cellsApplied[rowKey] || {})[column.name];
7180
- const columnWithConditions = Object.assign(Object.assign({}, column), cellsApplied);
7181
- if (!column.isVisible || !columnWithConditions.editable)
7193
+ if (!this.isColumnEditable(column, row))
7182
7194
  return;
7183
7195
  if (!this.isValid(column, row, true))
7184
7196
  allValid = false;
@@ -7304,6 +7316,12 @@ class GridEditable extends Grid {
7304
7316
  const column = this.getColumn(columnName);
7305
7317
  this.changeCell(rowKey, rowIdx, column, value);
7306
7318
  }
7319
+ isColumnEditable(column, row) {
7320
+ const rowKey = row[this.datasource.uniqueKey];
7321
+ const cellsApplied = (this.cellsApplied[rowKey] || {})[column.name];
7322
+ const columnWithConditions = Object.assign(Object.assign({}, column), cellsApplied);
7323
+ return column.isVisible && columnWithConditions.editable && this.callCanEditRow(row);
7324
+ }
7307
7325
  /**
7308
7326
  * Changes a cell value in editedRows
7309
7327
  * @param rowKey Cell's row key
@@ -7314,7 +7332,7 @@ class GridEditable extends Grid {
7314
7332
  changeCell(rowKey, rowIdx, column, value) {
7315
7333
  const originalRow = this.datasource.data[rowIdx];
7316
7334
  // Column doesn't have component
7317
- if (!column.editable || !column.isVisible) {
7335
+ if (!this.isColumnEditable(column, originalRow)) {
7318
7336
  this.changeEditableComponent(column, originalRow, value);
7319
7337
  return;
7320
7338
  }
@@ -7890,6 +7908,7 @@ Icons.mdiIcons = {
7890
7908
  success: 'mdi-check-circle',
7891
7909
  tableConfig: 'mdi-table-cog',
7892
7910
  tableColumns: 'mdi-table-headers-eye',
7911
+ tableSearch: 'mdi-table-search',
7893
7912
  unfold: 'mdi-unfold-more-horizontal',
7894
7913
  warning: 'mdi-exclamation',
7895
7914
  zoom: 'mdi-magnify',
@@ -7948,6 +7967,7 @@ Icons.faIcons = {
7948
7967
  success: 'fa fa-check-circle',
7949
7968
  tableConfig: 'fa fa-columns',
7950
7969
  tableColumns: 'fa fa-columns',
7970
+ tableSearch: 'fa fa-search',
7951
7971
  unfold: 'fa fa-sort',
7952
7972
  warning: 'fa fa-exclamation',
7953
7973
  zoom: 'fa fa-search',
@@ -9641,6 +9661,10 @@ class Select extends TextInput {
9641
9661
  */
9642
9662
  this.dataValueOutFormName = '';
9643
9663
  this.closeOnScroll = true;
9664
+ /* Defines if should open modal with grid to make the selection */
9665
+ this.modalSelection = false;
9666
+ /* Defines fields to show on modal */
9667
+ this.modalSelectionFields = [];
9644
9668
  this.dsSearch = {
9645
9669
  SEARCH: (value, searchIn) => ({
9646
9670
  searchIn: [searchIn],
@@ -9676,6 +9700,7 @@ class Select extends TextInput {
9676
9700
  this.pushedValue = null;
9677
9701
  this.loadMoreQtty = 0;
9678
9702
  this.debounceSearch = debounce(this.doSearch, 500);
9703
+ this.modalSelectionObj = undefined;
9679
9704
  this.appendIcon = this.getInitValue('appendIcon', props.appendIcon, 'expand');
9680
9705
  this.dataText = this.getInitValue('dataText', props.dataText, this.dataText);
9681
9706
  this.dataTextDiscrete = this.getInitValue('dataTextDiscrete', props.dataTextDiscrete, this.dataTextDiscrete);
@@ -9694,6 +9719,8 @@ class Select extends TextInput {
9694
9719
  this.dataValueOut = this.getInitValue('dataValueOut', props.dataValueOut, this.dataValueOut);
9695
9720
  this.dataValueOutFormName = this.getInitValue('dataValueOutFormName', props.dataValueOutFormName, this.dataValueOutFormName);
9696
9721
  this.closeOnScroll = this.getInitValue('closeOnScroll', props.closeOnScroll, this.closeOnScroll);
9722
+ this.modalSelection = this.getInitValue('modalSelection', props.modalSelection, this.modalSelection);
9723
+ this.modalSelectionFields = this.getInitValue('modalSelectionFields', props.modalSelectionFields, this.modalSelectionFields);
9697
9724
  if (((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.type) === 'simple') {
9698
9725
  this.dataValue = 'value';
9699
9726
  this.dataText = this.dataText || this.dataValue;
@@ -9706,8 +9733,8 @@ class Select extends TextInput {
9706
9733
  dataText: this.dataTextDiscrete,
9707
9734
  dataTextSeparator: this.dataTextSeparator,
9708
9735
  };
9709
- const defaultDatasource = this.getDefaultDatasource(props);
9710
- this.datasource = DatasourceFactory.factory(defaultDatasource);
9736
+ this.defaultDatasource = this.getDefaultDatasource(props);
9737
+ this.datasource = DatasourceFactory.factory(this.defaultDatasource);
9711
9738
  this.overrideGet();
9712
9739
  let defaultValue = props.value;
9713
9740
  if (Accessor.isAccessorDefinition(props.value)) {
@@ -9715,7 +9742,7 @@ class Select extends TextInput {
9715
9742
  this.getInitValue('value', props.value, this.value);
9716
9743
  }
9717
9744
  this.setDefaultValue(defaultValue, (_b = props.datasource) === null || _b === void 0 ? void 0 : _b.lazyLoad);
9718
- this.preventLoadOnFocus = !defaultDatasource.lazyLoad;
9745
+ this.preventLoadOnFocus = !this.defaultDatasource.lazyLoad;
9719
9746
  this.preventLoadOnFocus = this.getInitValue('preventLoadOnFocus', props.preventLoadOnFocus, this.preventLoadOnFocus);
9720
9747
  this.loadMoreQtty = this.datasource.limit;
9721
9748
  this.itemAfterSlot = props.itemAfterSlot || this.itemAfterSlot;
@@ -9729,6 +9756,31 @@ class Select extends TextInput {
9729
9756
  const instance = Loader.getInstance(controller);
9730
9757
  return instance[accessor];
9731
9758
  }
9759
+ onMounted(element) {
9760
+ super.onMounted(element);
9761
+ if (this.modalSelection && this.modalSelectionFields.length) {
9762
+ KeyMap.bind({
9763
+ 'shift+enter': {
9764
+ active: true,
9765
+ input: true,
9766
+ stop: true,
9767
+ prevent: true,
9768
+ event: this.openModalSelection.bind(this),
9769
+ },
9770
+ }, this, element);
9771
+ }
9772
+ }
9773
+ onBeforeDestroy() {
9774
+ super.onBeforeDestroy();
9775
+ this.datasource.destroy();
9776
+ if (this.modalSelection && this.modalSelectionFields.length) {
9777
+ KeyMap.unbind({
9778
+ 'shift+enter': {
9779
+ event: this.openModalSelection.bind(this),
9780
+ },
9781
+ }, this);
9782
+ }
9783
+ }
9732
9784
  /**
9733
9785
  * Retrieves datasource structure applying infinity scroll
9734
9786
  * @param field Field structure
@@ -10103,10 +10155,6 @@ class Select extends TextInput {
10103
10155
  && !this.datasource.loadAll
10104
10156
  && this.datasource.data.length - (this.pushedValue ? 1 : 0) < this.datasource.total;
10105
10157
  }
10106
- onBeforeDestroy() {
10107
- super.onBeforeDestroy();
10108
- this.datasource.destroy();
10109
- }
10110
10158
  indexOf(search) {
10111
10159
  const value = search && typeof search === 'object' ? search[this.dataValue] : search;
10112
10160
  return this.datasource.data.findIndex((row) => row[this.dataValue] === value);
@@ -10114,6 +10162,105 @@ class Select extends TextInput {
10114
10162
  isFilledObj(obj) {
10115
10163
  return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.keys(obj).length;
10116
10164
  }
10165
+ hideModalSelection() {
10166
+ if (this.modalSelectionObj)
10167
+ this.modalSelectionObj.hide();
10168
+ }
10169
+ modalSelectionGridClick({ row }) {
10170
+ this.setValue(row);
10171
+ this.hideModalSelection();
10172
+ setTimeout(() => {
10173
+ if (this.viewCloseMenu)
10174
+ this.viewCloseMenu();
10175
+ }, 200);
10176
+ }
10177
+ openModalSelection() {
10178
+ const modalSelectionDef = {
10179
+ name: `${this.name}-modal-selection`,
10180
+ persistent: true,
10181
+ children: [
10182
+ {
10183
+ name: `${this.name}-modal-selection-content-container`,
10184
+ component: 'ZdContainer',
10185
+ scrollView: true,
10186
+ cssClass: 'zd-my-2 zd-pa-0 zd-select-modal-selection-content-container',
10187
+ children: [
10188
+ {
10189
+ name: `${this.name}-modal-selection-grid`,
10190
+ component: 'ZdGrid',
10191
+ cssClass: 'zd-my-2 zd-pa-0 zd-select-modal-selection-grid',
10192
+ columns: this.modalSelectionFields,
10193
+ datasource: Object.assign(Object.assign({}, this.defaultDatasource), { lazyLoad: false, searchIn: undefined }),
10194
+ toolbarSlot: [
10195
+ {
10196
+ name: `${this.name}-modal-selection-title`,
10197
+ component: 'ZdText',
10198
+ cssStyle: `color: ${'var(--v-primary-base);'}`,
10199
+ text: this.label,
10200
+ tag: 'h3',
10201
+ },
10202
+ {
10203
+ name: `${this.name}-modal-selection-spacer`,
10204
+ component: 'VSpacer',
10205
+ },
10206
+ {
10207
+ name: `${this.name}-modal-selection_gridSearch`,
10208
+ component: 'ZdSearch',
10209
+ cssClass: 'zd-grid-search',
10210
+ autofocus: true,
10211
+ },
10212
+ ],
10213
+ events: {
10214
+ rowClick: this.modalSelectionGridClick.bind(this),
10215
+ },
10216
+ },
10217
+ ],
10218
+ },
10219
+ {
10220
+ name: `${this.name}-modal-selection-footer-container`,
10221
+ component: 'ZdContainer',
10222
+ cssClass: 'zd-pa-0',
10223
+ children: [
10224
+ {
10225
+ name: `${this.name}-modal-selection-footer`,
10226
+ component: 'ZdFooter',
10227
+ color: 'transparent',
10228
+ padless: true,
10229
+ rightSlot: [
10230
+ {
10231
+ name: `${this.name}-modal-selection-cancelButton`,
10232
+ component: 'ZdButton',
10233
+ label: 'CANCEL',
10234
+ keyMap: {
10235
+ esc: {
10236
+ event: this.hideModalSelection.bind(this),
10237
+ focus: true,
10238
+ visible: true,
10239
+ input: true,
10240
+ stop: true,
10241
+ },
10242
+ },
10243
+ outline: true,
10244
+ events: {
10245
+ click: this.hideModalSelection.bind(this),
10246
+ },
10247
+ },
10248
+ ],
10249
+ },
10250
+ ],
10251
+ },
10252
+ ],
10253
+ events: {
10254
+ onShow: () => {
10255
+ const grid = Metadata.getInstance(`${this.name}-modal-selection-grid`);
10256
+ grid.datasource.currentRow = {};
10257
+ },
10258
+ },
10259
+ };
10260
+ if (!this.modalSelectionObj)
10261
+ this.modalSelectionObj = ModalService.create(modalSelectionDef);
10262
+ this.modalSelectionObj.show();
10263
+ }
10117
10264
  }
10118
10265
  FormatterParserProvider.registerFormatter('ZdSelect', (value, { dataText, dataTextSeparator = ' | ', }) => {
10119
10266
  if (value === null || value === undefined) {
@@ -10154,7 +10301,24 @@ FormatterParserProvider.registerFormatter('ZdSelect', (value, { dataText, dataTe
10154
10301
  return result;
10155
10302
  }, '');
10156
10303
  });
10157
- InputFactory.register('ZdSelect', Select);
10304
+ InputFactory.register('ZdSelect', Select);
10305
+ Messages.add({
10306
+ 'pt-BR': {
10307
+ translation: {
10308
+ SELECT_MODAL_KEYMAP: '(shift+enter) para abrir modal',
10309
+ },
10310
+ },
10311
+ 'en-US': {
10312
+ translation: {
10313
+ SELECT_MODAL_KEYMAP: '(shift+enter) to open modal',
10314
+ },
10315
+ },
10316
+ 'es-ES': {
10317
+ translation: {
10318
+ SELECT_MODAL_KEYMAP: '(shift+enter) para abrir el modal',
10319
+ },
10320
+ },
10321
+ });
10158
10322
 
10159
10323
  /**
10160
10324
  * Base class for Iterable Page Size component
@@ -10300,6 +10464,7 @@ class Search extends TextInput {
10300
10464
  this.placeholder = this.getInitValue('placeholder', props.placeholder, 'SEARCH');
10301
10465
  this.cssClass = this.getInitValue('cssClass', props.cssClass, 'zd-float-right');
10302
10466
  this.lazyAttach = this.getInitValue('lazyAttach', props.lazyAttach, this.lazyAttach);
10467
+ this.debounceSetSearch = this.debounceSetSearch.bind(this);
10303
10468
  if (!this.lazyAttach)
10304
10469
  this.setIterableComponent();
10305
10470
  this.createAccessors();
@@ -10318,7 +10483,7 @@ class Search extends TextInput {
10318
10483
  }
10319
10484
  setSearch(search) {
10320
10485
  return __awaiter(this, void 0, void 0, function* () {
10321
- yield this.iterableComponent.setSearch(search);
10486
+ yield this.iterableComponent.setSearch(search.component.internalValue);
10322
10487
  });
10323
10488
  }
10324
10489
  }
@@ -10441,7 +10606,7 @@ class IterableComponentRender extends Iterable {
10441
10606
  * Returns the iterable component metadata based on row data
10442
10607
  */
10443
10608
  getComponentMetadata(row) {
10444
- const exp = new RegExp(`<<${this.rowPropName}.(.[A-z]+?)>>|"<<${this.rowPropName}.(.[A-z]+?)>>"`, 'g');
10609
+ const exp = new RegExp(`<<${this.rowPropName}\\.([A-z_.]+?)>>|"<<${this.rowPropName}.(.[A-z_.]+?)>>"`, 'g');
10445
10610
  const rowExp = new RegExp(`"<<${this.rowPropName}>>"`, 'g');
10446
10611
  const metadata = JSON.stringify(this.componentMetadata)
10447
10612
  .replace(rowExp, JSON.stringify(row))
@@ -1921,7 +1921,7 @@
1921
1921
  this.internalDisplayValue = '';
1922
1922
  this.internalValue = null;
1923
1923
  this.formParent = this.getFormParent();
1924
- this.lastInputValue = undefined;
1924
+ this.lastInputValue = '';
1925
1925
  this.callInputEvent = debounce__default["default"](({ event, element, component }) => {
1926
1926
  this.callEvent('input', { event, element, component });
1927
1927
  }, 50);
@@ -5403,6 +5403,8 @@
5403
5403
  this.actionFactoredConditions = {};
5404
5404
  this.helperText = '';
5405
5405
  this.defaultData = [];
5406
+ /* Column search mode */
5407
+ this.searchMode = 'any';
5406
5408
  this.lookup = debounce__default["default"]((lookupColumn) => {
5407
5409
  this.loading = true;
5408
5410
  const dataToLookup = Array.from(new Set(this.dataToLookup)); // remove duplicates
@@ -5433,6 +5435,7 @@
5433
5435
  this.componentProps = this.getInitValue('componentProps', props.componentProps, this.componentProps);
5434
5436
  this.xlsType = this.getInitValue('xlsType', props.xlsType, this.xlsType);
5435
5437
  this.conditions = this.getInitValue('conditions', props.conditions, this.conditions);
5438
+ this.searchMode = this.getInitValue('searchMode', props.searchMode, this.searchMode);
5436
5439
  this.helperText = this.getInitValue('', props.helperText, this.helperText);
5437
5440
  this.createConditions();
5438
5441
  this.createActionConditions();
@@ -5593,6 +5596,7 @@
5593
5596
  class IterableController {
5594
5597
  constructor(iterable) {
5595
5598
  this.searchInValue = undefined;
5599
+ this.searchInParamsValue = undefined;
5596
5600
  this.iterable = iterable;
5597
5601
  }
5598
5602
  get searchIn() {
@@ -5605,6 +5609,16 @@
5605
5609
  set searchIn(value) {
5606
5610
  this.searchInValue = value;
5607
5611
  }
5612
+ get searchInParams() {
5613
+ return this.searchInParamsValue || this.iterable.columns.reduce((result, column) => {
5614
+ if (!!column.searchMode && column.searchMode !== 'any')
5615
+ result[column.name] = column.searchMode;
5616
+ return result;
5617
+ }, {});
5618
+ }
5619
+ set searchInParams(value) {
5620
+ this.searchInParamsValue = value;
5621
+ }
5608
5622
  }
5609
5623
 
5610
5624
  /**
@@ -5653,12 +5667,13 @@
5653
5667
  this.searchVisibleOnly = this.getInitValue('searchVisibleOnly', props.searchVisibleOnly, this.defaultSearchVisibleOnly);
5654
5668
  this.virtualScroll = this.getInitValue('virtualScroll', props.virtualScroll, this.virtualScroll);
5655
5669
  this.virtualScrollCache = this.getInitValue('virtualScrollCache', props.virtualScrollCache, this.virtualScrollCache);
5670
+ this.searchIn = this.getInitValue('searchIn', props.searchIn, this.searchIn);
5656
5671
  }
5657
5672
  getDatasourceDefaults() {
5658
5673
  return {};
5659
5674
  }
5660
5675
  initializeDatasource(props) {
5661
- var _a;
5676
+ var _a, _b;
5662
5677
  let datasourceProps = props.datasource;
5663
5678
  // if using accessor, get props from the controller
5664
5679
  if (typeof props.datasource === 'string' && core.Accessor.isAccessorDefinition(props.datasource)) {
@@ -5666,7 +5681,7 @@
5666
5681
  const instance = core.Loader.getInstance(controller);
5667
5682
  datasourceProps = instance[accessor];
5668
5683
  }
5669
- this.datasource = core.DatasourceFactory.factory(Object.assign(Object.assign(Object.assign({}, datasourceProps), this.getDatasourceDefaults()), { searchIn: ((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.searchIn) || `{{IterableController_${this.name}.searchIn}}` }));
5684
+ this.datasource = core.DatasourceFactory.factory(Object.assign(Object.assign(Object.assign({}, datasourceProps), this.getDatasourceDefaults()), { searchIn: ((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.searchIn) || `{{IterableController_${this.name}.searchIn}}`, searchInParams: ((_b = props.datasource) === null || _b === void 0 ? void 0 : _b.searchInParams) || `{{IterableController_${this.name}.searchInParams}}` }));
5670
5685
  }
5671
5686
  createController() {
5672
5687
  const controller = new IterableController(this);
@@ -5769,7 +5784,7 @@
5769
5784
  });
5770
5785
  }
5771
5786
  isColumnSearchable(column) {
5772
- return !this.searchVisibleOnly || column.isVisible;
5787
+ return (!this.searchVisibleOnly || column.isVisible) && (this.searchIn === undefined || this.searchIn === column.name);
5773
5788
  }
5774
5789
  }
5775
5790
 
@@ -5904,7 +5919,7 @@
5904
5919
  });
5905
5920
  }
5906
5921
  }
5907
- const textColumn = formatterDataText || dataTextDiscrete || dataTextForeign;
5922
+ const textColumn = dataTextDiscrete || formatterDataText || dataTextForeign;
5908
5923
  if (!textColumn)
5909
5924
  return value;
5910
5925
  if (typeof textColumn === 'string') {
@@ -7182,10 +7197,7 @@
7182
7197
  }
7183
7198
  let allValid = true;
7184
7199
  this.datasource.data.forEach((row) => this.columns.forEach((column) => {
7185
- const rowKey = row[this.datasource.uniqueKey];
7186
- const cellsApplied = (this.cellsApplied[rowKey] || {})[column.name];
7187
- const columnWithConditions = Object.assign(Object.assign({}, column), cellsApplied);
7188
- if (!column.isVisible || !columnWithConditions.editable)
7200
+ if (!this.isColumnEditable(column, row))
7189
7201
  return;
7190
7202
  if (!this.isValid(column, row, true))
7191
7203
  allValid = false;
@@ -7311,6 +7323,12 @@
7311
7323
  const column = this.getColumn(columnName);
7312
7324
  this.changeCell(rowKey, rowIdx, column, value);
7313
7325
  }
7326
+ isColumnEditable(column, row) {
7327
+ const rowKey = row[this.datasource.uniqueKey];
7328
+ const cellsApplied = (this.cellsApplied[rowKey] || {})[column.name];
7329
+ const columnWithConditions = Object.assign(Object.assign({}, column), cellsApplied);
7330
+ return column.isVisible && columnWithConditions.editable && this.callCanEditRow(row);
7331
+ }
7314
7332
  /**
7315
7333
  * Changes a cell value in editedRows
7316
7334
  * @param rowKey Cell's row key
@@ -7321,7 +7339,7 @@
7321
7339
  changeCell(rowKey, rowIdx, column, value) {
7322
7340
  const originalRow = this.datasource.data[rowIdx];
7323
7341
  // Column doesn't have component
7324
- if (!column.editable || !column.isVisible) {
7342
+ if (!this.isColumnEditable(column, originalRow)) {
7325
7343
  this.changeEditableComponent(column, originalRow, value);
7326
7344
  return;
7327
7345
  }
@@ -7897,6 +7915,7 @@
7897
7915
  success: 'mdi-check-circle',
7898
7916
  tableConfig: 'mdi-table-cog',
7899
7917
  tableColumns: 'mdi-table-headers-eye',
7918
+ tableSearch: 'mdi-table-search',
7900
7919
  unfold: 'mdi-unfold-more-horizontal',
7901
7920
  warning: 'mdi-exclamation',
7902
7921
  zoom: 'mdi-magnify',
@@ -7955,6 +7974,7 @@
7955
7974
  success: 'fa fa-check-circle',
7956
7975
  tableConfig: 'fa fa-columns',
7957
7976
  tableColumns: 'fa fa-columns',
7977
+ tableSearch: 'fa fa-search',
7958
7978
  unfold: 'fa fa-sort',
7959
7979
  warning: 'fa fa-exclamation',
7960
7980
  zoom: 'fa fa-search',
@@ -9648,6 +9668,10 @@
9648
9668
  */
9649
9669
  this.dataValueOutFormName = '';
9650
9670
  this.closeOnScroll = true;
9671
+ /* Defines if should open modal with grid to make the selection */
9672
+ this.modalSelection = false;
9673
+ /* Defines fields to show on modal */
9674
+ this.modalSelectionFields = [];
9651
9675
  this.dsSearch = {
9652
9676
  SEARCH: (value, searchIn) => ({
9653
9677
  searchIn: [searchIn],
@@ -9683,6 +9707,7 @@
9683
9707
  this.pushedValue = null;
9684
9708
  this.loadMoreQtty = 0;
9685
9709
  this.debounceSearch = debounce__default["default"](this.doSearch, 500);
9710
+ this.modalSelectionObj = undefined;
9686
9711
  this.appendIcon = this.getInitValue('appendIcon', props.appendIcon, 'expand');
9687
9712
  this.dataText = this.getInitValue('dataText', props.dataText, this.dataText);
9688
9713
  this.dataTextDiscrete = this.getInitValue('dataTextDiscrete', props.dataTextDiscrete, this.dataTextDiscrete);
@@ -9701,6 +9726,8 @@
9701
9726
  this.dataValueOut = this.getInitValue('dataValueOut', props.dataValueOut, this.dataValueOut);
9702
9727
  this.dataValueOutFormName = this.getInitValue('dataValueOutFormName', props.dataValueOutFormName, this.dataValueOutFormName);
9703
9728
  this.closeOnScroll = this.getInitValue('closeOnScroll', props.closeOnScroll, this.closeOnScroll);
9729
+ this.modalSelection = this.getInitValue('modalSelection', props.modalSelection, this.modalSelection);
9730
+ this.modalSelectionFields = this.getInitValue('modalSelectionFields', props.modalSelectionFields, this.modalSelectionFields);
9704
9731
  if (((_a = props.datasource) === null || _a === void 0 ? void 0 : _a.type) === 'simple') {
9705
9732
  this.dataValue = 'value';
9706
9733
  this.dataText = this.dataText || this.dataValue;
@@ -9713,8 +9740,8 @@
9713
9740
  dataText: this.dataTextDiscrete,
9714
9741
  dataTextSeparator: this.dataTextSeparator,
9715
9742
  };
9716
- const defaultDatasource = this.getDefaultDatasource(props);
9717
- this.datasource = core.DatasourceFactory.factory(defaultDatasource);
9743
+ this.defaultDatasource = this.getDefaultDatasource(props);
9744
+ this.datasource = core.DatasourceFactory.factory(this.defaultDatasource);
9718
9745
  this.overrideGet();
9719
9746
  let defaultValue = props.value;
9720
9747
  if (core.Accessor.isAccessorDefinition(props.value)) {
@@ -9722,7 +9749,7 @@
9722
9749
  this.getInitValue('value', props.value, this.value);
9723
9750
  }
9724
9751
  this.setDefaultValue(defaultValue, (_b = props.datasource) === null || _b === void 0 ? void 0 : _b.lazyLoad);
9725
- this.preventLoadOnFocus = !defaultDatasource.lazyLoad;
9752
+ this.preventLoadOnFocus = !this.defaultDatasource.lazyLoad;
9726
9753
  this.preventLoadOnFocus = this.getInitValue('preventLoadOnFocus', props.preventLoadOnFocus, this.preventLoadOnFocus);
9727
9754
  this.loadMoreQtty = this.datasource.limit;
9728
9755
  this.itemAfterSlot = props.itemAfterSlot || this.itemAfterSlot;
@@ -9736,6 +9763,31 @@
9736
9763
  const instance = core.Loader.getInstance(controller);
9737
9764
  return instance[accessor];
9738
9765
  }
9766
+ onMounted(element) {
9767
+ super.onMounted(element);
9768
+ if (this.modalSelection && this.modalSelectionFields.length) {
9769
+ core.KeyMap.bind({
9770
+ 'shift+enter': {
9771
+ active: true,
9772
+ input: true,
9773
+ stop: true,
9774
+ prevent: true,
9775
+ event: this.openModalSelection.bind(this),
9776
+ },
9777
+ }, this, element);
9778
+ }
9779
+ }
9780
+ onBeforeDestroy() {
9781
+ super.onBeforeDestroy();
9782
+ this.datasource.destroy();
9783
+ if (this.modalSelection && this.modalSelectionFields.length) {
9784
+ core.KeyMap.unbind({
9785
+ 'shift+enter': {
9786
+ event: this.openModalSelection.bind(this),
9787
+ },
9788
+ }, this);
9789
+ }
9790
+ }
9739
9791
  /**
9740
9792
  * Retrieves datasource structure applying infinity scroll
9741
9793
  * @param field Field structure
@@ -10110,10 +10162,6 @@
10110
10162
  && !this.datasource.loadAll
10111
10163
  && this.datasource.data.length - (this.pushedValue ? 1 : 0) < this.datasource.total;
10112
10164
  }
10113
- onBeforeDestroy() {
10114
- super.onBeforeDestroy();
10115
- this.datasource.destroy();
10116
- }
10117
10165
  indexOf(search) {
10118
10166
  const value = search && typeof search === 'object' ? search[this.dataValue] : search;
10119
10167
  return this.datasource.data.findIndex((row) => row[this.dataValue] === value);
@@ -10121,6 +10169,105 @@
10121
10169
  isFilledObj(obj) {
10122
10170
  return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.keys(obj).length;
10123
10171
  }
10172
+ hideModalSelection() {
10173
+ if (this.modalSelectionObj)
10174
+ this.modalSelectionObj.hide();
10175
+ }
10176
+ modalSelectionGridClick({ row }) {
10177
+ this.setValue(row);
10178
+ this.hideModalSelection();
10179
+ setTimeout(() => {
10180
+ if (this.viewCloseMenu)
10181
+ this.viewCloseMenu();
10182
+ }, 200);
10183
+ }
10184
+ openModalSelection() {
10185
+ const modalSelectionDef = {
10186
+ name: `${this.name}-modal-selection`,
10187
+ persistent: true,
10188
+ children: [
10189
+ {
10190
+ name: `${this.name}-modal-selection-content-container`,
10191
+ component: 'ZdContainer',
10192
+ scrollView: true,
10193
+ cssClass: 'zd-my-2 zd-pa-0 zd-select-modal-selection-content-container',
10194
+ children: [
10195
+ {
10196
+ name: `${this.name}-modal-selection-grid`,
10197
+ component: 'ZdGrid',
10198
+ cssClass: 'zd-my-2 zd-pa-0 zd-select-modal-selection-grid',
10199
+ columns: this.modalSelectionFields,
10200
+ datasource: Object.assign(Object.assign({}, this.defaultDatasource), { lazyLoad: false, searchIn: undefined }),
10201
+ toolbarSlot: [
10202
+ {
10203
+ name: `${this.name}-modal-selection-title`,
10204
+ component: 'ZdText',
10205
+ cssStyle: `color: ${'var(--v-primary-base);'}`,
10206
+ text: this.label,
10207
+ tag: 'h3',
10208
+ },
10209
+ {
10210
+ name: `${this.name}-modal-selection-spacer`,
10211
+ component: 'VSpacer',
10212
+ },
10213
+ {
10214
+ name: `${this.name}-modal-selection_gridSearch`,
10215
+ component: 'ZdSearch',
10216
+ cssClass: 'zd-grid-search',
10217
+ autofocus: true,
10218
+ },
10219
+ ],
10220
+ events: {
10221
+ rowClick: this.modalSelectionGridClick.bind(this),
10222
+ },
10223
+ },
10224
+ ],
10225
+ },
10226
+ {
10227
+ name: `${this.name}-modal-selection-footer-container`,
10228
+ component: 'ZdContainer',
10229
+ cssClass: 'zd-pa-0',
10230
+ children: [
10231
+ {
10232
+ name: `${this.name}-modal-selection-footer`,
10233
+ component: 'ZdFooter',
10234
+ color: 'transparent',
10235
+ padless: true,
10236
+ rightSlot: [
10237
+ {
10238
+ name: `${this.name}-modal-selection-cancelButton`,
10239
+ component: 'ZdButton',
10240
+ label: 'CANCEL',
10241
+ keyMap: {
10242
+ esc: {
10243
+ event: this.hideModalSelection.bind(this),
10244
+ focus: true,
10245
+ visible: true,
10246
+ input: true,
10247
+ stop: true,
10248
+ },
10249
+ },
10250
+ outline: true,
10251
+ events: {
10252
+ click: this.hideModalSelection.bind(this),
10253
+ },
10254
+ },
10255
+ ],
10256
+ },
10257
+ ],
10258
+ },
10259
+ ],
10260
+ events: {
10261
+ onShow: () => {
10262
+ const grid = core.Metadata.getInstance(`${this.name}-modal-selection-grid`);
10263
+ grid.datasource.currentRow = {};
10264
+ },
10265
+ },
10266
+ };
10267
+ if (!this.modalSelectionObj)
10268
+ this.modalSelectionObj = ModalService.create(modalSelectionDef);
10269
+ this.modalSelectionObj.show();
10270
+ }
10124
10271
  }
10125
10272
  core.FormatterParserProvider.registerFormatter('ZdSelect', (value, { dataText, dataTextSeparator = ' | ', }) => {
10126
10273
  if (value === null || value === undefined) {
@@ -10161,7 +10308,24 @@
10161
10308
  return result;
10162
10309
  }, '');
10163
10310
  });
10164
- InputFactory.register('ZdSelect', Select);
10311
+ InputFactory.register('ZdSelect', Select);
10312
+ core.Messages.add({
10313
+ 'pt-BR': {
10314
+ translation: {
10315
+ SELECT_MODAL_KEYMAP: '(shift+enter) para abrir modal',
10316
+ },
10317
+ },
10318
+ 'en-US': {
10319
+ translation: {
10320
+ SELECT_MODAL_KEYMAP: '(shift+enter) to open modal',
10321
+ },
10322
+ },
10323
+ 'es-ES': {
10324
+ translation: {
10325
+ SELECT_MODAL_KEYMAP: '(shift+enter) para abrir el modal',
10326
+ },
10327
+ },
10328
+ });
10165
10329
 
10166
10330
  /**
10167
10331
  * Base class for Iterable Page Size component
@@ -10307,6 +10471,7 @@
10307
10471
  this.placeholder = this.getInitValue('placeholder', props.placeholder, 'SEARCH');
10308
10472
  this.cssClass = this.getInitValue('cssClass', props.cssClass, 'zd-float-right');
10309
10473
  this.lazyAttach = this.getInitValue('lazyAttach', props.lazyAttach, this.lazyAttach);
10474
+ this.debounceSetSearch = this.debounceSetSearch.bind(this);
10310
10475
  if (!this.lazyAttach)
10311
10476
  this.setIterableComponent();
10312
10477
  this.createAccessors();
@@ -10325,7 +10490,7 @@
10325
10490
  }
10326
10491
  setSearch(search) {
10327
10492
  return __awaiter(this, void 0, void 0, function* () {
10328
- yield this.iterableComponent.setSearch(search);
10493
+ yield this.iterableComponent.setSearch(search.component.internalValue);
10329
10494
  });
10330
10495
  }
10331
10496
  }
@@ -10448,7 +10613,7 @@
10448
10613
  * Returns the iterable component metadata based on row data
10449
10614
  */
10450
10615
  getComponentMetadata(row) {
10451
- const exp = new RegExp(`<<${this.rowPropName}.(.[A-z]+?)>>|"<<${this.rowPropName}.(.[A-z]+?)>>"`, 'g');
10616
+ const exp = new RegExp(`<<${this.rowPropName}\\.([A-z_.]+?)>>|"<<${this.rowPropName}.(.[A-z_.]+?)>>"`, 'g');
10452
10617
  const rowExp = new RegExp(`"<<${this.rowPropName}>>"`, 'g');
10453
10618
  const metadata = JSON.stringify(this.componentMetadata)
10454
10619
  .replace(rowExp, JSON.stringify(row))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeedhi/common",
3
- "version": "1.105.0",
3
+ "version": "1.106.0",
4
4
  "description": "Zeedhi Common",
5
5
  "author": "Zeedhi <zeedhi@teknisa.com>",
6
6
  "license": "ISC",
@@ -43,5 +43,5 @@
43
43
  "lodash.times": "4.3.*",
44
44
  "mockdate": "3.0.*"
45
45
  },
46
- "gitHead": "bac0dd5514d2a2e47f68c9e3b950e3041cf4aad4"
46
+ "gitHead": "58e22407f4dc955b797447dafc639d59358e0e16"
47
47
  }
@@ -233,6 +233,7 @@ export declare class GridEditable extends Grid implements IGridEditable {
233
233
  * @throws RowNotFoundError If the row is not present in datasource
234
234
  */
235
235
  updateCell(rowKey: string, columnName: string, value: any): void;
236
+ private isColumnEditable;
236
237
  /**
237
238
  * Changes a cell value in editedRows
238
239
  * @param rowKey Cell's row key
@@ -1,5 +1,5 @@
1
1
  import { IDictionary, Datasource, IEvents } from '@zeedhi/core';
2
- import { IColumn, ColumnAlign, ColumnType } from './interfaces';
2
+ import { IColumn, ColumnAlign, ColumnType, ColumnSearchMode } from './interfaces';
3
3
  import { Component } from '../zd-component/component';
4
4
  /**
5
5
  * Base class for Column.
@@ -42,6 +42,7 @@ export declare class Column extends Component implements IColumn {
42
42
  private viewGetWidth?;
43
43
  helperText: string;
44
44
  protected defaultData: IDictionary[];
45
+ searchMode: ColumnSearchMode;
45
46
  /**
46
47
  * Creates a new Column.
47
48
  * @param props Column properties
@@ -8,6 +8,7 @@ export interface IIterableEvents<T = IEventParam<any>> extends IComponentEvents<
8
8
  }
9
9
  export declare type ColumnAlign = 'left' | 'center' | 'right';
10
10
  export declare type ColumnType = 'action';
11
+ export declare type ColumnSearchMode = 'beginning' | 'end' | 'any';
11
12
  export interface IColumn extends IComponent {
12
13
  align?: ColumnAlign;
13
14
  label?: string;
@@ -26,6 +27,7 @@ export interface IColumn extends IComponent {
26
27
  style?: IDictionary;
27
28
  events?: IIterableEvents;
28
29
  xlsType?: string;
30
+ searchMode?: ColumnSearchMode;
29
31
  }
30
32
  export interface IIterable extends IComponentRender {
31
33
  columns?: IColumn[];
@@ -34,6 +36,7 @@ export interface IIterable extends IComponentRender {
34
36
  virtualScroll?: boolean;
35
37
  virtualScrollCache?: number;
36
38
  searchVisibleOnly?: boolean;
39
+ searchIn?: string | undefined;
37
40
  }
38
41
  export interface IIterablePageComponent extends IComponentRender {
39
42
  iterableComponentName?: string;
@@ -1,8 +1,12 @@
1
+ import { IDictionary } from '@zeedhi/core';
1
2
  import { Iterable } from './iterable';
2
3
  export declare class IterableController {
3
4
  private iterable;
4
5
  private searchInValue?;
6
+ private searchInParamsValue?;
5
7
  constructor(iterable: Iterable);
6
8
  get searchIn(): string[] | undefined;
7
9
  set searchIn(value: string[] | undefined);
10
+ get searchInParams(): IDictionary<any> | undefined;
11
+ set searchInParams(value: IDictionary<any> | undefined);
8
12
  }
@@ -44,6 +44,7 @@ export declare class Iterable extends ComponentRender implements IIterable {
44
44
  * Defines if searchIn should consider only visible columns or not
45
45
  */
46
46
  searchVisibleOnly: boolean;
47
+ searchIn: string | undefined;
47
48
  defaultSearchVisibleOnly: boolean;
48
49
  /**
49
50
  * Creates a new Iterable.
@@ -20,6 +20,6 @@ export declare class Search extends TextInput implements ISearch {
20
20
  */
21
21
  constructor(props: ISearch);
22
22
  setIterableComponent(name?: string): void;
23
- protected setSearch(search: string): Promise<void>;
23
+ protected setSearch(search: any): Promise<void>;
24
24
  debounceSetSearch: (search: string) => void;
25
25
  }
@@ -2,6 +2,7 @@ import { IDatasource } from '@zeedhi/core';
2
2
  import { ITextInput } from '../zd-text-input/interfaces';
3
3
  import { IComponentRender } from '../zd-component/interfaces';
4
4
  import { ISelectDataValueOut } from '../../utils';
5
+ import { IColumn } from '../zd-iterable/interfaces';
5
6
  export declare type SearchParam = 'SEARCH' | 'FILTER' | 'FIND' | 'DYNAMIC_FILTER';
6
7
  export interface ISelect extends ITextInput, ISelectDataValueOut {
7
8
  autocomplete?: boolean;
@@ -23,4 +24,6 @@ export interface ISelect extends ITextInput, ISelectDataValueOut {
23
24
  attach?: boolean;
24
25
  searchParam?: string;
25
26
  closeOnScroll?: boolean;
27
+ modalSelection?: boolean;
28
+ modalSelectionFields?: IColumn[];
26
29
  }
@@ -1,8 +1,9 @@
1
- import { Datasource, IDictionary } from '@zeedhi/core';
1
+ import { Datasource, IDictionary, IDatasource } from '@zeedhi/core';
2
2
  import { IComponentRender } from '../zd-component/interfaces';
3
3
  import { ISelect, SearchParam } from './interfaces';
4
4
  import { TextInput } from '../zd-text-input/text-input';
5
5
  import { ISelectDataValueOutItem } from '../../utils';
6
+ import { IColumn } from '../zd-iterable/interfaces';
6
7
  /**
7
8
  * Base class for Select component.
8
9
  */
@@ -92,6 +93,8 @@ export declare class Select extends TextInput implements ISelect {
92
93
  */
93
94
  dataValueOutFormName: string;
94
95
  closeOnScroll: boolean;
96
+ modalSelection?: boolean | undefined;
97
+ modalSelectionFields: IColumn[];
95
98
  protected dsSearch: {
96
99
  SEARCH: (value: any, searchIn: string) => {
97
100
  searchIn: string[];
@@ -128,14 +131,18 @@ export declare class Select extends TextInput implements ISelect {
128
131
  protected cachedTotal: number;
129
132
  protected formatterFn: Function;
130
133
  private pushedValue;
134
+ viewCloseMenu?: () => void;
131
135
  private discreteProps?;
132
136
  protected loadMoreQtty: number;
137
+ protected defaultDatasource: IDatasource;
133
138
  /**
134
139
  * Create a new Select.
135
140
  * @param props Select properties
136
141
  */
137
142
  constructor(props: ISelect);
138
143
  private getAccessorValue;
144
+ onMounted(element: any): void;
145
+ onBeforeDestroy(): void;
139
146
  /**
140
147
  * Retrieves datasource structure applying infinity scroll
141
148
  * @param field Field structure
@@ -230,7 +237,10 @@ export declare class Select extends TextInput implements ISelect {
230
237
  blur(event: Event, element: any): void;
231
238
  protected checkValueOnBlur(): void;
232
239
  showLoadMore(): boolean;
233
- onBeforeDestroy(): void;
234
240
  indexOf(search: IDictionary | string | number): number;
235
241
  protected isFilledObj(obj: any): number | false;
242
+ private modalSelectionObj?;
243
+ private hideModalSelection;
244
+ private modalSelectionGridClick;
245
+ openModalSelection(): void;
236
246
  }