@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.
@@ -5518,6 +5518,7 @@ class GridEditable extends Grid {
5518
5518
  };
5519
5519
  this.newRowIdentifier = '__added_row';
5520
5520
  this.doubleClickEdit = this.getInitValue('doubleClickEdit', props.doubleClickEdit, this.doubleClickEdit);
5521
+ this.canEditRow = this.getInitValue('canEditRow', props.canEditRow, this.canEditRow);
5521
5522
  this.createAccessors();
5522
5523
  }
5523
5524
  onMounted(element) {
@@ -5570,10 +5571,10 @@ class GridEditable extends Grid {
5570
5571
  * @param event DOM event
5571
5572
  * @param element DOM Element
5572
5573
  */
5573
- cellClick(row, column, event, element) {
5574
+ cellClick(row, column, event, element, canEdit = true) {
5574
5575
  if (this.editing)
5575
5576
  return;
5576
- if (column.editable) {
5577
+ if (column.editable && canEdit) {
5577
5578
  this.editing = true;
5578
5579
  this.preventRowClick = true;
5579
5580
  this.datasource.currentRow = row;
@@ -5922,6 +5923,9 @@ class GridEditable extends Grid {
5922
5923
  throw e;
5923
5924
  }
5924
5925
  }
5926
+ callCanEditRow(row) {
5927
+ return !this.canEditRow || typeof this.canEditRow !== 'function' || this.canEditRow({ row, component: this });
5928
+ }
5925
5929
  }
5926
5930
 
5927
5931
  /**
@@ -10229,7 +10233,7 @@ class Time extends TextInput {
10229
10233
  /**
10230
10234
  * Defines the format of a time displayed in picker. Available options are ampm and 24hr.
10231
10235
  */
10232
- this.timeFormat = Config.timeFormat || 'ampm';
10236
+ this.timeFormat = Config.timeFormat || 'ampm'; // change props to pickerFormat
10233
10237
  /**
10234
10238
  * Forces 100% width.
10235
10239
  */
@@ -10260,29 +10264,18 @@ class Time extends TextInput {
10260
10264
  this.width = 290;
10261
10265
  this.formatterFn = FormatterParserProvider.getFormatter('ZdTime');
10262
10266
  this.parserFn = FormatterParserProvider.getParser('ZdTime');
10267
+ this.isoFormatValue = 'HH:mm';
10268
+ this.valueFormatInternal = Config.valueTimeFormat;
10269
+ this.displayFormatInternal = Config.displayTimeFormat;
10263
10270
  /**
10264
- * Map of the mask functions
10265
- */
10266
- this.maskFunctions = {
10267
- ampm: () => this.ampmMask(),
10268
- '24hr': (value) => this.fullTimeMask(value),
10269
- };
10270
- /**
10271
- * Format used in time value
10271
+ * Defines the time input format.
10272
10272
  */
10273
- this.valueFormat = Config.valueTimeFormat;
10274
- /**
10275
- * Format used to display the value
10276
- */
10277
- this.displayFormat = Config.displayTimeFormat;
10273
+ this.inputFormat = Config.timeInputFormat;
10278
10274
  /**
10279
10275
  * True when displayValue is valid
10280
10276
  */
10281
10277
  this.isDisplayValid = true;
10282
- /**
10283
- * Last invalid value passed to formatter
10284
- */
10285
- this.lastInvalid = '';
10278
+ this.timeError = false;
10286
10279
  this.allowedHours = this.getInitValue('allowedHours', props.allowedHours, this.allowedHours);
10287
10280
  this.allowedMinutes = this.getInitValue('allowedMinutes', props.allowedMinutes, this.allowedMinutes);
10288
10281
  this.allowedSeconds = this.getInitValue('allowedSeconds', props.allowedSeconds, this.allowedSeconds);
@@ -10296,40 +10289,40 @@ class Time extends TextInput {
10296
10289
  this.useSeconds = this.getInitValue('useSeconds', props.useSeconds, this.useSeconds);
10297
10290
  this.width = this.getInitValue('width', props.width, this.width);
10298
10291
  this.autofill = this.getInitValue('autofill', props.autofill, this.autofill);
10299
- this.mask = this.getInitValue('mask', props.mask, this.getMask);
10300
10292
  this.timeValidation = this.timeValidation.bind(this);
10293
+ this.valueFormat = this.getInitValue('valueFormat', props.valueFormat, this.valueFormatInternal);
10294
+ this.displayFormat = this.getInitValue('displayFormat', props.displayFormat, this.displayFormatInternal);
10295
+ this.inputFormat = this.getInitValue('inputFormat', props.inputFormat, this.inputFormat);
10301
10296
  this.timeAllowedValidation = this.timeAllowedValidation.bind(this);
10302
10297
  this.rules.push(this.timeValidation, this.timeAllowedValidation);
10303
- this.valueFormat = this.getInitValue('valueFormat', props.valueFormat, this.valueFormat);
10304
- this.displayFormat = this.getInitValue('displayFormat', props.displayFormat, this.displayFormat);
10298
+ this.mask = this.getInitValue('mask', props.mask, undefined);
10305
10299
  this.createAccessors();
10306
- this.createFormatAccessors();
10307
- }
10308
- createFormatAccessors() {
10309
- if (!this.valueFormat) {
10310
- Object.defineProperty(this, 'valueFormat', {
10311
- get: () => this.defaultValueFmt,
10312
- set: (valueFormat) => {
10313
- delete this.valueFormat;
10314
- this.valueFormat = valueFormat;
10315
- },
10316
- });
10300
+ this.initialMask = this.getInitialMask();
10301
+ this.isSimpleDisplay = this.isSimpleFormat(this.displayFormat);
10302
+ }
10303
+ get displayFormat() {
10304
+ const commonsDisplay = ['hh:mm A', 'hh:mm:ss A', 'HH:mm:ss', 'HH:mm'];
10305
+ if (commonsDisplay.includes(this.displayFormatInternal)) {
10306
+ this.displayFormatInternal = this.defaultFormats[this.timeFormat];
10317
10307
  }
10318
- if (!this.displayFormat) {
10319
- Object.defineProperty(this, 'displayFormat', {
10320
- get: () => this.defaultDisplayFmt,
10321
- set: (displayFormat) => {
10322
- delete this.displayFormat;
10323
- this.displayFormat = displayFormat;
10324
- },
10325
- });
10308
+ return this.displayFormatInternal;
10309
+ }
10310
+ set displayFormat(value) {
10311
+ this.displayFormatInternal = value;
10312
+ }
10313
+ get valueFormat() {
10314
+ const commonsDisplay = ['hh:mm A', 'hh:mm:ss A', 'HH:mm:ss', 'HH:mm'];
10315
+ if (commonsDisplay.includes(this.valueFormatInternal)) {
10316
+ this.valueFormatInternal = this.defaultFormats['24hr'];
10326
10317
  }
10318
+ return this.valueFormatInternal;
10327
10319
  }
10328
- get defaultValueFmt() {
10329
- return this.defaultFormats['24hr'];
10320
+ set valueFormat(value) {
10321
+ this.valueFormatInternal = value;
10330
10322
  }
10331
- get defaultDisplayFmt() {
10332
- return this.defaultFormats[this.timeFormat];
10323
+ get isoFormat() {
10324
+ this.isoFormatValue = this.useSeconds ? 'HH:mm:ss' : 'HH:mm';
10325
+ return this.isoFormatValue;
10333
10326
  }
10334
10327
  get defaultFormats() {
10335
10328
  const seconds = this.useSeconds ? ':ss' : '';
@@ -10338,59 +10331,172 @@ class Time extends TextInput {
10338
10331
  '24hr': `HH:mm${seconds}`,
10339
10332
  };
10340
10333
  }
10341
- ampmMask() {
10342
- const ampmValue = this.displayValue || '';
10343
- const hours = [/[0-1]/];
10344
- if (ampmValue[0] === '1') {
10345
- hours.push(/[0-2]/);
10334
+ getInitialMask() {
10335
+ if (isUndefined(this.mask)) {
10336
+ this.mask = this.inputFormat && this.maskFormat(this.inputFormat);
10337
+ }
10338
+ return this.mask;
10339
+ }
10340
+ formatter(value) { return this.formatterFn(value, this); }
10341
+ parser(value) { return this.parserFn(value, this); }
10342
+ /**
10343
+ * Triggered when date is clicked.
10344
+ * @param event
10345
+ * @param element
10346
+ */
10347
+ selectTime(time, event, element) {
10348
+ if (this.events.onSelectTime && typeof this.events.onSelectTime === 'function') {
10349
+ this.events.onSelectTime({
10350
+ time, event, element, component: this,
10351
+ });
10352
+ }
10353
+ }
10354
+ get displayValue() {
10355
+ return this.internalDisplayValue;
10356
+ }
10357
+ set displayValue(newValue) {
10358
+ this.timeError = false;
10359
+ this.internalDisplayValue = newValue;
10360
+ this.internalValue = this.parser(newValue);
10361
+ this.value = this.internalValue; // forces value accessor to be called if necessary
10362
+ }
10363
+ /**
10364
+ * Assign the updated mask to mask property
10365
+ */
10366
+ updateMask() {
10367
+ this.isSimpleDisplay = this.isSimpleFormat(this.displayFormat);
10368
+ this.mask = this.getUpdatedMask();
10369
+ return this.mask;
10370
+ }
10371
+ /**
10372
+ * Gets the updated masked, based on displayFormat if the initial mask is undefined
10373
+ */
10374
+ getUpdatedMask() {
10375
+ if (isUndefined(this.initialMask)) {
10376
+ return this.maskFormat(this.displayFormat);
10346
10377
  }
10347
- else if (ampmValue[0] === '0') {
10348
- hours.push(/[1-9]/);
10378
+ return this.mask;
10379
+ }
10380
+ maskFormat(format) {
10381
+ return format.replace(/[A-Za-z]/gi, '#');
10382
+ }
10383
+ setTimeValue(displayValue) {
10384
+ const lastValue = this.displayValue;
10385
+ if (this.isValidTime(displayValue, this.displayFormat)) {
10386
+ this.internalDisplayValue = displayValue;
10387
+ this.internalValue = this.parser(displayValue);
10388
+ this.timeError = false;
10389
+ if (lastValue !== this.displayValue)
10390
+ this.change(this.value);
10349
10391
  }
10350
10392
  else {
10351
- hours.push(/[0-9]/);
10393
+ if (!displayValue) {
10394
+ this.internalDisplayValue = displayValue;
10395
+ this.internalValue = null;
10396
+ if (lastValue !== this.displayValue)
10397
+ this.change(this.value);
10398
+ }
10399
+ this.timeError = !!displayValue;
10352
10400
  }
10353
- const minutes = [/[0-5]/, /[0-9]/];
10354
- const seconds = this.useSeconds ? [':', ...minutes] : [];
10355
- const ampm = /(A|P)/;
10356
- return [...hours, ':', ...minutes, ...seconds, ' ', ampm, 'M'];
10401
+ this.value = this.internalValue; // forces value accessor to be called if necessary
10357
10402
  }
10358
- fullTimeMask(value) {
10359
- const hours = [
10360
- /[0-2]/,
10361
- value[0] === '2' ? /[0-3]/ : /[0-9]/,
10362
- ];
10363
- const minutes = [/[0-5]/, /[0-9]/];
10364
- const seconds = this.useSeconds ? [':', ...minutes] : [];
10365
- return [...hours, ':', ...minutes, ...seconds];
10403
+ isValidTime(value, format, strict = true) {
10404
+ return dayjs(value, format, strict).isValid();
10366
10405
  }
10367
- getMask(value) {
10368
- return this.maskFunctions[this.timeFormat](value);
10406
+ get isoValue() {
10407
+ return this.formatISOTimeValue(this.value);
10408
+ }
10409
+ set isoValue(newValue) {
10410
+ const lastValue = this.value;
10411
+ this.timeError = false;
10412
+ this.value = this.parseISOTimeValue(newValue);
10413
+ if (lastValue !== this.value)
10414
+ this.change(this.value);
10415
+ }
10416
+ formatISOTimeValue(value) {
10417
+ if (value && this.isValidTime(value, this.valueFormat)) {
10418
+ return dayjs(value, this.valueFormat).format(this.isoFormat);
10419
+ }
10420
+ return '';
10421
+ }
10422
+ parseISOTimeValue(value) {
10423
+ if (value && this.isValidTime(value, this.valueFormat)) {
10424
+ return dayjs(value, this.isoFormat).format(this.valueFormat);
10425
+ }
10426
+ return null;
10369
10427
  }
10370
10428
  /**
10371
- * Checks if value is valid according to valueFormat and if displayValue
10372
- * is true
10373
- */
10374
- isFullyValid(value = this.value) {
10375
- return this.isValidTime(value) && this.isDisplayValid;
10429
+ * Checks if a time format is simple.
10430
+ * Simple time formats are the ones that consists only of 'HH', 'mm', 'mm' or 'YYYY', and mask delimiters
10431
+ * @param format The format to be checked
10432
+ * @returns true if it is simple, false otherwise
10433
+ */
10434
+ isSimpleFormat(format) {
10435
+ const simpleTokens = ['HH', 'mm', 'ss', 'hh', 'A', 'a', 'p', 'P'];
10436
+ // remove the simple tokens from the string
10437
+ const replaced = simpleTokens.reduce((result, token) => result.replace(token, ''), format);
10438
+ const chars = replaced.split('');
10439
+ return chars.length ? chars.every((char) => Mask.isMaskDelimiter(char)) : true;
10376
10440
  }
10377
- formatter(value) {
10378
- const eq = this.lastInvalid === value;
10379
- if (eq || !this.isFullyValid(value)) {
10380
- this.isDisplayValid = true;
10381
- this.lastInvalid = value;
10382
- return value;
10441
+ timeValidation() {
10442
+ if (this.isValidTime(this.displayValue, this.displayFormat) || !this.displayValue) {
10443
+ return true;
10383
10444
  }
10384
- return this.formatterFn(value, this);
10445
+ return I18n.translate('VALIDATION_INVALID_TIME');
10446
+ }
10447
+ timeAllowedValidation() {
10448
+ return !this.displayValue
10449
+ || (this.isValidTime(this.displayValue, this.displayFormat)
10450
+ && this.isTimeAllowed())
10451
+ || I18n.translate('VALIDATION_TIME_NOT_ALLOWED');
10452
+ }
10453
+ click(event, element) {
10454
+ const clickEvent = event || new MouseEvent('click');
10455
+ super.click(clickEvent, element);
10456
+ if (!clickEvent.defaultPrevented) {
10457
+ this.showTimePicker = !this.showTimePicker;
10458
+ }
10459
+ }
10460
+ blur(event, element) {
10461
+ this.removeTimeMask();
10462
+ this.setTimeValue(this.formatter(this.value));
10463
+ super.blur(event, element);
10464
+ this.showTimePicker = false;
10465
+ }
10466
+ focus(event, element) {
10467
+ this.addTimeMask();
10468
+ super.focus(event, element);
10385
10469
  }
10386
- parser(value) {
10387
- const parsed = this.parserFn(value, this);
10388
- this.isDisplayValid = value === null || value === '' || this.isValidTime(value, this.displayFormat);
10389
- return parsed;
10470
+ /**
10471
+ * Add date mask
10472
+ */
10473
+ addTimeMask() {
10474
+ if (!this.value)
10475
+ return;
10476
+ this.mask = this.initialMask;
10477
+ this.internalDisplayValue = dayjs(this.value, this.valueFormat).format(this.inputFormat || this.displayFormat);
10390
10478
  }
10391
- isValidTime(value, format = this.valueFormat) {
10392
- return dayjs(value, format, true).isValid();
10479
+ /**
10480
+ * Removes the component mask if value is valid
10481
+ */
10482
+ removeTimeMask() {
10483
+ if (isUndefined(this.initialMask) || !this.value || this.timeError
10484
+ || !this.isValidTime(this.value, this.valueFormat)) {
10485
+ return;
10486
+ }
10487
+ this.mask = '';
10393
10488
  }
10489
+ /**
10490
+ * Checks if value is valid according to valueFormat and if displayValue
10491
+ * is true
10492
+ */
10493
+ isFullyValid(value = this.value) {
10494
+ return this.isValidTime(value, this.valueFormat, true) && this.isDisplayValid;
10495
+ }
10496
+ /**
10497
+ * Last invalid value passed to formatter
10498
+ */
10499
+ // private lastInvalid: string = '';
10394
10500
  isTimeAllowed(value = this.value) {
10395
10501
  return this.isSameOrAfterMin(value) && this.isSameOrBeforeMax(value)
10396
10502
  && this.isHourAllowed(value) && this.isMinuteAllowed(value)
@@ -10426,49 +10532,54 @@ class Time extends TextInput {
10426
10532
  const second = dayjs(value, this.valueFormat).second();
10427
10533
  return this.allowedSeconds.includes(second);
10428
10534
  }
10429
- timeValidation() {
10430
- return !this.displayValue
10431
- || this.isValidTime(this.displayValue, this.displayFormat)
10432
- || I18n.translate('VALIDATION_INVALID_TIME');
10433
- }
10434
- timeAllowedValidation() {
10435
- return !this.displayValue
10436
- || (this.isValidTime(this.displayValue, this.displayFormat)
10437
- && this.isTimeAllowed())
10438
- || I18n.translate('VALIDATION_TIME_NOT_ALLOWED');
10439
- }
10440
- click(event) {
10441
- this.callEvent('click', {
10442
- event: (event || new MouseEvent('click')),
10443
- component: this,
10444
- });
10445
- if (!(event === null || event === void 0 ? void 0 : event.defaultPrevented)) {
10446
- this.showTimePicker = !this.showTimePicker;
10447
- }
10448
- }
10449
10535
  clear() {
10450
10536
  this.value = null;
10451
10537
  this.change(this.value);
10452
10538
  }
10453
10539
  }
10454
- FormatterParserProvider.registerFormatter('ZdTime', (value, { displayFormat = Config.displayFormat, valueFormat = Config.valueTimeFormat, } = {}) => {
10540
+ FormatterParserProvider.registerFormatter('ZdTime', (value, { valueFormat = Config.valueTimeFormat, displayFormat = Config.displayTimeFormat, inputFormat = Config.timeInputFormat, mask = '', initialMask, isSimpleDisplay = false, } = {}) => {
10455
10541
  if (!value) {
10456
10542
  return '';
10457
10543
  }
10458
- if (dayjs(value, valueFormat, true).isValid()) {
10459
- return dayjs(value, valueFormat).format(displayFormat);
10544
+ const isTimeValid = dayjs(value, valueFormat, true).isValid();
10545
+ if (!isTimeValid) {
10546
+ return value;
10460
10547
  }
10461
- return value;
10548
+ if (mask && initialMask) {
10549
+ if (inputFormat) {
10550
+ return dayjs(value, valueFormat).format(inputFormat);
10551
+ }
10552
+ let valueToUnmask = value;
10553
+ if (isSimpleDisplay) {
10554
+ valueToUnmask = dayjs(value, valueFormat).format(displayFormat);
10555
+ }
10556
+ const unmasked = Mask.getValueWithoutMask(valueToUnmask);
10557
+ const masked = Mask.getValueWithMask(unmasked, mask);
10558
+ return masked;
10559
+ }
10560
+ return dayjs(value, valueFormat).format(displayFormat);
10462
10561
  });
10463
- FormatterParserProvider.registerParser('ZdTime', (value, { displayFormat = Config.displayFormat, valueFormat = Config.valueTimeFormat, } = {}) => {
10562
+ FormatterParserProvider.registerParser('ZdTime', (value, { displayFormat = Config.displayTimeFormat, valueFormat = Config.valueTimeFormat, mask = '', initialMask, } = {}) => {
10464
10563
  if (!value) {
10465
10564
  return null;
10466
10565
  }
10467
- const uppecaseValue = value.toUpperCase();
10468
- if (dayjs(uppecaseValue, displayFormat, true).isValid()) {
10469
- return dayjs(uppecaseValue, displayFormat).format(valueFormat);
10566
+ if (dayjs(value, displayFormat, true).isValid()) {
10567
+ return dayjs(value, displayFormat).format(valueFormat);
10470
10568
  }
10471
- return uppecaseValue;
10569
+ if (mask && Mask.checkMask(value, mask)) {
10570
+ const unmasked = Mask.getValueWithoutMask(value);
10571
+ let masked;
10572
+ if (!initialMask) {
10573
+ const displayFmtMask = displayFormat.replace(/[A-Za-z]/gi, '#');
10574
+ masked = Mask.getValueWithMask(unmasked, displayFmtMask);
10575
+ }
10576
+ const timeFmtMask = valueFormat.replace(/[A-Za-z]/gi, '#');
10577
+ masked = Mask.getValueWithMask(unmasked, timeFmtMask);
10578
+ if (dayjs(masked, valueFormat, true).format(valueFormat) === masked) {
10579
+ return masked;
10580
+ }
10581
+ }
10582
+ return value;
10472
10583
  });
10473
10584
 
10474
10585
  /**
@@ -10610,6 +10721,7 @@ class Tree extends ComponentRender {
10610
10721
  this.checkedField = this.getInitValue('checkedField', props.checkedField, this.checkedField);
10611
10722
  this.openLevelOnLoad = this.getInitValue('openLevelOnLoad', props.openLevelOnLoad, this.openLevelOnLoad);
10612
10723
  this.checkbox = this.getInitValue('checkbox', props.checkbox, this.checkbox);
10724
+ this.disableCheckbox = this.getInitValue('disableCheckbox', props.disableCheckbox, this.disableCheckbox);
10613
10725
  this.afterTitleSlot = props.afterTitleSlot || this.afterTitleSlot;
10614
10726
  this.toolbarSlot = props.toolbarSlot || this.toolbarSlot;
10615
10727
  this.titleSlot = props.titleSlot || this.titleSlot;
@@ -10845,16 +10957,13 @@ class Tree extends ComponentRender {
10845
10957
  const compName = component.name;
10846
10958
  const instanceName = `${compName}_${nodePath}`;
10847
10959
  const path = parentPath ? `${parentPath}.${compName}` : compName;
10848
- const newComponent = merge({}, component, (_a = this.appliedConditions[nodePath]) === null || _a === void 0 ? void 0 : _a[path]);
10960
+ const newInstances = Metadata.getInstances(instanceName);
10961
+ const newInstance = newInstances[0];
10962
+ const appliedConditions = (_a = this.appliedConditions[nodePath]) === null || _a === void 0 ? void 0 : _a[path];
10963
+ const newComponent = merge({}, component, newInstance, appliedConditions);
10849
10964
  const newChildren = this.getSlotComponent(newComponent.children || [], node, path);
10850
10965
  newComponent.name = instanceName;
10851
10966
  newComponent.children = newChildren;
10852
- try {
10853
- Metadata.updateInstance(instanceName, newComponent);
10854
- }
10855
- catch (e) {
10856
- // do nothing
10857
- }
10858
10967
  newComponents.push(newComponent);
10859
10968
  });
10860
10969
  return newComponents;
@@ -10916,6 +11025,10 @@ class Tree extends ComponentRender {
10916
11025
  return this.searchPath(currentNode.children || [], path.slice(1));
10917
11026
  return currentNode;
10918
11027
  }
11028
+ callDisableCheckbox(node) {
11029
+ return !!this.disableCheckbox && typeof this.disableCheckbox === 'function'
11030
+ && this.disableCheckbox({ node, component: this });
11031
+ }
10919
11032
  }
10920
11033
 
10921
11034
  /**
@@ -11062,6 +11175,8 @@ class TreeGrid extends Grid {
11062
11175
  const rows = [row, ...this.treeDataStructure.getChildren(row)];
11063
11176
  if (isSelected) {
11064
11177
  this.selectedRows = Array.from(new Set(this.selectedRows.concat(rows))); // remove duplicates
11178
+ // check if all the children of the parent are selected.
11179
+ this.selectParents(rows, row);
11065
11180
  }
11066
11181
  else {
11067
11182
  rows.forEach((item) => {
@@ -11069,6 +11184,31 @@ class TreeGrid extends Grid {
11069
11184
  if (index > -1)
11070
11185
  this.selectedRows.splice(index, 1);
11071
11186
  });
11187
+ this.unselectParents(row);
11188
+ }
11189
+ }
11190
+ selectParents(rows, row) {
11191
+ if (row[this.parentField]) {
11192
+ const parentRow = this.treeDataStructure.getRowData(row).tree__parent;
11193
+ const every = this.treeDataStructure.getChildren(parentRow).every((item) => {
11194
+ const index = this.treeDataStructure.findDataIndex(this.selectedRows, item[this.datasource.uniqueKey]);
11195
+ if (index > -1)
11196
+ return true;
11197
+ return false;
11198
+ });
11199
+ if (every)
11200
+ rows.push(parentRow);
11201
+ this.selectedRows = Array.from(new Set(this.selectedRows.concat(rows))); // remove duplicates
11202
+ this.selectParents(rows, parentRow);
11203
+ }
11204
+ }
11205
+ unselectParents(row) {
11206
+ if (row[this.parentField]) {
11207
+ const index = this.treeDataStructure.findDataIndex(this.selectedRows, row[this.parentField]);
11208
+ if (index > -1)
11209
+ this.selectedRows.splice(index, 1);
11210
+ const parentRow = this.treeDataStructure.getRowData(row).tree__parent;
11211
+ this.unselectParents(parentRow);
11072
11212
  }
11073
11213
  }
11074
11214
  }
@@ -11103,6 +11243,7 @@ class TreeGridEditable extends TreeGrid {
11103
11243
  },
11104
11244
  };
11105
11245
  this.doubleClickEdit = this.getInitValue('doubleClickEdit', props.doubleClickEdit, this.doubleClickEdit);
11246
+ this.canEditRow = this.getInitValue('canEditRow', props.canEditRow, this.canEditRow);
11106
11247
  this.noDataSlot = this.changeDefaultSlotNames(this.noDataSlot);
11107
11248
  this.createAccessors();
11108
11249
  }
@@ -11156,10 +11297,10 @@ class TreeGridEditable extends TreeGrid {
11156
11297
  * @param event DOM event
11157
11298
  * @param element DOM Element
11158
11299
  */
11159
- cellClick(row, column, event, element) {
11300
+ cellClick(row, column, event, element, canEdit = true) {
11160
11301
  if (this.editing)
11161
11302
  return;
11162
- if (column.editable) {
11303
+ if (column.editable && canEdit) {
11163
11304
  this.editing = true;
11164
11305
  this.preventRowClick = true;
11165
11306
  this.datasource.currentRow = row;
@@ -11476,6 +11617,9 @@ class TreeGridEditable extends TreeGrid {
11476
11617
  throw e;
11477
11618
  }
11478
11619
  }
11620
+ callCanEditRow(row) {
11621
+ return !this.canEditRow || typeof this.canEditRow !== 'function' || this.canEditRow({ row, component: this });
11622
+ }
11479
11623
  }
11480
11624
 
11481
11625
  class Icons {
@@ -11919,9 +12063,9 @@ class BaseReport {
11919
12063
  };
11920
12064
  this.colunmXLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
11921
12065
  }
11922
- buildColumns(columns) {
12066
+ getColumnsWidth(columns) {
11923
12067
  const widths = {};
11924
- let totalWidth;
12068
+ let totalWidth = 0;
11925
12069
  try {
11926
12070
  totalWidth = columns.reduce((sum, col) => {
11927
12071
  widths[col.name] = col.getWidth();
@@ -11933,6 +12077,10 @@ class BaseReport {
11933
12077
  throw e;
11934
12078
  }
11935
12079
  }
12080
+ return { widths, totalWidth };
12081
+ }
12082
+ buildColumns(columns) {
12083
+ const { widths, totalWidth } = this.getColumnsWidth(columns);
11936
12084
  return columns.reduce((result, col, index) => {
11937
12085
  let size;
11938
12086
  if (!totalWidth) {
@@ -11945,58 +12093,12 @@ class BaseReport {
11945
12093
  align: col.align || 'left',
11946
12094
  description: col.label,
11947
12095
  sequence: index,
11948
- format: this.getFormatOfColumn(col),
11949
12096
  size: `${size}%`,
11950
12097
  xlsType: col.xlsType,
11951
12098
  };
11952
12099
  return Object.assign(Object.assign({}, result), { [col.name]: row });
11953
12100
  }, {});
11954
12101
  }
11955
- isNumberComponent(component) {
11956
- return ['ZdNumber', 'ZdCurrency', 'ZdIncrement'].indexOf(component) !== -1;
11957
- }
11958
- checkAccessor(value) {
11959
- if (Accessor.isAccessorDefinition(value)) {
11960
- const [controller, accessor] = Accessor.getAccessor(value);
11961
- return Loader.getInstance(controller)[accessor];
11962
- }
11963
- return value;
11964
- }
11965
- getFormatOfColumn(column) {
11966
- let format;
11967
- let { mask } = column;
11968
- if (mask) {
11969
- format = {
11970
- type: 'fix',
11971
- params: {
11972
- mask,
11973
- },
11974
- };
11975
- }
11976
- else if (column.componentProps && Object.keys(column.componentProps).length) {
11977
- const { component } = column.componentProps;
11978
- if (this.isNumberComponent(component)) {
11979
- format = { type: 'float' };
11980
- mask = this.checkAccessor(column.componentProps.mask);
11981
- if (mask) {
11982
- format.params = {};
11983
- if (mask.currencySymbol) {
11984
- format.type = 'currency';
11985
- format.symbol = mask.currencySymbol;
11986
- format.decimal = mask.decimalCharacter;
11987
- format.thousands = mask.digitGroupSeparator;
11988
- format.precision = mask.decimalPlaces;
11989
- }
11990
- else {
11991
- format.params.decimal = mask.decimalCharacter;
11992
- format.params.thousands = mask.digitGroupSeparator;
11993
- format.params.precision = mask.decimalPlaces;
11994
- }
11995
- }
11996
- }
11997
- }
11998
- return format;
11999
- }
12000
12102
  buildFilter(filter) {
12001
12103
  return Object.keys(filter).map((key) => ({
12002
12104
  label: key,
@@ -12064,6 +12166,72 @@ class PDFReport extends BaseReport {
12064
12166
  buildDataset(data) {
12065
12167
  return JSON.stringify(data);
12066
12168
  }
12169
+ buildColumns(columns) {
12170
+ const { widths, totalWidth } = this.getColumnsWidth(columns);
12171
+ return columns.reduce((result, col, index) => {
12172
+ let size;
12173
+ if (!totalWidth) {
12174
+ size = Math.floor(100 / columns.length);
12175
+ }
12176
+ else {
12177
+ size = Math.floor((widths[col.name] * 100) / totalWidth);
12178
+ }
12179
+ const row = {
12180
+ align: col.align || 'left',
12181
+ description: col.label,
12182
+ sequence: index,
12183
+ format: this.getFormatOfColumn(col),
12184
+ size: `${size}%`,
12185
+ xlsType: col.xlsType,
12186
+ };
12187
+ return Object.assign(Object.assign({}, result), { [col.name]: row });
12188
+ }, {});
12189
+ }
12190
+ getFormatOfColumn(column) {
12191
+ let format;
12192
+ let { mask } = column;
12193
+ if (mask) {
12194
+ format = {
12195
+ type: 'fix',
12196
+ params: {
12197
+ mask,
12198
+ },
12199
+ };
12200
+ }
12201
+ else if (column.componentProps && Object.keys(column.componentProps).length) {
12202
+ const { component } = column.componentProps;
12203
+ if (this.isNumberComponent(component)) {
12204
+ format = { type: 'float' };
12205
+ mask = this.checkAccessor(column.componentProps.mask);
12206
+ if (mask) {
12207
+ format.params = {};
12208
+ if (mask.currencySymbol) {
12209
+ format.type = 'currency';
12210
+ format.symbol = mask.currencySymbol;
12211
+ format.decimal = mask.decimalCharacter;
12212
+ format.thousands = mask.digitGroupSeparator;
12213
+ format.precision = mask.decimalPlaces;
12214
+ }
12215
+ else {
12216
+ format.params.decimal = mask.decimalCharacter;
12217
+ format.params.thousands = mask.digitGroupSeparator;
12218
+ format.params.precision = mask.decimalPlaces;
12219
+ }
12220
+ }
12221
+ }
12222
+ }
12223
+ return format;
12224
+ }
12225
+ isNumberComponent(component) {
12226
+ return ['ZdNumber', 'ZdCurrency', 'ZdIncrement'].indexOf(component) !== -1;
12227
+ }
12228
+ checkAccessor(value) {
12229
+ if (Accessor.isAccessorDefinition(value)) {
12230
+ const [controller, accessor] = Accessor.getAccessor(value);
12231
+ return Loader.getInstance(controller)[accessor];
12232
+ }
12233
+ return value;
12234
+ }
12067
12235
  buildMetadata(name, title, columns, filter, portrait = true) {
12068
12236
  return __awaiter(this, void 0, void 0, function* () {
12069
12237
  const builtCols = this.buildColumns(columns);
@@ -12145,6 +12313,7 @@ class PDFReport extends BaseReport {
12145
12313
  }
12146
12314
  }
12147
12315
 
12316
+ // XLS without groups (formatXLS = 'F3')
12148
12317
  class XLSReport extends BaseReport {
12149
12318
  constructor() {
12150
12319
  super(...arguments);
@@ -12191,13 +12360,14 @@ class XLSReport extends BaseReport {
12191
12360
  columns: builtCols,
12192
12361
  filter: builtFilters,
12193
12362
  reportXLS: true,
12363
+ formatXLS: 'F3',
12194
12364
  xlsMergedCell: [],
12195
12365
  };
12196
12366
  return Promise.resolve(JSON.stringify(metadataObj));
12197
12367
  }
12198
12368
  }
12199
12369
 
12200
- // XLS with groups
12370
+ // XLS with groups (formatXLS = 'F1')
12201
12371
  class XLS2Report extends BaseReport {
12202
12372
  constructor() {
12203
12373
  super(...arguments);
@@ -12235,6 +12405,7 @@ class XLS2Report extends BaseReport {
12235
12405
  columns: builtCols,
12236
12406
  filter: builtFilters,
12237
12407
  reportXLS: true,
12408
+ formatXLS: 'F1',
12238
12409
  xlsMergedCell: [],
12239
12410
  };
12240
12411
  return Promise.resolve(JSON.stringify(metadataObj));
@@ -12393,7 +12564,7 @@ class XLS2Report extends BaseReport {
12393
12564
  }
12394
12565
  }
12395
12566
 
12396
- // Grid mirror (with groups)
12567
+ // Grid mirror (with groups) (formatXLS = 'F2')
12397
12568
  class XLS3Report extends BaseReport {
12398
12569
  constructor() {
12399
12570
  super(...arguments);
@@ -12431,6 +12602,7 @@ class XLS3Report extends BaseReport {
12431
12602
  columns: builtCols,
12432
12603
  filter: builtFilters,
12433
12604
  reportXLS: true,
12605
+ formatXLS: 'F2',
12434
12606
  xlsMergedCell: [],
12435
12607
  };
12436
12608
  return Promise.resolve(JSON.stringify(metadataObj));