katello 4.9.2 → 4.10.0.rc1

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 (276) 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/hosts_bulk_actions_controller.rb +0 -77
  59. data/app/controllers/katello/api/v2/organizations_controller.rb +2 -1
  60. data/app/controllers/katello/api/v2/repositories_controller.rb +6 -10
  61. data/app/controllers/katello/api/v2/sync_controller.rb +0 -1
  62. data/app/controllers/katello/concerns/api/api_controller.rb +0 -10
  63. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +1 -1
  64. data/app/lib/actions/katello/alternate_content_source/update.rb +1 -1
  65. data/app/lib/actions/katello/content_view/capsule_sync.rb +1 -1
  66. data/app/lib/actions/katello/content_view/incremental_updates.rb +3 -9
  67. data/app/lib/actions/katello/content_view_version/republish_repositories.rb +8 -2
  68. data/app/lib/actions/katello/repository/capsule_sync.rb +1 -1
  69. data/app/lib/actions/katello/repository/update_metadata_sync.rb +1 -1
  70. data/app/lib/katello/concerns/base_template_scope_extensions.rb +4 -9
  71. data/app/lib/katello/resources/cdn.rb +4 -0
  72. data/app/lib/katello/validators/alternate_content_source_products_validator.rb +1 -1
  73. data/app/models/katello/cdn_configuration.rb +4 -0
  74. data/app/models/katello/concerns/host_managed_extensions.rb +2 -1
  75. data/app/models/katello/content_view.rb +5 -1
  76. data/app/models/katello/content_view_component.rb +1 -1
  77. data/app/models/katello/content_view_version.rb +4 -0
  78. data/app/models/katello/host/content_facet.rb +4 -5
  79. data/app/models/katello/ping.rb +0 -19
  80. data/app/models/katello/repository.rb +5 -1
  81. data/app/models/katello/root_repository.rb +2 -8
  82. data/app/services/katello/applicability/applicable_content_helper.rb +2 -2
  83. data/app/services/katello/registration_manager.rb +2 -12
  84. data/app/views/foreman/job_templates/configure_host_for_new_content_source.erb +25 -0
  85. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +1 -1
  86. data/app/views/katello/api/v2/content_facet/show.json.rabl +0 -12
  87. data/app/views/katello/api/v2/content_view_components/show.json.rabl +4 -1
  88. data/app/views/katello/api/v2/content_views/base.json.rabl +6 -2
  89. data/app/views/katello/api/v2/repositories/show.json.rabl +0 -1
  90. data/config/initializers/monkeys.rb +1 -0
  91. data/config/katello.yaml.example +0 -4
  92. data/config/routes/api/v2.rb +3 -0
  93. data/config/routes/overrides.rb +0 -11
  94. data/db/migrate/20230609155411_add_custom_cdn_auth_enabled_to_katello_cdn_configurations.rb +5 -0
  95. data/db/migrate/20230710190626_remove_relative_path_limit.rb +5 -0
  96. data/db/migrate/20230717150442_change_change_content_source_job_template_name.rb +20 -0
  97. data/db/migrate/20230828143236_remove_katello_agent_dispatch_history.rb +15 -0
  98. data/db/seeds.d/111-upgrade_tasks.rb +1 -2
  99. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -1
  100. data/engines/bastion_katello/README.md +2 -1
  101. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/activation-keys.controller.js +4 -2
  102. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-associations-content-hosts.html +2 -2
  103. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/views/activation-keys.html +8 -3
  104. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +3 -44
  105. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-module-streams-modal.controller.js +0 -1
  106. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-packages-modal.controller.js +1 -65
  107. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +1 -3
  108. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-packages-modal.html +1 -6
  109. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-applicable.controller.js +1 -1
  110. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-errata.controller.js +1 -16
  111. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +0 -1
  112. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-actions.controller.js +0 -1
  113. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-applicable.controller.js +2 -11
  114. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +0 -2
  115. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages.controller.js +1 -39
  116. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-applicable.html +2 -2
  117. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-errata.html +1 -2
  118. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-actions.html +2 -3
  119. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-applicable.html +4 -5
  120. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-installed.html +1 -1
  121. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +2 -4
  122. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +2 -4
  123. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-details.html +0 -1
  124. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +0 -14
  125. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +0 -4
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +1 -2
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/file-content-views.controller.js +2 -1
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/views/file-content-views.html +1 -1
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +235 -521
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-manage-packages.html +13 -2
  131. data/engines/bastion_katello/lib/bastion_katello/engine.rb +1 -3
  132. data/lib/katello/engine.rb +0 -18
  133. data/lib/katello/permission_creator.rb +1 -1
  134. data/lib/katello/plugin.rb +0 -25
  135. data/lib/katello/version.rb +1 -1
  136. data/lib/monkeys/remove_hidden_distribution.rb +383 -0
  137. data/locale/action_names.rb +3 -1
  138. data/locale/bn/katello.po +130 -39
  139. data/locale/bn_IN/katello.po +130 -39
  140. data/locale/ca/katello.po +130 -39
  141. data/locale/cs/katello.po +130 -39
  142. data/locale/cs_CZ/katello.po +130 -39
  143. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  144. data/locale/de/katello.po +134 -43
  145. data/locale/de_AT/katello.po +130 -39
  146. data/locale/de_DE/katello.po +130 -39
  147. data/locale/el/katello.po +130 -39
  148. data/locale/en/katello.po +130 -39
  149. data/locale/en_GB/katello.po +130 -39
  150. data/locale/en_US/katello.po +130 -39
  151. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  152. data/locale/es/katello.po +133 -42
  153. data/locale/et_EE/katello.po +130 -39
  154. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  155. data/locale/fr/katello.po +138 -47
  156. data/locale/gl/katello.po +130 -39
  157. data/locale/gu/katello.po +130 -39
  158. data/locale/he_IL/katello.po +130 -39
  159. data/locale/hi/katello.po +130 -39
  160. data/locale/id/katello.po +130 -39
  161. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  162. data/locale/it/katello.po +131 -40
  163. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  164. data/locale/ja/katello.po +138 -47
  165. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  166. data/locale/ka/katello.po +131 -40
  167. data/locale/katello.pot +805 -642
  168. data/locale/kn/katello.po +130 -39
  169. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  170. data/locale/ko/katello.po +131 -40
  171. data/locale/ml_IN/katello.po +130 -39
  172. data/locale/mr/katello.po +130 -39
  173. data/locale/nl_NL/katello.po +130 -39
  174. data/locale/or/katello.po +130 -39
  175. data/locale/pa/katello.po +130 -39
  176. data/locale/pl/katello.po +130 -39
  177. data/locale/pl_PL/katello.po +130 -39
  178. data/locale/pt/katello.po +130 -39
  179. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  180. data/locale/pt_BR/katello.po +133 -42
  181. data/locale/ro/katello.po +130 -39
  182. data/locale/ro_RO/katello.po +130 -39
  183. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  184. data/locale/ru/katello.po +131 -40
  185. data/locale/sl/katello.po +130 -39
  186. data/locale/sv_SE/katello.po +130 -39
  187. data/locale/ta/katello.po +130 -39
  188. data/locale/ta_IN/katello.po +130 -39
  189. data/locale/te/katello.po +130 -39
  190. data/locale/tr/katello.po +130 -39
  191. data/locale/vi/katello.po +130 -39
  192. data/locale/vi_VN/katello.po +130 -39
  193. data/locale/zh/katello.po +130 -39
  194. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  195. data/locale/zh_CN/katello.po +138 -47
  196. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  197. data/locale/zh_TW/katello.po +131 -40
  198. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +0 -5
  199. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +9 -3
  200. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +7 -58
  201. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataActions.js +2 -11
  202. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +1 -40
  203. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesConstants.js +0 -3
  204. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +5 -40
  205. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +6 -65
  206. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +5 -4
  207. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +0 -212
  208. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +2 -157
  209. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +0 -20
  210. data/webpack/containers/Application/config.js +5 -0
  211. data/webpack/scenes/ActivationKeys/Details/ActivationKeyActions.js +31 -0
  212. data/webpack/scenes/ActivationKeys/Details/ActivationKeyConstants.js +3 -0
  213. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.js +127 -0
  214. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.scss +37 -0
  215. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetailsSelectors.js +16 -0
  216. data/webpack/scenes/ActivationKeys/Details/__tests__/activationKeyDetails.test.js +117 -0
  217. data/webpack/scenes/ActivationKeys/Details/components/DeleteMenu.js +77 -0
  218. data/webpack/scenes/ActivationKeys/Details/components/DeleteModal.js +63 -0
  219. data/webpack/scenes/ActivationKeys/Details/components/EditModal.js +199 -0
  220. data/webpack/scenes/ActivationKeys/Details/index.js +3 -0
  221. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditCredentials.js +10 -5
  222. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditProducts.js +8 -3
  223. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditSmartProxies.js +8 -3
  224. data/webpack/scenes/AlternateContentSources/Details/__tests__/ACSEdits.test.js +2 -2
  225. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +1 -1
  226. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +37 -29
  227. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +53 -37
  228. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +7 -0
  229. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.fixtures.json +15 -6
  230. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +6 -5
  231. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/publishedContentViewDetails.fixtures.json +43 -197
  232. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +1 -1
  233. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +1 -1
  234. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +2 -2
  235. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.fixtures.json +0 -98
  236. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +103 -1
  237. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersionsLatestEnvironment.fixtures.json +634 -0
  238. data/webpack/scenes/ContentViews/components/ContentViewSelect/helpers.js +1 -1
  239. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +14 -12
  240. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +45 -6
  241. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +42 -7
  242. data/webpack/scenes/Hosts/ChangeContentSource/index.js +37 -10
  243. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +5 -0
  244. data/webpack/scenes/RedHatRepositories/index.scss +1 -1
  245. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +2 -2
  246. metadata +85 -81
  247. data/app/lib/actions/katello/agent/dispatch_history_presenter.rb +0 -64
  248. data/app/lib/actions/katello/agent_action.rb +0 -120
  249. data/app/lib/actions/katello/bulk_agent_action.rb +0 -37
  250. data/app/lib/actions/katello/host/erratum/applicable_errata_install.rb +0 -44
  251. data/app/lib/actions/katello/host/erratum/install.rb +0 -38
  252. data/app/lib/actions/katello/host/package/install.rb +0 -34
  253. data/app/lib/actions/katello/host/package/remove.rb +0 -48
  254. data/app/lib/actions/katello/host/package/update.rb +0 -42
  255. data/app/lib/actions/katello/host/package_group/install.rb +0 -30
  256. data/app/lib/actions/katello/host/package_group/remove.rb +0 -30
  257. data/app/lib/katello/agent/base_message.rb +0 -41
  258. data/app/lib/katello/agent/client_message_handler.rb +0 -69
  259. data/app/lib/katello/agent/connection.rb +0 -38
  260. data/app/lib/katello/agent/install_errata_message.rb +0 -25
  261. data/app/lib/katello/agent/install_package_group_message.rb +0 -25
  262. data/app/lib/katello/agent/install_package_message.rb +0 -28
  263. data/app/lib/katello/agent/remove_package_group_message.rb +0 -25
  264. data/app/lib/katello/agent/remove_package_message.rb +0 -28
  265. data/app/lib/katello/agent/update_package_message.rb +0 -33
  266. data/app/lib/katello/event_daemon/services/agent_event_receiver.rb +0 -59
  267. data/app/lib/katello/qpid/connection.rb +0 -149
  268. data/app/lib/katello/util/default_enablement_migrator.rb +0 -183
  269. data/app/models/katello/agent/dispatch_history.rb +0 -19
  270. data/app/models/katello/events/delete_host_agent_queue.rb +0 -19
  271. data/app/services/katello/agent/dispatcher.rb +0 -60
  272. data/app/views/foreman/job_templates/change_content_source.erb +0 -18
  273. data/app/views/katello/api/v2/sync/index.json.rabl +0 -1
  274. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/views/katello-agent-notice.html +0 -8
  275. data/lib/katello/tasks/upgrades/4.9/update_custom_products_enablement.rake +0 -13
  276. data/webpack/components/extensions/HostDetails/common/KatelloAgentDeprecationAlert.js +0 -23
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { renderWithRedux, patientlyWaitFor, fireEvent, within } from 'react-testing-lib-wrapper';
3
3
  import { nockInstance, assertNockRequest, mockForemanAutocomplete } from '../../../../../test-utils/nockWrapper';
