@rancher/shell 3.0.4 → 3.0.5-rc.2

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 (270) hide show
  1. package/assets/images/providers/sks.svg +1 -0
  2. package/assets/styles/base/_basic.scss +6 -0
  3. package/assets/styles/base/_helpers.scss +4 -0
  4. package/assets/styles/base/_variables.scss +1 -0
  5. package/assets/styles/global/_button.scss +1 -0
  6. package/assets/translations/en-us.yaml +65 -15
  7. package/assets/translations/zh-hans.yaml +4 -3
  8. package/chart/monitoring/index.vue +3 -1
  9. package/cloud-credential/aws.vue +2 -0
  10. package/components/ActionDropdownShell.vue +71 -0
  11. package/components/AppModal.vue +18 -4
  12. package/components/AsyncButton.vue +24 -7
  13. package/components/BannerGraphic.vue +1 -0
  14. package/components/CommunityLinks.vue +4 -59
  15. package/components/CopyToClipboardText.vue +2 -1
  16. package/components/CruResource.vue +6 -1
  17. package/components/DetailText.vue +5 -0
  18. package/components/ExplorerMembers.vue +1 -1
  19. package/components/ExplorerProjectsNamespaces.vue +68 -18
  20. package/components/GlobalRoleBindings.vue +5 -1
  21. package/components/GrowlManager.vue +1 -0
  22. package/components/LandingPagePreference.vue +7 -3
  23. package/components/LocaleSelector.vue +39 -95
  24. package/components/ModalManager.vue +55 -0
  25. package/components/ModalWithCard.vue +1 -0
  26. package/components/PromptModal.vue +47 -8
  27. package/components/PromptRemove.vue +1 -0
  28. package/components/PromptRestore.vue +1 -0
  29. package/components/ResourceCancelModal.vue +1 -0
  30. package/components/ResourceDetail/Masthead.vue +38 -12
  31. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  32. package/components/ResourceDetail/index.vue +47 -12
  33. package/components/ResourceTable.vue +54 -19
  34. package/components/SideNav.vue +5 -1
  35. package/components/SlideInPanelManager.vue +126 -0
  36. package/components/SortableTable/THead.vue +5 -2
  37. package/components/SortableTable/actions.js +1 -1
  38. package/components/SortableTable/index.vue +64 -51
  39. package/components/SortableTable/paging.js +16 -19
  40. package/components/SortableTable/selection.js +0 -11
  41. package/components/Wizard.vue +2 -2
  42. package/components/__tests__/AsyncButton.test.ts +2 -2
  43. package/components/__tests__/ModalManager.spec.ts +176 -0
  44. package/components/__tests__/PromptModal.test.ts +148 -0
  45. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  46. package/components/auth/AuthBanner.vue +13 -11
  47. package/components/auth/Principal.vue +1 -0
  48. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  49. package/components/auth/login/ldap.vue +1 -1
  50. package/components/fleet/FleetResources.vue +21 -6
  51. package/components/form/ArrayList.vue +76 -60
  52. package/components/form/BannerSettings.vue +17 -2
  53. package/components/form/ColorInput.vue +35 -6
  54. package/components/form/Command.vue +6 -15
  55. package/components/form/EnvVars.vue +16 -8
  56. package/components/form/HealthCheck.vue +3 -3
  57. package/components/form/HookOption.vue +11 -16
  58. package/components/form/LabeledSelect.vue +18 -22
  59. package/components/form/LifecycleHooks.vue +3 -3
  60. package/components/form/MatchExpressions.vue +14 -8
  61. package/components/form/NameNsDescription.vue +128 -104
  62. package/components/form/Networking.vue +20 -12
  63. package/components/form/NodeAffinity.vue +31 -23
  64. package/components/form/NodeScheduling.vue +13 -3
  65. package/components/form/NotificationSettings.vue +15 -1
  66. package/components/form/Password.vue +1 -0
  67. package/components/form/PodAffinity.vue +43 -43
  68. package/components/form/Probe.vue +68 -66
  69. package/components/form/ResourceQuota/Project.vue +5 -1
  70. package/components/form/ResourceSelector.vue +7 -9
  71. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +16 -24
  72. package/components/form/SSHKnownHosts/index.vue +30 -13
  73. package/components/form/Security.vue +54 -56
  74. package/components/form/Select.vue +32 -21
  75. package/components/form/ShellInput.vue +5 -1
  76. package/components/form/Tolerations.vue +5 -1
  77. package/components/form/ValueFromResource.vue +134 -121
  78. package/components/form/WorkloadPorts.vue +18 -18
  79. package/components/form/__tests__/ArrayList.test.ts +5 -2
  80. package/components/form/__tests__/ColorInput.test.ts +35 -0
  81. package/components/form/__tests__/LabeledSelect.test.ts +40 -0
  82. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  83. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  84. package/components/form/__tests__/Probe.test.ts +12 -8
  85. package/components/form/__tests__/SSHKnownHosts.test.ts +22 -2
  86. package/components/form/__tests__/Select.test.ts +37 -0
  87. package/components/formatter/InternalExternalIP.vue +2 -0
  88. package/components/formatter/SecretData.vue +20 -7
  89. package/components/nav/Group.vue +27 -5
  90. package/components/nav/Header.vue +17 -43
  91. package/components/nav/NamespaceFilter.vue +134 -86
  92. package/components/nav/TopLevelMenu.vue +4 -5
  93. package/components/nav/Type.vue +12 -1
  94. package/components/nav/WindowManager/ContainerLogs.vue +87 -61
  95. package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
  96. package/components/templates/blank.vue +4 -1
  97. package/components/templates/default.vue +8 -3
  98. package/components/templates/home.vue +10 -1
  99. package/components/templates/plain.vue +10 -4
  100. package/composables/focusTrap.ts +12 -4
  101. package/composables/useRuntimeFlag.ts +29 -0
  102. package/config/router/routes.js +20 -13
  103. package/config/store.js +4 -0
  104. package/config/uiplugins.js +5 -1
  105. package/core/types.ts +12 -6
  106. package/detail/catalog.cattle.io.app.vue +6 -1
  107. package/detail/fleet.cattle.io.bundle.vue +70 -6
  108. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  109. package/detail/namespace.vue +0 -3
  110. package/detail/node.vue +17 -13
  111. package/detail/provisioning.cattle.io.cluster.vue +72 -6
  112. package/dialog/AddCustomBadgeDialog.vue +1 -1
  113. package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
  114. package/{components/AssignTo.vue → dialog/AssignToDialog.vue} +71 -80
  115. package/dialog/ChangePasswordDialog.vue +106 -0
  116. package/dialog/DeactivateDriverDialog.vue +1 -0
  117. package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
  118. package/dialog/DisableAuthProviderDialog.vue +101 -0
  119. package/dialog/DrainNode.vue +1 -1
  120. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
  121. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
  122. package/dialog/FeatureFlagListDialog.vue +288 -0
  123. package/dialog/ForceMachineRemoveDialog.vue +5 -2
  124. package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
  125. package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
  126. package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -59
  127. package/dialog/MoveNamespaceDialog.vue +157 -0
  128. package/dialog/ScalePoolDownDialog.vue +1 -1
  129. package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
  130. package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
  131. package/dialog/WechatDialog.vue +57 -0
  132. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
  133. package/edit/auth/__tests__/oidc.test.ts +152 -109
  134. package/edit/auth/azuread.vue +2 -1
  135. package/edit/auth/github.vue +1 -1
  136. package/edit/auth/googleoauth.vue +5 -1
  137. package/edit/auth/ldap/index.vue +1 -1
  138. package/edit/auth/oidc.vue +38 -5
  139. package/edit/auth/saml.vue +1 -1
  140. package/edit/cloudcredential.vue +24 -9
  141. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
  142. package/edit/management.cattle.io.user.vue +28 -3
  143. package/edit/namespace.vue +1 -4
  144. package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
  145. package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
  146. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
  147. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
  148. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -9
  149. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
  150. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
  151. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
  152. package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
  153. package/edit/provisioning.cattle.io.cluster/rke2.vue +49 -41
  154. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
  155. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
  156. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +33 -2
  157. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
  158. package/edit/token.vue +2 -0
  159. package/edit/workload/index.vue +1 -0
  160. package/edit/workload/mixins/workload.js +0 -2
  161. package/initialize/install-plugins.js +2 -1
  162. package/list/harvesterhci.io.management.cluster.vue +4 -1
  163. package/list/management.cattle.io.feature.vue +4 -287
  164. package/list/provisioning.cattle.io.cluster.vue +20 -12
  165. package/machine-config/azure.vue +16 -4
  166. package/mixins/vue-select-overrides.js +0 -4
  167. package/models/__tests__/namespace.test.ts +25 -1
  168. package/models/cloudcredential.js +5 -0
  169. package/models/fleet.cattle.io.cluster.js +8 -2
  170. package/models/fleet.cattle.io.gitrepo.js +8 -34
  171. package/models/kontainerdriver.js +6 -3
  172. package/models/management.cattle.io.feature.js +7 -1
  173. package/models/management.cattle.io.node.js +3 -3
  174. package/models/namespace.js +11 -6
  175. package/models/nodedriver.js +6 -3
  176. package/models/workload.js +4 -1
  177. package/package.json +3 -3
  178. package/pages/about.vue +13 -3
  179. package/pages/account/index.vue +16 -6
  180. package/pages/auth/login.vue +18 -7
  181. package/pages/auth/logout.vue +4 -1
  182. package/pages/auth/setup.vue +2 -0
  183. package/pages/auth/verify.vue +13 -8
  184. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  185. package/pages/c/_cluster/apps/charts/install.vue +26 -26
  186. package/pages/c/_cluster/auth/config/index.vue +10 -12
  187. package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
  188. package/pages/c/_cluster/explorer/index.vue +17 -15
  189. package/pages/c/_cluster/istio/index.vue +2 -2
  190. package/pages/c/_cluster/longhorn/index.vue +1 -1
  191. package/pages/c/_cluster/monitoring/index.vue +1 -1
  192. package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
  193. package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
  194. package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
  195. package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
  196. package/pages/c/_cluster/neuvector/index.vue +1 -1
  197. package/pages/c/_cluster/settings/banners.vue +4 -3
  198. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
  199. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +98 -55
  201. package/pages/diagnostic.vue +59 -11
  202. package/pages/fail-whale.vue +14 -8
  203. package/pages/home.vue +24 -18
  204. package/pages/prefs.vue +7 -6
  205. package/pages/support/index.vue +4 -1
  206. package/plugins/internal-api/index.ts +37 -0
  207. package/plugins/internal-api/shared/base-api.ts +13 -0
  208. package/plugins/internal-api/shell/shell.api.ts +108 -0
  209. package/plugins/steve/actions.js +0 -12
  210. package/public/index.html +1 -0
  211. package/rancher-components/Card/Card.vue +1 -1
  212. package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
  213. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
  214. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
  215. package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
  216. package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
  217. package/rancher-components/Form/Radio/RadioButton.vue +20 -4
  218. package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
  219. package/rancher-components/Form/Radio/RadioGroup.vue +52 -10
  220. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
  221. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
  222. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
  223. package/rancher-components/RcButton/RcButton.vue +2 -1
  224. package/rancher-components/RcButton/types.ts +1 -0
  225. package/rancher-components/RcDropdown/RcDropdown.vue +18 -6
  226. package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
  227. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
  228. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
  229. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
  230. package/rancher-components/RcDropdown/index.ts +2 -0
  231. package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
  232. package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
  233. package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
  234. package/scripts/extension/bundle +20 -0
  235. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
  236. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  237. package/scripts/extension/helmpatch +44 -31
  238. package/scripts/extension/publish +12 -12
  239. package/scripts/typegen.sh +2 -4
  240. package/server/har-file.js +25 -3
  241. package/store/action-menu.js +26 -56
  242. package/store/features.js +2 -1
  243. package/store/index.js +5 -0
  244. package/store/modal.ts +71 -0
  245. package/store/slideInPanel.ts +47 -0
  246. package/store/type-map.js +12 -1
  247. package/store/type-map.utils.ts +4 -4
  248. package/types/global-vue.d.ts +5 -0
  249. package/types/internal-api/shell/growl.d.ts +25 -0
  250. package/types/internal-api/shell/modal.d.ts +77 -0
  251. package/types/internal-api/shell/slideIn.d.ts +15 -0
  252. package/types/resources/fleet.d.ts +0 -14
  253. package/types/shell/index.d.ts +43 -24
  254. package/types/vue-shim.d.ts +4 -1
  255. package/utils/__mocks__/tabbable.js +13 -0
  256. package/utils/__tests__/object.test.ts +38 -4
  257. package/utils/cluster.js +35 -0
  258. package/utils/fleet.ts +15 -73
  259. package/utils/object.js +48 -5
  260. package/utils/validators/formRules/__tests__/index.test.ts +10 -1
  261. package/utils/validators/formRules/index.ts +27 -3
  262. package/utils/validators/machine-pool.ts +20 -0
  263. package/components/DisableAuthProviderModal.vue +0 -114
  264. package/components/MoveModal.vue +0 -166
  265. package/components/PromptChangePassword.vue +0 -123
  266. package/components/fleet/FleetBundleResources.vue +0 -86
  267. package/components/formatter/ExtensionCache.vue +0 -74
  268. package/components/formatter/Port.vue +0 -24
  269. package/components/formatter/SecretType.vue +0 -41
  270. package/types/vue-shim.d +0 -20
