@rancher/shell 3.0.8-rc.8 → 3.0.8

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 (260) hide show
  1. package/apis/impl/apis.ts +61 -0
  2. package/apis/index.ts +40 -0
  3. package/apis/intf/modal.ts +90 -0
  4. package/apis/intf/shell.ts +36 -0
  5. package/apis/intf/slide-in.ts +98 -0
  6. package/apis/intf/system.ts +41 -0
  7. package/apis/shell/__tests__/modal.test.ts +80 -0
  8. package/apis/shell/__tests__/notifications.test.ts +71 -0
  9. package/apis/shell/__tests__/slide-in.test.ts +54 -0
  10. package/apis/shell/__tests__/system.test.ts +129 -0
  11. package/apis/shell/index.ts +38 -0
  12. package/apis/shell/modal.ts +41 -0
  13. package/apis/shell/notifications.ts +65 -0
  14. package/apis/shell/slide-in.ts +33 -0
  15. package/apis/shell/system.ts +65 -0
  16. package/apis/vue-shim.d.ts +11 -0
  17. package/assets/brand/suse/dark/rancher-logo.svg +1 -64
  18. package/assets/styles/global/_tooltip.scss +6 -1
  19. package/assets/translations/en-us.yaml +14 -1
  20. package/components/ActionMenuShell.vue +3 -1
  21. package/components/BackLink.vue +8 -0
  22. package/components/BannerGraphic.vue +1 -5
  23. package/components/BrandImage.vue +17 -6
  24. package/components/Cron/CronExpressionEditor.vue +1 -1
  25. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  26. package/components/CruResource.vue +8 -1
  27. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +1 -0
  28. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +50 -1
  29. package/components/Drawer/ResourceDetailDrawer/composables.ts +19 -0
  30. package/components/Drawer/ResourceDetailDrawer/index.vue +4 -1
  31. package/components/Drawer/ResourceDetailDrawer/types.ts +2 -1
  32. package/components/LocaleSelector.vue +2 -2
  33. package/components/ModalManager.vue +11 -1
  34. package/components/Questions/__tests__/Yaml.test.ts +1 -1
  35. package/components/Questions/__tests__/index.test.ts +159 -0
  36. package/components/RelatedResources.vue +5 -0
  37. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  38. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  39. package/components/Resource/Detail/Metadata/index.vue +3 -3
  40. package/components/Resource/Detail/ResourcePopover/index.vue +5 -1
  41. package/components/Resource/Detail/composables.ts +2 -2
  42. package/components/ResourceDetail/Masthead/latest.vue +23 -21
  43. package/components/ResourceDetail/index.vue +3 -0
  44. package/components/ResourceTable.vue +54 -21
  45. package/components/SlideInPanelManager.vue +16 -11
  46. package/components/SortableTable/THead.vue +2 -1
  47. package/components/SortableTable/index.vue +20 -2
  48. package/components/Tabbed/__tests__/index.test.ts +86 -0
  49. package/components/Tabbed/index.vue +37 -2
  50. package/components/__tests__/NamespaceFilter.test.ts +49 -0
  51. package/components/auth/SelectPrincipal.vue +28 -6
  52. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  53. package/components/auth/login/ldap.vue +3 -3
  54. package/components/fleet/FleetSecretSelector.vue +1 -1
  55. package/components/form/KeyValue.vue +1 -1
  56. package/components/form/NameNsDescription.vue +1 -1
  57. package/components/form/NodeScheduling.vue +2 -2
  58. package/components/form/ResourceTabs/composable.ts +2 -2
  59. package/components/form/ResourceTabs/index.vue +0 -2
  60. package/components/form/__tests__/NameNsDescription.test.ts +42 -0
  61. package/components/formatter/InternalExternalIP.vue +4 -1
  62. package/components/formatter/LinkName.vue +5 -0
  63. package/components/formatter/__tests__/InternalExternalIP.test.ts +1 -1
  64. package/components/nav/Group.vue +25 -7
  65. package/components/nav/Header.vue +1 -1
  66. package/components/nav/NamespaceFilter.vue +1 -0
  67. package/components/nav/Type.vue +17 -6
  68. package/components/nav/WindowManager/panels/TabBodyContainer.vue +1 -1
  69. package/components/nav/__tests__/Type.test.ts +59 -0
  70. package/components/templates/standalone.vue +1 -1
  71. package/composables/cruResource.ts +27 -0
  72. package/composables/focusTrap.ts +3 -1
  73. package/composables/resourceDetail.ts +15 -0
  74. package/composables/useI18n.ts +10 -1
  75. package/composables/useLabeledFormElement.ts +3 -4
  76. package/config/__test__/uiplugins.test.ts +309 -0
  77. package/config/labels-annotations.js +1 -0
  78. package/config/product/explorer.js +3 -1
  79. package/config/product/fleet.js +1 -1
  80. package/config/router/navigation-guards/clusters.js +3 -3
  81. package/config/router/navigation-guards/products.js +1 -1
  82. package/config/router/routes.js +7 -7
  83. package/config/types.js +7 -0
  84. package/config/uiplugins.js +46 -2
  85. package/core/__tests__/extension-manager-impl.test.js +437 -0
  86. package/core/extension-manager-impl.js +21 -25
  87. package/core/plugin-helpers.ts +2 -2
  88. package/core/plugin.ts +9 -1
  89. package/core/plugins-loader.js +2 -2
  90. package/core/types-provisioning.ts +5 -1
  91. package/core/types.ts +35 -0
  92. package/detail/provisioning.cattle.io.cluster.vue +9 -6
  93. package/dialog/DeveloperLoadExtensionDialog.vue +13 -4
  94. package/dialog/MoveNamespaceDialog.vue +20 -4
  95. package/dialog/RollbackWorkloadDialog.vue +2 -5
  96. package/dialog/SearchDialog.vue +1 -0
  97. package/dialog/__tests__/MoveNamespaceDialog.test.ts +249 -0
  98. package/directives/__tests__/clean-tooltip.test.ts +298 -0
  99. package/directives/clean-tooltip.ts +234 -0
  100. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -2
  101. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +100 -3
  102. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  103. package/edit/configmap.vue +1 -0
  104. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  105. package/edit/fleet.cattle.io.helmop.vue +11 -6
  106. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  107. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  108. package/edit/logging-flow/index.vue +1 -0
  109. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  110. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  111. package/edit/management.cattle.io.project.vue +1 -0
  112. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  113. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  114. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  115. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  116. package/edit/monitoring.coreos.com.route.vue +1 -1
  117. package/edit/namespace.vue +1 -0
  118. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  119. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  120. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  121. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  122. package/edit/node.vue +1 -0
  123. package/edit/persistentvolume/index.vue +27 -22
  124. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  125. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  126. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  127. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  128. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  129. package/edit/persistentvolume/plugins/csi.vue +18 -16
  130. package/edit/persistentvolume/plugins/fc.vue +13 -14
  131. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  132. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  133. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  134. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  135. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  136. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  137. package/edit/persistentvolume/plugins/local.vue +1 -3
  138. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  139. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  140. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  141. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  142. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  143. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  144. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  145. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  146. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  147. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
  148. package/edit/provisioning.cattle.io.cluster/index.vue +5 -5
  149. package/edit/provisioning.cattle.io.cluster/rke2.vue +9 -8
  150. package/edit/resources.cattle.io.restore.vue +1 -1
  151. package/edit/secret/index.vue +1 -1
  152. package/edit/service.vue +1 -0
  153. package/edit/serviceaccount.vue +1 -0
  154. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  155. package/edit/workload/Job.vue +2 -2
  156. package/edit/workload/index.vue +2 -1
  157. package/edit/workload/mixins/workload.js +1 -1
  158. package/initialize/App.vue +4 -4
  159. package/initialize/install-plugins.js +19 -5
  160. package/machine-config/azure.vue +1 -1
  161. package/machine-config/components/GCEImage.vue +1 -1
  162. package/mixins/__tests__/brand.spec.ts +2 -2
  163. package/mixins/brand.js +1 -7
  164. package/mixins/create-edit-view/index.js +5 -0
  165. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +128 -5
  166. package/models/chart.js +70 -74
  167. package/models/management.cattle.io.cluster.js +21 -3
  168. package/models/provisioning.cattle.io.cluster.js +31 -11
  169. package/package.json +11 -10
  170. package/pages/auth/login.vue +4 -6
  171. package/pages/auth/setup.vue +1 -1
  172. package/pages/auth/verify.vue +3 -3
  173. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  174. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  175. package/pages/c/_cluster/apps/charts/index.vue +122 -24
  176. package/pages/c/_cluster/apps/charts/install.vue +33 -0
  177. package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
  178. package/pages/c/_cluster/explorer/index.vue +8 -6
  179. package/pages/c/_cluster/fleet/index.vue +4 -7
  180. package/pages/c/_cluster/manager/hostedprovider/index.vue +12 -6
  181. package/pages/c/_cluster/settings/brand.vue +1 -1
  182. package/pages/c/_cluster/settings/index.vue +5 -0
  183. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  184. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  185. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  186. package/pkg/auto-import.js +3 -3
  187. package/pkg/dynamic-importer.lib.js +1 -1
  188. package/pkg/import.js +1 -1
  189. package/plugins/__tests__/mutations.tests.ts +179 -0
  190. package/plugins/dashboard-client-init.js +3 -0
  191. package/plugins/dashboard-store/getters.js +19 -2
  192. package/plugins/dashboard-store/model-loader.js +1 -1
  193. package/plugins/dashboard-store/mutations.js +23 -2
  194. package/plugins/dashboard-store/resource-class.js +11 -5
  195. package/plugins/i18n.js +8 -0
  196. package/plugins/plugin.js +2 -2
  197. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +506 -0
  198. package/plugins/steve/steve-class.js +1 -1
  199. package/plugins/steve/steve-pagination-utils.ts +131 -47
  200. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  201. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  202. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -42
  203. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  204. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  205. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  206. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  207. package/rancher-components/Pill/types.ts +0 -1
  208. package/rancher-components/RcDropdown/useDropdownContext.ts +2 -4
  209. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  210. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  211. package/rancher-components/RcIcon/index.ts +1 -0
  212. package/rancher-components/RcIcon/types.ts +160 -0
  213. package/rancher-components/RcItemCard/RcItemCard.vue +1 -1
  214. package/rancher-components/utils/status.test.ts +67 -0
  215. package/rancher-components/utils/status.ts +77 -0
  216. package/scripts/publish-shell.sh +25 -0
  217. package/scripts/typegen.sh +1 -0
  218. package/store/__tests__/catalog.test.ts +1 -1
  219. package/store/__tests__/type-map.test.ts +164 -2
  220. package/store/action-menu.js +8 -0
  221. package/store/auth.js +25 -13
  222. package/store/catalog.js +6 -0
  223. package/store/i18n.js +3 -3
  224. package/store/index.js +8 -6
  225. package/store/notifications.ts +2 -0
  226. package/store/prefs.js +6 -7
  227. package/store/type-map.js +17 -7
  228. package/store/wm.ts +4 -4
  229. package/types/internal-api/shell/modal.d.ts +6 -6
  230. package/types/notifications/index.ts +126 -15
  231. package/types/rancher/index.d.ts +9 -0
  232. package/types/shell/index.d.ts +54 -3
  233. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  234. package/types/store/pagination.types.ts +157 -9
  235. package/types/vue-shim.d.ts +5 -4
  236. package/utils/__tests__/provider.test.ts +98 -0
  237. package/utils/__tests__/router.test.js +238 -0
  238. package/utils/__tests__/selector-typed.test.ts +263 -0
  239. package/utils/cluster.js +4 -1
  240. package/utils/color.js +1 -1
  241. package/utils/dynamic-content/__tests__/info.test.ts +6 -0
  242. package/utils/dynamic-content/info.ts +43 -0
  243. package/utils/favicon.js +4 -4
  244. package/utils/fleet.ts +8 -1
  245. package/utils/pagination-utils.ts +2 -2
  246. package/utils/pagination-wrapper.ts +1 -1
  247. package/utils/provider.ts +14 -0
  248. package/utils/router.js +50 -0
  249. package/utils/selector-typed.ts +6 -2
  250. package/utils/unit-tests/pagination-utils.spec.ts +8 -8
  251. package/vue.config.js +3 -3
  252. package/composables/useExtensionManager.ts +0 -17
  253. package/core/plugins.js +0 -38
  254. package/directives/clean-tooltip.js +0 -32
  255. package/plugins/internal-api/index.ts +0 -37
  256. package/plugins/internal-api/shared/base-api.ts +0 -13
  257. package/plugins/internal-api/shell/shell.api.ts +0 -108
  258. package/plugins/nuxt-client-init.js +0 -3
  259. package/types/internal-api/shell/growl.d.ts +0 -25
  260. package/types/internal-api/shell/slideIn.d.ts +0 -15