4
- import katelloApi, { foremanApi } from '../../../../../services/api';
4
+ import katelloApi from '../../../../../services/api';
5
5
  import mockPackagesData from './yumInstallablePackages.fixtures.json';
6
6
  import PackageInstallModal from '../PackagesTab/PackageInstallModal';
7
7
  import { HOST_YUM_INSTALLABLE_PACKAGES_KEY } from '../PackagesTab/YumInstallablePackagesConstants';
@@ -39,9 +39,7 @@ const renderOptions = (facetAttributes = contentFacetAttributes) => ({
39
39
  });
40
40
 
41
41
  const hostYumInstallablePackages = katelloApi.getApiUrl('/packages');
42
- const hostPackages = foremanApi.getApiUrl('/hosts/1/packages/install');
43
42
  const autocompleteUrl = '/hosts/1/packages/auto_complete_search';
44
- const fakeTask = { id: '21c0f9e4-b27b-49aa-8774-6be66126043b' };
45
43
 
46
44
  const defaultQuery = {
47
45
  packages_restrict_not_installed: true,
@@ -53,11 +51,10 @@ const defaultQuery = {
53
51
  };
54
52
 
55
53
  let firstPackages;
56
- let secondPackages;
57
54
 
58
55
  beforeEach(() => {
59
56
  const { results } = mockPackagesData;
60
- [firstPackages, secondPackages] = results;
57
+ [firstPackages] = results;
61
58
  });
62
59
 
63
60
  test('Can call API for installable packages and show on screen on page load', async (done) => {
@@ -74,7 +71,6 @@ test('Can call API for installable packages and show on screen on page load', as
74
71
  closeModal={jest.fn()}
75
72
  hostId={1}
76
73
  hostName="test-host"
77
- showKatelloAgent={false}
78
74
  triggerPackageInstall={jest.fn()}
79
75
  />, renderOptions());
80
76
 
@@ -107,7 +103,6 @@ test('Can handle no installable packages being present', async (done) => {
107
103
  closeModal={jest.fn()}
108
104
  hostId={1}
109
105
  hostName="test-host"
110
- showKatelloAgent={false}
111
106
  triggerPackageInstall={jest.fn()}
112
107
  />, renderOptions());
113
108
 
@@ -118,120 +113,6 @@ test('Can handle no installable packages being present', async (done) => {
118
113
  assertNockRequest(scope, done); // Pass jest callback to confirm test is done
119
114
  });
120
115
 
121
- test('Does not show katello-agent option when disabled', async (done) => {
122
- const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
123
-
124
- const scope = nockInstance
125
- .get(hostYumInstallablePackages)
126
- .query(defaultQuery)
127
- .reply(200, mockPackagesData);
128
-
129
- const {
130
- getAllByText, getByText, getByRole, queryByText,
131
- } = renderWithRedux(<PackageInstallModal
132
- isOpen
133
- closeModal={jest.fn()}
134
- hostId={1}
135
- hostName="test-host"
136
- showKatelloAgent={false}
137
- triggerPackageInstall={jest.fn()}
138
- />, renderOptions());
139
-
140
- // Assert that the packages are now showing on the screen, but wait for them to appear.
141
- await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
142
- // Assert request was made and completed, see helper function
143
- // find the first table row's checkbox
144
- const checkbox = getByRole('checkbox', { name: 'Select row 0' });
145
- // click the checkbox to make sure the Install dropdown will be enabled
146
- fireEvent.click(checkbox);
147
- const footer = getByRole('contentinfo');
148
- // find the dropdown to the right of the Install button
149
- // (no, the other one! The one that's in the footer.)
150
- const dropdown = await patientlyWaitFor(() => within(footer).getByRole('button', { name: 'Select' }));
151
- fireEvent.click(dropdown);
152
- expect(getByText('Install via remote execution')).toBeInTheDocument();
153
- // Assert that the katello-agent option is not present
154
- expect(queryByText('katello-agent')).not.toBeInTheDocument();
155
-
156
- assertNockRequest(autocompleteScope);
157
- assertNockRequest(scope, done); // Pass jest callback to confirm test is done
158
- });
159
-
160
- test('Shows the katello-agent option when enabled', async (done) => {
161
- const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
162
-
163
- const scope = nockInstance
164
- .get(hostYumInstallablePackages)
165
- .query(defaultQuery)
166
- .reply(200, mockPackagesData);
167
-
168
- const {
169
- getAllByText, getByText, getByRole,
170
- } = renderWithRedux(<PackageInstallModal
171
- isOpen
172
- closeModal={jest.fn()}
173
- hostId={1}
174
- hostName="test-host"
175
- showKatelloAgent
176
- triggerPackageInstall={jest.fn()}
177
- />, renderOptions());
178
-
179
- // Assert that the packages are now showing on the screen, but wait for them to appear.
180
- await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
181
- // Assert request was made and completed, see helper function
182
- // find the first table row's checkbox
183
- const checkbox = getByRole('checkbox', { name: 'Select row 0' });
184
- // click the checkbox to make sure the Install dropdown will be enabled
185
- fireEvent.click(checkbox);
186
- const footer = getByRole('contentinfo');
187
- const dropdown = await patientlyWaitFor(() => within(footer).getByRole('button', { name: 'Select' }));
188
- fireEvent.click(dropdown);
189
- expect(getByText('Install via remote execution')).toBeInTheDocument();
190
- expect(getByText('Install via katello-agent')).toBeInTheDocument();
191
-
192
- assertNockRequest(autocompleteScope);
193
- assertNockRequest(scope, done); // Pass jest callback to confirm test is done
194
- });
195
-
196
- test('Can install packages via katello-agent', async (done) => {
197
- const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
198
-
199
- const scope = nockInstance
200
- .get(hostYumInstallablePackages)
201
- .query(defaultQuery)
202
- .reply(200, mockPackagesData);
203
- const installScope = nockInstance
204
- .put(hostPackages, { packages: [secondPackages.name, firstPackages.name] })
205
- .reply(202, fakeTask);
206
- const {
207
- getAllByText, getByText, getByRole,
208
- } = renderWithRedux(<PackageInstallModal
209
- isOpen
210
- closeModal={jest.fn()}
211
- hostId={1}
212
- hostName="test-host"
213
- showKatelloAgent
214
- triggerPackageInstall={jest.fn()}
215
- />, renderOptions());
216
-
217
- await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
218
- // find and select the first two packages
219
- const checkbox1 = getByRole('checkbox', { name: 'Select row 0' });
220
- const checkbox2 = getByRole('checkbox', { name: 'Select row 1' });
221
- fireEvent.click(checkbox1);
222
- fireEvent.click(checkbox2);
223
- // click the Install dropdown
224
- const footer = getByRole('contentinfo');
225
- const dropdown = await patientlyWaitFor(() => within(footer).getByRole('button', { name: 'Select' }));
226
- fireEvent.click(dropdown);
227
- // click the katello-agent option
228
- const katelloAgentOption = getByText('Install via katello-agent');
229
- fireEvent.click(katelloAgentOption);
230
-
231
- assertNockRequest(autocompleteScope);
232
- assertNockRequest(scope);
233
- assertNockRequest(installScope, done);
234
- });
235
116
 
236
117
  test('Can install a package via remote execution', async (done) => {
237
118
  const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
@@ -248,7 +129,6 @@ test('Can install a package via remote execution', async (done) => {
248
129
  closeModal={jest.fn()}
249
130
  hostId={1}
250
131
  hostName="test-host"
251
- showKatelloAgent
252
132
  triggerPackageInstall={triggerPackageInstall}
253
133
  />, renderOptions());
254
134
 
@@ -345,38 +225,3 @@ test('Uses package_install_by_search_query template when in select all mode', as
345
225
  assertNockRequest(scope, done);
346
226
  });
347
227
 
348
- test('Disables the katello-agent option when in select all mode', async (done) => {
349
- const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
350
- const scope = nockInstance
351
- .get(hostYumInstallablePackages)
352
- .query(defaultQuery)
353
- .reply(200, mockPackagesData);
354
-
355
- const {
356
- getAllByText, getByText, getByRole,
357
- } = renderWithRedux(<PackageInstallModal
358
- isOpen
359
- closeModal={jest.fn()}
360
- hostId={1}
361
- hostName="test-host"
362
- showKatelloAgent
363
- triggerPackageInstall={jest.fn()}
364
- />, renderOptions());
365
-
366
- await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
367
- // find and click the select all checkbox
368
- const selectAllCheckbox = getByRole('checkbox', { name: 'Select all' });
369
- fireEvent.click(selectAllCheckbox);
370
- // find and deselect the first package
371
- const checkbox1 = getByRole('checkbox', { name: 'Select row 0' });
372
- fireEvent.click(checkbox1);
373
- // click the Install dropdown
374
- const footer = getByRole('contentinfo');
375
- const dropdown = await patientlyWaitFor(() => within(footer).getByRole('button', { name: 'Select' }));
376
- fireEvent.click(dropdown);
377
- const katelloAgentOption = getByText('Install via katello-agent');
378
- // expect the katello-agent option to be disabled
379
- expect(katelloAgentOption).toHaveAttribute('aria-disabled', 'true');
380
- assertNockRequest(autocompleteScope);
381
- assertNockRequest(scope, done);
382
- });
@@ -1,21 +1,3 @@
1
- import { propsToCamelCase } from 'foremanReact/common/helpers';
2
-
3
- export const REMOTE_EXECUTION = 'remoteExecution';
4
- export const KATELLO_AGENT = 'katelloAgent';
5
-
6
- export const defaultRemoteActionMethod = ({ hostDetails }) => {
7
- const {
8
- content_facet_attributes: contentFacetAttributes,
9
- } = hostDetails;
10
- const contentFacet = propsToCamelCase(contentFacetAttributes ?? {});
11
- const katelloAgentAvailable = (contentFacet.katelloAgentInstalled &&
12
- contentFacet.katelloAgentEnabled);
13
- if (contentFacet.remoteExecutionByDefault || !katelloAgentAvailable) {
14
- return REMOTE_EXECUTION;
15
- }
16
- return KATELLO_AGENT;
17
- };
18
-
19
1
  export const hostIsNotRegistered = ({ hostDetails }) => {
20
2
  const {
21
3
  subscription_facet_attributes: subscriptionFacetAttributes,
@@ -42,5 +24,3 @@ export const hasRequiredPermissions = (requiredPermissions = [], userPermissions
42
24
 
43
25
  export const missingRequiredPermissions = (requiredPermissions = [], userPermissions) =>
44
26
  !hasRequiredPermissions(requiredPermissions, userPermissions);
45
-
46
- export default defaultRemoteActionMethod;
@@ -3,6 +3,7 @@ import Repos from '../../scenes/RedHatRepositories';
3
3
  import Subscriptions from '../../scenes/Subscriptions';
4
4
  import UpstreamSubscriptions from '../../scenes/Subscriptions/UpstreamSubscriptions/index';
5
5
  import SubscriptionDetails from '../../scenes/Subscriptions/Details';
6
+ import ActivationKeyDetails from '../../scenes/ActivationKeys/Details/ActivationKeyDetails';
6
7
  import SetOrganization from '../../components/SelectOrg/SetOrganization';
7
8
  import WithOrganization from '../../components/WithOrganization/withOrganization';
8
9
  import ModuleStreams from '../../scenes/ModuleStreams';
@@ -29,6 +30,10 @@ export const links = [
29
30
  path: 'subscriptions/add',
30
31
  component: WithOrganization(withHeader(UpstreamSubscriptions, { title: __('Add Subscriptions') })),
31
32
  },
33
+ {
34
+ path: 'labs/activation_keys/:id',
35
+ component: WithOrganization(withHeader(ActivationKeyDetails, { title: __('Activation key details') })),
36
+ },
32
37
  {
33
38
  // eslint-disable-next-line no-useless-escape
34
39
  path: 'subscriptions/:id([0-9]+)',
@@ -0,0 +1,31 @@
1
+ import { translate as __ } from 'foremanReact/common/I18n';
2
+ import { APIActions, API_OPERATIONS, put, get } from 'foremanReact/redux/API';
3
+ import { errorToast } from '../../Tasks/helpers';
4
+ import katelloApi from '../../../services/api/index';
5
+ import { ACTIVATION_KEY } from './ActivationKeyConstants';
6
+
7
+ export const getActivationKey = akId => get({
8
+ type: API_OPERATIONS.GET,
9
+ key: `${ACTIVATION_KEY}_${akId}`,
10
+ url: katelloApi.getApiUrl(`/activation_keys/${akId}`),
11
+ });
12
+
13
+ export const putActivationKey = (akId, params, refreshActivationKeyDetails) => put({
14
+ type: API_OPERATIONS.PUT,
15
+ key: `ALTER_ACTIVATION_KEY_${akId}`,
16
+ url: katelloApi.getApiUrl(`/activation_keys/${akId}`),
17
+ successToast: () => __('Activation key details updated'),
18
+ errorToast,
19
+ params,
20
+ handleSuccess: refreshActivationKeyDetails,
21
+ });
22
+
23
+ export const deleteActivationKey = akId => APIActions.delete({
24
+ type: API_OPERATIONS.DELETE,
25
+ key: `${ACTIVATION_KEY}_${akId}`,
26
+ url: katelloApi.getApiUrl(`/activation_keys/${akId}`),
27
+ successToast: () => __('Activation key deleted'),
28
+ errorToast,
29
+ });
30
+
31
+ export default getActivationKey;
@@ -0,0 +1,3 @@
1
+ export const ACTIVATION_KEY = 'ACTIVATION_KEY';
2
+
3
+ export default ACTIVATION_KEY;
@@ -0,0 +1,127 @@
1
+ import React, {
2
+ useEffect,
3
+ useState,
4
+ } from 'react';
5
+ import {
6
+ useDispatch,
7
+ useSelector,
8
+ } from 'react-redux';
9
+ import { translate as __ } from 'foremanReact/common/I18n';
10
+ import PropTypes from 'prop-types';
11
+ import { propsToCamelCase } from 'foremanReact/common/helpers';
12
+ import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
13
+ import {
14
+ Title,
15
+ TextContent,
16
+ Text,
17
+ TextVariants,
18
+ Breadcrumb,
19
+ BreadcrumbItem,
20
+ Grid,
21
+ GridItem,
22
+ Label,
23
+ Split,
24
+ SplitItem,
25
+ Flex,
26
+ FlexItem,
27
+ Panel,
28
+ } from '@patternfly/react-core';
29
+ import './ActivationKeyDetails.scss';
30
+ import EditModal from './components/EditModal';
31
+ import DeleteMenu from './components/DeleteMenu';
32
+ import { getActivationKey } from './ActivationKeyActions';
33
+ import DeleteModal from './components/DeleteModal';
34
+ import InactiveText from '../../ContentViews/components/InactiveText';
35
+
36
+ const ActivationKeyDetails = ({ match }) => {
37
+ const dispatch = useDispatch();
38
+ const akId = match?.params?.id;
39
+ const akDetailsResponse = useSelector(state => selectAPIResponse(state, `ACTIVATION_KEY_${akId}`));
40
+ const akDetails = propsToCamelCase(akDetailsResponse);
41
+ const [isModalOpen, setModalOpen] = useState(false);
42
+
43
+ useEffect(() => {
44
+ if (akId) {
45
+ dispatch(getActivationKey(akId));
46
+ }
47
+ }, [akId, dispatch]);
48
+
49
+ const handleModalToggle = () => {
50
+ setModalOpen(!isModalOpen);
51
+ };
52
+
53
+ return (
54
+ <div >
55
+ <Panel className="ak-details-header">
56
+ <div className="breadcrumb-bar-pf4">
57
+ <Breadcrumb ouiaId="ak-breadcrumbs" className="breadcrumb-display">
58
+ <BreadcrumbItem className="breadcrumb-list" to="/activation_keys">
59
+ {__('Activation keys')}
60
+ </BreadcrumbItem>
61
+ <BreadcrumbItem to="#" isActive>
62
+ {akDetails.name}
63
+ </BreadcrumbItem>
64
+ </Breadcrumb>
65
+ </div>
66
+ <Grid>
67
+ <GridItem span={8} className="ak-name-wrapper">
68
+ <Flex justifyContent={{ default: 'jusifyContentSpaceBetween' }} alignItems={{ default: 'alignItemsCenter' }}>
69
+ <FlexItem>
70
+ <Title ouiaId="ak-title" headingLevel="h5" size="2xl" className="ak-name-truncate">
71
+ {akDetails.name}
72
+ </Title>
73
+ </FlexItem>
74
+ <FlexItem>
75
+ <Split hasGutter style={{ display: 'inline-flex' }}>
76
+ <SplitItem>
77
+ <Label>
78
+ {akDetails.usageCount ? akDetails.usageCount : 0}/{akDetails.unlimitedHosts ? __('Unlimited') : akDetails.maxHosts}
79
+ </Label>
80
+ </SplitItem>
81
+ </Split>
82
+ </FlexItem>
83
+ </Flex>
84
+ </GridItem>
85
+ <GridItem offset={8} span={4}>
86
+ <Flex>
87
+ <FlexItem align={{ default: 'align-right' }}>
88
+ <Split>
89
+ <SplitItem>
90
+ <EditModal akDetails={akDetails} akId={akId} />
91
+ </SplitItem>
92
+ <DeleteMenu handleModalToggle={handleModalToggle} akId={akId} />
93
+ </Split>
94
+ </FlexItem>
95
+ </Flex>
96
+ </GridItem>
97
+ </Grid>
98
+ <div className="ak-details-description">
99
+ {akDetails.description ?
100
+ <TextContent>
101
+ <Text ouiaId="ak-description" component={TextVariants.p}>
102
+ {akDetails.description}
103
+ </Text>
104
+ </TextContent> :
105
+ <InactiveText text={__('No description provided')} />
106
+ }
107
+ </div>
108
+ </Panel>
109
+ <DeleteModal isModalOpen={isModalOpen} handleModalToggle={handleModalToggle} akId={akId} />
110
+ </div>
111
+ );
112
+ };
113
+
114
+ export default ActivationKeyDetails;
115
+
116
+
117
+ ActivationKeyDetails.propTypes = {
118
+ match: PropTypes.shape({
119
+ params: PropTypes.shape({
120
+ id: PropTypes.string,
121
+ }),
122
+ }),
123
+ };
124
+
125
+ ActivationKeyDetails.defaultProps = {
126
+ match: {},
127
+ };
@@ -0,0 +1,37 @@
1
+ .ak-details-header {
2
+ margin: 0 24px 16px;
3
+ padding-top: 16px;
4
+ }
5
+
6
+ .ak-details-description {
7
+ padding-top: 16px;
8
+ }
9
+
10
+ .breadcrumb-bar-pf4 {
11
+ margin: 0 0 16px;
12
+ }
13
+
14
+ .breadcrumb-display {
15
+ display: block;
16
+ }
17
+
18
+ .breadcrumb-list {
19
+ display: flex;
20
+ flex-wrap: wrap;
21
+ align-items: center;
22
+ }
23
+
24
+ .ak-name-truncate {
25
+ text-overflow: ellipsis;
26
+ max-width: 100%;
27
+ white-space: nowrap;
28
+ overflow: hidden;
29
+ display: inline-block;
30
+ margin-right: 16px
31
+ }
32
+
33
+ .ak-name-wrapper {
34
+ display: inline-flex;
35
+ max-width: 60%;
36
+ margin-right: 8px;
37
+ }
@@ -0,0 +1,16 @@
1
+ import {
2
+ selectAPIStatus,
3
+ selectAPIError,
4
+ selectAPIResponse,
5
+ } from 'foremanReact/redux/API/APISelectors';
6
+ import { STATUS } from 'foremanReact/constants';
7
+ import { ACTIVATION_KEY } from './ActivationKeyConstants';
8
+
9
+ export const selectAKDetails = state =>
10
+ selectAPIResponse(state, ACTIVATION_KEY) ?? {};
11
+
12
+ export const selectAKDetailsStatus = state =>
13
+ selectAPIStatus(state, ACTIVATION_KEY) ?? STATUS.PENDING;
14
+
15
+ export const selectAKDetailsError = state =>
16
+ selectAPIError(state, ACTIVATION_KEY);
@@ -0,0 +1,117 @@
1
+ import React from 'react';
2
+ import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
3
+ import { assertNockRequest, nockInstance } from '../../../../test-utils/nockWrapper';
4
+ import ActivationKeyDetails from '../ActivationKeyDetails';
5
+ import katelloApi from '../../../../services/api/index';
6
+
7
+ const akDetails = katelloApi.getApiUrl('/activation_keys/1');
8
+
9
+ const baseAKDetails = {
10
+ id: 1,
11
+ name: 'test',
12
+ description: 'test description',
13
+ unlimited_hosts: false,
14
+ usage_count: 1,
15
+ max_hosts: 4,
16
+ };
17
+
18
+ const renderOptions = {
19
+ initialState: {
20
+ // This is the API state that your tests depend on for their data
21
+ // You can cross reference the needed useSelectors from your tested components
22
+ // with the data found within the redux chrome add-on to help determine this fixture data.
23
+ katello: {
24
+ hostDetails: {},
25
+ },
26
+ },
27
+ };
28
+
29
+ test('Makes API call and displays AK details on screen', async (done) => {
30
+ const akScope = nockInstance
31
+ .get(akDetails)
32
+ .reply(200, baseAKDetails);
33
+ // eslint-disable-next-line max-len
34
+ const { getByText, getByRole } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
35
+ await patientlyWaitFor(() => expect(getByRole('heading', { name: 'test' })).toBeInTheDocument());
36
+ expect(getByText('test description')).toBeInTheDocument();
37
+ expect(getByText('1/4')).toBeInTheDocument();
38
+
39
+ assertNockRequest(akScope, done);
40
+ });
41
+
42
+ test('Displays placeholder when description is missing', async (done) => {
43
+ const akScope = nockInstance
44
+ .get(akDetails)
45
+ .reply(
46
+ 200,
47
+ {
48
+ ...baseAKDetails,
49
+ description: '',
50
+ },
51
+ );
52
+ // eslint-disable-next-line max-len
53
+ const { getByText, getByRole } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
54
+ await patientlyWaitFor(() => expect(getByRole('heading', { name: 'test' })).toBeInTheDocument());
55
+ expect(getByText('No description provided')).toBeInTheDocument();
56
+
57
+ assertNockRequest(akScope, done);
58
+ });
59
+
60
+ test('Delete menu appears when toggle is clicked', async (done) => {
61
+ const akScope = nockInstance
62
+ .get(akDetails)
63
+ .reply(200, baseAKDetails);
64
+ // eslint-disable-next-line max-len
65
+ const { getByText, getByLabelText } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
66
+ const deleteToggle = getByLabelText('delete-toggle');
67
+ fireEvent.click(deleteToggle);
68
+ await patientlyWaitFor(() => expect(getByText('Delete')).toBeInTheDocument());
69
+
70
+ assertNockRequest(akScope, done);
71
+ });
72
+
73
+ test('Edit modal appears when button is clicked', async (done) => {
74
+ const akScope = nockInstance
75
+ .get(akDetails)
76
+ .reply(200, baseAKDetails);
77
+ const { getByLabelText, getByText } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
78
+ const editButton = getByLabelText('edit-button');
79
+ fireEvent.click(editButton);
80
+ await patientlyWaitFor(() => expect(getByText('Edit activation key')).toBeInTheDocument());
81
+
82
+ assertNockRequest(akScope, done);
83
+ });
84
+
85
+ test('Page displays 0 when usage count is null', async (done) => {
86
+ const akScope = nockInstance
87
+ .get(akDetails)
88
+ .reply(
89
+ 200,
90
+ {
91
+ ...baseAKDetails,
92
+ usage_count: null,
93
+ },
94
+ );
95
+
96
+ const { getByText, getByRole } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
97
+ await patientlyWaitFor(() => expect(getByRole('heading', { name: 'test' })).toBeInTheDocument());
98
+ expect(getByText('0/4')).toBeInTheDocument();
99
+
100
+ assertNockRequest(akScope, done);
101
+ });
102
+
103
+ test('Delete modal appears when link is clicked', async (done) => {
104
+ const akScope = nockInstance
105
+ .get(akDetails)
106
+ .reply(200, baseAKDetails);
107
+ // eslint-disable-next-line max-len
108
+ const { getByText, getByLabelText } = renderWithRedux(<ActivationKeyDetails match={{ params: { id: '1' } }} />, renderOptions);
109
+ const deleteToggle = getByLabelText('delete-toggle');
110
+ fireEvent.click(deleteToggle);
111
+ await patientlyWaitFor(() => expect(getByText('Delete')).toBeInTheDocument());
112
+ const deleteLink = getByLabelText('delete-link');
113
+ fireEvent.click(deleteLink);
114
+ await patientlyWaitFor(() => expect(getByText('Activation Key will no longer be available for use. This operation cannot be undone.')).toBeInTheDocument());
115
+
116
+ assertNockRequest(akScope, done);
117
+ });
@@ -0,0 +1,77 @@
1
+ import React, {
2
+ useState,
3
+ } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import { Dropdown, DropdownItem, KebabToggle, DropdownPosition, Split, Icon, Text } from '@patternfly/react-core';
6
+ import { UndoIcon, TrashIcon } from '@patternfly/react-icons';
7
+ import { noop } from 'foremanReact/common/helpers';
8
+ import { translate as __ } from 'foremanReact/common/I18n';
9
+
10
+ const DeleteMenu = ({ handleModalToggle, akId }) => {
11
+ const [isOpen, setIsOpen] = useState(false);
12
+ const onToggle = (isOpenValue) => {
13
+ setIsOpen(isOpenValue);
14
+ };
15
+ const onFocus = () => {
16
+ const element = document.getElementById('toggle-kebab');
17
+ element.focus();
18
+ };
19
+ const onSelect = () => {
20
+ setIsOpen(false);
21
+ onFocus();
22
+ };
23
+ const dropdownItems = [
24
+ <DropdownItem
25
+ ouiaId="delete-menu-option"
26
+ aria-label="delete-link"
27
+ key="delete-link"
28
+ component="button"
29
+ onClick={handleModalToggle}
30
+ >
31
+ <Split hasGutter>
32
+ <Icon>
33
+ <TrashIcon />
34
+ </Icon>
35
+ <Text ouiaId="delete-text">
36
+ {__('Delete')}
37
+ </Text>
38
+ </Split>
39
+ </DropdownItem>,
40
+ <DropdownItem
41
+ ouiaId="ak-legacy-ui"
42
+ key="ak-legacy-ui-link"
43
+ href={`../../../activation_keys/${akId}`}
44
+ >
45
+ <Split hasGutter>
46
+ <Icon>
47
+ <UndoIcon />
48
+ </Icon>
49
+ <Text ouiaId="delete-text">
50
+ {__('Legacy UI')}
51
+ </Text>
52
+ </Split>
53
+ </DropdownItem>];
54
+ return (
55
+ <Dropdown
56
+ ouiaId="dekete-action"
57
+ onSelect={onSelect}
58
+ position={DropdownPosition.right}
59
+ toggle={<KebabToggle id="toggle-kebab" aria-label="delete-toggle" onToggle={onToggle} />}
60
+ isOpen={isOpen}
61
+ isPlain
62
+ dropdownItems={dropdownItems}
63
+ />
64
+ );
65
+ };
66
+
67
+ DeleteMenu.propTypes = {
68
+ handleModalToggle: PropTypes.func,
69
+ akId: PropTypes.string.isRequired,
70
+ };
71
+
72
+ DeleteMenu.defaultProps = {
73
+ handleModalToggle: noop,
74
+ };
75
+
76
+ export default DeleteMenu;
77
+