katello 4.2.2 → 4.3.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 (495) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/common/katello.common.js +0 -67
  3. data/app/assets/javascripts/katello/common/katello.js +0 -27
  4. data/app/assets/javascripts/katello/common/vendor.js +0 -1
  5. data/app/assets/stylesheets/katello/katello.scss +0 -1
  6. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +10 -2
  7. data/app/controllers/katello/api/v2/api_controller.rb +35 -9
  8. data/app/controllers/katello/api/v2/capsule_content_controller.rb +16 -2
  9. data/app/controllers/katello/api/v2/content_view_components_controller.rb +22 -1
  10. data/app/controllers/katello/api/v2/content_view_filters_controller.rb +65 -1
  11. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +5 -1
  12. data/app/controllers/katello/api/v2/content_views_controller.rb +13 -6
  13. data/app/controllers/katello/api/v2/debs_controller.rb +74 -1
  14. data/app/controllers/katello/api/v2/errata_controller.rb +13 -10
  15. data/app/controllers/katello/api/v2/file_units_controller.rb +1 -0
  16. data/app/controllers/katello/api/v2/generic_content_units_controller.rb +1 -1
  17. data/app/controllers/katello/api/v2/host_errata_controller.rb +46 -5
  18. data/app/controllers/katello/api/v2/host_tracer_controller.rb +2 -1
  19. data/app/controllers/katello/api/v2/module_streams_controller.rb +4 -0
  20. data/app/controllers/katello/api/v2/organizations_controller.rb +22 -7
  21. data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
  22. data/app/controllers/katello/api/v2/repositories_controller.rb +36 -19
  23. data/app/controllers/katello/api/v2/subscriptions_controller.rb +0 -8
  24. data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +5 -1
  25. data/app/controllers/katello/concerns/api/v2/bulk_extensions.rb +40 -0
  26. data/app/controllers/katello/concerns/api/v2/host_errata_extensions.rb +4 -31
  27. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +1 -1
  28. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +1 -1
  29. data/app/helpers/katello/concerns/smart_proxy_helper_extensions.rb +2 -6
  30. data/app/helpers/katello/katello_url_helper.rb +1 -1
  31. data/app/lib/actions/candlepin/abstract_async_task.rb +6 -3
  32. data/app/lib/actions/candlepin/async_hypervisors.rb +12 -8
  33. data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +10 -1
  34. data/app/lib/actions/katello/capsule_content/refresh_repos.rb +1 -1
  35. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +2 -2
  36. data/app/lib/actions/katello/cdn_configuration/update.rb +38 -0
  37. data/app/lib/actions/katello/content_view/remove.rb +18 -7
  38. data/app/lib/actions/katello/content_view_version/destroy.rb +2 -2
  39. data/app/lib/actions/katello/content_view_version/republish_repositories.rb +1 -1
  40. data/app/lib/actions/katello/repository/clone_contents.rb +1 -2
  41. data/app/lib/actions/katello/repository/destroy.rb +21 -5
  42. data/app/lib/actions/katello/repository/fetch_pxe_files.rb +1 -1
  43. data/app/lib/actions/katello/repository/index_content.rb +19 -6
  44. data/app/lib/actions/katello/repository/multi_clone_contents.rb +1 -1
  45. data/app/lib/actions/katello/repository/sync.rb +3 -5
  46. data/app/lib/actions/katello/repository_set/scan_cdn.rb +0 -4
  47. data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +1 -1
  48. data/app/lib/actions/pulp/orphan_cleanup/remove_unneeded_repos.rb +1 -1
  49. data/app/lib/actions/pulp/repository/clear.rb +1 -1
  50. data/app/lib/actions/pulp3/abstract_async_task.rb +10 -1
  51. data/app/lib/actions/pulp3/capsule_content/generate_metadata.rb +4 -5
  52. data/app/lib/actions/pulp3/content_view_version/create_export_history.rb +1 -1
  53. data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +25 -42
  54. data/app/lib/actions/pulp3/orchestration/repository/upload_content.rb +3 -3
  55. data/app/lib/actions/pulp3/repository/commit_upload.rb +1 -1
  56. data/app/lib/actions/pulp3/repository/import_upload.rb +8 -4
  57. data/app/lib/actions/pulp3/repository/multi_copy_content.rb +1 -1
  58. data/app/lib/actions/pulp3/repository/multi_copy_units.rb +1 -1
  59. data/app/lib/actions/pulp3/repository/presenters/abstract_sync_presenter.rb +18 -0
  60. data/app/lib/actions/pulp3/repository/presenters/content_unit_presenter.rb +7 -2
  61. data/app/lib/actions/pulp3/repository/presenters/repair_presenter.rb +6 -1
  62. data/app/lib/actions/pulp3/repository/save_artifact.rb +14 -4
  63. data/app/lib/katello/errors.rb +2 -0
  64. data/app/lib/katello/resources/candlepin/consumer.rb +0 -20
  65. data/app/lib/katello/resources/candlepin/proxy.rb +8 -2
  66. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +2 -0
  67. data/app/lib/katello/resources/cdn/katello_cdn.rb +68 -0
  68. data/app/lib/katello/resources/cdn.rb +61 -29
  69. data/app/lib/katello/resources/registry.rb +1 -1
  70. data/app/lib/katello/util/cdn_var_substitutor.rb +15 -9
  71. data/app/lib/katello/util/package.rb +22 -0
  72. data/app/lib/katello/util/path_with_substitutions.rb +12 -14
  73. data/app/models/katello/activation_key.rb +10 -0
  74. data/app/models/katello/ansible_collection.rb +1 -1
  75. data/app/models/katello/authorization/repository.rb +4 -4
  76. data/app/models/katello/candlepin/repository_mapper.rb +5 -1
  77. data/app/models/katello/cdn_configuration.rb +32 -0
  78. data/app/models/katello/concerns/content_facet_host_extensions.rb +40 -0
  79. data/app/models/katello/concerns/host_managed_extensions.rb +29 -3
  80. data/app/models/katello/concerns/hostgroup_extensions.rb +1 -1
  81. data/app/models/katello/concerns/organization_extensions.rb +3 -1
  82. data/app/models/katello/concerns/pulp_database_unit.rb +16 -6
  83. data/app/models/katello/concerns/remote_execution_provider_extensions.rb +9 -0
  84. data/app/models/katello/concerns/setting_extensions.rb +1 -1
  85. data/app/models/katello/concerns/smart_proxy_extensions.rb +9 -8
  86. data/app/models/katello/content_credential.rb +4 -0
  87. data/app/models/katello/content_facet_applicable_deb.rb +7 -0
  88. data/app/models/katello/content_view.rb +24 -1
  89. data/app/models/katello/content_view_component.rb +4 -0
  90. data/app/models/katello/content_view_erratum_filter.rb +2 -0
  91. data/app/models/katello/content_view_filter.rb +1 -1
  92. data/app/models/katello/content_view_package_filter_rule.rb +2 -1
  93. data/app/models/katello/content_view_version.rb +30 -1
  94. data/app/models/katello/deb.rb +71 -0
  95. data/app/models/katello/erratum.rb +13 -1
  96. data/app/models/katello/generic_content_unit.rb +3 -1
  97. data/app/models/katello/glue/pulp/repos.rb +2 -2
  98. data/app/models/katello/host/content_facet.rb +23 -2
  99. data/app/models/katello/host/subscription_facet.rb +1 -1
  100. data/app/models/katello/host_tracer.rb +21 -2
  101. data/app/models/katello/installed_deb.rb +1 -1
  102. data/app/models/katello/module_stream.rb +4 -0
  103. data/app/models/katello/ping.rb +20 -1
  104. data/app/models/katello/product.rb +7 -5
  105. data/app/models/katello/provider.rb +1 -24
  106. data/app/models/katello/repository.rb +33 -10
  107. data/app/models/katello/root_repository.rb +28 -14
  108. data/app/models/setting/content.rb +8 -13
  109. data/app/services/katello/applicability/applicable_content_helper.rb +20 -0
  110. data/app/services/katello/organization_creator.rb +12 -11
  111. data/app/services/katello/pulp3/api/ansible_collection.rb +0 -40
  112. data/app/services/katello/pulp3/api/apt.rb +0 -47
  113. data/app/services/katello/pulp3/api/content_guard.rb +1 -1
  114. data/app/services/katello/pulp3/api/core.rb +28 -23
  115. data/app/services/katello/pulp3/api/docker.rb +0 -50
  116. data/app/services/katello/pulp3/api/file.rb +0 -48
  117. data/app/services/katello/pulp3/api/generic.rb +1 -44
  118. data/app/services/katello/pulp3/api/yum.rb +4 -44
  119. data/app/services/katello/pulp3/erratum.rb +1 -9
  120. data/app/services/katello/pulp3/generic_content_unit.rb +8 -4
  121. data/app/services/katello/pulp3/repository/ansible_collection.rb +4 -0
  122. data/app/services/katello/pulp3/repository/apt.rb +3 -3
  123. data/app/services/katello/pulp3/repository/generic.rb +10 -65
  124. data/app/services/katello/pulp3/repository/yum.rb +10 -0
  125. data/app/services/katello/pulp3/repository.rb +51 -21
  126. data/app/services/katello/pulp3/repository_mirror.rb +18 -9
  127. data/app/services/katello/pulp3/rpm.rb +2 -32
  128. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +7 -8
  129. data/app/services/katello/pulp3/smart_proxy_repository.rb +1 -1
  130. data/app/services/katello/registration_manager.rb +2 -0
  131. data/app/services/katello/repository_type.rb +103 -15
  132. data/app/services/katello/repository_type_manager.rb +14 -8
  133. data/app/services/katello/ui_notifications/subscriptions/manifest_expired_warning.rb +1 -1
  134. data/app/services/katello/upstream_connection_checker.rb +1 -0
  135. data/app/views/foreman/job_templates/resolve_traces.erb +25 -0
  136. data/app/views/foreman/job_templates/resolve_traces_-_katello_ansible_default.erb +28 -0
  137. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +1 -1
  138. data/app/views/katello/api/v2/common/_metadata.json.rabl +1 -0
  139. data/app/views/katello/api/v2/content_facet/base.json.rabl +3 -1
  140. data/app/views/katello/api/v2/content_facet/show.json.rabl +2 -1
  141. data/app/views/katello/api/v2/content_view_components/show.json.rabl +4 -0
  142. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +7 -0
  143. data/app/views/katello/api/v2/content_views/base.json.rabl +12 -8
  144. data/app/views/katello/api/v2/content_views/index.json.rabl +1 -0
  145. data/app/views/katello/api/v2/content_views/permissions.rabl +8 -0
  146. data/app/views/katello/api/v2/debs/base.json.rabl +5 -0
  147. data/app/views/katello/api/v2/errata/index.json.rabl +4 -0
  148. data/app/views/katello/api/v2/generic_content_units/base.json.rabl +2 -0
  149. data/app/views/katello/api/v2/generic_content_units/show.json.rabl +7 -0
  150. data/app/views/katello/api/v2/host_tracer/base.json.rabl +1 -0
  151. data/app/views/katello/api/v2/module_streams/index.json.rabl +4 -0
  152. data/app/views/katello/api/v2/organizations/cdn_configuration.rabl +1 -0
  153. data/app/views/katello/api/v2/organizations/show.json.rabl +7 -0
  154. data/app/views/katello/api/v2/repositories/base.json.rabl +10 -17
  155. data/app/views/overrides/activation_keys/_host_synced_content_select.html.erb +2 -6
  156. data/config/routes/api/v2.rb +13 -0
  157. data/config/routes/overrides.rb +2 -0
  158. data/config/routes.rb +14 -2
  159. data/db/migrate/20140110000001_update_environments_add_katello_id.rb +1 -3
  160. data/db/migrate/20140610154745_content_view_puppet_environment_id.rb +0 -35
  161. data/db/migrate/20190802112101_add_applicable_debs.rb +16 -0
  162. data/db/migrate/20210201163238_migrate_background_download_policy_to_migrate.rb +2 -2
  163. data/db/migrate/20210331180353_katello_pool_organization_id_not_nullable.rb +0 -2
  164. data/db/migrate/20210909140337_add_last_indexed_to_repos.rb +5 -0
  165. data/db/migrate/20210910190324_move_background_settings_to_immediate.rb +25 -0
  166. data/db/migrate/20211006161617_add_filename_to_katello_generic_content_units.rb +5 -0
  167. data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +30 -0
  168. data/db/migrate/20211025181315_add_additional_metadata_to_katello_generic_content_units.rb +5 -0
  169. data/engines/bastion/README.md +15 -0
  170. data/engines/bastion/app/assets/javascripts/bastion/components/nutupane.factory.js +2 -2
  171. data/engines/bastion/config/routes.rb +2 -0
  172. data/engines/bastion/vendor/assets/javascripts/bastion/angular/angular.js +3 -3
  173. data/engines/bastion/vendor/assets/javascripts/bastion/angular-sanitize/angular-sanitize.js +1 -1
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/bastion_katello.js +3 -0
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/views/registration.html +1 -1
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-applicable.controller.js +44 -0
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs.controller.js +1 -1
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-applicable.html +70 -0
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs.html +1 -1
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.routes.js +10 -0
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-details.html +5 -0
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +25 -9
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.routes.js +2 -2
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-versions.html +0 -9
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/debs.controller.js +22 -2
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/debs.routes.js +1 -1
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/deb.controller.js +22 -2
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/views/deb-content-views.html +1 -1
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/views/deb-info.html +36 -4
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/views/deb-repositories.html +1 -1
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/views/deb.html +4 -4
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/views/debs.html +31 -4
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/generic-content/generic-content.factory.js +21 -0
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/generic-content/generic-content.module.js +17 -0
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/details/package.controller.js +4 -0
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/details/views/package-info.html +3 -3
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/product-repositories.controller.js +6 -2
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +30 -2
  199. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.filter.js +1 -13
  200. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-manage-content.controller.js +32 -9
  201. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +15 -4
  202. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +32 -19
  203. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +28 -28
  204. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-manage-generic-content.html +57 -0
  205. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +46 -4
  206. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +57 -27
  207. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repositories.module.js +1 -0
  208. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repositories.routes.js +16 -7
  209. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository-types.service.js +30 -4
  210. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository.factory.js +2 -1
  211. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +8 -0
  212. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/sync-plan-details-info.controller.js +6 -2
  213. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-info.html +1 -1
  214. data/engines/bastion_katello/lib/bastion_katello/engine.rb +1 -1
  215. data/lib/katello/engine.rb +0 -1
  216. data/lib/katello/permission_creator.rb +4 -3
  217. data/lib/katello/permissions/host_permissions.rb +1 -0
  218. data/lib/katello/permissions/organization_permissions.rb +2 -1
  219. data/lib/katello/plugin.rb +15 -11
  220. data/lib/katello/repository_types/ansible_collection.rb +13 -1
  221. data/lib/katello/repository_types/deb.rb +13 -0
  222. data/lib/katello/repository_types/docker.rb +13 -1
  223. data/lib/katello/repository_types/file.rb +13 -0
  224. data/lib/katello/repository_types/ostree.rb +48 -4
  225. data/lib/katello/repository_types/python.rb +26 -12
  226. data/lib/katello/repository_types/yum.rb +16 -1
  227. data/lib/katello/tasks/repository.rake +3 -12
  228. data/lib/katello/tasks/reset.rake +4 -5
  229. data/lib/katello/version.rb +1 -1
  230. data/package.json +3 -2
  231. data/webpack/__mocks__/react-intl/index.js +4 -0
  232. data/webpack/components/ActionableDetail.js +23 -3
  233. data/webpack/components/AddedStatusLabel.js +1 -1
  234. data/webpack/components/Bookmark/AddBookmarkModal.js +96 -0
  235. data/webpack/components/Bookmark/Bookmark.scss +28 -0
  236. data/webpack/components/Bookmark/BookmarkActions.js +24 -0
  237. data/webpack/components/Bookmark/BookmarkConstants.js +3 -0
  238. data/webpack/components/Bookmark/BookmarkSelectors.js +15 -0
  239. data/webpack/components/Bookmark/index.js +94 -0
  240. data/webpack/components/EditableSwitch.js +6 -1
  241. data/webpack/components/EditableTextInput/EditableTextInput.js +41 -13
  242. data/webpack/components/Errata/index.js +69 -0
  243. data/webpack/components/ErratumTypeLabel.js +31 -0
  244. data/webpack/components/Loading.js +5 -2
  245. data/webpack/components/RoutedTabs/__tests__/RoutedTabs.test.js +5 -11
  246. data/webpack/components/RoutedTabs/index.js +77 -2
  247. data/webpack/components/Search/Search.js +67 -80
  248. data/webpack/components/Search/__tests__/search.test.js +8 -26
  249. data/webpack/components/SelectAllCheckbox/SelectAllCheckbox.scss +3 -0
  250. data/webpack/components/SelectAllCheckbox/index.js +126 -0
  251. data/webpack/components/SelectableDropdown/SelectableDropdown.js +7 -2
  252. data/webpack/components/Table/EmptyStateMessage.js +38 -17
  253. data/webpack/components/Table/MainTable.js +49 -10
  254. data/webpack/components/Table/MainTable.scss +11 -0
  255. data/webpack/components/Table/PageControls.js +45 -0
  256. data/webpack/components/Table/TableHooks.js +230 -0
  257. data/webpack/components/Table/TableWrapper.js +221 -50
  258. data/webpack/components/Table/helpers.js +17 -0
  259. data/webpack/components/TypeAhead/TypeAhead.js +74 -58
  260. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +25 -10
  261. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.scss +9 -8
  262. data/webpack/components/TypeAhead/pf4Search/TypeAheadItems.js +2 -2
  263. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +32 -22
  264. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +101 -0
  265. data/webpack/components/extensions/HostDetails/Cards/__tests__/contentViewDetailsCard.test.js +53 -0
  266. data/webpack/components/extensions/HostDetails/HostErrata/HostErrataActions.js +47 -0
  267. data/webpack/components/extensions/HostDetails/HostErrata/HostErrataConstants.js +32 -0
  268. data/webpack/components/extensions/HostDetails/HostErrata/HostErrataSelectors.js +16 -0
  269. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/EmptyPage.js +19 -0
  270. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +17 -0
  271. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +7 -0
  272. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/helpers.js +3 -0
  273. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +40 -0
  274. data/webpack/components/extensions/HostDetails/Tabs/EnableTracerEmptyState.js +42 -0
  275. data/webpack/components/extensions/HostDetails/Tabs/EnableTracerModal.js +118 -0
  276. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.js +347 -0
  277. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.scss +16 -0
  278. data/webpack/components/extensions/HostDetails/Tabs/ErratumExpansionContents.js +60 -0
  279. data/webpack/components/extensions/HostDetails/Tabs/ErratumExpansionDetail.js +69 -0
  280. data/webpack/components/extensions/HostDetails/Tabs/HostTracesActions.js +19 -0
  281. data/webpack/components/extensions/HostDetails/Tabs/HostTracesConstants.js +2 -0
  282. data/webpack/components/extensions/HostDetails/Tabs/HostTracesSelectors.js +19 -0
  283. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +56 -0
  284. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +5 -0
  285. data/webpack/components/extensions/HostDetails/Tabs/TracesTab.js +188 -0
  286. data/webpack/components/extensions/HostDetails/Tabs/TracesTab.scss +12 -0
  287. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errata.fixtures.json +67 -0
  288. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +785 -0
  289. data/webpack/components/extensions/HostDetails/Tabs/__tests__/resolveTraces.fixtures.json +35 -0
  290. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracerEmptyTraceResults.fixtures.json +7 -0
  291. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracerEnableJobInvocation.fixtures.json +35 -0
  292. data/webpack/components/extensions/HostDetails/Tabs/__tests__/traces.fixtures.json +44 -0
  293. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +386 -0
  294. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +20 -0
  295. data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +1 -1
  296. data/webpack/components/extensions/RegistrationCommands/index.js +1 -1
  297. data/webpack/components/pf3Table/components/Table.js +1 -1
  298. data/webpack/components/pf3Table/components/__snapshots__/Table.test.js.snap +3 -3
  299. data/webpack/containers/Application/Routes.js +3 -3
  300. data/webpack/containers/Application/config.js +21 -6
  301. data/webpack/containers/Application/overrides.scss +34 -3
  302. data/webpack/{fills_index.js → global_index.js} +11 -2
  303. data/webpack/global_test_setup.js +6 -1
  304. data/webpack/redux/actions/RedHatRepositories/helpers.js +4 -4
  305. data/webpack/scenes/AnsibleCollections/AnsibleCollectionsTableSchema.js +1 -1
  306. data/webpack/scenes/Content/ContentActions.js +31 -0
  307. data/webpack/scenes/Content/ContentConfig.js +138 -0
  308. data/webpack/scenes/Content/ContentConstants.js +7 -0
  309. data/webpack/scenes/Content/ContentPage.js +89 -0
  310. data/webpack/scenes/Content/ContentSelectors.js +43 -0
  311. data/webpack/scenes/Content/Details/ContentCounts.js +42 -0
  312. data/webpack/scenes/Content/Details/ContentDetails.js +66 -0
  313. data/webpack/scenes/Content/Details/ContentInfo.js +60 -0
  314. data/webpack/scenes/Content/Details/ContentRepositories.js +78 -0
  315. data/webpack/scenes/Content/Details/__tests__/ansibleCollectionDetails.fixtures.json +20 -0
  316. data/webpack/scenes/Content/Details/__tests__/ansibleCollectionRepositoryDetails.fixtures.json +71 -0
  317. data/webpack/scenes/Content/Details/__tests__/contentDetail.test.js +152 -0
  318. data/webpack/scenes/Content/Details/__tests__/pythonPackageDetails.fixtures.json +20 -0
  319. data/webpack/scenes/Content/Details/__tests__/pythonPackageRepositoryDetails.fixtures.json +71 -0
  320. data/webpack/scenes/Content/Details/index.js +4 -0
  321. data/webpack/scenes/Content/Table/ContentTable.js +90 -0
  322. data/webpack/scenes/Content/Table/index.js +3 -0
  323. data/webpack/scenes/Content/__tests__/ansibleCollections.fixtures.json +50 -0
  324. data/webpack/scenes/Content/__tests__/contentTable.test.js +89 -0
  325. data/webpack/scenes/Content/__tests__/contentTypes.fixtures.json +66 -0
  326. data/webpack/scenes/Content/__tests__/pythonPackages.fixtures.json +30 -0
  327. data/webpack/scenes/Content/index.js +4 -0
  328. data/webpack/scenes/ContentViews/ContentViewSelectors.js +5 -6
  329. data/webpack/scenes/ContentViews/ContentViewsActions.js +13 -8
  330. data/webpack/scenes/ContentViews/ContentViewsConstants.js +31 -4
  331. data/webpack/scenes/ContentViews/ContentViewsPage.js +4 -0
  332. data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +19 -7
  333. data/webpack/scenes/ContentViews/Copy/CopyContentViewModal.js +7 -5
  334. data/webpack/scenes/ContentViews/Copy/__tests__/copyContentView.test.js +1 -1
  335. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +7 -3
  336. data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +1 -2
  337. data/webpack/scenes/ContentViews/Delete/CVDeleteContext.js +4 -0
  338. data/webpack/scenes/ContentViews/Delete/ContentViewDeleteWizard.js +170 -0
  339. data/webpack/scenes/ContentViews/Delete/Steps/CVDeleteEnvironmentsSelection.js +108 -0
  340. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionFinish.js +69 -0
  341. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignActivationKeysForm.js +121 -0
  342. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +120 -0
  343. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReview.js +62 -0
  344. data/webpack/scenes/ContentViews/Delete/Steps/CVEnvironmentSelectionForm.scss +4 -0
  345. data/webpack/scenes/ContentViews/Delete/__tests__/CvData.fixtures.json +259 -0
  346. data/webpack/scenes/ContentViews/Delete/__tests__/affectedHosts.fixtures.json +155 -0
  347. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +241 -0
  348. data/webpack/scenes/ContentViews/Delete/__tests__/cvDetails.fixtures.json +248 -0
  349. data/webpack/scenes/ContentViews/Delete/__tests__/cvVersionsData.fixtures.json +865 -0
  350. data/webpack/scenes/ContentViews/Delete/__tests__/envPathData.fixtures.json +424 -0
  351. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +15 -7
  352. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +123 -0
  353. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentEnvironments.js +1 -1
  354. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentVersion.js +8 -5
  355. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +109 -51
  356. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.fixtures.json +21 -6
  357. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +80 -16
  358. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +248 -3
  359. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +141 -0
  360. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +36 -54
  361. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +20 -4
  362. data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +63 -38
  363. data/webpack/scenes/ContentViews/Details/Filters/Add/__tests__/cvFilterAdd.test.js +3 -4
  364. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositorySelection.js +65 -0
  365. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +260 -0
  366. data/webpack/scenes/ContentViews/Details/Filters/ArtifactsWithNoErrata.js +54 -0
  367. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +202 -0
  368. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +291 -0
  369. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +441 -0
  370. data/webpack/scenes/ContentViews/Details/Filters/CVFilterDetailType.js +62 -3
  371. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +302 -0
  372. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +186 -23
  373. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +144 -19
  374. data/webpack/scenes/ContentViews/Details/Filters/ContentType.js +2 -0
  375. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetails.js +44 -13
  376. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +81 -17
  377. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +43 -43
  378. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVRpmMatchContentModal.js +96 -0
  379. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContent.fixtures.json +166 -0
  380. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentModal.test.js +90 -0
  381. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentSearch.fixtures.json +33 -0
  382. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +91 -0
  383. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +237 -0
  384. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.fixtures.json +42 -0
  385. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +265 -0
  386. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +218 -11
  387. data/webpack/scenes/ContentViews/Details/Filters/__tests__/ContentViewPackageGroupFilter.test.js +517 -0
  388. data/webpack/scenes/ContentViews/Details/Filters/__tests__/allFilterErrata.fixtures.json +122 -0
  389. data/webpack/scenes/ContentViews/Details/Filters/__tests__/allFilterModulesStreams.fixtures.json +60 -0
  390. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewErrataByDateDetails.fixtures.json +359 -0
  391. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetail.fixtures.json +88 -102
  392. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +34 -9
  393. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.fixtures.json +148 -132
  394. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +25 -7
  395. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvAllRepos.fixtures.json +150 -0
  396. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataDateFilterContent.test.js +74 -0
  397. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataIDFilter.test.js +404 -0
  398. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErratumFilterDetails.fixtures.json +89 -0
  399. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvFilterDetailModuleAffectedRepos.fixtures.json +383 -0
  400. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvFilterDetailWithAffectedRepos.fixtures.json +375 -0
  401. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvFilterFixutre.fixture.json +282 -0
  402. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilter.test.js +392 -0
  403. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilterDetails.fixtures.json +97 -0
  404. data/webpack/scenes/ContentViews/Details/Filters/index.js +26 -0
  405. data/webpack/scenes/ContentViews/Details/Histories/ContentViewHistories.js +68 -79
  406. data/webpack/scenes/ContentViews/Details/Histories/__tests__/contentViewHistory.test.js +1 -2
  407. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +163 -0
  408. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromoteSelectors.js +16 -0
  409. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +9 -1
  410. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +88 -74
  411. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +8 -9
  412. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.fixtures.json +3 -3
  413. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +30 -9
  414. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionEnvironments.js +1 -1
  415. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionErrata.js +9 -5
  416. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionErrata.scss +2 -2
  417. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +132 -14
  418. data/webpack/scenes/ContentViews/Details/Versions/Delete/DeleteContext.js +4 -0
  419. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveCVVersionWizard.js +176 -0
  420. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVEnvironmentSelectionForm.js +127 -0
  421. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +131 -0
  422. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +128 -0
  423. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionDeleteFinish.js +94 -0
  424. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionRemoveReview.js +67 -0
  425. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvAffectedActivationKeys.fixture.json +53 -0
  426. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvAffectedHosts.fixture.json +153 -0
  427. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvDropDownOptionsResponse.fixture.json +192 -0
  428. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +313 -0
  429. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemoveResponse.fixture.json +74 -0
  430. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/versionRemoveEnvPaths.fixtures.json +352 -0
  431. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/versionsResponseData.fixtures.json +583 -0
  432. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +96 -0
  433. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +97 -0
  434. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +332 -0
  435. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +128 -0
  436. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.scss +44 -0
  437. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +66 -0
  438. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +125 -0
  439. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +115 -0
  440. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionAnsibleCollections.fixtures.json +449 -0
  441. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionComponent.fixtures.json +753 -0
  442. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDebPackages.fixtures.json +58 -0
  443. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.fixtures.json +158 -0
  444. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +289 -0
  445. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetailsCounts.fixtures.json +73 -0
  446. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetailsEmpty.test.js +44 -0
  447. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDockerTags.fixtures.json +3024 -0
  448. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionErrata.fixtures.json +201 -0
  449. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionFiles.fixtures.json +22 -0
  450. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionModuleStreams.fixtures.json +196 -0
  451. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionRepositories.fixtures.json +1000 -0
  452. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionRpmPackageGroups.fixtures.json +44 -0
  453. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionRpmPackages.fixtures.json +394 -0
  454. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.fixtures.json +4 -4
  455. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +95 -26
  456. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersionsWithTask.fixtures.json +2 -2
  457. data/webpack/scenes/ContentViews/Details/Versions/index.js +25 -0
  458. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +20 -16
  459. data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +3 -5
  460. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +106 -64
  461. data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +25 -4
  462. data/webpack/scenes/ContentViews/__tests__/basicContentViews.fixtures.js +1 -1
  463. data/webpack/scenes/ContentViews/__tests__/contentViewList.fixtures.json +4 -1
  464. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +29 -36
  465. data/webpack/scenes/ContentViews/__tests__/mockDetails.fixtures.json +10 -0
  466. data/webpack/scenes/ContentViews/components/CVBreadCrumb.js +117 -0
  467. data/webpack/scenes/ContentViews/components/ContentViewsCounter.js +59 -0
  468. data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +4 -3
  469. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +30 -11
  470. data/webpack/scenes/ContentViews/components/TaskPresenter/TaskPresenter.js +1 -1
  471. data/webpack/scenes/ContentViews/expansions/DetailsExpansion.js +38 -1
  472. data/webpack/scenes/ContentViews/expansions/RelatedCompositeContentViewsModal.js +79 -0
  473. data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +107 -0
  474. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsModal.test.js +59 -0
  475. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsResponse.fixtures.json +116 -0
  476. data/webpack/scenes/ContentViews/expansions/__tests__/relatedCompositeCvs.fixtures.json +4 -0
  477. data/webpack/scenes/ContentViews/helpers.js +1 -0
  478. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository/RepositorySetRepository.js +1 -1
  479. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +4 -3
  480. data/webpack/scenes/SmartProxy/SmartProxyContentTable.js +1 -1
  481. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +17 -9
  482. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +3 -3
  483. data/webpack/test-utils/nockWrapper.js +20 -3
  484. data/webpack/utils/helpers.js +16 -2
  485. data/webpack/utils/useDebounce.js +20 -0
  486. metadata +232 -54
  487. data/app/assets/javascripts/katello/widgets/tabs.js +0 -13
  488. data/app/assets/stylesheets/katello/widgets/tabs.scss +0 -69
  489. data/app/lib/actions/katello/provider/update.rb +0 -38
  490. data/webpack/components/RoutedTabs/RoutedTabs.js +0 -90
  491. data/webpack/components/Search/Search.test.js +0 -23
  492. data/webpack/components/Search/__snapshots__/Search.test.js.snap +0 -21
  493. data/webpack/components/extensions/HostDetails/Tabs/ContentTab.js +0 -42
  494. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.test.js +0 -145
  495. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionPackages.js +0 -0
