@zeedhi/common 1.53.0 → 1.54.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.
@@ -5525,6 +5525,7 @@
5525
5525
  };
5526
5526
  this.newRowIdentifier = '__added_row';
5527
5527
  this.doubleClickEdit = this.getInitValue('doubleClickEdit', props.doubleClickEdit, this.doubleClickEdit);
5528
+ this.canEditRow = this.getInitValue('canEditRow', props.canEditRow, this.canEditRow);
5528
5529
  this.createAccessors();
5529
5530
  }
5530
5531
  onMounted(element) {
@@ -5577,10 +5578,10 @@
5577
5578
  * @param event DOM event
5578
5579
  * @param element DOM Element
5579
5580
  */
5580
- cellClick(row, column, event, element) {
5581
+ cellClick(row, column, event, element, canEdit = true) {
5581
5582
  if (this.editing)
5582
5583
  return;
5583
- if (column.editable) {
5584
+ if (column.editable && canEdit) {
5584
5585
  this.editing = true;
5585
5586
  this.preventRowClick = true;
5586
5587
  this.datasource.currentRow = row;
@@ -5929,6 +5930,9 @@
5929
5930
  throw e;
5930
5931
  }
5931
5932
  }
5933
+ callCanEditRow(row) {
5934
+ return !this.canEditRow || typeof this.canEditRow !== 'function' || this.canEditRow({ row, component: this });
5935
+ }
5932
5936
  }
5933
5937
 
5934
5938
  /**
@@ -10236,7 +10240,7 @@
10236
10240
  /**
10237
10241
  * Defines the format of a time displayed in picker. Available options are ampm and 24hr.
10238
10242
  */
10239
- this.timeFormat = core.Config.timeFormat || 'ampm';
10243
+ this.timeFormat = core.Config.timeFormat || 'ampm'; // change props to pickerFormat
10240
10244
  /**
10241
10245
  * Forces 100% width.
10242
10246
  */
@@ -10267,29 +10271,18 @@
10267
10271
  this.width = 290;
10268
10272
  this.formatterFn = core.FormatterParserProvider.getFormatter('ZdTime');
10269
10273
  this.parserFn = core.FormatterParserProvider.getParser('ZdTime');
10274
+ this.isoFormatValue = 'HH:mm';
10275
+ this.valueFormatInternal = core.Config.valueTimeFormat;
10276
+ this.displayFormatInternal = core.Config.displayTimeFormat;
10270
10277
  /**
10271
- * Map of the mask functions
10272
- */
10273
- this.maskFunctions = {
10274
- ampm: () => this.ampmMask(),
10275
- '24hr': (value) => this.fullTimeMask(value),
10276
- };
10277
- /**
10278
- * Format used in time value
10278
+ * Defines the time input format.
10279
10279
  */
10280
- this.valueFormat = core.Config.valueTimeFormat;
10281
- /**
10282
- * Format used to display the value
10283
- */
10284
- this.displayFormat = core.Config.displayTimeFormat;
10280
+ this.inputFormat = core.Config.timeInputFormat;
10285
10281
  /**
10286
10282
  * True when displayValue is valid
10287
10283
  */
10288
10284
  this.isDisplayValid = true;
10289
- /**
10290
- * Last invalid value passed to formatter
10291
- */
10292
- this.lastInvalid = '';
10285
+ this.timeError = false;
10293
10286
  this.allowedHours = this.getInitValue('allowedHours', props.allowedHours, this.allowedHours);
10294
10287
  this.allowedMinutes = this.getInitValue('allowedMinutes', props.allowedMinutes, this.allowedMinutes);
10295
10288
  this.allowedSeconds = this.getInitValue('allowedSeconds', props.allowedSeconds, this.allowedSeconds);
@@ -10303,40 +10296,40 @@
10303
10296
  this.useSeconds = this.getInitValue('useSeconds', props.useSeconds, this.useSeconds);
10304
10297
  this.width = this.getInitValue('width', props.width, this.width);
10305
10298
  this.autofill = this.getInitValue('autofill', props.autofill, this.autofill);
10306
- this.mask = this.getInitValue('mask', props.mask, this.getMask);
10307
10299
  this.timeValidation = this.timeValidation.bind(this);
10300
+ this.valueFormat = this.getInitValue('valueFormat', props.valueFormat, this.valueFormatInternal);
10301
+ this.displayFormat = this.getInitValue('displayFormat', props.displayFormat, this.displayFormatInternal);
10302
+ this.inputFormat = this.getInitValue('inputFormat', props.inputFormat, this.inputFormat);
10308
10303
  this.timeAllowedValidation = this.timeAllowedValidation.bind(this);
10309
10304
  this.rules.push(this.timeValidation, this.timeAllowedValidation);
10310
- this.valueFormat = this.getInitValue('valueFormat', props.valueFormat, this.valueFormat);
10311
- this.displayFormat = this.getInitValue('displayFormat', props.displayFormat, this.displayFormat);
10305
+ this.mask = this.getInitValue('mask', props.mask, undefined);
10312
10306
  this.createAccessors();
10313
- this.createFormatAccessors();
10314
- }
10315
- createFormatAccessors() {
10316
- if (!this.valueFormat) {
10317
- Object.defineProperty(this, 'valueFormat', {
10318
- get: () => this.defaultValueFmt,
10319
- set: (valueFormat) => {
10320
- delete this.valueFormat;
10321
- this.valueFormat = valueFormat;
10322
- },
10323
- });
10307
+ this.initialMask = this.getInitialMask();
10308
+ this.isSimpleDisplay = this.isSimpleFormat(this.displayFormat);
10309
+ }
10310
+ get displayFormat() {
10311
+ const commonsDisplay = ['hh:mm A', 'hh:mm:ss A', 'HH:mm:ss', 'HH:mm'];
10312
+ if (commonsDisplay.includes(this.displayFormatInternal)) {
10313
+ this.displayFormatInternal = this.defaultFormats[this.timeFormat];
10324
10314
  }
10325
- if (!this.displayFormat) {
10326
- Object.defineProperty(this, 'displayFormat', {
10327
- get: () => this.defaultDisplayFmt,
10328
- set: (displayFormat) => {
10329
- delete this.displayFormat;
10330
- this.displayFormat = displayFormat;
10331
- },
10332
- });
10315
+ return this.displayFormatInternal;
10316
+ }
10317
+ set displayFormat(value) {
10318
+ this.displayFormatInternal = value;
10319
+ }
10320
+ get valueFormat() {
10321
+ const commonsDisplay = ['hh:mm A', 'hh:mm:ss A', 'HH:mm:ss', 'HH:mm'];
10322
+ if (commonsDisplay.includes(this.valueFormatInternal)) {
10323
+ this.valueFormatInternal = this.defaultFormats['24hr'];
10333
10324
  }
10325
+ return this.valueFormatInternal;
10334
10326
  }
10335
- get defaultValueFmt() {
10336
- return this.defaultFormats['24hr'];
10327
+ set valueFormat(value) {
10328
+ this.valueFormatInternal = value;
10337
10329
  }
10338
- get defaultDisplayFmt() {
10339
- return this.defaultFormats[this.timeFormat];
10330
+ get isoFormat() {
10331
+ this.isoFormatValue = this.useSeconds ? 'HH:mm:ss' : 'HH:mm';
10332
+ return this.isoFormatValue;
10340
10333
  }
10341
10334
  get defaultFormats() {
10342
10335
  const seconds = this.useSeconds ? ':ss' : '';
@@ -10345,59 +10338,172 @@
10345
10338
  '24hr': `HH:mm${seconds}`,
10346
10339
  };
10347
10340
  }
10348
- ampmMask() {
10349
- const ampmValue = this.displayValue || '';
10350
- const hours = [/[0-1]/];
10351
- if (ampmValue[0] === '1') {
10352
- hours.push(/[0-2]/);
10341
+ getInitialMask() {
10342
+ if (isUndefined__default["default"](this.mask)) {
10343
+ this.mask = this.inputFormat && this.maskFormat(this.inputFormat);
10344
+ }
10345
+ return this.mask;
10346
+ }
10347
+ formatter(value) { return this.formatterFn(value, this); }
10348
+ parser(value) { return this.parserFn(value, this); }
10349
+ /**
10350
+ * Triggered when date is clicked.
10351
+ * @param event
10352
+ * @param element
10353
+ */
10354
+ selectTime(time, event, element) {
10355
+ if (this.events.onSelectTime && typeof this.events.onSelectTime === 'function') {
10356
+ this.events.onSelectTime({
10357
+ time, event, element, component: this,
10358
+ });
10359
+ }
10360
+ }
10361
+ get displayValue() {
10362
+ return this.internalDisplayValue;
10363
+ }
10364
+ set displayValue(newValue) {
10365
+ this.timeError = false;
10366
+ this.internalDisplayValue = newValue;
10367
+ this.internalValue = this.parser(newValue);
10368
+ this.value = this.internalValue; // forces value accessor to be called if necessary
10369
+ }
10370
+ /**
10371
+ * Assign the updated mask to mask property
10372
+ */
10373
+ updateMask() {
10374
+ this.isSimpleDisplay = this.isSimpleFormat(this.displayFormat);
10375
+ this.mask = this.getUpdatedMask();
10376
+ return this.mask;
10377
+ }
10378
+ /**
10379
+ * Gets the updated masked, based on displayFormat if the initial mask is undefined
10380
+ */
10381
+ getUpdatedMask() {
10382
+ if (isUndefined__default["default"](this.initialMask)) {
10383
+ return this.maskFormat(this.displayFormat);
10353
10384
  }
10354
- else if (ampmValue[0] === '0') {
10355
- hours.push(/[1-9]/);
10385
+ return this.mask;
10386
+ }
10387
+ maskFormat(format) {
10388
+ return format.replace(/[A-Za-z]/gi, '#');
10389
+ }
10390
+ setTimeValue(displayValue) {
10391
+ const lastValue = this.displayValue;
10392
+ if (this.isValidTime(displayValue, this.displayFormat)) {
10393
+ this.internalDisplayValue = displayValue;
10394
+ this.internalValue = this.parser(displayValue);
10395
+ this.timeError = false;
10396
+ if (lastValue !== this.displayValue)
10397
+ this.change(this.value);
10356
10398
  }
10357
10399
  else {
10358
- hours.push(/[0-9]/);
10400
+ if (!displayValue) {
10401
+ this.internalDisplayValue = displayValue;
10402
+ this.internalValue = null;
10403
+ if (lastValue !== this.displayValue)
10404
+ this.change(this.value);
10405
+ }
10406
+ this.timeError = !!displayValue;
10359
10407
  }
10360
- const minutes = [/[0-5]/, /[0-9]/];
10361
- const seconds = this.useSeconds ? [':', ...minutes] : [];
10362
- const ampm = /(A|P)/;
10363
- return [...hours, ':', ...minutes, ...seconds, ' ', ampm, 'M'];
10408
+ this.value = this.internalValue; // forces value accessor to be called if necessary
10364
10409
  }
10365
- fullTimeMask(value) {
10366
- const hours = [
10367
- /[0-2]/,
10368
- value[0] === '2' ? /[0-3]/ : /[0-9]/,
10369
- ];
10370
- const minutes = [/[0-5]/, /[0-9]/];
10371
- const seconds = this.useSeconds ? [':', ...minutes] : [];
10372
- return [...hours, ':', ...minutes, ...seconds];
10410
+ isValidTime(value, format, strict = true) {
10411
+ return core.dayjs(value, format, strict).isValid();
10373
10412
  }
10374
- getMask(value) {
10375
- return this.maskFunctions[this.timeFormat](value);
10413
+ get isoValue() {
10414
+ return this.formatISOTimeValue(this.value);
10415
+ }
10416
+ set isoValue(newValue) {
10417
+ const lastValue = this.value;
10418
+ this.timeError = false;
10419
+ this.value = this.parseISOTimeValue(newValue);
10420
+ if (lastValue !== this.value)
10421
+ this.change(this.value);
10422
+ }
10423
+ formatISOTimeValue(value) {
10424
+ if (value && this.isValidTime(value, this.valueFormat)) {
10425
+ return core.dayjs(value, this.valueFormat).format(this.isoFormat);
10426
+ }
10427
+ return '';
10428
+ }
10429
+ parseISOTimeValue(value) {
10430
+ if (value && this.isValidTime(value, this.valueFormat)) {
10431
+ return core.dayjs(value, this.isoFormat).format(this.valueFormat);
10432
+ }
10433
+ return null;
10376
10434
  }
10377
10435
  /**
10378
- * Checks if value is valid according to valueFormat and if displayValue
10379
- * is true
10380
- */
10381
- isFullyValid(value = this.value) {
10382
- return this.isValidTime(value) && this.isDisplayValid;
10436
+ * Checks if a time format is simple.
10437
+ * Simple time formats are the ones that consists only of 'HH', 'mm', 'mm' or 'YYYY', and mask delimiters
10438
+ * @param format The format to be checked
10439
+ * @returns true if it is simple, false otherwise
10440
+ */
10441
+ isSimpleFormat(format) {
10442
+ const simpleTokens = ['HH', 'mm', 'ss', 'hh', 'A', 'a', 'p', 'P'];
10443
+ // remove the simple tokens from the string
10444
+ const replaced = simpleTokens.reduce((result, token) => result.replace(token, ''), format);
10445
+ const chars = replaced.split('');
10446
+ return chars.length ? chars.every((char) => core.Mask.isMaskDelimiter(char)) : true;
10383
10447
  }
10384
- formatter(value) {
10385
- const eq = this.lastInvalid === value;
10386
- if (eq || !this.isFullyValid(value)) {
10387
- this.isDisplayValid = true;
10388
- this.lastInvalid = value;
10389
- return value;
10448
+ timeValidation() {
10449
+ if (this.isValidTime(this.displayValue, this.displayFormat) || !this.displayValue) {
10450
+ return true;
10390
10451
  }
10391
- return this.formatterFn(value, this);
10452
+ return core.I18n.translate('VALIDATION_INVALID_TIME');
10453
+ }
10454
+ timeAllowedValidation() {
10455
+ return !this.displayValue
10456
+ || (this.isValidTime(this.displayValue, this.displayFormat)
10457
+ && this.isTimeAllowed())
10458
+ || core.I18n.translate('VALIDATION_TIME_NOT_ALLOWED');
10459
+ }
10460
+ click(event, element) {
10461
+ const clickEvent = event || new MouseEvent('click');
10462
+ super.click(clickEvent, element);
10463
+ if (!clickEvent.defaultPrevented) {
10464
+ this.showTimePicker = !this.showTimePicker;
10465
+ }
10466
+ }
10467
+ blur(event, element) {
10468
+ this.removeTimeMask();
10469
+ this.setTimeValue(this.formatter(this.value));
10470
+ super.blur(event, element);
10471
+ this.showTimePicker = false;
10472
+ }
10473
+ focus(event, element) {
10474
+ this.addTimeMask();
10475
+ super.focus(event, element);
10392
10476
  }
10393
- parser(value) {
10394
- const parsed = this.parserFn(value, this);
10395
- this.isDisplayValid = value === null || value === '' || this.isValidTime(value, this.displayFormat);
10396
- return parsed;
10477
+ /**
10478
+ * Add date mask
10479
+ */
10480
+ addTimeMask() {
10481
+ if (!this.value)
10482
+ return;
10483
+ this.mask = this.initialMask;
10484
+ this.internalDisplayValue = core.dayjs(this.value, this.valueFormat).format(this.inputFormat || this.displayFormat);
10397
10485
  }
10398
- isValidTime(value, format = this.valueFormat) {
10399
- return core.dayjs(value, format, true).isValid();
10486
+ /**
10487
+ * Removes the component mask if value is valid
10488
+ */
10489
+ removeTimeMask() {
10490
+ if (isUndefined__default["default"](this.initialMask) || !this.value || this.timeError
10491
+ || !this.isValidTime(this.value, this.valueFormat)) {
10492
+ return;
10493
+ }
10494
+ this.mask = '';
10400
10495
  }
10496
+ /**
10497
+ * Checks if value is valid according to valueFormat and if displayValue
10498
+ * is true
10499
+ */
10500
+ isFullyValid(value = this.value) {
10501
+ return this.isValidTime(value, this.valueFormat, true) && this.isDisplayValid;
10502
+ }
10503
+ /**
10504
+ * Last invalid value passed to formatter
10505
+ */
10506
+ // private lastInvalid: string = '';
10401
10507
  isTimeAllowed(value = this.value) {
10402
10508
  return this.isSameOrAfterMin(value) && this.isSameOrBeforeMax(value)
10403
10509
  && this.isHourAllowed(value) && this.isMinuteAllowed(value)
@@ -10433,49 +10539,54 @@
10433
10539
  const second = core.dayjs(value, this.valueFormat).second();
10434
10540
  return this.allowedSeconds.includes(second);
10435
10541
  }
10436
- timeValidation() {
10437
- return !this.displayValue
10438
- || this.isValidTime(this.displayValue, this.displayFormat)
10439
- || core.I18n.translate('VALIDATION_INVALID_TIME');
10440
- }
10441
- timeAllowedValidation() {
10442
- return !this.displayValue
10443
- || (this.isValidTime(this.displayValue, this.displayFormat)
10444
- && this.isTimeAllowed())
10445
- || core.I18n.translate('VALIDATION_TIME_NOT_ALLOWED');
10446
- }
10447
- click(event) {
10448
- this.callEvent('click', {
10449
- event: (event || new MouseEvent('click')),
10450
- component: this,
10451
- });
10452
- if (!(event === null || event === void 0 ? void 0 : event.defaultPrevented)) {
10453
- this.showTimePicker = !this.showTimePicker;
10454
- }
10455
- }
10456
10542
  clear() {
10457
10543
  this.value = null;
10458
10544
  this.change(this.value);
10459
10545
  }
10460
10546
  }
10461
- core.FormatterParserProvider.registerFormatter('ZdTime', (value, { displayFormat = core.Config.displayFormat, valueFormat = core.Config.valueTimeFormat, } = {}) => {
10547
+ core.FormatterParserProvider.registerFormatter('ZdTime', (value, { valueFormat = core.Config.valueTimeFormat, displayFormat = core.Config.displayTimeFormat, inputFormat = core.Config.timeInputFormat, mask = '', initialMask, isSimpleDisplay = false, } = {}) => {
10462
10548
  if (!value) {
10463
10549
  return '';
10464
10550
  }
10465
- if (core.dayjs(value, valueFormat, true).isValid()) {
10466
- return core.dayjs(value, valueFormat).format(displayFormat);
10551
+ const isTimeValid = core.dayjs(value, valueFormat, true).isValid();
10552
+ if (!isTimeValid) {
10553
+ return value;
10467
10554
  }
10468
- return value;
10555
+ if (mask && initialMask) {
10556
+ if (inputFormat) {
10557
+ return core.dayjs(value, valueFormat).format(inputFormat);
10558
+ }
10559
+ let valueToUnmask = value;
10560
+ if (isSimpleDisplay) {
10561
+ valueToUnmask = core.dayjs(value, valueFormat).format(displayFormat);
10562
+ }
10563
+ const unmasked = core.Mask.getValueWithoutMask(valueToUnmask);
10564
+ const masked = core.Mask.getValueWithMask(unmasked, mask);
10565
+ return masked;
10566
+ }
10567
+ return core.dayjs(value, valueFormat).format(displayFormat);
10469
10568
  });
10470
- core.FormatterParserProvider.registerParser('ZdTime', (value, { displayFormat = core.Config.displayFormat, valueFormat = core.Config.valueTimeFormat, } = {}) => {
10569
+ core.FormatterParserProvider.registerParser('ZdTime', (value, { displayFormat = core.Config.displayTimeFormat, valueFormat = core.Config.valueTimeFormat, mask = '', initialMask, } = {}) => {
10471
10570
  if (!value) {
10472
10571
  return null;
10473
10572
  }
10474
- const uppecaseValue = value.toUpperCase();
10475
- if (core.dayjs(uppecaseValue, displayFormat, true).isValid()) {
10476
- return core.dayjs(uppecaseValue, displayFormat).format(valueFormat);
10573
+ if (core.dayjs(value, displayFormat, true).isValid()) {
10574
+ return core.dayjs(value, displayFormat).format(valueFormat);
10477
10575
  }
10478
- return uppecaseValue;
10576
+ if (mask && core.Mask.checkMask(value, mask)) {
10577
+ const unmasked = core.Mask.getValueWithoutMask(value);
10578
+ let masked;
10579
+ if (!initialMask) {
10580
+ const displayFmtMask = displayFormat.replace(/[A-Za-z]/gi, '#');
10581
+ masked = core.Mask.getValueWithMask(unmasked, displayFmtMask);
10582
+ }
10583
+ const timeFmtMask = valueFormat.replace(/[A-Za-z]/gi, '#');
10584
+ masked = core.Mask.getValueWithMask(unmasked, timeFmtMask);
10585
+ if (core.dayjs(masked, valueFormat, true).format(valueFormat) === masked) {
10586
+ return masked;
10587
+ }
10588
+ }
10589
+ return value;
10479
10590
  });
10480
10591
 
10481
10592
  /**
@@ -10617,6 +10728,7 @@
10617
10728
  this.checkedField = this.getInitValue('checkedField', props.checkedField, this.checkedField);
10618
10729
  this.openLevelOnLoad = this.getInitValue('openLevelOnLoad', props.openLevelOnLoad, this.openLevelOnLoad);
10619
10730
  this.checkbox = this.getInitValue('checkbox', props.checkbox, this.checkbox);
10731
+ this.disableCheckbox = this.getInitValue('disableCheckbox', props.disableCheckbox, this.disableCheckbox);
10620
10732
  this.afterTitleSlot = props.afterTitleSlot || this.afterTitleSlot;
10621
10733
  this.toolbarSlot = props.toolbarSlot || this.toolbarSlot;
10622
10734
  this.titleSlot = props.titleSlot || this.titleSlot;
@@ -10852,16 +10964,13 @@
10852
10964
  const compName = component.name;
10853
10965
  const instanceName = `${compName}_${nodePath}`;
10854
10966
  const path = parentPath ? `${parentPath}.${compName}` : compName;
10855
- const newComponent = merge__default["default"]({}, component, (_a = this.appliedConditions[nodePath]) === null || _a === void 0 ? void 0 : _a[path]);
10967
+ const newInstances = core.Metadata.getInstances(instanceName);
10968
+ const newInstance = newInstances[0];
10969
+ const appliedConditions = (_a = this.appliedConditions[nodePath]) === null || _a === void 0 ? void 0 : _a[path];
10970
+ const newComponent = merge__default["default"]({}, component, newInstance, appliedConditions);
10856
10971
  const newChildren = this.getSlotComponent(newComponent.children || [], node, path);
10857
10972
  newComponent.name = instanceName;
10858
10973
  newComponent.children = newChildren;
10859
- try {
10860
- core.Metadata.updateInstance(instanceName, newComponent);
10861
- }
10862
- catch (e) {
10863
- // do nothing
10864
- }
10865
10974
  newComponents.push(newComponent);
10866
10975
  });
10867
10976
  return newComponents;
@@ -10923,6 +11032,10 @@
10923
11032
  return this.searchPath(currentNode.children || [], path.slice(1));
10924
11033
  return currentNode;
10925
11034
  }
11035
+ callDisableCheckbox(node) {
11036
+ return !!this.disableCheckbox && typeof this.disableCheckbox === 'function'
11037
+ && this.disableCheckbox({ node, component: this });
11038
+ }
10926
11039
  }
10927
11040
 
10928
11041
  /**
@@ -11069,6 +11182,8 @@
11069
11182
  const rows = [row, ...this.treeDataStructure.getChildren(row)];
11070
11183
  if (isSelected) {
11071
11184
  this.selectedRows = Array.from(new Set(this.selectedRows.concat(rows))); // remove duplicates
11185
+ // check if all the children of the parent are selected.
11186
+ this.selectParents(rows, row);
11072
11187
  }
11073
11188
  else {
11074
11189
  rows.forEach((item) => {
@@ -11076,6 +11191,31 @@
11076
11191
  if (index > -1)
11077
11192
  this.selectedRows.splice(index, 1);
11078
11193
  });
11194
+ this.unselectParents(row);
11195
+ }
11196
+ }
11197
+ selectParents(rows, row) {
11198
+ if (row[this.parentField]) {
11199
+ const parentRow = this.treeDataStructure.getRowData(row).tree__parent;
11200
+ const every = this.treeDataStructure.getChildren(parentRow).every((item) => {
11201
+ const index = this.treeDataStructure.findDataIndex(this.selectedRows, item[this.datasource.uniqueKey]);
11202
+ if (index > -1)
11203
+ return true;
11204
+ return false;
11205
+ });
11206
+ if (every)
11207
+ rows.push(parentRow);
11208
+ this.selectedRows = Array.from(new Set(this.selectedRows.concat(rows))); // remove duplicates
11209
+ this.selectParents(rows, parentRow);
11210
+ }
11211
+ }
11212
+ unselectParents(row) {
11213
+ if (row[this.parentField]) {
11214
+ const index = this.treeDataStructure.findDataIndex(this.selectedRows, row[this.parentField]);
11215
+ if (index > -1)
11216
+ this.selectedRows.splice(index, 1);
11217
+ const parentRow = this.treeDataStructure.getRowData(row).tree__parent;
11218
+ this.unselectParents(parentRow);
11079
11219
  }
11080
11220
  }
11081
11221
  }
@@ -11110,6 +11250,7 @@
11110
11250
  },
11111
11251
  };
11112
11252
  this.doubleClickEdit = this.getInitValue('doubleClickEdit', props.doubleClickEdit, this.doubleClickEdit);
11253
+ this.canEditRow = this.getInitValue('canEditRow', props.canEditRow, this.canEditRow);
11113
11254
  this.noDataSlot = this.changeDefaultSlotNames(this.noDataSlot);
11114
11255
  this.createAccessors();
11115
11256
  }
@@ -11163,10 +11304,10 @@
11163
11304
  * @param event DOM event
11164
11305
  * @param element DOM Element
11165
11306
  */
11166
- cellClick(row, column, event, element) {
11307
+ cellClick(row, column, event, element, canEdit = true) {
11167
11308
  if (this.editing)
11168
11309
  return;
11169
- if (column.editable) {
11310
+ if (column.editable && canEdit) {
11170
11311
  this.editing = true;
11171
11312
  this.preventRowClick = true;
11172
11313
  this.datasource.currentRow = row;
@@ -11483,6 +11624,9 @@
11483
11624
  throw e;
11484
11625
  }
11485
11626
  }
11627
+ callCanEditRow(row) {
11628
+ return !this.canEditRow || typeof this.canEditRow !== 'function' || this.canEditRow({ row, component: this });
11629
+ }
11486
11630
  }
11487
11631
 
11488
11632
  class Icons {
@@ -11926,9 +12070,9 @@
11926
12070
  };
11927
12071
  this.colunmXLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
11928
12072
  }
11929
- buildColumns(columns) {
12073
+ getColumnsWidth(columns) {
11930
12074
  const widths = {};
11931
- let totalWidth;
12075
+ let totalWidth = 0;
11932
12076
  try {
11933
12077
  totalWidth = columns.reduce((sum, col) => {
11934
12078
  widths[col.name] = col.getWidth();
@@ -11940,6 +12084,10 @@
11940
12084
  throw e;
11941
12085
  }
11942
12086
  }
12087
+ return { widths, totalWidth };
12088
+ }
12089
+ buildColumns(columns) {
12090
+ const { widths, totalWidth } = this.getColumnsWidth(columns);
11943
12091
  return columns.reduce((result, col, index) => {
11944
12092
  let size;
11945
12093
  if (!totalWidth) {
@@ -11952,58 +12100,12 @@
11952
12100
  align: col.align || 'left',
11953
12101
  description: col.label,
11954
12102
  sequence: index,
11955
- format: this.getFormatOfColumn(col),
11956
12103
  size: `${size}%`,
11957
12104
  xlsType: col.xlsType,
11958
12105
  };
11959
12106
  return Object.assign(Object.assign({}, result), { [col.name]: row });
11960
12107
  }, {});
11961
12108
  }
11962
- isNumberComponent(component) {
11963
- return ['ZdNumber', 'ZdCurrency', 'ZdIncrement'].indexOf(component) !== -1;
11964
- }
11965
- checkAccessor(value) {
11966
- if (core.Accessor.isAccessorDefinition(value)) {
11967
- const [controller, accessor] = core.Accessor.getAccessor(value);
11968
- return core.Loader.getInstance(controller)[accessor];
11969
- }
11970
- return value;
11971
- }
11972
- getFormatOfColumn(column) {
11973
- let format;
11974
- let { mask } = column;
11975
- if (mask) {
11976
- format = {
11977
- type: 'fix',
11978
- params: {
11979
- mask,
11980
- },
11981
- };
11982
- }
11983
- else if (column.componentProps && Object.keys(column.componentProps).length) {
11984
- const { component } = column.componentProps;
11985
- if (this.isNumberComponent(component)) {
11986
- format = { type: 'float' };
11987
- mask = this.checkAccessor(column.componentProps.mask);
11988
- if (mask) {
11989
- format.params = {};
11990
- if (mask.currencySymbol) {
11991
- format.type = 'currency';
11992
- format.symbol = mask.currencySymbol;
11993
- format.decimal = mask.decimalCharacter;
11994
- format.thousands = mask.digitGroupSeparator;
11995
- format.precision = mask.decimalPlaces;
11996
- }
11997
- else {
11998
- format.params.decimal = mask.decimalCharacter;
11999
- format.params.thousands = mask.digitGroupSeparator;
12000
- format.params.precision = mask.decimalPlaces;
12001
- }
12002
- }
12003
- }
12004
- }
12005
- return format;
12006
- }
12007
12109
  buildFilter(filter) {
12008
12110
  return Object.keys(filter).map((key) => ({
12009
12111
  label: key,
@@ -12071,6 +12173,72 @@
12071
12173
  buildDataset(data) {
12072
12174
  return JSON.stringify(data);
12073
12175
  }
12176
+ buildColumns(columns) {
12177
+ const { widths, totalWidth } = this.getColumnsWidth(columns);
12178
+ return columns.reduce((result, col, index) => {
12179
+ let size;
12180
+ if (!totalWidth) {
12181
+ size = Math.floor(100 / columns.length);
12182
+ }
12183
+ else {
12184
+ size = Math.floor((widths[col.name] * 100) / totalWidth);
12185
+ }
12186
+ const row = {
12187
+ align: col.align || 'left',
12188
+ description: col.label,
12189
+ sequence: index,
12190
+ format: this.getFormatOfColumn(col),
12191
+ size: `${size}%`,
12192
+ xlsType: col.xlsType,
12193
+ };
12194
+ return Object.assign(Object.assign({}, result), { [col.name]: row });
12195
+ }, {});
12196
+ }
12197
+ getFormatOfColumn(column) {
12198
+ let format;
12199
+ let { mask } = column;
12200
+ if (mask) {
12201
+ format = {
12202
+ type: 'fix',
12203
+ params: {
12204
+ mask,
12205
+ },
12206
+ };
12207
+ }
12208
+ else if (column.componentProps && Object.keys(column.componentProps).length) {
12209
+ const { component } = column.componentProps;
12210
+ if (this.isNumberComponent(component)) {
12211
+ format = { type: 'float' };
12212
+ mask = this.checkAccessor(column.componentProps.mask);
12213
+ if (mask) {
12214
+ format.params = {};
12215
+ if (mask.currencySymbol) {
12216
+ format.type = 'currency';
12217
+ format.symbol = mask.currencySymbol;
12218
+ format.decimal = mask.decimalCharacter;
12219
+ format.thousands = mask.digitGroupSeparator;
12220
+ format.precision = mask.decimalPlaces;
12221
+ }
12222
+ else {
12223
+ format.params.decimal = mask.decimalCharacter;
12224
+ format.params.thousands = mask.digitGroupSeparator;
12225
+ format.params.precision = mask.decimalPlaces;
12226
+ }
12227
+ }
12228
+ }
12229
+ }
12230
+ return format;
12231
+ }
12232
+ isNumberComponent(component) {
12233
+ return ['ZdNumber', 'ZdCurrency', 'ZdIncrement'].indexOf(component) !== -1;
12234
+ }
12235
+ checkAccessor(value) {
12236
+ if (core.Accessor.isAccessorDefinition(value)) {
12237
+ const [controller, accessor] = core.Accessor.getAccessor(value);
12238
+ return core.Loader.getInstance(controller)[accessor];
12239
+ }
12240
+ return value;
12241
+ }
12074
12242
  buildMetadata(name, title, columns, filter, portrait = true) {
12075
12243
  return __awaiter(this, void 0, void 0, function* () {
12076
12244
  const builtCols = this.buildColumns(columns);
@@ -12152,6 +12320,7 @@
12152
12320
  }
12153
12321
  }
12154
12322
 
12323
+ // XLS without groups (formatXLS = 'F3')
12155
12324
  class XLSReport extends BaseReport {
12156
12325
  constructor() {
12157
12326
  super(...arguments);
@@ -12198,13 +12367,14 @@
12198
12367
  columns: builtCols,
12199
12368
  filter: builtFilters,
12200
12369
  reportXLS: true,
12370
+ formatXLS: 'F3',
12201
12371
  xlsMergedCell: [],
12202
12372
  };
12203
12373
  return Promise.resolve(JSON.stringify(metadataObj));
12204
12374
  }
12205
12375
  }
12206
12376
 
12207
- // XLS with groups
12377
+ // XLS with groups (formatXLS = 'F1')
12208
12378
  class XLS2Report extends BaseReport {
12209
12379
  constructor() {
12210
12380
  super(...arguments);
@@ -12242,6 +12412,7 @@
12242
12412
  columns: builtCols,
12243
12413
  filter: builtFilters,
12244
12414
  reportXLS: true,
12415
+ formatXLS: 'F1',
12245
12416
  xlsMergedCell: [],
12246
12417
  };
12247
12418
  return Promise.resolve(JSON.stringify(metadataObj));
@@ -12400,7 +12571,7 @@
12400
12571
  }
12401
12572
  }
12402
12573
 
12403
- // Grid mirror (with groups)
12574
+ // Grid mirror (with groups) (formatXLS = 'F2')
12404
12575
  class XLS3Report extends BaseReport {
12405
12576
  constructor() {
12406
12577
  super(...arguments);
@@ -12438,6 +12609,7 @@
12438
12609
  columns: builtCols,
12439
12610
  filter: builtFilters,
12440
12611
  reportXLS: true,
12612
+ formatXLS: 'F2',
12441
12613
  xlsMergedCell: [],
12442
12614
  };
12443
12615
  return Promise.resolve(JSON.stringify(metadataObj));