bfg-common 1.3.132 → 1.3.134

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.
@@ -2218,5 +2218,6 @@
2218
2218
  "utilizedSpaceDesc": "Дыктуе мінімальны ўзровень спажыванай прасторы для кожнага сховішча дадзеных, які з'яўляецца парогам для дзеяння.",
2219
2219
  "minimumFreeSpaceDesc": "Дыктуе мінімальны ўзровень вольнай прасторы для кожнага сховішча дадзеных, які з'яўляецца парогам для дзеяння.",
2220
2220
  "dictatesMinimumIoLatency": "Задае мінімальную затрымку ўводу/вываду для кожнага сховішча даных, ніжэй за якую балансіроўка нагрузкі ўводу/вываду не ўлічваецца.",
2221
- "runtimeThresholdsGovern": "Парогавыя значэнні часу выканання вызначаюць, калі Storage DRS выконвае або рэкамендуе пераносы (на аснове абранага ўзроўню аўтаматызацыі)."
2221
+ "runtimeThresholdsGovern": "Парогавыя значэнні часу выканання вызначаюць, калі Storage DRS выконвае або рэкамендуе пераносы (на аснове абранага ўзроўню аўтаматызацыі).",
2222
+ "perDatastore": "на сховішча дадзеных"
2222
2223
  }
@@ -2222,5 +2222,6 @@
2222
2222
  "utilizedSpaceDesc": "Dictates the minimum level of consumed space for each datastore that is the threshold for action.",
2223
2223
  "minimumFreeSpaceDesc": "Dictates the minimum level of free space for each datastore that is the threshold for action.",
2224
2224
  "dictatesMinimumIoLatency": "Dictates the minimum I/O latency for each datastore below which I/O load balancing moves are not considered.",
2225
- "runtimeThresholdsGovern": "Runtime thresholds govern when Storage DRS performs or recommends migrations (based on the selected automation level)."
2225
+ "runtimeThresholdsGovern": "Runtime thresholds govern when Storage DRS performs or recommends migrations (based on the selected automation level).",
2226
+ "perDatastore": "per datastore"
2226
2227
  }
@@ -2222,5 +2222,6 @@
2222
2222
  "utilizedSpaceDesc": "Թելադրում է սպառված տարածքի նվազագույն մակարդակը յուրաքանչյուր տվյալների պահեստի համար, որը գործողության շեմն է:",
2223
2223
  "minimumFreeSpaceDesc": "Յուրաքանչյուր տվյալների պահեստի համար թելադրում է ազատ տարածության նվազագույն մակարդակը, որը գործողության շեմն է:",
2224
2224
  "dictatesMinimumIoLatency": "Թելադրում է նվազագույն I/O հետաձգումը յուրաքանչյուր տվյալների պահեստի համար, որից ցածր I/O բեռի հավասարակշռման շարժումները հաշվի չեն առնվում:",
2225
- "runtimeThresholdsGovern": "Գործարկման ժամանակի շեմերը կարգավորվում են, երբ Storage DRS-ը կատարում կամ առաջարկում է միգրացիաներ (ըստ ընտրված ավտոմատացման մակարդակի):"
2225
+ "runtimeThresholdsGovern": "Գործարկման ժամանակի շեմերը կարգավորվում են, երբ Storage DRS-ը կատարում կամ առաջարկում է միգրացիաներ (ըստ ընտրված ավտոմատացման մակարդակի):",
2226
+ "perDatastore": "մեկ տվյալների պահեստի համար"
2226
2227
  }
@@ -2221,5 +2221,6 @@
2221
2221
  "utilizedSpaceDesc": "Әрекет шегі болып табылатын әрбір деректер қоймасы үшін тұтынылатын кеңістіктің ең төменгі деңгейін белгілейді.",
2222
2222
  "minimumFreeSpaceDesc": "Әрекет шегі болып табылатын әрбір деректер қоймасы үшін бос кеңістіктің ең төменгі деңгейін белгілейді.",
2223
2223
  "dictatesMinimumIoLatency": "Әр деректер қоймасы үшін ең аз енгізу/шығару кідірісін белгілейді, одан төмен енгізу/шығару жүктемесін теңестіру қозғалыстары ескерілмейді.",
