@rancher/shell 0.3.15 → 0.3.17
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/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +70 -15
- package/assets/translations/zh-hans.yaml +155 -33
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/cloud-credential/generic.vue +1 -1
- package/components/BannerGraphic.vue +1 -0
- package/components/CommunityLinks.vue +1 -0
- package/components/CruResource.vue +1 -1
- package/components/EmberPage.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/GrafanaDashboard.vue +7 -1
- package/components/ResourceDetail/index.vue +4 -12
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/SimpleBox.vue +1 -0
- package/components/SortableTable/index.vue +5 -1
- package/components/YamlEditor.vue +1 -0
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/form/GitPicker.vue +1 -1
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +8 -3
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/nav/Header.vue +2 -2
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +5 -1
- package/config/product/auth.js +1 -1
- package/config/router.js +0 -9
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +20 -12
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +17 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/catalog.cattle.io.clusterrepo.vue +8 -1
- package/detail/node.vue +6 -6
- package/detail/pod.vue +2 -6
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +9 -9
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +56 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +8 -3
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +52 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +330 -150
- package/edit/ui.cattle.io.navlink.vue +2 -1
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +93 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/package.json +3 -3
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +10 -0
- package/pages/auth/logout.vue +11 -3
- package/pages/auth/setup.vue +4 -0
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- package/pages/c/_cluster/auth/roles/index.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +1 -10
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +155 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +10 -5
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/resource-class.js +35 -2
- package/plugins/plugin.js +9 -1
- package/plugins/steve/actions.js +22 -0
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +92 -58
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +1 -0
- package/server/server-middleware.js +4 -12
- package/store/index.js +13 -0
- package/store/prefs.js +0 -3
- package/store/type-map.js +17 -29
- package/types/shell/index.d.ts +243 -90
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/settings.ts +2 -2
- package/vue.config.js +3 -2
- package/pages/safeMode.vue +0 -17
- package/rancher-components/components/BadgeState/BadgeState.spec.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -63
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -420
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -23
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -355
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -287
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -254
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -170
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -149
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -151
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -484
- package/rancher-components/components/StringList/StringList.vue +0 -611
- package/rancher-components/components/StringList/index.ts +0 -1
- /package/rancher-components/{components/Card → Card}/Card.test.ts +0 -0
- /package/rancher-components/{components/Form → Form}/Radio/RadioButton.test.ts +0 -0
|
@@ -154,6 +154,9 @@ export default {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
return 'none';
|
|
157
|
+
},
|
|
158
|
+
updatePageValid(update) {
|
|
159
|
+
this.$emit('valid', update);
|
|
157
160
|
}
|
|
158
161
|
},
|
|
159
162
|
get
|
|
@@ -189,6 +192,7 @@ export default {
|
|
|
189
192
|
:value="value.s3"
|
|
190
193
|
:secrets="secrets"
|
|
191
194
|
:mode="mode"
|
|
195
|
+
@valid="updatePageValid($event)"
|
|
192
196
|
/>
|
|
193
197
|
<template v-else>
|
|
194
198
|
<div class="row">
|
|
@@ -33,7 +33,7 @@ export default {
|
|
|
33
33
|
for ( const k of keyOptions ) {
|
|
34
34
|
const sk = simplify(k);
|
|
35
35
|
|
|
36
|
-
if ( normanSchema || likelyFields.includes(sk) || iffyFields.includes(sk) ) {
|
|
36
|
+
if ( normanSchema?.resourceFields || likelyFields.includes(sk) || iffyFields.includes(sk) ) {
|
|
37
37
|
keys.push(k);
|
|
38
38
|
}
|
|
39
39
|
}
|
package/components/EmberPage.vue
CHANGED
|
@@ -252,6 +252,7 @@ export default {
|
|
|
252
252
|
if (iframeEl === null) {
|
|
253
253
|
iframeEl = document.createElement('iframe');
|
|
254
254
|
iframeEl.setAttribute('id', EMBER_FRAME);
|
|
255
|
+
iframeEl.setAttribute('data-testid', EMBER_FRAME);
|
|
255
256
|
iframeEl.classList.add(EMBER_FRAME_HIDE_CLASS);
|
|
256
257
|
|
|
257
258
|
if (this.inline) {
|
package/components/FileDiff.vue
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
2
|
+
import { Diff2HtmlUI } from 'diff2html/lib/ui/js/diff2html-ui-slim.js';
|
|
3
|
+
|
|
3
4
|
import { createPatch } from 'diff';
|
|
4
5
|
|
|
5
6
|
export default {
|
|
@@ -38,36 +39,40 @@ export default {
|
|
|
38
39
|
}
|
|
39
40
|
},
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
mounted() {
|
|
43
|
+
this.draw();
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
watch: {
|
|
47
|
+
sideBySide() {
|
|
48
|
+
this.draw();
|
|
49
|
+
}
|
|
50
|
+
},
|
|
46
51
|
|
|
52
|
+
methods: {
|
|
53
|
+
draw() {
|
|
54
|
+
const targetElement = document.getElementById('diffElement');
|
|
47
55
|
const patch = createPatch(
|
|
48
56
|
this.filename,
|
|
49
57
|
this.orig,
|
|
50
58
|
this.neu
|
|
51
59
|
);
|
|
60
|
+
const configuration = {
|
|
61
|
+
// UI
|
|
62
|
+
synchronisedScroll: true,
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
matching,
|
|
65
|
-
synchronizedScroll: true,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
},
|
|
64
|
+
// Base
|
|
65
|
+
outputFormat: this.sideBySide ? 'side-by-side' : 'line-by-line',
|
|
66
|
+
drawFileList: false,
|
|
67
|
+
matching: 'words',
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const diff2htmlUi = new Diff2HtmlUI(targetElement, patch, configuration);
|
|
71
|
+
|
|
72
|
+
diff2htmlUi.draw();
|
|
73
|
+
this.fit();
|
|
74
|
+
},
|
|
69
75
|
|
|
70
|
-
methods: {
|
|
71
76
|
fit() {
|
|
72
77
|
if ( !this.autoResize ) {
|
|
73
78
|
return;
|
|
@@ -97,8 +102,8 @@ export default {
|
|
|
97
102
|
<div>
|
|
98
103
|
<resize-observer @notify="fit" />
|
|
99
104
|
<div
|
|
105
|
+
id="diffElement"
|
|
100
106
|
ref="root"
|
|
101
|
-
v-clean-html="html"
|
|
102
107
|
class="root"
|
|
103
108
|
/>
|
|
104
109
|
</div>
|
|
@@ -112,66 +117,68 @@ export default {
|
|
|
112
117
|
}
|
|
113
118
|
</style>
|
|
114
119
|
|
|
115
|
-
<style lang="scss">
|
|
116
|
-
@import 'node_modules/diff2html/
|
|
117
|
-
|
|
118
|
-
.d2h-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.d2h-code-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
120
|
+
<style scoped lang="scss">
|
|
121
|
+
@import 'node_modules/diff2html/bundles/css/diff2html.min.css';
|
|
122
|
+
|
|
123
|
+
::v-deep .d2h-wrapper {
|
|
124
|
+
.d2h-file-header {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.d2h-file-wrapper {
|
|
129
|
+
border-color: var(--diff-border);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.d2h-diff-table {
|
|
133
|
+
font-family: Menlo,Consolas,monospace;
|
|
134
|
+
font-size: 13px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.d2h-emptyplaceholder, .d2h-code-side-emptyplaceholder {
|
|
138
|
+
border-color: var(--diff-linenum-border);
|
|
139
|
+
background-color: var(--diff-empty-placeholder);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.d2h-code-linenumber,
|
|
143
|
+
.d2h-code-side-linenumber {
|
|
144
|
+
background-color: var(--diff-linenum-bg);
|
|
145
|
+
color: var(--diff-linenum);
|
|
146
|
+
border-color: var(--diff-linenum-border);
|
|
147
|
+
border-left: 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.d2h-code-line del,.d2h-code-side-line del {
|
|
151
|
+
background-color: var(--diff-line-del-bg);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.d2h-code-line ins,.d2h-code-side-line ins {
|
|
155
|
+
background-color: var(--diff-line-ins-bg);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.d2h-del {
|
|
159
|
+
background-color: var(--diff-del-bg);
|
|
160
|
+
border-color: var(--diff-del-border);
|
|
161
|
+
color: var(--body-text);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.d2h-ins {
|
|
165
|
+
background-color: var(--diff-ins-bg);
|
|
166
|
+
border-color: var(--diff-ins-border);
|
|
167
|
+
color: var(--body-text);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.d2h-info {
|
|
171
|
+
background-color: var(--diff-header-bg);
|
|
172
|
+
color: var(--diff-header);
|
|
173
|
+
border-color: var(--diff-header-border);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.d2h-file-diff .d2h-del.d2h-change {
|
|
177
|
+
background-color: var(--diff-chg-del);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.d2h-file-diff .d2h-ins.d2h-change {
|
|
181
|
+
background-color: var(--diff-chg-ins);
|
|
182
|
+
}
|
|
176
183
|
}
|
|
177
184
|
</style>
|
|
@@ -259,10 +259,16 @@ export default {
|
|
|
259
259
|
v-if="!loading && !error"
|
|
260
260
|
class="external-link"
|
|
261
261
|
>
|
|
262
|
+
<!-- https://github.com/harvester/harvester-installer/pull/512/files -->
|
|
263
|
+
<!-- It is necessary to include the parameter referer when accessing the Grafana page. -->
|
|
264
|
+
<!-- This parameter is required by the backend to identify the origin of the request from which cluster -->
|
|
265
|
+
<!-- The matching mechanism as follows: -->
|
|
266
|
+
<!-- ~.*/k8s/clusters/(c-m-.+)/.* -->
|
|
267
|
+
<!-- ~.*/dashboard/harvester/c/(c-m-.+)/.* -->
|
|
262
268
|
<a
|
|
263
269
|
:href="grafanaUrl"
|
|
264
270
|
target="_blank"
|
|
265
|
-
rel="noopener
|
|
271
|
+
rel="noopener nofollow"
|
|
266
272
|
>{{ t('grafanaDashboard.grafana') }} <i class="icon icon-external-link" /></a>
|
|
267
273
|
</div>
|
|
268
274
|
</div>
|
|
@@ -193,6 +193,9 @@ export default {
|
|
|
193
193
|
opt: { watch: true }
|
|
194
194
|
});
|
|
195
195
|
} catch (e) {
|
|
196
|
+
if (e.status === 404 || e.status === 403) {
|
|
197
|
+
store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceIdNotFound', { resource, fqid }, true)));
|
|
198
|
+
}
|
|
196
199
|
liveModel = {};
|
|
197
200
|
notFound = fqid;
|
|
198
201
|
}
|
|
@@ -367,18 +370,7 @@ export default {
|
|
|
367
370
|
</script>
|
|
368
371
|
|
|
369
372
|
<template>
|
|
370
|
-
<Loading v-if="$fetchState.pending" />
|
|
371
|
-
<div v-else-if="notFound">
|
|
372
|
-
<IconMessage icon="icon-warning">
|
|
373
|
-
<template v-slot:message>
|
|
374
|
-
{{ t('generic.notFound') }}
|
|
375
|
-
<div>
|
|
376
|
-
<div>{{ t('generic.type') }}: {{ resource }}</div>
|
|
377
|
-
<div>{{ t('generic.id') }}: {{ notFound }}</div>
|
|
378
|
-
</div>
|
|
379
|
-
</template>
|
|
380
|
-
</IconMessage>
|
|
381
|
-
</div>
|
|
373
|
+
<Loading v-if="$fetchState.pending || notFound" />
|
|
382
374
|
<div v-else>
|
|
383
375
|
<Masthead
|
|
384
376
|
v-if="showMasthead"
|
|
@@ -70,7 +70,7 @@ export default {
|
|
|
70
70
|
|
|
71
71
|
if ( !this.hasFetch ) {
|
|
72
72
|
if ( !schema ) {
|
|
73
|
-
store.dispatch('loadingError', new Error(
|
|
73
|
+
store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceListNotFound', { resource }, true)));
|
|
74
74
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
@@ -4,8 +4,9 @@ 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 { NAMESPACE } from '@shell/config/table-headers';
|
|
7
|
+
import { NAMESPACE, AGE } from '@shell/config/table-headers';
|
|
8
8
|
import { findBy } from '@shell/utils/array';
|
|
9
|
+
import { ExtensionPoint, TableColumnLocation } from '@shell/core/types';
|
|
9
10
|
|
|
10
11
|
// Default group-by in the case the group stored in the preference does not apply
|
|
11
12
|
const DEFAULT_GROUP = 'namespace';
|
|
@@ -57,6 +58,12 @@ export default {
|
|
|
57
58
|
required: false
|
|
58
59
|
},
|
|
59
60
|
|
|
61
|
+
keyField: {
|
|
62
|
+
// Field that is unique for each row.
|
|
63
|
+
type: String,
|
|
64
|
+
default: '_key',
|
|
65
|
+
},
|
|
66
|
+
|
|
60
67
|
headers: {
|
|
61
68
|
type: Array,
|
|
62
69
|
default: null,
|
|
@@ -216,6 +223,7 @@ export default {
|
|
|
216
223
|
_headers() {
|
|
217
224
|
let headers;
|
|
218
225
|
const showNamespace = this.showNamespaceColumn;
|
|
226
|
+
const type = this.schema?.id || this.$route?.params?.resource || undefined;
|
|
219
227
|
|
|
220
228
|
if ( this.headers ) {
|
|
221
229
|
headers = this.headers.slice();
|
|
@@ -223,6 +231,46 @@ export default {
|
|
|
223
231
|
headers = this.$store.getters['type-map/headersFor'](this.schema);
|
|
224
232
|
}
|
|
225
233
|
|
|
234
|
+
// add custom table columns provided by the extensions ExtensionPoint.TABLE_COL hook
|
|
235
|
+
// gate it so that we prevent errors on older versions of dashboard
|
|
236
|
+
if (this.$store.$plugin?.getUIConfig) {
|
|
237
|
+
const extensionCols = this.$store.$plugin.getUIConfig(ExtensionPoint.TABLE_COL, TableColumnLocation.RESOURCE);
|
|
238
|
+
|
|
239
|
+
// Try and insert the columns before the Age column
|
|
240
|
+
let insertPosition = headers.length;
|
|
241
|
+
|
|
242
|
+
if (headers.length > 0) {
|
|
243
|
+
const ageColIndex = headers.findIndex((h) => h.name === AGE.name);
|
|
244
|
+
|
|
245
|
+
if (ageColIndex >= 0) {
|
|
246
|
+
insertPosition = ageColIndex;
|
|
247
|
+
} else {
|
|
248
|
+
// we've found some labels with ' ', which isn't necessarily empty (explore action/button)
|
|
249
|
+
// if we are to add cols, let's push them before these so that the UI doesn't look weird
|
|
250
|
+
const lastViableColIndex = headers.findIndex((h) => (!h.label || !h.label?.trim()) && (!h.labelKey || !h.labelKey?.trim()));
|
|
251
|
+
|
|
252
|
+
if (lastViableColIndex >= 0) {
|
|
253
|
+
insertPosition = lastViableColIndex;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// adding extension defined cols to the correct header config
|
|
259
|
+
extensionCols.forEach((col) => {
|
|
260
|
+
if (col.locationConfig.resource) {
|
|
261
|
+
col.locationConfig.resource.forEach((resource) => {
|
|
262
|
+
if (resource && type === resource) {
|
|
263
|
+
// we need the 'value' prop to be populated in order for the rows to show the values
|
|
264
|
+
if (!col.value && col.getValue) {
|
|
265
|
+
col.value = col.getValue;
|
|
266
|
+
}
|
|
267
|
+
headers.splice(insertPosition, 0, col);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
226
274
|
// If only one namespace is selected, hide the namespace column
|
|
227
275
|
if ( !showNamespace ) {
|
|
228
276
|
const idx = headers.findIndex((header) => header.name === NAMESPACE.name);
|
|
@@ -447,7 +495,7 @@ export default {
|
|
|
447
495
|
:has-advanced-filtering="hasAdvancedFiltering"
|
|
448
496
|
:adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
|
|
449
497
|
:adv-filter-prevent-filtering-labels="advFilterPreventFilteringLabels"
|
|
450
|
-
key-field="
|
|
498
|
+
:key-field="keyField"
|
|
451
499
|
:sort-generation-fn="safeSortGenerationFn"
|
|
452
500
|
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
453
501
|
:force-update-live-and-delayed="forceUpdateLiveAndDelayed"
|
package/components/SimpleBox.vue
CHANGED
|
@@ -903,7 +903,10 @@ export default {
|
|
|
903
903
|
</script>
|
|
904
904
|
|
|
905
905
|
<template>
|
|
906
|
-
<div
|
|
906
|
+
<div
|
|
907
|
+
ref="container"
|
|
908
|
+
data-testid="cluster-list-container"
|
|
909
|
+
>
|
|
907
910
|
<div
|
|
908
911
|
:class="{'titled': $slots.title && $slots.title.length}"
|
|
909
912
|
class="sortable-table-header"
|
|
@@ -1001,6 +1004,7 @@ export default {
|
|
|
1001
1004
|
<div
|
|
1002
1005
|
v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || ($slots['header-right'] && $slots['header-right'].length)"
|
|
1003
1006
|
class="search row"
|
|
1007
|
+
data-testid="search-box-filter-row"
|
|
1004
1008
|
>
|
|
1005
1009
|
<ul
|
|
1006
1010
|
v-if="hasAdvancedFiltering"
|
|
@@ -357,7 +357,7 @@ export default Vue.extend<Data, any, any, any>({
|
|
|
357
357
|
<div class="spacer">
|
|
358
358
|
<LabeledInput
|
|
359
359
|
v-model="selectedAccOrOrg"
|
|
360
|
-
data-testid="
|
|
360
|
+
data-testid="git_picker-username-or-org"
|
|
361
361
|
:tooltip="t(`gitPicker.${ type }.username.tooltip`)"
|
|
362
362
|
:label="t(`gitPicker.${ type }.username.inputLabel`)"
|
|
363
363
|
:required="true"
|
|
@@ -8,16 +8,7 @@ import { DESCRIPTION } from '@shell/config/labels-annotations';
|
|
|
8
8
|
import { _VIEW, _EDIT, _CREATE } from '@shell/config/query-params';
|
|
9
9
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
10
10
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
11
|
-
|
|
12
|
-
export function normalizeName(str) {
|
|
13
|
-
return (str || '')
|
|
14
|
-
.trim()
|
|
15
|
-
.toLowerCase()
|
|
16
|
-
.replace(/\s+/g, '-')
|
|
17
|
-
.replace(/-+/g, '-')
|
|
18
|
-
.replace(/^-+/, '')
|
|
19
|
-
.replace(/-+$/, '');
|
|
20
|
-
}
|
|
11
|
+
import { normalizeName } from '@shell/utils/kube';
|
|
21
12
|
|
|
22
13
|
export default {
|
|
23
14
|
name: 'NameNsDescription',
|
|
@@ -101,10 +92,20 @@ export default {
|
|
|
101
92
|
type: Boolean,
|
|
102
93
|
default: false
|
|
103
94
|
},
|
|
95
|
+
/**
|
|
96
|
+
* Use these objects instead of namespaces
|
|
97
|
+
*/
|
|
104
98
|
namespacesOverride: {
|
|
105
99
|
type: Array,
|
|
106
100
|
default: null,
|
|
107
101
|
},
|
|
102
|
+
/**
|
|
103
|
+
* User these namespaces instead of determining list within component
|
|
104
|
+
*/
|
|
105
|
+
namespaceOptions: {
|
|
106
|
+
type: Array,
|
|
107
|
+
default: null,
|
|
108
|
+
},
|
|
108
109
|
createNamespaceOverride: {
|
|
109
110
|
type: Boolean,
|
|
110
111
|
default: false,
|
|
@@ -228,8 +229,23 @@ export default {
|
|
|
228
229
|
* Map namespaces from the store to options, adding divider and create button
|
|
229
230
|
*/
|
|
230
231
|
options() {
|
|
231
|
-
|
|
232
|
-
|
|
232
|
+
let namespaces;
|
|
233
|
+
|
|
234
|
+
if (this.namespacesOverride) {
|
|
235
|
+
// Use the resources provided
|
|
236
|
+
namespaces = this.namespacesOverride;
|
|
237
|
+
} else {
|
|
238
|
+
if (this.namespaceOptions) {
|
|
239
|
+
// Use the namespaces provided
|
|
240
|
+
namespaces = (this.namespaceOptions.map((ns) => ns.name) || []).sort();
|
|
241
|
+
} else {
|
|
242
|
+
// Determine the namespaces
|
|
243
|
+
const namespaceObjs = this.isCreate ? this.allowedNamespaces() : this.namespaces();
|
|
244
|
+
|
|
245
|
+
namespaces = Object.keys(namespaceObjs);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
233
249
|
const options = namespaces
|
|
234
250
|
.map((namespace) => ({ nameDisplay: namespace, id: namespace }))
|
|
235
251
|
.map(this.namespaceMapper || ((obj) => ({
|
|
@@ -156,7 +156,7 @@ export default {
|
|
|
156
156
|
},
|
|
157
157
|
|
|
158
158
|
priorityDisplay(term) {
|
|
159
|
-
return
|
|
159
|
+
return 'weight' in term ? this.t('workload.scheduling.affinity.preferred') : this.t('workload.scheduling.affinity.required');
|
|
160
160
|
},
|
|
161
161
|
|
|
162
162
|
updateExpressions(row, expressions) {
|
|
@@ -212,7 +212,7 @@ export default {
|
|
|
212
212
|
/>
|
|
213
213
|
</div>
|
|
214
214
|
<div
|
|
215
|
-
v-if="props.row.value
|
|
215
|
+
v-if="'weight' in props.row.value"
|
|
216
216
|
class="col span-3"
|
|
217
217
|
>
|
|
218
218
|
<LabeledInput
|
|
@@ -286,7 +286,7 @@ export default {
|
|
|
286
286
|
},
|
|
287
287
|
|
|
288
288
|
priorityDisplay(term) {
|
|
289
|
-
return
|
|
289
|
+
return 'weight' in term ? this.t('workload.scheduling.affinity.preferred') : this.t('workload.scheduling.affinity.required');
|
|
290
290
|
},
|
|
291
291
|
|
|
292
292
|
changeNamespaceMode(val, term, idx) {
|
|
@@ -340,6 +340,11 @@ export default {
|
|
|
340
340
|
this.queueUpdate();
|
|
341
341
|
},
|
|
342
342
|
|
|
343
|
+
updateLabelSelector(e, props) {
|
|
344
|
+
this.set(props.row.value, 'labelSelector.matchExpressions', e);
|
|
345
|
+
this.queueUpdate();
|
|
346
|
+
},
|
|
347
|
+
|
|
343
348
|
isEmpty,
|
|
344
349
|
get,
|
|
345
350
|
set
|
|
@@ -431,7 +436,7 @@ export default {
|
|
|
431
436
|
:value="get(props.row.value, 'labelSelector.matchExpressions')"
|
|
432
437
|
:show-remove="false"
|
|
433
438
|
:data-testid="`pod-affinity-expressions-index${props.i}`"
|
|
434
|
-
@input="e=>
|
|
439
|
+
@input="e=>updateLabelSelector(e, props)"
|
|
435
440
|
/>
|
|
436
441
|
<div class="row mt-20">
|
|
437
442
|
<div class="col span-9">
|
|
@@ -463,7 +468,7 @@ export default {
|
|
|
463
468
|
/>
|
|
464
469
|
</div>
|
|
465
470
|
<div
|
|
466
|
-
v-if="props.row.value
|
|
471
|
+
v-if="'weight' in props.row.value"
|
|
467
472
|
class="col span-3"
|
|
468
473
|
>
|
|
469
474
|
<LabeledInput
|
|
@@ -13,6 +13,7 @@ import { _VIEW } from '@shell/config/query-params';
|
|
|
13
13
|
import RelatedResources from '@shell/components/RelatedResources';
|
|
14
14
|
import { ExtensionPoint, TabLocation } from '@shell/core/types';
|
|
15
15
|
import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
|
|
16
|
+
import { isConditionReadyAndWaiting } from '@shell/plugins/dashboard-store/resource-class';
|
|
16
17
|
|
|
17
18
|
export default {
|
|
18
19
|
|
|
@@ -60,6 +61,11 @@ export default {
|
|
|
60
61
|
needRelated: {
|
|
61
62
|
type: Boolean,
|
|
62
63
|
default: true
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
extensionParams: {
|
|
67
|
+
type: Object,
|
|
68
|
+
default: null
|
|
63
69
|
}
|
|
64
70
|
},
|
|
65
71
|
|
|
@@ -71,7 +77,7 @@ export default {
|
|
|
71
77
|
allEvents: [],
|
|
72
78
|
selectedTab: this.defaultTab,
|
|
73
79
|
didLoadEvents: false,
|
|
74
|
-
extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.RESOURCE_DETAIL, this.$route),
|
|
80
|
+
extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.RESOURCE_DETAIL, this.$route, this, this.extensionParams),
|
|
75
81
|
};
|
|
76
82
|
},
|
|
77
83
|
|
|
@@ -140,7 +146,7 @@ export default {
|
|
|
140
146
|
},
|
|
141
147
|
conditionsHaveIssues() {
|
|
142
148
|
if (this.showConditions) {
|
|
143
|
-
return this.value.status?.conditions?.some((cond) => cond.error);
|
|
149
|
+
return this.value.status?.conditions?.filter((cond) => !isConditionReadyAndWaiting(cond)).some((cond) => cond.error);
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
return false;
|
|
@@ -134,11 +134,27 @@ export default {
|
|
|
134
134
|
|
|
135
135
|
return true;
|
|
136
136
|
},
|
|
137
|
+
/**
|
|
138
|
+
* Get a unique value to represent the option
|
|
139
|
+
*/
|
|
137
140
|
getOptionKey(opt) {
|
|
141
|
+
// Use the property from a component level key
|
|
142
|
+
if (opt && this.optionKey) {
|
|
143
|
+
return get(opt, this.optionKey);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Use the property from an option level key
|
|
147
|
+
// This doesn't seem right, think it was meant to represent the actual option key... rather than the key to find the option key
|
|
148
|
+
// This approach also doesn't appear in LabeledSelect
|
|
138
149
|
if (opt?.optionKey) {
|
|
150
|
+
// opt.optionKey should in theory be optionKeyKey
|
|
139
151
|
return get(opt, opt.optionKey);
|
|
140
152
|
}
|
|
141
153
|
|
|
154
|
+
// There's no configuration to help us get a sensible key. Fall back on ..
|
|
155
|
+
// - the label
|
|
156
|
+
// - something random
|
|
157
|
+
|
|
142
158
|
const label = this.getOptionLabel(opt);
|
|
143
159
|
|
|
144
160
|
// label may be type of object
|