katello 4.7.4 → 4.8.0.rc2

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

Potentially problematic release.


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

Files changed (356) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +8 -22
  3. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +15 -12
  4. data/app/controllers/katello/api/v2/alternate_content_sources_controller.rb +7 -5
  5. data/app/controllers/katello/api/v2/capsule_content_controller.rb +0 -4
  6. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +22 -81
  7. data/app/controllers/katello/api/v2/content_exports_controller.rb +11 -80
  8. data/app/controllers/katello/api/v2/content_imports_controller.rb +1 -0
  9. data/app/controllers/katello/api/v2/exports_controller.rb +130 -0
  10. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +7 -8
  11. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +8 -4
  12. data/app/controllers/katello/api/v2/organizations_controller.rb +3 -0
  13. data/app/controllers/katello/api/v2/package_groups_controller.rb +0 -52
  14. data/app/controllers/katello/api/v2/repositories_controller.rb +3 -18
  15. data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +4 -6
  16. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +1 -2
  17. data/app/controllers/katello/concerns/authorization/api/v2/content_views_controller.rb +4 -1
  18. data/app/controllers/katello/concerns/content_facet_hosts_controller_extensions.rb +24 -0
  19. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +3 -3
  20. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +59 -23
  21. data/app/helpers/katello/katello_urls_helper.rb +0 -15
  22. data/app/helpers/katello/sync_management_helper.rb +0 -4
  23. data/app/lib/actions/candlepin/owner/destroy_imports.rb +1 -1
  24. data/app/lib/actions/katello/alternate_content_source/create.rb +3 -1
  25. data/app/lib/actions/katello/alternate_content_source/update.rb +3 -1
  26. data/app/lib/actions/katello/capsule_content/sync.rb +0 -4
  27. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +1 -2
  28. data/app/lib/actions/katello/content_view/publish.rb +6 -2
  29. data/app/lib/actions/katello/content_view/remove.rb +8 -2
  30. data/app/lib/actions/katello/content_view_version/destroy.rb +1 -1
  31. data/app/lib/actions/katello/environment/destroy.rb +8 -2
  32. data/app/lib/actions/katello/host/reassign.rb +4 -2
  33. data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +0 -1
  34. data/app/lib/actions/katello/product/destroy.rb +2 -1
  35. data/app/lib/actions/katello/repository/filtered_index_content.rb +2 -10
  36. data/app/lib/actions/katello/repository/import_upload.rb +0 -1
  37. data/app/lib/actions/katello/repository/sync.rb +0 -1
  38. data/app/lib/actions/katello/repository/update.rb +5 -3
  39. data/app/lib/actions/katello/repository/upload_files.rb +0 -1
  40. data/app/lib/actions/pulp3/abstract.rb +0 -6
  41. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -2
  42. data/app/lib/actions/pulp3/content_view_version/create_syncable_export_history.rb +4 -0
  43. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +1 -1
  44. data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +12 -11
  45. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -2
  46. data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +7 -4
  47. data/app/lib/actions/pulp3/repository/reclaim_space.rb +1 -1
  48. data/app/lib/actions/pulp3/repository/refresh_distribution.rb +1 -2
  49. data/app/lib/actions/pulp3/repository/save_distribution_references.rb +2 -2
  50. data/app/lib/katello/api/v2/error_handling.rb +12 -2
  51. data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -3
  52. data/app/lib/katello/concerns/renderer_extensions.rb +1 -1
  53. data/app/lib/katello/event_daemon/runner.rb +12 -9
  54. data/app/lib/katello/resources/candlepin/consumer.rb +6 -6
  55. data/app/lib/katello/resources/candlepin/owner.rb +1 -1
  56. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +3 -4
  57. data/app/lib/katello/resources/candlepin.rb +4 -4
  58. data/app/lib/katello/util/errata.rb +12 -10
  59. data/app/lib/katello/util/search.rb +0 -1
  60. data/app/lib/katello/validators/content_view_environment_org_validator.rb +5 -2
  61. data/app/lib/katello/validators/content_view_environment_validator.rb +1 -2
  62. data/app/lib/katello/validators/generated_content_view_validator.rb +16 -0
  63. data/app/mailers/katello/errata_mailer.rb +4 -2
  64. data/app/models/katello/alternate_content_source.rb +59 -5
  65. data/app/models/katello/concerns/content_facet_host_extensions.rb +25 -14
  66. data/app/models/katello/concerns/host_managed_extensions.rb +31 -8
  67. data/app/models/katello/concerns/redhat_extensions.rb +16 -6
  68. data/app/models/katello/concerns/smart_proxy_extensions.rb +0 -12
  69. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +1 -0
  70. data/app/models/katello/content_view.rb +22 -5
  71. data/app/models/katello/content_view_environment.rb +11 -2
  72. data/app/models/katello/content_view_environment_content_facet.rb +9 -0
  73. data/app/models/katello/content_view_version.rb +10 -5
  74. data/app/models/katello/erratum.rb +6 -1
  75. data/app/models/katello/glue/candlepin/pool.rb +6 -0
  76. data/app/models/katello/glue/candlepin/product.rb +7 -1
  77. data/app/models/katello/glue/candlepin/subscription.rb +5 -0
  78. data/app/models/katello/glue/provider.rb +26 -26
  79. data/app/models/katello/host/content_facet.rb +108 -18
  80. data/app/models/katello/host/info_provider.rb +25 -21
  81. data/app/models/katello/host/subscription_facet.rb +18 -14
  82. data/app/models/katello/kt_environment.rb +12 -7
  83. data/app/models/katello/package_group.rb +0 -12
  84. data/app/models/katello/pool.rb +4 -1
  85. data/app/models/katello/product.rb +11 -1
  86. data/app/models/katello/repository.rb +11 -11
  87. data/app/models/katello/root_repository.rb +5 -4
  88. data/app/models/katello/task_status.rb +0 -18
  89. data/app/services/katello/candlepin/consumer.rb +2 -2
  90. data/app/services/katello/host/package_profile_uploader.rb +1 -1
  91. data/app/services/katello/product_content_finder.rb +11 -8
  92. data/app/services/katello/pulp3/content_view_version/export.rb +8 -65
  93. data/app/services/katello/pulp3/content_view_version/export_validation_error.rb +7 -0
  94. data/app/services/katello/pulp3/content_view_version/export_validator.rb +121 -0
  95. data/app/services/katello/pulp3/content_view_version/importable_products.rb +1 -1
  96. data/app/services/katello/pulp3/content_view_version/syncable_format_export.rb +7 -1
  97. data/app/services/katello/pulp3/erratum.rb +1 -0
  98. data/app/services/katello/pulp3/module_stream.rb +26 -11
  99. data/app/services/katello/pulp3/repository/yum.rb +2 -1
  100. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +2 -1
  101. data/app/services/katello/registration_manager.rb +46 -26
  102. data/app/services/katello/repository_type.rb +3 -9
  103. data/app/services/katello/simple_package.rb +22 -0
  104. data/app/views/foreman/smart_proxies/_content_sync.html.erb +2 -1
  105. data/app/views/foreman/smart_proxies/_reclaim_space.html.erb +1 -0
  106. data/app/views/katello/api/v2/content_facet/base.json.rabl +23 -2
  107. data/app/views/katello/api/v2/content_facet/show.json.rabl +11 -8
  108. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -1
  109. data/app/views/katello/api/v2/hosts/base.json.rabl +22 -2
  110. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +2 -2
  111. data/config/initializers/monkeys.rb +0 -2
  112. data/config/routes/api/registry.rb +8 -7
  113. data/config/routes/api/v2.rb +0 -2
  114. data/config/routes.rb +3 -0
  115. data/db/migrate/20200429153103_installed_package_bad_nvrea.rb +1 -1
  116. data/db/migrate/20220228173251_remove_drpm_from_ignorable_content.rb +7 -3
  117. data/db/migrate/20220419193414_content_settings_to_dsl_category.rb +1 -1
  118. data/db/migrate/20220929204746_add_content_view_environment_content_facet.rb +52 -0
  119. data/db/migrate/20221123212341_remove_pulp_docker_registry_port_setting.rb +5 -0
  120. data/db/migrate/20230119003859_ensure_repo_username_password_nil_not_blank.rb +1 -1
  121. data/db/migrate/20230203141353_set_new_acs_verify_ssl_default.rb +5 -0
  122. data/db/seeds.d/111-upgrade_tasks.rb +3 -1
  123. data/engines/bastion/app/assets/stylesheets/bastion/bastion.scss +4 -0
  124. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-details.controller.js +2 -4
  125. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +0 -1
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +2 -4
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +2 -1
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +11 -3
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/views/host-collection-hosts-list.html +1 -1
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +8 -4
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +5485 -0
  132. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +5397 -0
  133. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +5658 -0
  134. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +5284 -0
  135. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ka.po +5231 -0
  136. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +5275 -0
  137. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +5389 -0
  138. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +5212 -0
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +5145 -0
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +9 -0
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +2 -2
  142. data/lib/katello/engine.rb +2 -1
  143. data/lib/katello/permission_creator.rb +2 -4
  144. data/lib/katello/permissions/registry_permissions.rb +5 -5
  145. data/lib/katello/plugin.rb +22 -14
  146. data/lib/katello/repository_types/README.md +136 -19
  147. data/lib/katello/repository_types/deb.rb +0 -1
  148. data/lib/katello/repository_types/docker.rb +0 -1
  149. data/lib/katello/repository_types/file.rb +0 -1
  150. data/lib/katello/repository_types/yum.rb +0 -4
  151. data/lib/katello/tasks/clean_candlepin_orphaned_products.rake +38 -0
  152. data/lib/katello/tasks/clean_orphaned_facets.rb +20 -0
  153. data/lib/katello/tasks/reimport.rake +1 -2
  154. data/lib/katello/tasks/repository.rake +1 -22
  155. data/lib/katello/tasks/reset.rake +1 -0
  156. data/lib/katello/tasks/upgrades/4.8/fix_incorrect_providers.rake +29 -0
  157. data/lib/katello/tasks/upgrades/4.8/regenerate_imported_repository_metadata.rake +33 -0
  158. data/lib/katello/version.rb +1 -1
  159. data/lib/katello.rb +0 -5
  160. data/locale/bn/katello.po +69 -27
  161. data/locale/cs/katello.po +69 -27
  162. data/locale/de/katello.po +78 -36
  163. data/locale/en/katello.po +69 -27
  164. data/locale/es/katello.po +70 -28
  165. data/locale/fr/katello.po +73 -31
  166. data/locale/gu/katello.po +69 -27
  167. data/locale/hi/katello.po +69 -27
  168. data/locale/it/katello.po +69 -27
  169. data/locale/ja/katello.po +73 -31
  170. data/locale/ka/katello.po +73 -31
  171. data/locale/katello.pot +335 -262
  172. data/locale/kn/katello.po +69 -27
  173. data/locale/ko/katello.po +69 -27
  174. data/locale/mr/katello.po +69 -27
  175. data/locale/or/katello.po +69 -27
  176. data/locale/pa/katello.po +69 -27
  177. data/locale/pt/katello.po +69 -27
  178. data/locale/pt_BR/katello.po +70 -28
  179. data/locale/ru/katello.po +70 -28
  180. data/locale/ta/katello.po +69 -27
  181. data/locale/te/katello.po +69 -27
  182. data/locale/zh_CN/katello.po +73 -31
  183. data/locale/zh_TW/katello.po +70 -28
  184. data/webpack/components/Content/ContentPage.js +51 -35
  185. data/webpack/components/Content/__tests__/ContentPage.test.js +2 -4
  186. data/webpack/components/Content/__tests__/__snapshots__/ContentPage.test.js.snap +22 -3
  187. data/webpack/components/Table/EmptyStateMessage.js +14 -11
  188. data/webpack/components/Table/MainTable.js +36 -15
  189. data/webpack/components/Table/TableWrapper.js +25 -25
  190. data/webpack/components/Table/__test__/emptyStateMessage.test.js +51 -0
  191. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +10 -72
  192. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +5 -4
  193. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +1 -1
  194. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/hostCollectionsModal.test.js +1 -17
  195. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +18 -9
  196. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +1 -2
  197. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +1 -2
  198. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +1 -2
  199. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +47 -27
  200. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesTab.js +1 -2
  201. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +2 -21
  202. data/webpack/components/extensions/HostDetails/Tabs/__tests__/moduleStreamsTab.test.js +1 -28
  203. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +1 -10
  204. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +1 -18
  205. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +1 -17
  206. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +1 -15
  207. data/webpack/global_test_setup.js +1 -1
  208. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -3
  209. data/webpack/scenes/AlternateContentSources/Create/ACSCreateWizard.js +12 -10
  210. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSCredentials.js +6 -0
  211. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSSmartProxies.js +1 -0
  212. data/webpack/scenes/AlternateContentSources/Create/Steps/AcsUrlPaths.js +3 -10
  213. data/webpack/scenes/AlternateContentSources/Create/Steps/NameACS.js +1 -0
  214. data/webpack/scenes/AlternateContentSources/Create/__tests__/acsCreate.test.js +3 -3
  215. data/webpack/scenes/AlternateContentSources/Details/ACSExpandableDetails.js +6 -5
  216. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditCredentials.js +1 -0
  217. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditDetails.js +3 -1
  218. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditProducts.js +1 -0
  219. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditSmartProxies.js +2 -0
  220. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditURLPaths.js +13 -4
  221. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +7 -4
  222. data/webpack/scenes/AlternateContentSources/MainTable/__tests__/acsTable.test.js +4 -8
  223. data/webpack/scenes/AlternateContentSources/helpers.js +1 -1
  224. data/webpack/scenes/Content/Details/ContentRepositories.js +5 -4
  225. data/webpack/scenes/Content/Details/__tests__/contentDetail.test.js +1 -12
  226. data/webpack/scenes/Content/Table/ContentTable.js +2 -1
  227. data/webpack/scenes/Content/__tests__/contentTable.test.js +1 -14
  228. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +1 -25
  229. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +2 -1
  230. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +44 -31
  231. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +3 -0
  232. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +6 -1
  233. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +2 -1
  234. data/webpack/scenes/ContentViews/Details/Filters/CVDebFilterContent.js +2 -1
  235. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +3 -1
  236. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +3 -1
  237. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +3 -1
  238. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +2 -1
  239. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +2 -0
  240. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +2 -1
  241. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVDebMatchContentModal.js +1 -1
  242. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVRpmMatchContentModal.js +1 -1
  243. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentModal.test.js +35 -33
  244. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +48 -45
  245. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +58 -24
  246. data/webpack/scenes/ContentViews/Details/Filters/__tests__/ContentViewPackageGroupFilter.test.js +64 -0
  247. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +36 -20
  248. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +40 -23
  249. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataIDFilter.test.js +0 -13
  250. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilter.test.js +0 -13
  251. data/webpack/scenes/ContentViews/Details/Histories/ContentViewHistories.js +2 -1
  252. data/webpack/scenes/ContentViews/Details/Histories/__tests__/contentViewHistory.test.js +1 -10
  253. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +2 -1
  254. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +1 -10
  255. data/webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompareConfig.js +21 -9
  256. data/webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompareTable.js +4 -0
  257. data/webpack/scenes/ContentViews/Details/Versions/Compare/__tests__/CVVersionCompare.test.js +1 -32
  258. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +3 -1
  259. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +1 -15
  260. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -1
  261. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -2
  262. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +31 -9
  263. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +4 -0
  264. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +30 -14
  265. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +1 -1
  266. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +55 -120
  267. data/webpack/scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption.js +87 -0
  268. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +1 -1
  269. data/webpack/scenes/ContentViews/components/WizardHeader.js +1 -1
  270. data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +1 -1
  271. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsModal.test.js +8 -1
  272. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +153 -28
  273. data/webpack/scenes/Hosts/ChangeContentSource/index.js +14 -15
  274. data/webpack/scenes/Hosts/ChangeContentSource/selectors.js +4 -0
  275. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +4 -0
  276. data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +3 -9
  277. data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamPage.test.js.snap +7 -1
  278. data/webpack/scenes/RedHatRepositories/components/Search.js +22 -16
  279. data/webpack/scenes/RedHatRepositories/index.scss +20 -1
  280. data/webpack/scenes/SmartProxy/SmartProxyContentTable.js +12 -1
  281. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +1 -1
  282. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CustomCdnTypeForm.js +1 -1
  283. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +21 -19
  284. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +34 -1
  285. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +20 -7
  286. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.test.js +0 -1
  287. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/__snapshots__/SubscriptionsToolbar.test.js.snap +65 -15
  288. metadata +52 -115
  289. data/app/lib/actions/katello/pulp_selector.rb +0 -24
  290. data/app/lib/actions/katello/repository/correct_checksum.rb +0 -24
  291. data/app/lib/actions/katello/repository/destroy_package_group.rb +0 -26
  292. data/app/lib/actions/katello/repository/upload_package_group.rb +0 -24
  293. data/app/lib/actions/pulp/abstract.rb +0 -37
  294. data/app/lib/actions/pulp/abstract_async_task.rb +0 -154
  295. data/app/lib/actions/pulp/abstract_async_task_group.rb +0 -94
  296. data/app/lib/actions/pulp/consumer/sync_capsule.rb +0 -45
  297. data/app/lib/actions/pulp/consumer/unassociate_units.rb +0 -20
  298. data/app/lib/actions/pulp/expect_one_task.rb +0 -11
  299. data/app/lib/actions/pulp/orchestration/orphan_cleanup/remove_orphans.rb +0 -16
  300. data/app/lib/actions/pulp/orchestration/repository/copy_all_units.rb +0 -19
  301. data/app/lib/actions/pulp/orchestration/repository/delete.rb +0 -15
  302. data/app/lib/actions/pulp/orchestration/repository/refresh.rb +0 -14
  303. data/app/lib/actions/pulp/orchestration/repository/refresh_if_needed.rb +0 -13
  304. data/app/lib/actions/pulp/orchestration/repository/refresh_repos.rb +0 -19
  305. data/app/lib/actions/pulp/orchestration/repository/remove_units.rb +0 -14
  306. data/app/lib/actions/pulp/orchestration/repository/smart_proxy_sync.rb +0 -34
  307. data/app/lib/actions/pulp/orchestration/repository/sync.rb +0 -18
  308. data/app/lib/actions/pulp/orchestration/repository/upload_content.rb +0 -37
  309. data/app/lib/actions/pulp/orphan_cleanup/remove_orphans.rb +0 -15
  310. data/app/lib/actions/pulp/orphan_cleanup/remove_unneeded_repos.rb +0 -16
  311. data/app/lib/actions/pulp/repository/abstract_copy_content.rb +0 -45
  312. data/app/lib/actions/pulp/repository/abstract_remove_content.rb +0 -32
  313. data/app/lib/actions/pulp/repository/clear.rb +0 -18
  314. data/app/lib/actions/pulp/repository/copy_all_units.rb +0 -30
  315. data/app/lib/actions/pulp/repository/copy_units.rb +0 -25
  316. data/app/lib/actions/pulp/repository/create.rb +0 -28
  317. data/app/lib/actions/pulp/repository/create_in_plan.rb +0 -15
  318. data/app/lib/actions/pulp/repository/create_upload_request.rb +0 -20
  319. data/app/lib/actions/pulp/repository/delete_upload_request.rb +0 -19
  320. data/app/lib/actions/pulp/repository/destroy.rb +0 -28
  321. data/app/lib/actions/pulp/repository/distributor_publish.rb +0 -25
  322. data/app/lib/actions/pulp/repository/download.rb +0 -16
  323. data/app/lib/actions/pulp/repository/import_upload.rb +0 -19
  324. data/app/lib/actions/pulp/repository/presenters/abstract_sync_presenter.rb +0 -47
  325. data/app/lib/actions/pulp/repository/presenters/deb_presenter.rb +0 -95
  326. data/app/lib/actions/pulp/repository/presenters/docker_presenter.rb +0 -103
  327. data/app/lib/actions/pulp/repository/presenters/file_unit_presenter.rb +0 -42
  328. data/app/lib/actions/pulp/repository/presenters/yum_presenter.rb +0 -131
  329. data/app/lib/actions/pulp/repository/refresh.rb +0 -21
  330. data/app/lib/actions/pulp/repository/regenerate_applicability.rb +0 -21
  331. data/app/lib/actions/pulp/repository/remove_distribution.rb +0 -11
  332. data/app/lib/actions/pulp/repository/remove_units.rb +0 -44
  333. data/app/lib/actions/pulp/repository/sync.rb +0 -99
  334. data/app/lib/actions/pulp/repository/upload_file.rb +0 -28
  335. data/app/lib/actions/pulp/repository_group/create.rb +0 -31
  336. data/app/lib/actions/pulp/repository_group/delete.rb +0 -17
  337. data/app/lib/actions/pulp/repository_group/export.rb +0 -51
  338. data/app/lib/katello/util/package_clause_generator.rb +0 -77
  339. data/app/models/katello/glue/pulp/pulp_errors.rb +0 -9
  340. data/app/models/katello/glue/pulp/repo.rb +0 -353
  341. data/app/models/katello/pulp_sync_status.rb +0 -165
  342. data/app/models/katello/pulp_task_status.rb +0 -63
  343. data/app/services/katello/pulp/content.rb +0 -24
  344. data/app/services/katello/pulp/importer_comparison.rb +0 -28
  345. data/app/services/katello/pulp/repository/deb.rb +0 -61
  346. data/app/services/katello/pulp/repository/docker.rb +0 -82
  347. data/app/services/katello/pulp/repository/file.rb +0 -52
  348. data/app/services/katello/pulp/repository/yum.rb +0 -205
  349. data/app/services/katello/pulp/repository.rb +0 -327
  350. data/app/services/katello/pulp/server.rb +0 -35
  351. data/app/services/katello/pulp/simple_package.rb +0 -24
  352. data/app/services/katello/pulp/smart_proxy_repository.rb +0 -52
  353. data/lib/monkeys/fix_deb_optimized_sync.rb +0 -35
  354. data/lib/monkeys/fix_pulp_container_path.rb +0 -35
  355. data/locale/zanata.xml +0 -30
  356. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentSearch.fixtures.json +0 -33
