@rancher/shell 3.0.1 → 3.0.2-rc.1

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 (96) hide show
  1. package/assets/styles/base/_basic.scss +17 -5
  2. package/assets/styles/base/_mixins.scss +2 -1
  3. package/assets/styles/global/_button.scss +10 -0
  4. package/assets/styles/global/_form.scss +2 -2
  5. package/assets/translations/en-us.yaml +33 -5
  6. package/assets/translations/zh-hans.yaml +1 -1
  7. package/components/ActionMenu.vue +8 -0
  8. package/components/AsyncButton.vue +9 -3
  9. package/components/BannerGraphic.vue +10 -0
  10. package/components/ButtonGroup.vue +2 -0
  11. package/components/ButtonMultiAction.vue +6 -0
  12. package/components/ClusterIconMenu.vue +1 -1
  13. package/components/CodeMirror.vue +28 -1
  14. package/components/CommunityLinks.vue +13 -0
  15. package/components/CruResource.vue +6 -0
  16. package/components/GrowlManager.vue +14 -4
  17. package/components/LocaleSelector.vue +49 -5
  18. package/components/PaginatedResourceTable.vue +4 -3
  19. package/components/ResourceDetail/Masthead.vue +11 -4
  20. package/components/ResourceList/index.vue +5 -3
  21. package/components/ResourceTable.vue +1 -1
  22. package/components/SortableTable/THead.vue +19 -4
  23. package/components/SortableTable/index.vue +13 -9
  24. package/components/SortableTable/selection.js +19 -5
  25. package/components/YamlEditor.vue +2 -1
  26. package/components/auth/SelectPrincipal.vue +1 -1
  27. package/components/fleet/FleetBundles.vue +2 -1
  28. package/components/form/LabeledSelect.vue +20 -7
  29. package/components/form/NodeScheduling.vue +5 -1
  30. package/components/form/Password.vue +23 -13
  31. package/components/form/ResourceLabeledSelect.vue +1 -1
  32. package/components/form/Select.vue +28 -6
  33. package/components/form/SelectOrCreateAuthSecret.vue +39 -11
  34. package/components/form/__tests__/NodeScheduling.test.ts +44 -0
  35. package/components/formatter/Endpoints.vue +1 -1
  36. package/components/formatter/LiveExpiryDate.vue +5 -1
  37. package/components/formatter/ServiceTargets.vue +1 -1
  38. package/components/formatter/ServiceType.vue +19 -17
  39. package/components/nav/Pinned.vue +6 -1
  40. package/components/nav/TopLevelMenu.helper.ts +17 -1
  41. package/components/nav/TopLevelMenu.vue +154 -19
  42. package/config/pagination-table-headers.js +9 -1
  43. package/config/product/apps.js +63 -30
  44. package/config/product/explorer.js +182 -17
  45. package/config/product/settings.js +9 -1
  46. package/config/router/routes.js +0 -1
  47. package/config/settings.ts +20 -2
  48. package/config/table-headers.js +23 -15
  49. package/config/types.js +2 -1
  50. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +12 -3
  51. package/edit/fleet.cattle.io.gitrepo.vue +40 -33
  52. package/edit/provisioning.cattle.io.cluster/rke2.vue +13 -2
  53. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +10 -2
  54. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +8 -2
  55. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +6 -3
  56. package/edit/workload/mixins/workload.js +15 -7
  57. package/list/catalog.cattle.io.app.vue +4 -11
  58. package/list/catalog.cattle.io.clusterrepo.vue +59 -25
  59. package/list/fleet.cattle.io.bundle.vue +2 -2
  60. package/list/management.cattle.io.feature.vue +12 -5
  61. package/list/management.cattle.io.setting.vue +30 -19
  62. package/list/namespace.vue +4 -1
  63. package/list/networking.k8s.io.ingress.vue +14 -11
  64. package/list/node.vue +65 -63
  65. package/list/persistentvolume.vue +55 -20
  66. package/list/persistentvolumeclaim.vue +3 -15
  67. package/list/service.vue +16 -21
  68. package/list/workload.vue +35 -49
  69. package/mixins/resource-fetch.js +8 -1
  70. package/mixins/vue-select-overrides.js +10 -16
  71. package/models/management.cattle.io.cluster.js +6 -1
  72. package/models/persistentvolume.js +1 -3
  73. package/models/storage.k8s.io.storageclass.js +4 -0
  74. package/package.json +28 -29
  75. package/pages/c/_cluster/explorer/EventsTable.vue +58 -16
  76. package/pages/c/_cluster/explorer/index.vue +3 -16
  77. package/pages/c/_cluster/settings/performance.vue +49 -23
  78. package/pages/home.vue +24 -3
  79. package/pages/support/index.vue +1 -1
  80. package/plugins/floating-vue.js +1 -1
  81. package/plugins/steve/steve-pagination-utils.ts +85 -15
  82. package/rancher-components/Banner/Banner.vue +12 -0
  83. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -5
  84. package/rancher-components/Form/Radio/RadioButton.vue +0 -6
  85. package/rancher-components/Form/Radio/RadioGroup.vue +5 -1
  86. package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +2 -2
  87. package/scripts/test-plugins-build.sh +21 -6
  88. package/scripts/typegen.sh +1 -0
  89. package/store/index.js +16 -0
  90. package/store/type-map.utils.ts +14 -1
  91. package/types/shell/index.d.ts +467 -418
  92. package/types/store/vuex.d.ts +1 -1
  93. package/types/vue-shim.d.ts +2 -8
  94. package/utils/cluster.js +2 -2
  95. package/utils/string.js +6 -0
  96. package/vue.config.js +3 -4
