dashboard-shell-shell 0.0.4 → 0.0.1000000000001124
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/assets/images/action.svg +6 -0
- package/assets/styles/base/_mixins.scss +1 -1
- package/assets/styles/global/_button.scss +17 -10
- package/assets/styles/global/_form.scss +2 -2
- package/assets/styles/global/_labeled-input.scss +6 -3
- package/assets/styles/global/_select.scss +5 -6
- package/assets/styles/global/_tooltip.scss +8 -1
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +5 -2
- package/assets/styles/vendor/vue-select.scss +2 -1
- package/components/ActionDropdown.vue +1 -0
- package/components/ActionMenuShell.vue +6 -1
- package/components/BrandImage.vue +21 -0
- package/components/ClusterIconMenu.vue +1 -1
- package/components/CodeMirror.vue +1 -0
- package/components/CruResource.vue +1 -0
- package/components/CruResourceFooter.vue +1 -1
- package/components/IndentedPanel.vue +4 -10
- package/components/PromptRemove.vue +2 -2
- package/components/ResourceDetail/Masthead.vue +161 -232
- package/components/ResourceDetail/index.vue +20 -1
- package/components/ResourceList/Masthead-btn.vue +225 -0
- package/components/ResourceList/Masthead.vue +96 -68
- package/components/ResourceList/ResourceLoadingIndicator.vue +5 -2
- package/components/ResourceTable.vue +64 -1
- package/components/SideNav.vue +24 -17
- package/components/SortableTable/THead.vue +6 -0
- package/components/SortableTable/index.vue +474 -366
- package/components/Tabbed/index.vue +4 -5
- package/components/auth/Principal.vue +3 -2
- package/components/auth/RoleDetailEdit.vue +56 -3
- package/components/auth/SelectPrincipal.vue +1 -0
- package/components/form/BannerSettings.vue +18 -16
- package/components/form/ChangePassword.vue +4 -4
- package/components/form/ColorInput.vue +32 -8
- package/components/form/Footer.vue +1 -1
- package/components/form/InputWithSelect.vue +2 -0
- package/components/form/KeyValue.vue +31 -7
- package/components/form/LabeledSelect.vue +178 -178
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -2
- package/components/form/Members/MembershipEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +24 -11
- package/components/form/Password.vue +6 -2
- package/components/form/Select.vue +2 -2
- package/components/nav/Favorite.vue +5 -1
- package/components/nav/Group.vue +45 -24
- package/components/nav/Header.vue +103 -14
- package/components/nav/HeaderPageActionMenu.vue +1 -0
- package/components/nav/TopLevelMenu.vue +63 -23
- package/components/nav/Type.vue +24 -5
- package/composables/useClickOutside.ts +1 -1
- package/config/product/auth.js +1 -1
- package/config/product/explorer.js +1 -1
- package/config/product/settings.js +10 -10
- package/detail/management.cattle.io.user.vue +1 -0
- package/edit/management.cattle.io.user.vue +17 -4
- package/list/management.cattle.io.user.vue +23 -12
- package/list/provisioning.cattle.io.cluster.vue +6 -7
- package/mixins/brand.js +17 -0
- package/package.json +1 -1
- package/pages/auth/login.vue +8 -22
- package/pages/c/_cluster/auth/roles/index.vue +48 -14
- package/pages/c/_cluster/settings/banners.vue +164 -101
- package/pages/c/_cluster/settings/brand.vue +338 -301
- package/pages/c/_cluster/settings/performance.vue +53 -38
- package/pages/home.vue +64 -8
- package/pages/prefs.vue +23 -21
- package/rancher-components/Banner/Banner.vue +4 -0
- package/rancher-components/Card/Card.vue +3 -6
- package/rancher-components/Form/Checkbox/Checkbox.vue +3 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +4 -2
- package/rancher-components/Form/Radio/RadioButton.vue +3 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +0 -4
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
- package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -2
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +3 -2
- package/rancher-components/RcDropdown/types.ts +1 -0
- package/scripts/typegen.sh +0 -1
- package/store/i18n.js +5 -5
- package/store/prefs.js +1 -1
- package/store/type-map.js +2 -1
- package/utils/router.js +1 -1
- package/types/resources/fleet.d.ts +0 -57
- package/types/resources/pod-security-admission.ts +0 -36
- package/types/resources/settings.d.ts +0 -93
- package/types/resources/userPreferences.d.ts +0 -13
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { mapGetters } from 'vuex';
|
|
3
|
+
import Favorite from '@shell/components/nav/Favorite';
|
|
4
|
+
import TypeDescription from '@shell/components/TypeDescription';
|
|
5
|
+
import { get } from '@shell/utils/object';
|
|
6
|
+
import { AS, _YAML } from '@shell/config/query-params';
|
|
7
|
+
import ResourceLoadingIndicator from './ResourceLoadingIndicator';
|
|
8
|
+
import TabTitle from '@shell/components/TabTitle';
|
|
9
|
+
import { harvesterhci2cloud, cloud2harvesterhci } from '@shell/utils/router'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resource List Masthead component.
|
|
13
|
+
*/
|
|
14
|
+
export default {
|
|
15
|
+
|
|
16
|
+
name: 'MastheadResourceList-btn',
|
|
17
|
+
|
|
18
|
+
components: {
|
|
19
|
+
Favorite,
|
|
20
|
+
TypeDescription,
|
|
21
|
+
ResourceLoadingIndicator,
|
|
22
|
+
TabTitle
|
|
23
|
+
},
|
|
24
|
+
props: {
|
|
25
|
+
resource: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
schema: {
|
|
31
|
+
type: Object,
|
|
32
|
+
default: null,
|
|
33
|
+
},
|
|
34
|
+
typeDisplay: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: null,
|
|
37
|
+
},
|
|
38
|
+
isCreatable: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: null,
|
|
41
|
+
},
|
|
42
|
+
isYamlCreatable: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: null,
|
|
45
|
+
},
|
|
46
|
+
createLocation: {
|
|
47
|
+
type: Object,
|
|
48
|
+
default: null,
|
|
49
|
+
},
|
|
50
|
+
yamlCreateLocation: {
|
|
51
|
+
type: Object,
|
|
52
|
+
default: null,
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
createButtonLabel: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: null
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Inherited global identifier prefix for tests
|
|
62
|
+
* Define a term based on the parent component to avoid conflicts on multiple components
|
|
63
|
+
*/
|
|
64
|
+
componentTestid: {
|
|
65
|
+
type: String,
|
|
66
|
+
default: 'masthead'
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
data() {
|
|
71
|
+
const params = { ...this.$route.params };
|
|
72
|
+
|
|
73
|
+
params.resource = harvesterhci2cloud(params.resource)
|
|
74
|
+
|
|
75
|
+
const formRoute = { name: `${ cloud2harvesterhci(this.$route.name) }-create`, params };
|
|
76
|
+
|
|
77
|
+
const hasEditComponent = this.$store.getters['type-map/hasCustomEdit'](this.resource);
|
|
78
|
+
|
|
79
|
+
const yamlRoute = {
|
|
80
|
+
name: `${ cloud2harvesterhci(this.$route.name) }-create`,
|
|
81
|
+
params,
|
|
82
|
+
query: { [AS]: _YAML },
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const tabList = ['集群配置'];
|
|
86
|
+
return {
|
|
87
|
+
formRoute,
|
|
88
|
+
yamlRoute,
|
|
89
|
+
hasEditComponent,
|
|
90
|
+
tabList,
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
computed: {
|
|
95
|
+
get,
|
|
96
|
+
...mapGetters(['isExplorer', 'currentCluster']),
|
|
97
|
+
|
|
98
|
+
_typeDisplay() {
|
|
99
|
+
if ( this.typeDisplay !== null) {
|
|
100
|
+
return this.typeDisplay;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if ( !this.schema ) {
|
|
104
|
+
return '?';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return this.$store.getters['type-map/labelFor'](this.schema, 99);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
_isYamlCreatable() {
|
|
112
|
+
if ( this.isYamlCreatable !== null) {
|
|
113
|
+
return this.isYamlCreatable;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return this.schema && this._isCreatable && this.$store.getters['type-map/optionsFor'](this.resource).canYaml;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
_isCreatable() {
|
|
120
|
+
// Does not take into account hasEditComponent, such that _isYamlCreatable works
|
|
121
|
+
if ( this.isCreatable !== null) {
|
|
122
|
+
return this.isCreatable;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// blocked-post means you can post through norman, but not through steve.
|
|
126
|
+
if ( this.schema && !this.schema?.collectionMethods.find((x) => ['blocked-post', 'post'].includes(x.toLowerCase())) ) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return this.$store.getters['type-map/optionsFor'](this.resource).isCreatable;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
_createLocation() {
|
|
134
|
+
return this.createLocation || this.formRoute;
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
_yamlCreateLocation() {
|
|
138
|
+
return this.yamlCreateLocation || this.yamlRoute;
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
_createButtonlabel() {
|
|
142
|
+
return this.createButtonLabel || this.t('resourceList.head.create');
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<template>
|
|
149
|
+
<!-- 顶部 header,带有子标题(subheader)样式类 -->
|
|
150
|
+
<div style="display: flex;width: 100%;">
|
|
151
|
+
|
|
152
|
+
<!-- 操作按钮区域 -->
|
|
153
|
+
<div
|
|
154
|
+
v-if="!(tabList.includes(_typeDisplay))"
|
|
155
|
+
class="actions-container"
|
|
156
|
+
style="min-height: 32px;align-self: flex-end;margin-right: 10px;"
|
|
157
|
+
>
|
|
158
|
+
<slot name="actions">
|
|
159
|
+
<div class="actions">
|
|
160
|
+
<slot name="extraActions" />
|
|
161
|
+
|
|
162
|
+
<slot name="createButton">
|
|
163
|
+
<router-link
|
|
164
|
+
v-if="hasEditComponent && _isCreatable"
|
|
165
|
+
:to="_createLocation"
|
|
166
|
+
class="btn role-primary"
|
|
167
|
+
:data-testid="componentTestid+'-create'"
|
|
168
|
+
>
|
|
169
|
+
{{ _createButtonlabel }}
|
|
170
|
+
</router-link>
|
|
171
|
+
<router-link
|
|
172
|
+
v-else-if="_isYamlCreatable"
|
|
173
|
+
:to="_yamlCreateLocation"
|
|
174
|
+
class="btn role-primary"
|
|
175
|
+
:data-testid="componentTestid+'-create-yaml'"
|
|
176
|
+
>
|
|
177
|
+
{{ t("resourceList.head.createFromYaml") }}
|
|
178
|
+
</router-link>
|
|
179
|
+
</slot>
|
|
180
|
+
</div>
|
|
181
|
+
</slot>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</template>
|
|
185
|
+
|
|
186
|
+
<style lang="scss" scoped>
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
header {
|
|
190
|
+
/* margin-bottom: 20px; */
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
header.with-subheader {
|
|
194
|
+
/* grid-template-areas:
|
|
195
|
+
'type-banner type-banner'
|
|
196
|
+
'title actions'
|
|
197
|
+
'sub-header sub-header'
|
|
198
|
+
'state-banner state-banner'; */
|
|
199
|
+
position: relative;
|
|
200
|
+
display: flex;
|
|
201
|
+
margin-bottom: 16px;
|
|
202
|
+
flex-direction: column;
|
|
203
|
+
}
|
|
204
|
+
.excram-list{
|
|
205
|
+
font-size: 14px;
|
|
206
|
+
line-height: 22px;
|
|
207
|
+
margin-bottom: 20px;
|
|
208
|
+
font-family: 'Microsoft YaHei';
|
|
209
|
+
}
|
|
210
|
+
.excram-last-name{
|
|
211
|
+
color: var(--primary);
|
|
212
|
+
}
|
|
213
|
+
.descrip-name{
|
|
214
|
+
font-size: 26px;
|
|
215
|
+
font-family: 'Microsoft YaHei';
|
|
216
|
+
}
|
|
217
|
+
.masthod-title-description{
|
|
218
|
+
font-family: 'Microsoft YaHei';
|
|
219
|
+
margin-top: 20px;
|
|
220
|
+
}
|
|
221
|
+
.actions-container{
|
|
222
|
+
/* display: flex; */
|
|
223
|
+
/* margin-left: 0px; */
|
|
224
|
+
}
|
|
225
|
+
</style>
|
|
@@ -80,12 +80,19 @@ export default {
|
|
|
80
80
|
componentTestid: {
|
|
81
81
|
type: String,
|
|
82
82
|
default: 'masthead'
|
|
83
|
-
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
mainButtonVisible: {
|
|
86
|
+
type: Boolean,
|
|
87
|
+
default: true
|
|
88
|
+
},
|
|
84
89
|
},
|
|
85
90
|
|
|
86
91
|
data() {
|
|
87
92
|
const params = { ...this.$route.params };
|
|
88
93
|
|
|
94
|
+
console.log(params.product, ' params.product----------------');
|
|
95
|
+
|
|
89
96
|
params.resource = harvesterhci2cloud(params.resource)
|
|
90
97
|
|
|
91
98
|
const formRoute = { name: `${ cloud2harvesterhci(this.$route.name) }-create`, params };
|
|
@@ -191,80 +198,94 @@ export default {
|
|
|
191
198
|
</script>
|
|
192
199
|
|
|
193
200
|
<template>
|
|
201
|
+
<!-- 顶部 header,带有子标题(subheader)样式类 -->
|
|
194
202
|
<header class="with-subheader">
|
|
195
|
-
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
<div style="display: flex;width: 100%;">
|
|
204
|
+
<div style="flex: 1;">
|
|
205
|
+
<!-- 标题区域 -->
|
|
206
|
+
<div class="title">
|
|
207
|
+
<div class="excram-list">
|
|
208
|
+
<span
|
|
209
|
+
v-for="(item,index) in demoDisplay"
|
|
210
|
+
:key="index"
|
|
211
|
+
>
|
|
212
|
+
<span v-if="item">{{ item }}</span>
|
|
213
|
+
<span v-if="item">/</span>
|
|
214
|
+
</span>
|
|
215
|
+
<span class="excram-last-name">{{ _typeDisplay }}</span>
|
|
216
|
+
</div>
|
|
217
|
+
<h1 style="display: flex;align-items: center;" class="m-0 descrip-name">
|
|
218
|
+
<TabTitle>{{ _typeDisplay }}</TabTitle>
|
|
219
|
+
|
|
220
|
+
<!-- <Favorite
|
|
221
|
+
v-if="isExplorer"
|
|
222
|
+
:resource="favoriteResource || resource"
|
|
223
|
+
/> -->
|
|
224
|
+
|
|
225
|
+
<ResourceLoadingIndicator
|
|
226
|
+
style="margin-left: 10px;"
|
|
227
|
+
v-if="showIncrementalLoadingIndicator"
|
|
228
|
+
:resources="loadResources"
|
|
229
|
+
:indeterminate="loadIndeterminate"
|
|
230
|
+
/>
|
|
231
|
+
</h1>
|
|
232
|
+
|
|
233
|
+
<!-- 插槽:typeDescription,用于插入类型描述组件 -->
|
|
234
|
+
<div v-if="_descriptionDisplay" class="masthod-title-description">
|
|
235
|
+
{{ _descriptionDisplay }}
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<!-- 子标题区域 -->
|
|
241
|
+
<div class="sub-header">
|
|
242
|
+
<slot name="subHeader">
|
|
243
|
+
<!--Slot content-->
|
|
244
|
+
</slot>
|
|
245
|
+
</div>
|
|
208
246
|
</div>
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
247
|
+
|
|
248
|
+
<!-- 操作按钮区域 -->
|
|
249
|
+
<div
|
|
250
|
+
v-if="!(tabList.includes(_typeDisplay)) && mainButtonVisible"
|
|
251
|
+
class="actions-container"
|
|
252
|
+
style="min-height: 32px;align-self: flex-end;"
|
|
253
|
+
>
|
|
254
|
+
<slot name="actions">
|
|
255
|
+
<div class="actions">
|
|
256
|
+
<slot name="extraActions" />
|
|
257
|
+
|
|
258
|
+
<slot name="createButton">
|
|
259
|
+
<router-link
|
|
260
|
+
v-if="hasEditComponent && _isCreatable"
|
|
261
|
+
:to="_createLocation"
|
|
262
|
+
class="btn role-primary"
|
|
263
|
+
:data-testid="componentTestid+'-create'"
|
|
264
|
+
>
|
|
265
|
+
{{ _createButtonlabel }}
|
|
266
|
+
</router-link>
|
|
267
|
+
<router-link
|
|
268
|
+
v-else-if="_isYamlCreatable"
|
|
269
|
+
:to="_yamlCreateLocation"
|
|
270
|
+
class="btn role-primary"
|
|
271
|
+
:data-testid="componentTestid+'-create-yaml'"
|
|
272
|
+
>
|
|
273
|
+
{{ t("resourceList.head.createFromYaml") }}
|
|
274
|
+
</router-link>
|
|
275
|
+
</slot>
|
|
276
|
+
</div>
|
|
277
|
+
</slot>
|
|
218
278
|
</div>
|
|
219
|
-
<ResourceLoadingIndicator
|
|
220
|
-
v-if="showIncrementalLoadingIndicator"
|
|
221
|
-
:resources="loadResources"
|
|
222
|
-
:indeterminate="loadIndeterminate"
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
<div class="sub-header">
|
|
226
|
-
<slot name="subHeader">
|
|
227
|
-
<!--Slot content-->
|
|
228
|
-
</slot>
|
|
229
279
|
</div>
|
|
230
280
|
<div
|
|
231
281
|
v-if="!(tabList.includes(_typeDisplay))"
|
|
232
|
-
style="width: 110%;height: 1px;background-color: #D7D7D7;margin-top:
|
|
282
|
+
style="width: 110%;height: 1px;background-color: #D7D7D7;margin-top: 16px;margin-left: -20px;margin-right: -20px;"
|
|
233
283
|
/>
|
|
234
|
-
<div
|
|
235
|
-
v-if="!(tabList.includes(_typeDisplay))"
|
|
236
|
-
class="actions-container"
|
|
237
|
-
style="width: 100%;min-height: 32px;text-align: left"
|
|
238
|
-
>
|
|
239
|
-
<slot name="actions">
|
|
240
|
-
<div class="actions">
|
|
241
|
-
<slot name="extraActions" />
|
|
242
|
-
|
|
243
|
-
<slot name="createButton">
|
|
244
|
-
<router-link
|
|
245
|
-
v-if="hasEditComponent && _isCreatable"
|
|
246
|
-
:to="_createLocation"
|
|
247
|
-
class="btn role-primary"
|
|
248
|
-
:data-testid="componentTestid+'-create'"
|
|
249
|
-
>
|
|
250
|
-
{{ _createButtonlabel }}
|
|
251
|
-
</router-link>
|
|
252
|
-
<!-- <router-link
|
|
253
|
-
v-else-if="_isYamlCreatable"
|
|
254
|
-
:to="_yamlCreateLocation"
|
|
255
|
-
class="btn role-primary"
|
|
256
|
-
:data-testid="componentTestid+'-create-yaml'"
|
|
257
|
-
>
|
|
258
|
-
{{ t("resourceList.head.createFromYaml") }}
|
|
259
|
-
</router-link> -->
|
|
260
|
-
</slot>
|
|
261
|
-
</div>
|
|
262
|
-
</slot>
|
|
263
|
-
</div>
|
|
264
284
|
</header>
|
|
265
285
|
</template>
|
|
266
286
|
|
|
267
287
|
<style lang="scss" scoped>
|
|
288
|
+
|
|
268
289
|
.title {
|
|
269
290
|
/* align-items: center;
|
|
270
291
|
display: flex; */
|
|
@@ -283,8 +304,10 @@ export default {
|
|
|
283
304
|
'title actions'
|
|
284
305
|
'sub-header sub-header'
|
|
285
306
|
'state-banner state-banner'; */
|
|
286
|
-
|
|
287
|
-
|
|
307
|
+
position: relative;
|
|
308
|
+
display: flex;
|
|
309
|
+
margin-bottom: 16px;
|
|
310
|
+
flex-direction: column;
|
|
288
311
|
}
|
|
289
312
|
.excram-list{
|
|
290
313
|
font-size: 14px;
|
|
@@ -301,11 +324,16 @@ export default {
|
|
|
301
324
|
}
|
|
302
325
|
.masthod-title-description{
|
|
303
326
|
font-family: 'Microsoft YaHei';
|
|
304
|
-
margin: 20px
|
|
327
|
+
margin-top: 20px;
|
|
305
328
|
}
|
|
306
329
|
.actions-container{
|
|
307
330
|
/* display: flex; */
|
|
308
331
|
/* margin-left: 0px; */
|
|
309
|
-
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.sub-header {
|
|
335
|
+
.btn {
|
|
336
|
+
text-align: left !important;
|
|
337
|
+
}
|
|
310
338
|
}
|
|
311
339
|
</style>
|
|
@@ -77,7 +77,7 @@ export default {
|
|
|
77
77
|
<template>
|
|
78
78
|
<div
|
|
79
79
|
v-if="count && !haveAll"
|
|
80
|
-
class="
|
|
80
|
+
class="resource-loading-indicator"
|
|
81
81
|
>
|
|
82
82
|
<div class="inner">
|
|
83
83
|
<div class="resource-loader">
|
|
@@ -118,10 +118,12 @@ export default {
|
|
|
118
118
|
.resource-loader {
|
|
119
119
|
padding: 1px 10px;
|
|
120
120
|
width: max-content;
|
|
121
|
+
height: 20px;
|
|
121
122
|
|
|
122
123
|
.rl-fg, .rl-bg {
|
|
123
|
-
align-content: center;
|
|
124
124
|
display: flex;
|
|
125
|
+
align-content: center;
|
|
126
|
+
font-size: 12px;
|
|
125
127
|
|
|
126
128
|
> i {
|
|
127
129
|
font-size: 18px;
|
|
@@ -129,6 +131,7 @@ export default {
|
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
> span {
|
|
134
|
+
margin-top: 2px;
|
|
132
135
|
margin-left: 5px;
|
|
133
136
|
}
|
|
134
137
|
}
|
|
@@ -4,6 +4,7 @@ import { get } from '@shell/utils/object';
|
|
|
4
4
|
import { mapPref, GROUP_RESOURCES } from '@shell/store/prefs';
|
|
5
5
|
import ButtonGroup from '@shell/components/ButtonGroup';
|
|
6
6
|
import SortableTable from '@shell/components/SortableTable';
|
|
7
|
+
import MastheadBtn from '@shell/components/ResourceList/Masthead-btn.vue';
|
|
7
8
|
import { NAMESPACE, AGE } from '@shell/config/table-headers';
|
|
8
9
|
import { findBy } from '@shell/utils/array';
|
|
9
10
|
import { ExtensionPoint, TableColumnLocation } from '@shell/core/types';
|
|
@@ -43,7 +44,7 @@ export default {
|
|
|
43
44
|
|
|
44
45
|
emits: ['clickedActionButton'],
|
|
45
46
|
|
|
46
|
-
components: { ButtonGroup, SortableTable },
|
|
47
|
+
components: { ButtonGroup, SortableTable, MastheadBtn },
|
|
47
48
|
|
|
48
49
|
props: {
|
|
49
50
|
schema: {
|
|
@@ -212,6 +213,49 @@ export default {
|
|
|
212
213
|
type: String,
|
|
213
214
|
default: '名称'
|
|
214
215
|
},
|
|
216
|
+
|
|
217
|
+
resource: {
|
|
218
|
+
type: String,
|
|
219
|
+
required: true,
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
typeDisplay: {
|
|
223
|
+
type: String,
|
|
224
|
+
default: null,
|
|
225
|
+
},
|
|
226
|
+
isCreatable: {
|
|
227
|
+
type: Boolean,
|
|
228
|
+
default: null,
|
|
229
|
+
},
|
|
230
|
+
isYamlCreatable: {
|
|
231
|
+
type: Boolean,
|
|
232
|
+
default: null,
|
|
233
|
+
},
|
|
234
|
+
createLocation: {
|
|
235
|
+
type: Object,
|
|
236
|
+
default: null,
|
|
237
|
+
},
|
|
238
|
+
yamlCreateLocation: {
|
|
239
|
+
type: Object,
|
|
240
|
+
default: null,
|
|
241
|
+
},
|
|
242
|
+
createButtonLabel: {
|
|
243
|
+
type: String,
|
|
244
|
+
default: null
|
|
245
|
+
},
|
|
246
|
+
/**
|
|
247
|
+
* Inherited global identifier prefix for tests
|
|
248
|
+
* Define a term based on the parent component to avoid conflicts on multiple components
|
|
249
|
+
*/
|
|
250
|
+
componentTestid: {
|
|
251
|
+
type: String,
|
|
252
|
+
default: 'masthead'
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
mainButtonVisible: {
|
|
256
|
+
type: Boolean,
|
|
257
|
+
default: false
|
|
258
|
+
},
|
|
215
259
|
},
|
|
216
260
|
|
|
217
261
|
data() {
|
|
@@ -641,6 +685,25 @@ export default {
|
|
|
641
685
|
@group-value-change="group = $event"
|
|
642
686
|
@enter="handleEnterKeyPress"
|
|
643
687
|
>
|
|
688
|
+
|
|
689
|
+
<template #search-main-button>
|
|
690
|
+
<MastheadBtn
|
|
691
|
+
v-if="mainButtonVisible"
|
|
692
|
+
:schema="schema"
|
|
693
|
+
:resource="resource"
|
|
694
|
+
>
|
|
695
|
+
|
|
696
|
+
<template #extraActions>
|
|
697
|
+
<slot name="extraActions" />
|
|
698
|
+
</template>
|
|
699
|
+
|
|
700
|
+
<template #createButton>
|
|
701
|
+
<slot name="createButton" />
|
|
702
|
+
</template>
|
|
703
|
+
|
|
704
|
+
</ MastheadBtn>
|
|
705
|
+
</template>
|
|
706
|
+
|
|
644
707
|
<template
|
|
645
708
|
v-if="showGrouping && _groupOptions.length > 1"
|
|
646
709
|
#header-middle
|
package/components/SideNav.vue
CHANGED
|
@@ -113,7 +113,7 @@ export default {
|
|
|
113
113
|
|
|
114
114
|
computed: {
|
|
115
115
|
...mapState(['managementReady', 'clusterReady']),
|
|
116
|
-
...mapGetters(['isStandaloneHarvester', 'productId', 'clusterId', 'currentProduct', 'rootProduct', 'isSingleProduct', 'namespaceMode', 'isExplorer', 'isVirtualCluster']),
|
|
116
|
+
...mapGetters(['isStandaloneHarvester', 'productId', 'clusterId', 'currentProduct', 'rootProduct', 'currentCluster', 'isSingleProduct', 'namespaceMode', 'isExplorer', 'isVirtualCluster']),
|
|
117
117
|
...mapGetters({ locale: 'i18n/selectedLocaleLabel', hasMultipleLocales: 'i18n/hasMultipleLocales' }),
|
|
118
118
|
...mapGetters('type-map', ['activeProducts']),
|
|
119
119
|
|
|
@@ -185,6 +185,12 @@ export default {
|
|
|
185
185
|
allNavLinksIds() {
|
|
186
186
|
return this.allNavLinks.map((a) => a.id);
|
|
187
187
|
},
|
|
188
|
+
|
|
189
|
+
prod() {
|
|
190
|
+
const name = this.rootProduct.name;
|
|
191
|
+
|
|
192
|
+
return this.$store.getters['i18n/withFallback'](`product."${ name }"`, null, ucFirst(name));
|
|
193
|
+
},
|
|
188
194
|
},
|
|
189
195
|
|
|
190
196
|
methods: {
|
|
@@ -400,9 +406,10 @@ export default {
|
|
|
400
406
|
role="navigation"
|
|
401
407
|
:aria-label="t('nav.ariaLabel.sideNav')"
|
|
402
408
|
>
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
409
|
+
<div class="side-all-title">
|
|
410
|
+
{{ currentCluster ? currentCluster.spec.displayName : prod }}
|
|
411
|
+
</div>
|
|
412
|
+
|
|
406
413
|
<!-- Actual nav -->
|
|
407
414
|
<div class="nav">
|
|
408
415
|
<template
|
|
@@ -422,36 +429,36 @@ export default {
|
|
|
422
429
|
</template>
|
|
423
430
|
</div>
|
|
424
431
|
<!-- SideNav footer area (seems to be tied to harvester) -->
|
|
425
|
-
|
|
432
|
+
<div
|
|
426
433
|
v-if="showProductFooter"
|
|
427
434
|
class="footer"
|
|
428
|
-
>
|
|
435
|
+
>
|
|
429
436
|
<!-- support link -->
|
|
430
|
-
|
|
437
|
+
<router-link
|
|
431
438
|
:to="supportLink"
|
|
432
439
|
class="pull-right"
|
|
433
440
|
role="link"
|
|
434
441
|
:aria-label="t('nav.support', {hasSupport: true})"
|
|
435
442
|
>
|
|
436
443
|
{{ t('nav.support', {hasSupport: true}) }}
|
|
437
|
-
</router-link>
|
|
444
|
+
</router-link>
|
|
438
445
|
<!-- version number -->
|
|
439
|
-
|
|
446
|
+
<span
|
|
440
447
|
v-clean-tooltip="{content: displayVersion, placement: 'top'}"
|
|
441
448
|
class="clip version text-muted"
|
|
442
449
|
>
|
|
443
450
|
{{ displayVersion }}
|
|
444
|
-
</span>
|
|
451
|
+
</span>
|
|
445
452
|
|
|
446
453
|
<!-- locale selector -->
|
|
447
|
-
|
|
454
|
+
<LocaleSelector
|
|
448
455
|
v-if="isSingleProduct && hasMultipleLocales && !isStandaloneHarvester"
|
|
449
456
|
mode="login"
|
|
450
457
|
:show-icon="false"
|
|
451
|
-
/>
|
|
452
|
-
|
|
458
|
+
/>
|
|
459
|
+
</div>
|
|
453
460
|
<!-- SideNav footer alternative -->
|
|
454
|
-
|
|
461
|
+
<div
|
|
455
462
|
v-else
|
|
456
463
|
class="version text-muted flex"
|
|
457
464
|
>
|
|
@@ -472,13 +479,14 @@ export default {
|
|
|
472
479
|
(Harvester-{{ harvesterVersion }})
|
|
473
480
|
</span>
|
|
474
481
|
</template>
|
|
475
|
-
</div>
|
|
482
|
+
</div>
|
|
476
483
|
</nav>
|
|
477
484
|
</template>
|
|
478
485
|
|
|
479
486
|
<style lang="scss" scoped>
|
|
480
487
|
.side-nav {
|
|
481
488
|
display: flex;
|
|
489
|
+
z-index: 10;
|
|
482
490
|
flex-direction: column;
|
|
483
491
|
.nav {
|
|
484
492
|
flex: 1;
|
|
@@ -498,9 +506,8 @@ export default {
|
|
|
498
506
|
|
|
499
507
|
A { padding-left: 0; }
|
|
500
508
|
}
|
|
501
|
-
:deep() A{
|
|
509
|
+
:deep() A:not(.menuRouterLink){
|
|
502
510
|
height: 50px;
|
|
503
|
-
background-color: #fff;
|
|
504
511
|
}
|
|
505
512
|
|
|
506
513
|
.tools {
|
|
@@ -274,6 +274,12 @@ export default {
|
|
|
274
274
|
class="content"
|
|
275
275
|
>
|
|
276
276
|
<span
|
|
277
|
+
v-if="(col.name === 'harvester' || col.name === 'explorer') && col.label === ' '"
|
|
278
|
+
>
|
|
279
|
+
管理
|
|
280
|
+
</span>
|
|
281
|
+
<span
|
|
282
|
+
v-if="!((col.name === 'harvester' || col.name === 'explorer') && col.label === ' ')"
|
|
277
283
|
v-clean-html="labelFor(col)"
|
|
278
284
|
class="text-no-break"
|
|
279
285
|
/>
|