@itfin/components 1.3.88 → 1.3.90
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.
- package/package.json +1 -1
- package/src/ITFSettings.js +29 -6
- package/src/assets/scss/icons.scss +2 -2
- package/src/components/filter/FilterPanel.vue +2 -6
- package/src/components/table/Table2.vue +2 -0
- package/src/components/table/TableBody.vue +2 -32
- package/src/components/table/TableGroup.vue +3 -0
- package/src/components/table/TableHeader.vue +19 -8
- package/src/components/table/TableRows.vue +6 -1
- package/src/components/table/table2.scss +60 -0
- package/src/helpers/formatters.js +28 -1
- package/src/helpers/formatters.spec.js +18 -1
package/package.json
CHANGED
package/src/ITFSettings.js
CHANGED
|
@@ -10,15 +10,41 @@ class ITFSettings {
|
|
|
10
10
|
defaultLocale: 'en_US',
|
|
11
11
|
defaultDisplayDateFormat: 'MM/dd/yyyy',
|
|
12
12
|
// defaultDisplayDateFormat: 'dd.MM.yyyy',
|
|
13
|
-
currencies: []
|
|
13
|
+
currencies: [],
|
|
14
|
+
moneyDisplayFormat: '{symbol}{value}',
|
|
15
|
+
moneyThousandSeparator: ',',
|
|
16
|
+
moneyDecimalSeparator: '.',
|
|
17
|
+
supportLanguages: [
|
|
18
|
+
{ shortCode: 'en', locale: 'en_US', name: 'English', dateFormat: 'MM/dd/yyyy', moneyDisplayFormat: '{symbol}{value}', moneyThousandSeparator: ',', moneyDecimalSeparator: '.' },
|
|
19
|
+
{ shortCode: 'uk', locale: 'uk_UA', name: 'Українська (Ukrainian)', dateFormat: 'dd.MM.yyyy', moneyDisplayFormat: '{value}\xA0{symbol}', moneyThousandSeparator: '\xA0', moneyDecimalSeparator: ',' },
|
|
20
|
+
]
|
|
14
21
|
};
|
|
15
22
|
|
|
23
|
+
get moneyDisplayFormat() {
|
|
24
|
+
return this.options.moneyDisplayFormat;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get moneyThousandSeparator() {
|
|
28
|
+
return this.options.moneyThousandSeparator;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get moneyDecimalSeparator() {
|
|
32
|
+
return this.options.moneyDecimalSeparator;
|
|
33
|
+
}
|
|
34
|
+
|
|
16
35
|
get defaultLocale() {
|
|
17
36
|
return this.options.defaultLocale;
|
|
18
37
|
}
|
|
19
38
|
|
|
20
39
|
set defaultLocale(val) {
|
|
21
|
-
this.options.
|
|
40
|
+
let lang = this.options.supportLanguages.find((l) => l.shortCode === val || l.locale === val);
|
|
41
|
+
if (!lang) {
|
|
42
|
+
lang = this.options.supportLanguages[0];
|
|
43
|
+
}
|
|
44
|
+
this.options.defaultLocale = lang.locale;
|
|
45
|
+
this.options.moneyDisplayFormat = lang.moneyDisplayFormat;
|
|
46
|
+
this.options.moneyDecimalSeparator = lang.moneyDecimalSeparator;
|
|
47
|
+
this.options.moneyThousandSeparator = lang.moneyThousandSeparator;
|
|
22
48
|
}
|
|
23
49
|
|
|
24
50
|
get currencies() {
|
|
@@ -30,10 +56,7 @@ class ITFSettings {
|
|
|
30
56
|
}
|
|
31
57
|
|
|
32
58
|
get supportLanguages() {
|
|
33
|
-
return
|
|
34
|
-
{ locale: 'en_US', name: 'English', dateFormat: 'MM/dd/yyyy' },
|
|
35
|
-
{ locale: 'uk_UA', name: 'Українська (Ukrainian)', dateFormat: 'dd.MM.yyyy' },
|
|
36
|
-
];
|
|
59
|
+
return this.options.supportLanguages;
|
|
37
60
|
}
|
|
38
61
|
|
|
39
62
|
get firstDayOfWeek() {
|
|
@@ -768,7 +768,7 @@ $bootstrap-icons-map: (
|
|
|
768
768
|
//"gear-fill": "\f3e2",
|
|
769
769
|
//"gear-wide-connected": "\f3e3",
|
|
770
770
|
//"gear-wide": "\f3e4",
|
|
771
|
-
|
|
771
|
+
"gear": "\f3e5",
|
|
772
772
|
//"gem": "\f3e6",
|
|
773
773
|
//"geo-alt-fill": "\f3e7",
|
|
774
774
|
//"geo-alt": "\f3e8",
|
|
@@ -896,7 +896,7 @@ $bootstrap-icons-map: (
|
|
|
896
896
|
//"layout-text-sidebar": "\f462",
|
|
897
897
|
//"layout-text-window-reverse": "\f463",
|
|
898
898
|
//"layout-text-window": "\f464",
|
|
899
|
-
"layout-three-columns": "\f465",
|
|
899
|
+
//"layout-three-columns": "\f465",
|
|
900
900
|
//"layout-wtf": "\f466",
|
|
901
901
|
//"life-preserver": "\f467",
|
|
902
902
|
//"lightbulb-fill": "\f468",
|
|
@@ -39,7 +39,7 @@ import itfIcon from '../icon/Icon';
|
|
|
39
39
|
import itfButton from '../button/Button';
|
|
40
40
|
import itfDropdown from '../dropdown/Dropdown.vue';
|
|
41
41
|
import itfTextField from '../text-field/TextField.vue';
|
|
42
|
-
import {
|
|
42
|
+
import { formatMoney, formatRangeDates } from '../../helpers/formatters';
|
|
43
43
|
import FilterBadge from './FilterBadge.vue';
|
|
44
44
|
|
|
45
45
|
export default @Component({
|
|
@@ -52,10 +52,6 @@ export default @Component({
|
|
|
52
52
|
},
|
|
53
53
|
directives: {
|
|
54
54
|
tooltip
|
|
55
|
-
},
|
|
56
|
-
filters: {
|
|
57
|
-
formatMoney,
|
|
58
|
-
formatDateonly
|
|
59
55
|
}
|
|
60
56
|
})
|
|
61
57
|
class FilterPanel extends Vue {
|
|
@@ -155,7 +151,7 @@ class FilterPanel extends Vue {
|
|
|
155
151
|
}
|
|
156
152
|
} else if (facet.type === 'date') {
|
|
157
153
|
const date = DateTime.fromISO(value.value);
|
|
158
|
-
value.label =
|
|
154
|
+
value.label = (date.isValid ? value.value : DateTime.fromISO(facet.options.defaultValue.value)).toFormat('dd MMM yyyy');
|
|
159
155
|
value.isDefault = facet.options.defaultValue ? value.value === facet.options.defaultValue.value : false;
|
|
160
156
|
} else if (facet.type === 'facets-list') {
|
|
161
157
|
const firstItem = facet.options.items.find(item => item.value === (Array.isArray(value.value) ? value.value[0] : value.value));
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
:show-grouping="showGrouping"
|
|
26
26
|
:show-summary="showSummary"
|
|
27
27
|
:show-add-column="showAddColumn"
|
|
28
|
+
:show-actions="showActions"
|
|
28
29
|
:show-header="!noHeader"
|
|
29
30
|
:schema="schema"
|
|
30
31
|
:editable="editable"
|
|
@@ -106,6 +107,7 @@ class itfTable2 extends Vue {
|
|
|
106
107
|
@Prop(Boolean) columnResizing;
|
|
107
108
|
@Prop(Boolean) showAddColumn;
|
|
108
109
|
@Prop(Boolean) showGrouping;
|
|
110
|
+
@Prop(Boolean) showActions;
|
|
109
111
|
@Prop(Boolean) showSummary;
|
|
110
112
|
@Prop(Boolean) noHeader;
|
|
111
113
|
@Prop(Boolean) noColumnMenu;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
:id-property="idProperty"
|
|
9
9
|
:subrows-property="subrowsProperty"
|
|
10
10
|
:show-add-column="showAddColumn"
|
|
11
|
+
:show-actions="showActions"
|
|
11
12
|
:no-select-all="noSelectAll"
|
|
12
13
|
:editable="editable"
|
|
13
14
|
:currency="currency"
|
|
@@ -118,38 +119,6 @@
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
.table-item-inner .boundary {
|
|
122
|
-
z-index: 3;
|
|
123
|
-
position: absolute;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.table-item-inner .boundary.top, .table-item-inner .boundary.bottom {
|
|
127
|
-
width: 100%;
|
|
128
|
-
border-top: thin solid #0000;
|
|
129
|
-
top: 0;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.table-item-inner .boundary {
|
|
133
|
-
z-index: 3;
|
|
134
|
-
position: absolute;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
.table-item-inner .boundary.left, .table-item-inner .boundary.right {
|
|
138
|
-
height: 100%;
|
|
139
|
-
border-left: thin solid #0000;
|
|
140
|
-
left: 0;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.table-item-inner .boundary.right {
|
|
144
|
-
left: auto;
|
|
145
|
-
border-right: 1px solid var(--itf-table-border-color);
|
|
146
|
-
right: 0;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.table-item-inner .boundary.bottom {
|
|
150
|
-
top: auto;
|
|
151
|
-
bottom: 0;
|
|
152
|
-
}
|
|
153
122
|
.table-small-row .table-view-item {
|
|
154
123
|
// height: var(--table-row-height);
|
|
155
124
|
}
|
|
@@ -185,6 +154,7 @@ class itfTableBody extends Vue {
|
|
|
185
154
|
@Prop() subrowsProperty;
|
|
186
155
|
@Prop() active;
|
|
187
156
|
@Prop(Boolean) showAddColumn;
|
|
157
|
+
@Prop(Boolean) showActions;
|
|
188
158
|
@Prop(Boolean) noSelectAll;
|
|
189
159
|
@Prop(Boolean) editable;
|
|
190
160
|
@Prop(Boolean) expandedAll;
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
:column-resizing="columnResizing"
|
|
38
38
|
:column-sorting="columnSorting"
|
|
39
39
|
:show-add-column="showAddColumn"
|
|
40
|
+
:show-actions="showActions"
|
|
40
41
|
:rows="rows"
|
|
41
42
|
:schema="schema"
|
|
42
43
|
:editable="editable"
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
:expanded-all="expandedAll"
|
|
70
71
|
:striped="striped"
|
|
71
72
|
:show-add-column="showAddColumn"
|
|
73
|
+
:show-actions="showActions"
|
|
72
74
|
:expanded-ids="expandedIds"
|
|
73
75
|
:css-property="cssProperty"
|
|
74
76
|
:editable-property="editableProperty"
|
|
@@ -349,6 +351,7 @@ class itfTableGroup extends Vue {
|
|
|
349
351
|
@Prop(Boolean) columnSorting;
|
|
350
352
|
@Prop(Boolean) columnResizing;
|
|
351
353
|
@Prop(Boolean) showAddColumn;
|
|
354
|
+
@Prop(Boolean) showActions;
|
|
352
355
|
@Prop(Boolean) showHeader;
|
|
353
356
|
@Prop(Boolean) noColumnMenu;
|
|
354
357
|
@Prop(Boolean) noSelectAll;
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
|
|
34
34
|
<itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
|
|
35
35
|
<template #button>
|
|
36
|
-
<span class="itf-table2__header-title text-truncate" :title="column.title
|
|
36
|
+
<span class="itf-table2__header-title text-truncate" :title="getTitle(column.title)" :class="{'ms-auto': column.align === 'end'}">
|
|
37
37
|
<span v-if="column.icon" :class="column.icon"></span>
|
|
38
|
-
{{column.title
|
|
38
|
+
{{getTitle(column.title)}}
|
|
39
39
|
<div v-if="column.prefix" class="itf-table2__subtitle" v-text="column.prefix" />
|
|
40
40
|
</span>
|
|
41
41
|
<itf-icon v-if="_sorting[column.property]" :name="_sorting[column.property] === 'asc' ? 'arrow_up' : 'arrow_down'" :size="16" class="ms-1" />
|
|
@@ -85,10 +85,10 @@
|
|
|
85
85
|
<div v-if="visibleHeader && columnResizing && !column.grow" ref="resizeHandle" class="resize-handle"></div>
|
|
86
86
|
</div>
|
|
87
87
|
</template>
|
|
88
|
-
<div
|
|
89
|
-
|
|
88
|
+
<div class="table-view-item-value extra flex-grow-1"></div>
|
|
89
|
+
<itf-dropdown v-if="showAddColumn && visibleHeader" ref="newDd" text append-to-context shadow autoclose="outside" class="table-header-add-column table-view-item-actions" data-test="table-header-add-column">
|
|
90
90
|
<template #button>
|
|
91
|
-
<span class="nom-
|
|
91
|
+
<itf-button icon small><span class="nom-gear"></span></itf-button>
|
|
92
92
|
</template>
|
|
93
93
|
|
|
94
94
|
<itf-sortable :value="sortedColumns" @input="onSortColumns">
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
<div>
|
|
100
100
|
<span class="nom-grip-vertical"></span>
|
|
101
101
|
<span v-if="column.icon" :class="column.icon"></span>
|
|
102
|
-
{{column.title
|
|
102
|
+
{{getTitle(column.title)}}
|
|
103
103
|
</div>
|
|
104
104
|
<span v-if="column.pinned" class="nom-pin-fill"></span>
|
|
105
105
|
</div>
|
|
@@ -117,13 +117,17 @@
|
|
|
117
117
|
<a href="" @click.prevent="addColumn(column)" :key="`inv-column${k}`" class="dropdown-item d-flex align-items-center justify-content-between px-2 py-1">
|
|
118
118
|
<div>
|
|
119
119
|
<span class="nom-plus"></span>
|
|
120
|
-
{{column.title
|
|
120
|
+
{{getTitle(column.title)}}
|
|
121
121
|
</div>
|
|
122
122
|
</a>
|
|
123
123
|
</template>
|
|
124
124
|
</div>
|
|
125
125
|
</itf-dropdown>
|
|
126
|
-
|
|
126
|
+
|
|
127
|
+
<div class="boundary top"></div>
|
|
128
|
+
<div class="boundary right"></div>
|
|
129
|
+
<div class="boundary bottom"></div>
|
|
130
|
+
<div class="boundary left"></div>
|
|
127
131
|
</div>
|
|
128
132
|
</div>
|
|
129
133
|
|
|
@@ -182,6 +186,13 @@ class itfTableHeader extends Vue {
|
|
|
182
186
|
}
|
|
183
187
|
}
|
|
184
188
|
|
|
189
|
+
getTitle(title) {
|
|
190
|
+
if (typeof title === 'string') {
|
|
191
|
+
return title;
|
|
192
|
+
}
|
|
193
|
+
return title[this.locale] || title['en_US'];
|
|
194
|
+
}
|
|
195
|
+
|
|
185
196
|
get locale() {
|
|
186
197
|
return settings.defaultLocale;
|
|
187
198
|
}
|
|
@@ -78,7 +78,10 @@
|
|
|
78
78
|
</slot>
|
|
79
79
|
</div>
|
|
80
80
|
</template>
|
|
81
|
-
<div
|
|
81
|
+
<div class="table-view-item-value extra"></div>
|
|
82
|
+
<div v-if="showActions" class="table-view-item-actions">
|
|
83
|
+
<slot name="actions" :level="level" :toggle="() => $emit('toggle', item)" :item="item"></slot>
|
|
84
|
+
</div>
|
|
82
85
|
<div class="boundary top"></div>
|
|
83
86
|
<div class="boundary right"></div>
|
|
84
87
|
<div class="boundary bottom"></div>
|
|
@@ -95,6 +98,7 @@
|
|
|
95
98
|
:id-property="idProperty"
|
|
96
99
|
:subrows-property="subrowsProperty"
|
|
97
100
|
:show-add-column="showAddColumn"
|
|
101
|
+
:show-actions="showActions"
|
|
98
102
|
:no-select-all="noSelectAll"
|
|
99
103
|
:editable="editable"
|
|
100
104
|
:currency="currency"
|
|
@@ -157,6 +161,7 @@ class itfTableRows extends Vue {
|
|
|
157
161
|
@Prop(Boolean) editable;
|
|
158
162
|
@Prop(Boolean) expandedAll;
|
|
159
163
|
@Prop(Boolean) striped;
|
|
164
|
+
@Prop(Boolean) showActions;
|
|
160
165
|
@Prop() editableProperty;
|
|
161
166
|
@Prop() selectedIds;
|
|
162
167
|
@Prop() expandedIds;
|
|
@@ -67,8 +67,35 @@ body[data-theme="dark"] {
|
|
|
67
67
|
cursor: pointer;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
.table-view-item-actions {
|
|
71
|
+
background-image: linear-gradient(90deg, transparent 0, var(--itf-table2-row-bg) 10px);
|
|
72
|
+
position: sticky;
|
|
73
|
+
top: 0;
|
|
74
|
+
bottom: 0;
|
|
75
|
+
right: -5px;
|
|
76
|
+
padding-right: 5px;
|
|
77
|
+
padding-left: 5px;
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
}
|
|
81
|
+
.on-hover {
|
|
82
|
+
opacity: 0;
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
}
|
|
85
|
+
.table-row-template:hover .on-hover {
|
|
86
|
+
opacity: 1;
|
|
87
|
+
pointer-events: all;
|
|
88
|
+
}
|
|
89
|
+
.table-row-template:hover .hide-hover {
|
|
90
|
+
opacity: 0;
|
|
91
|
+
pointer-events: none;
|
|
92
|
+
}
|
|
93
|
+
.table-header-add-column {
|
|
94
|
+
background-image: linear-gradient(90deg, transparent 0, var(--itf-table-header-bg) 10px);
|
|
95
|
+
}
|
|
70
96
|
|
|
71
97
|
&__header {
|
|
98
|
+
--itf-table2-row-bg: --itf-table-header-bg;
|
|
72
99
|
background-color: var(--itf-table-header-bg);
|
|
73
100
|
position: sticky;
|
|
74
101
|
top: 0;
|
|
@@ -87,8 +114,12 @@ body[data-theme="dark"] {
|
|
|
87
114
|
z-index: 100000001;
|
|
88
115
|
background: rgba(235,237,239,0.75);
|
|
89
116
|
}
|
|
117
|
+
.itf-table2 & .boundary.top, .itf-table2 & .boundary.bottom {
|
|
118
|
+
border-color: var(--itf-table-border-color)
|
|
119
|
+
}
|
|
90
120
|
.table-row-template {
|
|
91
121
|
display: flex;
|
|
122
|
+
position: relative;
|
|
92
123
|
align-items: stretch;
|
|
93
124
|
height: auto;
|
|
94
125
|
user-select: none;
|
|
@@ -305,4 +336,33 @@ body[data-theme="dark"] {
|
|
|
305
336
|
position: sticky;
|
|
306
337
|
}
|
|
307
338
|
}
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
.boundary {
|
|
342
|
+
z-index: 3;
|
|
343
|
+
position: absolute;
|
|
344
|
+
|
|
345
|
+
&.top, &.bottom {
|
|
346
|
+
width: 100%;
|
|
347
|
+
border-top: thin solid #0000;
|
|
348
|
+
top: 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
&.left, &.right {
|
|
352
|
+
height: 100%;
|
|
353
|
+
border-left: thin solid #0000;
|
|
354
|
+
left: 0;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
&.right {
|
|
358
|
+
left: auto;
|
|
359
|
+
border-right: 1px solid var(--itf-table-border-color);
|
|
360
|
+
right: 0;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
&.bottom {
|
|
364
|
+
top: auto;
|
|
365
|
+
bottom: 0;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
308
368
|
}
|
|
@@ -36,6 +36,33 @@ export function parseHours (str, { hoursInDay } = { hoursInDay: 8 }) {
|
|
|
36
36
|
return isNegative * seconds;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
|
|
40
|
+
// https://stptrans.com/wp-content/uploads/2020/02/Working-with-currency-number-and-date-formats.pdf
|
|
41
|
+
export function formatMoney (val, symbol = '', digits = null) {
|
|
42
|
+
const format = ITFSettings.moneyDisplayFormat || '{symbol}{value}';
|
|
43
|
+
const thousandSeparator = ITFSettings.moneyThousandSeparator || ',';
|
|
44
|
+
const decimalSeparator = ITFSettings.moneyDecimalSeparator || '.';
|
|
45
|
+
|
|
46
|
+
if (Number.isNaN(val) || val === null) {
|
|
47
|
+
return '—';
|
|
48
|
+
}
|
|
49
|
+
let symbolStr = symbol?.currencySymbol ?? symbol?.symbol ?? symbol?.Symbol ?? '';
|
|
50
|
+
if (typeof symbol === 'string') {
|
|
51
|
+
symbolStr = symbol;
|
|
52
|
+
}
|
|
53
|
+
if (digits === null) {
|
|
54
|
+
digits = symbol.precision ?? symbol.Precision ?? 2;
|
|
55
|
+
}
|
|
56
|
+
const value = parseFloat(val.toString()).toFixed(digits)
|
|
57
|
+
.replace(/\d(?=(\d{3})+\.)/g, '$&' + thousandSeparator)
|
|
58
|
+
.replace(/\.(\d+)$/, decimalSeparator + '$1')
|
|
59
|
+
;
|
|
60
|
+
return format
|
|
61
|
+
.replace('{value}', value)
|
|
62
|
+
.replace('{symbol}', symbolStr)
|
|
63
|
+
.trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
39
66
|
export function formatDate (date, inputFormat = 'yyyy-MM-dd', toFormat) {
|
|
40
67
|
if (!date) {
|
|
41
68
|
return date;
|
|
@@ -89,7 +116,7 @@ export function firstLetters(name) {
|
|
|
89
116
|
export function formatHours (val, removeEmptyMinutes = false) {
|
|
90
117
|
let hours = Math.floor(Math.abs(val) / 60);
|
|
91
118
|
let minutes = Math.abs(val) - hours * 60;
|
|
92
|
-
if (isNaN(minutes)) {
|
|
119
|
+
if (Number.isNaN(minutes)) {
|
|
93
120
|
return '—';
|
|
94
121
|
}
|
|
95
122
|
minutes = Math.floor(minutes);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
parseHours
|
|
2
|
+
parseHours, formatMoney
|
|
3
3
|
} from './formatters';
|
|
4
|
+
import ITFSettings from "../ITFSettings";
|
|
4
5
|
|
|
5
6
|
describe('Formatters', () => {
|
|
6
7
|
const $t = (str) => str;
|
|
@@ -14,4 +15,20 @@ describe('Formatters', () => {
|
|
|
14
15
|
expect(parseHours('12h 10m 10s')).toEqual(12 * 60 * 60 + 10 * 60 + 10);
|
|
15
16
|
expect(parseHours('1d 12h 10m 10s')).toEqual(8 * 60 * 60 + 12 * 60 * 60 + 10 * 60 + 10);
|
|
16
17
|
});
|
|
18
|
+
|
|
19
|
+
test('formatMoney', () => {
|
|
20
|
+
ITFSettings.defaultLocale = 'uk_UA';
|
|
21
|
+
let currency = { Id: 1, Symbol: '#', IsCryptoCurrency: false, Code: 'TTT' };
|
|
22
|
+
expect(formatMoney(1, '$')).toEqual('1,00 $');
|
|
23
|
+
expect(formatMoney(-1, '$')).toEqual('-1,00 $');
|
|
24
|
+
expect(formatMoney(-1000000, currency)).toEqual('-1 000 000,00 #');
|
|
25
|
+
expect(formatMoney(NaN)).toEqual('—');
|
|
26
|
+
|
|
27
|
+
ITFSettings.defaultLocale = 'en_US';
|
|
28
|
+
currency = { Id: 1, Symbol: '#', IsCryptoCurrency: false, Code: 'TTT' };
|
|
29
|
+
expect(formatMoney(1, '$')).toEqual('$1.00');
|
|
30
|
+
expect(formatMoney(-1, '$')).toEqual('$-1.00');
|
|
31
|
+
expect(formatMoney(-1, currency)).toEqual('#-1.00');
|
|
32
|
+
expect(formatMoney(NaN)).toEqual('—');
|
|
33
|
+
});
|
|
17
34
|
});
|