2224
- "runtimeThresholdsGovern": "Орындау уақытының шектері Storage DRS тасымалдауларды орындағанда немесе ұсынғанда (таңдалған автоматтандыру деңгейіне негізделген) басқарады."
2224
+ "runtimeThresholdsGovern": "Орындау уақытының шектері Storage DRS тасымалдауларды орындағанда немесе ұсынғанда (таңдалған автоматтандыру деңгейіне негізделген) басқарады.",
2225
+ "perDatastore": "деректер қоймасы үшін"
2225
2226
  }
@@ -2227,5 +2227,6 @@
2227
2227
  "utilizedSpaceDesc": "Определяет минимальный уровень потребляемого пространства для каждого хранилища данных, который является пороговым значением для действия.",
2228
2228
  "minimumFreeSpaceDesc": "Определяет минимальный уровень свободного места для каждого хранилища данных, который является пороговым значением для действия.",
2229
2229
  "dictatesMinimumIoLatency": "Определяет минимальную задержку ввода-вывода для каждого хранилища данных, ниже которой перемещения по балансировке нагрузки ввода-вывода не учитываются.",
2230
- "runtimeThresholdsGovern": "Пороги времени выполнения определяют, когда Storage DRS выполняет или рекомендует миграцию (в зависимости от выбранного уровня автоматизации)."
2230
+ "runtimeThresholdsGovern": "Пороги времени выполнения определяют, когда Storage DRS выполняет или рекомендует миграцию (в зависимости от выбранного уровня автоматизации).",
2231
+ "perDatastore": "на хранилище данных"
2231
2232
  }
@@ -2221,5 +2221,6 @@
2221
2221
  "utilizedSpaceDesc": "规定每个数据存储消耗的空间的最低级别,即操作的阈值。",
2222
2222
  "minimumFreeSpaceDesc": "规定每个数据存储的可用空间的最低级别,即操作的阈值。",
2223
2223
  "dictatesMinimumIoLatency": "规定每个数据存储的最小 I/O 延迟,低于该延迟时不考虑 I/O 负载平衡移动。",
2224
- "runtimeThresholdsGovern": "运行时阈值控制 Storage DRS 何时执行或建议迁移(基于所选的自动化级别)。"
2224
+ "runtimeThresholdsGovern": "运行时阈值控制 Storage DRS 何时执行或建议迁移(基于所选的自动化级别)。",
2225
+ "perDatastore": "每个数据存储"
2225
2226
  }
@@ -29,6 +29,22 @@
29
29
  </svg>
30
30
  </template>
31
31
  <template v-else-if="props.name === 'outline-port'">
32
+ <svg
33
+ xmlns="http://www.w3.org/2000/svg"
34
+ width="14"
35
+ height="14"
36
+ viewBox="-1 -1 14 14"
37
+ >
38
+ <g>
39
+ <path fill="#fff" d="M.5 11.5V.5h9v2h2v7h-2v2h-9z" />
40
+ <path
41
+ d="M9 1v2h2v6H9v2H1V1h8m1-1H0v12h10v-2h2V2h-2V0z"
42
+ fill="#36708c"
43
+ />
44
+ </g>
45
+ </svg>
46
+ </template>
47
+ <template v-else-if="props.name === 'outline-port-dark-mode'">
32
48
  <svg
33
49
  xmlns="http://www.w3.org/2000/svg"
34
50
  width="14"
@@ -117,7 +117,7 @@ const props = withDefaults(
117
117
  localization?: UI_I_Localization
118
118
  testId?: string
119
119
  wasCompleted: boolean
120
- height: string
120
+ height?: string
121
121
  }>(),
