@rancher/shell 3.0.5-rc.3 → 3.0.5-rc.5

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/icons/document.svg +3 -0
  2. package/assets/images/vendor/cognito.svg +1 -0
  3. package/assets/styles/app.scss +1 -0
  4. package/assets/styles/base/_basic.scss +10 -0
  5. package/assets/styles/base/_spacing.scss +29 -0
  6. package/assets/styles/global/_layout.scss +1 -1
  7. package/assets/styles/themes/_dark.scss +25 -0
  8. package/assets/styles/themes/_light.scss +65 -0
  9. package/assets/translations/en-us.yaml +322 -24
  10. package/assets/translations/zh-hans.yaml +8 -5
  11. package/components/Certificates.vue +5 -0
  12. package/components/FilterPanel.vue +156 -0
  13. package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
  14. package/components/IconOrSvg.vue +14 -35
  15. package/components/PromptRemove.vue +5 -1
  16. package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
  17. package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
  18. package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
  19. package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
  20. package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
  21. package/components/Resource/Detail/Card/Scaler.vue +89 -0
  22. package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
  23. package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
  24. package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
  25. package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
  26. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
  27. package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
  28. package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
  29. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
  30. package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
  31. package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
  32. package/components/Resource/Detail/Card/index.vue +56 -0
  33. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
  34. package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
  35. package/components/Resource/Detail/Metadata/Annotations/index.vue +26 -0
  36. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
  37. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +281 -0
  38. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +111 -0
  39. package/components/Resource/Detail/Metadata/KeyValue.vue +130 -0
  40. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
  41. package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
  42. package/components/Resource/Detail/Metadata/Labels/index.vue +27 -0
  43. package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
  44. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
  45. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
  46. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
  47. package/components/Resource/Detail/Metadata/composables.ts +29 -0
  48. package/components/Resource/Detail/Metadata/index.vue +66 -0
  49. package/components/Resource/Detail/Page.vue +22 -0
  50. package/components/Resource/Detail/PercentageBar.vue +40 -0
  51. package/components/Resource/Detail/ResourceRow.vue +119 -0
  52. package/components/Resource/Detail/SpacedRow.vue +14 -0
  53. package/components/Resource/Detail/StatusBar.vue +59 -0
  54. package/components/Resource/Detail/StatusRow.vue +61 -0
  55. package/components/Resource/Detail/TitleBar/Title.vue +13 -0
  56. package/components/Resource/Detail/TitleBar/Top.vue +14 -0
  57. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
  58. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
  59. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
  60. package/components/Resource/Detail/TitleBar/composable.ts +31 -0
  61. package/components/Resource/Detail/TitleBar/index.vue +124 -0
  62. package/components/Resource/Detail/Top/index.vue +34 -0
  63. package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
  64. package/components/ResourceDetail/__tests__/index.test.ts +114 -0
  65. package/components/ResourceDetail/index.vue +64 -562
  66. package/components/ResourceDetail/legacy.vue +545 -0
  67. package/components/ResourceTable.vue +41 -7
  68. package/components/SlideInPanelManager.vue +76 -8
  69. package/components/SortableTable/index.vue +13 -2
  70. package/components/SortableTable/selection.js +21 -8
  71. package/components/StatusBadge.vue +6 -4
  72. package/components/SubtleLink.vue +25 -0
  73. package/components/Wizard.vue +12 -1
  74. package/components/YamlEditor.vue +1 -1
  75. package/components/__tests__/FilterPanel.test.ts +81 -0
  76. package/components/auth/AuthBanner.vue +2 -3
  77. package/components/auth/RoleDetailEdit.vue +45 -3
  78. package/components/auth/login/oidc.vue +6 -1
  79. package/components/fleet/FleetApplications.vue +181 -0
  80. package/components/fleet/FleetHelmOps.vue +115 -0
  81. package/components/fleet/FleetIntro.vue +58 -28
  82. package/components/fleet/FleetNoWorkspaces.vue +5 -1
  83. package/components/fleet/FleetOCIStorageSecret.vue +171 -0
  84. package/components/fleet/FleetRepos.vue +38 -76
  85. package/components/fleet/FleetResources.vue +50 -22
  86. package/components/fleet/FleetSummary.vue +26 -51
  87. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
  88. package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
  89. package/components/fleet/dashboard/Empty.vue +73 -0
  90. package/components/fleet/dashboard/ResourceCard.vue +183 -0
  91. package/components/fleet/dashboard/ResourceCardSummary.vue +199 -0
  92. package/components/fleet/dashboard/ResourceDetails.vue +196 -0
  93. package/components/fleet/dashboard/ResourcePanel.vue +376 -0
  94. package/components/form/ArrayList.vue +6 -0
  95. package/components/form/SimpleSecretSelector.vue +8 -2
  96. package/components/form/ValueFromResource.vue +31 -19
  97. package/components/formatter/FleetApplicationClustersReady.vue +77 -0
  98. package/components/formatter/FleetApplicationSource.vue +71 -0
  99. package/components/formatter/FleetSummaryGraph.vue +7 -0
  100. package/components/nav/Header.vue +8 -7
  101. package/components/nav/TopLevelMenu.helper.ts +55 -34
  102. package/components/nav/TopLevelMenu.vue +11 -0
  103. package/components/nav/Type.vue +4 -1
  104. package/composables/useI18n.ts +12 -11
  105. package/config/labels-annotations.js +14 -11
  106. package/config/product/auth.js +1 -0
  107. package/config/product/fleet.js +70 -17
  108. package/config/query-params.js +3 -1
  109. package/config/roles.ts +1 -0
  110. package/config/router/routes.js +20 -2
  111. package/config/secret.ts +15 -0
  112. package/config/settings.ts +3 -2
  113. package/config/table-headers.js +52 -22
  114. package/config/types.js +2 -0
  115. package/core/plugin-helpers.ts +3 -2
  116. package/detail/fleet.cattle.io.cluster.vue +28 -15
  117. package/detail/fleet.cattle.io.gitrepo.vue +10 -1
  118. package/detail/fleet.cattle.io.helmop.vue +157 -0
  119. package/dialog/HelmOpForceUpdateDialog.vue +132 -0
  120. package/dialog/RedeployWorkloadDialog.vue +164 -0
  121. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +56 -67
  122. package/edit/auth/oidc.vue +159 -93
  123. package/edit/fleet.cattle.io.gitrepo.vue +26 -33
  124. package/edit/fleet.cattle.io.helmop.vue +997 -0
  125. package/edit/management.cattle.io.fleetworkspace.vue +43 -10
  126. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  127. package/list/fleet.cattle.io.helmop.vue +108 -0
  128. package/list/namespace.vue +5 -2
  129. package/mixins/auth-config.js +8 -1
  130. package/mixins/preset.js +100 -0
  131. package/mixins/resource-fetch-api-pagination.js +2 -0
  132. package/mixins/resource-fetch.js +1 -1
  133. package/mixins/resource-table-watch.js +45 -0
  134. package/models/__tests__/chart.test.ts +273 -0
  135. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  136. package/models/chart.js +144 -2
  137. package/models/fleet-application.js +385 -0
  138. package/models/fleet.cattle.io.bundle.js +9 -8
  139. package/models/fleet.cattle.io.gitrepo.js +41 -365
  140. package/models/fleet.cattle.io.helmop.js +228 -0
  141. package/models/management.cattle.io.authconfig.js +1 -0
  142. package/models/management.cattle.io.fleetworkspace.js +12 -0
  143. package/models/workload.js +14 -18
  144. package/package.json +2 -1
  145. package/pages/auth/verify.vue +13 -1
  146. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +37 -0
  147. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
  148. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
  149. package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
  150. package/pages/c/_cluster/apps/charts/index.vue +302 -484
  151. package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
  152. package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
  153. package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
  154. package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
  155. package/pages/c/_cluster/fleet/application/create.vue +340 -0
  156. package/pages/c/_cluster/fleet/application/index.vue +139 -0
  157. package/pages/c/_cluster/fleet/graph/config.js +277 -0
  158. package/pages/c/_cluster/fleet/index.vue +772 -330
  159. package/pages/explorer/resource/detail/configmap.vue +19 -0
  160. package/plugins/dashboard-store/actions.js +31 -9
  161. package/plugins/dashboard-store/getters.js +34 -21
  162. package/plugins/dashboard-store/mutations.js +51 -7
  163. package/plugins/dashboard-store/resource-class.js +14 -2
  164. package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
  165. package/plugins/steve/actions.js +3 -0
  166. package/plugins/steve/steve-pagination-utils.ts +14 -13
  167. package/plugins/steve/subscribe.js +229 -42
  168. package/rancher-components/BadgeState/BadgeState.vue +3 -1
  169. package/rancher-components/Form/Checkbox/Checkbox.vue +2 -2
  170. package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
  171. package/rancher-components/RcItemCard/RcItemCard.vue +425 -0
  172. package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
  173. package/rancher-components/RcItemCard/index.ts +2 -0
  174. package/store/auth.js +1 -0
  175. package/store/catalog.js +62 -24
  176. package/store/index.js +33 -14
  177. package/store/slideInPanel.ts +6 -0
  178. package/store/type-map.js +1 -0
  179. package/types/fleet.d.ts +35 -0
  180. package/types/resources/settings.d.ts +19 -1
  181. package/types/shell/index.d.ts +339 -272
  182. package/types/store/dashboard-store.types.ts +17 -3
  183. package/types/store/pagination.types.ts +6 -1
  184. package/types/store/subscribe.types.ts +50 -0
  185. package/utils/auth.js +32 -3
  186. package/utils/fleet-types.ts +0 -0
  187. package/utils/fleet.ts +200 -1
  188. package/utils/pagination-utils.ts +26 -1
  189. package/utils/pagination-wrapper.ts +132 -50
  190. package/utils/settings.ts +4 -1
  191. package/utils/style.ts +39 -0
  192. package/utils/validators/formRules/__tests__/index.test.ts +36 -3
  193. package/utils/validators/formRules/index.ts +10 -3
  194. package/utils/window.js +11 -7
  195. package/components/__tests__/ApplicationCard.test.ts +0 -27
  196. package/components/cards/ApplicationCard.vue +0 -145
  197. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
  198. package/config/secret.js +0 -14
  199. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
  200. /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
