@rancher/shell 3.0.4 → 3.0.5-rc.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.
- package/assets/styles/base/_basic.scss +6 -0
- package/assets/styles/global/_button.scss +1 -0
- package/assets/translations/en-us.yaml +37 -3
- package/cloud-credential/aws.vue +2 -0
- package/components/AssignTo.vue +25 -11
- package/components/AsyncButton.vue +24 -7
- package/components/BannerGraphic.vue +1 -0
- package/components/CommunityLinks.vue +3 -3
- package/components/CopyToClipboardText.vue +2 -1
- package/components/DetailText.vue +5 -0
- package/components/DisableAuthProviderModal.vue +1 -0
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +56 -14
- package/components/LandingPagePreference.vue +5 -3
- package/components/LocaleSelector.vue +38 -94
- package/components/ModalWithCard.vue +1 -0
- package/components/MoveModal.vue +1 -0
- package/components/PromptRemove.vue +1 -0
- package/components/PromptRestore.vue +1 -0
- package/components/ResourceCancelModal.vue +1 -0
- package/components/SortableTable/index.vue +10 -11
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
- package/components/form/ArrayList.vue +66 -54
- package/components/form/Command.vue +6 -15
- package/components/form/EnvVars.vue +15 -8
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +11 -16
- package/components/form/LabeledSelect.vue +2 -1
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +10 -7
- package/components/form/NameNsDescription.vue +123 -103
- package/components/form/Networking.vue +20 -12
- package/components/form/NodeAffinity.vue +31 -23
- package/components/form/NodeScheduling.vue +13 -3
- package/components/form/PodAffinity.vue +43 -43
- package/components/form/Probe.vue +67 -66
- package/components/form/ResourceQuota/Project.vue +5 -1
- package/components/form/ResourceSelector.vue +7 -9
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
- package/components/form/SSHKnownHosts/index.vue +16 -2
- package/components/form/Security.vue +54 -56
- package/components/form/Select.vue +31 -6
- package/components/form/ShellInput.vue +5 -1
- package/components/form/Tolerations.vue +5 -1
- package/components/form/ValueFromResource.vue +134 -121
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +3 -0
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +115 -14
- package/components/form/__tests__/Probe.test.ts +12 -8
- package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
- package/components/form/__tests__/Select.test.ts +37 -0
- package/components/formatter/InternalExternalIP.vue +2 -0
- package/components/formatter/SecretData.vue +20 -7
- package/components/nav/Group.vue +15 -1
- package/components/nav/Header.vue +1 -0
- package/components/nav/Type.vue +12 -1
- package/components/templates/blank.vue +4 -1
- package/components/templates/default.vue +2 -0
- package/components/templates/home.vue +4 -1
- package/components/templates/plain.vue +4 -1
- package/composables/useRuntimeFlag.ts +29 -0
- package/config/router/routes.js +20 -13
- package/core/types.ts +5 -0
- package/dialog/AddCustomBadgeDialog.vue +1 -0
- package/dialog/DeactivateDriverDialog.vue +1 -0
- package/dialog/ForceMachineRemoveDialog.vue +4 -1
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
- package/edit/auth/__tests__/oidc.test.ts +152 -109
- package/edit/auth/azuread.vue +1 -0
- package/edit/auth/googleoauth.vue +4 -0
- package/edit/auth/oidc.vue +37 -4
- package/edit/cloudcredential.vue +1 -0
- package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
- package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
- package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +25 -34
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +29 -1
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
- package/edit/token.vue +2 -0
- package/edit/workload/index.vue +1 -0
- package/edit/workload/mixins/workload.js +0 -2
- package/list/management.cattle.io.feature.vue +1 -0
- package/list/provisioning.cattle.io.cluster.vue +20 -12
- package/models/__tests__/namespace.test.ts +25 -1
- package/models/cloudcredential.js +5 -0
- package/models/kontainerdriver.js +6 -3
- package/models/management.cattle.io.node.js +3 -3
- package/models/namespace.js +4 -5
- package/models/nodedriver.js +6 -3
- package/models/workload.js +4 -1
- package/package.json +3 -3
- package/pages/account/index.vue +4 -1
- package/pages/auth/login.vue +11 -3
- package/pages/auth/logout.vue +4 -1
- package/pages/auth/setup.vue +1 -0
- package/pages/auth/verify.vue +4 -1
- package/pages/c/_cluster/apps/charts/chart.vue +1 -1
- package/pages/diagnostic.vue +47 -2
- package/pages/fail-whale.vue +6 -3
- package/pages/home.vue +24 -18
- package/pages/support/index.vue +4 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +25 -23
- package/rancher-components/RcDropdown/RcDropdown.vue +3 -2
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
- package/scripts/extension/publish +1 -0
- package/server/har-file.js +25 -3
- package/store/features.js +2 -1
- package/store/type-map.js +4 -0
- package/types/shell/index.d.ts +8 -1
- package/utils/cluster.js +35 -0
- package/utils/validators/machine-pool.ts +20 -0
- package/components/formatter/ExtensionCache.vue +0 -74
- package/components/formatter/Port.vue +0 -24
- package/components/formatter/SecretType.vue +0 -41
|
@@ -158,6 +158,7 @@ nav:
|
|
|
158
158
|
alt:
|
|
159
159
|
mainMenuIcon: Main menu icon
|
|
160
160
|
mainMenuRancherLogo: Main menu Rancher logo
|
|
161
|
+
userAvatar: User avatar image
|
|
161
162
|
expandCollapseAppBar: Expand/Collapse the Application Bar
|
|
162
163
|
harvesterDashboard: Harvester Dashboard
|
|
163
164
|
backToRancher: Cluster Manager
|
|
@@ -319,6 +320,15 @@ suffix:
|
|
|
319
320
|
##############################
|
|
320
321
|
# Components & Pages
|
|
321
322
|
##############################
|
|
323
|
+
layouts:
|
|
324
|
+
home: home layout
|
|
325
|
+
plain: plain layout
|
|
326
|
+
default: default layout
|
|
327
|
+
blank: blank layout
|
|
328
|
+
unauthenticated: unauthenticated layout
|
|
329
|
+
logout: logout layout
|
|
330
|
+
verify: verify layout
|
|
331
|
+
|
|
322
332
|
windowmanager:
|
|
323
333
|
closeTab: Close tab {tabId}
|
|
324
334
|
about:
|
|
@@ -379,11 +389,15 @@ accountAndKeys:
|
|
|
379
389
|
title: API Keys
|
|
380
390
|
notAllowed: You do not have permission to manage API Keys
|
|
381
391
|
apiEndpoint: "API Endpoint:"
|
|
392
|
+
copyApiEnpoint: Copy API Endpoint to clipboard
|
|
382
393
|
add:
|
|
383
394
|
description:
|
|
384
395
|
label: Description
|
|
385
396
|
placeholder: Optionally enter a description to help you identify this API Key
|
|
386
397
|
label: Create API Key
|
|
398
|
+
ariaLabel:
|
|
399
|
+
expiration: Expiration duration - number input
|
|
400
|
+
expirationUnits: Expiration unit - time unit
|
|
387
401
|
expiry:
|
|
388
402
|
label: Automatically expire
|
|
389
403
|
options:
|
|
@@ -483,6 +497,9 @@ authConfig:
|
|
|
483
497
|
4: 'Under Scopes for Google APIs, enable "email", "profile", and "openid".'
|
|
484
498
|
5: 'Click on "Save".'
|
|
485
499
|
topPrivateDomain: 'Top private domain of:'
|
|
500
|
+
ariaLabel:
|
|
501
|
+
hostname: Copy Hostname to clipboard
|
|
502
|
+
serverUrl: Copy Server URL to clipboard
|
|
486
503
|
2:
|
|
487
504
|
title: 'Navigate to the "Credentials" tab to create your OAuth client ID'
|
|
488
505
|
body:
|
|
@@ -491,6 +508,8 @@ authConfig:
|
|
|
491
508
|
3: 'Authorized redirect URIs:'
|
|
492
509
|
4: 'Click "Create", and then click on the "Download JSON" button.'
|
|
493
510
|
5: 'Upload the downloaded JSON file in the OAuth credentials box.'
|
|
511
|
+
ariaLabel:
|
|
512
|
+
serverUrlVerify: Copy Server Auth Verfication URL to clipboard
|
|
494
513
|
3:
|
|
495
514
|
title: 'Create Service Account credentials'
|
|
496
515
|
introduction: 'Follow <a href="{docsBase}/how-to-guides/new-user-guides/authentication-permissions-and-global-configuration/authentication-config/configure-google-oauth#3-creating-service-account-credentials" target="_blank" rel="noopener noreferrer nofollow">this</a> guide to:'
|
|
@@ -624,6 +643,7 @@ authConfig:
|
|
|
624
643
|
reply:
|
|
625
644
|
info: 'Azure AD requires a whitelisted URL for your Rancher server before beginning this setup. Please ensure that the following URL is set in the Reply URL section of your Azure Portal. Please note that it may take up to 5 minutes for the whitelisted URL to propagate.'
|
|
626
645
|
label: Reply URL
|
|
646
|
+
ariaLabel: Copy Reply URL to clipboard
|
|
627
647
|
updateEndpoint:
|
|
628
648
|
button: Update Endpoint
|
|
629
649
|
banner:
|
|
@@ -656,7 +676,7 @@ authConfig:
|
|
|
656
676
|
scope:
|
|
657
677
|
label: Scopes
|
|
658
678
|
placeholder: openid
|
|
659
|
-
protip: The <code>openid</code>
|
|
679
|
+
protip: The <code>openid</code>, <code>profile</code>, and <code>email</code> scopes are required and cannot be removed.
|
|
660
680
|
cert:
|
|
661
681
|
label: Certificate
|
|
662
682
|
placeholder: Paste in the certificate, starting with -----BEGIN CERTIFICATE-----
|
|
@@ -2097,7 +2117,8 @@ cluster:
|
|
|
2097
2117
|
title: Save Machine Configurations
|
|
2098
2118
|
body: Machine Configurations define how machines in Pools are deployed.<br><br> They will be saved upfront to ensure valid Cluster YAML can be saved.
|
|
2099
2119
|
snapshots:
|
|
2100
|
-
suffix: Snapshots
|
|
2120
|
+
suffix: Snapshots per node
|
|
2121
|
+
s3Suffix: Snapshots
|
|
2101
2122
|
systemService:
|
|
2102
2123
|
rke2-coredns: 'CoreDNS'
|
|
2103
2124
|
rke2-ingress-nginx: 'NGINX Ingress'
|
|
@@ -2398,8 +2419,11 @@ drivers:
|
|
|
2398
2419
|
=1 { {warningDrivers} Resources in the corresponding provider will not be automatically removed.}
|
|
2399
2420
|
other { {warningDrivers} Resources in the corresponding providers will not be automatically removed.}
|
|
2400
2421
|
}
|
|
2422
|
+
error:
|
|
2423
|
+
activate: Failed to activate { name } driver
|
|
2401
2424
|
|
|
2402
2425
|
detailText:
|
|
2426
|
+
copyAriaLabel: Copy {item} value to clipboard
|
|
2403
2427
|
collapse: Hide
|
|
2404
2428
|
binary: '<Binary Data: {n, number} bytes>'
|
|
2405
2429
|
empty: '<Empty>'
|
|
@@ -2731,6 +2755,7 @@ clusterBadge:
|
|
|
2731
2755
|
iconText: Icon Text
|
|
2732
2756
|
buttonAction: Apply
|
|
2733
2757
|
badgeBgColor: Badge background color
|
|
2758
|
+
badgeBgColorInput: Badge background color selector input
|
|
2734
2759
|
badgeTextColor: Badge text color
|
|
2735
2760
|
badgeAsIcon: Use custom badge
|
|
2736
2761
|
maxCharsTooltip: Overwrites the default cluster name abbreviation.
|
|
@@ -2930,6 +2955,8 @@ ingress:
|
|
|
2930
2955
|
|
|
2931
2956
|
internalExternalIP:
|
|
2932
2957
|
none: None
|
|
2958
|
+
copyInternalIp: Copy internal IP address to clipboard
|
|
2959
|
+
copyExternalIp: Copy external IP address to clipboard
|
|
2933
2960
|
|
|
2934
2961
|
istio:
|
|
2935
2962
|
links:
|
|
@@ -3137,6 +3164,7 @@ labels:
|
|
|
3137
3164
|
hide: Hide System Labels and Annotations
|
|
3138
3165
|
annotations:
|
|
3139
3166
|
title: Annotations
|
|
3167
|
+
singular: Annotation
|
|
3140
3168
|
|
|
3141
3169
|
labelSelect:
|
|
3142
3170
|
noOptions:
|
|
@@ -3150,6 +3178,8 @@ labeledSelect:
|
|
|
3150
3178
|
pressEnter: Press enter to add "{input}"
|
|
3151
3179
|
|
|
3152
3180
|
landing:
|
|
3181
|
+
bannerImage: Homepage banner image
|
|
3182
|
+
homepage: Homepage
|
|
3153
3183
|
clusters:
|
|
3154
3184
|
title: Clusters
|
|
3155
3185
|
provider: Provider
|
|
@@ -3473,8 +3503,10 @@ neuvector:
|
|
|
3473
3503
|
na: Resource Unavailable
|
|
3474
3504
|
|
|
3475
3505
|
login:
|
|
3506
|
+
login: Login
|
|
3476
3507
|
howdy: Howdy!
|
|
3477
3508
|
welcome: Welcome to {vendor}
|
|
3509
|
+
landscapeAlt: Landscape image
|
|
3478
3510
|
loggedOut: You have been logged out.
|
|
3479
3511
|
loggedOutFromSso: You've been logged out of Rancher, however you may still be logged in to your single sign-on identity provider.
|
|
3480
3512
|
loggedOutFromSlo: You've been logged out of Rancher and from your single sign-on identity provider.
|
|
@@ -4879,6 +4911,7 @@ promptForceRemove:
|
|
|
4879
4911
|
modalTitle: Are you sure?
|
|
4880
4912
|
removeWarning: "There was an issue with deleting underlying infrastructure. If you proceed with this action, the Machine <b>{nameToMatch}</b> will be deleted from Rancher only. It's highly recommended to manually delete any referenced infrastructure."
|
|
4881
4913
|
forceDelete: Force Delete
|
|
4914
|
+
ariaLabel: Copy Machine name to clipboard
|
|
4882
4915
|
confirmName: "Enter in the pool name below to confirm:"
|
|
4883
4916
|
podRemoveWarning: "Force deleting pods does not wait for confirmation that the pod's processes have been terminated. This may result in <strong>data corruption or inconsistencies</strong>"
|
|
4884
4917
|
|
|
@@ -5490,6 +5523,7 @@ setup:
|
|
|
5490
5523
|
setPassword: The first order of business is to set a strong password for the default <code>{username}</code> user. We suggest using this random one generated just for you, but enter your own if you like.
|
|
5491
5524
|
useManual: Set a specific password to use
|
|
5492
5525
|
useRandom: Use a randomly generated password
|
|
5526
|
+
copyRandom: Copy random password to clipboard
|
|
5493
5527
|
welcome: Welcome to {vendor}!
|
|
5494
5528
|
|
|
5495
5529
|
sortableTable:
|
|
@@ -7941,12 +7975,12 @@ customLinks:
|
|
|
7941
7975
|
commercialSupport: Commercial Support
|
|
7942
7976
|
appCo: SUSE Application Collection
|
|
7943
7977
|
|
|
7944
|
-
|
|
7945
7978
|
##############################
|
|
7946
7979
|
### Support Page
|
|
7947
7980
|
##############################
|
|
7948
7981
|
|
|
7949
7982
|
support:
|
|
7983
|
+
bannerImage: Support page banner image
|
|
7950
7984
|
community:
|
|
7951
7985
|
title: SUSE Rancher provides world-class support
|
|
7952
7986
|
linksTitle: Community Support
|
package/cloud-credential/aws.vue
CHANGED
|
@@ -78,6 +78,7 @@ export default {
|
|
|
78
78
|
:rules="fvGetAndReportPathRules('decodedData.accessKey')"
|
|
79
79
|
:mode="mode"
|
|
80
80
|
:required="true"
|
|
81
|
+
data-testid="access-key"
|
|
81
82
|
@update:value="$emit('valueChanged', 'accessKey', $event)"
|
|
82
83
|
/>
|
|
83
84
|
<LabeledInput
|
|
@@ -89,6 +90,7 @@ export default {
|
|
|
89
90
|
:rules="fvGetAndReportPathRules('decodedData.secretKey')"
|
|
90
91
|
:mode="mode"
|
|
91
92
|
:required="true"
|
|
93
|
+
data-testid="secret-key"
|
|
92
94
|
@update:value="$emit('valueChanged', 'secretKey', $event)"
|
|
93
95
|
/>
|
|
94
96
|
<LabeledSelect
|
package/components/AssignTo.vue
CHANGED
|
@@ -115,6 +115,7 @@ export default {
|
|
|
115
115
|
styles="background-color: var(--nav-bg); border-radius: var(--border-radius); max-height: 100vh;"
|
|
116
116
|
height="auto"
|
|
117
117
|
:scrollable="true"
|
|
118
|
+
:trigger-focus-trap="true"
|
|
118
119
|
@close="close"
|
|
119
120
|
>
|
|
120
121
|
<Card
|
|
@@ -157,17 +158,20 @@ export default {
|
|
|
157
158
|
</template>
|
|
158
159
|
|
|
159
160
|
<template #actions>
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
<div class="actions-container">
|
|
162
|
+
<button
|
|
163
|
+
class="btn role-secondary"
|
|
164
|
+
@click="close"
|
|
165
|
+
>
|
|
166
|
+
{{ t('generic.cancel') }}
|
|
167
|
+
</button>
|
|
168
|
+
|
|
169
|
+
<AsyncButton
|
|
170
|
+
class="apply-btn"
|
|
171
|
+
mode="apply"
|
|
172
|
+
@click="apply"
|
|
173
|
+
/>
|
|
174
|
+
</div>
|
|
171
175
|
</template>
|
|
172
176
|
</Card>
|
|
173
177
|
</app-modal>
|
|
@@ -181,5 +185,15 @@ export default {
|
|
|
181
185
|
& ::-webkit-scrollbar-corner {
|
|
182
186
|
background: rgba(0,0,0,0);
|
|
183
187
|
}
|
|
188
|
+
|
|
189
|
+
.actions-container {
|
|
190
|
+
display: flex;
|
|
191
|
+
justify-content: flex-end;
|
|
192
|
+
width: 100%;
|
|
193
|
+
|
|
194
|
+
.apply-btn {
|
|
195
|
+
margin-left: 20px;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
184
198
|
}
|
|
185
199
|
</style>
|
|
@@ -11,6 +11,7 @@ export const ASYNC_BUTTON_STATES = {
|
|
|
11
11
|
|
|
12
12
|
const TEXT = 'text';
|
|
13
13
|
const TOOLTIP = 'tooltip';
|
|
14
|
+
const DISABLED_CLASS_STYLE = 'btn-disabled';
|
|
14
15
|
|
|
15
16
|
export type AsyncButtonCallback = (success: boolean) => void;
|
|
16
17
|
|
|
@@ -152,9 +153,29 @@ export default defineComponent({
|
|
|
152
153
|
out[`btn-${ this.size }`] = true;
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
// while we are waiting for the async button to get
|
|
157
|
+
// it's callback we want to the button to appear as disabled
|
|
158
|
+
// but not being actually disabled as need it to be
|
|
159
|
+
// able to return the keyboard navigation focus back to it
|
|
160
|
+
// which can't be done while actually disabled, as per
|
|
161
|
+
// https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols
|
|
162
|
+
if (this.phase === ASYNC_BUTTON_STATES.WAITING) {
|
|
163
|
+
out[DISABLED_CLASS_STYLE] = true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// used to assist e2e testing mostly when waiting for button to return
|
|
167
|
+
// to it's normal state/phase
|
|
168
|
+
if (this.phase === ASYNC_BUTTON_STATES.ACTION) {
|
|
169
|
+
out['ready-for-action'] = true;
|
|
170
|
+
}
|
|
171
|
+
|
|
155
172
|
return out;
|
|
156
173
|
},
|
|
157
174
|
|
|
175
|
+
appearsDisabled(): boolean {
|
|
176
|
+
return this.disabled || this.phase === ASYNC_BUTTON_STATES.WAITING;
|
|
177
|
+
},
|
|
178
|
+
|
|
158
179
|
displayIcon(): string {
|
|
159
180
|
const exists = this.$store.getters['i18n/exists'];
|
|
160
181
|
const t = this.$store.getters['i18n/t'];
|
|
@@ -204,10 +225,6 @@ export default defineComponent({
|
|
|
204
225
|
return this.phase === ASYNC_BUTTON_STATES.WAITING;
|
|
205
226
|
},
|
|
206
227
|
|
|
207
|
-
isDisabled(): boolean {
|
|
208
|
-
return this.disabled || this.phase === ASYNC_BUTTON_STATES.WAITING;
|
|
209
|
-
},
|
|
210
|
-
|
|
211
228
|
isManualRefresh() {
|
|
212
229
|
return this.mode === 'manual-refresh';
|
|
213
230
|
},
|
|
@@ -232,7 +249,7 @@ export default defineComponent({
|
|
|
232
249
|
|
|
233
250
|
methods: {
|
|
234
251
|
clicked() {
|
|
235
|
-
if ( this.
|
|
252
|
+
if ( this.appearsDisabled ) {
|
|
236
253
|
return;
|
|
237
254
|
}
|
|
238
255
|
|
|
@@ -283,8 +300,8 @@ export default defineComponent({
|
|
|
283
300
|
:class="classes"
|
|
284
301
|
:name="name"
|
|
285
302
|
:type="type"
|
|
286
|
-
:disabled="
|
|
287
|
-
:aria-disabled="
|
|
303
|
+
:disabled="disabled"
|
|
304
|
+
:aria-disabled="appearsDisabled"
|
|
288
305
|
:tab-index="tabIndex"
|
|
289
306
|
:data-testid="componentTestid + '-async-button'"
|
|
290
307
|
@click="clicked"
|
|
@@ -140,7 +140,7 @@ export default {
|
|
|
140
140
|
:aria-label="t('footer.wechat.title')"
|
|
141
141
|
role="link"
|
|
142
142
|
@click="show"
|
|
143
|
-
@
|
|
143
|
+
@keydown.enter="show"
|
|
144
144
|
>
|
|
145
145
|
{{ t('footer.wechat.title') }}
|
|
146
146
|
</a>
|
|
@@ -151,6 +151,7 @@ export default {
|
|
|
151
151
|
name="wechat-modal"
|
|
152
152
|
height="auto"
|
|
153
153
|
:width="640"
|
|
154
|
+
:trigger-focus-trap="true"
|
|
154
155
|
@close="close"
|
|
155
156
|
>
|
|
156
157
|
<div class="wechat-modal">
|
|
@@ -164,8 +165,7 @@ export default {
|
|
|
164
165
|
:aria-label="t('generic.close')"
|
|
165
166
|
role="button"
|
|
166
167
|
@click="close"
|
|
167
|
-
@
|
|
168
|
-
@keyup.space="close"
|
|
168
|
+
@keydown.enter.stop
|
|
169
169
|
>
|
|
170
170
|
{{ t('generic.close') }}
|
|
171
171
|
</button>
|
|
@@ -49,9 +49,10 @@ export default {
|
|
|
49
49
|
v-if="text"
|
|
50
50
|
class="copy-to-clipboard-text"
|
|
51
51
|
role="button"
|
|
52
|
-
:aria-label="t('generic.copyToClipboard')"
|
|
53
52
|
:class="{ 'copied': copied, 'plain': plain}"
|
|
54
53
|
href="#"
|
|
54
|
+
:aria-label="t('generic.copyToClipboard')"
|
|
55
|
+
v-bind="$attrs"
|
|
55
56
|
@click="clicked"
|
|
56
57
|
@keyup.space="clicked"
|
|
57
58
|
>
|
|
@@ -58,6 +58,10 @@ export default {
|
|
|
58
58
|
},
|
|
59
59
|
|
|
60
60
|
computed: {
|
|
61
|
+
itemLabel() {
|
|
62
|
+
return this.labelKey ? this.t(this.labelKey) : this.label ? this.label : this.t('labels.annotations.singular');
|
|
63
|
+
},
|
|
64
|
+
|
|
61
65
|
isBinary() {
|
|
62
66
|
if ( this.binary === null ) {
|
|
63
67
|
return typeof this.value === 'string' && !asciiLike(this.value);
|
|
@@ -186,6 +190,7 @@ export default {
|
|
|
186
190
|
:text="value"
|
|
187
191
|
class="role-tertiary"
|
|
188
192
|
action-color=""
|
|
193
|
+
:aria-label="t('detailText.copyAriaLabel', {item: itemLabel })"
|
|
189
194
|
/>
|
|
190
195
|
</div>
|
|
191
196
|
</template>
|
|
@@ -63,7 +63,7 @@ export default {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (projectRoleTemplateBindingSchema) {
|
|
66
|
-
this.$store.dispatch('rancher/findAll', { type: NORMAN.PROJECT_ROLE_TEMPLATE_BINDING }, { root: true })
|
|
66
|
+
this.$store.dispatch('rancher/findAll', { type: NORMAN.PROJECT_ROLE_TEMPLATE_BINDING, opt: { force: true } }, { root: true })
|
|
67
67
|
.then((bindings) => {
|
|
68
68
|
this['projectRoleTemplateBindings'] = bindings;
|
|
69
69
|
this.loadingProjectBindings = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { mapGetters } from 'vuex';
|
|
2
|
+
import { mapGetters, useStore } from 'vuex';
|
|
3
3
|
import ResourceTable, { defaultTableSortGenerationFn } from '@shell/components/ResourceTable';
|
|
4
4
|
import { STATE, AGE, NAME, NS_SNAPSHOT_QUOTA } from '@shell/config/table-headers';
|
|
5
5
|
import { uniq } from '@shell/utils/array';
|
|
@@ -11,11 +11,13 @@ import Masthead from '@shell/components/ResourceList/Masthead';
|
|
|
11
11
|
import { mapPref, GROUP_RESOURCES, ALL_NAMESPACES, DEV } from '@shell/store/prefs';
|
|
12
12
|
import MoveModal from '@shell/components/MoveModal';
|
|
13
13
|
import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
|
|
14
|
-
|
|
14
|
+
import { escapeHtml } from '@shell/utils/string';
|
|
15
15
|
import { NAMESPACE_FILTER_ALL_ORPHANS } from '@shell/utils/namespace-filter';
|
|
16
16
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
17
17
|
import DOMPurify from 'dompurify';
|
|
18
18
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
19
|
+
import ActionMenu from '@shell/components/ActionMenuShell.vue';
|
|
20
|
+
import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
|
|
19
21
|
|
|
20
22
|
export default {
|
|
21
23
|
name: 'ListProjectNamespace',
|
|
@@ -25,6 +27,7 @@ export default {
|
|
|
25
27
|
MoveModal,
|
|
26
28
|
ResourceTable,
|
|
27
29
|
ButtonMultiAction,
|
|
30
|
+
ActionMenu,
|
|
28
31
|
},
|
|
29
32
|
mixins: [ResourceFetch],
|
|
30
33
|
|
|
@@ -58,6 +61,13 @@ export default {
|
|
|
58
61
|
this.projects = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT, opt: { force: true } });
|
|
59
62
|
},
|
|
60
63
|
|
|
64
|
+
setup() {
|
|
65
|
+
const store = useStore();
|
|
66
|
+
const { featureDropdownMenu } = useRuntimeFlag(store);
|
|
67
|
+
|
|
68
|
+
return { featureDropdownMenu };
|
|
69
|
+
},
|
|
70
|
+
|
|
61
71
|
data() {
|
|
62
72
|
return {
|
|
63
73
|
loadResources: [NAMESPACE],
|
|
@@ -155,7 +165,7 @@ export default {
|
|
|
155
165
|
rowsWithFakeNamespaces() {
|
|
156
166
|
const fakeRows = this.projectsWithoutNamespaces.map((project) => {
|
|
157
167
|
return {
|
|
158
|
-
|
|
168
|
+
groupById: `${ ('resourceTable.groupLabel.notInAProject') }-${ project.id }`,
|
|
159
169
|
isFake: true,
|
|
160
170
|
mainRowKey: project.id,
|
|
161
171
|
nameDisplay: project.spec?.displayName, // Enable filtering by the project name
|
|
@@ -166,8 +176,8 @@ export default {
|
|
|
166
176
|
|
|
167
177
|
if (this.showMockNotInProjectGroup) {
|
|
168
178
|
fakeRows.push( {
|
|
169
|
-
|
|
170
|
-
mainRowKey:
|
|
179
|
+
groupById: this.t('resourceTable.groupLabel.notInAProject'),
|
|
180
|
+
mainRowKey: 'fake-empty',
|
|
171
181
|
});
|
|
172
182
|
}
|
|
173
183
|
|
|
@@ -273,6 +283,9 @@ export default {
|
|
|
273
283
|
},
|
|
274
284
|
showCreateNsButton() {
|
|
275
285
|
return this.groupPreference !== 'namespace';
|
|
286
|
+
},
|
|
287
|
+
projectGroupBy() {
|
|
288
|
+
return this.groupPreference === 'none' ? null : 'groupById';
|
|
276
289
|
}
|
|
277
290
|
},
|
|
278
291
|
methods: {
|
|
@@ -336,6 +349,10 @@ export default {
|
|
|
336
349
|
return location;
|
|
337
350
|
},
|
|
338
351
|
|
|
352
|
+
getProjectActions(group) {
|
|
353
|
+
return group.rows[0].project;
|
|
354
|
+
},
|
|
355
|
+
|
|
339
356
|
showProjectAction(event, group) {
|
|
340
357
|
const project = group.rows[0].project;
|
|
341
358
|
|
|
@@ -359,7 +376,13 @@ export default {
|
|
|
359
376
|
);
|
|
360
377
|
}
|
|
361
378
|
|
|
362
|
-
|
|
379
|
+
if ( row.groupById === this.notInProjectKey) {
|
|
380
|
+
return this.t('resourceTable.groupLabel.notInAProject');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const project = row.project?.nameDisplay || row.project?.id || '';
|
|
384
|
+
|
|
385
|
+
return this.t('resourceTable.groupLabel.project', { name: escapeHtml(project) }, true);
|
|
363
386
|
},
|
|
364
387
|
|
|
365
388
|
projectDescription(group) {
|
|
@@ -431,6 +454,7 @@ export default {
|
|
|
431
454
|
:schema="schema"
|
|
432
455
|
:headers="headers"
|
|
433
456
|
:rows="filteredRows"
|
|
457
|
+
:group-by="projectGroupBy"
|
|
434
458
|
:groupable="true"
|
|
435
459
|
:sort-generation-fn="sortGenerationFn"
|
|
436
460
|
:loading="loading"
|
|
@@ -457,7 +481,7 @@ export default {
|
|
|
457
481
|
{{ projectDescription(group.group) }}
|
|
458
482
|
</div>
|
|
459
483
|
</div>
|
|
460
|
-
<div class="right">
|
|
484
|
+
<div class="right mr-10">
|
|
461
485
|
<router-link
|
|
462
486
|
v-if="isNamespaceCreatable && (canSeeProjectlessNamespaces || group.group.key !== notInProjectKey)"
|
|
463
487
|
class="create-namespace btn btn-sm role-secondary mr-5"
|
|
@@ -465,13 +489,26 @@ export default {
|
|
|
465
489
|
>
|
|
466
490
|
{{ t('projectNamespaces.createNamespace') }}
|
|
467
491
|
</router-link>
|
|
468
|
-
<
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
492
|
+
<template v-if="featureDropdownMenu">
|
|
493
|
+
<ActionMenu
|
|
494
|
+
v-if="showProjectActionButton(group.group)"
|
|
495
|
+
:resource="getProjectActions(group.group)"
|
|
496
|
+
:button-aria-label="t('projectNamespaces.tableActionsLabel', { resource: projectResource(group.group) })"
|
|
497
|
+
/>
|
|
498
|
+
<div
|
|
499
|
+
v-else
|
|
500
|
+
class="invisible"
|
|
501
|
+
/>
|
|
502
|
+
</template>
|
|
503
|
+
<template v-else>
|
|
504
|
+
<ButtonMultiAction
|
|
505
|
+
class="project-action"
|
|
506
|
+
:borderless="true"
|
|
507
|
+
:aria-label="t('projectNamespaces.tableActionsLabel', { resource: projectResource(group.group) })"
|
|
508
|
+
:invisible="!showProjectActionButton(group.group)"
|
|
509
|
+
@click="showProjectAction($event, group.group)"
|
|
510
|
+
/>
|
|
511
|
+
</template>
|
|
475
512
|
</div>
|
|
476
513
|
</div>
|
|
477
514
|
</template>
|
|
@@ -536,6 +573,11 @@ export default {
|
|
|
536
573
|
</div>
|
|
537
574
|
</template>
|
|
538
575
|
<style lang="scss" scoped>
|
|
576
|
+
.invisible {
|
|
577
|
+
display: inline-block;
|
|
578
|
+
min-width: 28px;
|
|
579
|
+
}
|
|
580
|
+
|
|
539
581
|
.project-namespaces {
|
|
540
582
|
& :deep() {
|
|
541
583
|
.project-namespaces-table table {
|
|
@@ -103,9 +103,6 @@ export default {
|
|
|
103
103
|
|
|
104
104
|
<template>
|
|
105
105
|
<div>
|
|
106
|
-
<p class="set-landing-leadin">
|
|
107
|
-
{{ t('landing.landingPrefs.body') }}
|
|
108
|
-
</p>
|
|
109
106
|
<RadioGroup
|
|
110
107
|
id="login-route"
|
|
111
108
|
:value="afterLoginRoute"
|
|
@@ -113,6 +110,11 @@ export default {
|
|
|
113
110
|
:options="routeRadioOptions"
|
|
114
111
|
@update:value="updateLoginRoute"
|
|
115
112
|
>
|
|
113
|
+
<template #label>
|
|
114
|
+
<p class="set-landing-leadin">
|
|
115
|
+
{{ t('landing.landingPrefs.body') }}
|
|
116
|
+
</p>
|
|
117
|
+
</template>
|
|
116
118
|
<template #2="{option}">
|
|
117
119
|
<div class="custom-page">
|
|
118
120
|
<RadioButton
|