@rancher/shell 3.0.5-rc.1 → 3.0.5-rc.2
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/sks.svg +1 -0
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_variables.scss +1 -0
- package/assets/translations/en-us.yaml +31 -15
- package/assets/translations/zh-hans.yaml +4 -3
- package/chart/monitoring/index.vue +3 -1
- package/components/ActionDropdownShell.vue +71 -0
- package/components/AppModal.vue +18 -4
- package/components/CommunityLinks.vue +3 -58
- package/components/CruResource.vue +6 -1
- package/components/ExplorerProjectsNamespaces.vue +12 -4
- package/components/GlobalRoleBindings.vue +5 -1
- package/components/GrowlManager.vue +1 -0
- package/components/LandingPagePreference.vue +2 -0
- package/components/LocaleSelector.vue +1 -1
- package/components/ModalManager.vue +55 -0
- package/components/PromptModal.vue +47 -8
- package/components/ResourceDetail/Masthead.vue +38 -12
- package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
- package/components/ResourceDetail/index.vue +47 -12
- package/components/ResourceTable.vue +54 -19
- package/components/SideNav.vue +5 -1
- package/components/SlideInPanelManager.vue +126 -0
- package/components/SortableTable/THead.vue +5 -2
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +54 -40
- package/components/SortableTable/paging.js +16 -19
- package/components/SortableTable/selection.js +0 -11
- package/components/Wizard.vue +2 -2
- package/components/__tests__/ModalManager.spec.ts +176 -0
- package/components/__tests__/PromptModal.test.ts +148 -0
- package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
- package/components/auth/AuthBanner.vue +13 -11
- package/components/auth/Principal.vue +1 -0
- package/components/auth/login/ldap.vue +1 -1
- package/components/fleet/FleetResources.vue +21 -6
- package/components/form/ArrayList.vue +10 -6
- package/components/form/BannerSettings.vue +17 -2
- package/components/form/ColorInput.vue +35 -6
- package/components/form/EnvVars.vue +1 -0
- package/components/form/LabeledSelect.vue +18 -23
- package/components/form/MatchExpressions.vue +4 -1
- package/components/form/NameNsDescription.vue +5 -1
- package/components/form/NotificationSettings.vue +15 -1
- package/components/form/Password.vue +1 -0
- package/components/form/Probe.vue +1 -0
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +15 -34
- package/components/form/SSHKnownHosts/index.vue +14 -11
- package/components/form/Select.vue +1 -15
- package/components/form/ValueFromResource.vue +12 -12
- package/components/form/__tests__/ArrayList.test.ts +2 -2
- package/components/form/__tests__/ColorInput.test.ts +35 -0
- package/components/form/__tests__/LabeledSelect.test.ts +40 -0
- package/components/form/__tests__/SSHKnownHosts.test.ts +11 -2
- package/components/nav/Group.vue +12 -4
- package/components/nav/Header.vue +16 -43
- package/components/nav/NamespaceFilter.vue +134 -86
- package/components/nav/TopLevelMenu.vue +4 -5
- package/components/nav/WindowManager/ContainerLogs.vue +87 -61
- package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
- package/components/templates/default.vue +6 -3
- package/components/templates/home.vue +6 -0
- package/components/templates/plain.vue +6 -3
- package/composables/focusTrap.ts +12 -4
- package/config/store.js +4 -0
- package/config/uiplugins.js +5 -1
- package/core/types.ts +7 -6
- package/detail/catalog.cattle.io.app.vue +6 -1
- package/detail/fleet.cattle.io.bundle.vue +70 -6
- package/detail/fleet.cattle.io.gitrepo.vue +1 -1
- package/detail/namespace.vue +0 -3
- package/detail/node.vue +17 -13
- package/detail/provisioning.cattle.io.cluster.vue +72 -6
- package/dialog/AddCustomBadgeDialog.vue +0 -1
- package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
- package/dialog/AssignToDialog.vue +176 -0
- package/dialog/ChangePasswordDialog.vue +106 -0
- package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
- package/dialog/DisableAuthProviderDialog.vue +101 -0
- package/dialog/DrainNode.vue +1 -1
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
- package/dialog/FeatureFlagListDialog.vue +288 -0
- package/dialog/ForceMachineRemoveDialog.vue +1 -1
- package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
- package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
- package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -62
- package/dialog/MoveNamespaceDialog.vue +157 -0
- package/dialog/ScalePoolDownDialog.vue +1 -1
- package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
- package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
- package/dialog/WechatDialog.vue +57 -0
- package/edit/auth/azuread.vue +1 -1
- package/edit/auth/github.vue +1 -1
- package/edit/auth/googleoauth.vue +1 -1
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +1 -1
- package/edit/auth/saml.vue +1 -1
- package/edit/cloudcredential.vue +24 -10
- package/edit/management.cattle.io.user.vue +28 -3
- package/edit/namespace.vue +1 -4
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -10
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +24 -7
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +4 -1
- package/initialize/install-plugins.js +2 -1
- package/list/harvesterhci.io.management.cluster.vue +4 -1
- package/list/management.cattle.io.feature.vue +4 -288
- package/machine-config/azure.vue +16 -4
- package/mixins/vue-select-overrides.js +0 -4
- package/models/fleet.cattle.io.cluster.js +8 -2
- package/models/fleet.cattle.io.gitrepo.js +8 -34
- package/models/management.cattle.io.feature.js +7 -1
- package/models/namespace.js +7 -1
- package/package.json +1 -1
- package/pages/about.vue +13 -3
- package/pages/account/index.vue +12 -5
- package/pages/auth/login.vue +7 -4
- package/pages/auth/setup.vue +1 -0
- package/pages/auth/verify.vue +9 -7
- package/pages/c/_cluster/apps/charts/install.vue +26 -26
- package/pages/c/_cluster/auth/config/index.vue +10 -12
- package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
- package/pages/c/_cluster/explorer/index.vue +17 -15
- package/pages/c/_cluster/istio/index.vue +2 -2
- package/pages/c/_cluster/longhorn/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
- package/pages/c/_cluster/neuvector/index.vue +1 -1
- package/pages/c/_cluster/settings/banners.vue +4 -3
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
- package/pages/c/_cluster/uiplugins/index.vue +98 -55
- package/pages/diagnostic.vue +12 -9
- package/pages/fail-whale.vue +8 -5
- package/pages/prefs.vue +7 -6
- package/plugins/internal-api/index.ts +37 -0
- package/plugins/internal-api/shared/base-api.ts +13 -0
- package/plugins/internal-api/shell/shell.api.ts +108 -0
- package/plugins/steve/actions.js +0 -12
- package/public/index.html +1 -0
- package/rancher-components/Card/Card.vue +1 -1
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
- package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
- package/rancher-components/Form/Radio/RadioButton.vue +20 -4
- package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +75 -35
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
- package/rancher-components/RcButton/RcButton.vue +2 -1
- package/rancher-components/RcButton/types.ts +1 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +17 -6
- package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
- package/rancher-components/RcDropdown/index.ts +2 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
- package/scripts/extension/bundle +20 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
- package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
- package/scripts/extension/helmpatch +44 -31
- package/scripts/extension/publish +12 -13
- package/scripts/typegen.sh +2 -4
- package/store/action-menu.js +26 -56
- package/store/index.js +5 -0
- package/store/modal.ts +71 -0
- package/store/slideInPanel.ts +47 -0
- package/store/type-map.js +8 -1
- package/store/type-map.utils.ts +4 -4
- package/types/global-vue.d.ts +5 -0
- package/types/internal-api/shell/growl.d.ts +25 -0
- package/types/internal-api/shell/modal.d.ts +77 -0
- package/types/internal-api/shell/slideIn.d.ts +15 -0
- package/types/resources/fleet.d.ts +0 -14
- package/types/shell/index.d.ts +35 -23
- package/types/vue-shim.d.ts +4 -1
- package/utils/__mocks__/tabbable.js +13 -0
- package/utils/__tests__/object.test.ts +38 -4
- package/utils/fleet.ts +15 -73
- package/utils/object.js +48 -5
- package/utils/validators/formRules/__tests__/index.test.ts +10 -1
- package/utils/validators/formRules/index.ts +27 -3
- package/components/AssignTo.vue +0 -199
- package/components/DisableAuthProviderModal.vue +0 -115
- package/components/MoveModal.vue +0 -167
- package/components/PromptChangePassword.vue +0 -123
- package/components/fleet/FleetBundleResources.vue +0 -86
- package/types/vue-shim.d +0 -20
|
@@ -24,9 +24,18 @@ import { ref } from 'vue';
|
|
|
24
24
|
import { useClickOutside } from '@shell/composables/useClickOutside';
|
|
25
25
|
import { useDropdownContext } from '@components/RcDropdown/useDropdownContext';
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
import type { Placement } from 'floating-vue';
|
|
28
|
+
|
|
29
|
+
withDefaults(
|
|
30
|
+
defineProps<{
|
|
31
|
+
// eslint-disable-next-line vue/require-default-prop
|
|
32
|
+
ariaLabel?: string;
|
|
33
|
+
// eslint-disable-next-line vue/require-default-prop
|
|
34
|
+
distance?: number;
|
|
35
|
+
placement?: Placement;
|
|
36
|
+
}>(),
|
|
37
|
+
{ placement: 'bottom-end' }
|
|
38
|
+
);
|
|
30
39
|
|
|
31
40
|
const emit = defineEmits(['update:open']);
|
|
32
41
|
|
|
@@ -61,7 +70,8 @@ const applyShow = () => {
|
|
|
61
70
|
:shown="isMenuOpen"
|
|
62
71
|
:auto-hide="false"
|
|
63
72
|
:container="popperContainer"
|
|
64
|
-
:placement="
|
|
73
|
+
:placement="placement"
|
|
74
|
+
:distance="distance"
|
|
65
75
|
@apply-show="applyShow"
|
|
66
76
|
>
|
|
67
77
|
<slot name="default">
|
|
@@ -78,8 +88,8 @@ const applyShow = () => {
|
|
|
78
88
|
dropdown-menu-collection
|
|
79
89
|
:aria-label="ariaLabel || 'Dropdown Menu'"
|
|
80
90
|
@keydown="handleKeydown"
|
|
81
|
-
@keydown.down="setFocus('down')"
|
|
82
|
-
@keydown.up="setFocus('up')"
|
|
91
|
+
@keydown.down.prevent="setFocus('down')"
|
|
92
|
+
@keydown.up.prevent="setFocus('up')"
|
|
83
93
|
>
|
|
84
94
|
<slot name="dropdownCollection">
|
|
85
95
|
<!--Empty slot content-->
|
|
@@ -111,6 +121,7 @@ const applyShow = () => {
|
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
.v-popper__inner {
|
|
124
|
+
overflow: unset;
|
|
114
125
|
padding: 10px 0 10px 0;
|
|
115
126
|
}
|
|
116
127
|
}
|
|
@@ -2,56 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* An item for a dropdown menu. Used in conjunction with RcDropdown.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { DropdownContext, defaultContext } from './types';
|
|
5
|
+
import { useDropdownItem } from '@components/RcDropdown/useDropdownItem';
|
|
7
6
|
|
|
8
7
|
const props = defineProps({ disabled: Boolean });
|
|
9
8
|
const emits = defineEmits(['click']);
|
|
10
9
|
|
|
11
|
-
const { close,
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Handles keydown events to navigate between dropdown items.
|
|
15
|
-
* @param {KeyboardEvent} e - The keydown event.
|
|
16
|
-
*/
|
|
17
|
-
const handleKeydown = (e: KeyboardEvent) => {
|
|
18
|
-
const activeItem = document.activeElement;
|
|
19
|
-
|
|
20
|
-
const activeIndex = dropdownItems.value.indexOf(activeItem || new HTMLElement());
|
|
21
|
-
|
|
22
|
-
if (activeIndex < 0) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const shouldAdvance = e.key === 'ArrowDown';
|
|
27
|
-
|
|
28
|
-
const newIndex = findNewIndex(shouldAdvance, activeIndex, dropdownItems.value);
|
|
29
|
-
|
|
30
|
-
if (dropdownItems.value[newIndex] instanceof HTMLElement) {
|
|
31
|
-
dropdownItems.value[newIndex].focus();
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Finds the new index for the dropdown item based on the key pressed.
|
|
37
|
-
* @param shouldAdvance - Whether to advance to the next or previous item.
|
|
38
|
-
* @param activeIndex - Current active index.
|
|
39
|
-
* @param itemsArr - Array of dropdown items.
|
|
40
|
-
* @returns The new index.
|
|
41
|
-
*/
|
|
42
|
-
const findNewIndex = (shouldAdvance: boolean, activeIndex: number, itemsArr: Element[]) => {
|
|
43
|
-
const newIndex = shouldAdvance ? activeIndex + 1 : activeIndex - 1;
|
|
44
|
-
|
|
45
|
-
if (newIndex > itemsArr.length - 1) {
|
|
46
|
-
return 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (newIndex < 0) {
|
|
50
|
-
return itemsArr.length - 1;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return newIndex;
|
|
54
|
-
};
|
|
10
|
+
const { handleKeydown, close, handleActivate } = useDropdownItem();
|
|
55
11
|
|
|
56
12
|
const handleClick = (e: MouseEvent) => {
|
|
57
13
|
if (props.disabled) {
|
|
@@ -62,15 +18,6 @@ const handleClick = (e: MouseEvent) => {
|
|
|
62
18
|
close();
|
|
63
19
|
};
|
|
64
20
|
|
|
65
|
-
/**
|
|
66
|
-
* Handles keydown events to activate the dropdown item.
|
|
67
|
-
* @param e - The keydown event.
|
|
68
|
-
*/
|
|
69
|
-
const handleActivate = (e: KeyboardEvent) => {
|
|
70
|
-
if (e?.target instanceof HTMLElement) {
|
|
71
|
-
e?.target?.click();
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
21
|
</script>
|
|
75
22
|
|
|
76
23
|
<template>
|
|
@@ -83,7 +30,7 @@ const handleActivate = (e: KeyboardEvent) => {
|
|
|
83
30
|
:aria-disabled="disabled || false"
|
|
84
31
|
@click.stop="handleClick"
|
|
85
32
|
@keydown.enter.space="handleActivate"
|
|
86
|
-
@keydown.up.down.stop="handleKeydown"
|
|
33
|
+
@keydown.up.down.prevent.stop="handleKeydown"
|
|
87
34
|
>
|
|
88
35
|
<slot name="before">
|
|
89
36
|
<!--Empty slot content-->
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* An item for a dropdown menu. Used in conjunction with RcDropdown.
|
|
4
|
+
*/
|
|
5
|
+
import { Checkbox as RcCheckbox } from '@components/Form/Checkbox';
|
|
6
|
+
import { useDropdownItem } from '@components/RcDropdown/useDropdownItem';
|
|
7
|
+
|
|
8
|
+
const props = defineProps({ modelValue: Boolean, disabled: Boolean });
|
|
9
|
+
const emits = defineEmits(['click']);
|
|
10
|
+
|
|
11
|
+
const { handleKeydown, handleActivate } = useDropdownItem();
|
|
12
|
+
|
|
13
|
+
const handleClick = () => {
|
|
14
|
+
if (props.disabled) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
emits('click', !props.modelValue);
|
|
19
|
+
};
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div
|
|
24
|
+
ref="dropdownMenuItem"
|
|
25
|
+
dropdown-menu-item
|
|
26
|
+
tabindex="-1"
|
|
27
|
+
role="menuitemcheckbox"
|
|
28
|
+
:disabled="disabled || null"
|
|
29
|
+
:aria-disabled="disabled || false"
|
|
30
|
+
@click.stop="handleClick"
|
|
31
|
+
@keydown.enter.space="handleActivate"
|
|
32
|
+
@keydown.up.down.prevent.stop="handleKeydown"
|
|
33
|
+
>
|
|
34
|
+
<rc-checkbox :value="modelValue">
|
|
35
|
+
<template #label>
|
|
36
|
+
<slot name="default">
|
|
37
|
+
<!--Empty slot content-->
|
|
38
|
+
</slot>
|
|
39
|
+
</template>
|
|
40
|
+
</rc-checkbox>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<style lang="scss" scoped>
|
|
45
|
+
[dropdown-menu-item] {
|
|
46
|
+
display: flex;
|
|
47
|
+
gap: 8px;
|
|
48
|
+
align-items: center;
|
|
49
|
+
padding: 9px 8px;
|
|
50
|
+
margin: 0 9px;
|
|
51
|
+
border-radius: 4px;
|
|
52
|
+
|
|
53
|
+
&:hover {
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
background-color: var(--dropdown-hover-bg);
|
|
56
|
+
}
|
|
57
|
+
&:focus-visible, &:focus {
|
|
58
|
+
@include focus-outline;
|
|
59
|
+
outline-offset: 0;
|
|
60
|
+
}
|
|
61
|
+
&[disabled] {
|
|
62
|
+
color: var(--disabled-text);
|
|
63
|
+
&:hover {
|
|
64
|
+
cursor: not-allowed;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
</style>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* An item for a dropdown menu. Used in conjunction with RcDropdown.
|
|
4
|
+
*/
|
|
5
|
+
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
6
|
+
import { useDropdownItem } from '@components/RcDropdown/useDropdownItem';
|
|
7
|
+
import { ref } from 'vue';
|
|
8
|
+
|
|
9
|
+
type LabeledSelectComponent = {
|
|
10
|
+
focusSearch: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
defineProps({
|
|
14
|
+
modelValue: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: ''
|
|
17
|
+
},
|
|
18
|
+
disabled: Boolean,
|
|
19
|
+
options: {
|
|
20
|
+
type: Array,
|
|
21
|
+
default() {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
const emits = defineEmits(['click', 'select']);
|
|
27
|
+
|
|
28
|
+
const { handleKeydown, handleActivate } = useDropdownItem();
|
|
29
|
+
|
|
30
|
+
const dropdownMenuItem = ref<HTMLDivElement | null>(null);
|
|
31
|
+
const menuItemSelect = ref<LabeledSelectComponent | null>(null);
|
|
32
|
+
|
|
33
|
+
const handleClick = () => {
|
|
34
|
+
menuItemSelect?.value?.focusSearch();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const focusMenuItem = () => {
|
|
38
|
+
dropdownMenuItem?.value?.focus();
|
|
39
|
+
};
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<div
|
|
44
|
+
ref="dropdownMenuItem"
|
|
45
|
+
dropdown-menu-item
|
|
46
|
+
tabindex="-1"
|
|
47
|
+
role="menuitem"
|
|
48
|
+
:disabled="disabled || null"
|
|
49
|
+
:aria-disabled="disabled || false"
|
|
50
|
+
@click.stop="handleClick"
|
|
51
|
+
@keydown.enter.space="handleActivate"
|
|
52
|
+
@keydown.up.down.prevent.stop="handleKeydown"
|
|
53
|
+
>
|
|
54
|
+
<LabeledSelect
|
|
55
|
+
ref="menuItemSelect"
|
|
56
|
+
:value="modelValue"
|
|
57
|
+
:label="t('wm.containerLogs.range.label')"
|
|
58
|
+
:options="options"
|
|
59
|
+
:clearable="false"
|
|
60
|
+
placement="top"
|
|
61
|
+
@keydown.enter.stop
|
|
62
|
+
@update:value="emits('select', $event)"
|
|
63
|
+
@on-close="focusMenuItem"
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<style lang="scss" scoped>
|
|
69
|
+
[dropdown-menu-item] {
|
|
70
|
+
display: flex;
|
|
71
|
+
gap: 8px;
|
|
72
|
+
align-items: center;
|
|
73
|
+
padding: 9px 8px;
|
|
74
|
+
margin: 0 9px;
|
|
75
|
+
border-radius: 4px;
|
|
76
|
+
|
|
77
|
+
&:hover {
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
background-color: var(--dropdown-hover-bg);
|
|
80
|
+
}
|
|
81
|
+
&:focus-visible, &:focus {
|
|
82
|
+
@include focus-outline;
|
|
83
|
+
outline-offset: 0;
|
|
84
|
+
}
|
|
85
|
+
&[disabled] {
|
|
86
|
+
color: var(--disabled-text);
|
|
87
|
+
&:hover {
|
|
88
|
+
cursor: not-allowed;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { default as RcDropdown } from './RcDropdown.vue';
|
|
2
2
|
export { default as RcDropdownItem } from './RcDropdownItem.vue';
|
|
3
|
+
export { default as RcDropdownItemCheckbox } from './RcDropdownItemCheckbox.vue';
|
|
4
|
+
export { default as RcDropdownItemSelect } from './RcDropdownItemSelect.vue';
|
|
3
5
|
export { default as RcDropdownSeparator } from './RcDropdownSeparator.vue';
|
|
4
6
|
export { default as RcDropdownTrigger } from './RcDropdownTrigger.vue';
|
|
5
7
|
export { default as RcDropdownMenu } from './RcDropdownMenu.vue';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
import { DropdownContext, defaultContext } from './types';
|
|
3
|
+
|
|
4
|
+
export const useDropdownItem = () => {
|
|
5
|
+
const { dropdownItems, close } = inject<DropdownContext>('dropdownContext') || defaultContext;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Handles keydown events to navigate between dropdown items.
|
|
9
|
+
* @param {KeyboardEvent} e - The keydown event.
|
|
10
|
+
*/
|
|
11
|
+
const handleKeydown = (e: KeyboardEvent) => {
|
|
12
|
+
const activeItem = document.activeElement;
|
|
13
|
+
|
|
14
|
+
const activeIndex = dropdownItems.value.indexOf(activeItem || new HTMLElement());
|
|
15
|
+
|
|
16
|
+
if (activeIndex < 0) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const shouldAdvance = e.key === 'ArrowDown';
|
|
21
|
+
|
|
22
|
+
const newIndex = findNewIndex(shouldAdvance, activeIndex, dropdownItems.value);
|
|
23
|
+
|
|
24
|
+
if (dropdownItems.value[newIndex] instanceof HTMLElement) {
|
|
25
|
+
dropdownItems.value[newIndex].focus();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Finds the new index for the dropdown item based on the key pressed.
|
|
31
|
+
* @param shouldAdvance - Whether to advance to the next or previous item.
|
|
32
|
+
* @param activeIndex - Current active index.
|
|
33
|
+
* @param itemsArr - Array of dropdown items.
|
|
34
|
+
* @returns The new index.
|
|
35
|
+
*/
|
|
36
|
+
const findNewIndex = (shouldAdvance: boolean, activeIndex: number, itemsArr: Element[]) => {
|
|
37
|
+
const newIndex = shouldAdvance ? activeIndex + 1 : activeIndex - 1;
|
|
38
|
+
|
|
39
|
+
if (newIndex > itemsArr.length - 1) {
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (newIndex < 0) {
|
|
44
|
+
return itemsArr.length - 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return newIndex;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Handles keydown events to activate the dropdown item.
|
|
52
|
+
* @param e - The keydown event.
|
|
53
|
+
*/
|
|
54
|
+
const handleActivate = (e: KeyboardEvent) => {
|
|
55
|
+
if (e?.target instanceof HTMLElement) {
|
|
56
|
+
e?.target?.click();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
handleKeydown, close, handleActivate
|
|
62
|
+
};
|
|
63
|
+
};
|
package/scripts/extension/bundle
CHANGED
|
@@ -29,12 +29,32 @@ cp -R ${CHART_TEMPLATE}/* ${TMP}/container/
|
|
|
29
29
|
# Copy the plugin assets
|
|
30
30
|
mkdir -p ${TMP}/container/plugin
|
|
31
31
|
|
|
32
|
+
# Copy Helm charts and plugin assets
|
|
32
33
|
cp -R ${BASE_DIR}/assets/* ${TMP}/container/plugin
|
|
33
34
|
cp ${BASE_DIR}/package.json ${TMP}/container/plugin
|
|
34
35
|
cp ${BASE_DIR}/index.yaml ${TMP}/container/
|
|
35
36
|
cp ${BASE_DIR}/index.yaml ${TMP}/container/plugin
|
|
36
37
|
rm -f ${TMP}/container/plugin/report.html
|
|
37
38
|
|
|
39
|
+
# Add extension .tgz files with proper naming
|
|
40
|
+
echo -e "${CYAN}Copying extension archives...${RESET}"
|
|
41
|
+
for pkg_dir in ${BASE_DIR}/extensions/*/; do
|
|
42
|
+
pkg=$(basename "${pkg_dir}")
|
|
43
|
+
echo -e "Processing package: ${pkg}"
|
|
44
|
+
|
|
45
|
+
# Find all .tgz files in the package directory
|
|
46
|
+
for tgz_path in "${pkg_dir}"*.tgz; do
|
|
47
|
+
if [ -f "${tgz_path}" ]; then
|
|
48
|
+
# Extract version from filename
|
|
49
|
+
version=$(basename "${tgz_path}" .tgz)
|
|
50
|
+
compressed_package_name="${pkg}-${version}.tgz"
|
|
51
|
+
|
|
52
|
+
echo "Copying ${tgz_path} to ${TMP}/container/plugin/${compressed_package_name}"
|
|
53
|
+
cp "${tgz_path}" "${TMP}/container/plugin/${compressed_package_name}"
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
done
|
|
57
|
+
|
|
38
58
|
# Generate files.txt for each pkg and move pkg files into relative plugin directories
|
|
39
59
|
for d in ${BASE_DIR}/dist-pkg/*; do
|
|
40
60
|
pkg=$(basename $d)
|
|
@@ -8,7 +8,8 @@ spec:
|
|
|
8
8
|
plugin:
|
|
9
9
|
name: {{ include "extension-server.fullname" . }}
|
|
10
10
|
version: {{ (semver (default .Chart.AppVersion .Values.plugin.versionOverride)).Original }}
|
|
11
|
-
endpoint:
|
|
11
|
+
endpoint: {{ .Values.plugin.endpoint | quote }}
|
|
12
|
+
compressedEndpoint: {{ .Values.plugin.compressedEndpoint | quote }}
|
|
12
13
|
noCache: {{ .Values.plugin.noCache }}
|
|
13
14
|
noAuth: {{ .Values.plugin.noAuth }}
|
|
14
15
|
metadata: {{ include "extension-server.pluginMetadata" . | indent 6 }}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// Update Chart.yaml and values.yaml files
|
|
4
|
-
|
|
5
3
|
const fs = require('fs');
|
|
6
4
|
const path = require('path');
|
|
7
5
|
const yaml = require('js-yaml');
|
|
8
6
|
|
|
9
|
-
// TODO: Should already be in the template
|
|
10
|
-
// const UI_PLUGIN_ANNOTATION_NAME = 'catalog.cattle.io/ui-component';
|
|
11
|
-
// const UI_PLUGIN_ANNOTATION_VALUE = 'plugins';
|
|
12
|
-
|
|
13
7
|
console.log('Helm file update');
|
|
14
8
|
|
|
15
9
|
if (process.argv.length !== 4) {
|
|
@@ -17,12 +11,10 @@ if (process.argv.length !== 4) {
|
|
|
17
11
|
process.exit(1);
|
|
18
12
|
}
|
|
19
13
|
|
|
20
|
-
const
|
|
14
|
+
const chartFolder = process.argv[2];
|
|
21
15
|
const pkgFilePath = process.argv[3];
|
|
22
16
|
|
|
23
17
|
const pkgFile = JSON.parse(fs.readFileSync(pkgFilePath, 'utf8'));
|
|
24
|
-
|
|
25
|
-
const chartFolder = destFolder;
|
|
26
18
|
const chartFile = path.join(chartFolder, 'Chart.yaml');
|
|
27
19
|
const valuesFile = path.join(chartFolder, 'values.yaml');
|
|
28
20
|
|
|
@@ -32,36 +24,57 @@ if (!fs.existsSync(chartFolder)) {
|
|
|
32
24
|
}
|
|
33
25
|
|
|
34
26
|
// --------------------------------------------------------------------------------
|
|
35
|
-
// Chart.yaml
|
|
27
|
+
// Chart.yaml updates (annotations)
|
|
36
28
|
// --------------------------------------------------------------------------------
|
|
37
29
|
const chart = yaml.load(fs.readFileSync(chartFile, 'utf8'));
|
|
38
|
-
let
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
}
|
|
30
|
+
let chartUpdated = false;
|
|
31
|
+
|
|
32
|
+
if (pkgFile.rancher?.annotations) {
|
|
33
|
+
chart.annotations = chart.annotations || {};
|
|
34
|
+
Object.entries(pkgFile.rancher.annotations).forEach(([key, value]) => {
|
|
35
|
+
if (chart.annotations[key] !== value) {
|
|
36
|
+
chart.annotations[key] = value;
|
|
37
|
+
chartUpdated = true;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
50
40
|
}
|
|
51
41
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
fs.writeFileSync(chartFile, str, 'utf8');
|
|
42
|
+
if (chartUpdated) {
|
|
43
|
+
fs.writeFileSync(chartFile, yaml.dump(chart), 'utf8');
|
|
44
|
+
console.log('Updated Chart.yaml annotations');
|
|
57
45
|
}
|
|
58
46
|
|
|
59
47
|
// --------------------------------------------------------------------------------
|
|
60
|
-
// values.yaml
|
|
48
|
+
// values.yaml updates (endpoints)
|
|
61
49
|
// --------------------------------------------------------------------------------
|
|
62
|
-
|
|
63
50
|
const values = yaml.load(fs.readFileSync(valuesFile, 'utf8'));
|
|
64
51
|
|
|
65
|
-
|
|
52
|
+
// Get package metadata from package.json
|
|
53
|
+
const pkgName = pkgFile.name;
|
|
54
|
+
const pkgVersion = pkgFile.version;
|
|
55
|
+
const pkgFullName = `${ pkgName }-${ pkgVersion }`;
|
|
56
|
+
|
|
57
|
+
// Determine build type from environment
|
|
58
|
+
const isGitHubBuild = process.env.GITHUB_BUILD === 'true';
|
|
59
|
+
|
|
60
|
+
// Set endpoints based on build type
|
|
61
|
+
if (isGitHubBuild) {
|
|
62
|
+
const githubSource = process.env.GITHUB_SOURCE;
|
|
63
|
+
const githubBranch = process.env.GITHUB_BRANCH;
|
|
64
|
+
|
|
65
|
+
values.plugin.endpoint = `https://raw.githubusercontent.com/${ githubSource }/${ githubBranch }/extensions/${ pkgName }/${ pkgVersion }`;
|
|
66
|
+
} else {
|
|
67
|
+
const imagePrefix = process.env.IMAGE_PREFIX || '';
|
|
68
|
+
const baseExt = process.env.BASE_EXT;
|
|
69
|
+
|
|
70
|
+
values.plugin.endpoint = `http://${ imagePrefix }${ baseExt }-svc.cattle-ui-plugin-system:8080/plugin/${ pkgFullName }`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Always set compressedEndpoint as endpoint + .tgz
|
|
74
|
+
values.plugin.compressedEndpoint = `${ values.plugin.endpoint }.tgz`;
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
// Write updated values.yaml
|
|
77
|
+
fs.writeFileSync(valuesFile, yaml.dump(values, { quotingType: '"' }), 'utf8');
|
|
78
|
+
console.log('Updated values.yaml endpoints:');
|
|
79
|
+
console.log(`- endpoint: ${ values.plugin.endpoint }`);
|
|
80
|
+
console.log(`- compressedEndpoint: ${ values.plugin.compressedEndpoint }`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
set -eo pipefail
|
|
2
|
+
# set -eo pipefail comment out for now because of a Harvester issue
|
|
3
3
|
|
|
4
4
|
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|
5
5
|
BASE_DIR="$(pwd)"
|
|
@@ -331,6 +331,12 @@ if [ "${UPDATE_LATEST_PACAKGES}" = "true" ]; then
|
|
|
331
331
|
find plugin -type f | sort > files.txt
|
|
332
332
|
popd > /dev/null
|
|
333
333
|
|
|
334
|
+
# --------------------------------------------------------------------------------
|
|
335
|
+
# Package extensions into tgz for the compressedEndpoint
|
|
336
|
+
# --------------------------------------------------------------------------------
|
|
337
|
+
echo -e "${CYAN}Packaging extension into tgz${RESET}"
|
|
338
|
+
tar -czf ${BASE_DIR}/extensions/${pkg}/${PKG_VERSION}.tgz -C ${BASE_DIR}/extensions/${pkg} ${PKG_VERSION}
|
|
339
|
+
|
|
334
340
|
# --------------------------------------------------------------------------------
|
|
335
341
|
# Create the Helm chart
|
|
336
342
|
# --------------------------------------------------------------------------------
|
|
@@ -359,18 +365,11 @@ if [ "${UPDATE_LATEST_PACAKGES}" = "true" ]; then
|
|
|
359
365
|
cp ./pkg/${pkg}/README.md ${CHART_FOLDER}/README.md
|
|
360
366
|
fi
|
|
361
367
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
else
|
|
368
|
-
echo "Patching for container build"
|
|
369
|
-
ENDPOINT=http://${IMAGE_PREFIX}${BASE_EXT}-svc.cattle-ui-plugin-system:8080/plugin/${PKG_NAME}
|
|
370
|
-
fi
|
|
371
|
-
sed -i.bak -e 's@endpoint: .*@endpoint: '"${ENDPOINT}"'@g' cr.yaml
|
|
372
|
-
rm *.bak
|
|
373
|
-
popd > /dev/null
|
|
368
|
+
export GITHUB_BUILD
|
|
369
|
+
export IMAGE_PREFIX
|
|
370
|
+
export BASE_EXT
|
|
371
|
+
export GITHUB_SOURCE
|
|
372
|
+
export GITHUB_BRANCH
|
|
374
373
|
|
|
375
374
|
# Additional patches
|
|
376
375
|
${SCRIPT_DIR}/helmpatch ${CHART_FOLDER} "${BASE_DIR}/pkg/${pkg}/package.json"
|
package/scripts/typegen.sh
CHANGED
|
@@ -63,10 +63,8 @@ rm -rf ${INDEX}
|
|
|
63
63
|
echo "// Auto-generated type definitions for shell" > ${INDEX}
|
|
64
64
|
echo "// Do not modify this file as changes will get overwritten" >> ${INDEX}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
cat "$BASE_DIR/shell/types/vue-shim.d" >> ${INDEX}
|
|
69
|
-
fi
|
|
66
|
+
echo "/// <reference types=\"@rancher/shell/types/vue-shim\" />" >> ${INDEX}
|
|
67
|
+
echo "/// <reference types=\"@rancher/shell/types/global-vue\" />" >> ${INDEX}
|
|
70
68
|
|
|
71
69
|
function processDir() {
|
|
72
70
|
local dir=$1
|