@rancher/shell 0.1.4 → 0.1.21

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 (152) hide show
  1. package/assets/brand/suse/favicon.png +0 -0
  2. package/assets/images/generic-plugin.svg +1 -7
  3. package/assets/translations/en-us.yaml +81 -47
  4. package/components/CommunityLinks.vue +40 -49
  5. package/components/ExplorerProjectsNamespaces.vue +20 -3
  6. package/components/LazyImage.vue +21 -8
  7. package/components/PromptRemove.vue +2 -2
  8. package/components/ResourceList/Masthead.vue +21 -1
  9. package/components/ResourceList/ResourceLoadingIndicator.vue +0 -8
  10. package/components/ResourceList/index.vue +9 -23
  11. package/components/SortableTable/index.vue +13 -10
  12. package/components/Tabbed/index.vue +25 -7
  13. package/components/TypeDescription.vue +10 -1
  14. package/components/fleet/FleetClusters.vue +6 -0
  15. package/components/fleet/FleetRepos.vue +7 -1
  16. package/components/form/Command.vue +5 -0
  17. package/components/form/EnvVars.vue +5 -0
  18. package/components/form/NameNsDescription.vue +3 -1
  19. package/components/form/NodeScheduling.vue +6 -1
  20. package/components/form/PodAffinity.vue +5 -0
  21. package/components/form/ServiceNameSelect.vue +5 -0
  22. package/components/form/ValueFromResource.vue +7 -1
  23. package/components/nav/TopLevelMenu.vue +2 -1
  24. package/config/home-links.js +155 -0
  25. package/config/private-label.js +1 -1
  26. package/config/product/manager.js +0 -2
  27. package/config/product/uiplugins.js +1 -1
  28. package/config/settings.js +3 -1
  29. package/config/uiplugins.js +63 -6
  30. package/config/version.js +17 -0
  31. package/core/plugin.ts +12 -0
  32. package/core/plugins.js +29 -5
  33. package/core/types.ts +6 -0
  34. package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
  35. package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
  36. package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
  37. package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
  38. package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
  39. package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
  40. package/creators/app/init +16 -17
  41. package/creators/app/package.json +6 -0
  42. package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
  43. package/creators/pkg/{index.ts → files/index.ts} +0 -0
  44. package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
  45. package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
  46. package/creators/pkg/init +1 -1
  47. package/creators/update/init +54 -0
  48. package/creators/update/package.json +20 -0
  49. package/creators/update/upgrade +56 -0
  50. package/creators/update/yarn-error.log +54 -0
  51. package/detail/workload/index.vue +1 -0
  52. package/edit/persistentvolume/index.vue +48 -13
  53. package/edit/persistentvolumeclaim.vue +31 -13
  54. package/edit/provisioning.cattle.io.cluster/rke2.vue +27 -19
  55. package/edit/workload/index.vue +19 -9
  56. package/edit/workload/mixins/workload.js +109 -114
  57. package/edit/workload/storage/index.vue +11 -17
  58. package/edit/workload/storage/persistentVolumeClaim/index.vue +5 -0
  59. package/edit/workload/storage/secret.vue +6 -1
  60. package/list/catalog.cattle.io.app.vue +10 -9
  61. package/list/catalog.cattle.io.clusterrepo.vue +6 -61
  62. package/list/cis.cattle.io.clusterscan.vue +12 -12
  63. package/list/fleet.cattle.io.bundle.vue +33 -28
  64. package/list/fleet.cattle.io.cluster.vue +26 -22
  65. package/list/fleet.cattle.io.clustergroup.vue +6 -0
  66. package/list/fleet.cattle.io.clusterregistrationtoken.vue +28 -24
  67. package/list/fleet.cattle.io.gitrepo.vue +25 -14
  68. package/list/helm.cattle.io.projecthelmchart.vue +52 -33
  69. package/list/logging.banzaicloud.io.clusterflow.vue +7 -12
  70. package/list/logging.banzaicloud.io.flow.vue +7 -14
  71. package/list/management.cattle.io.cluster.vue +26 -15
  72. package/list/management.cattle.io.feature.vue +13 -8
  73. package/list/management.cattle.io.user.vue +38 -19
  74. package/list/monitoring.coreos.com.alertmanagerconfig.vue +8 -15
  75. package/list/namespace.vue +14 -1
  76. package/list/node.vue +13 -16
  77. package/list/persistentvolume.vue +16 -9
  78. package/list/persistentvolumeclaim.vue +5 -8
  79. package/list/provisioning.cattle.io.cluster.vue +34 -8
  80. package/list/service.vue +24 -12
  81. package/list/ui.cattle.io.navlink.vue +6 -0
  82. package/list/workload.vue +2 -2
  83. package/middleware/authenticated.js +6 -0
  84. package/mixins/resource-fetch.js +12 -18
  85. package/mixins/resource-manager.js +126 -0
  86. package/models/catalog.cattle.io.uiplugin.js +4 -0
  87. package/models/pod.js +15 -5
  88. package/models/provisioning.cattle.io.cluster.js +4 -0
  89. package/models/workload.service.js +10 -0
  90. package/nuxt.config.js +2 -1
  91. package/package.json +1 -1
  92. package/pages/auth/login.vue +10 -0
  93. package/pages/auth/verify.vue +9 -0
  94. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +108 -0
  95. package/pages/c/_cluster/settings/links.vue +53 -101
  96. package/pages/c/_cluster/settings/performance.vue +90 -7
  97. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +3 -3
  98. package/pages/c/_cluster/uiplugins/InstallDialog.vue +71 -20
  99. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +21 -5
  100. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -7
  101. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +23 -15
  102. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +11 -4
  103. package/pages/c/_cluster/uiplugins/index.vue +179 -65
  104. package/pages/support/index.vue +31 -142
  105. package/plugins/dashboard-store/actions.js +19 -0
  106. package/plugins/dashboard-store/getters.js +20 -3
  107. package/plugins/dashboard-store/mutations.js +13 -7
  108. package/plugins/plugin.js +18 -15
  109. package/plugins/steve/getters.js +12 -0
  110. package/plugins/version.js +21 -0
  111. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -7
  112. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  113. package/rancher-components/components/BadgeState/BadgeState.vue +107 -0
  114. package/rancher-components/components/BadgeState/index.ts +1 -0
  115. package/rancher-components/components/Banner/Banner.test.ts +13 -0
  116. package/rancher-components/components/Banner/Banner.vue +163 -0
  117. package/rancher-components/components/Banner/index.ts +1 -0
  118. package/rancher-components/components/Card/Card.vue +150 -0
  119. package/rancher-components/components/Card/index.ts +1 -0
  120. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
  121. package/rancher-components/components/Form/Checkbox/Checkbox.vue +395 -0
  122. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  123. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +29 -0
  124. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +343 -0
  125. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  126. package/rancher-components/components/Form/Radio/RadioButton.vue +270 -0
  127. package/rancher-components/components/Form/Radio/RadioGroup.vue +235 -0
  128. package/rancher-components/components/Form/Radio/index.ts +2 -0
  129. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +168 -0
  130. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  131. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  132. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +137 -0
  133. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  134. package/rancher-components/components/Form/index.ts +5 -0
  135. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +137 -0
  136. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  137. package/scripts/publish-shell.sh +39 -6
  138. package/scripts/record-deps.js +37 -0
  139. package/scripts/test-plugins-build.sh +8 -5
  140. package/scripts/typegen.sh +84 -0
  141. package/store/auth.js +3 -0
  142. package/store/index.js +12 -3
  143. package/types/shell/index.d.ts +3046 -0
  144. package/utils/favicon.js +8 -2
  145. package/utils/gc/gc-interval.ts +40 -0
  146. package/utils/gc/gc-root-store.js +76 -0
  147. package/utils/gc/gc-route-changed.ts +44 -0
  148. package/utils/gc/gc-types.ts +21 -0
  149. package/utils/gc/gc.ts +282 -0
  150. package/config/footer.js +0 -18
  151. package/creators/pkg/nuxt.config.js +0 -6
  152. package/yarn-error.log +0 -195