@@ -1,16 +1,15 @@
1
1
  import React from 'react';
2
2
  import { shallow } from 'enzyme';
3
3
  import toJson from 'enzyme-to-json';
4
+ import SearchBar from 'foremanReact/components/SearchBar';
4
5
  import ContentPage from '../ContentPage';
5
6
  import ContentTable from '../ContentTable';
6
- import Search from '../../../components/Search/index';
7
7
 
8
8
  describe('Content page', () => {
9
9
  it('should render and contain appropriate components', async () => {
10
10
  const contentHeader = 'Content Header';
11
11
  const content = {};
12
12
  const onSearch = () => {};
13
- const getAutoCompleteParams = () => {};
14
13
  const updateSearchQuery = () => {};
15
14
  const searchQuery = '';
16
15
  const onPaginationChange = () => {};
@@ -21,7 +20,6 @@ describe('Content page', () => {
21
20
  content={content}
22
21
  tableSchema={TableSchema}
23
22
  onSearch={onSearch}
24
- getAutoCompleteParams={getAutoCompleteParams}
25
23
  updateSearchQuery={updateSearchQuery}
26
24
  initialInputValue={searchQuery}
27
25
  onPaginationChange={onPaginationChange}
@@ -29,6 +27,6 @@ describe('Content page', () => {
29
27
 
30
28
  expect(toJson(wrapper)).toMatchSnapshot();
31
29
  expect(wrapper.find(ContentTable)).toHaveLength(1);
32
- expect(wrapper.find(Search)).toHaveLength(1);
30
+ expect(wrapper.find(SearchBar)).toHaveLength(1);
33
31
  });
34
32
  });
@@ -40,11 +40,30 @@ exports[`Content page should render and contain appropriate components 1`] = `
40
40
  bsClass="form-group"
41
41
  className="toolbar-pf toolbar-pf-filter"
42
42
  >
43
- <Connect(Search)
44
- getAutoCompleteParams={[Function]}
43
+ <SearchBar
44
+ data={
45
+ Object {
46
+ "autocomplete": Object {
47
+ "apiParams": Object {},
48
+ "id": "searchBar-content-page-Content Header",
49
+ "searchQuery": "",
50
+ "url": "undefined/auto_complete_search",
51
+ "useKeyShortcuts": true,
52
+ },
53
+ "bookmarks": Object {
54
+ "canCreate": true,
55
+ "documentationUrl": "/links/manual/4.1.5Searching",
56
+ "id": "searchBar-content-page-Content Header",
57
+ "url": "/api/bookmarks",
58
+ },
59
+ "controller": undefined,
60
+ }
61
+ }
45
62
  initialInputValue=""
63
+ initialQuery=""
64
+ name={null}
46
65
  onSearch={[Function]}
47
- updateSearchQuery={[Function]}
66
+ onSearchChange={[Function]}
48
67
  />
49
68
  </FormGroup>
50
69
  </Form>
@@ -33,9 +33,9 @@ const EmptyStateMessage = ({
33
33
  let emptyStateTitle = title;
34
34
  let emptyStateBody = body;
35
35
  const {
36
- primaryActionTitle, showPrimaryAction, showSecondaryAction,
36
+ primaryActionTitle, showPrimaryAction, showSecondaryAction, showSecondaryActionButton,
37
37
  secondaryActionTitle, primaryActionLink, secondaryActionLink, searchIsActive, resetFilters,
38
- filtersAreActive, requestKey, primaryActionButton,
38
+ filtersAreActive, requestKey, primaryActionButton, secondaryActionTextOverride,
39
39
  } = extraTableProps;
40
40
  if (error) {
41
41
  if (error?.response?.data?.error) {
@@ -48,14 +48,16 @@ const EmptyStateMessage = ({
48
48
  emptyStateBody = error?.response?.data?.displayMessage || __('Something went wrong! Please check server logs!');
49
49
  }
50
50
  }
51
- const secondaryActionText = searchIsActive ? __('Clear search') : __('Clear filters');
51
+ const defaultSecondaryActionText = searchIsActive ? __('Clear search') : __('Clear filters');
52
+ const secondaryActionText = secondaryActionTextOverride || defaultSecondaryActionText;
52
53
  const dispatch = useDispatch();
53
54
  const clearSearch = useSelector(selectHostDetailsClearSearch);
55
+ const showSecondaryActionAnchor = showSecondaryAction && secondaryActionLink;
54
56
  const handleClick = () => {
55
57
  if (searchIsActive) {
56
58
  clearSearch();
57
59
  }
58
- if (filtersAreActive) {
60
+ if (filtersAreActive || showSecondaryActionButton) {
59
61
  resetFilters();
60
62
  }
61
63
  dispatch({
@@ -65,7 +67,7 @@ const EmptyStateMessage = ({
65
67
  };
66
68
 
67
69
  const actionButton = primaryActionButton ?? (
68
- <Button>
70
+ <Button ouiaId="empty-state-primary-action-button">
69
71
  <a href={primaryActionLink} style={{ color: 'white', textDecoration: 'none' }}>{primaryActionTitle}</a>
70
72
  </Button>
71
73
  );
@@ -87,17 +89,17 @@ const EmptyStateMessage = ({
87
89
  {emptyStateBody}
88
90
  </EmptyStateBody>
89
91
  {showPrimaryAction && actionButton}
90
- {showSecondaryAction &&
92
+ {showSecondaryActionAnchor &&
91
93
  <EmptyStateSecondaryActions>
92
- <Button variant="link">
94
+ <Button variant="link" ouiaId="empty-state-secondary-action-link">
93
95
  <a href={secondaryActionLink} style={{ textDecoration: 'none' }}>{secondaryActionTitle}</a>
94
96
  </Button>
95
97
  </EmptyStateSecondaryActions>
96
98
  }
97
99
 
98
- {(searchIsActive || !!filtersAreActive) &&
100
+ {(showSecondaryActionButton || searchIsActive || !!filtersAreActive) &&
99
101
  <EmptyStateSecondaryActions>
100
- <Button variant="link" onClick={handleClick}>
102
+ <Button variant="link" onClick={handleClick} ouiaId="empty-state-secondary-action-router-link">
101
103
  {secondaryActionText}
102
104
  </Button>
103
105
  </EmptyStateSecondaryActions>
@@ -143,9 +145,10 @@ EmptyStateMessage.propTypes = {
143
145
  ])),
144
146
  // eslint-disable-next-line react/require-default-props
145
147
  resetFilters: (props, propName) => {
146
- if (props.defaultFilters?.length || props.activeFilters?.length) {
148
+ if (props.showSecondaryActionButton || props.defaultFilters?.length
149
+ || props.activeFilters?.length) {
147
150
  if (typeof props[propName] !== 'function') {
148
- return new Error(`A ${propName} function is required when using activeFilters or defaultFilters`);
151
+ return new Error(`A ${propName} function is required when using activeFilters, defaultFilters, or showSecondaryActionButton`);
149
152
  }
150
153
  }
151
154
  return null;
@@ -16,11 +16,12 @@ import Loading from '../../components/Loading';
16
16
 
17
17
  const MainTable = ({
18
18
  status, cells, rows, error, emptyContentTitle, emptyContentBody,
19
- emptySearchTitle, emptySearchBody, errorSearchTitle, errorSearchBody,
20
- happyEmptyContent, searchIsActive, activeFilters, defaultFilters, actionButtons, rowsCount,
21
- children, showPrimaryAction, showSecondaryAction, primaryActionLink,
22
- secondaryActionLink, primaryActionTitle, secondaryActionTitle, resetFilters,
23
- updateSearchQuery, requestKey, primaryActionButton, ...extraTableProps
19
+ emptyContentOverride, emptySearchTitle, emptySearchBody, errorSearchTitle, errorSearchBody,
20
+ happyEmptyContent, searchIsActive, activeFilters, defaultFilters,
21
+ activeToggleState, unfilteredToggleState, actionButtons, rowsCount,
22
+ children, showPrimaryAction, showSecondaryAction, showSecondaryActionButton, primaryActionLink,
23
+ secondaryActionLink, primaryActionTitle, secondaryActionTitle, secondaryActionTextOverride,
24
+ resetFilters, updateSearchQuery, requestKey, primaryActionButton, ...extraTableProps
24
25
  }) => {
25
26
  const tableHasNoRows = () => {
26
27
  if (children) return rowsCount === 0;
@@ -29,15 +30,20 @@ const MainTable = ({
29
30
  const callToActionProps = {
30
31
  showPrimaryAction,
31
32
  showSecondaryAction,
33
+ showSecondaryActionButton,
32
34
  primaryActionLink,
33
35
  primaryActionTitle,
34
36
  secondaryActionLink,
35
37
  secondaryActionTitle,
36
38
  primaryActionButton,
39
+ secondaryActionTextOverride,
40
+ emptyContentOverride,
37
41
  };
38
42
  const filtersAreActive = activeFilters?.length &&
39
43
  !isEqual(new Set(activeFilters), new Set(defaultFilters));
40
- const isFiltering = searchIsActive || filtersAreActive;
44
+ const toggleIsActive = activeToggleState !== unfilteredToggleState;
45
+ const isSearchingOrFiltering = searchIsActive || filtersAreActive || toggleIsActive;
46
+
41
47
  if (status === STATUS.PENDING) return (<Loading />);
42
48
  const clearSearchProps = {
43
49
  resetFilters,
@@ -48,6 +54,10 @@ const MainTable = ({
48
54
  defaultFilters,
49
55
  activeFilters,
50
56
  };
57
+
58
+ const tableWouldBeEmpty = (status === STATUS.RESOLVED && tableHasNoRows());
59
+ const emptyContent = emptyContentOverride || (tableWouldBeEmpty && !isSearchingOrFiltering);
60
+ const emptySearch = (tableWouldBeEmpty && isSearchingOrFiltering);
51
61
  // Can we display the error message?
52
62
  if (status === STATUS.ERROR) return (<EmptyStateMessage error={error} />);
53
63
 
@@ -60,25 +70,26 @@ const MainTable = ({
60
70
  search
61
71
  />);
62
72
  }
63
- if (status === STATUS.RESOLVED && isFiltering && tableHasNoRows()) {
64
- return (<EmptyStateMessage
65
- title={emptySearchTitle}
66
- body={emptySearchBody}
67
- search
68
- {...clearSearchProps}
69
- />);
70
- }
71
- if (status === STATUS.RESOLVED && tableHasNoRows()) {
73
+ if (emptyContent) {
72
74
  return (
73
75
  <EmptyStateMessage
74
76
  title={emptyContentTitle}
75
77
  body={emptyContentBody}
76
78
  happy={happyEmptyContent}
77
79
  search={!happyEmptyContent}
80
+ {...clearSearchProps}
78
81
  {...callToActionProps}
79
82
  />
80
83
  );
81
84
  }
85
+ if (emptySearch) {
86
+ return (<EmptyStateMessage
87
+ title={emptySearchTitle}
88
+ body={emptySearchBody}
89
+ search
90
+ {...clearSearchProps}
91
+ />);
92
+ }
82
93
 
83
94
  const tableProps = { cells, rows, ...extraTableProps };
84
95
  if (children) {
@@ -129,6 +140,8 @@ MainTable.propTypes = {
129
140
  PropTypes.string,
130
141
  PropTypes.arrayOf(PropTypes.string),
131
142
  ])),
143
+ activeToggleState: PropTypes.string,
144
+ unfilteredToggleState: PropTypes.string,
132
145
  actionButtons: PropTypes.bool,
133
146
  rowsCount: PropTypes.number,
134
147
  children: PropTypes.oneOfType([
@@ -136,8 +149,11 @@ MainTable.propTypes = {
136
149
  PropTypes.node,
137
150
  ]),
138
151
  happyEmptyContent: PropTypes.bool,
152
+ emptyContentOverride: PropTypes.bool,
139
153
  showPrimaryAction: PropTypes.bool,
140
154
  showSecondaryAction: PropTypes.bool,
155
+ showSecondaryActionButton: PropTypes.bool,
156
+ secondaryActionTextOverride: PropTypes.string,
141
157
  primaryActionLink: PropTypes.string,
142
158
  secondaryActionLink: PropTypes.string,
143
159
  secondaryActionTitle: PropTypes.string,
@@ -153,6 +169,8 @@ MainTable.defaultProps = {
153
169
  searchIsActive: false,
154
170
  activeFilters: [],
155
171
  defaultFilters: [],
172
+ activeToggleState: '',
173
+ unfilteredToggleState: '',
156
174
  errorSearchTitle: __('Problem searching'),
157
175
  errorSearchBody: '',
158
176
  actionButtons: false,
@@ -161,8 +179,11 @@ MainTable.defaultProps = {
161
179
  rows: undefined,
162
180
  rowsCount: undefined,
163
181
  happyEmptyContent: false,
182
+ emptyContentOverride: false,
164
183
  showPrimaryAction: false,
165
184
  showSecondaryAction: false,
185
+ showSecondaryActionButton: false,
186
+ secondaryActionTextOverride: '',
166
187
  primaryActionLink: '',
167
188
  secondaryActionLink: '',
168
189
  primaryActionTitle: '',
@@ -2,8 +2,9 @@ import React, { useCallback, useRef } from 'react';
2
2
  import useDeepCompareEffect from 'use-deep-compare-effect';
3
3
  import PropTypes from 'prop-types';
4
4
  import { useDispatch } from 'react-redux';
5
- import { isEqual } from 'lodash';
6
- import { STATUS } from 'foremanReact/constants';
5
+ import { isEqual, isEmpty } from 'lodash';
6
+ import SearchBar from 'foremanReact/components/SearchBar';
7
+ import { STATUS, getControllerSearchProps } from 'foremanReact/constants';
7
8
  import { noop } from 'foremanReact/common/helpers';
8
9
  import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
9
10
  import { PaginationVariant, Flex, FlexItem } from '@patternfly/react-core';
@@ -11,7 +12,6 @@ import { translate as __ } from 'foremanReact/common/I18n';
11
12
  import PageControls from './PageControls';
12
13
  import MainTable from './MainTable';
13
14
  import { getPageStats } from './helpers';
14
- import Search from '../../components/Search';
15
15
  import SelectAllCheckbox from '../SelectAllCheckbox';
16
16
  import { orgId } from '../../services/api';
17
17
 
@@ -25,7 +25,7 @@ const TableWrapper = ({
25
25
  metadata,
26
26
  fetchItems,
27
27
  autocompleteEndpoint,
28
- foremanApiAutoComplete,
28
+ autocompleteQueryParams,
29
29
  searchQuery,
30
30
  updateSearchQuery,
31
31
  searchPlaceholderText,
@@ -43,6 +43,7 @@ const TableWrapper = ({
43
43
  clearSelectedResults,
44
44
  emptySearchBody,
45
45
  hideSearch,
46
+ alwaysHideToolbar,
46
47
  nodesBelowSearch,
47
48
  bookmarkController,
48
49
  readOnlyBookmarks,
@@ -60,8 +61,8 @@ const TableWrapper = ({
60
61
  const showPagination = !unresolvedStatusOrNoRows;
61
62
  const filtersAreActive = activeFilters?.length &&
62
63
  !isEqual(new Set(activeFilters), new Set(allTableProps.defaultFilters));
63
- const hideToolbar = !searchQuery && !filtersAreActive &&
64
- allTableProps.status === STATUS.RESOLVED && total === 0;
64
+ const hideToolbar = alwaysHideToolbar || (!searchQuery && !filtersAreActive &&
65
+ allTableProps.status === STATUS.RESOLVED && total === 0);
65
66
  const showActionButtons = actionButtons && (alwaysShowActionButtons || !hideToolbar);
66
67
  const showToggleGroup = toggleGroup && (alwaysShowToggleGroup || !hideToolbar);
67
68
  const paginationParams = useCallback(() =>
@@ -131,14 +132,6 @@ const TableWrapper = ({
131
132
  spawnFetch();
132
133
  }, [searchQuery, spawnFetch, additionalListeners]);
133
134
 
134
- const getAutoCompleteParams = search => ({
135
- endpoint: autocompleteEndpoint,
136
- params: {
137
- organization_id: orgId(),
138
- search,
139
- },
140
- });
141
-
142
135
  // If the new page wouldn't exist because of a perPage change,
143
136
  // we should set the current page to the last page.
144
137
  const validatePagination = (data) => {
@@ -164,6 +157,17 @@ const TableWrapper = ({
164
157
  spawnFetch(pagData);
165
158
  paginationChangePending.current = pagData;
166
159
  };
160
+
161
+ const extraSearchProps = (isEmpty(bookmarkController)) ?
162
+ { bookmarks: {} } :
163
+ { controller: bookmarkController };
164
+ const apiParams = { ...autocompleteQueryParams, organization_id: orgId() };
165
+ const searchDataProp = {
166
+ ...getControllerSearchProps(autocompleteEndpoint, `searchBar-${bookmarkController}`, !readOnlyBookmarks, apiParams),
167
+ ...extraSearchProps,
168
+ isDisabled: unresolvedStatusOrNoRows && !searchQuery,
169
+ };
170
+
167
171
  return (
168
172
  <>
169
173
  <Flex style={{ alignItems: 'center' }} className="margin-16-24">
@@ -186,16 +190,10 @@ const TableWrapper = ({
186
190
  }
187
191
  {!hideSearch && !hideToolbar &&
188
192
  <FlexItem>
189
- <Search
190
- isDisabled={unresolvedStatusOrNoRows && !searchQuery}
191
- patternfly4
192
- initialInputValue={searchQuery && searchQuery}
193
+ <SearchBar
194
+ data={searchDataProp}
195
+ initialQuery={searchQuery}
193
196
  onSearch={search => updateSearchQuery(search)}
194
- getAutoCompleteParams={getAutoCompleteParams}
195
- foremanApiAutoComplete={foremanApiAutoComplete}
196
- bookmarkController={bookmarkController}
197
- readOnlyBookmarks={readOnlyBookmarks}
198
- placeholder={searchPlaceholderText}
199
197
  />
200
198
  </FlexItem>
201
199
  }
@@ -272,7 +270,7 @@ TableWrapper.propTypes = {
272
270
  search: PropTypes.string,
273
271
  }),
274
272
  autocompleteEndpoint: PropTypes.string.isRequired,
275
- foremanApiAutoComplete: PropTypes.bool,
273
+ autocompleteQueryParams: PropTypes.shape({}),
276
274
  searchPlaceholderText: PropTypes.string,
277
275
  actionButtons: PropTypes.node,
278
276
  alwaysShowActionButtons: PropTypes.bool,
@@ -305,6 +303,7 @@ TableWrapper.propTypes = {
305
303
  areAllRowsSelected: PropTypes.func,
306
304
  emptySearchBody: PropTypes.string,
307
305
  hideSearch: PropTypes.bool,
306
+ alwaysHideToolbar: PropTypes.bool,
308
307
  nodesBelowSearch: PropTypes.node,
309
308
  bookmarkController: PropTypes.string,
310
309
  readOnlyBookmarks: PropTypes.bool,
@@ -317,7 +316,6 @@ TableWrapper.defaultProps = {
317
316
  additionalListeners: [],
318
317
  activeFilters: [],
319
318
  defaultFilters: [],
320
- foremanApiAutoComplete: false,
321
319
  searchPlaceholderText: undefined,
322
320
  actionButtons: null,
323
321
  alwaysShowActionButtons: true,
@@ -335,10 +333,12 @@ TableWrapper.defaultProps = {
335
333
  areAllRowsSelected: noop,
336
334
  emptySearchBody: __('Try changing your search settings.'),
337
335
  hideSearch: false,
336
+ alwaysHideToolbar: false,
338
337
  nodesBelowSearch: null,
339
338
  bookmarkController: undefined,
340
339
  readOnlyBookmarks: false,
341
340
  resetFilters: undefined,
341
+ autocompleteQueryParams: undefined,
342
342
  };
343
343
 
344
344
  export default TableWrapper;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { renderWithRedux, patientlyWaitFor } from 'react-testing-lib-wrapper';
3
+ import EmptyStateMessage from '../EmptyStateMessage';
4
+
5
+ describe('EmptyStateMessage', () => {
6
+ test('Shows clear search link when there are no results', async (done) => {
7
+ const { getByText } = renderWithRedux(<EmptyStateMessage
8
+ title="empty content title"
9
+ body="empty content body"
10
+ search
11
+ searchIsActive
12
+ />);
13
+
14
+ // Verify that the clear search link is visible
15
+ await patientlyWaitFor(() => expect(getByText('Clear search')).toBeInTheDocument());
16
+
17
+ done();
18
+ });
19
+
20
+ test('Shows clear filters link when there are no results', async (done) => {
21
+ const { getByText } = renderWithRedux(<EmptyStateMessage
22
+ title="empty content title"
23
+ body="empty content body"
24
+ search
25
+ filtersAreActive
26
+ activeFilters={['foo']}
27
+ resetFilters={jest.fn()}
28
+ />);
29
+
30
+ // Verify that the clear filters link is visible
31
+ await patientlyWaitFor(() => expect(getByText('Clear filters')).toBeInTheDocument());
32
+
33
+ done();
34
+ });
35
+
36
+ test('Handles override of secondaryActionText', async (done) => {
37
+ const { getByText } = renderWithRedux(<EmptyStateMessage
38
+ title="empty content title"
39
+ body="empty content body"
40
+ resetFilters={jest.fn()}
41
+ showSecondaryActionButton
42
+ secondaryActionTextOverride="Custom text"
43
+ />);
44
+
45
+ // Verify that the custom text is visible
46
+ await patientlyWaitFor(() => expect(getByText('Custom text')).toBeInTheDocument());
47
+
48
+ done();
49
+ });
50
+ });
51
+
@@ -1,11 +1,7 @@
1
1
  import React, { useState, useCallback } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
3
  import { useDispatch, useSelector } from 'react-redux';
5
- import { Modal, Button, SelectOption, Alert, Flex } from '@patternfly/react-core';
6
- import {
7
- global_palette_black_600 as pfDescriptionColor,
8
- } from '@patternfly/react-tokens';
4
+ import { Modal, Button, Alert } from '@patternfly/react-core';
9
5
  import { translate as __ } from 'foremanReact/common/I18n';
10
6
  import { STATUS } from 'foremanReact/constants';
11
7
  import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
@@ -15,42 +11,15 @@ import { ENVIRONMENT_PATHS_KEY } from '../../../../../scenes/ContentViews/compon
15
11
  import api from '../../../../../services/api';
16
12
  import getContentViews from '../../../../../scenes/ContentViews/ContentViewsActions';
17
13
  import { selectContentViews, selectContentViewStatus } from '../../../../../scenes/ContentViews/ContentViewSelectors';
18
- import { uniq } from '../../../../../utils/helpers';
19
- import ContentViewIcon from '../../../../../scenes/ContentViews/components/ContentViewIcon';
20
14
  import updateHostContentViewAndEnvironment from './HostContentViewActions';
21
15
  import HOST_CV_AND_ENV_KEY from './HostContentViewConstants';
22
16
  import { getHostDetails } from '../../HostDetailsActions';
23
17
  import ContentViewSelect from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelect';
18
+ import ContentViewSelectOption
19
+ from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption';
24
20
 
25
21
  const ENV_PATH_OPTIONS = { key: ENVIRONMENT_PATHS_KEY };
26
22
 
27
- const ContentViewDescription = ({ cv, versionNumber }) => {
28
- const descriptionStyle = {
29
- fontSize: '12px',
30
- fontWeight: 400,
31
- color: pfDescriptionColor.value,
32
- };
33
- if (cv.default) return <span style={descriptionStyle}>{__('Library')}</span>;
34
- return (
35
- <span style={descriptionStyle}>
36
- <FormattedMessage
37
- id={`content-view-${cv.id}-version-${cv.latest_version}`}
38
- defaultMessage="Version {versionNumber}"
39
- values={{ versionNumber }}
40
- />
41
- </span>
42
- );
43
- };
44
-
45
- ContentViewDescription.propTypes = {
46
- cv: PropTypes.shape({
47
- default: PropTypes.bool.isRequired,
48
- id: PropTypes.number.isRequired,
49
- latest_version: PropTypes.string.isRequired,
50
- }).isRequired,
51
- versionNumber: PropTypes.string.isRequired,
52
- };
53
-
54
23
  const ChangeHostCVModal = ({
55
24
  isOpen,
56
25
  closeModal,
@@ -66,6 +35,7 @@ const ChangeHostCVModal = ({
66
35
  const [cvSelectOpen, setCVSelectOpen] = useState(false);
67
36
  const dispatch = useDispatch();
68
37
  const contentViewsInEnvResponse = useSelector(state => selectContentViews(state, `FOR_ENV_${hostEnvId}`));
38
+ const { results } = contentViewsInEnvResponse;
69
39
  const contentViewsInEnvStatus = useSelector(state => selectContentViewStatus(state, `FOR_ENV_${hostEnvId}`));
70
40
  const hostUpdateStatus = useSelector(state => selectAPIStatus(state, HOST_CV_AND_ENV_KEY));
71
41
  useAPI( // No TableWrapper here, so we can useAPI from Foreman
@@ -73,6 +43,7 @@ const ChangeHostCVModal = ({
73
43
  api.getApiUrl(`/organizations/${orgId}/environments/paths?permission_type=promotable`),
74
44
  ENV_PATH_OPTIONS,
75
45
  );
46
+ const selectedCVForHostId = results?.find(cv => cv.name === selectedCVForHost)?.id;
76
47
 
77
48
  const handleModalClose = () => {
78
49
  setCVSelectOpen(false);
@@ -102,13 +73,6 @@ const ChangeHostCVModal = ({
102
73
  const { results: contentViewsInEnv = [] } = contentViewsInEnvResponse;
103
74
  const canSave = !!(selectedCVForHost && selectedEnvForHost.length);
104
75
 
105
- const relevantVersionObjFromCv = (cv, env) => { // returns the entire version object
106
- const versions = cv.versions.filter(version => new Set(version.environment_ids).has(env.id));
107
- return uniq(versions)?.[0];
108
- };
109
- const relevantVersionFromCv = (cv, env) =>
110
- relevantVersionObjFromCv(cv, env)?.version; // returns the version text e.g. "1.0"
111
-
112
76
  const refreshHostDetails = () => {
113
77
  handleModalClose();
114
78
  return dispatch(getHostDetails({ hostname: hostName }));
@@ -119,7 +83,7 @@ const ChangeHostCVModal = ({
119
83
  id: hostId,
120
84
  host: {
121
85
  content_facet_attributes: {
122
- content_view_id: selectedCVForHost,
86
+ content_view_id: selectedCVForHostId,
123
87
  lifecycle_environment_id: selectedEnvId,
124
88
  },
125
89
  },
@@ -183,7 +147,7 @@ const ChangeHostCVModal = ({
183
147
  headerText={__('Select environment')}
184
148
  isDisabled={hostUpdateStatus === STATUS.PENDING}
185
149
  />
186
- {selectedEnvForHost.length > 0 &&
150
+ {selectedEnvForHost.length > 0 && contentViewsInEnvStatus !== STATUS.PENDING &&
187
151
  <ContentViewSelect
188
152
  selections={selectedCVForHost}
189
153
  onClear={() => setSelectedCVForHost(null)}
@@ -193,35 +157,9 @@ const ChangeHostCVModal = ({
193
157
  onToggle={isExpanded => setCVSelectOpen(isExpanded)}
194
158
  placeholderText={cvPlaceholderText()}
195
159
  >
196
- {contentViewsInEnv?.map(cv => (
197
- <SelectOption
198
- key={cv.id}
199
- value={cv.id}
200
- >
201
- <Flex
202
- direction={{ default: 'row', sm: 'row' }}
203
- flexWrap={{ default: 'nowrap' }}
204
- alignItems={{ default: 'alignItemsCenter', sm: 'alignItemsCenter' }}
205
- >
206
- <ContentViewIcon
207
- composite={cv.composite}
208
- size="sm"
209
- />
210
- <Flex
211
- direction={{ default: 'column', sm: 'column' }}
212
- flexWrap={{ default: 'nowrap' }}
213
- alignItems={{ default: 'alignItemsFlexStart', sm: 'alignItemsFlexStart' }}
214
- >
215
- {cv.name}
216
- <ContentViewDescription
217
- cv={cv}
218
- versionNumber={relevantVersionFromCv(cv, selectedEnv)}
219
- />
220
- </Flex>
221
- </Flex>
222
- </SelectOption>
223
- ))
224
- }
160
+ {(contentViewsInEnv.length !== 0) &&
161
+ contentViewsInEnv?.map(cv =>
162
+ <ContentViewSelectOption key={cv.id} cv={cv} env={selectedEnvForHost[0]} />)}
225
163
  </ContentViewSelect>
226
164
  }
227
165
  </Modal>
@@ -20,6 +20,7 @@ import { TranslatedAnchor } from '../../../Table/components/TranslatedPlural';
20
20
  import EmptyStateMessage from '../../../Table/EmptyStateMessage';
21
21
  import './ErrataOverviewCard.scss';
22
22
  import { errataStatusContemplation } from '../../../Errata/errataHelpers';
23
+ import { pluralize } from '../../../../utils/helpers';
23
24
 
24
25
  function HostInstallableErrata({
25
26
  id, errataCounts, errataStatus, errataCategory, errataStatusLabel,
@@ -31,11 +32,11 @@ function HostInstallableErrata({
31
32
  const errataEnhance = counts.enhancement;
32
33
  const { neededErrata, allUpToDate, otherErrataStatus } = errataStatusContemplation(errataStatus);
33
34
  const chartData = [{
34
- w: 'security advisories', x: 'security', y: errataSecurity, z: errataTotal,
35
+ w: __('security advisories'), singular: __('security advisory'), x: 'security', y: errataSecurity, z: errataTotal,
35
36
  }, {
36
- w: 'bug fixes', x: 'bugfix', y: errataBug, z: errataTotal,
37
+ w: __('bug fixes'), singular: __('bug fix'), x: 'bugfix', y: errataBug, z: errataTotal,
37
38
  }, {
38
- w: 'enhancements', x: 'enhancement', y: errataEnhance, z: errataTotal,
39
+ w: __('enhancements'), singular: __('enhancement'), x: 'enhancement', y: errataEnhance, z: errataTotal,
39
40
  }];
40
41
  return (
41
42
  <CardBody>
@@ -75,7 +76,7 @@ function HostInstallableErrata({
75
76
  ariaDesc="errataChart"
76
77
  data={chartData}
77
78
  constrainToVisibleArea
78
- labels={({ datum }) => `${datum.y} ${datum.w}`}
79
+ labels={({ datum }) => pluralize(datum.y, datum.singular, datum.w)}
79
80
  padding={{
80
81
  bottom: 20,
81
82
  left: 20,
@@ -169,7 +169,7 @@ export const HostCollectionsModal = ({
169
169
  additionalListeners={[hostId, modalType, existingHostCollectionIds.join(',')]}
170
170
  fetchItems={fetchItems}
171
171
  searchPlaceholderText={__('Search host collections')}
172
- autocompleteEndpoint="/host_collections/auto_complete_search"
172
+ autocompleteEndpoint="/katello/api/v2/host_collections"
173
173
  variant={TableVariant.compact}
174
174
  {...selectAll}
175
175
  displaySelectAllCheckbox={results?.length > 0}