@@ -1,5 +1,7 @@
1
1
  import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
2
- import { PaginationParam, PaginationFilterField, PaginationParamProjectOrNamespace, PaginationParamFilter } from '@shell/types/store/pagination.types';
2
+ import {
3
+ PaginationParam, PaginationFilterField, PaginationParamProjectOrNamespace, PaginationParamFilter, PaginationFilterEquality
4
+ } from '@shell/types/store/pagination.types';
3
5
  import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
4
6
  import ModelNamespace from '@shell/models/namespace';
5
7
  import { uniq } from '@shell/utils/array';
@@ -35,18 +37,33 @@ interface Namespace extends ModelNamespace {
35
37
  }
36
38
  }
37
39
 
40
+ interface NamespaceProjectFilterResult {
41
+ /**
42
+ * True if the ns should be filtered IN. False if filtered OUT.
43
+ */
44
+ [nsName: string]: boolean;
45
+ }
46
+
47
+ /**
48
+ * Helper class, contains namespace / project filter specific functions
49
+ */
38
50
  class NamespaceProjectFilters {
39
51
  /**
40
52
  * User needs all resources.... except if there's some settings which should remove resources in specific circumstances
41
53
  */
42
54
  protected handlePrefAndSettingFilter(args: {
43
55
  allNamespaces: Namespace[],
56
+ /**
57
+ * Reserved / Obscure namespaces are ones used to support clusters and users. By default these are hidden
58
+ */
44
59
  showReservedRancherNamespaces: boolean,
60
+ /**
61
+ * Has product config disabled system projects and namespaces
62
+ */
45
63
  productHidesSystemNamespaces: boolean,
46
- }): PaginationParamFilter[] {
64
+ }): NamespaceProjectFilterResult {
47
65
  const { allNamespaces, showReservedRancherNamespaces, productHidesSystemNamespaces } = args;
48
66
 
49
- // These are AND'd together
50
67
  // Not ns 1 AND ns 2
51
68
  return allNamespaces.reduce((res, ns) => {
52
69
  // Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
@@ -56,13 +73,11 @@ class NamespaceProjectFilters {
56
73
  const hideSystem = productHidesSystemNamespaces ? ns.isSystem : false;
57
74
 
58
75
  if (hideObscure || hideSystem) {
59
- res.push(PaginationParamFilter.createSingleField({
60
- field: 'metadata.namespace', value: ns.name, equals: false
61
- }));
76
+ res[ns.name] = false;
62
77
  }
63
78
 
64
79
  return res;
65
- }, [] as PaginationParamFilter[]);
80
+ }, {} as NamespaceProjectFilterResult);
66
81
  }
