@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.
Files changed (200) hide show
  1. package/assets/images/providers/sks.svg +1 -0
  2. package/assets/styles/base/_helpers.scss +4 -0
  3. package/assets/styles/base/_variables.scss +1 -0
  4. package/assets/translations/en-us.yaml +31 -15
  5. package/assets/translations/zh-hans.yaml +4 -3
  6. package/chart/monitoring/index.vue +3 -1
  7. package/components/ActionDropdownShell.vue +71 -0
  8. package/components/AppModal.vue +18 -4
  9. package/components/CommunityLinks.vue +3 -58
  10. package/components/CruResource.vue +6 -1
  11. package/components/ExplorerProjectsNamespaces.vue +12 -4
  12. package/components/GlobalRoleBindings.vue +5 -1
  13. package/components/GrowlManager.vue +1 -0
  14. package/components/LandingPagePreference.vue +2 -0
  15. package/components/LocaleSelector.vue +1 -1
  16. package/components/ModalManager.vue +55 -0
  17. package/components/PromptModal.vue +47 -8
  18. package/components/ResourceDetail/Masthead.vue +38 -12
  19. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  20. package/components/ResourceDetail/index.vue +47 -12
  21. package/components/ResourceTable.vue +54 -19
  22. package/components/SideNav.vue +5 -1
  23. package/components/SlideInPanelManager.vue +126 -0
  24. package/components/SortableTable/THead.vue +5 -2
  25. package/components/SortableTable/actions.js +1 -1
  26. package/components/SortableTable/index.vue +54 -40
  27. package/components/SortableTable/paging.js +16 -19
  28. package/components/SortableTable/selection.js +0 -11
  29. package/components/Wizard.vue +2 -2
  30. package/components/__tests__/ModalManager.spec.ts +176 -0
  31. package/components/__tests__/PromptModal.test.ts +148 -0
  32. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  33. package/components/auth/AuthBanner.vue +13 -11
  34. package/components/auth/Principal.vue +1 -0
  35. package/components/auth/login/ldap.vue +1 -1
  36. package/components/fleet/FleetResources.vue +21 -6
  37. package/components/form/ArrayList.vue +10 -6
  38. package/components/form/BannerSettings.vue +17 -2
  39. package/components/form/ColorInput.vue +35 -6
  40. package/components/form/EnvVars.vue +1 -0
  41. package/components/form/LabeledSelect.vue +18 -23
  42. package/components/form/MatchExpressions.vue +4 -1
  43. package/components/form/NameNsDescription.vue +5 -1
  44. package/components/form/NotificationSettings.vue +15 -1
  45. package/components/form/Password.vue +1 -0
  46. package/components/form/Probe.vue +1 -0
  47. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +15 -34
  48. package/components/form/SSHKnownHosts/index.vue +14 -11
  49. package/components/form/Select.vue +1 -15
  50. package/components/form/ValueFromResource.vue +12 -12
  51. package/components/form/__tests__/ArrayList.test.ts +2 -2
  52. package/components/form/__tests__/ColorInput.test.ts +35 -0
  53. package/components/form/__tests__/LabeledSelect.test.ts +40 -0
  54. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -2
  55. package/components/nav/Group.vue +12 -4
  56. package/components/nav/Header.vue +16 -43
  57. package/components/nav/NamespaceFilter.vue +134 -86
  58. package/components/nav/TopLevelMenu.vue +4 -5
  59. package/components/nav/WindowManager/ContainerLogs.vue +87 -61
  60. package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
  61. package/components/templates/default.vue +6 -3
  62. package/components/templates/home.vue +6 -0
  63. package/components/templates/plain.vue +6 -3
  64. package/composables/focusTrap.ts +12 -4
  65. package/config/store.js +4 -0
  66. package/config/uiplugins.js +5 -1
  67. package/core/types.ts +7 -6
  68. package/detail/catalog.cattle.io.app.vue +6 -1
  69. package/detail/fleet.cattle.io.bundle.vue +70 -6
  70. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  71. package/detail/namespace.vue +0 -3
  72. package/detail/node.vue +17 -13
  73. package/detail/provisioning.cattle.io.cluster.vue +72 -6
  74. package/dialog/AddCustomBadgeDialog.vue +0 -1
  75. package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
  76. package/dialog/AssignToDialog.vue +176 -0
  77. package/dialog/ChangePasswordDialog.vue +106 -0
  78. package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
  79. package/dialog/DisableAuthProviderDialog.vue +101 -0
  80. package/dialog/DrainNode.vue +1 -1
  81. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
  82. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
  83. package/dialog/FeatureFlagListDialog.vue +288 -0
  84. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  85. package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
  86. package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
  87. package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -62
  88. package/dialog/MoveNamespaceDialog.vue +157 -0
  89. package/dialog/ScalePoolDownDialog.vue +1 -1
  90. package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
  91. package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
  92. package/dialog/WechatDialog.vue +57 -0
  93. package/edit/auth/azuread.vue +1 -1
  94. package/edit/auth/github.vue +1 -1
  95. package/edit/auth/googleoauth.vue +1 -1
  96. package/edit/auth/ldap/index.vue +1 -1
  97. package/edit/auth/oidc.vue +1 -1
  98. package/edit/auth/saml.vue +1 -1
  99. package/edit/cloudcredential.vue +24 -10
  100. package/edit/management.cattle.io.user.vue +28 -3
  101. package/edit/namespace.vue +1 -4
  102. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
  103. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -10
  104. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
  105. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
  106. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
  107. package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
  108. package/edit/provisioning.cattle.io.cluster/rke2.vue +24 -7
  109. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
  110. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +4 -1
  111. package/initialize/install-plugins.js +2 -1
  112. package/list/harvesterhci.io.management.cluster.vue +4 -1
  113. package/list/management.cattle.io.feature.vue +4 -288
  114. package/machine-config/azure.vue +16 -4
  115. package/mixins/vue-select-overrides.js +0 -4
  116. package/models/fleet.cattle.io.cluster.js +8 -2
  117. package/models/fleet.cattle.io.gitrepo.js +8 -34
  118. package/models/management.cattle.io.feature.js +7 -1
  119. package/models/namespace.js +7 -1
  120. package/package.json +1 -1
  121. package/pages/about.vue +13 -3
  122. package/pages/account/index.vue +12 -5
  123. package/pages/auth/login.vue +7 -4
  124. package/pages/auth/setup.vue +1 -0
  125. package/pages/auth/verify.vue +9 -7
  126. package/pages/c/_cluster/apps/charts/install.vue +26 -26
  127. package/pages/c/_cluster/auth/config/index.vue +10 -12
  128. package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
  129. package/pages/c/_cluster/explorer/index.vue +17 -15
  130. package/pages/c/_cluster/istio/index.vue +2 -2
  131. package/pages/c/_cluster/longhorn/index.vue +1 -1
  132. package/pages/c/_cluster/monitoring/index.vue +1 -1
  133. package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
  134. package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
  135. package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
  136. package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
  137. package/pages/c/_cluster/neuvector/index.vue +1 -1
  138. package/pages/c/_cluster/settings/banners.vue +4 -3
  139. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
  140. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
  141. package/pages/c/_cluster/uiplugins/index.vue +98 -55
  142. package/pages/diagnostic.vue +12 -9
  143. package/pages/fail-whale.vue +8 -5
  144. package/pages/prefs.vue +7 -6
  145. package/plugins/internal-api/index.ts +37 -0
  146. package/plugins/internal-api/shared/base-api.ts +13 -0
  147. package/plugins/internal-api/shell/shell.api.ts +108 -0
  148. package/plugins/steve/actions.js +0 -12
  149. package/public/index.html +1 -0
  150. package/rancher-components/Card/Card.vue +1 -1
  151. package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
  152. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
  153. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
  154. package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
  155. package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
  156. package/rancher-components/Form/Radio/RadioButton.vue +20 -4
  157. package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
  158. package/rancher-components/Form/Radio/RadioGroup.vue +75 -35
  159. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
  160. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
  161. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
  162. package/rancher-components/RcButton/RcButton.vue +2 -1
  163. package/rancher-components/RcButton/types.ts +1 -0
  164. package/rancher-components/RcDropdown/RcDropdown.vue +17 -6
  165. package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
  166. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
  167. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
  168. package/rancher-components/RcDropdown/index.ts +2 -0
  169. package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
  170. package/scripts/extension/bundle +20 -0
  171. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
  172. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  173. package/scripts/extension/helmpatch +44 -31
  174. package/scripts/extension/publish +12 -13
  175. package/scripts/typegen.sh +2 -4
  176. package/store/action-menu.js +26 -56
  177. package/store/index.js +5 -0
  178. package/store/modal.ts +71 -0
  179. package/store/slideInPanel.ts +47 -0
  180. package/store/type-map.js +8 -1
  181. package/store/type-map.utils.ts +4 -4
  182. package/types/global-vue.d.ts +5 -0
  183. package/types/internal-api/shell/growl.d.ts +25 -0
  184. package/types/internal-api/shell/modal.d.ts +77 -0
  185. package/types/internal-api/shell/slideIn.d.ts +15 -0
  186. package/types/resources/fleet.d.ts +0 -14
  187. package/types/shell/index.d.ts +35 -23
  188. package/types/vue-shim.d.ts +4 -1
  189. package/utils/__mocks__/tabbable.js +13 -0
  190. package/utils/__tests__/object.test.ts +38 -4
  191. package/utils/fleet.ts +15 -73
  192. package/utils/object.js +48 -5
  193. package/utils/validators/formRules/__tests__/index.test.ts +10 -1
  194. package/utils/validators/formRules/index.ts +27 -3
  195. package/components/AssignTo.vue +0 -199
  196. package/components/DisableAuthProviderModal.vue +0 -115
  197. package/components/MoveModal.vue +0 -167
  198. package/components/PromptChangePassword.vue +0 -123
  199. package/components/fleet/FleetBundleResources.vue +0 -86
  200. 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