@@ -0,0 +1,425 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed } from 'vue';
3
+ import { useStore } from 'vuex';
4
+ import { useI18n } from '@shell/composables/useI18n';
5
+ import LazyImage from '@shell/components/LazyImage.vue';
6
+ import { DropdownOption } from '@components/RcDropdown/types';
7
+ import ActionMenu from '@shell/components/ActionMenuShell.vue';
8
+
9
+ const store = useStore();
10
+ const { t } = useI18n(store);
11
+
12
+ /**
13
+ * Variants available for ItemCard layout
14
+ */
15
+ type RcItemCardVariant = 'small' | 'medium';
16
+
17
+ /**
18
+ * A label that can be either plain text or a translatable key.
19
+ */
20
+ type Label = {
21
+ key?: string;
22
+ text?: string;
23
+ };
24
+
25
+ /**
26
+ * Represents an image used in the card.
27
+ */
28
+ type Image = {
29
+ src: string;
30
+ alt?: Label;
31
+ };
32
+
33
+ /**
34
+ * Optional pill badge, typically used to highlight a tag or state.
35
+ */
36
+ type Pill = {
37
+ label: Label;
38
+ tooltip?: Label;
39
+ };
40
+
41
+ /**
42
+ * Represents an icon-based status indicator shown in the card header.
43
+ */
44
+ type Status = {
45
+ icon: string;
46
+ color?: string;
47
+ customColor?: string;
48
+ tooltip?: Label;
49
+ handleClick?: () => void;
50
+ };
51
+
52
+ /**
53
+ * Header metadata for the card.
54
+ */
55
+ type Header = {
56
+ title?: Label;
57
+ statuses?: Status[];
58
+ };
59
+
60
+ /**
61
+ * The generic data value passed to the card.
62
+ */
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ type ItemValue = Record<string, any>;
65
+
66
+ /**
67
+ * Props accepted by the ItemCard component.
68
+ */
69
+ interface RcItemCardProps {
70
+ /** Unique identifier for the card (used in test IDs) */
71
+ id: string;
72
+
73
+ /** Any object value associated with this card */
74
+ value: ItemValue;
75
+
76
+ /** Card title, status icons and action menu. Image will be included in the header in small variant too */
77
+ header: Header;
78
+
79
+ /** Optional image to show in card (position depends on variant). A slot is available for it too #item-card-image */
80
+ image?: Image;
81
+
82
+ /** Optional actions that will be displayed inside an action-menu */
83
+ actions?: DropdownOption;
84
+
85
+ /** Text content inside the card body. A slot is available for it too #item-card-content */
86
+ content?: Label;
87
+
88
+ /** Layout variant: 'small' or 'medium' */
89
+ variant?: RcItemCardVariant;
90
+
91
+ /** Optional pill shown (only if variant is not 'small'). A slot is available for it too #item-card-pill */
92
+ pill?: Pill;
93
+
94
+ /** Makes the card clickable and emits 'card-click' on click/enter/space */
95
+ clickable?: boolean;
96
+ }
97
+
98
+ const props = defineProps<RcItemCardProps>();
99
+
100
+ /**
101
+ * Emits 'card-click' when card is clicked or activated via keyboard.
102
+ */
103
+ const emit = defineEmits<{( e: 'card-click', value: ItemValue): void; }>();
104
+
105
+ /**
106
+ * Handles the card click while avoiding nested interactive elements
107
+ * By using RcItemCardAction.vue the 'item-card-action' attribute automatically gets added
108
+ * which then gets used to ignore 'card-click'
109
+ */
110
+ function _handleCardClick(e: MouseEvent | KeyboardEvent) {
111
+ const interactiveSelector = '[item-card-action]';
112
+
113
+ // Prevent card click if the user clicks on an inner actionable element like repo, category, or tag
114
+ if ((e.target as HTMLElement).closest(interactiveSelector)) {
115
+ return;
116
+ }
117
+
118
+ emit('card-click', props.value);
119
+ }
120
+
121
+ /**
122
+ * Utility to resolve localized or plain text labels.
123
+ */
124
+ function labelText(label?: Label): string {
125
+ return label?.key ? t(label.key) : label?.text ?? '';
126
+ }
127
+
128
+ /** ---------------- data ------------------ */
129
+ const cardEl = ref<HTMLElement | null>(null);
130
+
131
+ /** ---------------- Computed ------------------ */
132
+
133
+ const headerTitle = computed(() => labelText(props.header.title));
134
+ const imageAlt = computed(() => labelText(props.image?.alt));
135
+ const pillLabel = computed(() => labelText(props.pill?.label));
136
+ const pillTooltip = computed(() => labelText(props.pill?.tooltip));
137
+ const contentText = computed(() => labelText(props.content));
138
+ const statusTooltips = computed(() => props.header.statuses?.map((status) => labelText(status.tooltip)) || []);
139
+
140
+ const cardMeta = computed(() => ({
141
+ ariaLabel: props.clickable ? t('itemCard.ariaLabel.clickable', { cardTitle: labelText(props.header.title) }) : undefined,
142
+ tabIndex: props.clickable ? '0' : undefined,
143
+ role: props.clickable ? 'button' : undefined
144
+ }));
145
+
146
+ </script>
147
+
148
+ <template>
149
+ <div
150
+ ref="cardEl"
151
+ class="item-card"
152
+ :role="cardMeta.role"
153
+ :tabindex="cardMeta.tabIndex"
154
+ :aria-label="cardMeta.ariaLabel"
155
+ :data-testid="`item-card-${id}`"
156
+ @click="_handleCardClick"
157
+ @keydown.enter="_handleCardClick"
158
+ @keydown.space.prevent="_handleCardClick"
159
+ >
160
+ <div :class="['item-card-body', variant]">
161
+ <template v-if="variant !== 'small'">
162
+ <div>
163
+ <slot name="item-card-image">
164
+ <div
165
+ v-if="image"
166
+ :class="['item-card-image', variant]"
167
+ data-testid="item-card-image"
168
+ >
169
+ <LazyImage
170
+ :src="image.src"
171
+ :alt="imageAlt"
172
+ :style="{'width': '40px', 'height': '40px', 'object-fit': 'contain'}"
173
+ />
174
+ </div>
175
+ </slot>
176
+ <slot name="item-card-pill">
177
+ <div
178
+ v-if="pill"
179
+ v-clean-tooltip="pillTooltip"
180
+ class="item-card-pill"
181
+ data-testid="item-card-pill"
182
+ >
183
+ {{ pillLabel }}
184
+ </div>
185
+ </slot>
186
+ </div>
187
+ </template>
188
+
189
+ <div :class="['item-card-body-details', variant]">
190
+ <div :class="['item-card-header', variant]">
191
+ <div class="item-card-header-left">
192
+ <template v-if="variant === 'small'">
193
+ <slot name="item-card-image">
194
+ <div
195
+ v-if="image"
196
+ :class="['item-card-image', variant]"
197
+ data-testid="item-card-image"
198
+ >
199
+ <LazyImage
200
+ :src="image.src"
201
+ :alt="imageAlt"
202
+ :style="{'width': '24px', 'height': '24px', 'object-fit': 'contain'}"
203
+ />
204
+ </div>
205
+ </slot>
206
+ </template>
207
+ <slot name="item-card-header-title">
208
+ <h3
209
+ v-if="header.title"
210
+ v-clean-tooltip="headerTitle"
211
+ :class="['item-card-header-title', variant]"
212
+ data-testid="item-card-header-title"
213
+ >
214
+ {{ headerTitle }}
215
+ </h3>
216
+ </slot>
217
+ </div>
218
+ <div class="item-card-header-right">
219
+ <div
220
+ v-if="header.statuses?.length"
221
+ class="item-card-header-statuses"
222
+ >
223
+ <div
224
+ v-for="(status, i) in header.statuses"
225
+ :key="i"
226
+ class="item-card-header-statuses-status"
227
+ data-testid="item-card-header-statuses-status"
228
+ >
229
+ <i
230
+ v-clean-tooltip="statusTooltips[i]"
231
+ :class="['icon', status.icon, status.color]"
232
+ :style="{color: status.customColor}"
233
+ :data-testid="`item-card-header-status-${i}`"
234
+ />
235
+ </div>
236
+ </div>
237
+
238
+ <template v-if="$slots['item-card-actions']">
239
+ <div class="item-card-header-action-menu">
240
+ <slot name="item-card-actions" />
241
+ </div>
242
+ </template>
243
+ <template v-else-if="actions">
244
+ <div class="item-card-header-action-menu">
245
+ <ActionMenu
246
+ data-testid="item-card-header-action-menu"
247
+ :custom-actions="actions"
248
+ />
249
+ </div>
250
+ </template>
251
+ </div>
252
+ </div>
253
+
254
+ <slot name="item-card-sub-header" />
255
+
256
+ <template v-if="$slots['item-card-content']">
257
+ <slot name="item-card-content">
258
+ <div
259
+ class="item-card-content"
260
+ data-testid="item-card-content"
261
+ />
262
+ </slot>
263
+ </template>
264
+ <template v-else-if="content">
265
+ <div
266
+ class="item-card-content"
267
+ data-testid="item-card-content"
268
+ >
269
+ <p>{{ contentText }}</p>
270
+ </div>
271
+ </template>
272
+
273
+ <slot name="item-card-footer" />
274
+ </div>
275
+ </div>
276
+ </div>
277
+ </template>
278
+
279
+ <style scoped lang="scss">
280
+ $image-medium-box-width: 48px;
281
+
282
+ .item-card {
283
+ display: flex;
284
+ padding: 16px;
285
+ align-items: flex-start;
286
+ gap: var(--gap-lg);
287
+ border-radius: var(--border-radius-md);
288
+ border: 1px solid var(--border);
289
+ background: var(--body-bg);
290
+
291
+ &:hover {
292
+ border-color: var(--primary);
293
+ }
294
+
295
+ &:focus-visible {
296
+ @include focus-outline;
297
+ outline-offset: -2px;
298
+ }
299
+
300
+ &-image {
301
+ width: $image-medium-box-width;
302
+ height: $image-medium-box-width;
303
+ display: flex;
304
+ align-items: center;
305
+ justify-content: center;
306
+ background: #fff;
307
+ border-radius: var(--border-radius);
308
+
309
+ &.small {
310
+ width: 32px;
311
+ height: 32px;
312
+ margin-right: 12px;
313
+ }
314
+ }
315
+
316
+ &-header {
317
+ display: flex;
318
+ align-items: center;
319
+ justify-content: space-between;
320
+ width: 100%;
321
+ height: 24px;
322
+ color: var(--body-text);
323
+
324
+ &-left,
325
+ &-right {
326
+ display: flex;
327
+ align-items: center;
328
+ }
329
+
330
+ &-left {
331
+ flex-grow: 1;
332
+ }
333
+
334
+ &-title {
335
+ max-width: 60%;
336
+ font-size: 18px;
337
+ font-weight: 600;
338
+ margin-bottom: 0px;
339
+ line-height: 24px;
340
+ text-overflow: ellipsis;
341
+ white-space: nowrap;
342
+ overflow: hidden;
343
+ }
344
+
345
+ &-statuses {
346
+ display: flex;
347
+ align-items: flex-start;
348
+ gap: 12px;
349
+
350
+ &-status {
351
+ width: 24px;
352
+ height: 24px;
353
+ display: flex;
354
+ align-items: center;
355
+ justify-content: center;
356
+
357
+ .icon {
358
+ font-size: 23px;
359
+
360
+ &.error { color: var(--error); }
361
+ &.info { color: var(--info); }
362
+ &.success { color: var(--success); }
363
+ }
364
+ }
365
+ }
366
+
367
+ &-action-menu {
368
+ margin-left: 12px;
369
+ }
370
+ }
371
+
372
+ &-content {
373
+ display: -webkit-box;
374
+ -webkit-line-clamp: 3;
375
+ -webkit-box-orient: vertical;
376
+ overflow: hidden;
377
+ text-overflow: ellipsis;
378
+ line-height: 21px;
379
+ word-break: break-word;
380
+ }
381
+
382
+ &-pill {
383
+ display: flex;
384
+ width: $image-medium-box-width;
385
+ padding: 4px 8px;
386
+ margin-top: 16px;
387
+ justify-content: center;
388
+ align-items: center;
389
+ border-radius: var(--border-radius);
390
+ background: var(--default);
391
+ text-transform: uppercase;
392
+ color: var(--disabled-text);
393
+ font-size: 10px;
394
+ font-weight: 600;
395
+ }
396
+
397
+ &-body {
398
+ display: flex;
399
+ flex-direction: row;
400
+ width: 100%;
401
+ gap: var(--gap-lg);
402
+
403
+ &.small {
404
+ flex-direction: column;
405
+ align-items: flex-start;
406
+ gap: var(--gap);
407
+ flex: 1;
408
+ }
409
+
410
+ &-details {
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: flex-start;
414
+ width: calc(100% - var(--gap-lg) - $image-medium-box-width);
415
+ gap: var(--gap);
416
+ flex: 1;
417
+
418
+ &.small {
419
+ width: 100%;
420
+ }
421
+ }
422
+ }
423
+ }
424
+
425
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * RcItemCardAction
4
+ *
5
+ * This component is used to wrap any interactive elements (like buttons, links)
6
+ * inside an RcItemCard so they don't trigger the card-click event.
7
+ *
8
+ * Usage:
9
+ *
10
+ * <rc-item-card-action @click="doSomething">
11
+ * <a href="#">Click me</a>
12
+ * </rc-item-card-action>
13
+ *
14
+ */
15
+ </script>
16
+
17
+ <template>
18
+ <div
19
+ item-card-action
20
+ data-testid="rc-item-card-action"
21
+ >
22
+ <slot />
23
+ </div>
24
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as RcItemCard } from './RcItemCard.vue';
2
+ export { default as RcItemCardAction } from './RcItemCardAction.vue';
package/store/auth.js CHANGED
@@ -14,6 +14,7 @@ export const BASE_SCOPES = {
14
14
  azuread: [],
15
15
  keycloakoidc: ['openid profile email'],
16
16
  genericoidc: ['openid profile email'],
17
+ cognito: ['openid email'],
17
18
  };