@@ -1,7 +1,8 @@
1
1
  import React, { useState, useCallback } from 'react';
2
2
  import useDeepCompareEffect from 'use-deep-compare-effect';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
- import { Bullseye, Split, SplitItem, Button } from '@patternfly/react-core';
4
+ import { Bullseye, Split, SplitItem, Button, ActionList,
5
+ ActionListItem, Dropdown, DropdownItem, KebabToggle } from '@patternfly/react-core';
5
6
  import { Link } from 'react-router-dom';
6
7
  import { TableVariant, fitContent, TableText } from '@patternfly/react-table';
7
8
  import { PencilAltIcon } from '@patternfly/react-icons';
@@ -31,15 +32,17 @@ import { ADDED, ALL_STATUSES, NOT_ADDED } from '../../ContentViewsConstants';
31
32
  import SelectableDropdown from '../../../../components/SelectableDropdown/SelectableDropdown';
32
33
  import '../../../../components/EditableTextInput/editableTextInput.scss';
33
34
  import ComponentContentViewAddModal from './ComponentContentViewAddModal';
35
+ import ComponentContentViewBulkAddModal from './ComponentContentViewBulkAddModal';
36
+ import { hasPermission } from '../../helpers';
34
37
 
35
38
  const ContentViewComponents = ({ cvId, details }) => {
36
39
  const response = useSelector(state => selectCVComponents(state, cvId));
37
40
  const status = useSelector(state => selectCVComponentsStatus(state, cvId));
38
41
  const error = useSelector(state => selectCVComponentsError(state, cvId));
42
+ const { results, ...metadata } = response;
39
43
  const componentAddedStatus = useSelector(state => selectCVComponentAddStatus(state, cvId));
40
44
  const componentRemovedStatus = useSelector(state => selectCVComponentRemoveStatus(state, cvId));
41
45
  const [rows, setRows] = useState([]);
42
- const [metadata, setMetadata] = useState({});
43
46
  const [searchQuery, updateSearchQuery] = useState('');
44
47
  const [statusSelected, setStatusSelected] = useState(ALL_STATUSES);
45
48
  const [versionEditing, setVersionEditing] = useState(false);
@@ -47,6 +50,9 @@ const ContentViewComponents = ({ cvId, details }) => {
47
50
  const [componentCvEditing, setComponentCvEditing] = useState(null);
48
51
  const [componentLatest, setComponentLatest] = useState(false);
49
52
  const [componentId, setComponentId] = useState(null);
53
+ const [selectedComponentsToAdd, setSelectedComponentsToAdd] = useState(null);
54
+ const [bulkAdding, setBulkAdding] = useState(false);
55
+ const [bulkActionOpen, setBulkActionOpen] = useState(false);
50
56
  const dispatch = useDispatch();
51
57
 
52
58
  const columnHeaders = [
@@ -62,21 +68,22 @@ const ContentViewComponents = ({ cvId, details }) => {
62
68
  const addComponentsResolved = componentAddedStatus === STATUS.RESOLVED;
63
69
  const removeComponentsResolved = componentRemovedStatus === STATUS.RESOLVED;
64
70
 
65
- const { label } = details || {};
71
+ const { label, permissions } = details || {};
66
72
 
67
73
  const bulkRemoveEnabled = () => rows.some(row => row.selected && row.added);
74
+ const bulkAddEnabled = () => rows.some(row => row.selected && !row.added);
68
75
 
69
76
  const onAdd = useCallback(({
70
77
  componentCvId, published, added, latest,
71
78
  }) => {
72
- if (published) {
73
- dispatch(getContentViewDetails(componentCvId));
79
+ if (published) { // If 1 or more versions present, open a modal to let user select version
80
+ dispatch(getContentViewDetails(componentCvId, 'bulk_add'));
74
81
  setVersionEditing(true);
75
82
  setCompositeCvEditing(cvId);
76
83
  setComponentCvEditing(componentCvId);
77
84
  setComponentLatest(latest);
78
85
  setComponentId(added);
79
- } else {
86
+ } else { // if no versions are present, default to always latest and add cv without modal
80
87
  dispatch(addComponent({
81
88
  compositeContentViewId: cvId,
82
89
  components: [{ latest: true, content_view_id: componentCvId }],
@@ -93,6 +100,13 @@ const ContentViewComponents = ({ cvId, details }) => {
93
100
  }));
94
101
  };
95
102
 
103
+ const addBulk = () => {
104
+ const rowsToAdd = rows.filter(row => row.selected && !row.added);
105
+ setSelectedComponentsToAdd(rowsToAdd);
106
+ setCompositeCvEditing(cvId);
107
+ setBulkAdding(true);
108
+ };
109
+
96
110
  const onRemove = (componentIdToRemove) => {
97
111
  dispatch(removeComponent({
98
112
  compositeContentViewId: cvId,
@@ -100,11 +114,16 @@ const ContentViewComponents = ({ cvId, details }) => {
100
114
  }));
101
115
  };
102
116
 
103
- const buildRows = useCallback((results) => {
117
+ const toggleBulkAction = () => {
118
+ setBulkActionOpen(!bulkActionOpen);
119
+ };
120
+
121
+ const buildRows = useCallback(() => {
104
122
  const newRows = [];
105
123
  results.forEach((componentCV) => {
106
124
  const {
107
- id: componentCvId, content_view: cv, content_view_version: cvVersion, latest,
125
+ id: componentCvId, content_view: cv, content_view_version: cvVersion,
126
+ latest, component_content_view_versions: componentCvVersions,
108
127
  } = componentCV;
109
128
  const { environments, repositories } = cvVersion || {};
110
129
  const {
@@ -115,24 +134,24 @@ const ContentViewComponents = ({ cvId, details }) => {
115
134
 
116
135
  const cells = [
117
136
  { title: <Bullseye><ContentViewIcon composite={false} /></Bullseye> },
118
- { title: <Link to={urlBuilder('labs/content_views', '', id)}>{name}</Link> },
137
+ { title: <a href={urlBuilder('content_views', '') + id}>{name}</a> },
119
138
  {
120
139
  title:
121
140
  <Split>
122
141
  <SplitItem>
123
142
  <ComponentVersion {...{ componentCV }} />
124
143
  </SplitItem>
125
- {componentCvId && cvVersion &&
144
+ {hasPermission(permissions, 'edit_content_views') && componentCvId && cvVersion &&
126
145
  <SplitItem>
127
146
  <Button
128
147
  className="foreman-edit-icon"
129
148
  aria-label="edit_version"
130
149
  variant="plain"
131
150
  onClick={() => {
132
- onAdd({
133
- componentCvId: id, published: cvVersion, added: componentCvId, latest,
134
- });
135
- }}
151
+ onAdd({
152
+ componentCvId: id, published: cvVersion, added: componentCvId, latest,
153
+ });
154
+ }}
136
155
  >
137
156
  <PencilAltIcon />
138
157
  </Button>
@@ -140,18 +159,24 @@ const ContentViewComponents = ({ cvId, details }) => {
140
159
  </Split>,
141
160
  },
142
161
  { title: environments ? <ComponentEnvironments {...{ environments }} /> : __('Not yet published') },
143
- { title: <Link to={urlBuilder(`labs/content_views/${id}#repositories`, '')}>{ repositories ? repositories.length : 0 }</Link> },
162
+ { title: <Link to={urlBuilder(`content_views/${id}#repositories`, '')}>{repositories ? repositories.length : 0}</Link> },
144
163
  {
145
164
  title: <AddedStatusLabel added={!!componentCvId} />,
146
165
  },
147
166
  { title: <TableText wrapModifier="truncate">{description || __('No description')}</TableText> },
148
167
  ];
149
168
  newRows.push({
150
- componentCvId: id, added: componentCvId, published: cvVersion, latest, cells,
169
+ componentCvId: id,
170
+ componentCvName: name,
171
+ added: componentCvId,
172
+ componentCvVersions,
173
+ published: cvVersion,
174
+ latest,
175
+ cells,
151
176
  });
152
177
  });
153
178
  return newRows;
154
- }, [onAdd]);
179
+ }, [onAdd, results, permissions]);
155
180
 
156
181
  const actionResolver = (rowData, { _rowIndex }) => [
157
182
  {
@@ -175,21 +200,28 @@ const ContentViewComponents = ({ cvId, details }) => {
175
200
  },
176
201
  ];
177
202
 
203
+ const dropdownItems = [
204
+ <DropdownItem aria-label="bulk_add" key="bulk_add" isDisabled={!(bulkAddEnabled())} component="button" onClick={addBulk}>
205
+ {__('Add')}
206
+ </DropdownItem>,
207
+ <DropdownItem aria-label="bulk_remove" key="bulk_remove" isDisabled={!(bulkRemoveEnabled())} component="button" onClick={removeBulk}>
208
+ {__('Remove')}
209
+ </DropdownItem>,
210
+ ];
211
+
178
212
  const emptyContentTitle = __(`No content views belong to ${label}`);
179
213
  const emptyContentBody = __('Please add some content views.');
180
214
  const emptySearchTitle = __('No matching content views found');
181
215
  const emptySearchBody = __('Try changing your search settings.');
182
- const activeFilters = statusSelected && statusSelected !== ALL_STATUSES;
216
+ const activeFilters = [statusSelected];
217
+ const defaultFilters = [ALL_STATUSES];
183
218
 
184
219
  useDeepCompareEffect(() => {
185
- const { results, ...meta } = response;
186
- setMetadata(meta);
187
-
188
220
  if (!loading && results) {
189
221
  const newRows = buildRows(results);
190
222
  setRows(newRows);
191
223
  }
192
- }, [response, buildRows, loading]);
224
+ }, [results, response, buildRows, loading]);
193
225
 
194
226
  return (
195
227
  <TableWrapper
@@ -205,8 +237,9 @@ const ContentViewComponents = ({ cvId, details }) => {
205
237
  error,
206
238
  status,
207
239
  activeFilters,
208
- actionResolver,
240
+ defaultFilters,
209
241
  }}
242
+ actionResolver={hasPermission(permissions, 'edit_content_views') ? actionResolver : null}
210
243
  onSelect={onSelect(rows, setRows)}
211
244
  cells={columnHeaders}
212
245
  variant={TableVariant.compact}
@@ -214,35 +247,58 @@ const ContentViewComponents = ({ cvId, details }) => {
214
247
  fetchItems={useCallback(params =>
215
248
  getContentViewComponents(cvId, params, statusSelected), [cvId, statusSelected])}
216
249
  additionalListeners={[statusSelected, addComponentsResolved, removeComponentsResolved]}
217
- >
218
- <Split hasGutter>
219
- <SplitItem>
220
- <SelectableDropdown
221
- items={[ADDED, NOT_ADDED, ALL_STATUSES]}
222
- title={__('Status')}
223
- selected={statusSelected}
224
- setSelected={setStatusSelected}
225
- placeholderText={__('Status')}
226
- />
227
- </SplitItem>
228
- <SplitItem>
229
- <Button onClick={removeBulk} isDisabled={!(bulkRemoveEnabled())} variant="secondary" aria-label="remove_components">
230
- {__('Remove content views')}
231
- </Button>
232
- </SplitItem>
233
- </Split>
234
- {versionEditing &&
235
- <ComponentContentViewAddModal
236
- cvId={compositeCvEditing}
237
- componentCvId={componentCvEditing}
238
- componentId={componentId}
239
- latest={componentLatest}
240
- show={versionEditing}
241
- setIsOpen={setVersionEditing}
242
- aria-label="copy_content_view_modal"
243
- />
250
+ actionButtons={
251
+ <>
252
+ <Split hasGutter>
253
+ <SplitItem>
254
+ <SelectableDropdown
255
+ items={[ADDED, NOT_ADDED, ALL_STATUSES]}
256
+ title={__('Status')}
257
+ selected={statusSelected}
258
+ setSelected={setStatusSelected}
259
+ placeholderText={__('Status')}
260
+ />
261
+ </SplitItem>
262
+ {hasPermission(permissions, 'edit_content_views') &&
263
+ <SplitItem>
264
+ <ActionList>
265
+ <ActionListItem>
266
+ <Button onClick={addBulk} isDisabled={!(bulkAddEnabled())} variant="secondary" aria-label="bulk_add_components">
267
+ {__('Add content views')}
268
+ </Button>
269
+ </ActionListItem>
270
+ <ActionListItem>
271
+ <Dropdown
272
+ toggle={<KebabToggle aria-label="bulk_actions" onToggle={toggleBulkAction} />}
273
+ isOpen={bulkActionOpen}
274
+ isPlain
275
+ dropdownItems={dropdownItems}
276
+ />
277
+ </ActionListItem>
278
+ </ActionList>
279
+ </SplitItem>
280
+ }
281
+ </Split>
282
+ {versionEditing &&
283
+ <ComponentContentViewAddModal
284
+ cvId={compositeCvEditing}
285
+ componentCvId={componentCvEditing}
286
+ componentId={componentId}
287
+ latest={componentLatest}
288
+ show={versionEditing}
289
+ setIsOpen={setVersionEditing}
290
+ aria-label="edit_component_modal"
291
+ />}
292
+ {bulkAdding &&
293
+ <ComponentContentViewBulkAddModal
294
+ cvId={compositeCvEditing}
295
+ rowsToAdd={selectedComponentsToAdd}
296
+ onClose={() => setBulkAdding(false)}
297
+ aria-label="bulk_add_components_modal"
298
+ />}
299
+ </>
244
300
  }
245
- </TableWrapper>
301
+ />
246
302
  );
247
303
  };
248
304
 
@@ -250,12 +306,14 @@ ContentViewComponents.propTypes = {
250
306
  cvId: PropTypes.number.isRequired,
251
307
  details: PropTypes.shape({
252
308
  label: PropTypes.string,
309
+ permissions: PropTypes.shape({}),
253
310
  }),
254
311
  };
255
312
 
256
313
  ContentViewComponents.defaultProps = {
257
314
  details: {
258
315
  label: '',
316
+ permissions: {},
259
317
  },
260
318
  };
261
319
 
@@ -76,8 +76,8 @@
76
76
  },
77
77
  "content_view": {
78
78
  "id": 13,
79
- "name": "10",
80
- "label": "10",
79
+ "name": "cv-10",
80
+ "label": "cv-10",
81
81
  "description": "",
82
82
  "next_version": 34,
83
83
  "latest_version": "33.0",
@@ -122,7 +122,21 @@
122
122
  }
123
123
  ],
124
124
  "repositories": []
125
- }
125
+ },
126
+ "component_content_view_versions": [
127
+ {
128
+ "id": 36,
129
+ "version": "1.0"
130
+ },
131
+ {
132
+ "id": 42,
133
+ "version": "3.0"
134
+ },
135
+ {
136
+ "id": 44,
137
+ "version": "4.0"
138
+ }
139
+ ]
126
140
  },
127
141
  {
128
142
  "latest": true,
@@ -140,14 +154,15 @@
140
154
  },
141
155
  "content_view": {
142
156
  "id": 9,
143
- "name": "6",
144
- "label": "6",
157
+ "name": "cv-6",
158
+ "label": "cv-6",
145
159
  "description": "",
146
160
  "next_version": 1,
147
161
  "latest_version": null,
148
162
  "version_count": 0
149
163
  },
150
- "content_view_version": null
164
+ "content_view_version": null,
165
+ "component_content_view_versions": []
151
166
  }
152
167
  ]
153
168
  }
@@ -4,13 +4,14 @@ import nock, { nockInstance, assertNockRequest, mockAutocomplete, mockSetting }
4
4
  import api from '../../../../../services/api';
5
5
  import CONTENT_VIEWS_KEY from '../../../ContentViewsConstants';
6
6
  import ContentViewComponents from '../ContentViewComponents';
7
-
8
- const cvComponentData = require('./contentViewComponents.fixtures.json');
9
- const cvUnpublishedComponentData = require('./unpublishedCVComponents.fixtures.json');
10
- const cvPublishedComponentData = require('./publishedContentViewDetails.fixtures.json');
7
+ import cvComponentData from './contentViewComponents.fixtures.json';
8
+ import cvUnpublishedComponentData from './unpublishedCVComponents.fixtures.json';
9
+ import cvPublishedComponentData from './publishedContentViewDetails.fixtures.json';
10
+ import cvDetails from '../../__tests__/contentViewDetails.fixtures.json';
11
11
 
12
12
  const renderOptions = { apiNamespace: `${CONTENT_VIEWS_KEY}_1` };
13
- const cvComponents = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&status=All');
13
+ const cvComponentsWithoutSearch = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&status=All');
14
+ const cvComponents = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&search=&status=All');
14
15
  const addComponentURL = api.getApiUrl('/content_views/4/content_view_components/add');
15
16
  const publishedComponentDetailsURL = api.getApiUrl('/content_views/13');
16
17
  const removeComponentURL = api.getApiUrl('/content_views/4/content_view_components/remove');
@@ -41,7 +42,7 @@ test('Can call API and show components on page load', async (done) => {
41
42
  .reply(200, cvComponentData);
42
43
 
43
44
  const { getByText, queryByText } = renderWithRedux(
44
- <ContentViewComponents cvId={4} />,
45
+ <ContentViewComponents cvId={4} details={cvDetails} />,
45
46
  renderOptions,
46
47
  );
47
48
 
@@ -63,7 +64,7 @@ test('Can call API and show unpublished components', async (done) => {
63
64
  const unpublishedComponent = cvUnpublishedComponentData.results[1];
64
65
 
65
66
  const { getByText, queryByText, getAllByText } = renderWithRedux(
66
- <ContentViewComponents cvId={4} />,
67
+ <ContentViewComponents cvId={4} details={cvDetails} />,
67
68
  renderOptions,
68
69
  );
69
70
 
@@ -85,7 +86,7 @@ test('Can link to view environment', async () => {
85
86
  .reply(200, cvComponentData);
86
87
 
87
88
  const { getAllByText } = renderWithRedux(
88
- <ContentViewComponents cvId={4} />,
89
+ <ContentViewComponents cvId={4} details={cvDetails} />,
89
90
  renderOptions,
90
91
  );
91
92
 
@@ -114,7 +115,7 @@ test('Can search for component content views in composite view', async (done) =>
114
115
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
115
116
  const withSearchScope = mockAutocomplete(nockInstance, autocompleteUrl, searchQueryMatcher);
116
117
  const { getByText, queryByText, getByLabelText } =
117
- renderWithRedux(<ContentViewComponents cvId={4} />, renderOptions);
118
+ renderWithRedux(<ContentViewComponents cvId={4} details={cvDetails} />, renderOptions);
118
119
 
119
120
  // Basic results showing
120
121
  await patientlyWaitFor(() => {
@@ -152,7 +153,16 @@ test('Can handle no components being present', async (done) => {
152
153
  .get(cvComponents)
153
154
  .reply(200, noResults);
154
155
 
155
- const mockDetails = { label: 'test_empty' };
156
+ const mockDetails = {
157
+ label: 'test_empty',
158
+ permissions: {
159
+ view_content_views: true,
160
+ edit_content_views: true,
161
+ destroy_content_views: true,
162
+ publish_content_views: true,
163
+ promote_or_remove_content_views: true,
164
+ },
165
+ };
156
166
  const { queryByText } =
157
167
  renderWithRedux(<ContentViewComponents cvId={4} details={mockDetails} />, renderOptions);
158
168
 
@@ -165,7 +175,7 @@ test('Can handle no components being present', async (done) => {
165
175
  test('Can add published component views to content view with modal', async (done) => {
166
176
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
167
177
  const scope = nockInstance
168
- .get(cvComponents)
178
+ .get(cvComponentsWithoutSearch)
169
179
  .reply(200, cvComponentData);
170
180
 
171
181
  const returnScope = nockInstance
@@ -174,6 +184,7 @@ test('Can add published component views to content view with modal', async (done
174
184
 
175
185
  const publishedComponentVersionsScope = nockInstance
176
186
  .get(publishedComponentDetailsURL)
187
+ .query(true)
177
188
  .reply(200, cvPublishedComponentData);
178
189
 
179
190
  const addComponentParams = {
@@ -188,7 +199,7 @@ test('Can add published component views to content view with modal', async (done
188
199
  const {
189
200
  getByText, getByLabelText, queryByLabelText, getAllByLabelText,
190
201
  } = renderWithRedux(
191
- <ContentViewComponents cvId={4} />,
202
+ <ContentViewComponents cvId={4} details={cvDetails} />,
192
203
  renderOptions,
193
204
  );
194
205
  await patientlyWaitFor(() => {
@@ -217,7 +228,7 @@ test('Can add published component views to content view with modal', async (done
217
228
  test('Can add unpublished component views to content view', async (done) => {
218
229
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
219
230
  const scope = nockInstance
220
- .get(cvComponents)
231
+ .get(cvComponentsWithoutSearch)
221
232
  .reply(200, cvComponentData);
222
233
 
223
234
  const returnScope = nockInstance
@@ -234,7 +245,7 @@ test('Can add unpublished component views to content view', async (done) => {
234
245
  .reply(200, {});
235
246
 
236
247
  const { getByText, getAllByLabelText } = renderWithRedux(
237
- <ContentViewComponents cvId={4} />,
248
+ <ContentViewComponents cvId={4} details={cvDetails} />,
238
249
  renderOptions,
239
250
  );
240
251
  await patientlyWaitFor(() => {
@@ -253,7 +264,7 @@ test('Can add unpublished component views to content view', async (done) => {
253
264
  test('Can remove component views from content view', async (done) => {
254
265
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
255
266
  const scope = nockInstance
256
- .get(cvComponents)
267
+ .get(cvComponentsWithoutSearch)
257
268
  .reply(200, cvComponentData);
258
269
 
259
270
  const returnScope = nockInstance
@@ -270,7 +281,7 @@ test('Can remove component views from content view', async (done) => {
270
281
  .reply(200, {});
271
282
 
272
283
  const { getByText, getAllByLabelText } = renderWithRedux(
273
- <ContentViewComponents cvId={4} />,
284
+ <ContentViewComponents cvId={4} details={cvDetails} />,
274
285
  renderOptions,
275
286
  );
276
287
  await patientlyWaitFor(() => {
@@ -285,3 +296,56 @@ test('Can remove component views from content view', async (done) => {
285
296
  assertNockRequest(removeComponentScope);
286
297
  assertNockRequest(returnScope, done);
287
298
  });
299
+
300
+ test('Can bulk add component views to content view with modal', async (done) => {
301
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
302
+ const scope = nockInstance
303
+ .get(cvComponentsWithoutSearch)
304
+ .reply(200, cvComponentData);
305
+
306
+ const returnScope = nockInstance
307
+ .get(cvComponents)
308
+ .reply(200, cvComponentData);
309
+
310
+ const addComponentParams = {
311
+ compositeContentViewId: 4,
312
+ components: [{ content_view_version_id: 44 }, { latest: true, content_view_id: 9 }],
313
+ };
314
+
315
+ const addComponentScope = nockInstance
316
+ .put(addComponentURL, addComponentParams)
317
+ .reply(200, {});
318
+
319
+ const {
320
+ getByText, getByLabelText, queryByText,
321
+ } = renderWithRedux(
322
+ <ContentViewComponents cvId={4} details={cvDetails} />,
323
+ renderOptions,
324
+ );
325
+ await patientlyWaitFor(() => {
326
+ expect(getByLabelText('Select row 2')).toBeInTheDocument();
327
+ expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'true');
328
+ });
329
+ fireEvent.click(getByLabelText('Select row 2'));
330
+ fireEvent.click(getByLabelText('Select row 3'));
331
+ await patientlyWaitFor(() => {
332
+ expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'false');
333
+ });
334
+ fireEvent.click(getByLabelText('bulk_add_components'));
335
+ await patientlyWaitFor(() => {
336
+ expect(getByText('Add component content views')).toBeInTheDocument();
337
+ });
338
+ fireEvent.click(getByLabelText('version-select-cv-10'));
339
+ fireEvent.click(getByLabelText('cv-10-3.0'));
340
+
341
+ fireEvent.click(getByLabelText('add_components'));
342
+ await patientlyWaitFor(() => {
343
+ expect(queryByText('Add component content views')).not.toBeInTheDocument();
344
+ expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'false');
345
+ });
346
+
347
+ assertNockRequest(autocompleteScope);
348
+ assertNockRequest(scope);
349
+ assertNockRequest(addComponentScope);
350
+ assertNockRequest(returnScope, done);
351
+ });