- defineProps<{
28
- ariaLabel?: string
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="'bottom-end'"
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 { inject } from 'vue';
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, dropdownItems } = inject<DropdownContext>('dropdownContext') || defaultContext;
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
+ };
@@ -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: http://{{ include "extension-server.fullname" . }}.{{ .Release.Namespace }}.svc
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 }}
@@ -3,6 +3,8 @@ fullnameOverride: ""
3
3
  plugin:
4
4
  enabled: true
5
5
  versionOverride: ""
6
+ endpoint: ""
7
+ compressedEndpoint: ""
6
8
  noCache: false
7
9
  noAuth: false
8
10
  metadata: {}
@@ -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 destFolder = process.argv[2];
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 updated = false;
39
-
40
- // Add in annotations to match any rules in the package file
41
- if (pkgFile.rancher && typeof pkgFile.rancher === 'object') {
42
- // See if there are any annotations and merge them in, if there are
43
- if (pkgFile.rancher.annotations) {
44
- chart.annotations = chart.annotations || {};
45
- Object.keys(pkgFile.rancher.annotations).forEach((key) => {
46
- chart.annotations[key] = pkgFile.rancher.annotations[key];
47
- updated = true;
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 (updated) {
53
- // Write out updated file
54
- const str = yaml.dump(chart);
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
- const valuesYaml = yaml.dump(values, { quotingType: '"' });
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
- fs.writeFileSync(valuesFile, valuesYaml, 'utf8');
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
- pushd ${CHART_FOLDER}/templates > /dev/null
363
-
364
- if [ "${GITHUB_BUILD}" == "true" ]; then
365
- echo "Patching for GitHub build"
366
- ENDPOINT=https://raw.githubusercontent.com/${GITHUB_SOURCE}/${GITHUB_BRANCH}/extensions/${pkg}/${PKG_VERSION}
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"
@@ -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
- # Copy in the vue shim type definitions
67
- if [ -f "$BASE_DIR/shell/types/vue-shim.d" ]; then
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