@@ -3,50 +3,13 @@ import Loading from '@shell/components/Loading';
3
3
  import AsyncButton from '@shell/components/AsyncButton';
4
4
  import Banner from '@components/Banner/Banner.vue';
5
5
  import { MANAGEMENT } from '@shell/config/types';
6
- import { fetchOrCreateSetting, SETTING } from '@shell/config/settings';
7
6
  import { _EDIT, _VIEW } from '@shell/config/query-params';
8
7
  import KeyValue from '@shell/components/form/KeyValue';
9
- import { allHash } from '@shell/utils/promise';
10
8
  import { mapGetters } from 'vuex';
11
-
12
- const DEFAULT_CUSTOM_LINKS = [
13
- {
14
- order: 1,
15
- key: 'customLinks.defaults.docs',
16
- value: 'https://rancher.com/docs/rancher/v2.6/en'
17
- },
18
- {
19
- order: 2,
20
- key: 'customLinks.defaults.forums',
21
- value: 'https://forums.rancher.com/'
22
-
23
- },
24
- {
25
- order: 3,
26
- key: 'customLinks.defaults.slack',
27
- value: 'https://slack.rancher.io/'
28
- },
29
- {
30
- order: 5,
31
- key: 'customLinks.defaults.getStarted',
32
- value: '/docs/getting-started'
33
- }
34
-
35
- ];
36
-
37
- const DEFAULT_SUPPORT_LINK = {
38
- order: 4,
39
- key: 'customLinks.defaults.issues',
40
- value: 'https://github.com/rancher/dashboard/issues/new'
41
- };
42
-
43
- const COMMUNITY_LINKS = [
44
- {
45
- order: 99,
46
- key: 'customLinks.defaults.commercialSupport',
47
- value: '/support'
48
- }
49
- ];
9
+ import { isRancherPrime } from '@shell/config/version';
10
+ import DefaultLinksEditor from './DefaultLinksEditor';
11
+ import { CUSTOM_LINKS_VERSION, fetchLinks } from '@shell/config/home-links';
12
+ import { SETTING, fetchOrCreateSetting } from '@shell/config/settings';
50
13
 
