dashboard-shell-shell 3.0.5-logtest.3 → 3.0.5-natTest.1
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.
|
@@ -6477,6 +6477,7 @@ tableHeaders:
|
|
|
6477
6477
|
apikey: API Key
|
|
6478
6478
|
available: Available
|
|
6479
6479
|
attachedVM: Attached VM
|
|
6480
|
+
vpc: vpc
|
|
6480
6481
|
|
|
6481
6482
|
authRoles:
|
|
6482
6483
|
globalDefault: New User Default
|
|
@@ -7652,6 +7653,8 @@ typeDescription:
|
|
|
7652
7653
|
harvesterhci.io.logging.clusteroutput: 定义集群范围的日志输出目标,例如 Elasticsearch、Loki、S3、Kafka 等。可被多个集群日志配置引用,用于集中存储与分析集群级日志数据。
|
|
7653
7654
|
harvesterhci.io.logging.flow: 用于配置资源组(命名空间)内的日志采集与流转规则,仅作用于当前资源组内的日志,并将日志转发至对应的资源组日志外发目标,便于分组级的日志管理。
|
|
7654
7655
|
harvesterhci.io.logging.output: 定义资源组级别的日志输出目标,仅能被同一资源组下的日志配置引用,用于将该资源组内的日志发送至指定的存储或分析系统。
|
|
7656
|
+
kubeovn.io.ovneip: EIP(Elastic IP,弹性公网 IP) 是一种可独立分配、绑定和管理的公网 IPv4 地址资源,使云上实例能够与公网进行双向通信。EIP 具备可移植、可复用和高可用等特性,为云中应用提供灵活的公网访问能力。
|
|
7657
|
+
kubeovn.io.nat: NAT(Network Address Translation,网络地址转换) 是一种让私有子网内的云资源在不暴露自身公网 IP 的情况下访问互联网的网络服务。通过 NAT,实例可以共享统一的公网出口,实现安全、简化的外网访问能力。
|
|
7655
7658
|
typeLabel:
|
|
7656
7659
|
management.cattle.io.oidcclient: |-
|
|
7657
7660
|
{count, plural,
|
|
@@ -5543,6 +5543,7 @@ tableHeaders:
|
|
|
5543
5543
|
apikey: API 密钥
|
|
5544
5544
|
available: 可用
|
|
5545
5545
|
attachedVM: 挂载的虚拟机
|
|
5546
|
+
vpc: vpc
|
|
5546
5547
|
|
|
5547
5548
|
authRoles:
|
|
5548
5549
|
globalDefault: 新用户的默认角色
|
|
@@ -6661,6 +6662,8 @@ typeDescription:
|
|
|
6661
6662
|
harvesterhci.io.logging.clusteroutput: 定义集群范围的日志输出目标,例如 Elasticsearch、Loki、S3、Kafka 等。可被多个集群日志配置引用,用于集中存储与分析集群级日志数据。
|
|
6662
6663
|
harvesterhci.io.logging.flow: 用于配置资源组(命名空间)内的日志采集与流转规则,仅作用于当前资源组内的日志,并将日志转发至对应的资源组日志外发目标,便于分组级的日志管理。
|
|
6663
6664
|
harvesterhci.io.logging.output: 定义资源组级别的日志输出目标,仅能被同一资源组下的日志配置引用,用于将该资源组内的日志发送至指定的存储或分析系统。
|
|
6665
|
+
kubeovn.io.ovneip: EIP(Elastic IP,弹性公网 IP) 是一种可独立分配、绑定和管理的公网 IPv4 地址资源,使云上实例能够与公网进行双向通信。EIP 具备可移植、可复用和高可用等特性,为云中应用提供灵活的公网访问能力。
|
|
6666
|
+
kubeovn.io.nat: NAT(Network Address Translation,网络地址转换) 是一种让私有子网内的云资源在不暴露自身公网 IP 的情况下访问互联网的网络服务。通过 NAT,实例可以共享统一的公网出口,实现安全、简化的外网访问能力。
|
|
6664
6667
|
typeLabel:
|
|
6665
6668
|
management.cattle.io.project: |-
|
|
6666
6669
|
{count, plural,
|
|
@@ -33,6 +33,10 @@ export default {
|
|
|
33
33
|
TabTitle
|
|
34
34
|
},
|
|
35
35
|
props: {
|
|
36
|
+
actionsPositioning: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: '-48px',
|
|
39
|
+
},
|
|
36
40
|
resource: {
|
|
37
41
|
type: String,
|
|
38
42
|
required: true,
|
|
@@ -322,6 +326,7 @@ export default {
|
|
|
322
326
|
<div
|
|
323
327
|
ref="actionsContainer"
|
|
324
328
|
v-if="!(tabList.includes(_typeDisplay))"
|
|
329
|
+
:style="{ bottom: actionsPositioning ? actionsPositioning : '-48px' }"
|
|
325
330
|
class="actions-container actions-positioning"
|
|
326
331
|
style="min-height: 32px;align-self: flex-end;"
|
|
327
332
|
>
|
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { KUBERNETES, PROJECT } from '@shell/config/labels-annotations';
|
|
3
|
+
import { FLEET, NAMESPACE, MANAGEMENT, HELM } from '@shell/config/types';
|
|
4
|
+
import ButtonGroup from '@shell/components/ButtonGroup';
|
|
5
|
+
// import { BadgeState } from '@components/BadgeState';
|
|
6
|
+
import DotState from '@shell/components/DotState.vue';
|
|
7
|
+
import { Banner } from '@components/Banner';
|
|
8
|
+
import { get } from '@shell/utils/object';
|
|
9
|
+
import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
|
|
10
|
+
import { HIDE_SENSITIVE } from '@shell/store/prefs';
|
|
11
|
+
import {
|
|
12
|
+
AS, _DETAIL, _CONFIG, _YAML, MODE, _CREATE, _EDIT, _VIEW, _UNFLAG, _GRAPH
|
|
13
|
+
} from '@shell/config/query-params';
|
|
14
|
+
import { ExtensionPoint, PanelLocation } from '@shell/core/types';
|
|
15
|
+
import ExtensionPanel from '@shell/components/ExtensionPanel';
|
|
16
|
+
import TabTitle from '@shell/components/TabTitle';
|
|
17
|
+
import ActionMenu from '@shell/components/ActionMenuShell.vue';
|
|
18
|
+
import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
|
|
19
|
+
import { useStore } from 'vuex';
|
|
20
|
+
|
|
21
|
+
// i18n-uses resourceDetail.header.*
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Resource Detail Masthead component.
|
|
25
|
+
*
|
|
26
|
+
* ToDo: this component seem to be picking up a lot of logic from special cases, could be simplified down to parameters and then customized per use-case via wrapper component
|
|
27
|
+
*/
|
|
28
|
+
export default {
|
|
29
|
+
|
|
30
|
+
name: 'MastheadResourceDetail',
|
|
31
|
+
|
|
32
|
+
components: {
|
|
33
|
+
// BadgeState,
|
|
34
|
+
DotState,
|
|
35
|
+
Banner,
|
|
36
|
+
ButtonGroup,
|
|
37
|
+
ExtensionPanel,
|
|
38
|
+
TabTitle,
|
|
39
|
+
ActionMenu,
|
|
40
|
+
},
|
|
41
|
+
props: {
|
|
42
|
+
value: {
|
|
43
|
+
type: Object,
|
|
44
|
+
default: () => {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
isManuallyHide: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: true
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
mode: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: 'create'
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
realMode: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: 'create'
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
as: {
|
|
65
|
+
type: String,
|
|
66
|
+
default: _YAML,
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
hasGraph: {
|
|
70
|
+
type: Boolean,
|
|
71
|
+
default: false
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
hasDetail: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: false
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
hasEdit: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: false
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
storeOverride: {
|
|
85
|
+
type: String,
|
|
86
|
+
default: null,
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
resource: {
|
|
90
|
+
type: String,
|
|
91
|
+
default: null,
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
resourceSubtype: {
|
|
95
|
+
type: String,
|
|
96
|
+
default: null,
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
parentRouteOverride: {
|
|
100
|
+
type: String,
|
|
101
|
+
default: null,
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
canViewYaml: {
|
|
105
|
+
type: Boolean,
|
|
106
|
+
default: false,
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
setup() {
|
|
111
|
+
const store = useStore();
|
|
112
|
+
const { featureDropdownMenu } = useRuntimeFlag(store);
|
|
113
|
+
|
|
114
|
+
return { featureDropdownMenu };
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
data() {
|
|
118
|
+
return {
|
|
119
|
+
DETAIL_VIEW: _DETAIL,
|
|
120
|
+
extensionType: ExtensionPoint.PANEL,
|
|
121
|
+
extensionLocation: PanelLocation.DETAILS_MASTHEAD,
|
|
122
|
+
Svg: require('~shell/assets/images/API.svg')
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
computed: {
|
|
127
|
+
dev() {
|
|
128
|
+
return this.$store.getters['prefs/dev'];
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
schema() {
|
|
132
|
+
const inStore = this.storeOverride || this.$store.getters['currentStore'](this.resource);
|
|
133
|
+
|
|
134
|
+
return this.$store.getters[`${ inStore }/schemaFor`]( this.resource );
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
isView() {
|
|
138
|
+
return this.mode === _VIEW;
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
isEdit() {
|
|
142
|
+
return this.mode === _EDIT;
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
isCreate() {
|
|
146
|
+
return this.mode === _CREATE;
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
isNamespace() {
|
|
150
|
+
return this.schema?.id === NAMESPACE;
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
isProject() {
|
|
154
|
+
return this.schema?.id === MANAGEMENT.PROJECT;
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
isProjectHelmChart() {
|
|
158
|
+
return this.schema?.id === HELM.PROJECTHELMCHART;
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
hasMultipleNamespaces() {
|
|
162
|
+
return !!this.value.namespaces;
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
namespace() {
|
|
166
|
+
if (this.value?.metadata?.namespace) {
|
|
167
|
+
return this.value?.metadata?.namespace;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return null;
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
detailsAction() {
|
|
174
|
+
return this.value?.detailsAction;
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
shouldHifenize() {
|
|
178
|
+
return (this.mode === 'view' || this.mode === 'edit') && this.resourceSubtype?.length && this.value?.nameDisplay?.length;
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
namespaceLocation() {
|
|
182
|
+
if (!this.isNamespace) {
|
|
183
|
+
return this.value.namespaceLocation || {
|
|
184
|
+
name: 'c-cluster-product-resource-id',
|
|
185
|
+
params: {
|
|
186
|
+
cluster: this.$route.params.cluster,
|
|
187
|
+
product: this.$store.getters['productId'],
|
|
188
|
+
resource: NAMESPACE,
|
|
189
|
+
id: this.$route.params.namespace
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return null;
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
isWorkspace() {
|
|
198
|
+
return this.$store.getters['productId'] === FLEET_NAME && !!this.value?.metadata?.namespace;
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
workspaceLocation() {
|
|
202
|
+
return {
|
|
203
|
+
name: 'c-cluster-product-resource-id',
|
|
204
|
+
params: {
|
|
205
|
+
cluster: this.$route.params.cluster,
|
|
206
|
+
product: this.$store.getters['productId'],
|
|
207
|
+
resource: FLEET.WORKSPACE,
|
|
208
|
+
id: this.$route.params.namespace
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
project() {
|
|
214
|
+
if (this.isNamespace) {
|
|
215
|
+
const cluster = this.$store.getters['currentCluster'];
|
|
216
|
+
|
|
217
|
+
if (cluster) {
|
|
218
|
+
const id = (this.value?.metadata?.labels || {})[PROJECT];
|
|
219
|
+
|
|
220
|
+
return this.$store.getters['management/byId'](MANAGEMENT.PROJECT, `${ cluster.id }/${ id }`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return null;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
banner() {
|
|
228
|
+
if (this.value?.stateObj?.error) {
|
|
229
|
+
const defaultErrorMessage = this.t('resourceDetail.masthead.defaultBannerMessage.error', undefined, true);
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
color: 'error',
|
|
233
|
+
message: this.value.stateObj.message || defaultErrorMessage
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (this.value?.spec?.paused) {
|
|
238
|
+
return {
|
|
239
|
+
color: 'info',
|
|
240
|
+
message: this.t('asyncButton.pause.description')
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (this.value?.stateObj?.transitioning) {
|
|
245
|
+
const defaultTransitioningMessage = this.t('resourceDetail.masthead.defaultBannerMessage.transitioning', undefined, true);
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
color: 'info',
|
|
249
|
+
message: this.value.stateObj.message || defaultTransitioningMessage
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return null;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
parent() {
|
|
257
|
+
let displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
|
|
258
|
+
const product = this.$store.getters['currentProduct'].name;
|
|
259
|
+
|
|
260
|
+
const defaultLocation = {
|
|
261
|
+
name: 'c-cluster-product-resource',
|
|
262
|
+
params: {
|
|
263
|
+
resource: this.resource,
|
|
264
|
+
product,
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const location = this.value?.parentLocationOverride || defaultLocation;
|
|
269
|
+
|
|
270
|
+
if (this.parentRouteOverride) {
|
|
271
|
+
location.name = this.parentRouteOverride;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const typeOptions = this.$store.getters[`type-map/optionsFor`]( this.resource );
|
|
275
|
+
|
|
276
|
+
// 转换为中文
|
|
277
|
+
const displayName_zh_hans = {
|
|
278
|
+
'GlobalRole': '全局角色',
|
|
279
|
+
'RoleTemplate': '集群角色',
|
|
280
|
+
}
|
|
281
|
+
if (displayName_zh_hans[displayName]) {
|
|
282
|
+
displayName = displayName_zh_hans[displayName]
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (displayName == '集群角色' && (this.$route.query?.roleContext == 'NAMESPACE' || location.hash == '#NAMESPACE')) {
|
|
286
|
+
displayName = '项目或资源组角色'
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const out = {
|
|
290
|
+
displayName, location, ...typeOptions
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
return out;
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
hideSensitiveData() {
|
|
297
|
+
return this.$store.getters['prefs/get'](HIDE_SENSITIVE);
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
sensitiveOptions() {
|
|
301
|
+
return [
|
|
302
|
+
{
|
|
303
|
+
tooltipKey: 'resourceDetail.masthead.sensitive.hide',
|
|
304
|
+
icon: 'icon-hide',
|
|
305
|
+
value: true,
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
tooltipKey: 'resourceDetail.masthead.sensitive.show',
|
|
309
|
+
icon: 'icon-show',
|
|
310
|
+
value: false
|
|
311
|
+
}
|
|
312
|
+
];
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
viewOptions() {
|
|
316
|
+
const out = [];
|
|
317
|
+
|
|
318
|
+
if ( this.hasDetail ) {
|
|
319
|
+
out.push({
|
|
320
|
+
labelKey: 'resourceDetail.masthead.detail',
|
|
321
|
+
value: _DETAIL,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if ( this.hasEdit && this.parent?.showConfigView !== false) {
|
|
326
|
+
out.push({
|
|
327
|
+
labelKey: 'resourceDetail.masthead.config',
|
|
328
|
+
value: _CONFIG,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if ( this.hasGraph ) {
|
|
333
|
+
out.push({
|
|
334
|
+
labelKey: 'resourceDetail.masthead.graph',
|
|
335
|
+
value: _GRAPH,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// if ( this.canViewYaml ) {
|
|
340
|
+
// out.push({
|
|
341
|
+
// labelKey: 'resourceDetail.masthead.yaml',
|
|
342
|
+
// value: _YAML,
|
|
343
|
+
// });
|
|
344
|
+
// }
|
|
345
|
+
|
|
346
|
+
if ( out.length < 2 ) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return out;
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
currentView: {
|
|
354
|
+
get() {
|
|
355
|
+
return this.as;
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
set(val) {
|
|
359
|
+
switch ( val ) {
|
|
360
|
+
case _DETAIL:
|
|
361
|
+
this.$router.applyQuery({
|
|
362
|
+
[MODE]: _UNFLAG,
|
|
363
|
+
[AS]: _UNFLAG,
|
|
364
|
+
});
|
|
365
|
+
break;
|
|
366
|
+
case _CONFIG:
|
|
367
|
+
this.$router.applyQuery({
|
|
368
|
+
[MODE]: _UNFLAG,
|
|
369
|
+
[AS]: _CONFIG,
|
|
370
|
+
});
|
|
371
|
+
break;
|
|
372
|
+
case _GRAPH:
|
|
373
|
+
this.$router.applyQuery({
|
|
374
|
+
[MODE]: _UNFLAG,
|
|
375
|
+
[AS]: _GRAPH,
|
|
376
|
+
});
|
|
377
|
+
break;
|
|
378
|
+
case _YAML:
|
|
379
|
+
this.$router.applyQuery({
|
|
380
|
+
[MODE]: _UNFLAG,
|
|
381
|
+
[AS]: _YAML,
|
|
382
|
+
});
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
|
|
388
|
+
showSensitiveToggle() {
|
|
389
|
+
return !!this.value.hasSensitiveData && this.mode === _VIEW && this.as !== _YAML;
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
managedWarning() {
|
|
393
|
+
const { value } = this;
|
|
394
|
+
const labels = value?.metadata?.labels || {};
|
|
395
|
+
|
|
396
|
+
const managedBy = labels[KUBERNETES.MANAGED_BY] || '';
|
|
397
|
+
const appName = labels[KUBERNETES.MANAGED_NAME] || labels[KUBERNETES.INSTANCE] || '';
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
show: this.mode === _EDIT && !!managedBy,
|
|
401
|
+
type: value?.kind || '',
|
|
402
|
+
hasName: appName ? 'yes' : 'no',
|
|
403
|
+
appName,
|
|
404
|
+
managedBy,
|
|
405
|
+
};
|
|
406
|
+
},
|
|
407
|
+
|
|
408
|
+
displayName() {
|
|
409
|
+
let displayName = this.value.nameDisplay;
|
|
410
|
+
|
|
411
|
+
if (this.isProjectHelmChart) {
|
|
412
|
+
displayName = this.value.projectDisplayName;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return this.shouldHifenize ? ` - ${ displayName }` : displayName;
|
|
416
|
+
},
|
|
417
|
+
|
|
418
|
+
demoDisplay() {
|
|
419
|
+
const product = this.$store.getters['productId'];
|
|
420
|
+
|
|
421
|
+
const resources = this.location?.params?.resource || this.$route.params?.resource || ''
|
|
422
|
+
|
|
423
|
+
const productId = this.$store.getters['type-map/groupForBasicType'](this.$store.getters['productId'], resources);
|
|
424
|
+
|
|
425
|
+
if (productId === undefined) {
|
|
426
|
+
return '';
|
|
427
|
+
}
|
|
428
|
+
const parts = productId?.split('::') || [];
|
|
429
|
+
const newString = 'root';
|
|
430
|
+
|
|
431
|
+
if (!parts?.includes(newString)) {
|
|
432
|
+
parts.unshift(newString); // 将字符串添加到数组第一位
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const partsEn = parts.map((item) => {
|
|
436
|
+
return this.$store.getters['i18n/t'](`typeLabel."${ item.toLowerCase() }"`);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
return partsEn;
|
|
440
|
+
},
|
|
441
|
+
menuIcon() {
|
|
442
|
+
const product = this.$store.getters['productId'];
|
|
443
|
+
|
|
444
|
+
const resources = this.location?.params?.resource || this.$route.params?.resource || ''
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
return this.$store.getters['type-map/groupsForVirTypes'](product, resources) || 'default menuIcon';
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
location() {
|
|
451
|
+
const { parent } = this;
|
|
452
|
+
|
|
453
|
+
return parent?.location;
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
hideNamespaceLocation() {
|
|
457
|
+
return this.$store.getters['currentProduct'].hideNamespaceLocation || this.value.namespaceLocation === null;
|
|
458
|
+
},
|
|
459
|
+
|
|
460
|
+
resourceExternalLink() {
|
|
461
|
+
return this.value.resourceExternalLink;
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
methods: {
|
|
466
|
+
get,
|
|
467
|
+
|
|
468
|
+
showActions() {
|
|
469
|
+
this.$store.commit('action-menu/show', {
|
|
470
|
+
resources: this.value,
|
|
471
|
+
elem: this.$refs.actions,
|
|
472
|
+
});
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
toggleSensitiveData(e) {
|
|
476
|
+
this.$store.dispatch('prefs/set', { key: HIDE_SENSITIVE, value: !!e });
|
|
477
|
+
},
|
|
478
|
+
|
|
479
|
+
invokeDetailsAction() {
|
|
480
|
+
const action = this.detailsAction;
|
|
481
|
+
|
|
482
|
+
if (action) {
|
|
483
|
+
const fn = this.value[action.action];
|
|
484
|
+
|
|
485
|
+
if (fn) {
|
|
486
|
+
fn.apply(this.value, []);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
</script>
|
|
493
|
+
|
|
494
|
+
<template>
|
|
495
|
+
<div class="actions">
|
|
496
|
+
<button
|
|
497
|
+
v-if="detailsAction && currentView === DETAIL_VIEW && isView"
|
|
498
|
+
type="button"
|
|
499
|
+
class="btn role-primary actions mr-10"
|
|
500
|
+
:disabled="!detailsAction.enabled"
|
|
501
|
+
@click="invokeDetailsAction"
|
|
502
|
+
>
|
|
503
|
+
{{ detailsAction.label }}
|
|
504
|
+
</button>
|
|
505
|
+
<ButtonGroup
|
|
506
|
+
v-if="showSensitiveToggle"
|
|
507
|
+
:value="!!hideSensitiveData"
|
|
508
|
+
icon-size="lg"
|
|
509
|
+
:options="sensitiveOptions"
|
|
510
|
+
class="mr-10"
|
|
511
|
+
@update:value="toggleSensitiveData"
|
|
512
|
+
/>
|
|
513
|
+
<ButtonGroup
|
|
514
|
+
v-if="viewOptions && isView"
|
|
515
|
+
v-model:value="currentView"
|
|
516
|
+
:options="viewOptions"
|
|
517
|
+
class="mr-10"
|
|
518
|
+
/>
|
|
519
|
+
<template v-if="featureDropdownMenu">
|
|
520
|
+
<ActionMenu
|
|
521
|
+
v-if="isView"
|
|
522
|
+
button-role="multiAction"
|
|
523
|
+
button-size="compact"
|
|
524
|
+
:resource="value"
|
|
525
|
+
data-testid="masthead-action-menu"
|
|
526
|
+
/>
|
|
527
|
+
</template>
|
|
528
|
+
<template v-else>
|
|
529
|
+
<button
|
|
530
|
+
v-if="isView"
|
|
531
|
+
ref="actions"
|
|
532
|
+
data-testid="masthead-action-menu"
|
|
533
|
+
aria-haspopup="true"
|
|
534
|
+
type="button"
|
|
535
|
+
class="btn role-multi-action actions"
|
|
536
|
+
@click="showActions"
|
|
537
|
+
>
|
|
538
|
+
<i class="icon icon-actions" />
|
|
539
|
+
</button>
|
|
540
|
+
</template>
|
|
541
|
+
</div>
|
|
542
|
+
</template>
|
|
543
|
+
|
|
544
|
+
<style lang='scss' scoped>
|
|
545
|
+
.masthead {
|
|
546
|
+
padding-bottom: 10px;
|
|
547
|
+
/* border-bottom: 1px solid var(--border); */
|
|
548
|
+
margin-bottom: 10px;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
HEADER {
|
|
552
|
+
margin: 0;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.primaryheader {
|
|
556
|
+
display: flex;
|
|
557
|
+
flex-direction: row;
|
|
558
|
+
align-items: center;
|
|
559
|
+
font-size:14px;
|
|
560
|
+
height: 50px;
|
|
561
|
+
|
|
562
|
+
h1 {
|
|
563
|
+
margin: 0;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.subheader{
|
|
568
|
+
display: flex;
|
|
569
|
+
flex-direction: row;
|
|
570
|
+
color: var(--input-label);
|
|
571
|
+
& > * {
|
|
572
|
+
margin: 5px 20px 5px 0px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.live-data {
|
|
576
|
+
color: var(--body-text)
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.state-banner {
|
|
581
|
+
margin: 3px 0 0 0;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.masthead-state {
|
|
585
|
+
font-size: initial;
|
|
586
|
+
display: inline-block;
|
|
587
|
+
position: relative;
|
|
588
|
+
/* top: -2px; */
|
|
589
|
+
font-size: 12px;
|
|
590
|
+
margin-left: 5px;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.masthead-istio {
|
|
594
|
+
.icon {
|
|
595
|
+
vertical-align: middle;
|
|
596
|
+
color: var(--primary);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.left-right-split {
|
|
601
|
+
display: grid;
|
|
602
|
+
align-items: center;
|
|
603
|
+
|
|
604
|
+
.left-half {
|
|
605
|
+
grid-column: 1;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.right-half {
|
|
609
|
+
grid-column: 2;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.resource-external {
|
|
614
|
+
font-size: 18px;
|
|
615
|
+
}
|
|
616
|
+
.excram-list{
|
|
617
|
+
font-size: 14px;
|
|
618
|
+
margin-bottom: 20px;
|
|
619
|
+
}
|
|
620
|
+
.excram-last-name{
|
|
621
|
+
color: var(--link);
|
|
622
|
+
}
|
|
623
|
+
.valid{
|
|
624
|
+
color: #d7d7d7;
|
|
625
|
+
margin: 0px 10px;
|
|
626
|
+
}
|
|
627
|
+
.detailIcon-span{
|
|
628
|
+
width: 24px;
|
|
629
|
+
height: 24px;
|
|
630
|
+
display: inline-block;
|
|
631
|
+
position: relative;
|
|
632
|
+
background: var(--primary);
|
|
633
|
+
margin-right: 10px;
|
|
634
|
+
}
|
|
635
|
+
.detailIcon{
|
|
636
|
+
position: absolute;
|
|
637
|
+
color: #fff;
|
|
638
|
+
font-size: 38px;
|
|
639
|
+
left: 4px;
|
|
640
|
+
top: -2px;
|
|
641
|
+
}
|
|
642
|
+
.primary-title{
|
|
643
|
+
display: flex;
|
|
644
|
+
align-items: center;
|
|
645
|
+
}
|
|
646
|
+
.detailIcon-span-title{
|
|
647
|
+
font-weight: bold;
|
|
648
|
+
}
|
|
649
|
+
</style>
|
package/package.json
CHANGED