katello 4.4.2.2 → 4.5.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 (444) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +5 -1
  3. data/app/controllers/katello/api/v2/alternate_content_sources_controller.rb +98 -0
  4. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +39 -3
  5. data/app/controllers/katello/api/v2/content_exports_controller.rb +19 -0
  6. data/app/controllers/katello/api/v2/content_imports_controller.rb +13 -16
  7. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +0 -12
  8. data/app/controllers/katello/api/v2/content_views_controller.rb +13 -0
  9. data/app/controllers/katello/api/v2/environments_controller.rb +1 -1
  10. data/app/controllers/katello/api/v2/host_module_streams_controller.rb +8 -2
  11. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +25 -3
  12. data/app/controllers/katello/api/v2/organizations_controller.rb +4 -2
  13. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +1 -1
  14. data/app/controllers/katello/api/v2/repositories_controller.rb +9 -3
  15. data/app/controllers/katello/api/v2/repository_sets_controller.rb +40 -7
  16. data/app/controllers/katello/api/v2/subscriptions_controller.rb +2 -2
  17. data/app/controllers/katello/concerns/api/v2/hosts_controller_extensions.rb +1 -1
  18. data/app/helpers/katello/concerns/smart_proxy_helper_extensions.rb +4 -0
  19. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +21 -3
  20. data/app/lib/actions/katello/alternate_content_source/create.rb +24 -0
  21. data/app/lib/actions/katello/alternate_content_source/destroy.rb +27 -0
  22. data/app/lib/actions/katello/alternate_content_source/update.rb +41 -0
  23. data/app/lib/actions/katello/cdn_configuration/update.rb +2 -2
  24. data/app/lib/actions/katello/content_view/destroy.rb +2 -1
  25. data/app/lib/actions/katello/content_view/incremental_updates.rb +7 -3
  26. data/app/lib/actions/katello/content_view/publish.rb +7 -9
  27. data/app/lib/actions/katello/content_view_version/auto_create_products.rb +4 -4
  28. data/app/lib/actions/katello/content_view_version/auto_create_redhat_repositories.rb +6 -4
  29. data/app/lib/actions/katello/content_view_version/auto_create_repositories.rb +6 -4
  30. data/app/lib/actions/katello/content_view_version/import.rb +25 -22
  31. data/app/lib/actions/katello/content_view_version/import_library.rb +0 -1
  32. data/app/lib/actions/katello/content_view_version/import_repository.rb +21 -0
  33. data/app/lib/actions/katello/content_view_version/incremental_update.rb +85 -93
  34. data/app/lib/actions/katello/content_view_version/reset_content_view_repositories_from_metadata.rb +2 -2
  35. data/app/lib/actions/katello/product/content_create.rb +10 -8
  36. data/app/lib/actions/katello/repository/destroy.rb +36 -12
  37. data/app/lib/actions/katello/repository_set/disable_repository.rb +8 -3
  38. data/app/lib/actions/pulp3/alternate_content_source/create.rb +20 -0
  39. data/app/lib/actions/pulp3/alternate_content_source/create_remote.rb +20 -0
  40. data/app/lib/actions/pulp3/alternate_content_source/delete.rb +16 -0
  41. data/app/lib/actions/pulp3/alternate_content_source/delete_remote.rb +16 -0
  42. data/app/lib/actions/pulp3/alternate_content_source/update.rb +16 -0
  43. data/app/lib/actions/pulp3/alternate_content_source/update_remote.rb +17 -0
  44. data/app/lib/actions/pulp3/content_view_version/{import.rb → create_import.rb} +5 -5
  45. data/app/lib/actions/pulp3/content_view_version/create_importer.rb +4 -3
  46. data/app/lib/actions/pulp3/content_view_version/destroy_importer.rb +12 -1
  47. data/app/lib/actions/pulp3/orchestration/alternate_content_source/create.rb +18 -0
  48. data/app/lib/actions/pulp3/orchestration/alternate_content_source/delete.rb +23 -0
  49. data/app/lib/actions/pulp3/orchestration/alternate_content_source/update.rb +18 -0
  50. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +1 -1
  51. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +51 -0
  52. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +5 -2
  53. data/app/lib/actions/pulp3/repository/refresh_distribution.rb +4 -1
  54. data/app/lib/actions/pulp3/repository/save_distribution_references.rb +2 -0
  55. data/app/lib/katello/api/v2/error_handling.rb +1 -0
  56. data/app/lib/katello/resources/cdn/katello_cdn.rb +3 -1
  57. data/app/lib/katello/util/errata.rb +2 -3
  58. data/app/lib/katello/validators/alternate_content_source_path_validator.rb +29 -0
  59. data/app/lib/katello/validators/content_default_http_proxy_setting_validator.rb +12 -0
  60. data/app/lib/katello/validators/content_view_environment_validator.rb +10 -5
  61. data/app/models/katello/alternate_content_source.rb +66 -0
  62. data/app/models/katello/authorization/alternate_content_source.rb +33 -0
  63. data/app/models/katello/authorization/repository.rb +3 -3
  64. data/app/models/katello/candlepin/repository_mapper.rb +13 -6
  65. data/app/models/katello/cdn_configuration.rb +15 -15
  66. data/app/models/katello/concerns/content_facet_host_extensions.rb +25 -0
  67. data/app/models/katello/concerns/host_managed_extensions.rb +7 -5
  68. data/app/models/katello/concerns/http_proxy_extensions.rb +14 -0
  69. data/app/models/katello/concerns/organization_extensions.rb +4 -2
  70. data/app/models/katello/concerns/setting_extensions.rb +14 -0
  71. data/app/models/katello/concerns/smart_proxy_extensions.rb +2 -1
  72. data/app/models/katello/content.rb +1 -0
  73. data/app/models/katello/content_credential.rb +6 -0
  74. data/app/models/katello/content_override.rb +7 -3
  75. data/app/models/katello/content_view.rb +33 -2
  76. data/app/models/katello/content_view_erratum_filter.rb +26 -12
  77. data/app/models/katello/content_view_filter.rb +4 -0
  78. data/app/models/katello/content_view_version.rb +12 -0
  79. data/app/models/katello/content_view_version_export_history.rb +3 -1
  80. data/app/models/katello/erratum.rb +9 -5
  81. data/app/models/katello/events/delete_latest_content_view_version.rb +40 -0
  82. data/app/models/katello/host/content_facet.rb +14 -0
  83. data/app/models/katello/host_available_module_stream.rb +12 -0
  84. data/app/models/katello/product_content.rb +1 -0
  85. data/app/models/katello/purpose_sla_status.rb +1 -1
  86. data/app/models/katello/purpose_status.rb +2 -2
  87. data/app/models/katello/repository.rb +7 -4
  88. data/app/models/katello/root_repository.rb +1 -1
  89. data/app/models/katello/smart_proxy_alternate_content_source.rb +8 -0
  90. data/app/models/katello/sync_plan.rb +1 -1
  91. data/app/presenters/katello/product_content_presenter.rb +15 -0
  92. data/app/services/katello/applicable_host_queue.rb +1 -1
  93. data/app/services/katello/content_unit_indexer.rb +2 -1
  94. data/app/services/katello/product_content_finder.rb +12 -2
  95. data/app/services/katello/pulp3/alternate_content_source.rb +117 -0
  96. data/app/services/katello/pulp3/api/file.rb +8 -0
  97. data/app/services/katello/pulp3/api/yum.rb +8 -0
  98. data/app/services/katello/pulp3/content_view_version/export.rb +27 -5
  99. data/app/services/katello/pulp3/content_view_version/import.rb +97 -71
  100. data/app/services/katello/pulp3/content_view_version/import_export_common.rb +4 -4
  101. data/app/services/katello/pulp3/content_view_version/import_gpg_keys.rb +13 -11
  102. data/app/services/katello/pulp3/content_view_version/import_validator.rb +67 -72
  103. data/app/services/katello/pulp3/content_view_version/importable_products.rb +40 -24
  104. data/app/services/katello/pulp3/content_view_version/importable_repositories.rb +88 -39
  105. data/app/services/katello/pulp3/content_view_version/metadata_generator.rb +2 -2
  106. data/app/services/katello/pulp3/content_view_version/metadata_map.rb +117 -0
  107. data/app/services/katello/pulp3/pulp_content_unit.rb +6 -1
  108. data/app/services/katello/pulp3/repository/yum.rb +70 -12
  109. data/app/services/katello/pulp3/repository.rb +7 -91
  110. data/app/services/katello/pulp3/service_common.rb +66 -0
  111. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +4 -1
  112. data/app/services/katello/ui_notifications/content_view/delete_latest_version_failure.rb +22 -0
  113. data/app/views/foreman/job_templates/change_content_source.erb +1 -1
  114. data/app/views/foreman/job_templates/install_errata.erb +5 -5
  115. data/app/views/foreman/job_templates/install_errata_by_search_query.erb +7 -6
  116. data/app/views/foreman/job_templates/install_group.erb +4 -4
  117. data/app/views/foreman/job_templates/install_package.erb +4 -4
  118. data/app/views/foreman/job_templates/install_packages_by_search_query.erb +3 -3
  119. data/app/views/foreman/job_templates/remove_group.erb +4 -4
  120. data/app/views/foreman/job_templates/remove_package.erb +4 -4
  121. data/app/views/foreman/job_templates/remove_packages_by_search_query.erb +3 -3
  122. data/app/views/foreman/job_templates/resolve_traces.erb +2 -2
  123. data/app/views/foreman/job_templates/restart_services.erb +3 -3
  124. data/app/views/foreman/job_templates/update_group.erb +4 -4
  125. data/app/views/foreman/job_templates/update_package.erb +4 -4
  126. data/app/views/foreman/job_templates/update_packages_by_search_query.erb +3 -3
  127. data/app/views/katello/api/v2/alternate_content_sources/base.json.rabl +15 -0
  128. data/app/views/katello/api/v2/alternate_content_sources/index.json.rabl +7 -0
  129. data/app/views/katello/api/v2/alternate_content_sources/show.json.rabl +3 -0
  130. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +1 -1
  131. data/app/views/katello/api/v2/content_view_version_export_histories/show.json.rabl +2 -3
  132. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +1 -1
  133. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  134. data/app/views/katello/api/v2/environments/show.json.rabl +2 -0
  135. data/app/views/katello/api/v2/errata/_counts.json.rabl +2 -2
  136. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +2 -2
  137. data/app/views/katello/api/v2/hosts/host_collections.json.rabl +1 -1
  138. data/app/views/katello/api/v2/organizations/show.json.rabl +7 -1
  139. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -1
  140. data/app/views/katello/sync_management/_repo.html.erb +8 -29
  141. data/config/routes/api/v2.rb +7 -0
  142. data/db/migrate/20150930183738_migrate_content_hosts.rb +0 -399
  143. data/db/migrate/20171025163149_remove_use_pulp_oauth_setting.rb +1 -1
  144. data/db/migrate/20171114150937_cleanup_installed_packages.rb +1 -1
  145. data/db/migrate/20180402160223_clean_up_force_post_sync_action_setting.rb +1 -1
  146. data/db/migrate/20211129200124_remove_dependency_solving_algorithm_setting.rb +1 -1
  147. data/db/migrate/20211220185935_clean_duplicate_content_units.rb +10 -12
  148. data/db/migrate/20220110223754_update_disconnected_settings.rb +5 -5
  149. data/db/migrate/20220117151612_add_alternate_content_sources.rb +48 -0
  150. data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +9 -4
  151. data/db/migrate/20220209203251_add_generated_for_to_content_views.rb +13 -0
  152. data/db/migrate/20220209205137_expand_sync_timeout_settings.rb +7 -7
  153. data/db/migrate/20220228173251_remove_drpm_from_ignorable_content.rb +12 -0
  154. data/db/migrate/20220404190836_delete_old_setting_data.rb +9 -0
  155. data/db/migrate/20220405220616_update_cdn_configuration_type.rb +11 -0
  156. data/db/migrate/20220419193414_content_settings_to_dsl_category.rb +5 -0
  157. data/db/seeds.d/110-content-view-autopublish.rb +13 -0
  158. data/db/seeds.d/150-module_job_templates.rb +1 -1
  159. data/engines/bastion/README.md +1 -0
  160. data/engines/bastion/app/assets/javascripts/bastion/components/bst-modal.directive.js +1 -0
  161. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -0
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-details.controller.js +4 -2
  163. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +10 -5
  164. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +1 -0
  165. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +1 -0
  166. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-traces.controller.js +1 -0
  167. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-actions.html +1 -1
  168. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-applicable.html +1 -1
  169. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +8 -0
  170. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +4 -2
  171. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +2 -2
  172. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/content.service.js +10 -0
  173. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-deb-repositories.html +26 -0
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-debs.html +27 -0
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.controller.js +1 -0
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.routes.js +22 -0
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/views/environments.html +13 -7
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +63 -17
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +7 -8
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +10 -1
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +21 -3
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -9
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +7 -5
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -1
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery-create.controller.js +1 -1
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.routes.js +1 -0
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +6 -1
  189. data/lib/katello/engine.rb +1 -5
  190. data/lib/katello/permission_creator.rb +32 -4
  191. data/lib/katello/plugin.rb +378 -4
  192. data/lib/katello/tasks/reset.rake.bak +67 -0
  193. data/lib/katello/tasks/update_content_default_http_proxy.rake +2 -3
  194. data/lib/katello/version.rb +1 -1
  195. data/locale/action_names.rb +47 -41
  196. data/locale/bn/LC_MESSAGES/katello.mo +0 -0
  197. data/locale/bn/katello.po +820 -106
  198. data/locale/bn/katello.po.time_stamp +0 -0
  199. data/locale/cs/LC_MESSAGES/katello.mo +0 -0
  200. data/locale/cs/katello.po +818 -104
  201. data/locale/cs/katello.po.time_stamp +0 -0
  202. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  203. data/locale/de/katello.po +893 -179
  204. data/locale/de/katello.po.time_stamp +0 -0
  205. data/locale/en/LC_MESSAGES/katello.mo +0 -0
  206. data/locale/en/katello.po +817 -103
  207. data/locale/en/katello.po.time_stamp +0 -0
  208. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  209. data/locale/es/katello.po +882 -168
  210. data/locale/es/katello.po.time_stamp +0 -0
  211. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  212. data/locale/fr/katello.po +1219 -505
  213. data/locale/fr/katello.po.time_stamp +0 -0
  214. data/locale/gu/LC_MESSAGES/katello.mo +0 -0
  215. data/locale/gu/katello.po +826 -112
  216. data/locale/gu/katello.po.time_stamp +0 -0
  217. data/locale/hi/LC_MESSAGES/katello.mo +0 -0
  218. data/locale/hi/katello.po +826 -112
  219. data/locale/hi/katello.po.time_stamp +0 -0
  220. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  221. data/locale/it/katello.po +863 -148
  222. data/locale/it/katello.po.time_stamp +0 -0
  223. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  224. data/locale/ja/katello.po +1216 -499
  225. data/locale/ja/katello.po.time_stamp +0 -0
  226. data/locale/katello.pot +3847 -2507
  227. data/locale/kn/LC_MESSAGES/katello.mo +0 -0
  228. data/locale/kn/katello.po +826 -112
  229. data/locale/kn/katello.po.time_stamp +0 -0
  230. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  231. data/locale/ko/katello.po +912 -198
  232. data/locale/ko/katello.po.time_stamp +0 -0
  233. data/locale/mr/LC_MESSAGES/katello.mo +0 -0
  234. data/locale/mr/katello.po +826 -112
  235. data/locale/mr/katello.po.time_stamp +0 -0
  236. data/locale/or/LC_MESSAGES/katello.mo +0 -0
  237. data/locale/or/katello.po +826 -112
  238. data/locale/or/katello.po.time_stamp +0 -0
  239. data/locale/pa/LC_MESSAGES/katello.mo +0 -0
  240. data/locale/pa/katello.po +826 -112
  241. data/locale/pa/katello.po.time_stamp +0 -0
  242. data/locale/pt/LC_MESSAGES/katello.mo +0 -0
  243. data/locale/pt/katello.po +817 -103
  244. data/locale/pt/katello.po.time_stamp +0 -0
  245. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  246. data/locale/pt_BR/katello.po +879 -165
  247. data/locale/pt_BR/katello.po.time_stamp +0 -0
  248. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  249. data/locale/ru/katello.po +927 -213
  250. data/locale/ru/katello.po.time_stamp +0 -0
  251. data/locale/ta/LC_MESSAGES/katello.mo +0 -0
  252. data/locale/ta/katello.po +820 -106
  253. data/locale/ta/katello.po.time_stamp +0 -0
  254. data/locale/te/LC_MESSAGES/katello.mo +0 -0
  255. data/locale/te/katello.po +826 -112
  256. data/locale/te/katello.po.time_stamp +0 -0
  257. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  258. data/locale/zh_CN/katello.po +1202 -486
  259. data/locale/zh_CN/katello.po.time_stamp +0 -0
  260. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  261. data/locale/zh_TW/katello.po +856 -142
  262. data/locale/zh_TW/katello.po.time_stamp +0 -0
  263. data/webpack/components/EditableTextInput/EditableTextInput.js +20 -5
  264. data/webpack/components/Errata/index.js +38 -8
  265. data/webpack/components/Packages/index.js +1 -4
  266. data/webpack/components/Search/Search.js +18 -3
  267. data/webpack/components/SelectAllCheckbox/index.js +1 -0
  268. data/webpack/components/SelectableDropdown/SelectableDropdown.js +4 -2
  269. data/webpack/components/Table/EmptyStateMessage.js +21 -7
  270. data/webpack/components/Table/MainTable.js +29 -4
  271. data/webpack/components/Table/TableHooks.js +63 -19
  272. data/webpack/components/Table/TableWrapper.js +4 -2
  273. data/webpack/components/Table/components/SortableColumnHeaders.js +19 -0
  274. data/webpack/components/Table/components/TranslatedPlural.js +57 -0
  275. data/webpack/components/TypeAhead/TypeAhead.js +8 -0
  276. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +13 -11
  277. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +5 -2
  278. data/webpack/components/extensions/HostDetails/ActionsBar/index.js +27 -0
  279. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +256 -0
  280. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ContentViewDetailsCard.js +202 -0
  281. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/HostContentViewActions.js +19 -0
  282. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants.js +2 -0
  283. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/changeHostCVModal.test.js +131 -0
  284. data/webpack/components/extensions/HostDetails/Cards/{__tests__ → ContentViewDetailsCard/__tests__}/contentViewDetailsCard.test.js +22 -0
  285. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/contentViews.fixtures.json +443 -0
  286. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/envPaths.fixtures.json +320 -0
  287. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +57 -33
  288. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.scss +3 -0
  289. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsActions.js +30 -0
  290. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsCard.js +187 -0
  291. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsConstants.js +7 -0
  292. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +227 -0
  293. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsSelectors.js +18 -0
  294. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/availableHostCollections.fixtures.json +106 -0
  295. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/hostCollectionsCard.test.js +110 -0
  296. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/hostCollectionsModal.test.js +235 -0
  297. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/removableHostCollections.fixtures.json +45 -0
  298. data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +33 -8
  299. data/webpack/components/extensions/HostDetails/DetailsTabCards/InstalledProductsCard.js +44 -0
  300. data/webpack/components/extensions/HostDetails/DetailsTabCards/RegistrationCard.js +107 -0
  301. data/webpack/components/extensions/HostDetails/DetailsTabCards/SystemPropertiesCardExtensions.js +38 -0
  302. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +62 -39
  303. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataActions.js +1 -7
  304. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsActions.js +1 -3
  305. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsConstants.js +28 -0
  306. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +486 -116
  307. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/moduleStreamsTab.test.js +147 -1
  308. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/modules.fixtures.json +6 -3
  309. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +1 -7
  310. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +2 -1
  311. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +48 -19
  312. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +35 -47
  313. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +1 -0
  314. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsActions.js +33 -54
  315. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsConstants.js +20 -0
  316. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +269 -132
  317. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesTab.js +47 -11
  318. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +30 -42
  319. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +36 -1
  320. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +94 -46
  321. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +18 -2
  322. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +6 -0
  323. data/webpack/containers/Application/config.js +5 -0
  324. data/webpack/global_index.js +30 -7
  325. data/webpack/global_test_setup.js +13 -0
  326. data/webpack/redux/actions/RedHatRepositories/enabled.js +2 -1
  327. data/webpack/redux/actions/RedHatRepositories/helpers.js +9 -8
  328. data/webpack/scenes/AlternateContentSources/ACSActions.js +53 -0
  329. data/webpack/scenes/AlternateContentSources/ACSConstants.js +4 -0
  330. data/webpack/scenes/AlternateContentSources/ACSIndexPage.js +23 -0
  331. data/webpack/scenes/AlternateContentSources/ACSSelectors.js +15 -0
  332. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +152 -0
  333. data/webpack/scenes/AlternateContentSources/MainTable/__tests__/acsIndex.fixtures.json +91 -0
  334. data/webpack/scenes/AlternateContentSources/MainTable/__tests__/acsTable.test.js +67 -0
  335. data/webpack/scenes/AlternateContentSources/index.js +4 -0
  336. data/webpack/scenes/Content/Details/ContentRepositories.js +1 -0
  337. data/webpack/scenes/Content/Table/ContentTable.js +1 -0
  338. data/webpack/scenes/ContentViews/ContentViewsActions.js +6 -2
  339. data/webpack/scenes/ContentViews/ContentViewsConstants.js +11 -3
  340. data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +2 -1
  341. data/webpack/scenes/ContentViews/Create/ContentViewFormComponents.js +10 -1
  342. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +4 -3
  343. data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +1 -1
  344. data/webpack/scenes/ContentViews/Delete/ContentViewDeleteWizard.js +7 -5
  345. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionFinish.js +29 -21
  346. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +15 -8
  347. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +3 -3
  348. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +4 -4
  349. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +3 -1
  350. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +4 -4
  351. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +34 -8
  352. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +33 -29
  353. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +130 -79
  354. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +17 -3
  355. data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +2 -1
  356. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +2 -1
  357. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +6 -1
  358. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +41 -21
  359. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +38 -20
  360. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +2 -0
  361. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +8 -1
  362. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +9 -1
  363. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +2 -1
  364. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVRpmMatchContentModal.js +1 -0
  365. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +27 -12
  366. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +39 -17
  367. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +27 -10
  368. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +46 -23
  369. data/webpack/scenes/ContentViews/Details/Histories/ContentViewHistories.js +3 -2
  370. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +5 -2
  371. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +161 -108
  372. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +7 -7
  373. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewRepoAdd.fixture.json +1 -0
  374. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/ActionSummary.js +58 -0
  375. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteContextWrapper.js +45 -0
  376. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteHelpers.js +30 -0
  377. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteModal.js +56 -0
  378. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ConfirmBulkDelete.js +126 -0
  379. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/FinishBulkDelete.js +61 -0
  380. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignActivationKeys.js +196 -0
  381. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignHosts.js +220 -0
  382. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReviewEnvironments.js +104 -0
  383. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/BulkDeleteModal.test.js +122 -0
  384. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/BulkDeleteVersions.fixtures.json +600 -0
  385. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/contentView.fixtures.json +1504 -0
  386. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/contentViewVersion.fixtures.json +936 -0
  387. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/environmentPaths.fixtures.json +261 -0
  388. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/hosts.fixtures.json +163 -0
  389. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/bulkDeleteSteps.js +79 -0
  390. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +192 -167
  391. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveCVVersionWizard.js +2 -5
  392. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionDeleteFinish.js +38 -53
  393. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionRemoveReview.js +1 -1
  394. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -12
  395. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -0
  396. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -0
  397. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +1 -0
  398. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +8 -20
  399. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +23 -13
  400. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +3 -0
  401. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.fixtures.json +4 -4
  402. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +0 -3
  403. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetailsEmpty.test.js +4 -4
  404. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +12 -14
  405. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetails.fixtures.json +1 -0
  406. data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +96 -117
  407. data/webpack/scenes/ContentViews/Publish/PublishContentViewWizard.js +13 -19
  408. data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +9 -20
  409. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +165 -148
  410. data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +2 -0
  411. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +4 -4
  412. data/webpack/scenes/ContentViews/components/ContentViewIcon.js +14 -3
  413. data/webpack/scenes/ContentViews/components/ContentViewsCounter.js +1 -1
  414. data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +4 -3
  415. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +9 -5
  416. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.scss +6 -1
  417. data/webpack/scenes/ContentViews/components/TaskPresenter/TaskPresenter.js +40 -35
  418. data/webpack/scenes/ContentViews/expansions/DetailsExpansion.js +2 -2
  419. data/webpack/scenes/ContentViews/expansions/RelatedCompositeContentViewsModal.js +1 -1
  420. data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +4 -4
  421. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsModal.test.js +1 -1
  422. data/webpack/scenes/ContentViews/helpers.js +3 -0
  423. data/webpack/scenes/Hosts/ChangeContentSource/helpers.js +5 -0
  424. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +3 -3
  425. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepository.js +2 -1
  426. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/__tests__/EnabledRepository.test.js +2 -0
  427. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnConfigurationConstants.js +3 -3
  428. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +2 -0
  429. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/{AirGappedTypeForm.js → ExportSyncForm.js} +7 -6
  430. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/{UpstreamServerTypeForm.js → NetworkSyncForm.js} +15 -7
  431. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/{AirGappedTypeForm.test.js → ExportSyncForm.test.js} +4 -4
  432. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/{UpstreamServerTypeForm.test.js → NetworkSyncForm.test.js} +8 -8
  433. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/index.js +11 -11
  434. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  435. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +8 -7
  436. data/webpack/scenes/Tasks/TaskActions.js +6 -0
  437. data/webpack/scenes/Tasks/TaskSelectors.js +11 -0
  438. data/webpack/scenes/Tasks/helpers.js +33 -5
  439. data/webpack/utils/helpers.js +2 -0
  440. metadata +158 -40
  441. data/app/models/setting/content.rb +0 -201
  442. data/webpack/components/Table/__test__/useBulkSelect.test.js +0 -99
  443. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +0 -96
  444. data/webpack/scenes/ContentViews/Details/DetailsContainer.js +0 -36
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import { renderWithRedux, patientlyWaitFor } from 'react-testing-lib-wrapper';
3
+
4
+ import nock, { nockInstance, assertNockRequest, mockAutocomplete, mockSetting } from '../../../../test-utils/nockWrapper';
5
+ import api from '../../../../services/api';
6
+ import ACSTable from '../ACSTable';
7
+ import acsData from './acsIndex.fixtures.json';
8
+
9
+ const acsURL = api.getApiUrl('/alternate_content_sources');
10
+ const autocompleteUrl = '/alternate_content_sources/auto_complete_search';
11
+
12
+ let firstAcs;
13
+ let searchDelayScope;
14
+ let autoSearchScope;
15
+
16
+ beforeEach(() => {
17
+ const { results } = acsData;
18
+ [firstAcs] = results;
19
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
20
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
21
+ });
22
+
23
+ afterEach(() => {
24
+ nock.cleanAll();
25
+ assertNockRequest(searchDelayScope);
26
+ assertNockRequest(autoSearchScope);
27
+ });
28
+
29
+ test('Can call API and show ACS on page load', async (done) => {
30
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
31
+ const scope = nockInstance
32
+ .get(acsURL)
33
+ .query(true)
34
+ .reply(200, acsData);
35
+
36
+ const { getByText, queryByText } = renderWithRedux(<ACSTable />);
37
+
38
+ // Nothing will show at first, page is loading
39
+ expect(queryByText(firstAcs.name)).toBeNull();
40
+ // Assert that the ACS name is now showing on the screen, but wait for it to appear.
41
+ await patientlyWaitFor(() => expect(getByText(firstAcs.name)).toBeInTheDocument());
42
+ assertNockRequest(autocompleteScope);
43
+ assertNockRequest(scope, done);
44
+ });
45
+
46
+ test('Can handle no ACS being present', async (done) => {
47
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
48
+
49
+ const noResults = {
50
+ total: 0,
51
+ subtotal: 0,
52
+ page: 1,
53
+ per_page: 20,
54
+ results: [],
55
+ };
56
+ const scope = nockInstance
57
+ .get(acsURL)
58
+ .query(true)
59
+ .reply(200, noResults);
60
+
61
+ const { queryByText } = renderWithRedux(<ACSTable />);
62
+
63
+ expect(queryByText(firstAcs.name)).toBeNull();
64
+ await patientlyWaitFor(() => expect(queryByText("You currently don't have any alternate content sources.")).toBeInTheDocument());
65
+ assertNockRequest(autocompleteScope);
66
+ assertNockRequest(scope, done);
67
+ });
@@ -0,0 +1,4 @@
1
+ import { withRouter } from 'react-router-dom';
2
+ import ACSIndexPage from './ACSIndexPage';
3
+
4
+ export default withRouter(ACSIndexPage);
@@ -42,6 +42,7 @@ const ContentRepositories = ({ contentType, id, tabKey }) => {
42
42
  emptySearchBody,
43
43
  emptyContentBody,
44
44
  }}