51
14
  export default {
52
15
  layout: 'authenticated',
@@ -55,40 +18,20 @@ export default {
55
18
  Loading,
56
19
  AsyncButton,
57
20
  Banner,
21
+ DefaultLinksEditor,
58
22
  },
59
23
  async fetch() {
60
- try {
61
- const { uiIssuesSetting, uiCommunitySetting } = await allHash({
62
- uiIssuesSetting: this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES }),
63
- uiCommunitySetting: this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.COMMUNITY_LINKS })
64
- });
65
-
66
- this.uiIssuesSetting = uiIssuesSetting;
67
- this.uiCommunitySetting = uiCommunitySetting;
68
- } catch {}
69
-
70
- try {
71
- const defaultIssueLink = !!this.uiIssuesSetting.value ? { key: this.t('customLinks.defaults.issues'), value: this.uiIssuesSetting.value } : DEFAULT_SUPPORT_LINK;
72
- const defaultLinks = this.multiWithFallback([...DEFAULT_CUSTOM_LINKS, defaultIssueLink, ...COMMUNITY_LINKS]);
73
-
74
- this.uiCustomLinks = await fetchOrCreateSetting(this.$store, SETTING.UI_CUSTOM_LINKS, JSON.stringify(defaultLinks));
75
-
76
- await this.deprecateIssueLinks();
77
- } catch {}
78
-
79
- const sValue = this.uiCustomLinks?.value || JSON.stringify(this.multiWithFallback([...DEFAULT_CUSTOM_LINKS]));
80
-
81
- this.value = JSON.parse(sValue);
24
+ this.value = await fetchLinks(this.$store, this.hasSupport, false, str => this.t(str));
82
25
  },
83
26
 
84
27
  data() {
85
28
  return {
29
+ defaultsDisabled: true,
30
+ isRancherPrime: isRancherPrime(),
86
31
  uiCustomLinks: {},
87
- defaultValues: undefined,
88
32
  bannerVal: {},
89
- value: {},
33
+ value: [],
90
34
  errors: [],
91
- showRestoredBanner: false
92
35
  };
93
36
  },