67
82
 
68
83
  /**
@@ -76,31 +91,88 @@ class NamespaceProjectFilters {
76
91
  allNamespaces: Namespace[],
77
92
  isAllSystem: boolean,
78
93
  isAllUser: boolean,
79
- }) {
80
- const { allNamespaces, isAllSystem } = args;
94
+ }): NamespaceProjectFilterResult {
95
+ const { allNamespaces, isAllSystem, isAllUser } = args;
81
96
  const allSystem = allNamespaces.filter((ns) => ns.isSystem);
82
97
 
83
- // > Neither of these use projectsOrNamespaces to avoid scenarios where the local cluster provides a namespace which has
84
- // > a matching project... which could lead to results in the user project resource being included in the system filter
85
- if (isAllSystem) {
86
- // return resources in system ns 1 OR in system ns 2 ...
87
- // &filter=metadata.namespace=system ns 1,metadata.namespace=system ns 2
88
- return [PaginationParamFilter.createMultipleFields(
89
- allSystem.map(
90
- (ns) => new PaginationFilterField({ field: 'metadata.namespace', value: ns.name })
91
- )
92
- )];
93
- } else { // if isAllUser
94
- // return resources not in system ns 1 AND not in system ns 2 ...
95
- // &filter=metadata.namespace!=system ns 1&filter=metadata.namespace!=system ns 2
96
- return allSystem.map((ns) => PaginationParamFilter.createSingleField({
97
- field: 'metadata.namespace', value: ns.name, equals: false
98
+ return allSystem.reduce((res, ns) => {
99
+ if (isAllSystem) {
100
+ // We want to filter IN system namespaces
101
+ res[ns.name] = true;
102
+ }
103
+
104
+ if (isAllUser) {
105
+ // We want to filter OUT system namespaces
106
+ res[ns.name] = false;
107
+ }
108
+
109
+ return res;
110
+ }, {} as NamespaceProjectFilterResult);
111
+ }
112
+
113
+ /**
114
+ * Combine result `b` into `a` and return result
115
+ */
116
+ protected combineNsProjectFilterResults(a: NamespaceProjectFilterResult, b: NamespaceProjectFilterResult): NamespaceProjectFilterResult {
117
+ // Start with `a`
118
+ const res = { ...a };
119
+
120
+ // Merge entries from `b` into `a` if they don't exist in `a`. This maintains a hierarchy
121
+ // 1. if something has been excluded in `a` ignore requests to include given `b`
122
+ // 2. if something has been included in `a` ignore requests to exclude given `b`
123
+ Object.entries(b).forEach(([ns, include]) => {
124
+ if (res[ns] === undefined) {
125
+ res[ns] = include;
126
+ }
127
+ });
128
+
129
+ return res;
130
+ }
131
+
132
+ /**
133
+ * Convert @NamespaceProjectFilterResult into @PaginationParamFilter
134
+ */
135
+ protected createFiltersFromNamespaceProjectFilterResult(filterResult: NamespaceProjectFilterResult): PaginationParamFilter[] {
136
+ const inList: string[] = [];
137
+ const outList: string[] = [];
138
+
139
+ Object.entries(filterResult).forEach(([ns, include]) => {
140
+ if (include) {
141
+ inList.push(ns);
142
+ } else {
143
+ outList.push(ns);
144
+ }
145
+ });
146
+
147
+ const res: PaginationParamFilter[] = [];
148
+
149
+ // There's no point having both IN and OUT lists together, so prefer the IN list
150
+ if (inList.length) {
151
+ res.push(new PaginationParamFilter({
152
+ fields: [{
153
+ value: inList.join(','),
154
+ equality: PaginationFilterEquality.IN,
155
+ field: 'metadata.namespace',
156
+ }],
157
+ }));
158
+ } else if (outList.length) {
159
+ res.push(new PaginationParamFilter({
160
+ fields: [{
161
+ value: outList.join(','),
162
+ equality: PaginationFilterEquality.NOT_IN,
163
+ field: 'metadata.namespace',
164
+ }],
98
165
  }));
99
166
  }
167
+
168
+ return res;
100
169
  }