@@ -86,9 +86,7 @@ export default {
86
86
 
87
87
  this.tlsMode = tls;
88
88
 
89
- if (this.value.spec.correctDrift === undefined) {
90
- this.value.spec['correctDrift'] = { enabled: false };
91
- }
89
+ this.correctDriftEnabled = this.value.spec?.correctDrift?.enabled || false;
92
90
 
93
91
  this.updateTargets();
94
92
  },
@@ -119,7 +117,7 @@ export default {
119
117
  subtext: this.t('fleet.gitRepo.add.steps.repoInfo.subtext'),
120
118
  descriptionKey: 'fleet.gitRepo.add.steps.repoInfo.description',
121
119
  ready: false,
122
- weight: 30
120
+ weight: 1
123
121
  };
124
122
 
125
123
  const stepTargetInfo = {
@@ -129,11 +127,9 @@ export default {
129
127
  subtext: this.t('fleet.gitRepo.add.steps.targetInfo.subtext'),
130
128
  descriptionKey: 'fleet.gitRepo.steps.add.targetInfo.description',
131
129
  ready: true,
132
- weight: 30
130
+ weight: 1
133
131
  };
134
132
 
135
- const addRepositorySteps = [stepRepoInfo, stepTargetInfo].sort((a, b) => (b.weight || 0) - (a.weight || 0));
136
-
137
133
  return {
138
134
  allClusters: [],
139
135
  allClusterGroups: [],
@@ -145,6 +141,7 @@ export default {
145
141
  privateKey: null,
146
142
  tlsMode: null,
147
143
  caBundle: null,
144
+ correctDriftEnabled: false,
148
145
  targetAdvancedErrors: null,
149
146
  matchingClusters: null,
150
147
  ref,
@@ -155,7 +152,6 @@ export default {
155
152
  targetAdvanced,
156
153
  stepRepoInfo,
157
154
  stepTargetInfo,
158
- addRepositorySteps,
159
155
  displayHelmRepoURLRegex: false,
160
156
  fvFormRuleSets: [{ path: 'spec.repo', rules: ['required'] }]
161
157
  };
@@ -168,6 +164,13 @@ export default {
168
164
  return _SPECIFY;
169
165
  },
170
166
 
167
+ steps() {
168
+ return [
169
+ this.stepRepoInfo,
170
+ this.stepTargetInfo
171
+ ];
172
+ },
173
+
171
174
  isLocal() {
172
175
  return this.value.metadata.namespace === 'fleet-local';
173
176
  },
@@ -463,7 +466,7 @@ export default {
463
466
  },
464
467
 
465
468
  stepOneReady() {
466
- this.addRepositorySteps[0]['ready'] = this.stepOneRequires;
469
+ this.stepRepoInfo['ready'] = this.stepOneRequires;
467
470
  },
468
471
 
469
472
  updateTls() {
@@ -492,6 +495,12 @@ export default {
492
495
  }
493
496
  }
494
497
  },
498
+
499
+ onSave() {
500
+ this.value.spec['correctDrift'] = { enabled: this.correctDriftEnabled };
501
+
502
+ this.save();
503
+ }
495
504
  }
496
505
  };