@@ -10,7 +10,6 @@ import { allHash } from '@shell/utils/promise';
10
10
  import ResourceManager from '@shell/mixins/resource-manager';
11
11
 
12
12
  import AsyncButton from '@shell/components/AsyncButton';
13
- import AppModal from '@shell/components/AppModal';
14
13
  import LabeledSelect from '@shell/components/form/LabeledSelect';
15
14
  import Loading from '@shell/components/Loading.vue';
16
15
  import { Banner } from '@components/Banner';
@@ -98,14 +97,41 @@ const initialState = () => {
98
97
  };
99
98
 
100
99
  export default {
101
- emits: ['closed', 'refresh'],
100
+ emits: ['close'],
102
101
 
103
102
  components: {
104
- AsyncButton, Banner, LabeledInput, Loading, LabeledSelect, AppModal,
103
+ AsyncButton, Banner, LabeledInput, Loading, LabeledSelect
105
104
  },
106
105
 
107
106
  mixins: [ResourceManager],
108
107
 
108
+ props: {
109
+ /**
110
+ * Callback to trigger refresh banner on extensions screen
111
+ */
112
+ refresh: {
113
+ type: Function,
114
+ default: () => {},
115
+ required: true
116
+ },
117
+ /**
118
+ * Callback when modal is closed
119
+ */
120
+ closed: {
121
+ type: Function,
122
+ default: () => {},
123
+ required: true
124
+ },
125
+ resources: {
126
+ type: Array,
127
+ default: () => []
128
+ },
129
+ registerBackgroundClosing: {
130
+ type: Function,
131
+ default: () => {}
132
+ }
133
+ },
134
+
109
135
  async fetch() {
110
136
  const hash = {};
111
137
 
@@ -126,9 +152,7 @@ export default {
126
152
  data() {
127
153
  return {
128
154
  ...initialState(),
129
- secondaryResourceData: null,
130
- showModal: false,
131
- returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]'
155
+ secondaryResourceData: null
132
156
  };
133
157
  },
134
158
 
@@ -163,18 +187,15 @@ export default {
163
187
  };
164
188
  },
165
189
 
166
- showDialog() {
167
- this.showModal = true;
168
- },
169
-
170
190
  closeDialog(result) {
171
- this.showModal = false;
172
- this.$emit('closed', result);
191
+ this.closed(result);
173
192
 
174
193
  // Reset state
175
194
  Object.assign(this.$data, initialState());
176
195
  this.secondaryResourceData = this.secondaryResourceDataConfig();
177
196
  this.resourceManagerFetchSecondaryResources(this.secondaryResourceData);
197
+
198
+ this.$emit('close');
178
199
  },
179
200
 
180
201
  async loadImage(btnCb) {
@@ -205,7 +226,8 @@ export default {
205
226
  message: this.t('plugins.manageCatalog.imageLoad.success.message'),
206
227
  timeout: 4000,
207
228
  }, { root: true });
208
- this.$emit('refresh');
229
+
230
+ this.refresh();
209
231
  }