45
+ ouiaId="content-repositories-table"
45
46
  variant={TableVariant.compact}
46
47
  autocompleteEndpoint="/repositories/auto_complete_search"
47
48
  fetchItems={useCallback(
@@ -30,6 +30,7 @@ const ContentTable = ({
30
30
  error,
31
31
  status,
32
32
  }}
33
+ ouiaId="content-table"
33
34
  key={selectedContentType}
34
35
  variant={TableVariant.compact}
35
36
  autocompleteEndpoint={`/${contentTypes[selectedContentType][1]}/auto_complete_search`}
@@ -54,12 +54,16 @@ export const copyContentView = params => post({
54
54
  errorToast: error => cvErrorToast(error),
55
55
  });
56
56
 
57
- export const publishContentView = params => post({
57
+ export const publishContentView = (params, handleSuccess, handleError) => post({
58
58
  type: API_OPERATIONS.POST,
59
59
  key: cvVersionPublishKey(params.id, params.versionCount),
60
60
  url: api.getApiUrl(`/content_views/${params.id}/publish`),
61
61
  params,
62
- handleSuccess: response => renderTaskStartedToast(response.data),
62
+ handleSuccess: (response) => {
63
+ if (handleSuccess) handleSuccess(response);
64
+ return renderTaskStartedToast(response.data);
65
+ },
66
+ handleError,
63
67
  errorToast: error => cvErrorToast(error),
64
68
  });
65
69
 
@@ -43,10 +43,12 @@ export const cvDetailsHistoryKey = cvId => `${CONTENT_VIEWS_KEY}_HISTORIES_${cvI
43
43
  export const cvFilterRulesKey = filterId => `CONTENT_VIEW_FILTER_${filterId}_RULES`;
44
44
  export const cvDetailsComponentKey = cvId => `${CONTENT_VIEWS_KEY}_COMPONENTS_${cvId}`;
45
45
  export const cvDetailsVersionKey = cvId => `${CONTENT_VIEWS_KEY}_VERSIONS_${cvId}`;
46
+ export const bulkRemoveVersionKey = cvId => `BULK_REMOVE_CV_VERSION_${cvId}`;
46
47
  export const cvRemoveVersionKey = (versionId, versionEnvironments) => `REMOVE_CV_VERSION_${versionId}_${versionEnvironments.length}`;
47
48
  export const cvVersionPromoteKey = (versionId, environmentIds) => `PROMOTE_CONTENT_VIEW_VERSION_${versionId}_${environmentIds.length}`;
48
49
  export const cvVersionDetailsKey = (cvId, versionId) => `CONTENT_VIEW_VERSION_DETAILS_${cvId}_${versionId}`;
49
50
  export const cvVersionPublishKey = (cvId, versionCount) => `${PUBLISH_CONTENT_VIEW_KEY}_${cvId}_VERSION_${versionCount}`;
51
+ export const cvVersionTaskPollingKey = cvId => `CONTENT_VIEW_VERSION_POLLING_${cvId}`;
50
52
  export const cvAddComponentKey = cvId => `${CONTENT_VIEWS_KEY}_ADD_COMPONENT_${cvId}`;
51
53
  export const cvRemoveComponentKey = cvId => `${CONTENT_VIEWS_KEY}_REMOVE_COMPONENT_${cvId}`;
52
54
 
@@ -56,9 +58,15 @@ export const addComponentSuccessMessage = component => (component ? __('Updated
56
58
 
57
59
 
58
60
  // Repo added to content view status display and key
59
- export const ADDED = 'Added';
60
- export const NOT_ADDED = 'Not added';
61
- export const ALL_STATUSES = 'All';
61
+ export const ADDED = __('Added');
62
+ export const NOT_ADDED = __('Not added');
63
+ export const ALL_STATUSES = __('All');
64
+
65
+ export const STATUS_TRANSLATIONS_ENUM = {
66
+ [ADDED]: 'Added',
67
+ [NOT_ADDED]: 'Not added',
68
+ [ALL_STATUSES]: 'All',
69
+ };
62
70
 
63
71
  export const REPOSITORY_TYPES = 'REPOSITORY_TYPES';
64
72
  export const FILTER_TYPES = ['rpm', 'package_group', 'erratum_date', 'erratum_id', 'docker', 'modulemd'];
@@ -59,6 +59,7 @@ const CopyContentViewForm = ({ cvId, setModalOpen }) => {
59
59
  </FormGroup>
60
60
  <ActionGroup>
61
61
  <Button
62
+ ouiaId="copy-form-submit-button"
62
63
  aria-label="copy_content_view"
63
64
  variant="primary"
64
65
  isDisabled={!name?.length || saving}
@@ -66,7 +67,7 @@ const CopyContentViewForm = ({ cvId, setModalOpen }) => {
66
67
  >
67
68
  {__('Copy content view')}
68
69
  </Button>
69
- <Button variant="link" onClick={() => setModalOpen(false)}>{__('Cancel')}</Button>
70
+ <Button ouiaId="copy-form-cancel" variant="link" onClick={() => setModalOpen(false)}>{__('Cancel')}</Button>
70
71
  </ActionGroup>
71
72
  </Form >
72
73
  );
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { translate as __ } from 'foremanReact/common/I18n';
3
3
  import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
4
4
  import { Tooltip, TooltipPosition, Flex, FlexItem } from '@patternfly/react-core';
5
- import { autoPublishHelpText, dependenciesHelpText, importOnlyHelpText } from '../helpers';
5
+ import { autoPublishHelpText, dependenciesHelpText, importOnlyHelpText, generatedContentViewHelpText } from '../helpers';
6
6
  import ContentViewIcon from '../components/ContentViewIcon';
7
7
 
8
8
  const HelpToolTip = tooltip => (
@@ -56,3 +56,12 @@ export const LabelImportOnly = () => (
56
56
  </FlexItem>
57
57
  </Flex>
58
58
  );
59
+
60
+ export const LabelGenerated = () => (
61
+ <Flex>
62
+ <FlexItem spacer={{ default: 'spacerSm' }}>{__('Generated')}</FlexItem>
63
+ <FlexItem>
64
+ {HelpToolTip(generatedContentViewHelpText)}
65
+ </FlexItem>
66
+ </Flex>
67
+ );
@@ -115,7 +115,7 @@ const CreateContentViewForm = ({ setModalOpen }) => {
115
115
  aria-label="component_tile"
116
116
  icon={<ContentViewIcon composite={false} />}
117
117
  id="component"
118
- title={__('Content view')}
118
+ title={__('Component content view')}
119
119
  onClick={() => { setComponent(true); setComposite(false); }}
120
120
  isSelected={component}
121
121
  >
@@ -133,7 +133,7 @@ const CreateContentViewForm = ({ setModalOpen }) => {
133
133
  onClick={() => { setComposite(true); setComponent(false); }}
134
134
  isSelected={composite}
135
135
  >
136
- {__('Consisting of multiple content views')}
136
+ {__('Consisting of multiple component content views')}
137
137
  </Tile>
138
138
  </GridItem>
139
139
  </Grid>
@@ -170,6 +170,7 @@ const CreateContentViewForm = ({ setModalOpen }) => {
170
170
  </FormGroup>}
171
171
  <ActionGroup>
172
172
  <Button
173
+ ouiaId="create-content-view-form-submit"
173
174
  aria-label="create_content_view"
174
175
  variant="primary"
175
176
  isDisabled={submitDisabled}
@@ -177,7 +178,7 @@ const CreateContentViewForm = ({ setModalOpen }) => {
177
178
  >
178
179
  {__('Create content view')}
179
180
  </Button>
180
- <Button variant="link" onClick={() => setModalOpen(false)}>
181
+ <Button ouiaId="create-content-view-form-cancel" variant="link" onClick={() => setModalOpen(false)}>
181
182
  {__('Cancel')}
182
183
  </Button>
183
184
  </ActionGroup>
@@ -68,7 +68,7 @@ test('Displays dependent fields correctly', () => {
68
68
  expect(getByText('Name')).toBeInTheDocument();
69
69
  expect(getByText('Label')).toBeInTheDocument();
70
70
  expect(getByText('Composite content view')).toBeInTheDocument();
71
- expect(getByText('Content view')).toBeInTheDocument();
71
+ expect(getByText('Component content view')).toBeInTheDocument();
72
72
  expect(getByText('Solve dependencies')).toBeInTheDocument();
73
73
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
74
74
  expect(getByText('Import only')).toBeInTheDocument();
@@ -13,6 +13,7 @@ import {
13
13
  selectCVVersionsStatus,
14
14
  } from '../Details/ContentViewDetailSelectors';
15
15
  import getEnvironmentPaths from '../components/EnvironmentPaths/EnvironmentPathActions';
16
+ import getContentViewDetails, { getContentViewVersions } from '../Details/ContentViewDetailActions';
16
17
  import CVDeletionReassignHostsForm from './Steps/CVDeletionReassignHostsForm';
17
18
  import CVDeletionReassignActivationKeysForm from './Steps/CVDeletionReassignActivationKeysForm';
18
19
  import CVDeletionReview from './Steps/CVDeletionReview';
@@ -23,7 +24,6 @@ import Loading from '../../../components/Loading';
23
24
  const ContentViewDeleteWizard =
24
25
  ({
25
26
  cvId, cvEnvironments, show, setIsOpen,
26
- currentStep, setCurrentStep,
27
27
  }) => {
28
28
  const cvVersionResponse = useSelector(state => selectCVVersions(state, cvId));
29
29
  const cvVersionStatus = useSelector(state => selectCVVersionsStatus(state, cvId));
@@ -39,14 +39,19 @@ const ContentViewDeleteWizard =
39
39
  const [affectedActivationKeys, setAffectedActivationKeys] = useState(false);
40
40
  const [affectedHosts, setAffectedHosts] = useState(false);
41
41
  const [canReview, setCanReview] = useState(false);
42
+ const [currentStep, setCurrentStep] = useState(1);
42
43
 
43
44
  const { name } = cvDetailsResponse ?? {};
44
45
 
45
46
  useEffect(
46
47
  () => {
48
+ if (cvDetailsStatus !== STATUS.RESOLVED) { dispatch(getContentViewDetails(cvId)); }
49
+ if (cvVersionStatus !== STATUS.RESOLVED) { dispatch(getContentViewVersions(cvId)); }
47
50
  dispatch(getEnvironmentPaths());
48
51
  },
49
- [dispatch],
52
+ // We don't want to call this everytime the status changes
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ [cvId, dispatch],
50
55
  );
51
56
 
52
57
  useEffect(() => {
@@ -144,7 +149,6 @@ const ContentViewDeleteWizard =
144
149
  startAtStep={currentStep}
145
150
  onClose={() => {
146
151
  setIsOpen(false);
147
- setCurrentStep(0);
148
152
  }}
149
153
  isOpen={show}
150
154
  />
@@ -157,8 +161,6 @@ ContentViewDeleteWizard.propTypes = {
157
161
  cvEnvironments: PropTypes.arrayOf(PropTypes.shape({})),
158
162
  show: PropTypes.bool,
159
163
  setIsOpen: PropTypes.func,
160
- currentStep: PropTypes.number.isRequired,
161
- setCurrentStep: PropTypes.func.isRequired,
162
164
  };
163
165
 
164
166
  ContentViewDeleteWizard.defaultProps = {
@@ -10,9 +10,11 @@ import getContentViews from '../../ContentViewsActions';
10
10
  import CVDeleteContext from '../CVDeleteContext';
11
11
  import Loading from '../../../../components/Loading';
12
12
 
13
+
13
14
  const CVDeletionFinish = () => {
14
15
  const {
15
- cvId, cvEnvironments,
16
+ cvId,
17
+ cvEnvironments,
16
18
  setIsOpen,
17
19
  selectedCVForAK, selectedEnvForAK, selectedCVForHosts,
18
20
  selectedEnvForHost, affectedActivationKeys, affectedHosts,
@@ -21,53 +23,59 @@ const CVDeletionFinish = () => {
21
23
  selectRemoveCVVersionResponse(state, cvId, cvEnvironments));
22
24
  const removeCVStatus = useSelector(state =>
23
25
  selectRemoveCVVersionStatus(state, cvId, cvEnvironments));
24
- const removeResolved = removeCVStatus === STATUS.RESOLVED;
25
26
  const dispatch = useDispatch();
26
27
  const [removeDispatched, setRemoveDispatched] = useState(false);
27
- const { push } = useHistory();
28
+ const { push, location: { pathname } } = useHistory();
28
29
 
29
30
  useDeepCompareEffect(() => {
30
- if (removeResolved && removeDispatched) {
31
- dispatch(getContentViews());
32
- push('/content_views');
33
- setIsOpen(false);
34
- }
35
- if (removeCVStatus === STATUS.ERROR) {
31
+ // If there is an error, we still want to refresh or redirect to show it.
32
+ if (removeDispatched && removeCVStatus === STATUS.ERROR) {
33
+ if (pathname === '/content_views') dispatch(getContentViews());
34
+ else push('/content_views');
36
35
  setIsOpen(false);
37
36
  }
38
- }, [removeCVResponse, removeCVStatus, removeResolved,
39
- setIsOpen, dispatch, cvId, removeDispatched, push]);
37
+ }, [dispatch, pathname, push, removeCVStatus, removeDispatched, setIsOpen]);
40
38
 
41
39
  useDeepCompareEffect(() => {
42
40
  if (!removeDispatched) {
43
41
  let params = {
44
42
  id: cvId,
43
+ destroy_content_view: true,
45
44
  };
46
45
 
47
46
  if (affectedActivationKeys) {
48
- const activationKeysParams = {
47
+ params = {
48
+ ...params,
49
49
  key_content_view_id: selectedCVForAK,
50
50
  key_environment_id: selectedEnvForAK[0].id,
51
51
  };
52
- params = { ...activationKeysParams, ...params };
53
52
  }
54
53
 
55
54
  if (affectedHosts) {
56
- const hostParams = {
55
+ params = {
56
+ ...params,
57
57
  system_content_view_id: selectedCVForHosts,
58
58
  system_environment_id: selectedEnvForHost[0].id,
59
59
  };
60
- params = { ...hostParams, ...params };
61
60
  }
62
61
 
63
- const deletionParams = { destroy_content_view: true };
64
- params = { ...deletionParams, ...params };
65
- dispatch(removeContentViewVersion(cvId, cvId, cvEnvironments, params));
62
+ dispatch(removeContentViewVersion(
63
+ cvId, cvId, cvEnvironments, params,
64
+ // Only when we are on the contentViews page do we need to call getContentViews.
65
+ () => {
66
+ if (pathname === '/content_views') dispatch(getContentViews());
67
+ else push('/content_views');
68
+ setIsOpen(false);
69
+ },
70
+ () => {
71
+ setIsOpen(false);
72
+ },
73
+ ));
66
74
  setRemoveDispatched(true);
67
75
  }
68
- }, [cvId, cvEnvironments, dispatch, affectedActivationKeys,
69
- affectedHosts, selectedCVForAK, selectedCVForHosts,
70
- selectedEnvForAK, selectedEnvForHost, removeCVResponse, removeCVStatus, removeDispatched]);
76
+ }, [cvId, cvEnvironments, dispatch, affectedActivationKeys, affectedHosts,
77
+ selectedCVForAK, selectedCVForHosts, selectedEnvForAK, selectedEnvForHost,
78
+ removeCVResponse, removeCVStatus, removeDispatched, pathname, push, setIsOpen]);
71
79
 
72
80
  return <Loading loadingText={__('Please wait while the task starts..')} />;
73
81
  };
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-useless-escape */
2
2
  import React from 'react';
3
- import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
3
+ import { renderWithRedux, patientlyWaitFor, fireEvent, act } from 'react-testing-lib-wrapper';
4
4
  import api, { foremanApi } from '../../../../services/api';
5
5
  import nock, {
6
6
  nockInstance, assertNockRequest, mockAutocomplete, mockSetting, mockForemanAutocomplete,
@@ -16,23 +16,27 @@ import affectedHostData from './affectedHosts.fixtures.json';
16
16
  import cVDropDownOptionsData from '../../Details/Versions/Delete/__tests__/cvDropDownOptionsResponse.fixture.json';
17
17
  import cvDeleteResponse from '../../Details/Versions/Delete/__tests__/cvVersionRemoveResponse.fixture.json';
18
18
 
19
- const cvIndexPath = api.getApiUrl('/content_views?organization_id=1&nondefault=true&include_permissions=true&per_page=20&page=1');
19
+ const cvIndexPath = api.getApiUrl('/content_views');
20
20
  const autocompleteUrl = '/content_views/auto_complete_search';
21
21
  const renderOptions = { apiNamespace: CONTENT_VIEWS_KEY };
22
22
  const environmentPathsPath = api.getApiUrl('/organizations/1/environments/paths');
23
-
24
23
  const cvVersionsPath = api.getApiUrl('/content_view_versions');
25
-
26
24
  const cvDetailsPath = api.getApiUrl('/content_views/20');
27
-
28
25
  const activationKeyURL = api.getApiUrl('/activation_keys');
29
-
30
26
  const hostURL = foremanApi.getApiUrl('/hosts');
31
-
32
27
  const cVDropDownOptionsPath = api.getApiUrl('/content_views?organization_id=1&environment_id=9&include_default=true&include_permissions=true&full_result=true');
33
-
34
28
  const cvDeleteUrl = api.getApiUrl('/content_views/20/remove');
35
29
 
30
+ const baseQuery = {
31
+ organization_id: 1,
32
+ nondefault: true,
33
+ include_permissions: true,
34
+ per_page: 20,
35
+ page: 1,
36
+ sort_by: 'name',
37
+ sort_order: 'asc',
38
+ };
39
+
36
40
  let scopeBookmark;
37
41
  let firstCV;
38
42
  let searchDelayScope;
@@ -58,6 +62,7 @@ test('Can call API for CVs and show Delete Wizard for the row', async (done) =>
58
62
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
59
63
  const scope = nockInstance
60
64
  .get(cvIndexPath)
65
+ .query(baseQuery)
61
66
  .reply(200, cvIndexData);
62
67
 
63
68
  const envPathDeleteScope = nockInstance
@@ -110,6 +115,7 @@ test('Can open Delete wizard and delete CV with all steps', async (done) => {
110
115
 
111
116
  const scope = nockInstance
112
117
  .get(cvIndexPath)
118
+ .query(true)
113
119
  .reply(200, cvIndexData);
114
120
 
115
121
  const envPathDeleteScope = nockInstance
@@ -243,4 +249,5 @@ test('Can open Delete wizard and delete CV with all steps', async (done) => {
243
249
  assertNockRequest(cVDropDownOptionsScope);
244
250
  assertNockRequest(cvDeleteScope);
245
251
  assertNockRequest(cvRedirectScope, done);
252
+ act(done);
246
253
  });
@@ -87,7 +87,7 @@ const ComponentContentViewAddModal = ({
87
87
 
88
88
  return (
89
89
  <Modal
90
- title={componentId ? __('Update version') : __('Add content view')}
90
+ title={componentId ? __('Update version') : __('Add component')}
91
91
  variant={ModalVariant.small}
92
92
  isOpen={show}
93
93
  description={__(`Select available version of ${cvName} to use`)}
@@ -137,8 +137,8 @@ const ComponentContentViewAddModal = ({
137
137
  </Flex>
138
138
  </FormGroup>
139
139
  <ActionGroup>
140
- <Button aria-label="add_component" variant="primary" type="submit">{__('Submit')}</Button>
141
- <Button variant="link" onClick={() => setIsOpen(false)}>{__('Cancel')}</Button>
140
+ <Button ouiaId="add-component-submit" aria-label="add_component" variant="primary" type="submit">{__('Submit')}</Button>
141
+ <Button ouiaId="add-component-cancel" variant="link" onClick={() => setIsOpen(false)}>{__('Cancel')}</Button>
142
142
  </ActionGroup>
143
143
  </Form>
144
144
  </Modal >);
@@ -51,10 +51,10 @@ const ComponentContentViewBulkAddModal = ({ cvId, rowsToAdd, onClose }) => {
51
51
 
52
52
  return (
53
53
  <Modal
54
- title={__('Add content views')}
54
+ title={__('Add component content views')}
55
55
  variant={ModalVariant.large}
56
56
  isOpen
57
- description={__('Select available version of content views to use')}
57
+ description={__('Select available version of components to use')}
58
58
  onClose={onClose}
59
59
  appendTo={document.body}
60
60
  >
@@ -112,8 +112,8 @@ const ComponentContentViewBulkAddModal = ({ cvId, rowsToAdd, onClose }) => {
112
112
  </Card>
113
113
  ))}
114
114
  <ActionGroup>
115
- <Button aria-label="add_components" variant="primary" type="submit">{__('Add')}</Button>
116
- <Button variant="link" onClick={onClose}>{__('Cancel')}</Button>
115
+ <Button ouiaId="add-components-modal-add" aria-label="add_components" variant="primary" type="submit">{__('Add')}</Button>
116
+ <Button ouiaId="add-components-modal-cancel" variant="link" onClick={onClose}>{__('Cancel')}</Button>
117
117
  </ActionGroup>
118
118
  </Form>
119
119
  </Modal >);
@@ -148,6 +148,7 @@ const ContentViewComponents = ({ cvId, details }) => {
148
148
  {hasPermission(permissions, 'edit_content_views') && componentCvId && cvVersion &&
149
149
  <SplitItem>
150
150
  <Button
151
+ ouiaId={`edit-component-version-${componentCvId}`}
151
152
  className="foreman-edit-icon"
152
153
  aria-label="edit_version"
153
154
  variant="plain"
@@ -244,6 +245,7 @@ const ContentViewComponents = ({ cvId, details }) => {
244
245
  activeFilters,
245
246
  defaultFilters,
246
247
  }}
248
+ ouiaId="content-view-components-table"
247
249
  actionResolver={hasPermission(permissions, 'edit_content_views') ? actionResolver : null}
248
250
  onSelect={onSelect(rows, setRows)}
249
251
  cells={columnHeaders}
@@ -268,7 +270,7 @@ const ContentViewComponents = ({ cvId, details }) => {
268
270
  <SplitItem>
269
271
  <ActionList>
270
272
  <ActionListItem>
271
- <Button onClick={addBulk} isDisabled={!(bulkAddEnabled())} variant="primary" aria-label="bulk_add_components">
273
+ <Button ouiaId="add-content-views" onClick={addBulk} isDisabled={!(bulkAddEnabled())} variant="primary" aria-label="bulk_add_components">
272
274
  {__('Add content views')}
273
275
  </Button>
274
276
  </ActionListItem>
@@ -212,7 +212,7 @@ test('Can add published component views to content view with modal', async (done
212
212
  });
213
213
  fireEvent.click(getByText('Add'));
214
214
  await patientlyWaitFor(() => {
215
- expect(getByText('Add content view')).toBeInTheDocument();
215
+ expect(getByText('Add component')).toBeInTheDocument();
216
216
  });
217
217
  fireEvent.click(getByLabelText('add_component'));
218
218
  await patientlyWaitFor(() => {
@@ -317,7 +317,7 @@ test('Can bulk add component views to content view with modal', async (done) =>
317
317
  .reply(200, {});
318
318
 
319
319
  const {
320
- getAllByText, getByLabelText, queryByText,
320
+ getByText, getByLabelText, queryByText,
321
321
  } = renderWithRedux(
322
322
  <ContentViewComponents cvId={4} details={cvDetails} />,
323
323
  renderOptions,
@@ -333,14 +333,14 @@ test('Can bulk add component views to content view with modal', async (done) =>
333
333
  });
334
334
  fireEvent.click(getByLabelText('bulk_add_components'));
335
335
  await patientlyWaitFor(() => {
336
- expect(getAllByText('Add content views')[1]).toBeInTheDocument();
336
+ expect(getByText('Add component content views')).toBeInTheDocument();
337
337
  });
338
338
  fireEvent.click(getByLabelText('version-select-cv-10'));
339
339
  fireEvent.click(getByLabelText('cv-10-3.0'));
340
340
 
341
341
  fireEvent.click(getByLabelText('add_components'));
342
342
  await patientlyWaitFor(() => {
343
- expect(queryByText('Select available version of content views to use')).not.toBeInTheDocument();
343
+ expect(queryByText('Add component content views')).not.toBeInTheDocument();
344
344
  expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'false');
345
345
  });
346
346
 
@@ -47,6 +47,8 @@ import {
47
47
  DEB_PACKAGES_CONTENT,
48
48
  DOCKER_TAGS_CONTENT,
49
49
  generatedContentKey,
50
+ STATUS_TRANSLATIONS_ENUM,
51
+ bulkRemoveVersionKey,
50
52
  } from '../ContentViewsConstants';
51
53
  import api, { foremanApi, orgId } from '../../../services/api';
52
54
  import { getResponseErrorMsgs } from '../../../utils/helpers';
@@ -372,7 +374,7 @@ export const getCVFilterRules = (filterId, params) => get({
372
374
  });
373
375
 
374
376
  export const getContentViewComponents = (cvId, params, statusSelected) => {
375
- const apiParams = { ...params, status: statusSelected };
377
+ const apiParams = { ...params, status: STATUS_TRANSLATIONS_ENUM[statusSelected] };
376
378
  const apiUrl = `/content_views/${cvId}/content_view_components/show_all`;
377
379
  return get({
378
380
  key: cvDetailsComponentKey(cvId),
@@ -413,21 +415,45 @@ export const editContentViewVersionDetails = (versionId, cvId, params, handleSuc
413
415
  errorToast: error => __(`Something went wrong while editing version details. ${getResponseErrorMsgs(error.response)}`),
414
416
  });
415
417
 
416
- export const removeContentViewVersion = (cvId, versionId, versionEnvironments, params) => put({
418
+ export const bulkDeleteContentViewVersion = (cvId, params, handleSuccess, handleError) => put({
417
419
  type: API_OPERATIONS.PUT,
418
- key: cvRemoveVersionKey(versionId, versionEnvironments),
419
- url: api.getApiUrl(`/content_views/${cvId}/remove`),
420
+ key: bulkRemoveVersionKey(cvId),
421
+ url: api.getApiUrl(`/content_views/${cvId}/bulk_delete_versions`),
420
422
  params,
421
- handleSuccess: response => renderTaskStartedToast(response.data),
422
- errorToast: error => cvErrorToast(error),
423
+ handleSuccess: (response) => {
424
+ renderTaskStartedToast(response?.data);
425
+ handleSuccess(response);
426
+ },
427
+ handleError,
428
+ errorToast: error => __(`Something went wrong while deleting versions ${getResponseErrorMsgs(error.response)}`),
423
429
  });
424
430
 
425
- export const promoteContentViewVersion = params => post({
431
+ export const removeContentViewVersion =
432
+ (cvId, versionId, versionEnvironments, params, handleSuccess, handleError) =>
433
+ put({
434
+ type: API_OPERATIONS.PUT,
435
+ key: cvRemoveVersionKey(versionId, versionEnvironments),
436
+ url: api.getApiUrl(`/content_views/${cvId}/remove`),
437
+ params,
438
+ handleSuccess: (response) => {
439
+ renderTaskStartedToast(response.data);
440
+ if (handleSuccess) return handleSuccess(response);
441
+ return undefined; // consistent-return
442
+ },
443
+ handleError,
444
+ errorToast: error => cvErrorToast(error),
445
+ });
446
+
447
+
448
+ export const promoteContentViewVersion = (params, handleSuccess) => post({
426
449
  type: API_OPERATIONS.POST,
427
450
  key: cvVersionPromoteKey(params.id, params.versionEnvironments),
428
451
  url: api.getApiUrl(`/content_view_versions/${params.id}/promote`),
429
452
  params,
430
- handleSuccess: response => renderTaskStartedToast(response.data),
453
+ handleSuccess: (response) => {
454
+ if (handleSuccess) return handleSuccess();
455
+ return renderTaskStartedToast(response.data);
456
+ },
431
457
  errorToast: error => cvErrorToast(error),
432
458
  });
433
459