497
506
  </script>
@@ -507,13 +516,12 @@ export default {
507
516
  :subtypes="[]"
508
517
  :validation-passed="true"
509
518
  :errors="errors"
510
- :steps="addRepositorySteps"
511
- :edit-first-step="true"
519
+ :steps="steps"
512
520
  :finish-mode="'finish'"
513
521
  class="wizard"
514
522
  @cancel="done"
515
523
  @error="e=>errors = e"
516
- @finish="save"
524
+ @finish="onSave"
517
525
  >
518
526
  <template #noticeBanner>
519
527
  <Banner
@@ -646,35 +654,26 @@ export default {
646
654
  </template>
647
655
  <div class="spacer" />
648
656
  <h2 v-t="'fleet.gitRepo.resources.label'" />
649
- <div>
657
+ <div class="resource-handling">
650
658
  <Checkbox
651
- v-model:value="value.spec.correctDrift.enabled"
659
+ v-model:value="correctDriftEnabled"
660
+ :tooltip="t('fleet.gitRepo.resources.correctDriftBanner')"
652
661
  data-testid="GitRepo-correctDrift-checkbox"
653
662
  class="check"
654
663
  type="checkbox"
655
664
  label-key="fleet.gitRepo.resources.correctDrift"
656
665
  :mode="mode"
657
666
  />
658
- <Banner
659
- data-testid="GitRepo-correctDrift-banner"
660
- color="info"
661
- >
662
- {{ t('fleet.gitRepo.resources.correctDriftBanner') }}
663
- </Banner>
667
+ <Checkbox
668
+ v-model:value="value.spec.keepResources"
669
+ :tooltip="t('fleet.gitRepo.resources.keepResourcesBanner')"
670
+ data-testid="GitRepo-keepResources-checkbox"
671
+ class="check"
672
+ type="checkbox"
673
+ label-key="fleet.gitRepo.resources.keepResources"
674
+ :mode="mode"
675
+ />
664
676
  </div>
665
-
666
- <Checkbox
667
- v-model:value="value.spec.keepResources"
668
- class="check"
669
- type="checkbox"
670
- label-key="fleet.gitRepo.resources.keepResources"
671
- :mode="mode"
672
- />
673
- <Banner
674
- color="info"
675
- >
676
- {{ t('fleet.gitRepo.resources.keepResourcesBanner') }}
677
- </Banner>
678
677
  <div class="spacer" />
679
678
  <h2 v-t="'fleet.gitRepo.paths.label'" />
680
679
  <ArrayList
@@ -764,3 +763,11 @@ export default {
764
763
  </template>
765
764
  </CruResource>
766
765
  </template>
766
+
767
+ <style lang="scss" scoped>
768
+ .resource-handling {
769
+ display: flex;
770
+ flex-direction: column;
771
+ gap: 5px
772
+ }
773
+ </style>
@@ -248,6 +248,7 @@ export default {
248
248
  busy: false,
249
249
  machinePoolValidation: {}, // map of validation states for each machine pool
250
250
  machinePoolErrors: {},
251
+ addonConfigValidation: {}, // validation state of each addon config (boolean of whether codemirror's yaml lint passed)
251
252
  allNamespaces: [],
252
253
  extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.CLUSTER_CREATE_RKE2, this.$route, this),
253
254
  labelForAddon
@@ -797,7 +798,9 @@ export default {
797
798
  // and in all of the validation statuses for each machine pool
798
799
  Object.values(this.machinePoolValidation).forEach((v) => (base = base && v));
799
800
 
800
- return validRequiredPools && base;
801
+ const hasAddonConfigErrors = Object.values(this.addonConfigValidation).filter((v) => v === false).length > 0;
802
+
803
+ return validRequiredPools && base && !hasAddonConfigErrors;
801
804
  },
802
805
  currentCluster() {
803
806
  if (this.mode === _EDIT) {
@@ -1565,6 +1568,8 @@ export default {
1565
1568
  * 2) We're ready to cache any values the user provides for each addon
1566
1569
  */
1567
1570
  async initAddons() {
1571
+ this.addonConfigValidation = {};
1572
+
1568
1573
  for (const chartName of this.addonNames) {
1569
1574
  const entry = this.chartVersions[chartName];
1570
1575
 
@@ -2133,7 +2138,11 @@ export default {
2133
2138
  }
2134
2139
  }
2135
2140
  }
2136
- }
2141
+ },
2142
+
2143
+ addonConfigValidationChanged(configName, isValid) {
2144
+ this.addonConfigValidation[configName] = isValid;
2145
+ },
2137
2146
  }
2138
2147
  };
2139
2148
  </script>
@@ -2430,6 +2439,7 @@ export default {
2430
2439
  :label="labelForAddon($store, v.name, false)"
2431
2440
  :weight="9"
2432
2441
  :showHeader="false"
2442
+ :error="addonConfigValidation[v.name]===false"
2433
2443
  @active="showAddons(v.name)"
2434
2444
  >
2435
2445
  <AddOnConfig
@@ -2444,6 +2454,7 @@ export default {
2444
2454
  @update:value="$emit('input', $event)"
2445
2455
  @update-questions="syncChartValues"
2446
2456
  @update-values="updateValues"
2457
+ @validationChanged="e => addonConfigValidationChanged(v.name, e)"
2447
2458
  />
2448
2459
  </Tab>
2449
2460
 
@@ -7,7 +7,7 @@ import { labelForAddon } from '@shell/utils/cluster';
7
7
  import { _EDIT } from '@shell/config/query-params';
8
8
 
9
9
  export default {
10
- emits: ['additional-manifest-changed', 'update-questions', 'update-values'],
10
+ emits: ['additional-manifest-changed', 'update-questions', 'update-values', 'validationChanged'],
11
11
 
12
12
  components: {
13
13
  Banner,
@@ -60,7 +60,13 @@ export default {
60
60
  isEdit() {
61
61
  return this.mode === _EDIT;
62
62
  }
63
- }
63
+ },
64
+
65
+ methods: {
66
+ handleValidationChanged(e) {
67
+ this.$emit('validationChanged', e);
68
+ }
69
+ },
64
70
  };
65
71
  </script>
66
72
 
@@ -91,12 +97,14 @@ export default {
91
97
  <YamlEditor
92
98
  v-else
93
99
  ref="yaml-values"
100
+ data-testid="addon-yaml-editor"
94
101
  :value="initYamlEditor(addonVersion.name)"
95
102
  :scrolling="true"
96
103
  :as-object="true"
97
104
  :editor-mode="mode === 'view' ? 'VIEW_CODE' : 'EDIT_CODE'"
98
105
  :hide-preview-buttons="true"
99
106
  @update:value="$emit('update-values', addonVersion.name, $event)"
107
+ @validationChanged="handleValidationChanged"
100
108
  />
101
109
  <div class="spacer" />
102
110
  </div>
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { clone } from '@shell/utils/object';
2
3
  import ArrayListGrouped from '@shell/components/form/ArrayListGrouped';
3
4
  import { LabeledInput } from '@components/Form/LabeledInput';
4
5
  import { Checkbox } from '@components/Form/Checkbox';
@@ -6,6 +7,7 @@ import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthS
6
7
  import CreateEditView from '@shell/mixins/create-edit-view';
7
8
  import SecretSelector from '@shell/components/form/SecretSelector';
8
9
  import { SECRET_TYPES as TYPES } from '@shell/config/secret';
10
+ import { isBase64 } from '@shell/utils/string';
9
11
  import { base64Decode, base64Encode } from '@shell/utils/crypto';
10
12
 
11
13
  export default {
@@ -42,7 +44,7 @@ export default {
42
44
  },
43
45
 
44
46
  data() {
45
- const configMap = this.value.spec.rkeConfig?.registries?.configs || {};
47
+ const configMap = clone(this.value.spec.rkeConfig?.registries?.configs) || {};
46
48
  const entries = [];
47
49
 
48
50
  const defaultAddValue = {
@@ -57,7 +59,11 @@ export default {
57
59
  if (configMap[hostname]) {
58
60
  configMap[hostname].insecureSkipVerify = configMap[hostname].insecureSkipVerify ?? defaultAddValue.insecureSkipVerify;
59
61
  configMap[hostname].authConfigSecretName = configMap[hostname].authConfigSecretName ?? defaultAddValue.authConfigSecretName;
60
- configMap[hostname].caBundle = base64Decode(configMap[hostname].caBundle ?? defaultAddValue.caBundle);
62
+
63
+ const caBundle = configMap[hostname].caBundle ?? defaultAddValue.caBundle;
64
+
65
+ configMap[hostname].caBundle = isBase64(caBundle) ? base64Decode(caBundle) : caBundle;
66
+
61
67
  configMap[hostname].tlsSecretName = configMap[hostname].tlsSecretName ?? defaultAddValue.tlsSecretName;
62
68
  }
63
69
  entries.push({
@@ -23,10 +23,13 @@ describe('component: RegistryConfigs', () => {
23
23
  };
24
24
 
25
25
  describe('key CA Cert Bundle', () => {
26
- it('should display default key', () => {
26
+ it.each([
27
+ ['source is plain text', 'Zm9vYmFy', 'foobar'],
28
+ ['source is base64', 'foobar', 'foobar'],
29
+ ])('should display key, %p', (_, sourceCaBundle, displayedCaBundle) => {
27
30
  const value = clone(PROV_CLUSTER);
28
31
 
29
- value.spec.rkeConfig.registries.configs = { foo: { caBundle: 'Zm9vYmFy' } };
32
+ value.spec.rkeConfig.registries.configs = { foo: { caBundle: sourceCaBundle } };
30
33
 
31
34
  mountOptions.propsData.value = value;
32
35
 
@@ -37,7 +40,7 @@ describe('component: RegistryConfigs', () => {
37
40
 
38
41
  const registry = wrapper.findComponent('[data-testid^="registry-caBundle"]');
39
42
 
40
- expect(registry.props().value).toBe('foobar');
43
+ expect(registry.props().value).toBe(displayedCaBundle);
41
44
  });
42
45
 
43
46
  it('should update key in base64 format', async() => {
@@ -250,7 +250,6 @@ export default {
250
250
  }
251
251
  }
252
252
 
253
- this.selectContainer(container);
254
253
  if (this.realMode === _CLONE && this.value.type === WORKLOAD_TYPES.JOB) {
255
254
  this.cleanUpClonedJobData();
256
255
  }
@@ -280,12 +279,10 @@ export default {
280
279
  podFsGroup: podTemplateSpec.securityContext?.fsGroup,
281
280
  savePvcHookName: 'savePvcHook',
282
281
  tabWeightMap: TAB_WEIGHT_MAP,
283
- fvFormRuleSets: [{
284
- path: 'image', rootObject: this.container, rules: ['required'], translationKey: 'workload.container.image'
285
- }],
286
- fvReportedValidationPaths: ['spec'],
287
- isNamespaceNew: false,
288
- idKey: ID_KEY
282
+ fvFormRuleSets: [],
283
+ fvReportedValidationPaths: ['spec'],
284
+ isNamespaceNew: false,
285
+ idKey: ID_KEY
289
286
  };
290
287
  },
291
288
 
@@ -605,6 +602,15 @@ export default {
605
602
  this.value['type'] = neu;
606
603
  delete this.value.apiVersion;
607
604
  },
605
+
606
+ container: {
607
+ handler(c) {
608
+ this.fvFormRuleSets = [{
609
+ path: 'image', rootObject: c, rules: ['required'], translationKey: 'workload.container.image'
610
+ }];
611
+ },
612
+ immediate: true
613
+ }
608
614
  },
609
615
 
610
616
  created() {
@@ -612,6 +618,8 @@ export default {
612
618
  this.registerBeforeHook(this.getPorts, 'getPorts');
613
619
 
614
620
  this.registerAfterHook(this.saveService, 'saveService');
621
+
622
+ this.selectContainer(this.container);
615
623
  },
616
624
 
617
625
  methods: {
@@ -1,11 +1,9 @@
1
1
  <script>
2
- import ResourceTable from '@shell/components/ResourceTable';
3
- import ResourceFetch from '@shell/mixins/resource-fetch';
2
+ import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
4
3
 
5
4
  export default {
6
5
  name: 'ListApps',
7
- components: { ResourceTable },
8
- mixins: [ResourceFetch],
6
+ components: { PaginatedResourceTable },
9
7
 
10
8
  props: {
11
9
  resource: {
@@ -25,20 +23,15 @@ export default {
25
23
 
26
24
  async fetch() {
27
25
  await this.$store.dispatch('catalog/load');
28
-
29
- await this.$fetchType(this.resource);
30
26
  },
31
27
  };
32
28
  </script>
33
29
 
34
30
  <template>
35
- <ResourceTable
31
+ <PaginatedResourceTable
36
32
  class="apps"
37
33
  :schema="schema"
38
- :rows="rows"
39
- :loading="loading"
40
34
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
41
- :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
42
35
  data-testid="installed-app-catalog-list"
43
36
  >
44
37
  <template #cell:upgrade="{row}">
@@ -56,7 +49,7 @@ export default {
56
49
  class="text-muted"
57
50
  />
58
51
  </template>
59
- </ResourceTable>
52
+ </PaginatedResourceTable>
60
53
  </template>
61
54
 
62
55
  <style scoped>
@@ -1,47 +1,81 @@
1
- <script>
2
- import ResourceTable from '@shell/components/ResourceTable';
1
+ <script lang="ts">
2
+ import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
3
3
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
4
+ import ClusterRepo from '@shell/models/catalog.cattle.io.clusterrepo';
5
+ import { PaginationArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
6
+ import { defineComponent } from 'vue';
4
7
 
5
- export default {
6
- name: 'ListClusterReposApps',
7
- components: { ResourceTable },
8
- props: {
9
- resource: {
10
- type: String,
11
- required: true,
12
- },
8
+ export default defineComponent({
9
+ name: 'ListClusterReposApps',
10
+
11
+ components: { PaginatedResourceTable },
12
+
13
+ props: {
13
14
  schema: {
14
15
  type: Object,
15
16
  required: true,
16
17
  },
17
- rows: {
18
- type: Array,
19
- required: true,
20
- },
21
- loading: {
22
- type: Boolean,
23
- required: false,
24
- },
25
18
  useQueryParamsForSimpleFiltering: {
26
19
  type: Boolean,
27
20
  default: false
28
21
  }
29
22
  },
30
23
 
31
- computed: {
32
- filterHideRows() {
33
- return this.rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
24
+ methods: {
25
+ /**
26
+ * Filter out hidden repos from list of all repos
27
+ */
28
+ filterRowsLocal(rows: ClusterRepo[]) {
29
+ return rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
30
+ },
31
+
32
+ /**
33
+ * Filter out hidden repos via api
34
+ */
35
+ filterRowsApi(pagination: PaginationArgs): PaginationArgs {
36
+ if (!pagination.filters) {
37
+ pagination.filters = [];
38
+ }
39
+
40
+ const field = `metadata.annotations[${ CATALOG_ANNOTATIONS.HIDDEN_REPO }]`;
41
+
42
+ let existing: PaginationParamFilter | null = null;
43
+
44
+ for (let i = 0; i < pagination.filters.length; i++) {
45
+ const filter = pagination.filters[i];
46
+
47
+ if (!!filter.fields.find((f) => f.field === field)) {
48
+ existing = filter;
49
+ break;
50
+ }
51
+ }
52
+
53
+ const required = PaginationParamFilter.createSingleField({
54
+ field,
55
+ exact: true,
56
+ value: 'true',
57
+ equals: false
58
+ });
59
+
60
+ if (!!existing) {
61
+ Object.assign(existing, required);
62
+ } else {
63
+ pagination.filters.push(required);
64
+ }
65
+
66
+ return pagination;
34
67
  }
35
68
  }
36
- };
69
+
70
+ });
37
71
  </script>
38
72
 
39
73
  <template>
40
74
  <div>
41
- <ResourceTable
75
+ <PaginatedResourceTable
42
76
  :schema="schema"
43
- :rows="filterHideRows"
44
- :loading="loading"
77
+ :local-filter="filterRowsLocal"
78
+ :api-filter="filterRowsApi"
45
79
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
46
80
  data-testid="app-cluster-repo-list"
47
81
  />
@@ -115,11 +115,11 @@ export default {
115
115
  >
116
116
  <template #cell:deploymentsReady="{row}">
117
117
  <span
118
- v-if="row.status && (row.status.summary.desiredReady !== row.status.summary.ready)"
118
+ v-if="row.status && row.status.summary && (row.status.summary.desiredReady !== row.status.summary.ready)"
119
119
  class="text-warning"
120
120
  >
121
121
  {{ row.status.summary.ready }}/{{ row.status.summary.desiredReady }}</span>
122
- <span v-else-if="row.status">{{ row.status.summary.desiredReady }}</span>
122
+ <span v-else-if="row.status && row.status.summary">{{ row.status.summary.desiredReady }}</span>
123
123
  <span v-else>-</span>
124
124
  </template>
125
125
  </ResourceTable>
@@ -9,6 +9,7 @@ import { LabeledInput } from '@components/Form/LabeledInput';
9
9
  import { MANAGEMENT } from '@shell/config/types';
10
10
  import { SETTING } from '@shell/config/settings';
11
11
  import ResourceFetch from '@shell/mixins/resource-fetch';
12
+ import { getVendor } from '@shell/config/private-label';
12
13
 
13
14
  export default {
14
15
  components: {
@@ -63,6 +64,7 @@ export default {
63
64
  serverUrl: '',
64
65
  noUrlSet: false,
65
66
  showModal: false,
67
+ vendor: getVendor(),
66
68
  };
67
69
  },
68
70
 
@@ -93,6 +95,9 @@ export default {
93
95
  watch: {
94
96
  showPromptUpdate(show) {
95
97
  if (show) {
98
+ // Clear last error
99
+ this.error = null;
100
+
96
101
  this.showModal = true;
97
102
  } else {
98
103
  this.showModal = false;
@@ -138,7 +143,9 @@ export default {
138
143
  btnCB(true);
139
144
  this.close();
140
145
  } catch (err) {
141
- this.error = err;
146
+ // An error occurred, so toggle back the value - the call failed, so the change was not made
147
+ this.update.spec.value = !this.update.enabled;
148
+ this.error = err.message || err;
142
149
  btnCB(false);
143
150
  }
144
151
  },
@@ -214,7 +221,7 @@ export default {
214
221
  v-if="showModal"
215
222
  class="update-modal"
216
223
  name="toggleFlag"
217
- :width="350"
224
+ :width="450"
218
225
  height="auto"
219
226
  styles="max-height: 100vh;"
220
227
  :click-to-close="!restart || !waiting"
@@ -227,7 +234,7 @@ export default {
227
234
  >
228
235
  <template #title>
229
236
  <h4 class="text-default-text">
230
- Are you sure?
237
+ {{ t('featureFlags.title') }}
231
238
  </h4>
232
239
  </template>
233
240
  <template #body>
@@ -263,8 +270,8 @@ export default {
263
270
  </span>
264
271
  <Banner
265
272
  v-if="restart"
266
- color="warning"
267
- :label="t('featureFlags.restartRequired')"
273
+ color="error"
274
+ :label="t('featureFlags.restartRequired', vendor)"
268
275
  />
269
276
  </div>
270
277
  <div class="text-error mb-10">