101
170
 
102
171
  /**
103
172
  * User needs resources in a set of projects or namespaces
173
+ *
174
+ * Mainly deals with the projectornamespaces filter, also ensures namespace in local cluster matching target project's aren't included
175
+ *
104
176
  */
105
177
  protected handleSelectionFilter(neu: string[], isLocalCluster: boolean) {
106
178
  // User has one or more projects or namespaces. We can pass this straight through to projectsornamespaces
@@ -112,12 +184,12 @@ class NamespaceProjectFilters {
112
184
  ];
113
185
 
114
186
  if (isLocalCluster) {
115
- // > As per `handleSystemOrUserFilter` above, we need to be careful of the local cluster where there's namespaces related to projects with the same id
116
- // > In this case
187
+ // We need to be careful of the local cluster where there's namespaces related to projects with the same id
188
+ // In this case
117
189
  // - We're including resources in the project and it's related namespace (via projectsornamespaces)
118
190
  // - We're also then excluding resources in the related namespace (via below `filter`)
119
191
 
120
- // Exclude resources NOT in projects namespace 1 AND not in projects namespace 2
192
+ // Exclude resources NOT in project's backing namespace 1 AND not in project's backing namespace 2
121
193
  // &filter=metadata.namespace!=pn1&filter=metadata.namespace!=pn2
122
194
  return {
123
195
  projectsOrNamespaces,
@@ -340,24 +412,29 @@ class StevePaginationUtils extends NamespaceProjectFilters {
340
412
  let projectsOrNamespaces: PaginationParamProjectOrNamespace[] = [];
341
413
  // used to return resources in / not in namespaces
342
414
  // &filter=metadata.namespace=abc
343
- let filters: PaginationParamFilter[] = [];
415
+ const filters: PaginationParamFilter[] = [];
416
+ let nsProjectFilterResults = {};
344
417
 
345
418
  if (!showReservedRancherNamespaces || productHidesSystemNamespaces) {
346
- // We need to hide reserved namespaces ('c-', 'user-', etc) OR system namespaces
347
- filters = this.handlePrefAndSettingFilter({
419
+ // We need to hide reserved namespaces ('c-', 'user-', etc) OR system namespaces (given product may hide them)
420
+ nsProjectFilterResults = this.combineNsProjectFilterResults(nsProjectFilterResults, this.handlePrefAndSettingFilter({
348
421
  allNamespaces, showReservedRancherNamespaces, productHidesSystemNamespaces
349
- });
422
+ }));
350
423
  }
351
424
 
352
425
  const isAllSystem = selection[0] === NAMESPACE_FILTER_ALL_SYSTEM;
353
426
  const isAllUser = selection[0] === NAMESPACE_FILTER_ALL_USER;
354
427
 
355
428
  if (selection.length === 1 && (isAllSystem || isAllUser)) {
356
- // Filter by resources either in or not in system namespaces
357
- filters.push(...this.handleSystemOrUserFilter({
429
+ // Filter by resources either in or not in system namespaces (given user selection)
430
+ nsProjectFilterResults = this.combineNsProjectFilterResults(nsProjectFilterResults, this.handleSystemOrUserFilter({
358
431
  allNamespaces, isAllSystem, isAllUser
359
432
  }));
433
+
434
+ filters.push(...this.createFiltersFromNamespaceProjectFilterResult(nsProjectFilterResults));
360
435
  } else {
436
+ filters.push(...this.createFiltersFromNamespaceProjectFilterResult(nsProjectFilterResults));
437
+
361
438
  // User has one or more projects or namespaces
362
439
  const res = this.handleSelectionFilter(selection, isLocalCluster);
363
440
 
@@ -502,29 +579,36 @@ class StevePaginationUtils extends NamespaceProjectFilters {
502
579
  // Check if the API supports filtering by this field
503
580
  this.validateField(validateFields, schema, field.field);
504
581
 
505
- // we're just checking that the field exists, so there's no value
582
+ // we're just checking that the field exists, so there's no equality or value
506
583
  if (field.exists) {
507
584
  return field.field;
508
585
  }
509
- const encodedValue = encodeURIComponent(field.value || '');
510
586
 
511
- // = exact match (equals + exact)
512
- // ~ partial match (equals + !exact)
513
- // != not exact match (!equals + exact)
514
- // !~ not partial match (!equals + !exact)
515
- const operator = `${ field.equals ? '' : '!' }${ field.exact ? '=' : '~' }`;
587
+ // If field was created by PaginationFilterField ctor equality will be set. If field created by json (legacy) it might not
588
+ const equality = field.equality || PaginationFilterField.safeEquality(field);
589
+
590
+ if (!equality) {
591
+ throw new Error(`A pagination filter must contain an equality. ${ JSON.stringify(field) }`);
592
+ }
593
+
516
594
  let safeValue;
517
595
 
518
- if (StevePaginationUtils.VALID_FIELD_VALUE_REGEX.test(field.value || '')) {
519
- // Does not contain any protected characters, send as is
520
- safeValue = encodedValue;
596
+ if ([PaginationFilterEquality.IN, PaginationFilterEquality.NOT_IN].includes(equality)) {
597
+ safeValue = `(${ field.value })`;
521
598
  } else {
522
- // Contains protected characters, wrap in quotes to ensure backend doesn't fail
523
- // - replace reserver `"`/`%22` with empty string - see https://github.com/rancher/dashboard/issues/14549 for improvement
524
- safeValue = `"${ encodedValue.replaceAll('%22', '') }"`;
599
+ const encodedValue = encodeURIComponent(field.value || '');
600
+
601
+ if (StevePaginationUtils.VALID_FIELD_VALUE_REGEX.test(field.value || '')) {
602
+ // Does not contain any protected characters, send as is
603
+ safeValue = encodedValue;
604
+ } else {
605
+ // Contains protected characters, wrap in quotes to ensure backend doesn't fail
606
+ // - replace reserver `"`/`%22` with empty string - see https://github.com/rancher/dashboard/issues/14549 for improvement
607
+ safeValue = `"${ encodedValue.replaceAll('%22', '') }"`;
608
+ }
525
609
  }
526
610
 
527
- return `${ this.convertArrayPath(field.field) }${ operator }${ safeValue }`;
611
+ return `${ this.convertArrayPath(field.field) }${ equality }${ safeValue }`;
528
612
  }
529
613
 
530
614
  return field.value;
@@ -269,7 +269,7 @@ export default defineComponent({
269
269
  class="checkbox-outer-container"
270
270
  data-checkbox-ctrl
271
271
  :class="{
272
- 'v-popper--has-tooltip': hasTooltip,
272
+ 'has-clean-tooltip': hasTooltip,
273
273
  }"
274
274
  >
275
275
  <label
@@ -355,7 +355,7 @@ export default defineComponent({
355
355
  disabled: isDisabled,
356
356
  [status]: status,
357
357
  suffix: hasSuffix,
358
- 'v-popper--has-tooltip': hasTooltip,
358
+ 'has-clean-tooltip': hasTooltip,
359
359
  'compact-input': isCompact,
360
360
  hideArrows,
361
361
  [className]: true
@@ -1,7 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { RcStatusBadgeProps } from './types';
3
+ import { useStatusColors } from '@components/utils/status';
3
4
 
4
5
  const props = defineProps<RcStatusBadgeProps>();
6
+
7
+ const { backgroundColor, borderColor, textColor } = useStatusColors(props, 'outlined');
5
8
  </script>
6
9
 
7
10
  <template>
@@ -27,47 +30,8 @@ const props = defineProps<RcStatusBadgeProps>();
27
30
  font-size: 12px;
28
31
  line-height: 19px;
29
32
 
30
- &.info {
31
- background-color: var(--rc-info-secondary);
32
- border-color: var(--rc-info-secondary);
33
- color: var(--rc-info);
34
- }
35
-
36
- &.success {
37
- background-color: var(--rc-success-secondary);
38
- border-color: var(--rc-success-secondary);
39
- color: var(--rc-success);
40
- }
41
-
42
- &.warning {
43
- background-color: var(--rc-warning);
44
- border-color: var(--rc-warning);
45
- color: var(--rc-warning-secondary);
46
- }
47
-
48
- &.error {
49
- background-color: var(--rc-error);
50
- border-color: var(--rc-error);
51
- color: var(--rc-error-secondary);
52
- }
53
-
54
- &.unknown {
55
- background-color: var(--rc-unknown);
56
- border-color: var(--rc-unknown);
57
- color: var(--rc-unknown-secondary);
58
- }
59
-
60
- &.none {
61
- border-color: var(--rc-none);
62
- color: var(--rc-none-secondary);
63
- }
64
-
65
- &.prime {
66
- background-color: var(--rc-success-secondary);
67
- border-color: var(--rc-success-secondary);
68
- color: var(--rc-success);
69
- font-size: 10px;
70
- line-height: 15px;
71
- }
33
+ background-color: v-bind(backgroundColor);
34
+ border-color: v-bind(borderColor);
35
+ color: v-bind(textColor);
72
36
  }
73
37
  </style>
@@ -1,2 +1 @@
1
1
  export { default } from './RcStatusBadge.vue';
2
- export type { Status } from '../types';
@@ -1,4 +1,4 @@
1
- import { Status } from '@components/Pill/types';
1
+ import { Status } from '@components/utils/status';
2
2
 
3
3
  export interface RcStatusBadgeProps {
4
4
  status: Status;
@@ -1,7 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { RcStatusIndicatorProps } from './types';
3
+ import { useStatusColors } from '@components/utils/status';
3
4
 
4
5
  const props = defineProps<RcStatusIndicatorProps>();
6
+
7
+ const { backgroundColor, borderColor } = useStatusColors(props, 'solid');
5
8
  </script>
6
9
 
7
10
  <template>
@@ -42,34 +45,8 @@ const props = defineProps<RcStatusIndicatorProps>();
42
45
  border-radius: 2px;
43
46
  }
44
47
 
45
- &.info {
46
- background-color: var(--rc-info);
47
- border-color: var(--rc-info);
48
- }
49
-
50
- &.success {
51
- background-color: var(--rc-success);
52
- border-color: var(--rc-success);
53
- }
54
-
55
- &.warning {
56
- background-color: var(--rc-warning);
57
- border-color: var(--rc-warning);
58
- }
59
-
60
- &.error {
61
- background-color: var(--rc-error);
62
- border-color: var(--rc-error);
63
- }
64
-
65
- &.unknown {
66
- background-color: var(--rc-unknown);
67
- border-color: var(--rc-unknown);
68
- }
69
-
70
- &.none {
71
- border-color: var(--rc-none);
72
- }
48
+ background-color: v-bind(backgroundColor);
49
+ border-color: v-bind(borderColor);
73
50
  }
74
51
  }
75
52
  </style>
@@ -1,4 +1,5 @@
1
- import { Status } from '../types';
1
+ import { Status } from '@components/utils/status';
2
+
2
3
  export type Shape = 'disc' | 'horizontal-bar' | 'vertical-bar';
3
4
 
4
5
  export interface RcStatusIndicatorProps {
@@ -1,3 +1,2 @@
1
1
  export type Shape = 'disc' | 'horizontal-bar' | 'vertical-bar';
2
- export type Status = 'info' | 'success' | 'warning' | 'error' | 'unknown' | 'none';
3
2
  export type Type = 'active' | 'inactive';
@@ -1,9 +1,7 @@
1
- import { ref, provide, nextTick, defineEmits } from 'vue';
1
+ import { ref, provide, nextTick, EmitFn } from 'vue';
2
2
  import { useDropdownCollection } from './useDropdownCollection';
3
3
  import { RcButtonType } from '@components/RcButton';
4
4
 
5
- const rcDropdownEmits = defineEmits(['update:open']);
6
-
7
5
  /**
8
6
  * Composable that provides the context for a dropdown menu. Includes methods
9
7
  * and state for managing the dropdown's visibility, focus, and keyboard
@@ -13,7 +11,7 @@ const rcDropdownEmits = defineEmits(['update:open']);
13
11
  * @returns Dropdown context methods and state. Used for programmatic
14
12
  * interactions and setting focus.
15
13
  */
16
- export const useDropdownContext = (emit: typeof rcDropdownEmits) => {
14
+ export const useDropdownContext = (emit: EmitFn<['update:open']>) => {
17
15
  const {
18
16
  dropdownItems,
19
17
  firstDropdownItem,
@@ -0,0 +1,51 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import RcIcon from './RcIcon.vue';
3
+
4
+ describe('rcIcon.vue', () => {
5
+ it('renders with the correct type class and size classes', () => {
6
+ const wrapper = shallowMount(RcIcon, {
7
+ props: {
8
+ size: 'medium',
9
+ type: 'search',
10
+ },
11
+ });
12
+
13
+ expect(wrapper.classes()).toContain('icon-search');
14
+ expect(wrapper.classes()).toContain('medium');
15
+ });
16
+
17
+ it('sets aria-hidden to true by default', () => {
18
+ const wrapper = shallowMount(RcIcon, {
19
+ props: {
20
+ size: 'medium',
21
+ type: 'search',
22
+ },
23
+ });
24
+
25
+ expect(wrapper.attributes('aria-hidden')).toBe('true');
26
+ });
27
+
28
+ it('sets aria-hidden to false when explicitly provided', () => {
29
+ const wrapper = shallowMount(RcIcon, {
30
+ props: {
31
+ size: 'medium',
32
+ type: 'search',
33
+ ariaHidden: false,
34
+ },
35
+ });
36
+
37
+ expect(wrapper.attributes('aria-hidden')).toBe('false');
38
+ });
39
+
40
+ it('sets aria-hidden to true when explicitly provided', () => {
41
+ const wrapper = shallowMount(RcIcon, {
42
+ props: {
43
+ size: 'medium',
44
+ type: 'search',
45
+ ariaHidden: true,
46
+ },
47
+ });
48
+
49
+ expect(wrapper.attributes('aria-hidden')).toBe('true');
50
+ });
51
+ });
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import { RcIconProps, RcIconType, RcIconSize } from '@components/RcIcon/types';
3
+ import { computed } from 'vue';
4
+ import { useStatusColors } from '@components/utils/status';
5
+ const props = withDefaults(defineProps<RcIconProps>(), { size: 'small', ariaHidden: true });
6
+ const fontSize = computed(() => {
7
+ return RcIconSize[props.size];
8
+ });
9
+
10
+ const iconClass = computed(() => {
11
+ return RcIconType[props.type];
12
+ });
13
+
14
+ const status = computed(() => {
15
+ if (props.status && props.status !== 'inherit') {
16
+ return props.status;
17
+ }
18
+
19
+ return 'none';
20
+ });
21
+
22
+ const { textColor } = useStatusColors({ status: status.value }, 'outlined');
23
+
24
+ const color = computed(() => {
25
+ if (props.status === 'inherit') {
26
+ return 'inherit';
27
+ }
28
+
29
+ return textColor.value;
30
+ });
31
+ </script>
32
+
33
+ <template>
34
+ <i
35
+ class="rc-icon"
36
+ :class="{[props.size]: true, [iconClass]: true}"
37
+ :aria-hidden="props.ariaHidden"
38
+ />
39
+ </template>
40
+
41
+ <style lang="scss" scoped>
42
+ .rc-icon {
43
+ font-size: v-bind(fontSize);
44
+ color: v-bind(color);
45
+ }
46
+ </style>
@@ -0,0 +1 @@
1
+ export { default as RcIcon } from './RcIcon.vue';