@rancher/shell 0.3.5 → 0.3.6
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/providers/outscale.svg +19 -0
- package/assets/styles/base/_basic.scss +18 -0
- package/assets/styles/base/_mixins.scss +0 -11
- package/assets/styles/base/_variables.scss +2 -4
- package/assets/styles/global/_button.scss +12 -2
- package/assets/translations/en-us.yaml +22 -1
- package/assets/translations/zh-hans.yaml +30 -10
- package/chart/gatekeeper.vue +3 -2
- package/chart/istio.vue +29 -3
- package/components/BrandImage.vue +1 -4
- package/components/Carousel.vue +85 -37
- package/components/EtcdInfoBanner.vue +7 -3
- package/components/ExplorerMembers.vue +100 -5
- package/components/ExplorerProjectsNamespaces.vue +32 -2
- package/components/GrafanaDashboard.vue +9 -2
- package/components/SortableTable/index.vue +23 -11
- package/components/SortableTable/selection.js +58 -50
- package/components/Wizard.vue +4 -2
- package/components/auth/RoleDetailEdit.vue +2 -2
- package/components/form/HookOption.vue +14 -10
- package/components/form/Labels.vue +32 -27
- package/components/form/MatchExpressions.vue +2 -2
- package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +46 -21
- package/components/form/Tolerations.vue +4 -1
- package/components/form/ValueFromResource.vue +14 -9
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/form/__tests__/NameNsDescription.ts +27 -0
- package/components/formatter/WorkloadHealthScale.vue +8 -2
- package/components/nav/NamespaceFilter.vue +8 -0
- package/{nuxt/components → components/nuxt}/nuxt.js +1 -1
- package/{nuxt → config}/middleware.js +8 -8
- package/config/product/explorer.js +24 -3
- package/config/query-params.js +1 -0
- package/config/router.js +1 -1
- package/{nuxt → config}/store.js +82 -79
- package/config/table-headers.js +46 -12
- package/config/types.js +7 -0
- package/core/plugin.ts +4 -2
- package/core/types.ts +258 -1
- package/creators/app/files/tsconfig.json +0 -1
- package/creators/app/files/vue.config.js +0 -1
- package/creators/pkg/files/.github/workflows/build-extension.yml +3 -4
- package/creators/pkg/files/tsconfig.json +0 -1
- package/creators/pkg/pkg.package.json +3 -3
- package/detail/constraints.gatekeeper.sh.constraint.vue +14 -7
- package/detail/fleet.cattle.io.clustergroup.vue +7 -1
- package/edit/fleet.cattle.io.gitrepo.vue +16 -1
- package/edit/logging.banzaicloud.io.output/index.vue +18 -5
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/namespace.vue +12 -8
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -4
- package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
- package/edit/provisioning.cattle.io.cluster/rke2.vue +96 -18
- package/edit/workload/mixins/workload.js +6 -7
- package/edit/workload/storage/Mount.vue +3 -3
- package/initialize/App.js +206 -0
- package/{nuxt → initialize}/client.js +406 -360
- package/{nuxt → initialize}/index.js +21 -22
- package/layouts/standalone.vue +13 -0
- package/list/catalog.cattle.io.clusterrepo.vue +1 -0
- package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
- package/list/workload.vue +6 -4
- package/mixins/chart.js +29 -1
- package/mixins/fetch.client.js +95 -0
- package/{nuxt/mixins → mixins}/fetch.server.js +30 -26
- package/mixins/labeled-form-element.ts +2 -2
- package/models/constraints.gatekeeper.sh.constraint.js +37 -0
- package/models/pod.js +4 -0
- package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
- package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
- package/package.json +9 -13
- package/pages/c/_cluster/apps/charts/install.vue +61 -39
- package/pages/diagnostic.vue +32 -25
- package/pages/rio/mesh.vue +1 -2
- package/pkg/tsconfig.json +0 -1
- package/plugins/clean-html-directive.js +3 -0
- package/plugins/dashboard-store/index.js +1 -1
- package/plugins/plugin.js +0 -14
- package/plugins/portal-vue.js +4 -0
- package/rancher-components/components/Banner/Banner.test.ts +3 -5
- package/rancher-components/components/Banner/Banner.vue +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
- package/scripts/extension/publish +42 -23
- package/scripts/serve-pkgs +6 -2
- package/store/type-map.js +1 -1
- package/tsconfig.json +0 -1
- package/types/rancher/index.d.ts +2 -0
- package/types/shell/index.d.ts +353 -284
- package/utils/__tests__/grafana.test.ts +44 -0
- package/utils/axios.js +190 -0
- package/{nuxt → utils}/cookie-universal-nuxt.js +7 -6
- package/utils/dom.js +15 -0
- package/utils/grafana.js +35 -16
- package/{nuxt/utils.js → utils/nuxt.js} +265 -236
- package/utils/router.scrollBehavior.js +1 -1
- package/vue.config.js +30 -19
- package/nuxt/App.js +0 -210
- package/nuxt/axios.js +0 -186
- package/nuxt/empty.js +0 -1
- package/nuxt/jsonp.js +0 -82
- package/nuxt/loading.html +0 -39
- package/nuxt/mixins/fetch.client.js +0 -90
- package/nuxt/portal-vue.js +0 -4
- package/nuxt/server.js +0 -312
- package/nuxt/views/app.template.html +0 -9
- package/nuxt/views/error.html +0 -23
- package/plugins/dashboard-store/extensions.js +0 -22
- /package/{nuxt/components → components/nuxt}/nuxt-build-indicator.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-child.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-error.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.client.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.server.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-loading.vue +0 -0
package/components/Carousel.vue
CHANGED
|
@@ -47,11 +47,19 @@ export default {
|
|
|
47
47
|
computed: {
|
|
48
48
|
...mapGetters(['clusterId']),
|
|
49
49
|
trackStyle() {
|
|
50
|
-
|
|
51
|
-
const width = 60 * this.slider.length;
|
|
50
|
+
let sliderItem = ( this.activeItemId + 1) * 100 / (this.slider.length + 2);
|
|
51
|
+
const width = 60 * (this.slider.length + 2);
|
|
52
|
+
|
|
53
|
+
if (this.slider.length === 1) {
|
|
54
|
+
sliderItem = 0;
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
return `transform: translateX(-${ sliderItem }%); width: ${ width }%`;
|
|
54
58
|
},
|
|
59
|
+
|
|
60
|
+
test() {
|
|
61
|
+
return 'test';
|
|
62
|
+
}
|
|
55
63
|
},
|
|
56
64
|
|
|
57
65
|
methods: {
|
|
@@ -64,26 +72,35 @@ export default {
|
|
|
64
72
|
scrollSlide(i) {
|
|
65
73
|
this.autoScroll = false;
|
|
66
74
|
this.activeItemId = i;
|
|
67
|
-
setTimeout(() => {
|
|
68
|
-
this.slidePosition();
|
|
69
|
-
}, 400);
|
|
70
75
|
},
|
|
71
76
|
|
|
72
|
-
nextPrev(
|
|
77
|
+
nextPrev(direction) {
|
|
73
78
|
this.autoScroll = false;
|
|
74
|
-
|
|
75
|
-
this.activeItemId++;
|
|
76
|
-
}
|
|
79
|
+
const slideTrack = document.getElementById('slide-track');
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
slideTrack.style.transition = `transform 450ms ease-in-out`;
|
|
82
|
+
|
|
83
|
+
direction !== 'prev' ? (this.activeItemId++) : (this.activeItemId--);
|
|
81
84
|
|
|
82
|
-
this.
|
|
85
|
+
slideTrack.addEventListener('transitionend', this.slideTransition);
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
slideTransition() {
|
|
89
|
+
const slideTrack = document.getElementById('slide-track');
|
|
90
|
+
const slidesArray = this.slider.length + 2;
|
|
91
|
+
|
|
92
|
+
if (this.activeItemId === -1) {
|
|
93
|
+
slideTrack.style.transition = 'none';
|
|
94
|
+
this.activeItemId = this.slider.length - 1;
|
|
95
|
+
}
|
|
96
|
+
if (this.activeItemId === slidesArray - 2) {
|
|
97
|
+
slideTrack.style.transition = 'none';
|
|
98
|
+
this.activeItemId = 0;
|
|
99
|
+
}
|
|
83
100
|
},
|
|
84
101
|
|
|
85
102
|
autoScrollSlide() {
|
|
86
|
-
if (this.activeItemId < this.slider.length && this.autoScroll ) {
|
|
103
|
+
if (this.activeItemId < (this.slider.length + 1) && this.autoScroll ) {
|
|
87
104
|
this.activeItemId++;
|
|
88
105
|
}
|
|
89
106
|
|
|
@@ -91,18 +108,7 @@ export default {
|
|
|
91
108
|
this.autoScroll = false;
|
|
92
109
|
this.activeItemId = 0;
|
|
93
110
|
}
|
|
94
|
-
this.slidePosition();
|
|
95
111
|
},
|
|
96
|
-
|
|
97
|
-
slidePosition() {
|
|
98
|
-
if (this.activeItemId <= 1) {
|
|
99
|
-
this.$refs.slide[this.slider.length - 1].style.left = '-93%';
|
|
100
|
-
this.$refs.slide[0].style.left = '7%';
|
|
101
|
-
} else {
|
|
102
|
-
this.$refs.slide[this.slider.length - 1].style.left = '7%';
|
|
103
|
-
this.$refs.slide[0].style.left = '107%';
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
112
|
},
|
|
107
113
|
|
|
108
114
|
beforeDestroy() {
|
|
@@ -112,14 +118,30 @@ export default {
|
|
|
112
118
|
},
|
|
113
119
|
|
|
114
120
|
mounted() {
|
|
121
|
+
const slideTrack = document.getElementById('slide-track');
|
|
122
|
+
|
|
123
|
+
if (this.slider.length === 1) {
|
|
124
|
+
// singleSlide.style = 'width: 100%; max-width: 100%';
|
|
125
|
+
slideTrack.style = 'transform:translateX(0%); width:100%; left:0';
|
|
126
|
+
} else {
|
|
127
|
+
const node = document.getElementById('slide0');
|
|
128
|
+
const clone = node.cloneNode(true);
|
|
129
|
+
|
|
130
|
+
const nodeLast = document.getElementById(`slide${ this.slider.length - 1 }`);
|
|
131
|
+
const cloneLast = nodeLast.cloneNode(true);
|
|
132
|
+
|
|
133
|
+
slideTrack.appendChild(clone);
|
|
134
|
+
slideTrack.insertBefore(cloneLast, slideTrack.children[0]);
|
|
135
|
+
}
|
|
136
|
+
|
|
115
137
|
const lastSeenCluster = sessionStorage.getItem(carouselSeenStorageKey);
|
|
116
138
|
|
|
117
139
|
if (lastSeenCluster !== this.clusterId) {
|
|
118
140
|
// Session storage lasts until tab/window closed (retained on refresh)
|
|
119
141
|
sessionStorage.setItem(carouselSeenStorageKey, this.clusterId);
|
|
120
|
-
|
|
121
|
-
this.autoScrollSlideInterval = setInterval(this.autoScrollSlide, 5000);
|
|
122
142
|
}
|
|
143
|
+
|
|
144
|
+
this.autoScrollSlideInterval = setInterval(this.autoScrollSlide, 5000);
|
|
123
145
|
},
|
|
124
146
|
|
|
125
147
|
};
|
|
@@ -127,7 +149,10 @@ export default {
|
|
|
127
149
|
</script>
|
|
128
150
|
|
|
129
151
|
<template>
|
|
130
|
-
<div
|
|
152
|
+
<div
|
|
153
|
+
class="slider"
|
|
154
|
+
:class="{'disable': sliders.length === 1}"
|
|
155
|
+
>
|
|
131
156
|
<div
|
|
132
157
|
id="slide-track"
|
|
133
158
|
ref="slider"
|
|
@@ -141,6 +166,7 @@ export default {
|
|
|
141
166
|
ref="slide"
|
|
142
167
|
:key="get(slide, keyField)"
|
|
143
168
|
class="slide"
|
|
169
|
+
:class="{'singleSlide': sliders.length === 1}"
|
|
144
170
|
:href="asLink ? get(slide, linkField) : null"
|
|
145
171
|
:target="get(slide, targetField)"
|
|
146
172
|
:rel="rel"
|
|
@@ -155,13 +181,16 @@ export default {
|
|
|
155
181
|
:label="slide.repoName"
|
|
156
182
|
color="slider-badge mb-20"
|
|
157
183
|
/>
|
|
158
|
-
<h1>{{ slide.chartNameDisplay }}</h1>
|
|
184
|
+
<h1>{{ slide.chartNameDisplay }} {{ i + 1 }}</h1>
|
|
159
185
|
<p>{{ slide.chartDescription }}</p>
|
|
160
186
|
</div>
|
|
161
187
|
</div>
|
|
162
188
|
</div>
|
|
163
189
|
</div>
|
|
164
|
-
<div
|
|
190
|
+
<div
|
|
191
|
+
class="controls"
|
|
192
|
+
:class="{'disable': sliders.length === 1}"
|
|
193
|
+
>
|
|
165
194
|
<div
|
|
166
195
|
v-for="(slide, i) in slider"
|
|
167
196
|
:key="i"
|
|
@@ -173,7 +202,7 @@ export default {
|
|
|
173
202
|
<div
|
|
174
203
|
ref="prev"
|
|
175
204
|
class="prev"
|
|
176
|
-
:class="
|
|
205
|
+
:class="{'disable': sliders.length === 1}"
|
|
177
206
|
@click="nextPrev('prev')"
|
|
178
207
|
>
|
|
179
208
|
<i class="icon icon-chevron-left icon-4x" />
|
|
@@ -181,7 +210,7 @@ export default {
|
|
|
181
210
|
<div
|
|
182
211
|
ref="next"
|
|
183
212
|
class="next"
|
|
184
|
-
:class="
|
|
213
|
+
:class="{'disable': sliders.length === 1}"
|
|
185
214
|
@click="nextPrev('next')"
|
|
186
215
|
>
|
|
187
216
|
<i class="icon icon-chevron-right icon-4x" />
|
|
@@ -197,7 +226,19 @@ export default {
|
|
|
197
226
|
place-items: center;
|
|
198
227
|
overflow: hidden;
|
|
199
228
|
margin-bottom: 30px;
|
|
200
|
-
min-width: 700px;
|
|
229
|
+
// min-width: 700px;
|
|
230
|
+
|
|
231
|
+
&.disable::before,
|
|
232
|
+
&.disable::after {
|
|
233
|
+
display: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
&.disable:hover {
|
|
237
|
+
.prev,
|
|
238
|
+
.next {
|
|
239
|
+
display: none;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
201
242
|
|
|
202
243
|
&:hover {
|
|
203
244
|
.prev,
|
|
@@ -212,6 +253,7 @@ export default {
|
|
|
212
253
|
animation: scrolls 10s ;
|
|
213
254
|
position: relative;
|
|
214
255
|
transition: 1s ease-in-out;
|
|
256
|
+
left: 21%;
|
|
215
257
|
}
|
|
216
258
|
|
|
217
259
|
.slider-badge {
|
|
@@ -226,13 +268,12 @@ export default {
|
|
|
226
268
|
position: relative;
|
|
227
269
|
border: 1px solid var(--tabbed-border);
|
|
228
270
|
border-radius: var(--border-radius);
|
|
229
|
-
left: 7%;
|
|
230
271
|
cursor: pointer;
|
|
231
272
|
|
|
232
|
-
|
|
233
|
-
|
|
273
|
+
&.singleSlide {
|
|
274
|
+
width: 100%;
|
|
275
|
+
max-width: 100%;
|
|
234
276
|
}
|
|
235
|
-
|
|
236
277
|
.slide-header {
|
|
237
278
|
background: var(--default);
|
|
238
279
|
width: 100%;
|
|
@@ -278,6 +319,9 @@ export default {
|
|
|
278
319
|
.slider::before {
|
|
279
320
|
left: 0;
|
|
280
321
|
top: 0;
|
|
322
|
+
&.disable {
|
|
323
|
+
display: none;
|
|
324
|
+
}
|
|
281
325
|
}
|
|
282
326
|
.slider::after{
|
|
283
327
|
right: -1px;
|
|
@@ -291,6 +335,10 @@ export default {
|
|
|
291
335
|
justify-content: center;
|
|
292
336
|
margin-top: 10px;
|
|
293
337
|
|
|
338
|
+
&.disable {
|
|
339
|
+
display: none;
|
|
340
|
+
}
|
|
341
|
+
|
|
294
342
|
.control-item {
|
|
295
343
|
width: 10px;
|
|
296
344
|
height: 10px;
|
|
@@ -3,15 +3,19 @@ import { Banner } from '@components/Banner';
|
|
|
3
3
|
import Loading from '@shell/components/Loading';
|
|
4
4
|
import { mapGetters } from 'vuex';
|
|
5
5
|
import { hasLeader, leaderChanges, failedProposals } from '@shell/utils/grafana';
|
|
6
|
+
import { CATALOG } from '@shell/config/types';
|
|
6
7
|
|
|
7
8
|
export default {
|
|
8
9
|
components: { Banner, Loading },
|
|
9
10
|
async fetch() {
|
|
10
|
-
const
|
|
11
|
+
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
12
|
+
const res = await this.$store.dispatch(`${ inStore }/find`, { type: CATALOG.APP, id: 'cattle-monitoring-system/rancher-monitoring' });
|
|
13
|
+
const monitoringVersion = res?.currentVersion;
|
|
14
|
+
const leader = await hasLeader(monitoringVersion, this.$store.dispatch, this.currentCluster.id);
|
|
11
15
|
|
|
12
16
|
this.hasLeader = leader ? this.t('generic.yes') : this.t('generic.no');
|
|
13
|
-
this.leaderChanges = await leaderChanges(this.$store.dispatch, this.currentCluster.id);
|
|
14
|
-
this.failedProposals = await failedProposals(this.$store.dispatch, this.currentCluster.id);
|
|
17
|
+
this.leaderChanges = await leaderChanges(monitoringVersion, this.$store.dispatch, this.currentCluster.id);
|
|
18
|
+
this.failedProposals = await failedProposals(monitoringVersion, this.$store.dispatch, this.currentCluster.id);
|
|
15
19
|
},
|
|
16
20
|
data() {
|
|
17
21
|
return {
|
|
@@ -114,7 +114,6 @@ export default {
|
|
|
114
114
|
labelKey: 'tableHeaders.role',
|
|
115
115
|
value: 'roleTemplate.nameDisplay'
|
|
116
116
|
},
|
|
117
|
-
{ ...AGE, value: 'createdTS' }
|
|
118
117
|
],
|
|
119
118
|
loadingProjectBindings: true,
|
|
120
119
|
loadingClusterBindings: true
|
|
@@ -185,7 +184,25 @@ export default {
|
|
|
185
184
|
};
|
|
186
185
|
});
|
|
187
186
|
|
|
188
|
-
|
|
187
|
+
// We need to group each of the TemplateRoleBindings by the user + project
|
|
188
|
+
const userRoles = [...fakeRows, ...this.filteredProjectRoleTemplateBindings].reduce((rows, curr) => {
|
|
189
|
+
const { userId, roleTemplate, projectId } = curr;
|
|
190
|
+
|
|
191
|
+
const userKey = userId + projectId;
|
|
192
|
+
|
|
193
|
+
if (!rows[userKey] && userId ) {
|
|
194
|
+
rows[userKey] = curr;
|
|
195
|
+
rows[userKey].allRoles = [];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (roleTemplate && userId) {
|
|
199
|
+
rows[userKey].allRoles.push(curr.roleTemplate);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return rows;
|
|
203
|
+
}, {});
|
|
204
|
+
|
|
205
|
+
return Object.values(userRoles);
|
|
189
206
|
},
|
|
190
207
|
canManageMembers() {
|
|
191
208
|
return canViewClusterPermissionsEditor(this.$store);
|
|
@@ -223,6 +240,26 @@ export default {
|
|
|
223
240
|
modalSticky: true
|
|
224
241
|
});
|
|
225
242
|
},
|
|
243
|
+
|
|
244
|
+
getProjectRoleBinding(row, role) {
|
|
245
|
+
// Each row is a combination of user and project
|
|
246
|
+
// So find the specfic roleBindingTemplate corresponding to the specific role + project
|
|
247
|
+
return this.projectRoleTemplateBindings.find(r => r.roleTemplateId === role.id && r.userId === row.userId);
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
async removeRole(row, role, event) {
|
|
251
|
+
const resource = this.getProjectRoleBinding(row, role);
|
|
252
|
+
|
|
253
|
+
await resource.promptRemove();
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
viewRoleInAPI(row, role) {
|
|
257
|
+
const resource = this.getProjectRoleBinding(row, role);
|
|
258
|
+
|
|
259
|
+
if (resource?.canViewInApi) {
|
|
260
|
+
resource.viewInApi();
|
|
261
|
+
}
|
|
262
|
+
},
|
|
226
263
|
slotName(project) {
|
|
227
264
|
return `main-row:${ project.id }`;
|
|
228
265
|
},
|
|
@@ -249,7 +286,7 @@ export default {
|
|
|
249
286
|
<Tabbed>
|
|
250
287
|
<Tab
|
|
251
288
|
name="cluster-membership"
|
|
252
|
-
label="
|
|
289
|
+
:label="t('members.clusterMemebership')"
|
|
253
290
|
>
|
|
254
291
|
<div
|
|
255
292
|
v-if="canEditClusterMembers"
|
|
@@ -266,7 +303,8 @@ export default {
|
|
|
266
303
|
:schema="schema"
|
|
267
304
|
:headers="headers"
|
|
268
305
|
:rows="filteredClusterRoleTemplateBindings"
|
|
269
|
-
:groupable="
|
|
306
|
+
:groupable="true"
|
|
307
|
+
:show-grouping="true"
|
|
270
308
|
:namespaced="false"
|
|
271
309
|
:loading="$fetchState.pending || !currentCluster || loadingClusterBindings"
|
|
272
310
|
sub-search="subSearch"
|
|
@@ -276,13 +314,15 @@ export default {
|
|
|
276
314
|
<Tab
|
|
277
315
|
v-if="canManageProjectMembers"
|
|
278
316
|
name="project-membership"
|
|
279
|
-
label="
|
|
317
|
+
:label="t('members.projectMembership')"
|
|
280
318
|
>
|
|
281
319
|
<SortableTable
|
|
282
320
|
group-by="projectId"
|
|
283
321
|
:loading="$fetchState.pending || !currentCluster || loadingProjectBindings"
|
|
284
322
|
:rows="rowsWithFakeProjects"
|
|
285
323
|
:headers="projectRoleTemplateColumns"
|
|
324
|
+
:table-actions="false"
|
|
325
|
+
:row-actions="false"
|
|
286
326
|
>
|
|
287
327
|
<template #group-by="group">
|
|
288
328
|
<div class="group-bar">
|
|
@@ -307,6 +347,31 @@ export default {
|
|
|
307
347
|
</div>
|
|
308
348
|
</div>
|
|
309
349
|
</template>
|
|
350
|
+
<template
|
|
351
|
+
#cell:role="{row}"
|
|
352
|
+
>
|
|
353
|
+
<span
|
|
354
|
+
v-for="(role, j) in row.allRoles"
|
|
355
|
+
:key="j"
|
|
356
|
+
|
|
357
|
+
ref="value"
|
|
358
|
+
:data-testid="`role-value-${j}`"
|
|
359
|
+
class="role"
|
|
360
|
+
>
|
|
361
|
+
<span
|
|
362
|
+
class="role-value"
|
|
363
|
+
:class="{'text-link-enabled' : row.canViewInApi}"
|
|
364
|
+
@click="viewRoleInAPI(row, role)"
|
|
365
|
+
>
|
|
366
|
+
{{ role.nameDisplay }}
|
|
367
|
+
</span>
|
|
368
|
+
<i
|
|
369
|
+
class="icon icon-close"
|
|
370
|
+
:data-testid="`role-values-close-${j}`"
|
|
371
|
+
@click="removeRole(row, role, $event)"
|
|
372
|
+
/>
|
|
373
|
+
</span>
|
|
374
|
+
</template>
|
|
310
375
|
<template
|
|
311
376
|
v-for="project in projectsWithoutRoles"
|
|
312
377
|
v-slot:[slotName(project)]
|
|
@@ -330,6 +395,36 @@ export default {
|
|
|
330
395
|
</template>
|
|
331
396
|
|
|
332
397
|
<style lang='scss' scoped>
|
|
398
|
+
|
|
399
|
+
.role {
|
|
400
|
+
align-items: center;
|
|
401
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
402
|
+
border: 1px solid var(--header-border);
|
|
403
|
+
border-radius: 5px;
|
|
404
|
+
color: var(--tag-text);
|
|
405
|
+
line-height: 20px;
|
|
406
|
+
padding: 2px 5px;
|
|
407
|
+
white-space: nowrap;
|
|
408
|
+
display: inline-flex;
|
|
409
|
+
margin-right: 3px;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.role-value {
|
|
413
|
+
&.text-link-enabled {
|
|
414
|
+
cursor: pointer;
|
|
415
|
+
&:hover {
|
|
416
|
+
color: var(--primary);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
+ .icon-close {
|
|
420
|
+
margin-left: 3px;
|
|
421
|
+
cursor: pointer;
|
|
422
|
+
&:hover {
|
|
423
|
+
color: var(--primary);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
333
428
|
.project-members {
|
|
334
429
|
& ::v-deep .group-bar{
|
|
335
430
|
display: flex;
|
|
@@ -4,7 +4,7 @@ import ResourceTable from '@shell/components/ResourceTable';
|
|
|
4
4
|
import { STATE, AGE, NAME } from '@shell/config/table-headers';
|
|
5
5
|
import { uniq } from '@shell/utils/array';
|
|
6
6
|
import { MANAGEMENT, NAMESPACE, VIRTUAL_TYPES } from '@shell/config/types';
|
|
7
|
-
import { PROJECT_ID } from '@shell/config/query-params';
|
|
7
|
+
import { PROJECT_ID, FLAT_VIEW } from '@shell/config/query-params';
|
|
8
8
|
import Masthead from '@shell/components/ResourceList/Masthead';
|
|
9
9
|
import { mapPref, GROUP_RESOURCES, ALL_NAMESPACES } from '@shell/store/prefs';
|
|
10
10
|
import MoveModal from '@shell/components/MoveModal';
|
|
@@ -236,6 +236,9 @@ export default {
|
|
|
236
236
|
|
|
237
237
|
notInProjectKey() {
|
|
238
238
|
return this.$store.getters['i18n/t']('resourceTable.groupLabel.notInAProject');
|
|
239
|
+
},
|
|
240
|
+
showCreateNsButton() {
|
|
241
|
+
return this.groupPreference !== 'namespace';
|
|
239
242
|
}
|
|
240
243
|
},
|
|
241
244
|
methods: {
|
|
@@ -284,6 +287,21 @@ export default {
|
|
|
284
287
|
|
|
285
288
|
return location;
|
|
286
289
|
},
|
|
290
|
+
|
|
291
|
+
createNamespaceLocationFlatList() {
|
|
292
|
+
const location = this.createNamespaceLocationOverride ? { ...this.createNamespaceLocationOverride } : {
|
|
293
|
+
name: 'c-cluster-product-resource-create',
|
|
294
|
+
params: {
|
|
295
|
+
product: this.$store.getters['currentProduct']?.name,
|
|
296
|
+
resource: NAMESPACE
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
location.query = { [FLAT_VIEW]: true };
|
|
301
|
+
|
|
302
|
+
return location;
|
|
303
|
+
},
|
|
304
|
+
|
|
287
305
|
showProjectAction(event, group) {
|
|
288
306
|
const project = group.rows[0].project;
|
|
289
307
|
|
|
@@ -343,7 +361,19 @@ export default {
|
|
|
343
361
|
:show-incremental-loading-indicator="showIncrementalLoadingIndicator"
|
|
344
362
|
:load-resources="loadResources"
|
|
345
363
|
:load-indeterminate="loadIndeterminate"
|
|
346
|
-
|
|
364
|
+
>
|
|
365
|
+
<template
|
|
366
|
+
v-if="showCreateNsButton"
|
|
367
|
+
slot="extraActions"
|
|
368
|
+
>
|
|
369
|
+
<n-link
|
|
370
|
+
:to="createNamespaceLocationFlatList()"
|
|
371
|
+
class="btn role-primary mr-10"
|
|
372
|
+
>
|
|
373
|
+
{{ t('projectNamespaces.createNamespace') }}
|
|
374
|
+
</n-link>
|
|
375
|
+
</template>
|
|
376
|
+
</Masthead>
|
|
347
377
|
<ResourceTable
|
|
348
378
|
ref="table"
|
|
349
379
|
class="table"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import Loading from '@shell/components/Loading';
|
|
3
3
|
import { Banner } from '@components/Banner';
|
|
4
4
|
import { computeDashboardUrl } from '@shell/utils/grafana';
|
|
5
|
+
import { CATALOG } from '@shell/config/types';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
7
8
|
components: { Banner, Loading },
|
|
@@ -31,9 +32,15 @@ export default {
|
|
|
31
32
|
default: 'dark'
|
|
32
33
|
}
|
|
33
34
|
},
|
|
35
|
+
async fetch() {
|
|
36
|
+
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
37
|
+
const res = await this.$store.dispatch(`${ inStore }/find`, { type: CATALOG.APP, id: 'cattle-monitoring-system/rancher-monitoring' });
|
|
38
|
+
|
|
39
|
+
this.monitoringVersion = res?.currentVersion;
|
|
40
|
+
},
|
|
34
41
|
data() {
|
|
35
42
|
return {
|
|
36
|
-
loading: false, error: false, interval: null, initialUrl: this.computeUrl(), errorTimer: null
|
|
43
|
+
loading: false, error: false, interval: null, initialUrl: this.computeUrl(), errorTimer: null, monitoringVersion: null
|
|
37
44
|
};
|
|
38
45
|
},
|
|
39
46
|
computed: {
|
|
@@ -131,7 +138,7 @@ export default {
|
|
|
131
138
|
const clusterId = this.$store.getters['currentCluster'].id;
|
|
132
139
|
const params = this.computeParams();
|
|
133
140
|
|
|
134
|
-
return computeDashboardUrl(embedUrl, clusterId, params);
|
|
141
|
+
return computeDashboardUrl(this.monitoringVersion, embedUrl, clusterId, params);
|
|
135
142
|
},
|
|
136
143
|
computeParams() {
|
|
137
144
|
const params = {};
|
|
@@ -7,7 +7,6 @@ import { removeObject } from '@shell/utils/array';
|
|
|
7
7
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
8
8
|
import AsyncButton, { ASYNC_BUTTON_STATES } from '@shell/components/AsyncButton';
|
|
9
9
|
import ActionDropdown from '@shell/components/ActionDropdown';
|
|
10
|
-
import $ from 'jquery';
|
|
11
10
|
import throttle from 'lodash/throttle';
|
|
12
11
|
import debounce from 'lodash/debounce';
|
|
13
12
|
import THead from './THead';
|
|
@@ -19,6 +18,8 @@ import grouping from './grouping';
|
|
|
19
18
|
import actions from './actions';
|
|
20
19
|
import AdvancedFiltering from './advanced-filtering';
|
|
21
20
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
21
|
+
import { getParent } from '@shell/utils/dom';
|
|
22
|
+
|
|
22
23
|
// Uncomment for table performance debugging
|
|
23
24
|
// import tableDebug from './debug';
|
|
24
25
|
|
|
@@ -340,10 +341,10 @@ export default {
|
|
|
340
341
|
}, 200);
|
|
341
342
|
|
|
342
343
|
// Add scroll listener to the main element
|
|
343
|
-
const $main =
|
|
344
|
+
const $main = document.querySelector('main');
|
|
344
345
|
|
|
345
346
|
this._onScroll = this.onScroll.bind(this);
|
|
346
|
-
$main
|
|
347
|
+
$main?.addEventListener('scroll', this._onScroll);
|
|
347
348
|
},
|
|
348
349
|
|
|
349
350
|
beforeDestroy() {
|
|
@@ -354,9 +355,9 @@ export default {
|
|
|
354
355
|
clearTimeout(this._delayedColumnsTimer);
|
|
355
356
|
clearTimeout(this.manualRefreshTimer);
|
|
356
357
|
|
|
357
|
-
const $main =
|
|
358
|
+
const $main = document.querySelector('main');
|
|
358
359
|
|
|
359
|
-
$main
|
|
360
|
+
$main?.removeEventListener('scroll', this._onScroll);
|
|
360
361
|
},
|
|
361
362
|
|
|
362
363
|
watch: {
|
|
@@ -817,13 +818,12 @@ export default {
|
|
|
817
818
|
},
|
|
818
819
|
|
|
819
820
|
nearestCheckbox() {
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
return $cur[0];
|
|
821
|
+
return document.activeElement.closest('tr.main-row')?.querySelector('.checkbox-custom');
|
|
823
822
|
},
|
|
824
823
|
|
|
825
824
|
focusAdjacent(next = true) {
|
|
826
|
-
const all =
|
|
825
|
+
const all = Array.from(this.$el.querySelectorAll('.checkbox-custom'));
|
|
826
|
+
|
|
827
827
|
const cur = this.nearestCheckbox();
|
|
828
828
|
let idx = -1;
|
|
829
829
|
|
|
@@ -837,10 +837,14 @@ export default {
|
|
|
837
837
|
|
|
838
838
|
if ( idx < 1 ) { // Don't go up to the check all button
|
|
839
839
|
idx = 1;
|
|
840
|
+
|
|
841
|
+
return null;
|
|
840
842
|
}
|
|
841
843
|
|
|
842
844
|
if ( idx >= all.length ) {
|
|
843
845
|
idx = all.length - 1;
|
|
846
|
+
|
|
847
|
+
return null;
|
|
844
848
|
}
|
|
845
849
|
|
|
846
850
|
if ( all[idx] ) {
|
|
@@ -852,14 +856,22 @@ export default {
|
|
|
852
856
|
|
|
853
857
|
focusNext: throttle(function(event, more = false) {
|
|
854
858
|
const elem = this.focusAdjacent(true);
|
|
855
|
-
const row =
|
|
859
|
+
const row = getParent(elem, 'tr');
|
|
860
|
+
|
|
861
|
+
if (row?.classList.contains('row-selected')) {
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
856
864
|
|
|
857
865
|
this.keySelectRow(row, more);
|
|
858
866
|
}, 50),
|
|
859
867
|
|
|
860
868
|
focusPrevious: throttle(function(event, more = false) {
|
|
861
869
|
const elem = this.focusAdjacent(false);
|
|
862
|
-
const row =
|
|
870
|
+
const row = getParent(elem, 'tr');
|
|
871
|
+
|
|
872
|
+
if (row?.classList.contains('row-selected')) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
863
875
|
|
|
864
876
|
this.keySelectRow(row, more);
|
|
865
877
|
}, 50),
|