katello 4.3.0 → 4.4.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 (337) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/common/vendor.js +0 -1
  3. data/app/controllers/katello/api/v2/api_controller.rb +13 -4
  4. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +3 -0
  5. data/app/controllers/katello/api/v2/content_views_controller.rb +46 -0
  6. data/app/controllers/katello/api/v2/host_packages_controller.rb +21 -1
  7. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +30 -1
  8. data/app/controllers/katello/api/v2/organizations_controller.rb +10 -6
  9. data/app/controllers/katello/api/v2/packages_controller.rb +4 -0
  10. data/app/controllers/katello/api/v2/repositories_controller.rb +17 -7
  11. data/app/controllers/katello/api/v2/repository_sets_controller.rb +7 -0
  12. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +3 -0
  13. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +32 -0
  14. data/app/controllers/katello/remote_execution_controller.rb +5 -4
  15. data/app/helpers/katello/content_source_helper.rb +43 -0
  16. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +4 -0
  17. data/app/lib/actions/katello/cdn_configuration/update.rb +5 -7
  18. data/app/lib/actions/katello/content_view/publish.rb +5 -0
  19. data/app/lib/actions/katello/content_view_version/incremental_update.rb +17 -3
  20. data/app/lib/actions/katello/repository/discover.rb +1 -14
  21. data/app/lib/actions/katello/repository/filtered_index_content.rb +1 -1
  22. data/app/lib/actions/pulp3/content_view_version/import.rb +7 -0
  23. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +7 -5
  24. data/app/lib/actions/pulp3/repository/copy_content.rb +1 -1
  25. data/app/lib/actions/pulp3/repository/save_artifact.rb +1 -0
  26. data/app/lib/katello/concerns/base_template_scope_extensions.rb +11 -0
  27. data/app/lib/katello/errors.rb +3 -3
  28. data/app/lib/katello/logging.rb +6 -1
  29. data/app/lib/katello/repo_discovery.rb +27 -19
  30. data/app/lib/katello/resources/cdn/katello_cdn.rb +41 -3
  31. data/app/lib/katello/resources/cdn.rb +4 -2
  32. data/app/lib/katello/util/deduplication_migrator.rb +105 -0
  33. data/app/models/katello/candlepin/repository_mapper.rb +1 -1
  34. data/app/models/katello/cdn_configuration.rb +38 -6
  35. data/app/models/katello/concerns/host_managed_extensions.rb +23 -1
  36. data/app/models/katello/concerns/organization_extensions.rb +5 -1
  37. data/app/models/katello/concerns/pulp_database_unit.rb +59 -173
  38. data/app/models/katello/concerns/remote_execution_proxy_selector_extensions.rb +11 -0
  39. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -1
  40. data/app/models/katello/content_view.rb +4 -4
  41. data/app/models/katello/content_view_filter.rb +1 -1
  42. data/app/models/katello/content_view_history.rb +1 -1
  43. data/app/models/katello/content_view_version.rb +6 -2
  44. data/app/models/katello/content_view_version_export_history.rb +1 -1
  45. data/app/models/katello/deb.rb +1 -3
  46. data/app/models/katello/docker_meta_tag.rb +1 -1
  47. data/app/models/katello/erratum.rb +0 -15
  48. data/app/models/katello/glue/pulp/repos.rb +1 -1
  49. data/app/models/katello/host/content_facet.rb +2 -27
  50. data/app/models/katello/host/info_provider.rb +9 -0
  51. data/app/models/katello/host/subscription_facet.rb +2 -2
  52. data/app/models/katello/hostgroup/content_facet.rb +2 -2
  53. data/app/models/katello/product.rb +1 -1
  54. data/app/models/katello/product_content.rb +2 -2
  55. data/app/models/katello/repository.rb +10 -9
  56. data/app/models/katello/root_repository.rb +24 -13
  57. data/app/models/katello/rpm.rb +8 -2
  58. data/app/models/setting/content.rb +6 -3
  59. data/app/services/cert/rhsm_client.rb +1 -5
  60. data/app/services/katello/content_unit_indexer.rb +166 -0
  61. data/app/services/katello/organization_creator.rb +12 -4
  62. data/app/services/katello/pulp/repository/docker.rb +1 -1
  63. data/app/services/katello/pulp/repository/yum.rb +0 -54
  64. data/app/services/katello/pulp/repository.rb +0 -6
  65. data/app/services/katello/pulp3/ansible_collection.rb +26 -10
  66. data/app/services/katello/pulp3/api/apt.rb +7 -0
  67. data/app/services/katello/pulp3/content_view_version/import.rb +11 -2
  68. data/app/services/katello/pulp3/deb.rb +10 -9
  69. data/app/services/katello/pulp3/docker_manifest.rb +6 -5
  70. data/app/services/katello/pulp3/docker_manifest_list.rb +23 -6
  71. data/app/services/katello/pulp3/docker_tag.rb +16 -7
  72. data/app/services/katello/pulp3/erratum.rb +51 -56
  73. data/app/services/katello/pulp3/file_unit.rb +9 -6
  74. data/app/services/katello/pulp3/generic_content_unit.rb +11 -12
  75. data/app/services/katello/pulp3/module_stream.rb +76 -30
  76. data/app/services/katello/pulp3/package_group.rb +5 -5
  77. data/app/services/katello/pulp3/pulp_content_unit.rb +19 -11
  78. data/app/services/katello/pulp3/repository/apt.rb +5 -3
  79. data/app/services/katello/pulp3/repository/docker.rb +14 -7
  80. data/app/services/katello/pulp3/repository/generic.rb +1 -1
  81. data/app/services/katello/pulp3/repository/yum.rb +10 -12
  82. data/app/services/katello/pulp3/repository.rb +26 -7
  83. data/app/services/katello/pulp3/repository_mirror.rb +18 -5
  84. data/app/services/katello/pulp3/rpm.rb +13 -13
  85. data/app/services/katello/pulp3/srpm.rb +10 -9
  86. data/app/services/katello/repository_type.rb +15 -4
  87. data/app/services/katello/repository_type_manager.rb +1 -1
  88. data/app/services/katello/ui_notifications/subscriptions/manifest_expired_warning.rb +1 -1
  89. data/app/services/katello/upstream_connection_checker.rb +2 -2
  90. data/app/views/foreman/job_templates/change_content_source.erb +1 -31
  91. data/app/views/foreman/job_templates/install_errata.erb +6 -9
  92. data/app/views/foreman/job_templates/install_errata_by_search_query.erb +26 -0
  93. data/app/views/foreman/job_templates/install_packages_by_search_query.erb +19 -0
  94. data/app/views/katello/api/v2/cdn_configurations/show.json.rabl +1 -1
  95. data/app/views/katello/api/v2/environments/show.json.rabl +9 -0
  96. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -0
  97. data/app/views/katello/layouts/react.html.erb +0 -1
  98. data/app/views/katello/sync_management/_repo.html.erb +36 -25
  99. data/config/initializers/monkeys.rb +0 -1
  100. data/config/routes/api/v2.rb +1 -0
  101. data/config/routes/overrides.rb +3 -0
  102. data/config/routes.rb +2 -0
  103. data/db/migrate/20150930183738_migrate_content_hosts.rb +1 -1
  104. data/db/migrate/20180612164926_add_content_org_id.rb +2 -2
  105. data/db/migrate/20211201154845_add_unique_indexes.rb +20 -0
  106. data/db/migrate/20211208034230_add_content_view_and_lifecycle_environment.rb +6 -0
  107. data/db/migrate/20211220185935_clean_duplicate_content_units.rb +144 -0
  108. data/db/migrate/20220110223754_update_disconnected_settings.rb +20 -0
  109. data/db/migrate/20220120163252_fix_docker_download_policy.rb +11 -0
  110. data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +22 -0
  111. data/db/migrate/20220127120843_fix_debian_download_policy.rb +11 -0
  112. data/db/migrate/20220204171908_rename_docker_tags_whitelist_and_add_exclude_tags.rb +8 -0
  113. data/db/migrate/20220207140355_change_deb_attributes_size_limit.rb +7 -0
  114. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  115. data/engines/bastion/app/views/bastion/layouts/application.html.erb +0 -1
  116. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +0 -1
  117. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/content-credentials.controller.js +1 -1
  118. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-products.controller.js +1 -1
  119. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-repositories.controller.js +1 -1
  120. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-traces-modal.html +1 -1
  121. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment.html +26 -1
  122. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +212 -152
  123. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/packages.controller.js +1 -0
  124. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +20 -8
  125. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-manage-content.controller.js +2 -3
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +8 -3
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +34 -30
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +16 -2
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +35 -15
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +5 -4
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.routes.js +4 -3
  132. data/lib/katello/engine.rb +4 -0
  133. data/lib/katello/permission_creator.rb +1 -1
  134. data/lib/katello/permissions/host_permissions.rb +3 -1
  135. data/lib/katello/plugin.rb +4 -1
  136. data/lib/katello/repository_types/deb.rb +0 -1
  137. data/lib/katello/repository_types/docker.rb +4 -4
  138. data/lib/katello/repository_types/file.rb +0 -1
  139. data/lib/katello/repository_types/ostree.rb +4 -0
  140. data/lib/katello/repository_types/python.rb +5 -1
  141. data/lib/katello/repository_types/yum.rb +2 -9
  142. data/lib/katello/tasks/content_view_import_only.rake +34 -0
  143. data/lib/katello/tasks/import_applicability.rake +1 -1
  144. data/lib/katello/tasks/jenkins.rake +0 -2
  145. data/lib/katello/tasks/repository.rake +4 -1
  146. data/lib/katello/tasks/upgrades/4.4/publish_import_cvvs.rake +17 -0
  147. data/lib/katello/version.rb +1 -1
  148. data/locale/action_names.rb +8 -7
  149. data/locale/bn/katello.po +1402 -650
  150. data/locale/cs/katello.po +1217 -96
  151. data/locale/de/katello.po +2359 -1347
  152. data/locale/en/katello.po +1216 -94
  153. data/locale/es/katello.po +2201 -1172
  154. data/locale/fr/katello.po +2601 -1615
  155. data/locale/gu/katello.po +1564 -814
  156. data/locale/hi/katello.po +1563 -810
  157. data/locale/it/katello.po +1311 -282
  158. data/locale/ja/katello.po +2534 -1518
  159. data/locale/katello.pot +3430 -1326
  160. data/locale/kn/katello.po +1564 -812
  161. data/locale/ko/katello.po +1441 -409
  162. data/locale/mr/katello.po +1564 -776
  163. data/locale/or/katello.po +1565 -813
  164. data/locale/pa/katello.po +1559 -792
  165. data/locale/pt/katello.po +1314 -277
  166. data/locale/pt_BR/katello.po +2226 -1181
  167. data/locale/ru/katello.po +1587 -563
  168. data/locale/ta/katello.po +1373 -619
  169. data/locale/te/katello.po +1564 -810
  170. data/locale/zh_CN/katello.po +2936 -1890
  171. data/locale/zh_TW/katello.po +1508 -606
  172. data/webpack/__mocks__/foremanReact/{redux/actions/toasts.js → components/ToastsList/index.js} +3 -2
  173. data/webpack/components/ActionableDetail.js +35 -21
  174. data/webpack/components/Content/Details/__tests__/ContentDetailInfo.test.js +0 -2
  175. data/webpack/components/Content/Details/__tests__/ContentDetailRepositories.test.js +0 -2
  176. data/webpack/components/Content/Details/__tests__/ContentDetails.test.js +0 -2
  177. data/webpack/components/Content/__tests__/ContentPage.test.js +0 -2
  178. data/webpack/components/Content/__tests__/ContentTable.test.js +0 -2
  179. data/webpack/components/EditableSwitch.js +8 -2
  180. data/webpack/components/EditableTextInput/EditableTextInput.js +44 -86
  181. data/webpack/components/EditableTextInput/__tests__/editableTextInput.test.js +3 -3
  182. data/webpack/components/Errata/index.js +19 -11
  183. data/webpack/components/Packages/index.js +1 -1
  184. data/webpack/components/Search/Search.js +5 -2
  185. data/webpack/components/Search/__tests__/search.test.js +2 -3
  186. data/webpack/components/SelectOrg/SetOrganization.js +1 -1
  187. data/webpack/components/Table/PageControls.js +3 -6
  188. data/webpack/components/Table/TableHooks.js +46 -7
  189. data/webpack/components/Table/TableWrapper.js +14 -3
  190. data/webpack/components/TypeAhead/TypeAhead.js +5 -1
  191. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +4 -1
  192. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +2 -1
  193. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +1 -1
  194. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +3 -4
  195. data/webpack/components/extensions/HostDetails/HostDetailsActions.js +2 -0
  196. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +18 -2
  197. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesConstants.js +12 -0
  198. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +1 -1
  199. data/webpack/components/extensions/HostDetails/Tabs/{ErrataTab.js → ErrataTab/ErrataTab.js} +30 -21
  200. data/webpack/components/extensions/HostDetails/Tabs/{ErrataTab.scss → ErrataTab/ErrataTab.scss} +0 -0
  201. data/webpack/components/extensions/HostDetails/Tabs/{ErratumExpansionContents.js → ErrataTab/ErratumExpansionContents.js} +0 -0
  202. data/webpack/components/extensions/HostDetails/Tabs/{ErratumExpansionDetail.js → ErrataTab/ErratumExpansionDetail.js} +0 -0
  203. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataActions.js +3 -3
  204. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataConstants.js +11 -0
  205. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataSelectors.js +0 -0
  206. data/webpack/components/extensions/HostDetails/Tabs/PackageInstallModal.js +279 -0
  207. data/webpack/components/extensions/HostDetails/Tabs/PackageInstallModal.scss +3 -0
  208. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +125 -8
  209. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +27 -4
  210. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +2 -1
  211. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +6 -3
  212. data/webpack/components/extensions/HostDetails/Tabs/{EnableTracerEmptyState.js → TracesTab/EnableTracerEmptyState.js} +0 -0
  213. data/webpack/components/extensions/HostDetails/Tabs/{EnableTracerModal.js → TracesTab/EnableTracerModal.js} +3 -2
  214. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesActions.js → TracesTab/HostTracesActions.js} +2 -2
  215. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesConstants.js → TracesTab/HostTracesConstants.js} +0 -0
  216. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesSelectors.js → TracesTab/HostTracesSelectors.js} +0 -0
  217. data/webpack/components/extensions/HostDetails/Tabs/{TracesTab.js → TracesTab/TracesTab.js} +8 -5
  218. data/webpack/components/extensions/HostDetails/Tabs/{TracesTab.scss → TracesTab/TracesTab.scss} +0 -0
  219. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +17 -18
  220. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +385 -0
  221. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packages.fixtures.json +1 -1
  222. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +58 -7
  223. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +2 -2
  224. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +4 -4
  225. data/webpack/components/extensions/HostDetails/Tabs/__tests__/yumInstallablePackages.fixtures.json +72 -0
  226. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +12 -5
  227. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesActions.js +18 -0
  228. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesConstants.js +3 -0
  229. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesSelectors.js +16 -0
  230. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +19 -0
  231. data/webpack/components/pf3Table/components/Table.js +2 -3
  232. data/webpack/components/pf3Table/components/Table.test.js +0 -3
  233. data/webpack/components/pf3Table/components/__snapshots__/Table.test.js.snap +9 -8
  234. data/webpack/containers/Application/config.js +5 -0
  235. data/webpack/global_index.js +1 -1
  236. data/webpack/global_test_setup.js +1 -1
  237. data/webpack/index.js +7 -0
  238. data/webpack/scenes/AnsibleCollections/Details/__tests__/AnsibleCollectionDetails.test.js +0 -2
  239. data/webpack/scenes/AnsibleCollections/__tests__/AnsibleCollectionPage.test.js +0 -2
  240. data/webpack/scenes/AnsibleCollections/__tests__/AnsibleCollectionsTable.test.js +0 -2
  241. data/webpack/scenes/Content/ContentConfig.js +55 -5
  242. data/webpack/scenes/Content/ContentPage.js +1 -1
  243. data/webpack/scenes/Content/Details/ContentDetails.js +1 -1
  244. data/webpack/scenes/Content/Details/ContentInfo.js +1 -1
  245. data/webpack/scenes/Content/Details/ContentRepositories.js +1 -1
  246. data/webpack/scenes/Content/Details/__tests__/contentDetail.test.js +4 -4
  247. data/webpack/scenes/Content/Table/ContentTable.js +1 -1
  248. data/webpack/scenes/Content/__tests__/contentTable.test.js +3 -3
  249. data/webpack/scenes/ContentViews/ContentViewsConstants.js +2 -1
  250. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +6 -6
  251. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +2 -2
  252. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +21 -27
  253. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +5 -5
  254. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +8 -3
  255. data/webpack/scenes/ContentViews/Details/DetailsContainer.js +11 -16
  256. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetails.js +2 -2
  257. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +14 -8
  258. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentModal.test.js +2 -2
  259. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +2 -3
  260. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +2 -9
  261. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +3 -5
  262. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +2 -10
  263. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataIDFilter.test.js +2 -3
  264. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilter.test.js +2 -3
  265. data/webpack/scenes/ContentViews/Details/Histories/__tests__/contentViewHistory.test.js +2 -2
  266. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +1 -1
  267. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +23 -2
  268. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +11 -5
  269. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +16 -17
  270. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +1 -1
  271. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -6
  272. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +30 -34
  273. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +9 -8
  274. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +13 -15
  275. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +1 -1
  276. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +4 -4
  277. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +3 -3
  278. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +5 -3
  279. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +2 -2
  280. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +43 -0
  281. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +87 -0
  282. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +90 -0
  283. data/webpack/scenes/Hosts/ChangeContentSource/components/FormField.js +43 -0
  284. data/webpack/scenes/Hosts/ChangeContentSource/constants.js +3 -0
  285. data/webpack/scenes/Hosts/ChangeContentSource/helpers.js +27 -0
  286. data/webpack/scenes/Hosts/ChangeContentSource/index.js +126 -0
  287. data/webpack/scenes/Hosts/ChangeContentSource/selectors.js +42 -0
  288. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +11 -0
  289. data/webpack/scenes/ModuleStreams/Details/Profiles/__tests__/ModuleStreamDetailProfiles.test.js +0 -1
  290. data/webpack/scenes/ModuleStreams/Details/__tests__/ModuleStreamDetails.test.js +0 -2
  291. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +0 -2
  292. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamsTable.test.js +0 -2
  293. data/webpack/scenes/Organizations/OrganizationActions.js +5 -1
  294. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +31 -1
  295. data/webpack/scenes/RedHatRepositories/__tests__/RedHatRepositoriesPage.test.js +16 -0
  296. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +11 -2
  297. data/webpack/scenes/RedHatRepositories/helpers.js +5 -5
  298. data/webpack/scenes/RedHatRepositories/index.js +11 -3
  299. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/AirGappedTypeForm.js +81 -0
  300. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnConfigurationConstants.js +13 -0
  301. data/webpack/scenes/Subscriptions/Manifest/{CdnConfigurationForm.scss → CdnConfigurationTab/CdnConfigurationForm.scss} +0 -0
  302. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +106 -0
  303. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/UpstreamServerTypeForm.js +259 -0
  304. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/AirGappedTypeForm.test.js +44 -0
  305. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/CdnTypeForm.test.js +67 -0
  306. data/webpack/scenes/Subscriptions/Manifest/{__tests__/CdnConfigurationForm.test.js → CdnConfigurationTab/__tests__/UpstreamServerTypeForm.test.js} +46 -17
  307. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/index.js +97 -0
  308. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +6 -1
  309. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +0 -1
  310. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +0 -1
  311. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +3 -2
  312. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +4 -0
  313. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +9 -0
  314. data/webpack/scenes/Tasks/TaskActions.js +1 -1
  315. data/webpack/scenes/Tasks/__tests__/__snapshots__/TaskActions.test.js.snap +3 -2
  316. data/webpack/services/api/testHelpers.js +5 -3
  317. data/webpack/utils/helpers.js +6 -3
  318. metadata +81 -58
  319. data/app/services/katello/pulp/deb.rb +0 -55
  320. data/app/services/katello/pulp/distribution.rb +0 -7
  321. data/app/services/katello/pulp/docker_blob.rb +0 -7
  322. data/app/services/katello/pulp/docker_manifest.rb +0 -13
  323. data/app/services/katello/pulp/docker_manifest_list.rb +0 -14
  324. data/app/services/katello/pulp/docker_tag.rb +0 -14
  325. data/app/services/katello/pulp/erratum.rb +0 -129
  326. data/app/services/katello/pulp/file_unit.rb +0 -21
  327. data/app/services/katello/pulp/module_stream.rb +0 -39
  328. data/app/services/katello/pulp/package_category.rb +0 -7
  329. data/app/services/katello/pulp/package_group.rb +0 -20
  330. data/app/services/katello/pulp/pulp_content_unit.rb +0 -156
  331. data/app/services/katello/pulp/rpm.rb +0 -57
  332. data/app/services/katello/pulp/srpm.rb +0 -29
  333. data/app/services/katello/pulp/yum_metadata_file.rb +0 -30
  334. data/lib/monkeys/pulp3_13_checksumfix.rb +0 -17
  335. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationHooks.js +0 -2
  336. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
  337. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationForm.js +0 -185
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import { camelCase } from 'lodash';
3
4
  import { Link } from 'react-router-dom';