122
122
  {
123
123
  isLoading: false,
@@ -44,6 +44,7 @@
44
44
  :diagram-id="props.diagramData.id"
45
45
  :in-portlet="props.inPortlet"
46
46
  :is-visible-line="hasActiveAdapter"
47
+ :is-dark-mode="props.isDarkMode"
47
48
  @toggle-ports="onTogglePorts"
48
49
  @select-port="onSelectPort"
49
50
  @select-network="onSelectNetwork"
@@ -83,12 +83,12 @@ export interface UI_I_Sysx {
83
83
 
84
84
  export interface UI_I_OverrideValue {
85
85
  override: boolean
86
- value: string | boolean
86
+ value: string | number | boolean
87
87
  }
88
88
 
89
89
  export interface UI_I_NetworkSummaryPortletListItem {
90
90
  label: string
91
- value: string
91
+ value: string | number
92
92
  id: string
93
93
  initialValue: UI_I_OverrideValue
94
94
  }
@@ -211,39 +211,40 @@ export interface UI_I_ToggleDiagramAdaptersPayload {
211
211
  export interface UI_I_SecurityFields {
212
212
  promiscuousMode: {
213
213
  checked: boolean
214
- selected: string
214
+ selected: string | number
215
215
  }
216
216
  macAddressChanges: {
217
217
  checked: boolean
218
- selected: string
218
+ selected: string | number
219
219
  }
220
220
  forgedTransmits: {
221
221
  checked: boolean
222
- selected: string
222
+ selected: string | number
223
223
  }
224
224
  }
225
225
 
226
226
  export interface UI_I_TeamingFailoverFields {
227
227
  loadBalancing: {
228
- checked: string | number | boolean
229
- selected: string
228
+ checked: boolean
229
+ selected: string | number
230
230
  }
231
231
  networkFailureDetection: {
232
- checked: string | number | boolean
233
- selected: string
232
+ checked: boolean
233
+ selected: string | number
234
234
  }
235
235
  notifySwitches: {
236
- checked: string | number | boolean
237
- selected: string
236
+ checked: boolean
237
+ selected: string | number
238
238
  }
239
239
  failback: {
240
- checked: string | number | boolean
241
- selected: string
240
+ checked: boolean
241
+ selected: string | number
242
242
  }
243
243
  failoverOrder: {
244
- checked: string | number | boolean
244
+ checked: boolean
245
245
  }
246
246
  }
247
+
247
248
  export interface UI_I_TeamingFailoverWithAdaptersFields
248
249
  extends UI_I_TeamingFailoverFields {
249
250
  adapters: UI_I_AdapterStatus
@@ -252,7 +253,7 @@ export interface UI_I_TeamingFailoverWithAdaptersFields
252
253
  export interface UI_I_TrafficShapingFields {
253
254
  status: {
254
255
  checked: boolean
255
- selected: string
256
+ selected: string | number
256
257
  }
257
258
  average: number
258
259
  peak: number
@@ -417,7 +418,7 @@ export interface API_UI_I_SwitchAdapters {
417
418
  export interface UI_I_TeamingAndFailoverTemplate {
418
419
  key: string
419
420
  options: {
420
- value: string
421
+ value: string | number
421
422
  text: string
422
423
  }[]
423
424
  }
@@ -463,7 +464,7 @@ export interface UI_I_ModalTabs {
463
464
  export interface API_UI_I_Security {
464
465
  forged_transmits: UI_T_YNIOption
465
466
  mac_change: UI_T_YNIOption
466
- promiscuous_mode: UI_T_YNIOption
467
+ promiscuous: UI_T_YNIOption
467
468
  }
468
469
  export interface API_UI_I_Shaping {
469
470
  enabled: boolean
@@ -32,10 +32,16 @@
32
32
  :disabled="!fieldsValues.promiscuousMode.checked"
33
33
  name="selectName"
34
34
  >
35
- <option value="no" :label="localization.reject">
35
+ <option
36
+ :value="props.isSwitch ? 2 : 'no'"
37
+ :label="localization.reject"
38
+ >
36
39
  {{ localization.reject }}
37
40
  </option>
38
- <option value="yes" :label="localization.accept">
41
+ <option
42
+ :value="props.isSwitch ? 1 : 'yes'"
43
+ :label="localization.accept"
44
+ >
39
45
  {{ localization.accept }}
40
46
  </option>
41
47
  </select>
@@ -76,10 +82,16 @@
76
82
  :disabled="!fieldsValues.macAddressChanges.checked"
77
83
  name="selectName"
78
84
  >
79
- <option value="no" :label="localization.reject">
85
+ <option
86
+ :value="props.isSwitch ? 2 : 'no'"
87
+ :label="localization.reject"
88
+ >
80
89
  {{ localization.reject }}
81
90
  </option>
82
- <option value="yes" :label="localization.accept">
91
+ <option
92
+ :value="props.isSwitch ? 1 : 'yes'"
93
+ :label="localization.accept"
94
+ >
83
95
  {{ localization.accept }}
84
96
  </option>
85
97
  </select>
@@ -120,10 +132,16 @@
120
132
  :disabled="!fieldsValues.forgedTransmits.checked"
121
133
  name="selectName"
122
134
  >
123
- <option value="no" :label="localization.reject">
135
+ <option
136
+ :value="props.isSwitch ? 2 : 'no'"
137
+ :label="localization.reject"
138
+ >
124
139
  {{ localization.reject }}
125
140
  </option>
126
- <option value="yes" :label="localization.accept">
141
+ <option
142
+ :value="props.isSwitch ? 1 : 'yes'"
143
+ :label="localization.accept"
144
+ >
127
145
  {{ localization.accept }}
128
146
  </option>
129
147
  </select>
@@ -145,7 +163,10 @@ import {
145
163
  UI_I_ModalsInitialData,
146
164
  UI_I_SecurityFields,
147
165
  } from '~/components/common/diagramMain/lib/models/interfaces'
148
- import { securityFieldsInitialFunc } from '~/components/common/diagramMain/modals/lib/config'
166
+ import {
167
+ securityFieldsInitialFunc,
168
+ securityNetworkFieldsInitialFunc,
169
+ } from '~/components/common/diagramMain/modals/lib/config'
149
170
 
150
171
  // Props from up
151
172
  const props = withDefaults(
@@ -162,7 +183,9 @@ const props = withDefaults(
162
183
  const localization = computed<UI_I_Localization>(() => useLocal())
163
184
 
164
185
  const fieldsValues = ref<UI_I_SecurityFields>(
165
- securityFieldsInitialFunc(props.isSwitch, props.initialData)
186
+ props.isSwitch
187
+ ? securityFieldsInitialFunc(props.isSwitch, props.initialData)
188
+ : securityNetworkFieldsInitialFunc(props.isSwitch, props.initialData)
166
189
  )
167
190
 
168
191
  const emits = defineEmits<{
@@ -103,7 +103,9 @@ import {
103
103
  } from '~/components/common/diagramMain/lib/models/interfaces'
104
104
  import {
105
105
  teamingFailoverFieldsInitialFunc,
106
+ teamingFailoverNetworkFieldsInitialFunc,
106
107
  teamingAndFailoverTemplateMakerFunc,
108
+ teamingAndFailoverNetworkTemplateMakerFunc,
107
109
  } from '~/components/common/diagramMain/modals/lib/config'
108
110
 
109
111
  // Props from up
@@ -127,11 +129,16 @@ const localization = computed<UI_I_Localization>(() => useLocal())
127
129
 
128
130
  // Making fields template
129
131
  const teamingAndFailoverTemplate = computed<UI_I_TeamingAndFailoverTemplate[]>(
130
- () => teamingAndFailoverTemplateMakerFunc(localization.value)
132
+ () =>
133
+ props.isSwitch
134
+ ? teamingAndFailoverTemplateMakerFunc(localization.value)
135
+ : teamingAndFailoverNetworkTemplateMakerFunc(localization.value)
131
136
  )
132
137
  // Temporary data for this component
133
138
  const fieldsValues = ref<UI_I_TeamingFailoverFields>(
134
- teamingFailoverFieldsInitialFunc(props.isSwitch, props.initialData)
139
+ props.isSwitch
140
+ ? teamingFailoverFieldsInitialFunc(props.isSwitch, props.initialData)
141
+ : teamingFailoverNetworkFieldsInitialFunc(props.isSwitch, props.initialData)
135
142
  )
136
143
 
137
144
  const emits = defineEmits<{
@@ -30,7 +30,7 @@
30
30
  {{ localization.override }}
31
31
  </label>
32
32
  </div>
33
- <div class="flex-property-value-group">
33
+ <div v-if="!props.isSwitch" class="flex-property-value-group">
34
34
  <div class="select">
35
35
  <select
36
36
  id="traffic-shaping-select"
@@ -47,6 +47,23 @@
47
47
  </select>
48
48
  </div>
49
49
  </div>
50
+ <div v-else class="flex-property-value-group">
51
+ <div class="select">
52
+ <select
53
+ id="traffic-shaping-select"
54
+ v-model.number="fieldsValues.status.selected"
55
+ :disabled="!fieldsValues.status.checked"
56
+ name="selectName"
57
+ >
58
+ <option :label="localization.enabled" value="1">
59
+ {{ localization.enabled }}
60
+ </option>
61
+ <option :label="localization.disabled" value="0">
62
+ {{ localization.disabled }}
63
+ </option>
64
+ </select>
65
+ </div>
66
+ </div>
50
67
  </div>
51
68
  </div>
52
69
  </div>
@@ -76,7 +93,10 @@
76
93
  {{ localization.override }}
77
94
  </label>
78
95
  </div>
79
- <div class="property-value-group tooltip-field-container">
96
+ <div
97
+ v-if="!props.isSwitch"
98
+ class="property-value-group tooltip-field-container"
99
+ >
80
100
  <atoms-tooltip-error
81
101
  :has-error="!!props.errorMessages.average"
82
102
  >
@@ -107,6 +127,40 @@
107
127
  </template>
108
128
  </atoms-tooltip-error>
109
129
  </div>
130
+ <div
131
+ v-else
132
+ class="property-value-group tooltip-field-container"
133
+ >
134
+ <atoms-tooltip-error
135
+ :has-error="!!props.errorMessages.average"
136
+ >
137
+ <template #elem>
138
+ <input
139
+ id="average"
140
+ v-model="fieldsValues.average"
141
+ type="number"
142
+ :disabled="
143
+ !fieldsValues.status.checked ||
144
+ fieldsValues.status.selected === 0
145
+ "
146
+ name="average"
147
+ :class="[
148
+ 'tooltip-field',
149
+ {
150
+ 'danger-not-valid':
151
+ fieldsValues.status.checked &&
152
+ fieldsValues.status.selected !== 0 &&
153
+ props.errorMessages.average,
154
+ },
155
+ ]"
156
+ @click.stop
157
+ />
158
+ </template>
159
+ <template #content>
160
+ {{ props.errorMessages.average }}
161
+ </template>
162
+ </atoms-tooltip-error>
163
+ </div>
110
164
  </div>
111
165
  </div>
112
166
  </div>
@@ -136,7 +190,10 @@
136
190
  {{ localization.override }}
137
191
  </label>
138
192
  </div>
139
- <div class="property-value-group tooltip-field-container">
193
+ <div
194
+ v-if="!props.isSwitch"
195
+ class="property-value-group tooltip-field-container"
196
+ >
140
197
  <atoms-tooltip-error
141
198
  :has-error="!!props.errorMessages.peak"
142
199
  >
@@ -167,6 +224,40 @@
167
224
  </template>
168
225
  </atoms-tooltip-error>
169
226
  </div>
227
+ <div
228
+ v-else
229
+ class="property-value-group tooltip-field-container"
230
+ >
231
+ <atoms-tooltip-error
232
+ :has-error="!!props.errorMessages.peak"
233
+ >
234
+ <template #elem>
235
+ <input
236
+ id="peak"
237
+ v-model="fieldsValues.peak"
238
+ type="number"
239
+ :disabled="
240
+ !fieldsValues.status.checked ||
241
+ fieldsValues.status.selected === 0
242
+ "
243
+ name="peak"
244
+ :class="[
245
+ 'tooltip-field',
246
+ {
247
+ 'danger-not-valid':
248
+ fieldsValues.status.checked &&
249
+ fieldsValues.status.selected !== 0 &&
250
+ props.errorMessages.peak,
251
+ },
252
+ ]"
253
+ @click.stop
254
+ />
255
+ </template>
256
+ <template #content>
257
+ {{ props.errorMessages.peak }}
258
+ </template>
259
+ </atoms-tooltip-error>
260
+ </div>
170
261
  </div>
171
262
  </div>
172
263
  </div>
@@ -196,7 +287,10 @@
196
287
  {{ localization.override }}
197
288
  </label>
198
289
  </div>
199
- <div class="property-value-group tooltip-field-container">
290
+ <div
291
+ v-if="!props.isSwitch"
292
+ class="property-value-group tooltip-field-container"
293
+ >
200
294
  <atoms-tooltip-error
201
295
  :has-error="!!props.errorMessages.burstSize"
202
296
  >
@@ -227,6 +321,40 @@
227
321
  </template>
228
322
  </atoms-tooltip-error>
229
323
  </div>
324
+ <div
325
+ v-else
326
+ class="property-value-group tooltip-field-container"
327
+ >
328
+ <atoms-tooltip-error
329
+ :has-error="!!props.errorMessages.burstSize"
330
+ >
331
+ <template #elem>
332
+ <input
333
+ id="burst-size"
334
+ v-model="fieldsValues.burstSize"
335
+ type="number"
336
+ :disabled="
337
+ !fieldsValues.status.checked ||
338
+ fieldsValues.status.selected === 0
339
+ "
340
+ name="burst-size"
341
+ :class="[
342
+ 'tooltip-field',
343
+ {
344
+ 'danger-not-valid':
345
+ fieldsValues.status.checked &&
346
+ fieldsValues.status.selected !== 0 &&
347
+ props.errorMessages.burstSize,
348
+ },
349
+ ]"
350
+ @click.stop
351
+ />
352
+ </template>
353
+ <template #content>
354
+ {{ props.errorMessages.burstSize }}
355
+ </template>
356
+ </atoms-tooltip-error>
357
+ </div>
230
358
  </div>
231
359
  </div>
232
360
  </div>
@@ -246,7 +374,10 @@ import {
246
374
  } from '~/components/common/diagramMain/lib/models/interfaces'
247
375
  import { UI_T_TrafficShapingFieldName } from '~/components/common/diagramMain/lib/models/types'
248
376
  import { validationMessagesArrayFunc } from '~/components/common/diagramMain/modals/lib/utils'
249
- import { trafficShapingFieldsInitialFunc } from '~/components/common/diagramMain/modals/lib/config'
377
+ import {
378
+ trafficShapingFieldsInitialFunc,
379
+ trafficShapingNetworkFieldsInitialFunc,
380
+ } from '~/components/common/diagramMain/modals/lib/config'
250
381
 
251
382
  // Props from up
252
383
  const props = withDefaults(
@@ -279,11 +410,9 @@ const isShowErrorMessage = computed<boolean>(
279
410
  )
280
411
 
281
412
  const fieldsValues = ref<UI_I_TrafficShapingFields>(
282
- trafficShapingFieldsInitialFunc(props.isSwitch, props.initialData, {
283
- average_bw: props.initialData?.average_bw || 0,
284
- peak_bw: props.initialData?.peak_bw || 0,
285
- burst_size: props.initialData?.burst_size || 0,
286
- })
413
+ props.isSwitch
414
+ ? trafficShapingFieldsInitialFunc(props.isSwitch, props.initialData)
415
+ : trafficShapingNetworkFieldsInitialFunc(props.isSwitch, props.initialData)
287
416
  )
288
417
 
289
418
  // Validation
@@ -4,9 +4,7 @@ import * as adapterModalConfig from './adapterModal'
4
4
  import * as vCenterModalConfig from './vCenterModal'
5
5
  import * as initialConfig from './initial'
6
6
  import * as switchModalConfig from './switchModal'
7
- import * as validationData from './validation'
8
7
  import * as vmKernelAdapterData from './vmKernelAdapter'
9
- // import * as temporaryData from './temporaryData'
10
8
  import * as diagramConfig from './diagramConfig'
11
9
 
12
10
  export const {
@@ -18,6 +16,7 @@ export const {
18
16
  } = portModalConfig
19
17
  export const {
20
18
  teamingAndFailoverTemplateMakerFunc,
19
+ teamingAndFailoverNetworkTemplateMakerFunc,
21
20
  networkViewSettingsModalTabsFunc,
22
21
  networkEditSettingsTabsFunc,
23
22
  networkViewSettingsFunc,
@@ -32,8 +31,11 @@ export const { vCenterViewSettingsFunc, vCenterPopupFieldsFunc } =
32
31
  vCenterModalConfig
33
32
  export const {
34
33
  trafficShapingFieldsInitialFunc,
34
+ trafficShapingNetworkFieldsInitialFunc,
35
35
  securityFieldsInitialFunc,
36
+ securityNetworkFieldsInitialFunc,
36
37
  teamingFailoverFieldsInitialFunc,
38
+ teamingFailoverNetworkFieldsInitialFunc,
37
39
  ipvFourSettingsFields,
38
40
  } = initialConfig
39
41
  export const {