94
37
  computed: {
@@ -99,20 +42,20 @@ export default {
99
42
 
100
43
  return schema?.resourceMethods?.includes('PUT') ? _EDIT : _VIEW;
101
44
  },
102
- },
103
- methods: {
104
- useDefaults() {
105
- const nonCommercialRancherLinks = this.isCommercial ? [] : COMMUNITY_LINKS;
106
45
 
107
- this.defaultValues = this.multiWithFallback([...DEFAULT_CUSTOM_LINKS, DEFAULT_SUPPORT_LINK, ...nonCommercialRancherLinks]);
108
-
109
- this.showRestoredBanner = true;
110
-
111
- setTimeout(() => {
112
- this.showRestoredBanner = false;
113
- }, 10000);
46
+ allValues() {
47
+ return {
48
+ version: CUSTOM_LINKS_VERSION,
49
+ defaults: this.value.defaults.filter(obj => obj.enabled).map(obj => obj.key),
50
+ custom: this.value.custom
51
+ };
114
52
  },
115
53
 
54
+ hasSupport() {
55
+ return isRancherPrime() || this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SUPPORTED )?.value === 'true';
56
+ },
57
+ },
58
+ methods: {
116
59
  deprecateIssueLinks() {
117
60
  if (this.uiIssuesSetting.value || this.uiIssuesSetting.value) {
118
61
  this.uiIssuesSetting.value = '';
@@ -123,10 +66,15 @@ export default {
123
66
  },
124
67
 
125
68
  async save(btnCB) {
126
- this.uiCustomLinks.value = JSON.stringify(this.value);
127
69
  this.errors = [];
128
70
  try {
129
- await this.uiCustomLinks.save();
71
+ const uiCustomLinks = await fetchOrCreateSetting(this.$store, SETTING.UI_CUSTOM_LINKS, '');
72
+
73
+ uiCustomLinks.value = JSON.stringify(this.allValues);
74
+
75
+ await uiCustomLinks.save();
76
+
77
+ this.value = await fetchLinks(this.$store, this.hasSupport, false, str => this.t(str));
130
78
  btnCB(true);
131
79
  } catch (err) {
132
80
  this.errors.push(err);
@@ -139,38 +87,39 @@ export default {
139
87
  <template>
140
88
  <Loading v-if="$fetchState.pending" />
141
89
  <div v-else>
142
- <Banner v-if="showRestoredBanner" :color="'success'" label="Default restored" :closable="true" :label-key="'customLinks.restoreSuccess'" />
143
- <h1
144
- class="mb-20"
145
- >
90
+ <h1 class="mb-20">
146
91
  {{ t("customLinks.label") }}
147
92
  </h1>
148
93
  <div>
149
94
  <label class="text-label">
150
95
  {{ t(`customLinks.description`, {}, true) }}
151
96
  </label>
152
- <div class="ui-links-setting mt-20">
153
- <KeyValue
154
- v-model="value"
155
- :default-value="defaultValues"
156
- :as-map="false"
157
- :key-label="t('customLinks.settings.keyLabel')"
158
- :value-label="t('customLinks.settings.valueLabel')"
159
- :add-label="t('customLinks.addLink')"
160
- :mode="mode"
161
- :read-allowed="false"
162
- :protip="false"
163
- />
164
- </div>
97
+ </div>
98
+ <div class="mt-20">
99
+ <KeyValue
100
+ v-model="value.custom"
101
+ :title="'Custom Links'"
102
+ :as-map="false"
103
+ key-name="label"
104
+ :key-label="t('customLinks.settings.keyLabel')"
105
+ :value-label="t('customLinks.settings.valueLabel')"
106
+ :add-label="t('customLinks.addLink')"
107
+ :read-allowed="false"
108
+ :protip="false"
109
+ :mode="mode"
110
+ />
111
+ </div>
112
+ <div class="ui-links-setting mt-20">
113
+ <DefaultLinksEditor
114
+ v-model="value.defaults"
115
+ :mode="mode"
116
+ />
165
117
  </div>
166
118
  <template v-for="err in errors">
167
119
  <Banner :key="err" color="error" :label="err" />
168
120
  </template>
169
121
  <div v-if="mode === 'edit'" class="mt-20">
170
122
  <AsyncButton class="pull-right" mode="apply" @click="save" />
171
- <button class="pull-right btn role-secondary mr-10" @click="useDefaults">
172
- {{ t('customLinks.restoreDefaults') }}
173
- </button>
174
123
  </div>
175
124
  </div>
176
125
  </template>
@@ -194,7 +143,10 @@ export default {
194
143
  text-decoration: underline;
195
144
  }
196
145
  }
197
- .input {
198
- max-width: 25%;
146
+ .action {
147
+ display: flex;
148
+ input {
149
+ margin-right: 5px;
150
+ }
199
151
  }
200
152
  </style>
@@ -7,6 +7,7 @@ import { LabeledInput } from '@components/Form/LabeledInput';
7
7
  import { MANAGEMENT } from '@shell/config/types';
8
8
  import { DEFAULT_PERF_SETTING, SETTING } from '@shell/config/settings';
9
9
  import { _EDIT, _VIEW } from '@shell/config/query-params';
10
+ import UnitInput from '@shell/components/form/UnitInput';
10
11
 
11
12
  export default {
12
13
  layout: 'authenticated',
@@ -16,6 +17,7 @@ export default {
16
17
  AsyncButton,
17
18
  Banner,
18
19
  LabeledInput,
20
+ UnitInput
19
21
  },
20
22
 
21
23
  async fetch() {
@@ -30,15 +32,21 @@ export default {
30
32
 
31
33
  const sValue = this.uiPerfSetting?.value || JSON.stringify(DEFAULT_PERF_SETTING);
32
34
 
33
- this.value = JSON.parse(sValue);
35
+ this.value = {
36
+ ...DEFAULT_PERF_SETTING,
37
+ ...JSON.parse(sValue),
38
+ };
39
+
40
+ this.gcStartedEnabled = this.value.garbageCollection.enabled;
34
41
  },
35
42
 
36
43
  data() {
37
44
  return {
38
- uiPerfSetting: DEFAULT_PERF_SETTING,
39
- bannerVal: {},
40
- value: {},
41
- errors: [],
45
+ uiPerfSetting: DEFAULT_PERF_SETTING,
46
+ bannerVal: {},
47
+ value: {},
48
+ errors: [],
49
+ gcStartedEnabled: null
42
50
  };
43
51
  },
44
52
 
@@ -57,12 +65,19 @@ export default {
57
65
 
58
66
  try {
59
67
  await this.uiPerfSetting.save();
68
+
69
+ this.$store.dispatch('gcPreferencesUpdated', {
70
+ previouslyEnabled: this.gcStartedEnabled,
71
+ newPreferences: this.value.garbageCollection
72
+ }, { root: true });
73
+
74
+ this.gcStartedEnabled = this.value.garbageCollection.enabled;
60
75
  btnCB(true);
61
76
  } catch (err) {
62
77
  this.errors.push(err);
63
78
  btnCB(false);
64
79
  }
65
- },
80
+ }
66
81
  }
67
82
  };
68
83
  </script>
@@ -75,7 +90,7 @@ export default {
75
90
  <div>
76
91
  <div class="ui-perf-setting">
77
92
  <!-- Websocket Notifications -->
78
- <div class="mt-40">
93
+ <div class="mt-20">
79
94
  <h2>{{ t('performance.websocketNotification.label') }}</h2>
80
95
  <p>{{ t('performance.websocketNotification.description') }}</p>
81
96
  <Checkbox
@@ -134,6 +149,74 @@ export default {
134
149
  />
135
150
  </div>
136
151
  </div>
152
+ <!-- Enable GC of resources from store -->
153
+ <div class="mt-40">
154
+ <h2 v-t="'performance.gc.label'" />
155
+ <p>{{ t('performance.gc.description') }}</p>
156
+ <Banner color="error" label-key="performance.gc.banner" />
157
+ <Checkbox
158
+ v-model="value.garbageCollection.enabled"
159
+ :label="t('performance.gc.checkboxLabel')"
160
+ class="mt-10 mb-20"
161
+ :primary="true"
162
+ />
163
+ <div class="ml-20">
164
+ <h3>{{ t('performance.gc.whenRun.description') }}</h3>
165
+ <div class="ml-20 mb-10">
166
+ <Checkbox
167
+ v-model="value.garbageCollection.enabledInterval"
168
+ :class="{ 'text-muted': !value.garbageCollection.enabled }"
169
+ :label="t('performance.gc.whenRun.intervalCheckBox.label')"
170
+ class="mt-10 mb-10"
171
+ :disabled="!value.garbageCollection.enabled"
172
+ :primary="true"
173
+ />
174
+ <div class="ml-20">
175
+ <UnitInput
176
+ v-model="value.garbageCollection.interval"
177
+ :suffix="t('suffix.seconds', { count: value.garbageCollection.interval })"
178
+ :label="t('performance.gc.whenRun.interval.inputLabel')"
179
+ :disabled="!value.garbageCollection.enabled || !value.garbageCollection.enabledInterval"
180
+ min="30"
181
+ class="input"
182
+ />
183
+ </div>
184
+ <Checkbox
185
+ v-model="value.garbageCollection.enabledOnNavigate"
186
+ :class="{ 'text-muted': !value.garbageCollection.enabled }"
187
+ :label="t('performance.gc.whenRun.route.description')"
188
+ class="mt-20 mb-10"
189
+ :disabled="!value.garbageCollection.enabled"
190
+ :primary="true"
191
+ />
192
+ </div>
193
+ <h3>{{ t('performance.gc.howRun.description') }}</h3>
194
+ <div class="ml-20">
195
+ <p :class="{ 'text-muted': !value.garbageCollection.enabled }">
196
+ {{ t('performance.gc.howRun.age.description', {}, true) }}
197
+ </p>
198
+ <UnitInput
199
+ v-model="value.garbageCollection.ageThreshold"
200
+ :suffix="t('suffix.seconds', { count: value.garbageCollection.ageThreshold })"
201
+ :label="t('performance.gc.howRun.age.inputLabel')"
202
+ :disabled="!value.garbageCollection.enabled"
203
+ min="30"
204
+ class="input"
205
+ />
206
+ <p class="mt-20" :class="{ 'text-muted': !value.garbageCollection.enabled }">
207
+ {{ t('performance.gc.howRun.count.description') }}
208
+ </p>
209
+ <LabeledInput
210
+ v-model.number="value.garbageCollection.countThreshold"
211
+ :label="t('performance.gc.howRun.count.inputLabel')"
212
+ :disabled="!value.garbageCollection.enabled"
213
+ class="input"
214
+ type="number"
215
+ min="0"
216
+ />
217
+ </div>
218
+ </div>
219
+ </div>
137
220
  </div>
138
221
  </div>
139
222
  <template v-for="err in errors">
@@ -83,9 +83,9 @@ export default {
83
83
 
84
84
  const parts = name.split('-');
85
85
 
86
- if (parts.length === 2) {
87
- crdName = parts[0];
88
- version = parts[1];
86
+ if (parts.length >= 2) {
87
+ version = parts.pop();
88
+ crdName = parts.join('-');
89
89
  }
90
90
 
91
91
  if (this.persist) {
@@ -1,7 +1,7 @@
1
1
  <script>
2
2
  import AsyncButton from '@shell/components/AsyncButton';
3
3
  import LabeledSelect from '@shell/components/form/LabeledSelect';
4
- import { CATALOG } from '@shell/config/types';
4
+ import { CATALOG, MANAGEMENT } from '@shell/config/types';
5
5
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
6
6
  import { UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
7
7
  import Banner from '@components/Banner/Banner.vue';
@@ -15,13 +15,21 @@ export default {
15
15
  LabeledSelect,
16
16
  },
17
17
 
18
+ async fetch() {
19
+ this.defaultRegistrySetting = await this.$store.dispatch('management/find', {
20
+ type: MANAGEMENT.SETTING,
21
+ id: 'system-default-registry'
22
+ });
23
+ },
24
+
18
25
  data() {
19
26
  return {
20
- plugin: undefined,
21
- busy: false,
22
- version: '',
23
- update: false,
24
- mode: '',
27
+ defaultRegistrySetting: null,
28
+ plugin: undefined,
29
+ busy: false,
30
+ version: '',
31
+ update: false,
32
+ mode: '',
25
33
  };
26
34
  },
27
35
 
@@ -92,7 +100,7 @@ export default {
92
100
 
93
101
  const plugin = this.plugin;
94
102
 
95
- this.$emit(plugin.name, 'install');
103
+ this.$emit('update', plugin.name, 'install');
96
104
 
97
105
  // Find the version that the user wants to install
98
106
  const version = plugin.versions?.find(v => v.version === this.version);
@@ -103,6 +111,35 @@ export default {
103
111
  return;
104
112
  }
105
113
 
114
+ // is the image used by the chart in the rancher org?
115
+ let isRancherImage = false;
116
+
117
+ try {
118
+ const chartVersionInfo = await this.$store.dispatch('catalog/getVersionInfo', {
119
+ repoType: version.repoType,
120
+ repoName: version.repoName,
121
+ chartName: plugin.chart.chartName,
122
+ versionName: this.version,
123
+ });
124
+
125
+ const image = chartVersionInfo?.values?.image?.repository || '';
126
+
127
+ isRancherImage = image.startsWith('rancher/');
128
+ } catch (e) {}
129
+
130
+ // See if there is already a plugin with this name
131
+ let exists = false;
132
+
133
+ try {
134
+ const app = await this.$store.dispatch('management/find', {
135
+ type: CATALOG.APP,
136
+ id: `${ UI_PLUGIN_NAMESPACE }/${ plugin.chart.chartName }`,
137
+ opt: { force: true },
138
+ });
139
+
140
+ exists = !!app;
141
+ } catch (e) {}
142
+
106
143
  const repoType = version.repoType;
107
144
  const repoName = version.repoName;
108
145
  const repo = this.$store.getters['catalog/repo']({ repoType, repoName });
@@ -118,6 +155,15 @@ export default {
118
155
  values: {}
119
156
  };
120
157
 
158
+ // Pass in the system default registry property if set - only if the image is in the rancher org
159
+ const defaultRegistry = this.defaultRegistrySetting?.value || '';
160
+
161
+ if (isRancherImage && defaultRegistry) {
162
+ chart.values.global = chart.values.global || {};
163
+ chart.values.global.cattle = chart.values.global.cattle || {};
164
+ chart.values.global.cattle.systemDefaultRegistry = defaultRegistry;
165
+ }
166
+
121
167
  const input = {
122
168
  charts: [chart],
123
169
  // timeout: this.cmdOptions.timeout > 0 ? `${ this.cmdOptions.timeout }s` : null,
@@ -126,24 +172,29 @@ export default {
126
172
  };
127
173
 
128
174
  // Helm action
129
- const action = this.update ? 'upgrade' : 'install';
175
+ const action = (exists || this.update) ? 'upgrade' : 'install';
130
176
 
131
- // const name = plugin.chart.chartName;
177
+ try {
178
+ const res = await repo.doAction(action, input);
179
+ const operationId = `${ res.operationNamespace }/${ res.operationName }`;
132
180
 
133
- // const res = await this.repo.doAction((isUpgrade ? 'upgrade' : 'install'), input);
134
- const res = await repo.doAction(action, input);
135
- const operationId = `${ res.operationNamespace }/${ res.operationName }`;
181
+ this.closeDialog(plugin);
136
182
 
137
- // Vue.set(this.installing, this.selected.chart.chartName, operationId);
183
+ await repo.waitForOperation(operationId);
138
184
 
139
- this.closeDialog(plugin);
185
+ await this.$store.dispatch(`management/find`, {
186
+ type: CATALOG.OPERATION,
187
+ id: operationId
188
+ });
189
+ } catch (e) {
190
+ this.$store.dispatch('growl/error', {
191
+ title: this.t('plugins.error.generic'),
192
+ message: e.message ? e.message : e,
193
+ timeout: 10000
194
+ }, { root: true });
140
195
 
141
- await repo.waitForOperation(operationId);
142
-
143
- await this.$store.dispatch(`management/find`, {
144
- type: CATALOG.OPERATION,
145
- id: operationId
146
- });
196
+ this.closeDialog(plugin);
197
+ }
147
198
  }
148
199
  }
149
200
  };
@@ -83,7 +83,7 @@ export default {
83
83
  <div class="plugin-info-panel">
84
84
  <div v-if="showSlideIn" class="glass" @click="hide()" />
85
85
  <div class="slideIn" :class="{'hide': false, 'slideIn__show': showSlideIn}">
86
- <div v-if="info">
86
+ <div v-if="info" class="plugin-info-content">
87
87
  <div class="plugin-header">
88
88
  <div class="plugin-icon">
89
89
  <LazyImage
@@ -116,11 +116,12 @@ export default {
116
116
  </div>
117
117
  </div>
118
118
  <div>
119
+ <Banner v-if="info.error" color="error" :label="info.error" class="mt-10" />
119
120
  <Banner v-if="!info.certified" color="warning" :label="t('plugins.descriptions.third-party')" class="mt-10" />
120
121
  <Banner v-if="info.experimental" color="warning" :label="t('plugins.descriptions.experimental')" class="mt-10" />
121
122
  </div>
122
123
 
123
- <h3 v-if="info.versions">
124
+ <h3 v-if="info.versions.length">
124
125
  {{ t('plugins.info.versions') }}
125
126
  </h3>
126
127
  <div class="plugin-versions mb-10">
@@ -138,11 +139,16 @@ export default {
138
139
  <div v-if="versionError">
139
140
  {{ t('plugins.info.versionError') }}
140
141
  </div>
141
- <div v-else>
142
+ <h3 v-if="versionInfo">
143
+ {{ t('plugins.info.detail') }}
144
+ </h3>
145
+ <div v-if="versionInfo" class="plugin-info-detail">
146
+ <ChartReadme v-if="versionInfo" :version-info="versionInfo" />
147
+ </div>
148
+ <div v-if="!info.versions.length">
142
149
  <h3>
143
- {{ t('plugins.info.detail') }}
150
+ {{ t('plugins.version', { version: info.displayVersion }) }}
144
151
  </h3>
145
- <ChartReadme v-if="versionInfo" :version-info="versionInfo" />
146
152
  </div>
147
153
  </div>
148
154
  </div>
@@ -186,6 +192,16 @@ export default {
186
192
 
187
193
  transition: right .5s ease;
188
194
 
195
+ .plugin-info-content {
196
+ display: flex;
197
+ flex-direction: column;
198
+ overflow: hidden;
199
+
200
+ .plugin-info-detail {
201
+ overflow: auto;
202
+ }
203
+ }
204
+
189
205
  h3 {
190
206
  font-size: 14px;
191
207
  margin: 15px 0 10px 0;
@@ -79,14 +79,9 @@ export default {
79
79
 
80
80
  await new Promise(resolve => setTimeout(resolve, 5000));
81
81
 
82
- btnCb(true);
82
+ this.$emit('done');
83
83
 
84
- this.$router.push(
85
- {
86
- path: this.$route.path,
87
- force: true,
88
- },
89
- );
84
+ btnCb(true);
90
85
  },
91
86
  }
92
87
  };
@@ -1,7 +1,7 @@
1
1
  <script>
2
2
  import AsyncButton from '@shell/components/AsyncButton';
3
3
  import IconMessage from '@shell/components/IconMessage.vue';
4
- import { CATALOG, UI_PLUGIN } from '@shell/config/types';
4
+ import { CATALOG, MANAGEMENT } from '@shell/config/types';
5
5
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
6
6
  import Dialog from '@shell/components/Dialog.vue';
7
7
  import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
@@ -47,17 +47,23 @@ export default {
47
47
  }
48
48
  }
49
49
 
50
+ this.defaultRegistrySetting = await this.$store.dispatch('management/find', {
51
+ type: MANAGEMENT.SETTING,
52
+ id: 'system-default-registry'
53
+ });
54
+
50
55
  this.loading = false;
51
56
  },
52
57
 
53
58
  data() {
54
59
  return {
55
- loading: true,
56
- haveCharts: false,
57
- installCharts: [],
58
- errors: [],
59
- addRepo: true,
60
- buttonState: ASYNC_BUTTON_STATES.ACTION,
60
+ loading: true,
61
+ haveCharts: false,
62
+ installCharts: [],
63
+ errors: [],
64
+ addRepo: true,
65
+ buttonState: ASYNC_BUTTON_STATES.ACTION,
66
+ defaultRegistrySetting: null,
61
67
  };
62
68
  },
63
69
 
@@ -88,6 +94,15 @@ export default {
88
94
  values: {}
89
95
  };
90
96
 
97
+ // Pass in the system default registry property if set
98
+ const defaultRegistry = this.defaultRegistrySetting?.value || '';
99
+
100
+ if (defaultRegistry) {
101
+ chart.values.global = chart.values.global || {};
102
+ chart.values.global.cattle = chart.values.global.cattle || {};
103
+ chart.values.global.cattle.systemDefaultRegistry = defaultRegistry;
104
+ }
105
+
91
106
  const input = {
92
107
  charts: [chart],
93
108
  wait: true,
@@ -130,16 +145,9 @@ export default {
130
145
 
131
146
  await new Promise(resolve => setTimeout(resolve, 5000));
132
147
 
133
- this.$store.dispatch('management/forgetType', UI_PLUGIN);
134
-
135
148
  this.buttonState = this.errors.length > 0 ? ASYNC_BUTTON_STATES.ERROR : ASYNC_BUTTON_STATES.ACTION;
136
149
 
137
- this.$router.push(
138
- {
139
- path: this.$route.path,
140
- force: true,
141
- },
142
- );
150
+ this.$emit('done');
143
151
  }
144
152
  },
145
153