18
19
 
19
20
  const KEY = 'rc_nonce';
package/store/catalog.js CHANGED
@@ -31,6 +31,12 @@ const CERTIFIED_SORTS = {
31
31
  other: 3,
32
32
  };
33
33
 
34
+ export const APP_STATUS = {
35
+ INSTALLED: 'installed',
36
+ DEPRECATED: 'deprecated',
37
+ UPGRADEABLE: 'upgradeable'
38
+ };
39
+
34
40
  export const APP_UPGRADE_STATUS = {
35
41
  NOT_APPLICABLE: 'not_applicable', // managed by fleet
36
42
  NO_UPGRADE: 'no_upgrade', // no upgrade found
@@ -498,35 +504,51 @@ function addChart(ctx, map, chart, repo) {
498
504
 
499
505
  if ( !obj ) {
500
506
  if ( ctx ) { }
507
+ const experimental = !!chart.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL];
508
+ const windowsIncompatible = !(chart.annotations?.[CATALOG_ANNOTATIONS.PERMITTED_OS] || '').includes('windows');
509
+ const deploysOnWindows = (chart.annotations?.[CATALOG_ANNOTATIONS.DEPLOYED_OS] || '').includes('windows');
510
+ const tags = [];
511
+
512
+ if (experimental) {
513
+ tags.push(ctx.rootGetters['i18n/withFallback']('generic.experimental'));
514
+ }
515
+ if (windowsIncompatible) {
516
+ tags.push(ctx.rootGetters['i18n/withFallback']('catalog.charts.windowsIncompatible'));
517
+ }
518
+ if (deploysOnWindows) {
519
+ tags.push(ctx.rootGetters['i18n/withFallback']('catalog.charts.deploysOnWindows'));
520
+ }
521
+
501
522
  obj = classify(ctx, {
502
523
  key,
503
- type: 'chart',
504
- id: key,
524
+ type: 'chart',
525
+ id: key,
505
526
  certified,
506
527
  sideLabel,
507
528
  repoType,
508
529
  repoName,
509
- repoNameDisplay: ctx.rootGetters['i18n/withFallback'](`catalog.repo.name."${ repoName }"`, null, repoName),
510
- certifiedSort: CERTIFIED_SORTS[certified] || 99,
511
- icon: chart.icon,
512
- color: repo.color,
513
- chartType: chart.annotations?.[CATALOG_ANNOTATIONS.TYPE] || CATALOG_ANNOTATIONS._APP,
514
- chartName: chart.name,
515
- chartNameDisplay: chart.annotations?.[CATALOG_ANNOTATIONS.DISPLAY_NAME] || chart.name,
516
- chartDescription: chart.description,
517
- featured: chart.annotations?.[CATALOG_ANNOTATIONS.FEATURED],
518
- repoKey: repo._key,
519
- versions: [],
520
- categories: filterCategories(chart.keywords),
521
- deprecated: !!chart.deprecated,
522
- experimental: !!chart.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL],
523
- hidden: !!chart.annotations?.[CATALOG_ANNOTATIONS.HIDDEN],
524
- targetNamespace: chart.annotations?.[CATALOG_ANNOTATIONS.NAMESPACE],
525
- targetName: chart.annotations?.[CATALOG_ANNOTATIONS.RELEASE_NAME],
526
- scope: chart.annotations?.[CATALOG_ANNOTATIONS.SCOPE],
527
- provides: [],
528
- windowsIncompatible: !(chart.annotations?.[CATALOG_ANNOTATIONS.PERMITTED_OS] || '').includes('windows'),
529
- deploysOnWindows: (chart.annotations?.[CATALOG_ANNOTATIONS.DEPLOYED_OS] || '').includes('windows')
530
+ repoNameDisplay: ctx.rootGetters['i18n/withFallback'](`catalog.repo.name."${ repoName }"`, null, repoName),
531
+ certifiedSort: CERTIFIED_SORTS[certified] || 99,
532
+ icon: chart.icon,
533
+ color: repo.color,
534
+ chartType: chart.annotations?.[CATALOG_ANNOTATIONS.TYPE] || CATALOG_ANNOTATIONS._APP,
535
+ chartName: chart.name,
536
+ chartNameDisplay: chart.annotations?.[CATALOG_ANNOTATIONS.DISPLAY_NAME] || chart.name,
537
+ chartDescription: chart.description,
538
+ featured: chart.annotations?.[CATALOG_ANNOTATIONS.FEATURED],
539
+ repoKey: repo._key,
540
+ versions: [],
541
+ categories: filterCategories(chart.keywords),
542
+ deprecated: !!chart.deprecated,
543
+ experimental,
544
+ hidden: !!chart.annotations?.[CATALOG_ANNOTATIONS.HIDDEN],
545
+ targetNamespace: chart.annotations?.[CATALOG_ANNOTATIONS.NAMESPACE],
546
+ targetName: chart.annotations?.[CATALOG_ANNOTATIONS.RELEASE_NAME],
547
+ scope: chart.annotations?.[CATALOG_ANNOTATIONS.SCOPE],
548
+ provides: [],
549
+ windowsIncompatible,
550
+ deploysOnWindows,
551
+ tags
530
552
  });
531
553
 
532
554
  map[key] = obj;
@@ -582,6 +604,16 @@ function normalizeCategory(c) {
582
604
  return c.replace(/\s+/g, '').toLowerCase();
583
605
  }
584
606
 
607
+ export function normalizeFilterQuery(value) {
608
+ if (Array.isArray(value)) {
609
+ return value.map((v) => v.toLowerCase());
610
+ } else if (value) {
611
+ return [value.toLowerCase()];
612
+ }
613
+
614
+ return undefined;
615
+ }
616
+
585
617
  /*
586
618
  catalog.cattle.io/deplys-on-os: OS -> requires global.cattle.OS.enabled: true
587
619
  default: nothing
@@ -614,6 +646,7 @@ export function filterAndArrangeCharts(charts, {
614
646
  clusterProvider = '',
615
647
  operatingSystems,
616
648
  category,
649
+ tag,
617
650
  searchQuery,
618
651
  showDeprecated = false,
619
652
  showHidden = false,
@@ -641,11 +674,16 @@ export function filterAndArrangeCharts(charts, {
641
674
  return false;
642
675
  }
643
676
 
644
- if ( category && !c.categories.includes(category) ) {
677
+ if (category?.length && !c.categories.some((cat) => category.includes(cat.toLowerCase()))) {
645
678
  // The category filter doesn't match
646
679
  return false;
647
680
  }
648
681
 
682
+ if (tag?.length && !c.tags.some((t) => tag.includes(t.toLowerCase()))) {
683
+ // The tag filter doesn't match
684
+ return false;
685
+ }
686
+
649
687
  if ( searchQuery ) {
650
688
  // The search filter doesn't match
651
689
  const searchTokens = searchQuery.split(/\s*[, ]\s*/).map((x) => ensureRegex(x, false));