210
232
  } else {
211
233
  throw new Error('Unable to determine image name');
@@ -430,90 +452,80 @@ export default {
430
452
  </script>
431
453
 
432
454
  <template>
433
- <app-modal
434
- v-if="showModal"
435
- name="catalogLoadDialog"
436
- height="auto"
437
- :scrollable="true"
438
- :trigger-focus-trap="true"
439
- :return-focus-selector="returnFocusSelector"
440
- @close="closeDialog()"
455
+ <Loading
456
+ v-if="$fetchState.loading"
457
+ mode="relative"
458
+ />
459
+ <div
460
+ v-else
461
+ class="plugin-install-dialog"
441
462
  >
442
- <Loading
443
- v-if="$fetchState.loading"
444
- mode="relative"
445
- />
446
- <div
447
- v-else
448
- class="plugin-install-dialog"
449
- >
450
- <div>
451
- <h4>
452
- {{ t('plugins.manageCatalog.imageLoad.load') }}
453
- </h4>
454
- <p>
455
- {{ t('plugins.manageCatalog.imageLoad.prompt') }}
456
- </p>
457
-
458
- <div class="custom mt-10">
459
- <Banner
460
- color="info"
461
- :label="t('plugins.manageCatalog.imageLoad.banner')"
462
- class="mt-10"
463
- />
464
- </div>
463
+ <div>
464
+ <h4>
465
+ {{ t('plugins.manageCatalog.imageLoad.load') }}
466
+ </h4>
467
+ <p>
468
+ {{ t('plugins.manageCatalog.imageLoad.prompt') }}
469
+ </p>
465
470
 
466
- <div class="custom mt-10">
467
- <div class="fields">
468
- <LabeledInput
469
- v-model:value.trim="deploymentValues.spec.template.spec.containers[0].image"
470
- label-key="plugins.manageCatalog.imageLoad.fields.image.label"
471
- placeholder-key="plugins.manageCatalog.imageLoad.fields.image.placeholder"
472
- />
473
- </div>
474
- </div>
475
- <div class="custom mt-10">
476
- <div class="fields">
477
- <LabeledSelect
478
- v-model:value="imagePullSecrets"
479
- :label="t('plugins.manageCatalog.imageLoad.fields.imagePullSecrets.label')"
480
- :tooltip="t('plugins.manageCatalog.imageLoad.fields.imagePullSecrets.tooltip')"
481
- :multiple="true"
482
- :taggable="true"
483
- :options="imagePullNamespacedSecrets"
484
- option-label="metadata.name"
485
- :reduce="service => service.metadata.name"
486
- />
487
- <Banner
488
- color="warning"
489
- class="mt-10"
490
- >
491
- <span v-clean-html="t('plugins.manageCatalog.imageLoad.fields.secrets.banner', {}, true)" />
492
- </Banner>
493
- </div>
494
- </div>
471
+ <div class="custom mt-10">
472
+ <Banner
473
+ color="info"
474
+ :label="t('plugins.manageCatalog.imageLoad.banner')"
475
+ class="mt-10"
476
+ />
495
477
  </div>
496
478
 
497
479
  <div class="custom mt-10">
498
480
  <div class="fields">
499
- <div class="dialog-buttons mt-20">
500
- <button
501
- class="btn role-secondary"
502
- data-testid="image-load-ext-modal-cancel-btn"
503
- @click="closeDialog()"
504
- >
505
- {{ t('generic.cancel') }}
506
- </button>
507
- <AsyncButton
508
- mode="load"
509
- data-testid="image-load-ext-modal-install-btn"
510
- @click="loadImage"
511
- />
512
- </div>
481
+ <LabeledInput
482
+ v-model:value.trim="deploymentValues.spec.template.spec.containers[0].image"
483
+ label-key="plugins.manageCatalog.imageLoad.fields.image.label"
484
+ placeholder-key="plugins.manageCatalog.imageLoad.fields.image.placeholder"
485
+ />
486
+ </div>
487
+ </div>
488
+ <div class="custom mt-10">
489
+ <div class="fields">
490
+ <LabeledSelect
491
+ v-model:value="imagePullSecrets"
492
+ :label="t('plugins.manageCatalog.imageLoad.fields.imagePullSecrets.label')"
493
+ :tooltip="t('plugins.manageCatalog.imageLoad.fields.imagePullSecrets.tooltip')"
494
+ :multiple="true"
495
+ :taggable="true"
496
+ :options="imagePullNamespacedSecrets"
497
+ option-label="metadata.name"
498
+ :reduce="service => service.metadata.name"
499
+ />
500
+ <Banner
501
+ color="warning"
502
+ class="mt-10"
503
+ >
504
+ <span v-clean-html="t('plugins.manageCatalog.imageLoad.fields.secrets.banner', {}, true)" />
505
+ </Banner>
506
+ </div>
507
+ </div>
508
+ </div>
509
+
510
+ <div class="custom mt-10">
511
+ <div class="fields">
512
+ <div class="dialog-buttons mt-20">
513
+ <button
514
+ class="btn role-secondary"
515
+ data-testid="image-load-ext-modal-cancel-btn"
516
+ @click="closeDialog()"
517
+ >
518
+ {{ t('generic.cancel') }}
519
+ </button>
520
+ <AsyncButton
521
+ mode="load"
522
+ data-testid="image-load-ext-modal-install-btn"
523
+ @click="loadImage"
524
+ />
513
525
  </div>
514
526
  </div>
515
527
  </div>
516
- </app-modal>
528
+ </div>
517
529
  </template>
518
530
 
519
531
  <style lang="scss" scoped>
@@ -6,12 +6,46 @@ import { UI_PLUGIN_LABELS, UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
6
6
  import { allHash } from '@shell/utils/promise';
7
7
 
8
8
  import AsyncButton from '@shell/components/AsyncButton';
9
- import AppModal from '@shell/components/AppModal.vue';
10
9
 
11
10
  export default {
12
- emits: ['closed', 'refresh', 'update'],
13
-
14
- components: { AsyncButton, AppModal },
11
+ emits: ['close'],
12
+
13
+ components: { AsyncButton },
14
+
15
+ props: {
16
+ /**
17
+ * Catalog object
18
+ */
19
+ catalog: {
20
+ type: Object,
21
+ default: () => {},
22
+ required: true
23
+ },
24
+ /**
25
+ * Callback to trigger refresh banner on extensions screen
26
+ */
27
+ refresh: {
28
+ type: Function,
29
+ default: () => {},
30
+ required: true
31
+ },
32
+ /**
33
+ * Callback when modal is closed
34
+ */
35
+ closed: {
36
+ type: Function,
37
+ default: () => {},
38
+ required: true
39
+ },
40
+ resources: {
41
+ type: Array,
42
+ default: () => []
43
+ },
44
+ registerBackgroundClosing: {
45
+ type: Function,
46
+ default: () => {}
47
+ }
48
+ },
15
49
 
16
50
  async fetch() {
17
51
  if ( this.$store.getters['management/schemaFor'](UI_PLUGIN) ) {
@@ -23,11 +57,8 @@ export default {
23
57
 
24
58
  data() {
25
59
  return {
26
- catalog: undefined,
27
- busy: false,
28
- plugins: null,
29
- showModal: false,
30
- returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]'
60
+ busy: false,
61
+ plugins: null,
31
62
  };
32
63
  },
33
64
 
@@ -40,19 +71,14 @@ export default {
40
71
  },
41
72
 
42
73
  methods: {
43
- showDialog(catalog) {
44
- this.catalog = catalog;
45
- this.busy = false;
46
- this.showModal = true;
47
- },
48
-
49
74
  closeDialog(result) {
50
- this.showModal = false;
51
- this.$emit('closed', result);
75
+ this.closed(result);
52
76
 
53
77
  if ( result ) {
54
- this.$emit('refresh');
78
+ this.refresh();
55
79
  }
80
+
81
+ this.$emit('close');
56
82
  },
57
83
 
58
84
  async uninstall() {
@@ -76,7 +102,6 @@ export default {
76
102
  if ( pluginApps.length ) {
77
103
  try {
78
104
  pluginApps.forEach((app) => {
79
- this.$emit('update', app.name, 'uninstall');
80
105
  app.remove();
81
106
  });
82
107
  } catch (e) {
@@ -120,46 +145,33 @@ export default {
120
145
  </script>
121
146
 
122
147
  <template>
123
- <app-modal
124
- v-if="showModal"
125
- name="uninstallCatalogDialog"
126
- height="auto"
127
- :scrollable="true"
128
- :trigger-focus-trap="true"
129
- :return-focus-selector="returnFocusSelector"
130
- @close="closeDialog(false)"
131
- >
132
- <div
133
- v-if="catalog"
134
- class="plugin-install-dialog"
135
- >
136
- <h4 class="mt-10">
137
- {{ t('plugins.uninstall.title', { name: catalog.name }) }}
138
- </h4>
139
- <div class="mt-10 dialog-panel">
140
- <div class="dialog-info">
141
- <p>
142
- {{ t('plugins.uninstall.catalog') }}
143
- </p>
144
- </div>
145
- <div class="dialog-buttons">
146
- <button
147
- :disabled="busy"
148
- class="btn role-secondary"
149
- data-testid="uninstall-ext-modal-cancel-btn"
150
- @click="closeDialog(false)"
151
- >
152
- {{ t('generic.cancel') }}
153
- </button>
154
- <AsyncButton
155
- mode="uninstall"
156
- data-testid="uninstall-ext-modal-uninstall-btn"
157
- @click="uninstall()"
158
- />
159
- </div>
148
+ <div class="plugin-install-dialog">
149
+ <h4 class="mt-10">
150
+ {{ t('plugins.uninstall.title', { name: catalog.name }) }}
151
+ </h4>
152
+ <div class="mt-10 dialog-panel">
153
+ <div class="dialog-info">
154
+ <p>
155
+ {{ t('plugins.uninstall.catalog') }}
156
+ </p>
157
+ </div>
158
+ <div class="dialog-buttons">
159
+ <button
160
+ :disabled="busy"
161
+ class="btn role-secondary"
162
+ data-testid="uninstall-ext-modal-cancel-btn"
163
+ @click="closeDialog(false)"
164
+ >
165
+ {{ t('generic.cancel') }}
166
+ </button>
167
+ <AsyncButton
168
+ mode="uninstall"
169
+ data-testid="uninstall-ext-modal-uninstall-btn"
170
+ @click="uninstall()"
171
+ />
160
172
  </div>
161
173
  </div>
162
- </app-modal>
174
+ </div>
163
175
  </template>
164
176
 
165
177
  <style lang="scss" scoped>
@@ -0,0 +1,288 @@
1
+
2
+ <script>
3
+ import { mapGetters } from 'vuex';
4
+
5
+ import { Card } from '@components/Card';
6
+ import { Banner } from '@components/Banner';
7
+ import { LabeledInput } from '@components/Form/LabeledInput';
8
+ import AsyncButton from '@shell/components/AsyncButton';
9
+
10
+ import { MANAGEMENT } from '@shell/config/types';
11
+ import { SETTING } from '@shell/config/settings';
12
+ import { getVendor } from '@shell/config/private-label';
13
+
14
+ export default {
15
+ name: 'FeatureFlagListDialog',
16
+
17
+ emits: ['close'],
18
+
19
+ components: {
20
+ Card, Banner, LabeledInput, AsyncButton
21
+ },
22
+
23
+ props: {
24
+ resources: {
25
+ type: Array,
26
+ default: () => []
27
+ },
28
+ registerBackgroundClosing: {
29
+ type: Function,
30
+ default: () => {}
31
+ }
32
+ },
33
+
34
+ async fetch() {
35
+ // Only support updating one at a time - bulk does not make sense, as they may
36
+ // be in different states and with different restart values
37
+ this.update = this.resources[0];
38
+
39
+ if (this.update) {
40
+ this.restart = this.update.restartRequired;
41
+ // If the value is currently false, then we will be enabling it
42
+ this.enabling = !this.update.enabled;
43
+ this.updateMode = this.enabling ? 'activate' : 'deactivate';
44
+ }
45
+
46
+ this.serverUrlSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SERVER_URL);
47
+
48
+ if (this.serverUrlSetting?.value) {
49
+ this.serverUrl = this.serverUrlSetting.value;
50
+ } else {
51
+ this.noUrlSet = true;
52
+ this.serverUrl = window.location.origin;
53
+ }
54
+ },
55
+
56
+ data() {
57
+ return {
58
+ update: [],
59
+ updateMode: 'activate',
60
+ error: null,
61
+ enabling: false,
62
+ restart: false,
63
+ waiting: false,
64
+ timer: null,
65
+ serverUrlSetting: {},
66
+ serverUrl: '',
67
+ noUrlSet: false,
68
+ vendor: getVendor(),
69
+ };
70
+ },
71
+
72
+ computed: {
73
+ ...mapGetters({ t: 'i18n/t' }),
74
+
75
+ promptForUrl() {
76
+ return this.update?.id === 'multi-cluster-management' && this.noUrlSet;
77
+ }
78
+ },
79
+
80
+ methods: {
81
+ close() {
82
+ if (this.timer) {
83
+ clearTimeout(this.timer);
84
+ this.timer = null;
85
+ }
86
+
87
+ this.$emit('close');
88
+ },
89
+
90
+ toggleFlag(btnCB) {
91
+ if (this.restart) {
92
+ this.doToggleWithRestart(btnCB);
93
+ } else {
94
+ this.doToggle(btnCB);
95
+ }
96
+ },
97
+
98
+ async doToggle(btnCB) {
99
+ this.error = null;
100
+ try {
101
+ this.update.spec.value = !this.update.enabled;
102
+ await this.update.save();
103
+ btnCB(true);
104
+ this.close();
105
+ } catch (err) {
106
+ // An error occurred, so toggle back the value - the call failed, so the change was not made
107
+ this.update.spec.value = !this.update.enabled;
108
+ this.error = err.message || err;
109
+ btnCB(false);
110
+ }
111
+ },
112
+
113
+ doToggleWithRestart(btnCB) {
114
+ this.error = null;
115
+ try {
116
+ this.update.spec.value = !this.update.enabled;
117
+ // await can go back in when backend returns from the save before restarting
118
+ this.update.save();
119
+ } catch (err) {}
120
+
121
+ this.waitForBackend(btnCB, this.update.id);
122
+ this.waiting = true;
123
+ },
124
+
125
+ waitForBackend(btnCB, id) {
126
+ const url = `/v3/features/${ id }`;
127
+
128
+ this.timer = setTimeout(async() => {
129
+ try {
130
+ const response = await this.$axios.get(url, { timeout: 5000 });
131
+
132
+ if (response?.status === 200) {
133
+ btnCB(true);
134
+ this.waiting = false;
135
+ this.close();
136
+
137
+ await this.$store.dispatch('management/findAll', { type: this.resource, opt: { force: true } });
138
+ }
139
+ } catch (e) {}
140
+
141
+ if (this.waiting) {
142
+ this.waitForBackend(btnCB, id);
143
+ }
144
+ }, 5000);
145
+ },
146
+
147
+ async saveUrl(btnCB) {
148
+ try {
149
+ this.serverUrlSetting.value = this.serverUrl;
150
+ await this.serverUrlSetting.save();
151
+ btnCB(true);
152
+ } catch (err) {
153
+ this.error = err;
154
+ btnCB(false);
155
+ }
156
+ },
157
+ }
158
+ };
159
+ </script>
160
+
161
+ <template>
162
+ <Card
163
+ v-if="!waiting"
164
+ class="prompt-update"
165
+ :show-highlight-border="false"
166
+ >
167
+ <template #title>
168
+ <h4 class="text-default-text">
169
+ {{ t('featureFlags.title') }}
170
+ </h4>
171
+ </template>
172
+ <template #body>
173
+ <div
174
+ v-if="update"
175
+ class="mb-10"
176
+ >
177
+ <div v-if="enabling">
178
+ <span>
179
+ {{ t('featureFlags.promptActivate', {flag: update.id}) }}
180
+ </span>
181
+ <div
182
+ v-if="promptForUrl"
183
+ class="mt-10"
184
+ >
185
+ <span> {{ t('featureFlags.requiresSetting') }}</span>
186
+ <div
187
+ :style="{'align-items':'center'}"
188
+ class="row mt-10"
189
+ >
190
+ <LabeledInput
191
+ v-model:value="serverUrl"
192
+ :label="t('setup.serverUrl.label')"
193
+ />
194
+ <div class="col pl-5">
195
+ <AsyncButton @click="saveUrl" />
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ <span v-else>
201
+ {{ t('featureFlags.promptDeactivate', {flag: update.id}) }}
202
+ </span>
203
+ <Banner
204
+ v-if="restart"
205
+ color="error"
206
+ :label="t('featureFlags.restartRequired', vendor)"
207
+ />
208
+ </div>
209
+ <div class="text-error mb-10">
210
+ {{ error }}
211
+ </div>
212
+ </template>
213
+ <template #actions>
214
+ <button
215
+ class="btn role-secondary"
216
+ @click="close"
217
+ >
218
+ {{ t('generic.cancel') }}
219
+ </button>
220
+ <AsyncButton
221
+ :disabled="promptForUrl && !serverUrlSetting.value"
222
+ :mode="updateMode"
223
+ class="btn bg-error ml-10"
224
+ @click="toggleFlag"
225
+ />
226
+ </template>
227
+ </Card>
228
+ <Card
229
+ v-else
230
+ class="prompt-update"
231
+ :show-highlight-border="false"
232
+ >
233
+ <template #title>
234
+ <h4 class="text-default-text">
235
+ {{ t('featureFlags.restart.title') }}
236
+ </h4>
237
+ </template>
238
+ <template #body>
239
+ <div class="waiting">
240
+ <p>{{ t('featureFlags.restart.wait') }}</p>
241
+ <span class="restarting-icon">
242
+ <i class=" icon icon-spinner icon-spin" />
243
+ </span>
244
+ </div>
245
+ </template>
246
+ <template #actions>
247
+ <button
248
+ class="btn role-secondary"
249
+ @click="close"
250
+ >
251
+ {{ t('generic.cancel') }}
252
+ </button>
253
+ </template>
254
+ </Card>
255
+ </template>
256
+
257
+ <style lang="scss" scoped>
258
+ .prompt-update {
259
+ &.card-container {
260
+ box-shadow: none;
261
+ }
262
+
263
+ :deep() .card-actions {
264
+ display: flex;
265
+ justify-content: center;
266
+ }
267
+
268
+ .waiting {
269
+ text-align: center;
270
+ font-size: 14px;
271
+ margin: 10px 0;
272
+
273
+ p {
274
+ line-height: 20px;;
275
+ }
276
+ }
277
+
278
+ .restarting-icon {
279
+ display: flex;
280
+ justify-content: center;
281
+ margin-top: 10px;
282
+
283
+ > I {
284
+ font-size: 24px;
285
+ }
286
+ }
287
+ }
288
+ </style>