@rancher/shell 3.0.2-rc.2 → 3.0.2-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/base/_basic.scss +7 -8
- package/assets/styles/global/_button.scss +10 -0
- package/assets/styles/global/_form.scss +2 -1
- package/assets/styles/global/_tooltip.scss +2 -2
- package/assets/styles/themes/_dark.scss +15 -3
- package/assets/styles/themes/_light.scss +7 -2
- package/assets/styles/vendor/vue-select.scss +4 -0
- package/assets/translations/en-us.yaml +66 -9
- package/assets/translations/zh-hans.yaml +2 -3
- package/components/AppModal.vue +50 -0
- package/components/BannerGraphic.vue +0 -42
- package/components/ButtonMultiAction.vue +1 -1
- package/components/Carousel.vue +88 -74
- package/components/CommunityLinks.vue +6 -1
- package/components/CopyToClipboardText.vue +3 -0
- package/components/Dialog.vue +20 -1
- package/components/GrowlManager.vue +9 -2
- package/components/LocaleSelector.vue +8 -1
- package/components/PaginatedResourceTable.vue +4 -7
- package/components/ProgressBarMulti.vue +14 -0
- package/components/PromptChangePassword.vue +3 -0
- package/components/Questions/Reference.vue +57 -28
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/SelectIconGrid.vue +12 -1
- package/components/SideNav.vue +12 -38
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/index.vue +9 -1
- package/components/YamlEditor.vue +1 -0
- package/components/__tests__/Carousel.test.ts +56 -27
- package/components/auth/Principal.vue +5 -3
- package/components/fleet/FleetClusters.vue +82 -1
- package/components/fleet/FleetRepos.vue +13 -30
- package/components/fleet/ForceDirectedTreeChart/index.vue +2 -2
- package/components/form/ChangePassword.vue +2 -0
- package/components/form/ColorInput.vue +24 -1
- package/components/form/FileSelector.vue +2 -0
- package/components/form/KeyValue.vue +230 -160
- package/components/form/LabeledSelect.vue +2 -2
- package/components/form/PlusMinus.vue +14 -2
- package/components/form/ResourceLabeledSelect.vue +13 -53
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +79 -36
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +192 -0
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +104 -0
- package/components/form/SSHKnownHosts/index.vue +101 -0
- package/components/form/SecretSelector.vue +2 -2
- package/components/form/Select.vue +1 -1
- package/components/form/SelectOrCreateAuthSecret.vue +43 -11
- package/components/form/__tests__/KeyValue.test.ts +1 -1
- package/components/form/__tests__/SSHKnownHosts.test.ts +59 -0
- package/components/formatter/FleetClusterSummaryGraph.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +6 -7
- package/components/formatter/WorkloadHealthScale.vue +7 -0
- package/components/nav/Group.vue +30 -4
- package/components/nav/Header.vue +82 -114
- package/components/nav/HeaderPageActionMenu.vue +27 -131
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/Type.vue +15 -0
- package/composables/focusTrap.ts +68 -0
- package/config/home-links.js +21 -13
- package/config/labels-annotations.js +2 -0
- package/config/page-actions.js +1 -0
- package/config/pagination-table-headers.js +15 -1
- package/config/product/explorer.js +7 -17
- package/config/table-headers.js +6 -0
- package/config/version.js +5 -1
- package/core/plugin.ts +41 -1
- package/core/plugins.js +125 -72
- package/core/types-provisioning.ts +91 -2
- package/core/types.ts +55 -0
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +12 -3
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/fleet.cattle.io.cluster.vue +3 -3
- package/detail/namespace.vue +13 -19
- package/detail/networking.k8s.io.ingress.vue +13 -53
- package/detail/provisioning.cattle.io.cluster.vue +12 -1
- package/detail/secret.vue +25 -0
- package/detail/workload/index.vue +3 -3
- package/dialog/AddCustomBadgeDialog.vue +5 -1
- package/edit/auth/ldap/__tests__/config.test.ts +18 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/auth/saml.vue +8 -6
- package/edit/fleet.cattle.io.gitrepo.vue +34 -23
- package/edit/logging-flow/index.vue +4 -19
- package/edit/networking.k8s.io.ingress/index.vue +18 -65
- package/edit/networking.k8s.io.networkpolicy/index.vue +4 -5
- package/edit/provisioning.cattle.io.cluster/index.vue +27 -8
- package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -115
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue +14 -28
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +25 -12
- package/edit/secret/index.vue +1 -1
- package/edit/secret/ssh.vue +21 -3
- package/edit/service.vue +1 -2
- package/list/networking.k8s.io.ingress.vue +1 -1
- package/list/node.vue +15 -8
- package/list/persistentvolume.vue +12 -4
- package/list/provisioning.cattle.io.cluster.vue +1 -0
- package/list/service.vue +1 -1
- package/list/workload.vue +4 -0
- package/mixins/chart.js +4 -1
- package/models/catalog.cattle.io.app.js +3 -1
- package/models/catalog.cattle.io.clusterrepo.js +56 -7
- package/models/fleet.cattle.io.bundle.js +0 -11
- package/models/fleet.cattle.io.cluster.js +17 -1
- package/models/fleet.cattle.io.gitrepo.js +88 -52
- package/models/provisioning.cattle.io.cluster.js +36 -1
- package/models/secret.js +5 -0
- package/models/service.js +1 -0
- package/models/workload.js +19 -1
- package/package.json +5 -4
- package/pages/account/index.vue +4 -0
- package/pages/c/_cluster/apps/charts/index.vue +4 -0
- package/pages/c/_cluster/explorer/ConfigBadge.vue +4 -2
- package/pages/c/_cluster/explorer/index.vue +13 -6
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +3 -3
- package/pages/c/_cluster/fleet/index.vue +75 -89
- package/pages/c/_cluster/settings/links.vue +2 -2
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +3 -1
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +3 -0
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +7 -1
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +3 -1
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +10 -7
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +7 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +181 -106
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +2 -0
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +9 -1
- package/pages/c/_cluster/uiplugins/index.vue +50 -12
- package/pages/diagnostic.vue +17 -15
- package/pages/home.vue +32 -6
- package/plugins/clean-html.js +50 -0
- package/plugins/dashboard-store/resource-class.js +4 -0
- package/plugins/plugin.js +54 -49
- package/plugins/steve/mutations.js +1 -1
- package/plugins/steve/steve-class.js +8 -0
- package/plugins/steve/steve-pagination-utils.ts +3 -1
- package/rancher-components/Accordion/Accordion.vue +4 -4
- package/rancher-components/BadgeState/BadgeState.vue +7 -0
- package/rancher-components/Card/Card.vue +12 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +9 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +19 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +39 -2
- package/rancher-components/RcButton/RcButton.vue +90 -0
- package/rancher-components/RcButton/index.ts +2 -0
- package/rancher-components/RcButton/types.ts +17 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +122 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +127 -0
- package/rancher-components/RcDropdown/RcDropdownSeparator.vue +6 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +42 -0
- package/rancher-components/RcDropdown/index.ts +4 -0
- package/rancher-components/RcDropdown/types.ts +22 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +46 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +110 -0
- package/scripts/test-plugins-build.sh +2 -0
- package/scripts/typegen.sh +2 -0
- package/store/catalog.js +1 -1
- package/tsconfig.json +2 -1
- package/types/components/paginatedResourceTable.ts +25 -0
- package/types/components/resourceLabeledSelect.ts +48 -0
- package/types/resources/fleet.d.ts +17 -0
- package/types/shell/index.d.ts +61 -0
- package/utils/auth.js +5 -1
- package/utils/cluster.js +106 -0
- package/utils/fleet.ts +35 -3
- package/utils/ingress.ts +64 -0
- package/utils/uiplugins.ts +56 -44
- package/utils/validators/cron-schedule.js +7 -2
- package/utils/validators/formRules/__tests__/index.test.ts +53 -17
- package/utils/validators/formRules/index.ts +20 -5
- package/vue.config.js +1 -1
- package/components/RelatedWorkloadsTable.vue +0 -50
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* A button element used for performing actions, such as submitting forms or
|
|
4
|
+
* opening dialogs.
|
|
5
|
+
*
|
|
6
|
+
* Example:
|
|
7
|
+
*
|
|
8
|
+
* <rc-button primary @click="doAction">Perform an Action</rc-button>
|
|
9
|
+
*/
|
|
10
|
+
import { computed, ref, defineExpose } from 'vue';
|
|
11
|
+
import { ButtonRoleProps, ButtonSizeProps } from './types';
|
|
12
|
+
|
|
13
|
+
const buttonRoles: { role: keyof ButtonRoleProps, className: string }[] = [
|
|
14
|
+
{ role: 'primary', className: 'role-primary' },
|
|
15
|
+
{ role: 'secondary', className: 'role-secondary' },
|
|
16
|
+
{ role: 'tertiary', className: 'role-tertiary' },
|
|
17
|
+
{ role: 'link', className: 'role-link' },
|
|
18
|
+
{ role: 'ghost', className: 'role-ghost' },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const buttonSizes: { size: keyof ButtonSizeProps, className: string }[] = [
|
|
22
|
+
{ size: 'small', className: 'btn-sm' },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const props = defineProps<ButtonRoleProps & ButtonSizeProps>();
|
|
26
|
+
|
|
27
|
+
const buttonClass = computed(() => {
|
|
28
|
+
const activeRole = buttonRoles.find(({ role }) => props[role]);
|
|
29
|
+
const isButtonSmall = buttonSizes.some(({ size }) => props[size]);
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
btn: true,
|
|
33
|
+
|
|
34
|
+
[activeRole?.className || 'role-primary']: true,
|
|
35
|
+
|
|
36
|
+
'btn-sm': isButtonSmall,
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const RcFocusTarget = ref<HTMLElement | null>(null);
|
|
41
|
+
|
|
42
|
+
const focus = () => {
|
|
43
|
+
RcFocusTarget?.value?.focus();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
defineExpose({ focus });
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<button
|
|
51
|
+
ref="RcFocusTarget"
|
|
52
|
+
role="button"
|
|
53
|
+
:class="{ ...buttonClass, ...($attrs.class || { }) }"
|
|
54
|
+
>
|
|
55
|
+
<slot name="before">
|
|
56
|
+
<!-- Empty Content -->
|
|
57
|
+
</slot>
|
|
58
|
+
<slot>
|
|
59
|
+
<!-- Empty Content -->
|
|
60
|
+
</slot>
|
|
61
|
+
<slot name="after">
|
|
62
|
+
<!-- Empty Content -->
|
|
63
|
+
</slot>
|
|
64
|
+
</button>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<style lang="scss" scoped>
|
|
68
|
+
.role-link {
|
|
69
|
+
&:focus, &.focused {
|
|
70
|
+
outline: var(--outline-width) solid var(--border);
|
|
71
|
+
box-shadow: 0 0 0 var(--outline-width) var(--outline);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
button {
|
|
76
|
+
&.role-ghost {
|
|
77
|
+
padding: 0;
|
|
78
|
+
background-color: transparent;
|
|
79
|
+
|
|
80
|
+
&:focus, &.focused {
|
|
81
|
+
outline: 2px solid var(--primary-keyboard-focus);
|
|
82
|
+
outline-offset: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&:focus-visible {
|
|
86
|
+
outline: 2px solid var(--primary-keyboard-focus);
|
|
87
|
+
outline-offset: 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// TODO: 13211 Investigate why `InstanceType<typeof RcButton>` fails prod builds
|
|
2
|
+
// export type RcButtonType = InstanceType<typeof RcButton>
|
|
3
|
+
export type RcButtonType = {
|
|
4
|
+
focus: () => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type ButtonRoleProps = {
|
|
8
|
+
primary?: boolean;
|
|
9
|
+
secondary?: boolean;
|
|
10
|
+
tertiary?: boolean;
|
|
11
|
+
link?: boolean;
|
|
12
|
+
ghost?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ButtonSizeProps = {
|
|
16
|
+
small?: boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Offers a list of choices to the user, such as a set of actions or functions.
|
|
4
|
+
* Opened by activating RcDropdownTrigger.
|
|
5
|
+
*
|
|
6
|
+
* Example:
|
|
7
|
+
*
|
|
8
|
+
* <rc-dropdown :aria-label="t('nav.actionMenu.label')">
|
|
9
|
+
* <rc-dropdown-trigger tertiary>
|
|
10
|
+
* <i class="icon icon-actions" />
|
|
11
|
+
* </rc-dropdown-trigger>
|
|
12
|
+
* <template #dropdownCollection>
|
|
13
|
+
* <rc-dropdown-item @click="performAction()">
|
|
14
|
+
* Action 1
|
|
15
|
+
* </rc-dropdown-item>
|
|
16
|
+
* <rc-dropdown-separator />
|
|
17
|
+
* <rc-dropdown-item @click="performAction()">
|
|
18
|
+
* Action 2
|
|
19
|
+
* </rc-dropdown-item>
|
|
20
|
+
* </template>
|
|
21
|
+
* </rc-dropdown>
|
|
22
|
+
*/
|
|
23
|
+
import { useTemplateRef } from 'vue';
|
|
24
|
+
import { useClickOutside } from '@shell/composables/useClickOutside';
|
|
25
|
+
import { useDropdownContext } from '@components/RcDropdown/useDropdownContext';
|
|
26
|
+
|
|
27
|
+
defineProps<{
|
|
28
|
+
ariaLabel?: string
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
isMenuOpen,
|
|
33
|
+
showMenu,
|
|
34
|
+
returnFocus,
|
|
35
|
+
setFocus,
|
|
36
|
+
provideDropdownContext,
|
|
37
|
+
registerDropdownCollection,
|
|
38
|
+
handleKeydown,
|
|
39
|
+
} = useDropdownContext();
|
|
40
|
+
|
|
41
|
+
provideDropdownContext();
|
|
42
|
+
|
|
43
|
+
const popperContainer = useTemplateRef<HTMLElement>('popperContainer');
|
|
44
|
+
const dropdownTarget = useTemplateRef<HTMLElement>('dropdownTarget');
|
|
45
|
+
|
|
46
|
+
useClickOutside(dropdownTarget, () => showMenu(false));
|
|
47
|
+
|
|
48
|
+
const applyShow = () => {
|
|
49
|
+
registerDropdownCollection(dropdownTarget.value);
|
|
50
|
+
setFocus();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<v-dropdown
|
|
57
|
+
no-auto-focus
|
|
58
|
+
:triggers="[]"
|
|
59
|
+
:shown="isMenuOpen"
|
|
60
|
+
:auto-hide="false"
|
|
61
|
+
:container="popperContainer"
|
|
62
|
+
:placement="'bottom-end'"
|
|
63
|
+
@apply-show="applyShow"
|
|
64
|
+
>
|
|
65
|
+
<slot name="default">
|
|
66
|
+
<!--Empty slot content Trigger-->
|
|
67
|
+
</slot>
|
|
68
|
+
|
|
69
|
+
<template #popper>
|
|
70
|
+
<div
|
|
71
|
+
ref="dropdownTarget"
|
|
72
|
+
class="dropdownTarget"
|
|
73
|
+
tabindex="-1"
|
|
74
|
+
role="menu"
|
|
75
|
+
aria-orientation="vertical"
|
|
76
|
+
dropdown-menu-collection
|
|
77
|
+
:aria-label="ariaLabel || 'Dropdown Menu'"
|
|
78
|
+
@keydown="handleKeydown"
|
|
79
|
+
@keydown.down="setFocus()"
|
|
80
|
+
>
|
|
81
|
+
<slot name="dropdownCollection">
|
|
82
|
+
<!--Empty slot content-->
|
|
83
|
+
</slot>
|
|
84
|
+
</div>
|
|
85
|
+
</template>
|
|
86
|
+
</v-dropdown>
|
|
87
|
+
<div
|
|
88
|
+
ref="popperContainer"
|
|
89
|
+
class="popperContainer"
|
|
90
|
+
@keydown.tab="showMenu(false)"
|
|
91
|
+
@keydown.escape="returnFocus"
|
|
92
|
+
>
|
|
93
|
+
<!--Empty container for mounting popper content-->
|
|
94
|
+
</div>
|
|
95
|
+
</template>
|
|
96
|
+
|
|
97
|
+
<style lang="scss" scoped>
|
|
98
|
+
.popperContainer {
|
|
99
|
+
display: contents;
|
|
100
|
+
&:deep(.v-popper__popper) {
|
|
101
|
+
|
|
102
|
+
.v-popper__wrapper {
|
|
103
|
+
box-shadow: 0px 6px 18px 0px rgba(0, 0, 0, 0.25), 0px 4px 10px 0px rgba(0, 0, 0, 0.15);
|
|
104
|
+
border-radius: var(--border-radius-lg);
|
|
105
|
+
|
|
106
|
+
.v-popper__arrow-container {
|
|
107
|
+
display: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.v-popper__inner {
|
|
111
|
+
padding: 10px 0 10px 0;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.dropdownTarget {
|
|
118
|
+
&:focus-visible, &:focus {
|
|
119
|
+
outline: none;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* An item for a dropdown menu. Used in conjunction with RcDropdown.
|
|
4
|
+
*/
|
|
5
|
+
import { inject } from 'vue';
|
|
6
|
+
import { DropdownContext, defaultContext } from './types';
|
|
7
|
+
|
|
8
|
+
const props = defineProps({ disabled: Boolean });
|
|
9
|
+
const emits = defineEmits(['click']);
|
|
10
|
+
|
|
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
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleClick = () => {
|
|
57
|
+
if (props.disabled) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
emits('click');
|
|
62
|
+
close();
|
|
63
|
+
};
|
|
64
|
+
|
|
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
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Handles keydown events to focus the dropdown item.
|
|
77
|
+
* @param e - The Mouse event.
|
|
78
|
+
*/
|
|
79
|
+
const handleMouseEnter = (e: MouseEvent) => {
|
|
80
|
+
if (e?.target instanceof HTMLElement) {
|
|
81
|
+
e?.target?.focus();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<template>
|
|
88
|
+
<div
|
|
89
|
+
ref="dropdownMenuItem"
|
|
90
|
+
dropdown-menu-item
|
|
91
|
+
tabindex="-1"
|
|
92
|
+
role="menuitem"
|
|
93
|
+
:disabled="disabled || null"
|
|
94
|
+
:aria-disabled="disabled || false"
|
|
95
|
+
@click.stop="handleClick"
|
|
96
|
+
@keydown.enter.space="handleActivate"
|
|
97
|
+
@keydown.up.down.stop="handleKeydown"
|
|
98
|
+
@mouseenter="handleMouseEnter"
|
|
99
|
+
>
|
|
100
|
+
<slot name="default">
|
|
101
|
+
<!--Empty slot content-->
|
|
102
|
+
</slot>
|
|
103
|
+
</div>
|
|
104
|
+
</template>
|
|
105
|
+
|
|
106
|
+
<style lang="scss" scoped>
|
|
107
|
+
[dropdown-menu-item] {
|
|
108
|
+
padding: 9px 8px;
|
|
109
|
+
margin: 0 9px;
|
|
110
|
+
border-radius: 4px;
|
|
111
|
+
|
|
112
|
+
&:hover {
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
background-color: var(--dropdown-hover-bg);
|
|
115
|
+
}
|
|
116
|
+
&:focus-visible, &:focus {
|
|
117
|
+
@include focus-outline;
|
|
118
|
+
outline-offset: 0;
|
|
119
|
+
}
|
|
120
|
+
&[disabled] {
|
|
121
|
+
color: var(--disabled-text);
|
|
122
|
+
&:hover {
|
|
123
|
+
cursor: not-allowed;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* A button that opens a menu. Used in conjunction with `RcDropdown.vue`.
|
|
4
|
+
*/
|
|
5
|
+
import { inject, onMounted, useTemplateRef } from 'vue';
|
|
6
|
+
import { RcButton, RcButtonType } from '@components/RcButton';
|
|
7
|
+
import { DropdownContext, defaultContext } from './types';
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
showMenu,
|
|
11
|
+
registerTrigger,
|
|
12
|
+
isMenuOpen,
|
|
13
|
+
handleKeydown,
|
|
14
|
+
} = inject<DropdownContext>('dropdownContext') || defaultContext;
|
|
15
|
+
|
|
16
|
+
const dropdownTrigger = useTemplateRef<RcButtonType>('dropdownTrigger');
|
|
17
|
+
|
|
18
|
+
onMounted(() => {
|
|
19
|
+
registerTrigger(dropdownTrigger.value);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const focus = () => {
|
|
23
|
+
dropdownTrigger?.value?.focus();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
defineExpose({ focus });
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<RcButton
|
|
31
|
+
ref="dropdownTrigger"
|
|
32
|
+
role="button"
|
|
33
|
+
aria-haspopup="menu"
|
|
34
|
+
:aria-expanded="isMenuOpen"
|
|
35
|
+
@keydown.enter.space="handleKeydown"
|
|
36
|
+
@click="showMenu(true)"
|
|
37
|
+
>
|
|
38
|
+
<slot name="default">
|
|
39
|
+
<!--Empty slot content-->
|
|
40
|
+
</slot>
|
|
41
|
+
</RcButton>
|
|
42
|
+
</template>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as RcDropdown } from './RcDropdown.vue';
|
|
2
|
+
export { default as RcDropdownItem } from './RcDropdownItem.vue';
|
|
3
|
+
export { default as RcDropdownSeparator } from './RcDropdownSeparator.vue';
|
|
4
|
+
export { default as RcDropdownTrigger } from './RcDropdownTrigger.vue';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Ref, ref } from 'vue';
|
|
2
|
+
import type { RcButtonType } from '@components/RcButton';
|
|
3
|
+
|
|
4
|
+
export type DropdownContext = {
|
|
5
|
+
handleKeydown: () => void;
|
|
6
|
+
showMenu: (show: boolean) => void;
|
|
7
|
+
registerTrigger: (triggerRef: RcButtonType | null) => void;
|
|
8
|
+
dropdownItems: Ref<Element[]>;
|
|
9
|
+
focusFirstElement: () => void;
|
|
10
|
+
isMenuOpen: Ref<boolean>;
|
|
11
|
+
close: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const defaultContext: DropdownContext = {
|
|
15
|
+
handleKeydown: () => null,
|
|
16
|
+
showMenu: (_show: boolean | null) => null,
|
|
17
|
+
registerTrigger: (_triggerRef: RcButtonType | null) => null,
|
|
18
|
+
dropdownItems: ref([]),
|
|
19
|
+
focusFirstElement: () => null,
|
|
20
|
+
isMenuOpen: ref(false),
|
|
21
|
+
close: () => null,
|
|
22
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manages a collection of dropdown items. Includes methods for registering
|
|
5
|
+
* dropdown items and providing the collection to descendant components.
|
|
6
|
+
*
|
|
7
|
+
* @returns Dropdown collection methods and state.
|
|
8
|
+
*/
|
|
9
|
+
export const useDropdownCollection = () => {
|
|
10
|
+
const dropdownItems = ref<Element[]>([]);
|
|
11
|
+
const dropdownContainer = ref<HTMLElement | null>(null);
|
|
12
|
+
const firstDropdownItem = ref<HTMLElement | null>(null);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Registers the dropdown container and initializes dropdown items.
|
|
16
|
+
* @param target - The dropdown container element.
|
|
17
|
+
*/
|
|
18
|
+
const registerDropdownCollection = (target: HTMLElement | null) => {
|
|
19
|
+
dropdownContainer.value = target;
|
|
20
|
+
if (dropdownContainer.value?.firstElementChild instanceof HTMLElement) {
|
|
21
|
+
registerDropdownItems();
|
|
22
|
+
if (dropdownItems.value[0] instanceof HTMLElement) {
|
|
23
|
+
firstDropdownItem.value = dropdownItems.value[0];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Registers dropdown items by querying the dropdown container for elements.
|
|
30
|
+
*/
|
|
31
|
+
const registerDropdownItems = () => {
|
|
32
|
+
dropdownItems.value = [];
|
|
33
|
+
const dropdownNodeList = dropdownContainer.value?.querySelectorAll('[dropdown-menu-item]');
|
|
34
|
+
|
|
35
|
+
dropdownNodeList?.forEach((element) => {
|
|
36
|
+
dropdownItems.value.push(element);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
dropdownItems,
|
|
42
|
+
firstDropdownItem,
|
|
43
|
+
dropdownContainer,
|
|
44
|
+
registerDropdownCollection,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ref, provide, nextTick } from 'vue';
|
|
2
|
+
import { useDropdownCollection } from './useDropdownCollection';
|
|
3
|
+
import { RcButtonType } from '@components/RcButton';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Composable that provides the context for a dropdown menu. Includes methods
|
|
7
|
+
* and state for managing the dropdown's visibility, focus, and keyboard
|
|
8
|
+
* interactions.
|
|
9
|
+
*
|
|
10
|
+
* @param firstDropdownItem - First item in the dropdown menu.
|
|
11
|
+
* @returns Dropdown context methods and state. Used for programmatic
|
|
12
|
+
* interactions and setting focus.
|
|
13
|
+
*/
|
|
14
|
+
export const useDropdownContext = () => {
|
|
15
|
+
const {
|
|
16
|
+
dropdownItems,
|
|
17
|
+
firstDropdownItem,
|
|
18
|
+
dropdownContainer,
|
|
19
|
+
registerDropdownCollection,
|
|
20
|
+
} = useDropdownCollection();
|
|
21
|
+
|
|
22
|
+
const isMenuOpen = ref(false);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Controls the visibility of the dropdown menu.
|
|
26
|
+
* @param show - Whether to show or hide the dropdown menu.
|
|
27
|
+
*/
|
|
28
|
+
const showMenu = (show: boolean) => {
|
|
29
|
+
if (!show) {
|
|
30
|
+
didKeydown.value = false;
|
|
31
|
+
}
|
|
32
|
+
isMenuOpen.value = show;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A ref for the dropdown trigger element. Used for programmatic
|
|
37
|
+
* interactions and setting focus.
|
|
38
|
+
*/
|
|
39
|
+
const dropdownTrigger = ref<RcButtonType | null>(null);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Registers the dropdown trigger element.
|
|
43
|
+
* @param triggerRef - The dropdown trigger element.
|
|
44
|
+
*/
|
|
45
|
+
const registerTrigger = (triggerRef: RcButtonType) => {
|
|
46
|
+
dropdownTrigger.value = triggerRef;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns focus to the dropdown trigger and closes the menu.
|
|
51
|
+
*/
|
|
52
|
+
const returnFocus = () => {
|
|
53
|
+
showMenu(false);
|
|
54
|
+
dropdownTrigger?.value?.focus();
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Tracks if a keydown event has occurred. Important for distinguishing keyboard
|
|
59
|
+
* events from mouse events.
|
|
60
|
+
*/
|
|
61
|
+
const didKeydown = ref(false);
|
|
62
|
+
|
|
63
|
+
const handleKeydown = () => {
|
|
64
|
+
didKeydown.value = true;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Sets focus to the first dropdown item if a keydown event has occurred.
|
|
69
|
+
*/
|
|
70
|
+
const setFocus = () => {
|
|
71
|
+
nextTick(() => {
|
|
72
|
+
if (!didKeydown.value) {
|
|
73
|
+
dropdownContainer.value?.focus();
|
|
74
|
+
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
firstDropdownItem.value?.focus();
|
|
79
|
+
didKeydown.value = false;
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Provides Dropdown Context data and methods to descendants of RcDropdown.
|
|
85
|
+
* Accessed in descendents with the `inject()` function.
|
|
86
|
+
*/
|
|
87
|
+
const provideDropdownContext = () => {
|
|
88
|
+
provide('dropdownContext', {
|
|
89
|
+
showMenu,
|
|
90
|
+
registerTrigger,
|
|
91
|
+
isMenuOpen,
|
|
92
|
+
dropdownItems,
|
|
93
|
+
close: () => returnFocus(),
|
|
94
|
+
focusFirstElement: () => {
|
|
95
|
+
setFocus();
|
|
96
|
+
},
|
|
97
|
+
handleKeydown,
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
isMenuOpen,
|
|
103
|
+
showMenu,
|
|
104
|
+
returnFocus,
|
|
105
|
+
setFocus,
|
|
106
|
+
provideDropdownContext,
|
|
107
|
+
registerDropdownCollection,
|
|
108
|
+
handleKeydown,
|
|
109
|
+
};
|
|
110
|
+
};
|
|
@@ -141,6 +141,8 @@ if [ "${SKIP_STANDALONE}" == "false" ]; then
|
|
|
141
141
|
pushd test-app > /dev/null
|
|
142
142
|
|
|
143
143
|
yarn install
|
|
144
|
+
# this is the "same" as doing a yarn dev (in a build sense)
|
|
145
|
+
# it's to make sure the dev environment is running properly
|
|
144
146
|
FORCE_COLOR=true yarn build | cat
|
|
145
147
|
|
|
146
148
|
# Add test list component to the test package
|
package/scripts/typegen.sh
CHANGED
|
@@ -21,10 +21,12 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/query-params.js --declarat
|
|
|
21
21
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/table-headers.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
22
22
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/types.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
23
23
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/labels-annotations.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
24
|
+
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/version.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
24
25
|
|
|
25
26
|
# # store
|
|
26
27
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/features.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
27
28
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/prefs.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
29
|
+
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/plugins.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
28
30
|
|
|
29
31
|
# # plugins
|
|
30
32
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/normalize.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
|
package/store/catalog.js
CHANGED
|
@@ -57,7 +57,7 @@ export const getters = {
|
|
|
57
57
|
const clustered = state.clusterRepos || [];
|
|
58
58
|
const namespaced = state.namespacedRepos || [];
|
|
59
59
|
|
|
60
|
-
return [...clustered, ...namespaced];
|
|
60
|
+
return [...clustered, ...namespaced].filter((r) => r.spec?.enabled !== false);
|
|
61
61
|
},
|
|
62
62
|
|
|
63
63
|
// Raw charts
|
package/tsconfig.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { StorePaginationResult } from '@shell/types/store/pagination.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* see {@link PagTableFetchSecondaryResources}
|
|
5
|
+
*/
|
|
6
|
+
export type PagTableFetchSecondaryResourcesOpts = { canPaginate: boolean }
|
|
7
|
+
/**
|
|
8
|
+
* see {@link PagTableFetchSecondaryResources}
|
|
9
|
+
*/
|
|
10
|
+
export type PagTableFetchSecondaryResourcesReturns = Promise<any>
|
|
11
|
+
/**
|
|
12
|
+
* Function to fetch resources that are required to supplement information needed by rows in a PaginatedResourceTable
|
|
13
|
+
*
|
|
14
|
+
* Used in scenarios where ALL resources are expected
|
|
15
|
+
*/
|
|
16
|
+
export type PagTableFetchSecondaryResources = (opts: PagTableFetchSecondaryResourcesOpts) => PagTableFetchSecondaryResourcesReturns
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* see {@link PagTableFetchPageSecondaryResources}
|
|
20
|
+
*/
|
|
21
|
+
export type PagTableFetchPageSecondaryResourcesOpts = { canPaginate: boolean, force: boolean, page: any[], pagResult: StorePaginationResult }
|
|
22
|
+
/**
|
|
23
|
+
* Function to fetch resources that are required to supplement information needed by a single page in a PaginatedResourceTable
|
|
24
|
+
*/
|
|
25
|
+
export type PagTableFetchPageSecondaryResources = (opts: PagTableFetchPageSecondaryResourcesOpts) => Promise<any>
|