katello 4.9.1 → 4.10.0.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -7
  3. data/app/assets/javascripts/katello/locale/bn/katello.js +8967 -1
  4. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +8967 -0
  5. data/app/assets/javascripts/katello/locale/ca/katello.js +8967 -0
  6. data/app/assets/javascripts/katello/locale/cs/katello.js +8967 -1
  7. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +8969 -0
  8. data/app/assets/javascripts/katello/locale/de/katello.js +8991 -1
  9. data/app/assets/javascripts/katello/locale/de_AT/katello.js +8966 -0
  10. data/app/assets/javascripts/katello/locale/de_DE/katello.js +8967 -0
  11. data/app/assets/javascripts/katello/locale/el/katello.js +8967 -0
  12. data/app/assets/javascripts/katello/locale/en/katello.js +8967 -1
  13. data/app/assets/javascripts/katello/locale/en_GB/katello.js +8967 -0
  14. data/app/assets/javascripts/katello/locale/en_US/katello.js +8966 -0
  15. data/app/assets/javascripts/katello/locale/es/katello.js +8984 -1
  16. data/app/assets/javascripts/katello/locale/et_EE/katello.js +8966 -0
  17. data/app/assets/javascripts/katello/locale/fr/katello.js +9008 -1
  18. data/app/assets/javascripts/katello/locale/gl/katello.js +8967 -0
  19. data/app/assets/javascripts/katello/locale/gu/katello.js +8967 -1
  20. data/app/assets/javascripts/katello/locale/he_IL/katello.js +8967 -0
  21. data/app/assets/javascripts/katello/locale/hi/katello.js +8967 -1
  22. data/app/assets/javascripts/katello/locale/id/katello.js +8966 -0
  23. data/app/assets/javascripts/katello/locale/it/katello.js +8974 -1
  24. data/app/assets/javascripts/katello/locale/ja/katello.js +9004 -1
  25. data/app/assets/javascripts/katello/locale/ka/katello.js +8976 -1
  26. data/app/assets/javascripts/katello/locale/kn/katello.js +8967 -1
  27. data/app/assets/javascripts/katello/locale/ko/katello.js +8972 -1
  28. data/app/assets/javascripts/katello/locale/locale/katello.js +3070 -1
  29. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +8966 -0
  30. data/app/assets/javascripts/katello/locale/mr/katello.js +8967 -1
  31. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +8967 -0
  32. data/app/assets/javascripts/katello/locale/or/katello.js +8967 -1
  33. data/app/assets/javascripts/katello/locale/pa/katello.js +8967 -1
  34. data/app/assets/javascripts/katello/locale/pl/katello.js +8967 -0
  35. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +8966 -0
  36. data/app/assets/javascripts/katello/locale/pt/katello.js +8967 -1
  37. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +8984 -1
  38. data/app/assets/javascripts/katello/locale/ro/katello.js +8966 -0
  39. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +8966 -0
  40. data/app/assets/javascripts/katello/locale/ru/katello.js +8973 -1
  41. data/app/assets/javascripts/katello/locale/sl/katello.js +8967 -0
  42. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +8967 -0
  43. data/app/assets/javascripts/katello/locale/ta/katello.js +8967 -1
  44. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +8967 -0
  45. data/app/assets/javascripts/katello/locale/te/katello.js +8967 -1
  46. data/app/assets/javascripts/katello/locale/tr/katello.js +8967 -0
  47. data/app/assets/javascripts/katello/locale/vi/katello.js +8966 -0
  48. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +8966 -0
  49. data/app/assets/javascripts/katello/locale/zh/katello.js +8966 -0
  50. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +9004 -1
  51. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +8972 -1
  52. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
  53. data/app/controllers/katello/api/v2/alternate_content_sources_bulk_actions_controller.rb +22 -1
  54. data/app/controllers/katello/api/v2/api_controller.rb +0 -15
  55. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +13 -4
  56. data/app/controllers/katello/api/v2/host_errata_controller.rb +0 -12
  57. data/app/controllers/katello/api/v2/host_packages_controller.rb +0 -55
  58. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +1 -1
  59. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +0 -77
  60. data/app/controllers/katello/api/v2/organizations_controller.rb +2 -1
  61. data/app/controllers/katello/api/v2/products_controller.rb +4 -4
  62. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +12 -5
  63. data/app/controllers/katello/api/v2/repositories_controller.rb +16 -17
  64. data/app/controllers/katello/api/v2/sync_controller.rb +0 -1
  65. data/app/controllers/katello/concerns/api/api_controller.rb +0 -10
  66. data/app/controllers/katello/concerns/content_facet_hosts_controller_extensions.rb +7 -9
  67. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +1 -1
  68. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +14 -2
  69. data/app/lib/actions/katello/alternate_content_source/update.rb +1 -1
  70. data/app/lib/actions/katello/content_view/capsule_sync.rb +1 -1
  71. data/app/lib/actions/katello/content_view/incremental_updates.rb +3 -9
  72. data/app/lib/actions/katello/content_view_environment/destroy.rb +5 -3
  73. data/app/lib/actions/katello/content_view_version/destroy.rb +5 -1
  74. data/app/lib/actions/katello/content_view_version/republish_repositories.rb +8 -2
  75. data/app/lib/actions/katello/host/update_content_view.rb +4 -2
  76. data/app/lib/actions/katello/product/destroy.rb +15 -11
  77. data/app/lib/actions/katello/repository/capsule_sync.rb +1 -1
  78. data/app/lib/actions/katello/repository/destroy.rb +10 -2
  79. data/app/lib/actions/katello/repository/index_content.rb +0 -1
  80. data/app/lib/actions/katello/repository/sync.rb +1 -3
  81. data/app/lib/actions/katello/repository/update_metadata_sync.rb +1 -1
  82. data/app/lib/actions/katello/repository/verify_checksum.rb +2 -10
  83. data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +12 -5
  84. data/app/lib/katello/concerns/base_template_scope_extensions.rb +4 -9
  85. data/app/lib/katello/resources/cdn.rb +4 -0
  86. data/app/lib/katello/validators/alternate_content_source_products_validator.rb +1 -1
  87. data/app/models/katello/candlepin/repository_mapper.rb +1 -0
  88. data/app/models/katello/cdn_configuration.rb +4 -0
  89. data/app/models/katello/concerns/host_managed_extensions.rb +57 -4
  90. data/app/models/katello/content_view.rb +21 -3
  91. data/app/models/katello/content_view_component.rb +1 -1
  92. data/app/models/katello/content_view_version.rb +4 -0
  93. data/app/models/katello/docker_meta_tag.rb +3 -1
  94. data/app/models/katello/host/content_facet.rb +10 -8
  95. data/app/models/katello/kt_environment.rb +1 -1
  96. data/app/models/katello/ping.rb +1 -12
  97. data/app/models/katello/product_content.rb +14 -1
  98. data/app/models/katello/repository.rb +6 -1
  99. data/app/models/katello/root_repository.rb +2 -8
  100. data/app/services/katello/applicability/applicable_content_helper.rb +2 -2
  101. data/app/services/katello/registration_manager.rb +2 -12
  102. data/app/views/foreman/job_templates/configure_host_for_new_content_source.erb +25 -0
  103. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +1 -1
  104. data/app/views/katello/api/v2/content_facet/show.json.rabl +0 -12
  105. data/app/views/katello/api/v2/content_view_components/show.json.rabl +4 -1
  106. data/app/views/katello/api/v2/content_views/base.json.rabl +6 -2
  107. data/app/views/katello/api/v2/products/show.json.rabl +3 -0
  108. data/app/views/katello/api/v2/repositories/base.json.rabl +18 -0
  109. data/app/views/katello/api/v2/repositories/show.json.rabl +0 -1
  110. data/app/views/katello/api/v2/repository_sets/show.json.rabl +2 -2
  111. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +4 -5
  112. data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +11 -3
  113. data/app/views/overrides/activation_keys/_host_synced_content_select.html.erb +15 -7
  114. data/config/initializers/monkeys.rb +1 -0
  115. data/config/katello.yaml.example +0 -4
  116. data/config/routes/api/v2.rb +3 -0
  117. data/config/routes/overrides.rb +0 -11
  118. data/db/migrate/20220228173251_remove_drpm_from_ignorable_content.rb +1 -0
  119. data/db/migrate/20230609155411_add_custom_cdn_auth_enabled_to_katello_cdn_configurations.rb +5 -0
  120. data/db/migrate/20230710190626_remove_relative_path_limit.rb +5 -0
  121. data/db/migrate/20230717150442_change_change_content_source_job_template_name.rb +20 -0
  122. data/db/migrate/20230828143236_remove_katello_agent_dispatch_history.rb +15 -0
  123. data/db/seeds.d/111-upgrade_tasks.rb +1 -2
  124. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -1
  125. data/engines/bastion_katello/README.md +2 -1
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/activation-keys.controller.js +4 -2
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-associations-content-hosts.html +2 -2
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/views/activation-keys.html +8 -3
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +3 -44
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-module-streams-modal.controller.js +0 -1
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-packages-modal.controller.js +1 -65
  132. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +1 -3
  133. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-packages-modal.html +1 -6
  134. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-applicable.controller.js +1 -1
  135. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-errata.controller.js +1 -16
  136. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +0 -1
  137. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-actions.controller.js +0 -1
  138. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-applicable.controller.js +2 -11
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +0 -2
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages.controller.js +1 -39
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-applicable.html +2 -2
  142. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-errata.html +1 -4
  143. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-actions.html +2 -4
  144. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-applicable.html +4 -6
  145. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-installed.html +1 -3
  146. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +0 -14
  147. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +1 -2
  148. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/file-content-views.controller.js +2 -1
  149. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/views/file-content-views.html +1 -1
  150. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +235 -521
  151. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/product-details.controller.js +2 -0
  152. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +17 -4
  153. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +55 -6
  154. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +2 -2
  155. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-manage-packages.html +13 -2
  156. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -2
  157. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +4 -1
  158. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/views/product-details.html +5 -0
  159. data/engines/bastion_katello/lib/bastion_katello/engine.rb +1 -3
  160. data/lib/katello/engine.rb +0 -18
  161. data/lib/katello/permission_creator.rb +1 -1
  162. data/lib/katello/plugin.rb +0 -25
  163. data/lib/katello/version.rb +1 -1
  164. data/lib/monkeys/remove_hidden_distribution.rb +383 -0
  165. data/locale/action_names.rb +3 -1
  166. data/locale/bn/katello.po +130 -39
  167. data/locale/bn_IN/katello.po +130 -39
  168. data/locale/ca/katello.po +130 -39
  169. data/locale/cs/katello.po +130 -39
  170. data/locale/cs_CZ/katello.po +130 -39
  171. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  172. data/locale/de/katello.po +134 -43
  173. data/locale/de_AT/katello.po +130 -39
  174. data/locale/de_DE/katello.po +130 -39
  175. data/locale/el/katello.po +130 -39
  176. data/locale/en/katello.po +130 -39
  177. data/locale/en_GB/katello.po +130 -39
  178. data/locale/en_US/katello.po +130 -39
  179. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  180. data/locale/es/katello.po +133 -42
  181. data/locale/et_EE/katello.po +130 -39
  182. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  183. data/locale/fr/katello.po +138 -47
  184. data/locale/gl/katello.po +130 -39
  185. data/locale/gu/katello.po +130 -39
  186. data/locale/he_IL/katello.po +130 -39
  187. data/locale/hi/katello.po +130 -39
  188. data/locale/id/katello.po +130 -39
  189. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  190. data/locale/it/katello.po +131 -40
  191. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  192. data/locale/ja/katello.po +138 -47
  193. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  194. data/locale/ka/katello.po +131 -40
  195. data/locale/katello.pot +805 -642
  196. data/locale/kn/katello.po +130 -39
  197. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  198. data/locale/ko/katello.po +131 -40
  199. data/locale/ml_IN/katello.po +130 -39
  200. data/locale/mr/katello.po +130 -39
  201. data/locale/nl_NL/katello.po +130 -39
  202. data/locale/or/katello.po +130 -39
  203. data/locale/pa/katello.po +130 -39
  204. data/locale/pl/katello.po +130 -39
  205. data/locale/pl_PL/katello.po +130 -39
  206. data/locale/pt/katello.po +130 -39
  207. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  208. data/locale/pt_BR/katello.po +133 -42
  209. data/locale/ro/katello.po +130 -39
  210. data/locale/ro_RO/katello.po +130 -39
  211. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  212. data/locale/ru/katello.po +131 -40
  213. data/locale/sl/katello.po +130 -39
  214. data/locale/sv_SE/katello.po +130 -39
  215. data/locale/ta/katello.po +130 -39
  216. data/locale/ta_IN/katello.po +130 -39
  217. data/locale/te/katello.po +130 -39
  218. data/locale/tr/katello.po +130 -39
  219. data/locale/vi/katello.po +130 -39
  220. data/locale/vi_VN/katello.po +130 -39
  221. data/locale/zh/katello.po +130 -39
  222. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  223. data/locale/zh_CN/katello.po +138 -47
  224. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  225. data/locale/zh_TW/katello.po +131 -40
  226. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +0 -5
  227. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +9 -3
  228. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +7 -54
  229. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataActions.js +2 -11
  230. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +1 -40
  231. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesConstants.js +0 -3
  232. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +5 -40
  233. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +6 -61
  234. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +5 -4
  235. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +0 -212
  236. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +2 -157
  237. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +0 -20
  238. data/webpack/containers/Application/config.js +5 -0
  239. data/webpack/scenes/ActivationKeys/Details/ActivationKeyActions.js +31 -0
  240. data/webpack/scenes/ActivationKeys/Details/ActivationKeyConstants.js +3 -0
  241. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.js +127 -0
  242. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.scss +37 -0
  243. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetailsSelectors.js +16 -0
  244. data/webpack/scenes/ActivationKeys/Details/__tests__/activationKeyDetails.test.js +117 -0
  245. data/webpack/scenes/ActivationKeys/Details/components/DeleteMenu.js +77 -0
  246. data/webpack/scenes/ActivationKeys/Details/components/DeleteModal.js +63 -0
  247. data/webpack/scenes/ActivationKeys/Details/components/EditModal.js +199 -0
  248. data/webpack/scenes/ActivationKeys/Details/index.js +3 -0
  249. data/webpack/scenes/AlternateContentSources/Create/Steps/AcsUrlPaths.js +1 -1
  250. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditCredentials.js +10 -5
  251. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditProducts.js +8 -3
  252. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditSmartProxies.js +8 -3
  253. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditURLPaths.js +1 -1
  254. data/webpack/scenes/AlternateContentSources/Details/__tests__/ACSEdits.test.js +2 -2
  255. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +1 -1
  256. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +37 -29
  257. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +53 -37
  258. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +7 -0
  259. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.fixtures.json +15 -6
  260. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +6 -5
  261. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/publishedContentViewDetails.fixtures.json +43 -197
  262. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +1 -1
  263. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +1 -1
  264. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +2 -2
  265. data/webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompareConfig.js +1 -1
  266. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.fixtures.json +0 -98
  267. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +103 -1
  268. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersionsLatestEnvironment.fixtures.json +634 -0
  269. data/webpack/scenes/ContentViews/components/ContentViewSelect/helpers.js +1 -1
  270. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +14 -12
  271. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +45 -6
  272. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +42 -7
  273. data/webpack/scenes/Hosts/ChangeContentSource/index.js +37 -10
  274. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +5 -0
  275. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +0 -8
  276. data/webpack/scenes/RedHatRepositories/index.scss +1 -1
  277. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +2 -2
  278. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +0 -8
  279. metadata +85 -80
  280. data/app/lib/actions/katello/agent/dispatch_history_presenter.rb +0 -64
  281. data/app/lib/actions/katello/agent_action.rb +0 -119
  282. data/app/lib/actions/katello/bulk_agent_action.rb +0 -34
  283. data/app/lib/actions/katello/host/erratum/applicable_errata_install.rb +0 -44
  284. data/app/lib/actions/katello/host/erratum/install.rb +0 -38
  285. data/app/lib/actions/katello/host/package/install.rb +0 -34
  286. data/app/lib/actions/katello/host/package/remove.rb +0 -48
  287. data/app/lib/actions/katello/host/package/update.rb +0 -42
  288. data/app/lib/actions/katello/host/package_group/install.rb +0 -30
  289. data/app/lib/actions/katello/host/package_group/remove.rb +0 -30
  290. data/app/lib/katello/agent/base_message.rb +0 -41
  291. data/app/lib/katello/agent/client_message_handler.rb +0 -69
  292. data/app/lib/katello/agent/connection.rb +0 -38
  293. data/app/lib/katello/agent/install_errata_message.rb +0 -25
  294. data/app/lib/katello/agent/install_package_group_message.rb +0 -25
  295. data/app/lib/katello/agent/install_package_message.rb +0 -28
  296. data/app/lib/katello/agent/remove_package_group_message.rb +0 -25
  297. data/app/lib/katello/agent/remove_package_message.rb +0 -28
  298. data/app/lib/katello/agent/update_package_message.rb +0 -33
  299. data/app/lib/katello/event_daemon/services/agent_event_receiver.rb +0 -59
  300. data/app/lib/katello/qpid/connection.rb +0 -149
  301. data/app/lib/katello/util/default_enablement_migrator.rb +0 -183
  302. data/app/models/katello/agent/dispatch_history.rb +0 -19
  303. data/app/models/katello/events/delete_host_agent_queue.rb +0 -19
  304. data/app/services/katello/agent/dispatcher.rb +0 -60
  305. data/app/views/foreman/job_templates/change_content_source.erb +0 -18
  306. data/app/views/katello/api/v2/sync/index.json.rabl +0 -1
  307. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/views/katello-agent-notice.html +0 -8
  308. data/lib/katello/tasks/upgrades/4.9/update_custom_products_enablement.rake +0 -13
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import {
3
+ useDispatch,
4
+ } from 'react-redux';
5
+ import PropTypes from 'prop-types';
6
+ import { noop } from 'foremanReact/common/helpers';
7
+ import { translate as __ } from 'foremanReact/common/I18n';
8
+ import { Modal, ModalVariant, Button, Icon, Title, Flex } from '@patternfly/react-core';
9
+ import { ExclamationTriangleIcon } from '@patternfly/react-icons';
10
+ import { deleteActivationKey } from '../ActivationKeyActions';
11
+
12
+ const DeleteModal = ({ isModalOpen, handleModalToggle, akId }) => {
13
+ const dispatch = useDispatch();
14
+
15
+ const handleDelete = () => {
16
+ dispatch(deleteActivationKey(akId));
17
+ handleModalToggle();
18
+ window.location.replace('/activation_keys');
19
+ };
20
+
21
+ return (
22
+ <Modal
23
+ ouiaId="ak-delete-modal"
24
+ variant={ModalVariant.small}
25
+ title={[
26
+ <Flex key="delete-modal-header">
27
+ <Icon status="warning" key="exclamation-triangle">
28
+ <ExclamationTriangleIcon />
29
+ </Icon>
30
+ <Title ouiaId="ak-delete-header" key="delete-ak-title" headingLevel="h5" size="2xl">
31
+ {__('Delete activation key?')}
32
+ </Title>
33
+ </Flex>,
34
+ ]}
35
+ isOpen={isModalOpen}
36
+ onClose={handleModalToggle}
37
+ actions={[
38
+ <Button ouiaId="delete-button" key="delete" variant="danger" onClick={handleDelete}>
39
+ {__('Delete')}
40
+ </Button>,
41
+ <Button ouiaId="cancel-button" key="cancel" variant="link" onClick={handleModalToggle}>
42
+ {__('Cancel')}
43
+ </Button>,
44
+ ]}
45
+ >
46
+ {__('Activation Key will no longer be available for use. This operation cannot be undone.')}
47
+ </Modal>
48
+ );
49
+ };
50
+
51
+
52
+ DeleteModal.propTypes = {
53
+ isModalOpen: PropTypes.bool,
54
+ handleModalToggle: PropTypes.func,
55
+ akId: PropTypes.string.isRequired,
56
+ };
57
+
58
+ DeleteModal.defaultProps = {
59
+ isModalOpen: false,
60
+ handleModalToggle: noop,
61
+ };
62
+
63
+ export default DeleteModal;
@@ -0,0 +1,199 @@
1
+ import React, {
2
+ useEffect,
3
+ useState,
4
+ } from 'react';
5
+ import {
6
+ useDispatch,
7
+ } from 'react-redux';
8
+ import PropTypes from 'prop-types';
9
+ import { translate as __ } from 'foremanReact/common/I18n';
10
+ import {
11
+ Modal,
12
+ ModalVariant,
13
+ Button,
14
+ Form,
15
+ FormGroup,
16
+ TextInput,
17
+ Checkbox,
18
+ NumberInput,
19
+ TextArea,
20
+ Stack,
21
+ StackItem,
22
+ } from '@patternfly/react-core';
23
+ import { getActivationKey, putActivationKey } from '../ActivationKeyActions';
24
+
25
+ const EditModal = ({ akDetails, akId }) => {
26
+ const dispatch = useDispatch();
27
+
28
+ const {
29
+ name, description, maxHosts, unlimitedHosts, usageCount,
30
+ } = akDetails;
31
+
32
+ const initialMaxHosts = maxHosts || '';
33
+
34
+ const [nameValue, setNameValue] = useState(name);
35
+ const [descriptionValue, setDescriptionValue] = useState(description);
36
+ const [maxHostsValue, setMaxHostsValue] = useState(initialMaxHosts);
37
+ const [isUnlimited, setUnlimited] = useState(unlimitedHosts);
38
+ const [isModalOpen, setModalOpen] = useState(false);
39
+
40
+ useEffect(() => {
41
+ setNameValue(name);
42
+ setDescriptionValue(description);
43
+ setMaxHostsValue(initialMaxHosts);
44
+ setUnlimited(unlimitedHosts);
45
+ }, [name, description, initialMaxHosts, unlimitedHosts]);
46
+
47
+ const refreshActivationKeyDetails = () => dispatch(getActivationKey(akId));
48
+
49
+ const handleModalToggle = () => {
50
+ setModalOpen(!isModalOpen);
51
+ };
52
+ const handleSave = () => {
53
+ dispatch(putActivationKey(
54
+ akId,
55
+ {
56
+ name: nameValue,
57
+ description: descriptionValue,
58
+ max_hosts: maxHostsValue || (usageCount !== 0 ? usageCount : usageCount + 1),
59
+ unlimited_hosts: isUnlimited,
60
+ },
61
+ refreshActivationKeyDetails,
62
+ ));
63
+ handleModalToggle();
64
+ };
65
+
66
+ const resetModalValues = () => {
67
+ setNameValue(name);
68
+ setDescriptionValue(description);
69
+ setMaxHostsValue(initialMaxHosts);
70
+ setUnlimited(unlimitedHosts);
71
+ };
72
+
73
+ const handleClose = () => {
74
+ resetModalValues();
75
+ handleModalToggle();
76
+ };
77
+
78
+ const handleNameInputChange = (value) => {
79
+ setNameValue(value);
80
+ };
81
+ const handleDescriptionInputChange = (value) => {
82
+ setDescriptionValue(value);
83
+ };
84
+
85
+ const onMinus = () => {
86
+ setMaxHostsValue(oldValue => (oldValue || 0) - 1);
87
+ };
88
+ const onChange = (event) => {
89
+ let newValue = (event.target.value === '' ? event.target.value : Math.round(+event.target.value));
90
+ if (newValue < 1 && newValue !== '') {
91
+ newValue = 1;
92
+ }
93
+ setMaxHostsValue(newValue);
94
+ };
95
+ const onPlus = () => {
96
+ setMaxHostsValue(oldValue => (oldValue || 0) + 1);
97
+ };
98
+
99
+ const handleCheckBox = () => {
100
+ setUnlimited(prevUnlimited => !prevUnlimited);
101
+ setMaxHostsValue(usageCount > 0 ? usageCount : usageCount + 1);
102
+ };
103
+
104
+ return (
105
+ <>
106
+ <Button ouiaId="ak-edit-button" aria-label="edit-button" variant="secondary" onClick={handleModalToggle}>
107
+ {__('Edit')}
108
+ </Button>
109
+ <Modal
110
+ ouiaId="ak-edit-modal"
111
+ variant={ModalVariant.small}
112
+ title={__('Edit activation key')}
113
+ description={__(`Select attributes for ${akDetails.name}`)}
114
+ isOpen={isModalOpen}
115
+ onClose={handleClose}
116
+ actions={[
117
+ <Button ouiaId="edit-modal-save-button" key="create" variant="primary" form="modal-with-form-form" onClick={handleSave}>
118
+ {__('Save')}
119
+ </Button>,
120
+ <Button ouiaId="cancel-button" key="cancel" variant="link" onClick={handleClose}>
121
+ {__('Cancel')}
122
+ </Button>,
123
+ ]}
124
+ >
125
+ <Form isHorizontal>
126
+ <FormGroup
127
+ label={__('Name')}
128
+ >
129
+ <TextInput
130
+ ouiaId="ak-name-input"
131
+ id="ak-name-input"
132
+ type="text"
133
+ value={nameValue}
134
+ onChange={handleNameInputChange}
135
+ />
136
+ </FormGroup>
137
+ <FormGroup
138
+ label={__('Host Limit')}
139
+ >
140
+ <Stack hasGutter>
141
+ <StackItem>
142
+ <NumberInput
143
+ value={maxHostsValue}
144
+ min={1}
145
+ onMinus={onMinus}
146
+ onChange={onChange}
147
+ onPlus={onPlus}
148
+ inputName="input"
149
+ inputAriaLabel="number input"
150
+ minusBtnAriaLabel="minus"
151
+ plusBtnAriaLabel="plus"
152
+ isDisabled={isUnlimited}
153
+ allowEmptyInput
154
+ />
155
+ </StackItem>
156
+ <StackItem>
157
+ <Checkbox
158
+ ouiaId="unlimited-checkbox"
159
+ id="unlimited-checkbox"
160
+ label={__('Unlimited')}
161
+ isChecked={isUnlimited}
162
+ onChange={handleCheckBox}
163
+ />
164
+ </StackItem>
165
+ </Stack>
166
+ </FormGroup>
167
+ <FormGroup
168
+ label={__('Description')}
169
+ >
170
+ <TextArea
171
+ id="ak-description"
172
+ type="text"
173
+ placeholder={__('Description')}
174
+ value={descriptionValue || ''}
175
+ onChange={handleDescriptionInputChange}
176
+ />
177
+ </FormGroup>
178
+ </Form>
179
+ </Modal>
180
+ </>
181
+ );
182
+ };
183
+
184
+ export default EditModal;
185
+
186
+ EditModal.propTypes = {
187
+ akDetails: PropTypes.shape({
188
+ name: PropTypes.string,
189
+ maxHosts: PropTypes.number,
190
+ description: PropTypes.string,
191
+ unlimitedHosts: PropTypes.bool,
192
+ usageCount: PropTypes.number,
193
+ }),
194
+ akId: PropTypes.string.isRequired,
195
+ };
196
+
197
+ EditModal.defaultProps = {
198
+ akDetails: {},
199
+ };
@@ -0,0 +1,3 @@
1
+ import ActivationKeyDetails from './ActivationKeyDetails';
2
+
3
+ export default ActivationKeyDetails;
@@ -21,7 +21,7 @@ const AcsUrlPaths = () => {
21
21
 
22
22
  const baseURLplaceholder = acsType === 'rhui' ?
23
23
  'https://rhui-server.example.com/pulp/content' :
24
- 'http:// or https://';
24
+ 'http://, https:// or file://';
25
25
  const helperTextInvalid = acsType === 'rhui' ?
26
26
  'http://rhui-server.example.com/pulp/content or https://rhui-server.example.com/pulp/content' :
27
27
  'http://, https:// or file://';
@@ -273,11 +273,11 @@ const ACSEditCredentials = ({ onClose, acsId, acsDetails }) => {
273
273
  fieldId="client_key"
274
274
  >
275
275
  <FormSelect
276
- ouiaId="sslCAcert-select"
276
+ ouiaId="ssl_client_key_select"
277
277
  isRequired
278
278
  value={acsSslClientKey}
279
279
  onChange={value => setAcsSslClientKey(value)}
280
- aria-label="sslCAcert_select"
280
+ aria-label="ssl_client_key_select"
281
281
  >
282
282
  {
283
283
  [
@@ -314,8 +314,8 @@ const ACSEditCredentials = ({ onClose, acsId, acsDetails }) => {
314
314
  />
315
315
  <ActionGroup>
316
316
  <Button
317
- ouiaId="edit-acs-details-submit"
318
- aria-label="edit_acs_details"
317
+ ouiaId="edit-acs-credentials-submit"
318
+ aria-label="edit_acs_credentials"
319
319
  variant="primary"
320
320
  isDisabled={saving}
321
321
  isLoading={saving}
@@ -323,7 +323,12 @@ const ACSEditCredentials = ({ onClose, acsId, acsDetails }) => {
323
323
  >
324
324
  {__('Edit')}
325
325
  </Button>
326
- <Button ouiaId="edit-acs-details-cancel" variant="link" onClick={onClose}>
326
+ <Button
327
+ ouiaId="edit-acs-credentials-cancel"
328
+ aria-label="edit-acs-credentials-cancel"
329
+ variant="link"
330
+ onClick={onClose}
331
+ >
327
332
  {__('Cancel')}
328
333
  </Button>
329
334
  </ActionGroup>
@@ -88,8 +88,8 @@ const ACSEditProducts = ({ onClose, acsId, acsDetails }) => {
88
88
  />
89
89
  <ActionGroup>
90
90
  <Button
91
- ouiaId="edit-acs-details-submit"
92
- aria-label="edit_acs_details"
91
+ ouiaId="edit-acs-products-submit"
92
+ aria-label="edit-acs-products"
93
93
  variant="primary"
94
94
  isDisabled={saving}
95
95
  isLoading={saving}
@@ -97,7 +97,12 @@ const ACSEditProducts = ({ onClose, acsId, acsDetails }) => {
97
97
  >
98
98
  {__('Edit')}
99
99
  </Button>
100
- <Button ouiaId="edit-acs-smart-proxies-cancel" variant="link" onClick={onClose}>
100
+ <Button
101
+ ouiaId="edit-acs-products-cancel"
102
+ aria-label="edit-acs-products-cancel"
103
+ variant="link"
104
+ onClick={onClose}
105
+ >
101
106
  {__('Cancel')}
102
107
  </Button>
103
108
  </ActionGroup>
@@ -118,8 +118,8 @@ const ACSEditSmartProxies = ({ onClose, acsId, acsDetails }) => {
118
118
  </FormGroup>
119
119
  <ActionGroup>
120
120
  <Button
121
- ouiaId="edit-acs-details-submit"
122
- aria-label="edit_acs_details"
121
+ ouiaId="edit-acs-smart-proxies-submit"
122
+ aria-label="edit-acs-smart-proxies"
123
123
  variant="primary"
124
124
  isDisabled={saving}
125
125
  isLoading={saving}
@@ -127,7 +127,12 @@ const ACSEditSmartProxies = ({ onClose, acsId, acsDetails }) => {
127
127
  >
128
128
  {__('Edit')}
129
129
  </Button>
130
- <Button ouiaId="edit-acs-smart-proxies-cancel" variant="link" onClick={onClose}>
130
+ <Button
131
+ ouiaId="edit-acs-smart-proxies-cancel"
132
+ aria-label="edit-acs-smart-proxies-cancel"
133
+ variant="link"
134
+ onClick={onClose}
135
+ >
131
136
  {__('Cancel')}
132
137
  </Button>
133
138
  </ActionGroup>
@@ -16,7 +16,7 @@ const ACSEditURLPaths = ({ onClose, acsId, acsDetails }) => {
16
16
  const urlValidated = (acsUrl === '' || isValidUrl(acsUrl, acsType)) ? 'default' : 'error';
17
17
  const baseURLplaceholder = acsType === 'rhui' ?
18
18
  'https://rhui-server.example.com/pulp/content' :
19
- 'http:// or https://';
19
+ 'http://, https:// or file://';
20
20
  const helperTextInvalid = acsType === 'rhui' ?
21
21
  'http://rhui-server.example.com/pulp/content or https://rhui-server.example.com/pulp/content' :
22
22
  'http://, https:// or file://';
@@ -229,9 +229,9 @@ test('Can edit products in a simplified ACS details edit modal', async (done) =>
229
229
  // Can open modal
230
230
  await patientlyWaitFor(() => {
231
231
  expect(queryAllByText('Edit')).toHaveLength(4);
232
- expect(getByLabelText('edit_acs_details')).toBeInTheDocument();
232
+ expect(getByLabelText('edit-acs-products')).toBeInTheDocument();
233
233
  });
234
- const saveButton = getByLabelText('edit_acs_details');
234
+ const saveButton = getByLabelText('edit-acs-products');
235
235
  fireEvent.click(saveButton);
236
236
  // can close modal
237
237
  await patientlyWaitFor(() => {
@@ -172,7 +172,7 @@ const ACSTable = () => {
172
172
  {__('Last refresh :')}
173
173
  </TextListItem>
174
174
  <TextListItem
175
- aria-label="name_text_value"
175
+ aria-label="last_refresh_text_value"
176
176
  component={TextListItemVariants.dd}
177
177
  >
178
178
  <LastSync
@@ -1,8 +1,8 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useMemo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import {
4
- Flex, Modal, ModalVariant, FormSelect,
5
- FormSelectOption, Checkbox, Form, FormGroup,
4
+ Flex, Modal, ModalVariant, Select, SelectVariant,
5
+ SelectOption, Checkbox, Form, FormGroup,
6
6
  ActionGroup, Button, Tooltip,
7
7
  } from '@patternfly/react-core';
8
8
  import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
@@ -12,13 +12,12 @@ import { STATUS } from 'foremanReact/constants';
12
12
  import {
13
13
  selectCVDetails,
14
14
  selectCVDetailStatus,
15
- selectCVDetailError,
16
15
  } from '../../Details/ContentViewDetailSelectors';
17
16
  import { addComponent } from '../ContentViewDetailActions';
18
17
  import { CONTENT_VIEW_NEEDS_PUBLISH } from '../../ContentViewsConstants';
19
18
 
20
19
  const ComponentContentViewAddModal = ({
21
- cvId, componentCvId, componentId, latest, show, setIsOpen,
20
+ cvId, componentCvId, componentId, latest, componentVersionId, show, setIsOpen,
22
21
  }) => {
23
22
  const dispatch = useDispatch();
24
23
  const componentDetails = useSelector(
@@ -29,26 +28,20 @@ const ComponentContentViewAddModal = ({
29
28
  state => selectCVDetailStatus(state, componentCvId),
30
29
  shallowEqual,
31
30
  );
32
- const componentError = useSelector(
33
- state => selectCVDetailError(state, componentCvId),
34
- shallowEqual,
35
- );
36
- const [cvName, setCvName] = useState('');
37
- const [options, setOptions] = useState([]);
31
+ const cvName = componentDetails?.name ?? '';
32
+ const options = useMemo(() => (componentDetails?.versions ?? []).map(item => ({
33
+ value: item.id, label: __(`Version ${item.version}`), description: item.description, publishedAtWords: __(` (${item.published_at_words} ago)`),
34
+ })), [componentDetails?.versions]);
38
35
  const [formLatest, setFormLatest] = useState(componentId ? latest : false);
39
36
  const [selected, setSelected] = useState(null);
37
+ const [prevOptions, setPrevOptions] = useState(options);
38
+ const [cvVersionSelectOpen, setCvVersionSelectOpen] = useState(false);
40
39
  const versionsLoading = componentStatus === STATUS.PENDING;
41
40
 
42
- useEffect(() => {
43
- if (!versionsLoading && componentDetails) {
44
- const { name, versions } = componentDetails;
45
- const versionMutable = versions;
46
- setCvName(name);
47
- const opt = versionMutable.map(item => ({ value: item.id, label: __(`Version ${item.version}`) }));
48
- setOptions([...opt].reverse());
49
- setSelected(opt.slice(-1)[0].value);
50
- }
51
- }, [componentDetails, componentStatus, componentError, versionsLoading]);
41
+ if (options !== prevOptions) {
42
+ setPrevOptions(options);
43
+ setSelected(componentVersionId ?? options[0]?.value);
44
+ }
52
45
 
53
46
  const getAddParams = () => {
54
47
  if (formLatest) {
@@ -66,7 +59,7 @@ const ComponentContentViewAddModal = ({
66
59
 
67
60
  const updateLatest = (checked) => {
68
61
  setFormLatest(checked);
69
- if (checked) setSelected(options[0]);
62
+ if (checked) setSelected(options[0]?.value);
70
63
  };
71
64
 
72
65
  const onSubmit = () => {
@@ -104,20 +97,30 @@ const ComponentContentViewAddModal = ({
104
97
  }}
105
98
  >
106
99
  <FormGroup label={__('Version')} isRequired fieldId="version">
107
- <FormSelect
108
- value={selected}
100
+ <Select
101
+ variant={SelectVariant.typeahead}
102
+ selections={selected}
109
103
  isDisabled={formLatest || options.length === 1}
110
- onChange={value => setSelected(value)}
104
+ onSelect={(event, value) => { setSelected(value); setCvVersionSelectOpen(false); }}
111
105
  id="horzontal-form-title"
112
106
  name="horizontal-form-title"
107
+ isOpen={cvVersionSelectOpen}
108
+ onToggle={isExpanded => setCvVersionSelectOpen(isExpanded)}
113
109
  aria-label="CvVersion"
114
110
  ouiaId="select-cv-version"
111
+ menuAppendTo="parent"
112
+ maxHeight="20rem"
115
113
  >
116
- {options.map((option, index) => (
117
- // eslint-disable-next-line react/no-array-index-key
118
- <FormSelectOption key={index} value={option.value} label={option.label} />
114
+ {options.map(option => (
115
+ <SelectOption
116
+ key={option.value}
117
+ value={option.value}
118
+ description={option.description}
119
+ >
120
+ <>{option.label}{option.publishedAtWords}</>
121
+ </SelectOption>
119
122
  ))}
120
- </FormSelect>
123
+ </Select>
121
124
  </FormGroup>
122
125
  <FormGroup fieldId="latest">
123
126
  <Flex style={{ display: 'inline-flex' }}>
@@ -162,6 +165,10 @@ ComponentContentViewAddModal.propTypes = {
162
165
  PropTypes.string,
163
166
  ]),
164
167
  latest: PropTypes.bool,
168
+ componentVersionId: PropTypes.oneOfType([
169
+ PropTypes.number,
170
+ PropTypes.string,
171
+ ]),
165
172
  show: PropTypes.bool,
166
173
  setIsOpen: PropTypes.func,
167
174
  };
@@ -169,6 +176,7 @@ ComponentContentViewAddModal.propTypes = {
169
176
  ComponentContentViewAddModal.defaultProps = {
170
177
  componentId: null,
171
178
  latest: false,
179
+ componentVersionId: null,
172
180
  show: false,
173
181
  setIsOpen: null,
174
182
  };
@@ -1,9 +1,8 @@
1
- import React, { useState, useMemo } from 'react';
2
- import { last } from 'lodash';
1
+ import React, { useState } from 'react';
3
2
  import PropTypes from 'prop-types';
4
3
  import {
5
- Flex, Modal, ModalVariant, FormSelect,
6
- FormSelectOption, Checkbox, Form, FormGroup,
4
+ Flex, Modal, ModalVariant, Select, SelectVariant,
5
+ SelectOption, Checkbox, Form, FormGroup,
7
6
  ActionGroup, Button, Card, CardTitle, CardBody, Tooltip,
8
7
  } from '@patternfly/react-core';
9
8
  import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
@@ -13,25 +12,18 @@ import { addComponent } from '../ContentViewDetailActions';
13
12
 
14
13
  const ComponentContentViewBulkAddModal = ({ cvId, rowsToAdd, onClose }) => {
15
14
  const dispatch = useDispatch();
16
- const [versionSelectOptions, setVersionSelectOptions] = useState({});
17
- const [selectedVersion, setSelectedVersion] = useState({});
18
- const [selectedComponentLatest, setSelectedComponentLatest] = useState({});
19
-
20
- useMemo(() => {
21
- const versionSelect = {};
22
- const versionSelectedOption = {};
23
- const componentLatest = {};
24
- rowsToAdd.forEach((row) => {
25
- const { componentCvVersions: versions, componentCvName: name } = row;
26
- const sortedVersions = [].concat(versions).sort((a, b) => (a.id > b.id ? 1 : -1));
27
- versionSelect[name] = sortedVersions;
28
- versionSelectedOption[name] = last(sortedVersions)?.id;
29
- componentLatest[name] = sortedVersions && sortedVersions?.length === 0;
30
- });
31
- setVersionSelectOptions(versionSelect);
32
- setSelectedVersion(versionSelectedOption);
33
- setSelectedComponentLatest(componentLatest);
34
- }, [rowsToAdd, setVersionSelectOptions, setSelectedVersion, setSelectedComponentLatest]);
15
+ const versionSelect = {};
16
+ const versionSelectedOption = {};
17
+ const componentLatest = {};
18
+ rowsToAdd.forEach((row) => {
19
+ const { componentCvVersions: versions, componentCvName: name } = row;
20
+ versionSelect[name] = versions;
21
+ versionSelectedOption[name] = versions[0]?.id;
22
+ componentLatest[name] = versions && versions?.length === 0;
23
+ });
24
+ const [selectedVersion, setSelectedVersion] = useState(versionSelectedOption);
25
+ const [selectedComponentLatest, setSelectedComponentLatest] = useState(componentLatest);
26
+ const [cvVersionSelectOpen, setCvVersionSelectOpen] = useState('');
35
27
 
36
28
  const bulkAddParams = () => rowsToAdd.map((row) => {
37
29
  const { componentCvId: id, componentCvName: name } = row;
@@ -64,26 +56,45 @@ const ComponentContentViewBulkAddModal = ({ cvId, rowsToAdd, onClose }) => {
64
56
  onSubmit();
65
57
  }}
66
58
  >
67
- {Object.keys(versionSelectOptions).sort().map(componentCvName => (
68
- <Card ouiaId="componentCvName" key={componentCvName}>
59
+ {Object.keys(versionSelect).sort().map(componentCvName => (
60
+ <Card
61
+ ouiaId="componentCvName"
62
+ aria-label="componentCvName"
63
+ key={componentCvName}
64
+ >
69
65
  <CardTitle aria-label={componentCvName}>{componentCvName}</CardTitle>
70
66
  <CardBody>
71
67
  <FormGroup label={__('Version')} isRequired fieldId="version">
72
- <FormSelect
73
- value={selectedVersion[componentCvName]}
68
+ <Select
69
+ variant={SelectVariant.typeahead}
70
+ selections={selectedVersion[componentCvName]}
74
71
  ouiaId="select-version"
75
- isDisabled={versionSelectOptions[componentCvName].length <= 1}
76
- onChange={value =>
77
- setSelectedVersion({ ...selectedVersion, ...{ [componentCvName]: value } })}
78
- id={`horzontal-form-title-${componentCvName}`}
72
+ isDisabled={versionSelect[componentCvName].length <= 1 ||
73
+ selectedComponentLatest[componentCvName]}
74
+ onSelect={(__event, value) => {
75
+ setSelectedVersion({ ...selectedVersion, ...{ [componentCvName]: value } });
76
+ setCvVersionSelectOpen('');
77
+ }
78
+ }
79
+ isOpen={cvVersionSelectOpen === componentCvName}
80
+ onToggle={isExpanded => setCvVersionSelectOpen(isExpanded ? componentCvName : '')}
81
+ id={`horzontal-form-title-${componentCvName}-${cvVersionSelectOpen[componentCvName]}`}
79
82
  name="horizontal-form-title"
80
83
  aria-label={`version-select-${componentCvName}`}
84
+ menuAppendTo="parent"
85
+ maxHeight="20rem"
81
86
  >
82
- {versionSelectOptions[componentCvName].map((version, index) => (
83
- // eslint-disable-next-line react/no-array-index-key
84
- <FormSelectOption aria-label={`${componentCvName}-${version.version}`} key={index} value={version.id} label={`${__('Version')} ${version.version}`} />
87
+ {versionSelect[componentCvName].map(version => (
88
+ <SelectOption
89
+ key={`${componentCvName}-${version.version}`}
90
+ aria-label={`${componentCvName}-${version.version}`}
91
+ value={version.id}
92
+ description={version.description}
93
+ >
94
+ <>{`${__('Version')} ${version.version}`}{__(` (${version.published_at_words} ago)`)}</>
95
+ </SelectOption>
85
96
  ))}
86
- </FormSelect>
97
+ </Select>
87
98
  </FormGroup>
88
99
  <FormGroup style={{ marginTop: '1em' }}>
89
100
  <Flex style={{ display: 'inline-flex' }}>
@@ -94,11 +105,16 @@ const ComponentContentViewBulkAddModal = ({ cvId, rowsToAdd, onClose }) => {
94
105
  name="latest"
95
106
  label={__('Always update to latest version')}
96
107
  isChecked={selectedComponentLatest[componentCvName]}
97
- onChange={checked =>
108
+ onChange={(checked) => {
98
109
  setSelectedComponentLatest({
99
110
  ...selectedComponentLatest,
100
111
  ...{ [componentCvName]: checked },
101
- })
112
+ });
113
+ setSelectedVersion({
114
+ ...selectedVersion,
115
+ ...{ [componentCvName]: versionSelect[componentCvName][0]?.id },
116
+ });
117
+ }
102
118
  }
103
119
  />
104
120
  <Tooltip