@rancher/shell 2.0.0 → 2.0.2-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/translations/en-us.yaml +69 -29
- package/assets/translations/zh-hans.yaml +1 -0
- package/components/AlertTable.vue +17 -7
- package/components/AssignTo.vue +2 -0
- package/components/GrafanaDashboard.vue +6 -4
- package/components/PromptRemove.vue +1 -0
- package/components/Questions/index.vue +2 -2
- package/components/auth/RoleDetailEdit.vue +5 -4
- package/components/form/KeyValue.vue +1 -0
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +11 -3
- package/components/form/Taints.vue +13 -7
- package/components/form/__tests__/Taints.test.ts +70 -0
- package/components/form/labeled-select-utils/labeled-select.utils.ts +1 -1
- package/components/nav/Header.vue +1 -1
- package/components/nav/TopLevelMenu.vue +1 -4
- package/config/pagination-table-headers.js +5 -4
- package/config/product/auth.js +1 -1
- package/config/roles.ts +34 -19
- package/config/router/navigation-guards/attempt-first-login.js +1 -1
- package/config/router/navigation-guards/authentication.js +1 -1
- package/config/router/navigation-guards/i18n.js +13 -0
- package/config/router/navigation-guards/index.js +3 -1
- package/config/router/navigation-guards/load-initial-settings.js +1 -1
- package/config/router/navigation-guards/runtime-extension-route.js +31 -0
- package/config/router/routes.js +10 -1
- package/config/uiplugins.js +130 -61
- package/core/plugin.ts +5 -0
- package/core/plugins.js +7 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +42 -0
- package/detail/provisioning.cattle.io.cluster.vue +4 -4
- package/dialog/DeactivateDriverDialog.vue +30 -11
- package/edit/auth/__tests__/oidc.test.ts +2 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +86 -13
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +3 -134
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +209 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/rke2.vue +115 -17
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +50 -0
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +29 -64
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +42 -3
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +22 -86
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +8 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +61 -0
- package/edit/token.vue +2 -1
- package/initialize/entry-helpers.js +4 -24
- package/list/management.cattle.io.feature.vue +4 -2
- package/middleware/authenticated.js +0 -19
- package/mixins/__tests__/chart.test.ts +4 -1
- package/mixins/auth-config.js +1 -1
- package/mixins/chart.js +30 -14
- package/models/__tests__/apps.deployment.test.ts +93 -0
- package/models/apps.deployment.js +18 -4
- package/models/driver.js +3 -2
- package/models/kontainerdriver.js +30 -13
- package/models/management.cattle.io.authconfig.js +2 -2
- package/models/management.cattle.io.cluster.js +2 -2
- package/models/management.cattle.io.user.js +3 -3
- package/models/nodedriver.js +35 -13
- package/models/provisioning.cattle.io.cluster.js +4 -0
- package/package.json +3 -2
- package/pages/404.vue +15 -0
- package/pages/auth/login.vue +4 -1
- package/pages/auth/setup.vue +4 -1
- package/pages/c/_cluster/apps/charts/install.vue +3 -2
- package/pages/c/_cluster/explorer/index.vue +5 -0
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +0 -3
- package/pages/c/_cluster/manager/drivers/nodeDriver/index.vue +1 -4
- package/pages/c/_cluster/manager/jwt.authentication/index.vue +10 -4
- package/pages/c/_cluster/settings/performance.vue +2 -2
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +2 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +7 -10
- package/pages/c/_cluster/uiplugins/index.vue +24 -16
- package/pages/home.vue +1 -13
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/steve/__tests__/getters.test.ts +5 -5
- package/plugins/steve/getters.js +6 -4
- package/plugins/steve/hybrid-class.js +1 -5
- package/promptRemove/pod.vue +15 -7
- package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +1 -1
- package/scripts/publish-shell.sh +54 -55
- package/scripts/test-plugins-build.sh +45 -39
- package/shell/types/shell/index.d.ts +2 -0
- package/store/auth.js +1 -1
- package/store/index.js +1 -1
- package/store/type-map.js +4 -2
- package/types/store/pagination.types.ts +1 -1
- package/utils/__tests__/kontainer.test.ts +89 -1
- package/utils/auth.js +1 -1
- package/utils/cluster.js +9 -0
- package/utils/kontainer.ts +5 -1
- package/utils/settings.ts +3 -1
- package/utils/version.js +2 -1
- package/creators/app/app.package.json +0 -13
- package/creators/app/files/.eslintignore +0 -16
- package/creators/app/files/.eslintrc.js +0 -173
- package/creators/app/files/.gitignore +0 -70
- package/creators/app/files/.gitlab-ci.yml +0 -14
- package/creators/app/files/.vscode/settings.json +0 -21
- package/creators/app/files/babel.config.js +0 -1
- package/creators/app/files/tsconfig.json +0 -42
- package/creators/app/files/vue.config.js +0 -6
- package/creators/app/init +0 -120
- package/creators/app/package.json +0 -25
- package/creators/pkg/files/.github/workflows/build-extension-catalog.yml +0 -24
- package/creators/pkg/files/.github/workflows/build-extension-charts.yml +0 -22
- package/creators/pkg/files/babel.config.js +0 -1
- package/creators/pkg/files/index.ts +0 -14
- package/creators/pkg/files/tsconfig.json +0 -53
- package/creators/pkg/files/vue.config.js +0 -1
- package/creators/pkg/init +0 -286
- package/creators/pkg/package.json +0 -19
- package/creators/pkg/pkg.package.json +0 -21
- package/creators/pkg/vue-shim.ts +0 -4
- package/creators/update/init +0 -56
- package/creators/update/package.json +0 -20
- package/creators/update/upgrade +0 -56
- package/rancher-components/components/Accordion/Accordion.test.ts +0 -45
- package/rancher-components/components/Accordion/Accordion.vue +0 -86
- package/rancher-components/components/Accordion/index.ts +0 -1
- package/rancher-components/components/BadgeState/BadgeState.test.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 -59
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.test.ts +0 -37
- 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 -421
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -40
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -402
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +0 -33
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -293
- package/rancher-components/components/Form/Radio/RadioGroup.test.ts +0 -30
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -259
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -172
- 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 -152
- 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 -156
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -754
- package/rancher-components/components/StringList/StringList.vue +0 -650
- package/rancher-components/components/StringList/index.ts +0 -1
- package/types/shell/index.d.ts +0 -4585
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue';
|
|
3
|
-
import TextAreaAutoGrow from '@components/Form/TextArea/TextAreaAutoGrow.vue';
|
|
4
|
-
import LabeledTooltip from '@components/LabeledTooltip/LabeledTooltip.vue';
|
|
5
|
-
import { escapeHtml } from '@shell/utils/string';
|
|
6
|
-
import cronstrue from 'cronstrue';
|
|
7
|
-
import { isValidCron } from 'cron-validator';
|
|
8
|
-
import { debounce } from 'lodash';
|
|
9
|
-
import { useLabeledFormElement, labeledFormElementProps } from '@shell/composables/useLabeledFormElement';
|
|
10
|
-
import { useCompactInput } from '@shell/composables/useCompactInput';
|
|
11
|
-
|
|
12
|
-
declare module 'vue/types/vue' {
|
|
13
|
-
interface Vue {
|
|
14
|
-
onInput: (event: Event) => void | ((event: Event) => void);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default defineComponent({
|
|
19
|
-
components: { LabeledTooltip, TextAreaAutoGrow },
|
|
20
|
-
|
|
21
|
-
inheritAttrs: false,
|
|
22
|
-
|
|
23
|
-
props: {
|
|
24
|
-
...labeledFormElementProps,
|
|
25
|
-
/**
|
|
26
|
-
* The type of the Labeled Input.
|
|
27
|
-
* @values text, cron, multiline, multiline-password
|
|
28
|
-
*/
|
|
29
|
-
type: {
|
|
30
|
-
type: String,
|
|
31
|
-
default: 'text'
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The status class of the Labeled Input and tooltip.
|
|
36
|
-
* @values info, success, warning, error
|
|
37
|
-
*/
|
|
38
|
-
status: {
|
|
39
|
-
type: String,
|
|
40
|
-
default: null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* The sub-label for the Labeled Input.
|
|
45
|
-
*/
|
|
46
|
-
subLabel: {
|
|
47
|
-
type: String,
|
|
48
|
-
default: null
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* The tooltip to display for the Labeled Input.
|
|
53
|
-
*/
|
|
54
|
-
tooltip: {
|
|
55
|
-
default: null,
|
|
56
|
-
type: [String, Object]
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Renders the tooltip when hovering the cursor over the Labeled Input.
|
|
61
|
-
*/
|
|
62
|
-
hoverTooltip: {
|
|
63
|
-
type: Boolean,
|
|
64
|
-
default: true
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Disables the password manager prompt to save the contents of the Labeled
|
|
69
|
-
* Input.
|
|
70
|
-
*/
|
|
71
|
-
ignorePasswordManagers: {
|
|
72
|
-
default: false,
|
|
73
|
-
type: Boolean
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The max length of the Labeled Input.
|
|
78
|
-
*/
|
|
79
|
-
maxlength: {
|
|
80
|
-
type: Number,
|
|
81
|
-
default: null
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Hides arrows on the Labeled Input.
|
|
86
|
-
* @deprecated This doesn't appear to be in use for Labeled Input.
|
|
87
|
-
*/
|
|
88
|
-
hideArrows: {
|
|
89
|
-
type: Boolean,
|
|
90
|
-
default: false
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Optionally delay on input while typing.
|
|
95
|
-
*/
|
|
96
|
-
delay: {
|
|
97
|
-
type: Number,
|
|
98
|
-
default: 0
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
setup(props, { emit }) {
|
|
103
|
-
const {
|
|
104
|
-
focused,
|
|
105
|
-
onFocusLabeled,
|
|
106
|
-
onBlurLabeled,
|
|
107
|
-
isDisabled,
|
|
108
|
-
validationMessage,
|
|
109
|
-
requiredField
|
|
110
|
-
} = useLabeledFormElement(props, emit);
|
|
111
|
-
const { isCompact } = useCompactInput(props);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
focused,
|
|
115
|
-
onFocusLabeled,
|
|
116
|
-
onBlurLabeled,
|
|
117
|
-
isDisabled,
|
|
118
|
-
validationMessage,
|
|
119
|
-
requiredField,
|
|
120
|
-
isCompact,
|
|
121
|
-
};
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
data() {
|
|
125
|
-
return {
|
|
126
|
-
updated: false,
|
|
127
|
-
validationErrors: '',
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
computed: {
|
|
132
|
-
/**
|
|
133
|
-
* Determines if the Labeled Input should display a label.
|
|
134
|
-
*/
|
|
135
|
-
hasLabel(): boolean {
|
|
136
|
-
return this.isCompact ? false : !!this.label || !!this.labelKey || !!this.$slots.label;
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Determines if the Labeled Input should display a tooltip.
|
|
141
|
-
*/
|
|
142
|
-
hasTooltip(): boolean {
|
|
143
|
-
return !!this.tooltip || !!this.tooltipKey;
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
tooltipValue(): string | Record<string, unknown> | undefined {
|
|
147
|
-
if (this.hasTooltip) {
|
|
148
|
-
return this.tooltipKey ? this.t(this.tooltipKey) : this.tooltip;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return undefined;
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Determines if the Labeled Input makes use of the suffix slot.
|
|
156
|
-
*/
|
|
157
|
-
hasSuffix(): boolean {
|
|
158
|
-
return !!this.$slots.suffix;
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Determines if the Labeled Input should display a cron hint.
|
|
163
|
-
*/
|
|
164
|
-
cronHint(): string | undefined {
|
|
165
|
-
if (this.type !== 'cron' || !this.value) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (typeof this.value === 'string' && !isValidCron(this.value)) {
|
|
169
|
-
return this.t('generic.invalidCron');
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
const hint = cronstrue.toString(this.value);
|
|
173
|
-
|
|
174
|
-
return hint;
|
|
175
|
-
} catch (e) {
|
|
176
|
-
return this.t('generic.invalidCron');
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* The placeholder value for the Labeled Input.
|
|
182
|
-
*/
|
|
183
|
-
_placeholder(): string {
|
|
184
|
-
if (this.placeholder) {
|
|
185
|
-
return this.placeholder.toString();
|
|
186
|
-
}
|
|
187
|
-
if (this.placeholderKey) {
|
|
188
|
-
return this.t(this.placeholderKey);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return '';
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* The max length for the Labeled Input.
|
|
196
|
-
*/
|
|
197
|
-
_maxlength(): number | undefined {
|
|
198
|
-
if (this.type === 'text' && this.maxlength) {
|
|
199
|
-
return this.maxlength;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return undefined;
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
created() {
|
|
207
|
-
/**
|
|
208
|
-
* Determines if the Labeled Input @input event should be debounced.
|
|
209
|
-
*/
|
|
210
|
-
this.onInput = this.delay ? debounce(this.delayInput, this.delay) : this.delayInput;
|
|
211
|
-
},
|
|
212
|
-
|
|
213
|
-
methods: {
|
|
214
|
-
/**
|
|
215
|
-
* Attempts to give the Labeled Input focus.
|
|
216
|
-
*/
|
|
217
|
-
focus(): void {
|
|
218
|
-
const comp = this.$refs.value as HTMLInputElement;
|
|
219
|
-
|
|
220
|
-
if (comp) {
|
|
221
|
-
comp.focus();
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Attempts to select the Labeled Input.
|
|
227
|
-
* @deprecated
|
|
228
|
-
*/
|
|
229
|
-
select(): void {
|
|
230
|
-
const comp = this.$refs.value as HTMLInputElement;
|
|
231
|
-
|
|
232
|
-
if (comp) {
|
|
233
|
-
comp.select();
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Emit on input change
|
|
239
|
-
*/
|
|
240
|
-
onChange(event: Event): void {
|
|
241
|
-
this.$emit('change', event);
|
|
242
|
-
},
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Emit on input with delay. Note: Arrow function is avoided due context
|
|
246
|
-
* binding.
|
|
247
|
-
*
|
|
248
|
-
* NOTE: In multiline, TextAreaAutoGrow emits a string with the value
|
|
249
|
-
* https://github.com/rancher/dashboard/issues/10249
|
|
250
|
-
*/
|
|
251
|
-
delayInput(val: string | Event): void {
|
|
252
|
-
const value = typeof val === 'string' ? val : (val?.target as HTMLInputElement)?.value;
|
|
253
|
-
|
|
254
|
-
this.$emit('input', value);
|
|
255
|
-
},
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Handles the behavior of the Labeled Input when given focus.
|
|
259
|
-
* @see labeled-form-element.ts mixin for onFocusLabeled()
|
|
260
|
-
*/
|
|
261
|
-
onFocus(): void {
|
|
262
|
-
this.onFocusLabeled();
|
|
263
|
-
},
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Handles the behavior of the Labeled Input when blurred and emits the blur
|
|
267
|
-
* event.
|
|
268
|
-
* @see labeled-form-element.ts mixin for onBlurLabeled()
|
|
269
|
-
*/
|
|
270
|
-
onBlur(event: string | FocusEvent): void {
|
|
271
|
-
this.$emit('blur', event);
|
|
272
|
-
this.onBlurLabeled();
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
escapeHtml
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
</script>
|
|
279
|
-
|
|
280
|
-
<template>
|
|
281
|
-
<div
|
|
282
|
-
:class="{
|
|
283
|
-
'labeled-input': true,
|
|
284
|
-
focused,
|
|
285
|
-
[mode]: true,
|
|
286
|
-
disabled: isDisabled,
|
|
287
|
-
[status]: status,
|
|
288
|
-
suffix: hasSuffix,
|
|
289
|
-
'has-tooltip': hasTooltip,
|
|
290
|
-
'compact-input': isCompact,
|
|
291
|
-
hideArrows
|
|
292
|
-
}"
|
|
293
|
-
>
|
|
294
|
-
<slot name="label">
|
|
295
|
-
<label v-if="hasLabel">
|
|
296
|
-
<t
|
|
297
|
-
v-if="labelKey"
|
|
298
|
-
:k="labelKey"
|
|
299
|
-
/>
|
|
300
|
-
<template v-else-if="label">{{ label }}</template>
|
|
301
|
-
|
|
302
|
-
<span
|
|
303
|
-
v-if="requiredField"
|
|
304
|
-
class="required"
|
|
305
|
-
>*</span>
|
|
306
|
-
</label>
|
|
307
|
-
</slot>
|
|
308
|
-
|
|
309
|
-
<slot name="prefix" />
|
|
310
|
-
|
|
311
|
-
<slot name="field">
|
|
312
|
-
<TextAreaAutoGrow
|
|
313
|
-
v-if="type === 'multiline' || type === 'multiline-password'"
|
|
314
|
-
ref="value"
|
|
315
|
-
v-bind="$attrs"
|
|
316
|
-
:maxlength="_maxlength"
|
|
317
|
-
:disabled="isDisabled"
|
|
318
|
-
:value="value"
|
|
319
|
-
:placeholder="_placeholder"
|
|
320
|
-
autocapitalize="off"
|
|
321
|
-
:class="{ conceal: type === 'multiline-password' }"
|
|
322
|
-
@input="onInput"
|
|
323
|
-
@focus="onFocus"
|
|
324
|
-
@blur="onBlur"
|
|
325
|
-
/>
|
|
326
|
-
<input
|
|
327
|
-
v-else
|
|
328
|
-
ref="value"
|
|
329
|
-
:class="{ 'no-label': !hasLabel }"
|
|
330
|
-
v-bind="$attrs"
|
|
331
|
-
:maxlength="_maxlength"
|
|
332
|
-
:disabled="isDisabled"
|
|
333
|
-
:type="type === 'cron' ? 'text' : type"
|
|
334
|
-
:value="value"
|
|
335
|
-
:placeholder="_placeholder"
|
|
336
|
-
autocomplete="off"
|
|
337
|
-
autocapitalize="off"
|
|
338
|
-
:data-lpignore="ignorePasswordManagers"
|
|
339
|
-
@input="onInput"
|
|
340
|
-
@focus="onFocus"
|
|
341
|
-
@blur="onBlur"
|
|
342
|
-
@change="onChange"
|
|
343
|
-
>
|
|
344
|
-
</slot>
|
|
345
|
-
|
|
346
|
-
<slot name="suffix" />
|
|
347
|
-
<LabeledTooltip
|
|
348
|
-
v-if="hasTooltip && !focused"
|
|
349
|
-
:hover="hoverTooltip"
|
|
350
|
-
:value="tooltipValue"
|
|
351
|
-
:status="status"
|
|
352
|
-
/>
|
|
353
|
-
<LabeledTooltip
|
|
354
|
-
v-if="!!validationMessage"
|
|
355
|
-
:hover="hoverTooltip"
|
|
356
|
-
:value="validationMessage"
|
|
357
|
-
/>
|
|
358
|
-
<div
|
|
359
|
-
v-if="cronHint || subLabel"
|
|
360
|
-
class="sub-label"
|
|
361
|
-
>
|
|
362
|
-
<div
|
|
363
|
-
v-if="cronHint"
|
|
364
|
-
>
|
|
365
|
-
{{ cronHint }}
|
|
366
|
-
</div>
|
|
367
|
-
<div
|
|
368
|
-
v-if="subLabel"
|
|
369
|
-
v-clean-html="subLabel"
|
|
370
|
-
/>
|
|
371
|
-
</div>
|
|
372
|
-
</div>
|
|
373
|
-
</template>
|
|
374
|
-
<style scoped lang="scss">
|
|
375
|
-
.labeled-input.view {
|
|
376
|
-
input {
|
|
377
|
-
text-overflow: ellipsis;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.hideArrows {
|
|
382
|
-
/* Hide arrows on number input when it overlaps with the unit */
|
|
383
|
-
/* Chrome, Safari, Edge, Opera */
|
|
384
|
-
input::-webkit-outer-spin-button,
|
|
385
|
-
input::-webkit-inner-spin-button {
|
|
386
|
-
-webkit-appearance: none;
|
|
387
|
-
margin: 0;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/* Firefox */
|
|
391
|
-
input[type=number] {
|
|
392
|
-
-moz-appearance: textfield;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
</style>
|
|
396
|
-
<style>
|
|
397
|
-
.validation-message {
|
|
398
|
-
padding: 5px;
|
|
399
|
-
position: absolute;
|
|
400
|
-
bottom: -35px;
|
|
401
|
-
}
|
|
402
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as LabeledInput } from './LabeledInput.vue';
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { RadioButton } from './index';
|
|
3
|
-
|
|
4
|
-
describe('radioButton.vue', () => {
|
|
5
|
-
it('renders label slot contents', () => {
|
|
6
|
-
const wrapper = shallowMount(RadioButton, { slots: { label: 'Test Label' }, propsData: { val: {}, value: {} } });
|
|
7
|
-
|
|
8
|
-
expect(wrapper.find('.radio-label').text()).toBe('Test Label');
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('renders label prop contents', () => {
|
|
12
|
-
const wrapper = shallowMount(
|
|
13
|
-
RadioButton,
|
|
14
|
-
{
|
|
15
|
-
propsData: {
|
|
16
|
-
label: 'Test Label', val: {}, value: {}
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
expect(wrapper.find('.radio-label').text()).toBe('Test Label');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('renders slot contents when both slot and label prop are provided', () => {
|
|
24
|
-
const wrapper = shallowMount(RadioButton, {
|
|
25
|
-
slots: { label: 'Test Label - Slot' },
|
|
26
|
-
propsData: {
|
|
27
|
-
label: 'Test Label - Props', val: {}, value: {}
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
expect(wrapper.find('.radio-label').text()).toBe('Test Label - Slot');
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue';
|
|
3
|
-
import { _VIEW } from '@shell/config/query-params';
|
|
4
|
-
import { randomStr } from '@shell/utils/string';
|
|
5
|
-
|
|
6
|
-
export default defineComponent({
|
|
7
|
-
props: {
|
|
8
|
-
/**
|
|
9
|
-
* The name of the input, for grouping.
|
|
10
|
-
*/
|
|
11
|
-
name: {
|
|
12
|
-
type: String,
|
|
13
|
-
default: ''
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The value for this option.
|
|
18
|
-
*/
|
|
19
|
-
val: {
|
|
20
|
-
required: true,
|
|
21
|
-
validator: () => true
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The selected value.
|
|
26
|
-
*/
|
|
27
|
-
value: {
|
|
28
|
-
required: true,
|
|
29
|
-
validator: () => true
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The label shown next to the radio.
|
|
34
|
-
*/
|
|
35
|
-
label: {
|
|
36
|
-
type: String,
|
|
37
|
-
default: ''
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Disable the radio.
|
|
42
|
-
*/
|
|
43
|
-
disabled: {
|
|
44
|
-
type: Boolean,
|
|
45
|
-
default: false
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* The radio editing mode.
|
|
50
|
-
* @values _EDIT, _VIEW
|
|
51
|
-
*/
|
|
52
|
-
mode: {
|
|
53
|
-
type: String,
|
|
54
|
-
default: 'edit'
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The i18n key to use for the radio description.
|
|
59
|
-
*/
|
|
60
|
-
descriptionKey: {
|
|
61
|
-
type: String,
|
|
62
|
-
default: null
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* The radio description.
|
|
67
|
-
*/
|
|
68
|
-
description: {
|
|
69
|
-
type: String,
|
|
70
|
-
default: null
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
data() {
|
|
75
|
-
return {
|
|
76
|
-
isChecked: this.value === this.val,
|
|
77
|
-
randomString: `${ randomStr() }-radio`,
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
computed: {
|
|
82
|
-
/**
|
|
83
|
-
* Determines if the radio is disabled.
|
|
84
|
-
*/
|
|
85
|
-
isDisabled(): boolean {
|
|
86
|
-
return this.mode === _VIEW || this.disabled;
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Determines if the label for the radio should be muted.
|
|
91
|
-
*/
|
|
92
|
-
muteLabel(): boolean {
|
|
93
|
-
// Don't mute the label if the mode is view and the button is checked
|
|
94
|
-
return this.disabled && !(this.mode === _VIEW && this.isChecked);
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Determines if the description slot is in use.
|
|
99
|
-
*/
|
|
100
|
-
hasDescriptionSlot(): boolean {
|
|
101
|
-
return !!this.$slots.description;
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
hasLabelSlot(): boolean {
|
|
105
|
-
return !!this.$slots.label || !!this.$scopedSlots.label;
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
watch: {
|
|
110
|
-
value(neu) {
|
|
111
|
-
this.isChecked = this.val === neu;
|
|
112
|
-
if (this.isChecked) {
|
|
113
|
-
(this.$refs.custom as HTMLElement).focus();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
methods: {
|
|
119
|
-
/**
|
|
120
|
-
* Emits the input event.
|
|
121
|
-
*/
|
|
122
|
-
clicked(event: MouseEvent | KeyboardEvent) {
|
|
123
|
-
const target = event.target;
|
|
124
|
-
|
|
125
|
-
if (this.isDisabled || (target instanceof HTMLElement && target.tagName === 'A')) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
this.$emit('input', this.val);
|
|
130
|
-
},
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
</script>
|
|
134
|
-
|
|
135
|
-
<template>
|
|
136
|
-
<label
|
|
137
|
-
:class="{'disabled': isDisabled, 'radio-container': true}"
|
|
138
|
-
@keydown.enter="clicked($event)"
|
|
139
|
-
@keydown.space="clicked($event)"
|
|
140
|
-
@click.stop="clicked($event)"
|
|
141
|
-
>
|
|
142
|
-
<input
|
|
143
|
-
:id="randomString"
|
|
144
|
-
:disabled="isDisabled"
|
|
145
|
-
:name="name"
|
|
146
|
-
:value="''+val"
|
|
147
|
-
:checked="isChecked"
|
|
148
|
-
type="radio"
|
|
149
|
-
:tabindex="-1"
|
|
150
|
-
@click.stop.prevent
|
|
151
|
-
>
|
|
152
|
-
<span
|
|
153
|
-
ref="custom"
|
|
154
|
-
:class="[ isDisabled ? 'text-muted' : '', 'radio-custom']"
|
|
155
|
-
:tabindex="isDisabled ? -1 : 0"
|
|
156
|
-
:aria-label="label"
|
|
157
|
-
:aria-checked="isChecked"
|
|
158
|
-
role="radio"
|
|
159
|
-
/>
|
|
160
|
-
<div class="labeling">
|
|
161
|
-
<label
|
|
162
|
-
:class="[ muteLabel ? 'text-muted' : '', 'radio-label', 'm-0']"
|
|
163
|
-
:for="name"
|
|
164
|
-
>
|
|
165
|
-
<slot
|
|
166
|
-
v-if="hasLabelSlot"
|
|
167
|
-
name="label"
|
|
168
|
-
>
|
|
169
|
-
<!-- slot content -->
|
|
170
|
-
</slot>
|
|
171
|
-
<span
|
|
172
|
-
v-else-if="label"
|
|
173
|
-
v-clean-html="label"
|
|
174
|
-
/>
|
|
175
|
-
</label>
|
|
176
|
-
<div
|
|
177
|
-
v-if="descriptionKey || description"
|
|
178
|
-
class="radio-button-outer-container-description"
|
|
179
|
-
>
|
|
180
|
-
<t
|
|
181
|
-
v-if="descriptionKey"
|
|
182
|
-
:k="descriptionKey"
|
|
183
|
-
/>
|
|
184
|
-
<template v-else-if="description">
|
|
185
|
-
{{ description }}
|
|
186
|
-
</template>
|
|
187
|
-
</div>
|
|
188
|
-
<div
|
|
189
|
-
v-else-if="hasDescriptionSlot"
|
|
190
|
-
class="radio-button-outer-container-description"
|
|
191
|
-
>
|
|
192
|
-
<slot name="description" />
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
</label>
|
|
196
|
-
</template>
|
|
197
|
-
|
|
198
|
-
<style lang='scss'>
|
|
199
|
-
$fontColor: var(--input-label);
|
|
200
|
-
|
|
201
|
-
.radio-view {
|
|
202
|
-
display: flex;
|
|
203
|
-
flex-direction: column;
|
|
204
|
-
LABEL {
|
|
205
|
-
color: var(--input-label);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.radio-group {
|
|
210
|
-
.text-label {
|
|
211
|
-
display: block;
|
|
212
|
-
padding-bottom: 5px;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.radio-container {
|
|
217
|
-
position: relative;
|
|
218
|
-
display: inline-flex;
|
|
219
|
-
align-items: flex-start;
|
|
220
|
-
margin: 0;
|
|
221
|
-
user-select: none;
|
|
222
|
-
border-radius: var(--border-radius);
|
|
223
|
-
padding-bottom: 5px;
|
|
224
|
-
|
|
225
|
-
&,
|
|
226
|
-
.radio-label,
|
|
227
|
-
.radio-button-outer-container-description {
|
|
228
|
-
cursor: pointer;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
&.disabled,
|
|
232
|
-
&.disabled .radio-label,
|
|
233
|
-
&.disabled .radio-button-outer-container-description {
|
|
234
|
-
cursor: not-allowed
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.radio-custom {
|
|
238
|
-
height: 14px;
|
|
239
|
-
width: 14px;
|
|
240
|
-
min-height: 14px;
|
|
241
|
-
min-width: 14px;
|
|
242
|
-
background-color: var(--input-bg);
|
|
243
|
-
border-radius: 50%;
|
|
244
|
-
transition: all 0.3s ease-out;
|
|
245
|
-
border: 1.5px solid var(--border);
|
|
246
|
-
margin-top: 5px;
|
|
247
|
-
|
|
248
|
-
&:focus {
|
|
249
|
-
outline: none;
|
|
250
|
-
border-radius: 50%;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
input {
|
|
255
|
-
display: none;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.radio-custom {
|
|
259
|
-
&[aria-checked="true"] {
|
|
260
|
-
background-color: var(--primary);
|
|
261
|
-
-webkit-transform: rotate(0deg) scale(1);
|
|
262
|
-
-ms-transform: rotate(0deg) scale(1);
|
|
263
|
-
transform: rotate(0deg) scale(1);
|
|
264
|
-
opacity:1;
|
|
265
|
-
border: 1.5px solid var(--primary);
|
|
266
|
-
|
|
267
|
-
// Ensure that checked radio buttons are muted but still visibly selected when muted
|
|
268
|
-
&.text-muted {
|
|
269
|
-
opacity: .25;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
input:disabled ~ .radio-custom:not([aria-checked="true"]) {
|
|
275
|
-
background-color: var(--disabled-bg);
|
|
276
|
-
opacity: .25;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.radio-button-outer-container-description {
|
|
280
|
-
color: $fontColor;
|
|
281
|
-
font-size: 11px;
|
|
282
|
-
margin-top: 5px;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.labeling {
|
|
286
|
-
display: inline-flex;
|
|
287
|
-
flex-direction: column;
|
|
288
|
-
|
|
289
|
-
margin: 3px 10px 0px 5px;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
</style>
|