@isrd-isi-edu/ermrestjs 2.7.0 → 2.8.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.
@@ -25,7 +25,8 @@ import {
25
25
 
26
26
  // legacy
27
27
  import { _convertSearchTermToFilter, _getSortModifier, _getPagingModifier } from '@isrd-isi-edu/ermrestjs/js/parser';
28
- import { _isValidSortElement, _formatValueByType, _extends } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
28
+ import { _isValidSortElement, _extends } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
29
+ import { _formatValueByType } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
29
30
  import { _compressFacetObject } from '@isrd-isi-edu/ermrestjs/js/utils/pseudocolumn_helpers';
30
31
 
31
32
  import { Type } from '@isrd-isi-edu/ermrestjs/js/core';
package/js/core.js CHANGED
@@ -48,14 +48,13 @@ import SourceObjectWrapper from '@isrd-isi-edu/ermrestjs/src/models/source-objec
48
48
  import { parse } from '@isrd-isi-edu/ermrestjs/js/parser';
49
49
  import {
50
50
  _isValidBulkCreateForeignKey,
51
- _formatValueByType,
52
- _formatUtils,
53
51
  _getFormattedKeyValues,
54
52
  _getNullValue,
55
53
  _processColumnOrderList,
56
54
  processMarkdownPattern,
57
55
  _renderTemplate,
58
56
  } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
57
+ import { _formatUtils, _formatValueByType } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
59
58
  import printf from '@isrd-isi-edu/ermrestjs/js/format';
60
59
 
61
60
  // legacy
@@ -3,7 +3,6 @@
3
3
  /* eslint-disable @typescript-eslint/no-unused-vars */
4
4
  /* eslint-disable no-useless-escape */
5
5
  import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string';
6
- import moment from 'moment-timezone';
7
6
  import { default as mustache } from 'mustache';
8
7
 
9
8
  import $log from '@isrd-isi-edu/ermrestjs/src/services/logger';
@@ -12,12 +11,12 @@ import { InvalidFacetOperatorError } from '@isrd-isi-edu/ermrestjs/src/models/er
12
11
  import { Reference } from '@isrd-isi-edu/ermrestjs/src/models/reference';
13
12
 
14
13
  // legacy
15
- import { isObject, isObjectAndNotNull, isValidColorRGBHex, isStringAndNotEmpty } from '@isrd-isi-edu/ermrestjs/src/utils/type-utils';
14
+ import { isObject, isObjectAndNotNull, isStringAndNotEmpty } from '@isrd-isi-edu/ermrestjs/src/utils/type-utils';
16
15
  import { fixedEncodeURIComponent } from '@isrd-isi-edu/ermrestjs/src/utils/value-utils';
17
16
  import { renderMarkdown } from '@isrd-isi-edu/ermrestjs/src/utils/markdown-utils';
17
+ import { _formatUtils } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
18
18
  import {
19
19
  _systemColumns,
20
- _dataFormats,
21
20
  _contextArray,
22
21
  _contexts,
23
22
  _annotations,
@@ -27,8 +26,6 @@ import {
27
26
  URL_PATH_LENGTH_LIMIT,
28
27
  _ERMrestFeatures,
29
28
  _systemColumnNames,
30
- _specialPresentation,
31
- _classNames,
32
29
  TEMPLATE_ENGINES,
33
30
  _entryContexts,
34
31
  _compactContexts,
@@ -1341,461 +1338,6 @@ import AuthnService from '@isrd-isi-edu/ermrestjs/src/services/authn';
1341
1338
  return formatedDate;
1342
1339
  };
1343
1340
 
1344
- /**
1345
- * Given a number and precision, it will truncate it to show the given number
1346
- * of digits.
1347
- *
1348
- *
1349
- * @param {number} num
1350
- * @param {number} precision
1351
- * @param {number} minAllowedPrecision
1352
- */
1353
- export function _toPrecision(num, precision, minAllowedPrecision) {
1354
- precision = parseInt(precision);
1355
- precision = isNaN(precision) || precision < minAllowedPrecision ? minAllowedPrecision : precision;
1356
-
1357
- var isNegative = num < 0;
1358
- if (isNegative) num = num * -1;
1359
-
1360
- // this truncation logic only works because of the minimum precision that
1361
- // we're allowing. if we want to allow less than that, then we should change this.
1362
- var displayedNum = num.toString();
1363
- var f = displayedNum.indexOf('.');
1364
- if (f !== -1) {
1365
- // find the number of digits after decimal point
1366
- var decimalPlaces = Math.pow(10, precision - f);
1367
-
1368
- // truncate the value
1369
- displayedNum = Math.floor(num * decimalPlaces) / decimalPlaces;
1370
- }
1371
-
1372
- // if precision is too large, the calculation might return NaN.
1373
- if (isNaN(displayedNum)) {
1374
- return (isNegative ? '-' : '') + num;
1375
- }
1376
-
1377
- return (isNegative ? '-' : '') + displayedNum;
1378
- };
1379
-
1380
- /**
1381
- * @desc An object of pretty print utility functions
1382
- * @private
1383
- */
1384
- export const _formatUtils = {
1385
- /**
1386
- * @function
1387
- * @param {Object} value A boolean value to transform
1388
- * @param {Object} [options] Configuration options
1389
- * @return {string} A string representation of a boolean value
1390
- * @desc Formats a given boolean value into a string for display
1391
- */
1392
- printBoolean: function printBoolean(value, options) {
1393
- options = (typeof options === 'undefined') ? {} : options;
1394
- if (value === null) {
1395
- return '';
1396
- }
1397
- return Boolean(value).toString();
1398
- },
1399
-
1400
- /**
1401
- * @function
1402
- * @param {Object} value An integer value to transform
1403
- * @param {Object} [options] Configuration options
1404
- * @return {string} A string representation of value
1405
- * @desc Formats a given integer value into a whole number (with a thousands
1406
- * separator if necessary), which is transformed into a string for display.
1407
- */
1408
- printInteger: function printInteger(value, options) {
1409
- options = (typeof options === 'undefined') ? {} : options;
1410
- if (value === null) {
1411
- return '';
1412
- }
1413
-
1414
- // Remove fractional digits
1415
- value = Math.round(value);
1416
-
1417
- // Add comma separators
1418
- return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1419
- },
1420
-
1421
- /**
1422
- * @function
1423
- * @param {Object} value An timestamp value to transform
1424
- * @param {Object} [options] Configuration options. No options implemented so far.
1425
- * @return {string} A string representation of value. Default is ISO 8601-ish like 2017-01-08 15:06:02.
1426
- * @desc Formats a given timestamp value into a string for display.
1427
- */
1428
- printTimestamp: function printTimestamp(value, options) {
1429
- options = (typeof options === 'undefined') ? {} : options;
1430
- if (value === null) {
1431
- return '';
1432
- }
1433
-
1434
- try {
1435
- value = value.toString();
1436
- } catch (exception) {
1437
- $log.error("Couldn't extract timestamp from input: " + value);
1438
- $log.error(exception);
1439
- return '';
1440
- }
1441
-
1442
- if (!moment(value).isValid()) {
1443
- $log.error("Couldn't transform input to a valid timestamp: " + value);
1444
- return '';
1445
- }
1446
-
1447
- return moment(value).format(_dataFormats.DATETIME.display);
1448
- },
1449
-
1450
- /**
1451
- * @function
1452
- * @param {Object} value A date value to transform
1453
- * @param {Object} [options] Configuration options. No options implemented so far.
1454
- * @return {string} A string representation of value
1455
- * @desc Formats a given date[time] value into a date string for display.
1456
- * If any time information is provided, it will be left off.
1457
- */
1458
- printDate: function printDate(value, options) {
1459
- options = (typeof options === 'undefined') ? {} : options;
1460
- if (value === null) {
1461
- return '';
1462
- }
1463
- // var year, month, date;
1464
- try {
1465
- value = value.toString();
1466
- } catch (exception) {
1467
- $log.error("Couldn't extract date info from input: " + value);
1468
- $log.error(exception);
1469
- return '';
1470
- }
1471
-
1472
- if (!moment(value).isValid()) {
1473
- $log.error("Couldn't transform input to a valid date: " + value);
1474
- return '';
1475
- }
1476
-
1477
- return moment(value).format(_dataFormats.DATE);
1478
- },
1479
-
1480
- /**
1481
- * @function
1482
- * @param {Object} value A float value to transform
1483
- * @param {Object} [options] Configuration options.
1484
- * - "numFracDigits" is the number of fractional digits to appear after the decimal point
1485
- * @return {string} A string representation of value
1486
- * @desc Formats a given float value into a string for display. Removes leading 0s; adds thousands separator.
1487
- */
1488
- printFloat: function printFloat(value, options) {
1489
- options = (typeof options === 'undefined') ? {} : options;
1490
-
1491
- if (value === null) {
1492
- return '';
1493
- }
1494
-
1495
- value = parseFloat(value);
1496
- if (options.numFracDigits) {
1497
- value = value.toFixed(options.numFracDigits); // toFixed() rounds the value, is ok?
1498
- } else {
1499
- // if the float has 13 digits or more (1 trillion or greater)
1500
- // or the float has 7 decimals or more, use scientific notation
1501
- // NOTE: javascript in browser uses 22 as the threshold for large numbers
1502
- // If there are 22 digits or more, then scientific notation is used
1503
- // ecmascript language spec: https://262.ecma-international.org/5.1/#sec-9.8.1
1504
- if (Math.abs(value) >= 1000000000000 || Math.abs(value) < 0.000001) {
1505
- // this also ensures there are more digits than the precision used
1506
- // so the number will be converted to scientific notation instead of
1507
- // being padded with zeroes with no conversion
1508
- // for example: 0.000001.toPrecision(4) ==> '0.000001000'
1509
- value = value.toPrecision(5);
1510
- } else {
1511
- value = value.toFixed(4);
1512
- }
1513
-
1514
- }
1515
-
1516
- // Remove leading zeroes
1517
- value = value.toString().replace(/^0+(?!\.|$)/, '');
1518
-
1519
- // Add comma separators
1520
- var parts = value.split(".");
1521
- parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1522
- return parts.join(".");
1523
- },
1524
-
1525
- /**
1526
- * @function
1527
- * @param {Object} value A text value to transform
1528
- * @param {Object} [options] Configuration options.
1529
- * @return {string} A string representation of value
1530
- * @desc Formats a given text value into a string for display.
1531
- */
1532
- printText: function printText(value, options) {
1533
- options = (typeof options === 'undefined') ? {} : options;
1534
- if (value === null) {
1535
- return '';
1536
- }
1537
- if (typeof value === 'object') {
1538
- return JSON.stringify(value);
1539
- }
1540
- return value.toString();
1541
- },
1542
-
1543
- /**
1544
- * @function
1545
- * @param {Object} value The Markdown to transform
1546
- * @param {Object} [options] Configuration options.
1547
- * @return {string} A string representation of value
1548
- * @desc Formats Markdown syntax into an HTML string for display.
1549
- */
1550
- printMarkdown: function printMarkdown(value, options) {
1551
- options = (typeof options === 'undefined') ? {} : options;
1552
- if (value === null) {
1553
- return '';
1554
- }
1555
-
1556
- return renderMarkdown(value, options.inline);
1557
- },
1558
-
1559
- /**
1560
- * @function
1561
- * @param {Object} value A json value to transform
1562
- * @return {string} A string representation of value based on different context
1563
- * The beautified version of JSON in other cases
1564
- * A special case to show null if the value is blank string
1565
- * @desc Formats a given json value into a string for display.
1566
- */
1567
- printJSON: function printJSON(value, options) {
1568
- return value === "" ? JSON.stringify(null) : JSON.stringify(value, undefined, 2);
1569
- },
1570
-
1571
- /**
1572
- * @function
1573
- * @param {string} value The gene sequence to transform
1574
- * @param {Object} [options] Configuration options. Accepted parameters
1575
- * are "increment" (desired number of characters in each segment) and
1576
- * "separator" (desired separator between segments).
1577
- * @return {string} A string representation of value
1578
- * @desc Formats a gene sequence into a string for display. By default,
1579
- * it will split gene sequence into an increment of 10 characters and
1580
- * insert an empty space in between each increment.
1581
- */
1582
-
1583
- printGeneSeq: function printGeneSeq(value, options) {
1584
- options = (typeof options === 'undefined') ? {} : options;
1585
-
1586
- if (value === null) {
1587
- return '';
1588
- }
1589
-
1590
- try {
1591
- // Default separator is a space.
1592
- if (!options.separator) {
1593
- options.separator = ' ';
1594
- }
1595
- // Default increment is 10
1596
- if (!options.increment) {
1597
- options.increment = 10;
1598
- }
1599
- var inc = parseInt(options.increment, 10);
1600
-
1601
- if (inc === 0) {
1602
- return value.toString();
1603
- }
1604
-
1605
- // Reset the increment if it's negative
1606
- if (inc <= -1) {
1607
- inc = 1;
1608
- }
1609
-
1610
- var formattedSeq = '`';
1611
- var separator = options.separator;
1612
- while (value.length >= inc) {
1613
- // Get the first inc number of chars
1614
- var chunk = value.slice(0, inc);
1615
- // Append the chunk and separator
1616
- formattedSeq += chunk + separator;
1617
- // Remove this chunk from value
1618
- value = value.slice(inc);
1619
- }
1620
-
1621
- // Append any remaining chars from value that was too small to form an increment
1622
- formattedSeq += value;
1623
-
1624
- // Slice off separator at the end
1625
- if (formattedSeq.slice(-1) == separator) {
1626
- formattedSeq = formattedSeq.slice(0, -1);
1627
- }
1628
-
1629
- // Add the ending backtick at the end
1630
- formattedSeq += '`';
1631
-
1632
- // Run it through renderMarkdown to get the sequence in a fixed-width font
1633
- return renderMarkdown(formattedSeq, true);
1634
- } catch (e) {
1635
- $log.error("Couldn't parse the given markdown value: " + value);
1636
- $log.error(e);
1637
- return value;
1638
- }
1639
-
1640
- },
1641
-
1642
- /**
1643
- * @function
1644
- * @param {Array} value the array of values
1645
- * @param {Object} options Configuration options. Accepted parameters:
1646
- * - `isMarkdown`: if this is true, we will not esacpe markdown characters
1647
- * - `returnArray`: if this is true, it will return an array of strings.
1648
- * @return {string|string[]} A string represntation of array.
1649
- * @desc
1650
- * Will generate a comma seperated value for an array. It will also change `null` and `""`
1651
- * to their special presentation.
1652
- * The returned value might return markdown, which then should call printMarkdown on it.
1653
- */
1654
- printArray: function (value, options) {
1655
- options = (typeof options === 'undefined') ? {} : options;
1656
-
1657
- if (!value || !Array.isArray(value) || value.length === 0) {
1658
- return '';
1659
- }
1660
-
1661
- var arr = value.map(function (v) {
1662
- var isMarkdown = (options.isMarkdown === true);
1663
- var pv = v;
1664
- if (v === "") {
1665
- pv = _specialPresentation.EMPTY_STR;
1666
- isMarkdown = true;
1667
- }
1668
- else if (v == null) {
1669
- pv = _specialPresentation.NULL;
1670
- isMarkdown = true;
1671
- }
1672
-
1673
- if (!isMarkdown) pv = _escapeMarkdownCharacters(pv);
1674
- return pv;
1675
- });
1676
-
1677
- if (options.returnArray) return arr;
1678
- return arr.join(", ");
1679
- },
1680
-
1681
- printColor: function (value, options) {
1682
- options = (typeof options === 'undefined') ? {} : options;
1683
-
1684
- if (!isValidColorRGBHex(value)) {
1685
- return '';
1686
- }
1687
-
1688
- value = value.toUpperCase();
1689
- return ':span: :/span:{.' + _classNames.colorPreview + ' style=background-color:' + value +'} ' + value;
1690
- },
1691
-
1692
- /**
1693
- * Return the humanize value of byte count
1694
- *
1695
- * This function will not round up and will only truncate the number
1696
- * to honor the given precision. In 'si', precision below 3 is not allowed.
1697
- * Similarly, precision below 4 is not allowed in 'binary'.
1698
- * 'raw' will return the "formatted" value.
1699
- *
1700
- * @param {*} value
1701
- * @param {?string} mode either `raw`, `si`, or `binary` (if invalid or missing, 'si' will be used)
1702
- * @param {?number} precision An integer specifying the number of digits to be displayed
1703
- * (if invalid or missing, `3` will be used by default.)
1704
- * @param {?boolean} withTooltip whether we should return it with tooltip or just the value.
1705
- */
1706
- humanizeBytes: function (value, mode, precision, withTooltip) {
1707
- // we cannot use parseInt here since it won't allow larger numbers.
1708
- var v = parseFloat(value);
1709
- mode = ['raw', 'si', 'binary'].indexOf(mode) === -1 ? 'si' : mode;
1710
-
1711
- if (isNaN(v)) return '';
1712
- if (v === 0 || mode === 'raw') {
1713
- return _formatUtils.printInteger(value);
1714
- }
1715
-
1716
- var divisor = 1000, units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
1717
- if (mode === 'binary') {
1718
- divisor = 1024;
1719
- units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
1720
- }
1721
-
1722
- // find the closest power of the divisor to the given number ('u').
1723
- // in the end, 'v' will be the number that we should display.
1724
- var u = 0;
1725
- while (v >= divisor || -v >= divisor) {
1726
- v /= divisor;
1727
- u++;
1728
- }
1729
-
1730
- // our units don't support this, so just return the "raw" mode value.
1731
- if (u >= units.length) {
1732
- return _formatUtils.printInteger(value);
1733
- }
1734
-
1735
- // we don't want to truncate the value, so we should set a minimum
1736
- var minP = mode === "si" ? 3 : 4;
1737
-
1738
- var res = (u ? _toPrecision(v, precision, minP) : v) + ' ' + units[u];
1739
- if (typeof withTooltip === 'boolean' && withTooltip && u > 0) {
1740
- var numBytes = _formatUtils.printInteger(Math.pow(divisor, u));
1741
- var tooltip = _formatUtils.printInteger(value);
1742
- tooltip += ' bytes (1 ' + units[u] + ' = ' + numBytes + ' bytes)';
1743
- res = ':span:' + res + ':/span:{data-chaise-tooltip="' + tooltip + '"}';
1744
- }
1745
- return res;
1746
- }
1747
- };
1748
-
1749
- /**
1750
- * format the raw value based on the column definition type, heuristics, annotations, etc.
1751
- * @param {Type} type - the type object of the column
1752
- * @param {Object} data - the 'raw' data value.
1753
- * @returns {string} The formatted value.
1754
- */
1755
- export function _formatValueByType(type, data, options) {
1756
- var utils = _formatUtils;
1757
- switch(type.name) {
1758
- case 'timestamp':
1759
- case 'timestamptz':
1760
- data = utils.printTimestamp(data, options);
1761
- break;
1762
- case 'date':
1763
- data = utils.printDate(data, options);
1764
- break;
1765
- case 'numeric':
1766
- case 'float4':
1767
- case 'float8':
1768
- data = utils.printFloat(data, options);
1769
- break;
1770
- case 'int2':
1771
- case 'int4':
1772
- case 'int8':
1773
- data = utils.printInteger(data, options);
1774
- break;
1775
- case 'boolean':
1776
- data = utils.printBoolean(data, options);
1777
- break;
1778
- case 'markdown':
1779
- // Do nothing as we will format markdown at the end of format
1780
- data = data.toString();
1781
- break;
1782
- case 'gene_sequence':
1783
- data = utils.printGeneSeq(data, options);
1784
- break;
1785
- //Cases to support json and jsonb columns
1786
- case 'json':
1787
- case 'jsonb':
1788
- data = utils.printJSON(data, options);
1789
- break;
1790
- case 'color_rgb_hex':
1791
- data = utils.printColor(data, options);
1792
- break;
1793
- default: // includes 'text' and 'longtext' cases
1794
- data = type.baseType ? _formatValueByType(type.baseType, data, options) : utils.printText(data, options);
1795
- break;
1796
- }
1797
- return data;
1798
- };
1799
1341
 
1800
1342
  export function _isValidSortElement(element, index, array) {
1801
1343
  return (typeof element == 'object' &&
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@isrd-isi-edu/ermrestjs",
3
3
  "description": "ERMrest client library in JavaScript",
4
- "version": "2.7.0",
4
+ "version": "2.8.0",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
7
7
  "node": ">= 20.0.0",
package/src/index.ts CHANGED
@@ -60,12 +60,12 @@ import {
60
60
  decodeFacet,
61
61
  encodeFacet,
62
62
  encodeFacetString,
63
- _formatUtils,
64
63
  processMarkdownPattern,
65
64
  renderMustacheTemplate,
66
65
  _validateMustacheTemplate,
67
66
  generateKeyValueFilters,
68
67
  } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
68
+ import { _formatUtils } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
69
69
  import {
70
70
  AttributeGroupColumn,
71
71
  AttributeGroupReference,
@@ -4,7 +4,7 @@ import { DisplayName } from '@isrd-isi-edu/ermrestjs/src/models/display-name';
4
4
 
5
5
  // utils
6
6
  import { fixedEncodeURIComponent, shallowCopy, simpleDeepCopy } from '@isrd-isi-edu/ermrestjs/src/utils/value-utils';
7
- import { isObjectAndNotNull } from '@isrd-isi-edu/ermrestjs/src/utils/type-utils';
7
+ import { isObjectAndNotNull, isStringAndNotEmpty } from '@isrd-isi-edu/ermrestjs/src/utils/type-utils';
8
8
  import { _ERMrestACLs, _contexts, _permissionMessages } from '@isrd-isi-edu/ermrestjs/src/utils/constants';
9
9
 
10
10
  import { isAllOutboundColumn } from '@isrd-isi-edu/ermrestjs/src/utils/column-utils';
@@ -154,6 +154,13 @@ export class Tuple {
154
154
  return this._data;
155
155
  }
156
156
 
157
+ /**
158
+ *
159
+ * @param permission the ermrest permission that should be checked (refer to _ERMrestACLs constant for more details)
160
+ * @param colName the name of the column for which the permission should be checked
161
+ * @param isAssoc whether the permission check is for an association
162
+ * @returns a boolean indicating whether the permission is granted
163
+ */
157
164
  checkPermissions(permission: string, colName?: string, isAssoc = false): boolean {
158
165
  let sum = this._rightsSummary[permission];
159
166
  if (isAssoc) {
@@ -161,6 +168,12 @@ export class Tuple {
161
168
  }
162
169
 
163
170
  if (permission === _ERMrestACLs.COLUMN_UPDATE) {
171
+ // if the column is passed but doesn't exist in the table, return false
172
+ if (isStringAndNotEmpty(colName) && !this._pageRef.table.columns.has(colName!)) {
173
+ return false;
174
+ }
175
+
176
+ // if there aren't any column-level permissions, then allow it
164
177
  if (!isObjectAndNotNull(sum) || typeof sum[colName!] !== 'boolean') return true;
165
178
  return sum[colName!];
166
179
  }
@@ -12,11 +12,11 @@ import {
12
12
  _addErmrestVarsToTemplate,
13
13
  _addTemplateVars,
14
14
  _escapeMarkdownCharacters,
15
- _formatUtils,
16
15
  _getPath,
17
16
  encodeFacet,
18
17
  encodeFacetString,
19
18
  } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
19
+ import { _formatUtils } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
20
20
  import AuthnService from '@isrd-isi-edu/ermrestjs/src/services/authn';
21
21
  import { isObjectAndNotNull } from '@isrd-isi-edu/ermrestjs/src/utils/type-utils';
22
22
  import { fixedEncodeURIComponent } from '@isrd-isi-edu/ermrestjs/src/utils/value-utils';
@@ -403,6 +403,28 @@ export default class HandlebarsService {
403
403
  return _formatUtils.humanizeBytes(value, mode, precision, tooltip);
404
404
  },
405
405
 
406
+ /**
407
+ * {{datetimeDuration start end}}
408
+ * {{datetimeDuration start end unit="month"}}
409
+ * {{datetimeDuration start end unit="auto" fraction=2}}
410
+ * {{datetimeDuration start end unit="multi"}}
411
+ * {{datetimeDuration start end unit="calendar"}}
412
+ * {{datetimeDuration start end direction="before/after"}}
413
+ * {{datetimeDuration start end unit="month" tooltip=true}}
414
+ * @ignore
415
+ * @returns human-readable duration between `start` and `end`
416
+ */
417
+ datetimeDuration: function (start: any, end: any, options: Handlebars.HelperOptions) {
418
+ let unit, fraction, direction, tooltip;
419
+ if (options && isObjectAndNotNull(options.hash)) {
420
+ unit = options.hash.unit;
421
+ fraction = options.hash.fraction;
422
+ direction = options.hash.direction;
423
+ tooltip = options.hash.tooltip;
424
+ }
425
+ return _formatUtils.datetimeDuration(start, end, unit, fraction, direction, tooltip);
426
+ },
427
+
406
428
  /**
407
429
  * {{stringLength value }}
408
430
  * @ignore
@@ -18,12 +18,12 @@ import { isDefinedAndNotNull } from '@isrd-isi-edu/ermrestjs/src/utils/type-util
18
18
 
19
19
  // legacy
20
20
  import {
21
- _formatUtils,
22
21
  _generateRowPresentation,
23
22
  _getRowTemplateVariables,
24
23
  _processColumnOrderList,
25
24
  _renderTemplate,
26
25
  } from '@isrd-isi-edu/ermrestjs/js/utils/helpers';
26
+ import { _formatUtils } from '@isrd-isi-edu/ermrestjs/src/utils/format-utils';
27
27
 
28
28
  /**
29
29
  * Convert the raw value of an aggregate column to a formatted value.