4
5
  import { translate as __ } from 'foremanReact/common/I18n';
5
6
  import { urlBuilder } from 'foremanReact/common/urlHelpers';
@@ -17,15 +18,16 @@ const ContentViewVersionContent = ({ cvId, versionId, cvVersion }) => {
17
18
  } = cvVersion;
18
19
 
19
20
 
20
- const genericContentTypes = ContentConfig().filter(({ names: { singularLabel } }) => {
21
- // Ansible Collections has a tab in version details so it's handled separately below.
22
- if (singularLabel === 'ansible_collection') return false;
23
- const countLabel = `${singularLabel}_count`;
24
- return !!cvVersion[countLabel];
25
- }).map(({ names: { singularLabel, singularLowercase, pluralLowercase } }) => {
21
+ const contentConfigTypes = ContentConfig.filter(({ names: { singularLabel } }) =>
22
+ !!cvVersion[`${singularLabel}_count`]).map(({
23
+ names: {
24
+ singularLabel, singularLowercase, pluralLowercase, pluralLabel,
25
+ },
26
+ }) => {
26
27
  const countParam = `${singularLabel}_count`;
27
28
  const count = cvVersion[countParam];
28
29
  return {
30
+ pluralLabel,
29
31
  label: count > 1 ? pluralLowercase : singularLowercase,
30
32
  count,
31
33
  };
@@ -34,7 +36,7 @@ const ContentViewVersionContent = ({ cvId, versionId, cvVersion }) => {
34
36
  const noCounts =
35
37
  !Number(debCount) && !Number(dockerManifestCount) && !Number(dockerTagCount) &&
36
38
  !Number(fileCount) && !Number(moduleStreamCount) && !Number(ansibleCollectionCount) &&
37
- !genericContentTypes?.length;
39
+ !contentConfigTypes?.length;
38
40
 
39
41
  if (noCounts) {
40
42
  return <InactiveText text={__('No content')} />;
@@ -69,16 +71,13 @@ const ContentViewVersionContent = ({ cvId, versionId, cvVersion }) => {
69
71
  <a href={urlBuilder(`content_views/${cvId}#/versions/${versionId}/files`, '')}>{`${fileCount} Files`}</a><br />
70
72
  </>
71
73
  }
72
- {ansibleCollectionCount > 0 &&
73
- <>
74
- <a href={urlBuilder(`content_views/${cvId}#/versions/${versionId}/ansibleCollections`, '')}>{`${ansibleCollectionCount} Collections`}</a><br />
75
- </>
76
- }
77
- {genericContentTypes?.length > 0 &&
78
- genericContentTypes.map(({ label, count }) => (
79
- <span key={label} style={{ whiteSpace: 'pre-line' }}>
80
- {`${count} ${label}`}
81
- </span>))
74
+ {contentConfigTypes?.length > 0 &&
75
+ contentConfigTypes.map(({ label, count, pluralLabel }) => (
76
+ <React.Fragment key={label}>
77
+ <a href={urlBuilder(`content_views/${cvId}#/versions/${versionId}/${camelCase(pluralLabel)}`, '')}>
78
+ {`${count} ${label}`}
79
+ </a><br />
80
+ </React.Fragment>))
82
81
  }
83
82
  </>
84
83
  );
@@ -92,7 +92,7 @@ const ContentViewVersions = ({ cvId, details }) => {
92
92
  { title: <ContentViewVersionEnvironments {...{ environments }} /> },
93
93
  {
94
94
  title: Number(packageCount) ?
95
- <a href={urlBuilder(`content_views/${cvId}#/versions/${versionId}/packages`, '')}>{packageCount}</a> :
95
+ <a href={urlBuilder(`content_views/${cvId}#/versions/${versionId}/rpmPackages`, '')}>{packageCount}</a> :
96
96
  <InactiveText text={__('No packages')} />,
97
97
  },
98
98
  { title: <ContentViewVersionErrata {...{ cvId, versionId, errataCounts }} /> },
@@ -34,8 +34,8 @@ let envScope;
34
34
  beforeEach(() => {
35
35
  const { results } = cvVersionsData;
36
36
  [firstVersion] = results;
37
- searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
38
- autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
37
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
38
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
39
39
  envScope = nockInstance
40
40
  .get(environmentPathsPath)
41
41
  .query(true)
@@ -131,8 +131,8 @@ test('Can open Remove wizard and remove version from environment with hosts', as
131
131
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
132
132
  const hostAutocompleteUrl = '/hosts/auto_complete_search';
133
133
  const hostAutocompleteScope = mockForemanAutocomplete(nockInstance, hostAutocompleteUrl);
134
- const hostSearchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
135
- const hostAutoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
134
+ const hostSearchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
135
+ const hostAutoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
136
136
 
137
137
  const scope = nockInstance
138
138
  .get(cvVersions)
@@ -223,8 +223,8 @@ test('Can open Remove wizard and remove version from environment with activation
223
223
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
224
224
  const akAutocompleteUrl = '/activation_keys/auto_complete_search';
225
225
  const akAutocompleteScope = mockAutocomplete(nockInstance, akAutocompleteUrl);
226
- const akSearchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
227
- const akAutoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
226
+ const akSearchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
227
+ const akAutoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
228
228
 
229
229
  const scope = nockInstance
230
230
  .get(cvVersions)
@@ -3,14 +3,13 @@ import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { urlBuilder } from 'foremanReact/common/urlHelpers';
5
5
  import LongDateTime from 'foremanReact/components/common/dates/LongDateTime';
6
- import { startCase } from 'lodash';
6
+ import { startCase, camelCase } from 'lodash';
7
7
  import {
8
8
  BugIcon,
9
9
  SecurityIcon,
10
10
  EnhancementIcon,
11
11
  } from '@patternfly/react-icons';
12
12
  import {
13
- getAnsibleCollections,
14
13
  getContentViewVersions,
15
14
  getDebPackages,
16
15
  getDockerTags,
@@ -20,10 +19,9 @@ import {
20
19
  getPackageGroups,
21
20
  getRepositories,
22
21
  getRPMPackages,
22
+ getContent,
23
23
  } from '../../ContentViewDetailActions';
24
24
  import {
25
- selectAnsibleCollections,
26
- selectAnsibleCollectionsStatus,
27
25
  selectCVVersions,
28
26
  selectCVVersionsStatus,
29
27
  selectDebPackages,
@@ -42,11 +40,15 @@ import {
42
40
  selectRPMPackageGroupsStatus,
43
41
  selectRPMPackages,
44
42
  selectRPMPackagesStatus,
43
+ selectContent,
44
+ selectContentStatus,
45
45
  } from '../../ContentViewDetailSelectors';
46
46
  import ContentViewVersionRepositoryCell from './ContentViewVersionRepositoryCell';
47
+ import ContentConfig from '../../../../Content/ContentConfig';
47
48
 
48
49
  export const TableType = PropTypes.shape({
49
50
  name: PropTypes.string,
51
+ route: PropTypes.string,
50
52
  getCountKey: PropTypes.func,
51
53
  repoType: PropTypes.string,
52
54
  responseSelector: PropTypes.func,
@@ -64,6 +66,7 @@ export const TableType = PropTypes.shape({
64
66
  export default ({ cvId, versionId }) => [
65
67
  {
66
68
  name: __('Components'),
69
+ route: 'components',
67
70
  getCountKey: item => item?.component_view_count,
68
71
  responseSelector: state => selectCVVersions(state, cvId),
69
72
  statusSelector: state => selectCVVersionsStatus(state, cvId),
@@ -91,6 +94,7 @@ export default ({ cvId, versionId }) => [
91
94
  },
92
95
  {
93
96
  name: __('Repositories'),
97
+ route: 'repositories',
94
98
  getCountKey: item => item?.repositories?.length,
95
99
  responseSelector: state => selectRepositories(state),
96
100
  statusSelector: state => selectRepositoriesStatus(state),
@@ -127,6 +131,7 @@ export default ({ cvId, versionId }) => [
127
131
  },
128
132
  {
129
133
  name: __('RPM Packages'),
134
+ route: 'rpmPackages',
130
135
  repoType: 'yum',
131
136
  getCountKey: item => item?.rpm_count,
132
137
  responseSelector: state => selectRPMPackages(state),
@@ -148,6 +153,7 @@ export default ({ cvId, versionId }) => [
148
153
  },
149
154
  {
150
155
  name: __('RPM Package Groups'),
156
+ route: 'rpmPackageGroups',
151
157
  repoType: 'yum',
152
158
  getCountKey: item => item?.package_group_count,
153
159
  responseSelector: state => selectRPMPackageGroups(state),
@@ -161,6 +167,7 @@ export default ({ cvId, versionId }) => [
161
167
  },
162
168
  {
163
169
  name: __('Files'),
170
+ route: 'files',
164
171
  repoType: 'file',
165
172
  getCountKey: item => item?.file_count,
166
173
  responseSelector: state => selectFiles(state),
@@ -180,6 +187,7 @@ export default ({ cvId, versionId }) => [
180
187
  },
181
188
  {
182
189
  name: __('Errata'),
190
+ route: 'errata',
183
191
  repoType: 'yum',
184
192
  getCountKey: item => item?.erratum_count,
185
193
  responseSelector: state => selectErrata(state),
@@ -233,6 +241,7 @@ export default ({ cvId, versionId }) => [
233
241
  },
234
242
  {
235
243
  name: __('Module Streams'),
244
+ route: 'moduleStreams',
236
245
  repoType: 'yum',
237
246
  getCountKey: item => item?.module_stream_count,
238
247
  responseSelector: state => selectModuleStreams(state),
@@ -255,6 +264,7 @@ export default ({ cvId, versionId }) => [
255
264
  },
256
265
  {
257
266
  name: __('Deb Packages'),
267
+ route: 'debPackages',
258
268
  repoType: 'deb',
259
269
  getCountKey: item => item?.deb_count,
260
270
  responseSelector: state => selectDebPackages(state),
@@ -273,38 +283,9 @@ export default ({ cvId, versionId }) => [
273
283
  { title: __('Architecture'), getProperty: item => item?.architecture },
274
284
  ],
275
285
  },
276
- {
277
- name: __('Ansible Collections'),
278
- repoType: 'ansible_collection',
279
- getCountKey: item => item?.ansible_collection_count,
280
- responseSelector: state => selectAnsibleCollections(state),
281
- statusSelector: state => selectAnsibleCollectionsStatus(state),
282
- autocompleteEndpoint: `/ansible_collections/auto_complete_search?content_view_version_id=${versionId}`,
283
- fetchItems: params => getAnsibleCollections({ content_view_version_id: versionId, ...params }),
284
- columnHeaders: [
285
- {
286
- title: __('Name'),
287
- getProperty: item => (
288
- <a href={urlBuilder(`ansible_collections/${item?.id}`, '')}>
289
- {item?.name}
290
- </a>),
291
- },
292
- {
293
- title: __('Author'),
294
- getProperty: item => item?.namespace,
295
- },
296
- {
297
- title: __('Version'),
298
- getProperty: item => item?.version,
299
- },
300
- {
301
- title: __('Checksum'),
302
- getProperty: item => item?.checksum,
303
- },
304
- ],
305
- },
306
286
  {
307
287
  name: __('Docker Tags'),
288
+ route: 'dockerTags',
308
289
  repoType: 'docker',
309
290
  getCountKey: item => item?.docker_tag_count,
310
291
  responseSelector: state => selectDockerTags(state),
@@ -329,4 +310,19 @@ export default ({ cvId, versionId }) => [
329
310
  { title: __('Product Name'), getProperty: item => item?.product?.name },
330
311
  ],
331
312
  },
313
+ ...ContentConfig.map(({
314
+ names: { pluralTitle, pluralLabel, singularLabel },
315
+ columnHeaders,
316
+ }) => ({
317
+ name: pluralTitle,
318
+ route: camelCase(pluralLabel),
319
+ repoType: singularLabel,
320
+ getCountKey: item => item[`${singularLabel}_count`],
321
+ responseSelector: state => selectContent(pluralLabel, state),
322
+ statusSelector: state => selectContentStatus(pluralLabel, state),
323
+ autocompleteEndpoint: `/${pluralLabel}/auto_complete_search?content_view_version_id=${versionId}`,
324
+ fetchItems: params =>
325
+ getContent(pluralLabel, { content_view_version_id: versionId, ...params }),
326
+ columnHeaders,
327
+ })),
332
328
  ];
@@ -3,7 +3,7 @@ import useDeepCompareEffect from 'use-deep-compare-effect';
3
3
  import { useParams, Route, useHistory, useLocation, Redirect, Switch } from 'react-router-dom';
4
4
  import { useDispatch, useSelector, shallowEqual } from 'react-redux';
5
5
  import { STATUS } from 'foremanReact/constants';
6
- import { isEmpty, camelCase, first } from 'lodash';
6
+ import { isEmpty, first } from 'lodash';
7
7
  import { Grid, Tabs, Tab, TabTitleText, Label } from '@patternfly/react-core';
8
8
  import { number, shape } from 'prop-types';
9
9
  import './ContentViewVersionDetails.scss';
@@ -68,13 +68,14 @@ const ContentViewVersionDetails = ({ cvId, details }) => {
68
68
  const filteredTableConfigs = tableConfigs.filter(({ getCountKey }) => !!getCountKey(response));
69
69
  const { repositories } = versionDetails;
70
70
  const showTabs = filteredTableConfigs.length > 0 && repositories;
71
- const getCurrentActiveKey = tab ?? camelCase(first(filteredTableConfigs)?.name);
71
+ const getCurrentActiveKey = tab ?? first(filteredTableConfigs)?.route;
72
72
 
73
73
  return (
74
74
  <Grid>
75
75
  <ContentViewVersionDetailsHeader
76
76
  versionDetails={versionDetails}
77
77
  onEdit={editDiscription}
78
+ loading={status === STATUS.PENDING}
78
79
  details={details}
79
80
  />
80
81
  {showTabs &&
@@ -84,10 +85,10 @@ const ContentViewVersionDetails = ({ cvId, details }) => {
84
85
  onSelect={onSelect}
85
86
  isVertical
86
87
  >
87
- {filteredTableConfigs.map(({ name, getCountKey }) => (
88
+ {filteredTableConfigs.map(({ route, name, getCountKey }) => (
88
89
  <Tab
89
- key={name}
90
- eventKey={camelCase(name)}
90
+ key={route}
91
+ eventKey={route}
91
92
  title={
92
93
  <>
93
94
  <TabTitleText>{name}</TabTitleText>
@@ -100,9 +101,9 @@ const ContentViewVersionDetails = ({ cvId, details }) => {
100
101
  <Switch>
101
102
  {filteredTableConfigs.map(config => (
102
103
  <Route
103
- key={camelCase(config.name)}
104
+ key={config.route}
104
105
  exact
105
- path={`/versions/:versionId([0-9]+)/${camelCase(config.name)}`}
106
+ path={`/versions/:versionId([0-9]+)/${config.route}`}
106
107
  >
107
108
  <ContentViewVersionDetailsTable
108
109
  tableConfig={config}
@@ -111,7 +112,7 @@ const ContentViewVersionDetails = ({ cvId, details }) => {
111
112
  </Route>))
112
113
  }
113
114
  <Redirect
114
- to={`/versions/${versionId}/${camelCase(first(filteredTableConfigs).name)}`}
115
+ to={`/versions/${versionId}/${first(filteredTableConfigs).route}`}
115
116
  />
116
117
  </Switch>
117
118
  </div>
@@ -6,9 +6,7 @@ import {
6
6
  GridItem,
7
7
  TextContent,
8
8
  Text,
9
- TextList,
10
9
  TextVariants,
11
- TextListVariants,
12
10
  Label,
13
11
  Flex,
14
12
  FlexItem,
@@ -18,11 +16,11 @@ import {
18
16
  DropdownPosition,
19
17
  } from '@patternfly/react-core';
20
18
  import { translate as __ } from 'foremanReact/common/I18n';
21
- import EditableTextInput from '../../../../../components/EditableTextInput';
22
19
  import { hasPermission } from '../../../helpers';
23
20
  import ContentViewVersionPromote from '../../Promote/ContentViewVersionPromote';
24
21
  import getEnvironmentPaths from '../../../components/EnvironmentPaths/EnvironmentPathActions';
25
22
  import RemoveCVVersionWizard from '../Delete/RemoveCVVersionWizard';
23
+ import ActionableDetail from '../../../../../components/ActionableDetail';
26
24
 
27
25
  const ContentViewVersionDetailsHeader = ({
28
26
  versionDetails: {
@@ -30,6 +28,7 @@ const ContentViewVersionDetailsHeader = ({
30
28
  },
31
29
  onEdit,
32
30
  details: { permissions },
31
+ loading,
33
32
  }) => {
34
33
  const dispatch = useDispatch();
35
34
  useEffect(
@@ -98,18 +97,16 @@ const ContentViewVersionDetailsHeader = ({
98
97
  </GridItem>
99
98
  <GridItem className="content-view-header-content" span={12}>
100
99
  <TextContent>
101
- <TextList component={TextListVariants.dl}>
102
- <EditableTextInput
103
- key={description} // This fixes a render issue with the initial value
104
- textArea
105
- label={__('Description')}
106
- attribute="description"
107
- placeholder={__('No description')}
108
- onEdit={onEdit}
109
- disabled={!hasPermission(permissions, 'edit_content_views')}
110
- value={description}
111
- />
112
- </TextList>
100
+ <ActionableDetail
101
+ key={description} // This fixes a render issue with the initial value
102
+ textArea
103
+ attribute="description"
104
+ loading={loading}
105
+ placeholder={__('No description')}
106
+ onEdit={onEdit}
107
+ disabled={!hasPermission(permissions, 'edit_content_views')}
108
+ value={description}
109
+ />
113
110
  </TextContent>
114
111
  <Flex>
115
112
  {environments?.map(({ name, id: envId }) =>
@@ -164,6 +161,7 @@ ContentViewVersionDetailsHeader.propTypes = {
164
161
  details: PropTypes.shape({
165
162
  permissions: PropTypes.shape({}),
166
163
  }).isRequired,
164
+ loading: PropTypes.bool.isRequired,
167
165
  };
168
166
 
169
167
  export default ContentViewVersionDetailsHeader;
@@ -67,7 +67,7 @@ const ContentViewVersionRepositoryCell = ({
67
67
  },
68
68
  };
69
69
 
70
- ContentConfig().forEach((type) => {
70
+ ContentConfig.forEach((type) => {
71
71
  CONTENT_COUNTS[type.names.singularLabel] = {
72
72
  name: type.names.pluralLowercase,
73
73
  url: `products/${id}/repositories/${libraryInstanceId}/content/${type.names.pluralLabel}`,
@@ -199,8 +199,8 @@ testConfig.forEach(({
199
199
  const { version } = ContentViewVersionDetailsData;
200
200
 
201
201
  const autocompleteScope = mockAutocomplete(nockInstance, autoCompleteUrl);
202
- const searchDelayScope = mockSetting(nockInstance, AUTOSEARCH_DELAY, 500);
203
- const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
202
+ const searchDelayScope = mockSetting(nockInstance, AUTOSEARCH_DELAY);
203
+ const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING);
204
204
 
205
205
  const scope = nockInstance
206
206
  .get(cvVersions)
@@ -251,8 +251,8 @@ test('Can change repository selector', async (done) => {
251
251
 
252
252
  const { version } = ContentViewVersionDetailsData;
253
253
  const autocompleteScope = mockAutocomplete(nockInstance, autoCompleteUrl);
254
- const searchDelayScope = mockSetting(nockInstance, AUTOSEARCH_DELAY, 500);
255
- const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
254
+ const searchDelayScope = mockSetting(nockInstance, AUTOSEARCH_DELAY, 0);
255
+ const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING);
256
256
 
257
257
  const scope = nockInstance
258
258
  .get(cvVersions)
@@ -41,8 +41,8 @@ let envScope;
41
41
  beforeEach(() => {
42
42
  const { results } = cvVersionsData;
43
43
  [firstVersion] = results;
44
- searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
45
- autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
44
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
45
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
46
46
  envScope = nockInstance
47
47
  .get(environmentPathsPath)
48
48
  .query(true)
@@ -122,7 +122,7 @@ test('Can show package and erratas and link to list page', async () => {
122
122
 
123
123
  await patientlyWaitFor(() => {
124
124
  expect(getAllByText(8)[0].closest('a'))
125
- .toHaveAttribute('href', '/content_views/5#/versions/11/packages/');
125
+ .toHaveAttribute('href', '/content_views/5#/versions/11/rpmPackages/');
126
126
  expect(getAllByText(15)[0].closest('a'))
127
127
  .toHaveAttribute('href', '/content_views/5#/versions/11/errata/');
128
128
  expect(getByText(5)).toBeInTheDocument();
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Route } from 'react-router-dom';
3
- import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
3
+ import { renderWithRedux, patientlyWaitFor, fireEvent, act } from 'react-testing-lib-wrapper';
4
4
  import { nockInstance, assertNockRequest } from '../../../../test-utils/nockWrapper';
5
5
  import api from '../../../../services/api';
6
6
  import ContentViewDetails from '../ContentViewDetails';
@@ -53,7 +53,7 @@ test('Can edit text details such as name', async (done) => {
53
53
  .query(true)
54
54
  .reply(200, cvDetailData);
55
55
  const updatescope = nockInstance
56
- .put(cvDetailsPath, { name: newName })
56
+ .put(cvDetailsPath, { include_permissions: true, name: newName })
57
57
  .reply(200, updatedCVDetails);
58
58
  const afterUpdateScope = nockInstance
59
59
  .get(cvDetailsPath)
@@ -81,6 +81,7 @@ test('Can edit text details such as name', async (done) => {
81
81
  assertNockRequest(getscope);
82
82
  assertNockRequest(updatescope);
83
83
  assertNockRequest(afterUpdateScope, done);
84
+ act(done);
84
85
  });
85
86
 
86
87
  test('Can edit boolean details such as solve dependencies', async (done) => {
@@ -90,7 +91,7 @@ test('Can edit boolean details such as solve dependencies', async (done) => {
90
91
  .query(true)
91
92
  .reply(200, cvDetailData);
92
93
  const updatescope = nockInstance
93
- .put(cvDetailsPath, { solve_dependencies: true })
94
+ .put(cvDetailsPath, { include_permissions: true, solve_dependencies: true })
94
95
  .reply(200, updatedCVDetails);
95
96
  const afterUpdateScope = nockInstance
96
97
  .get(cvDetailsPath)
@@ -115,6 +116,7 @@ test('Can edit boolean details such as solve dependencies', async (done) => {
115
116
  assertNockRequest(getscope);
116
117
  assertNockRequest(updatescope);
117
118
  assertNockRequest(afterUpdateScope, done);
119
+ act(done);
118
120
  });
119
121
 
120
122
  test('Can link to view tasks', async () => {
@@ -26,8 +26,8 @@ beforeEach(() => {
26
26
  .get('/api/v2/bookmarks')
27
27
  .query(true)
28
28
  .reply(200, {});
29
- searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
30
- autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
29
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
30
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
31
31
  });
32
32
 
33
33
  afterEach(() => {
@@ -0,0 +1,43 @@
1
+
2
+ import { foremanUrl } from 'foremanReact/common/helpers';
3
+ import { get, post, put } from 'foremanReact/redux/API';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+
6
+ import { CHANGE_CONTENT_SOURCE_DATA,
7
+ CHANGE_CONTENT_SOURCE,
8
+ CHANGE_CONTENT_SOURCE_VIEWS } from './constants';
9
+
10
+ import { getHostIds } from './helpers';
11
+
12
+ export const getFormData = () =>
13
+ post({
14
+ key: CHANGE_CONTENT_SOURCE_DATA,
15
+ url: foremanUrl('/change_host_content_source/data'),
16
+ params: { host_ids: getHostIds() },
17
+ errorToast: () => __('Something went wrong while getting the data. See the logs for more information'),
18
+ });
19
+
20
+ export const changeContentSource = (environmentId, contentViewId, contentSourceId, hostIds) =>
21
+ put({
22
+ key: CHANGE_CONTENT_SOURCE,
23
+ url: foremanUrl('/api/v2/hosts/bulk/change_content_source'),
24
+ params: {
25
+ environment_id: environmentId,
26
+ content_view_id: contentViewId,
27
+ content_source_id: contentSourceId,
28
+ host_ids: hostIds,
29
+ },
30
+ successToast: () => __('Content source successfully updated.'),
31
+ errorToast: () => __('Something went wrong while updating the content source. See the logs for more information'),
32
+ });
33
+
34
+ export const getContentViews = environmentId =>
35
+ get({
36
+ key: CHANGE_CONTENT_SOURCE_VIEWS,
37
+ url: foremanUrl('/katello/api/v2/content_views'),
38
+ params: {
39
+ environment_id: environmentId,
40
+ full_result: true,
41
+ },
42
+ errorToast: () => __('Something went wrong while loading the content views. See the logs for more information'),
43
+ });
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import {
3
+ ActionGroup,
4
+ Button,
5
+ Form,
6
+ Grid,
7
+ GridItem,
8
+ } from '@patternfly/react-core';
9
+ import { translate as __ } from 'foremanReact/common/I18n';
10
+ import PropTypes from 'prop-types';
11
+
12
+ import FormField from './FormField';
13
+
14
+ const ContentSourceForm = ({
15
+ handleSubmit,
16
+ environments,
17
+ handleEnvironment,
18
+ environmentId,
19
+ contentViews,
20
+ handleContentView,
21
+ contentViewId,
22
+ contentSources,
23
+ handleContentSource,
24
+ contentSourceId,
25
+ contentHostsIds,
26
+ isLoading,
27
+ }) => {
28
+ const formIsValid = () => (!!environmentId &&
29
+ !!contentViewId &&
30
+ !!contentSourceId &&
31
+ contentHostsIds.length !== 0);
32
+
33
+ return (
34
+ <Form
35
+ onSubmit={e => handleSubmit(e)}
36
+ className="content_source_form"
37
+ isHorizontal
38
+ >
39
+ <Grid hasGutter>
40
+ <FormField label={__('Environment')} id="change_cs_environment" value={environmentId} items={environments} onChange={handleEnvironment} isLoading={isLoading} contentHostsCount={contentHostsIds.length} />
41
+ <FormField label={__('Content View')} id="change_cs_content_view" value={contentViewId} items={contentViews} onChange={handleContentView} isLoading={isLoading} contentHostsCount={contentHostsIds.length} />
42
+ <FormField label={__('Content Source')} id="change_cs_content_source" value={contentSourceId} items={contentSources} onChange={handleContentSource} isLoading={isLoading} contentHostsCount={contentHostsIds.length} />
43
+
44
+ <GridItem>
45
+ <ActionGroup>
46
+ <Button
47
+ variant="primary"
48
+ id="generate_btn"
49
+ onClick={e => handleSubmit(e)}
50
+ isDisabled={isLoading || !formIsValid()}
51
+ isLoading={isLoading}
52
+ >
53
+ { __('Change content source')}
54
+ </Button>
55
+ </ActionGroup>
56
+ </GridItem>
57
+ </Grid>
58
+ </Form>);
59
+ };
60
+
61
+ ContentSourceForm.propTypes = {
62
+ handleSubmit: PropTypes.func.isRequired,
63
+ environments: PropTypes.arrayOf(PropTypes.object),
64
+ handleEnvironment: PropTypes.func.isRequired,
65
+ environmentId: PropTypes.string,
66
+ contentViews: PropTypes.arrayOf(PropTypes.object),
67
+ handleContentView: PropTypes.func.isRequired,
68
+ contentViewId: PropTypes.string,
69
+ contentSources: PropTypes.arrayOf(PropTypes.object),
70
+ handleContentSource: PropTypes.func.isRequired,
71
+ contentSourceId: PropTypes.string,
72
+ contentHostsIds: PropTypes.arrayOf(PropTypes.number),
73
+ isLoading: PropTypes.bool,
74
+ };
75
+
76
+ ContentSourceForm.defaultProps = {
77
+ environments: [],
78
+ environmentId: '',
79
+ contentViews: [],
80
+ contentViewId: '',
81
+ contentSources: [],
82
+ contentSourceId: '',
83
+ contentHostsIds: [],
84
+ isLoading: false,
85
+ };
86
+
87
+ export default ContentSourceForm;