katello 3.17.0 → 3.18.0

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 (272) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +38 -21
  3. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +3 -1
  4. data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -15
  5. data/app/controllers/katello/api/v2/capsule_content_controller.rb +2 -2
  6. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -8
  7. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +98 -0
  8. data/app/controllers/katello/api/v2/content_exports_controller.rb +84 -0
  9. data/app/controllers/katello/api/v2/content_imports_controller.rb +59 -0
  10. data/app/controllers/katello/api/v2/content_view_components_controller.rb +31 -14
  11. data/app/controllers/katello/api/v2/content_view_filters_controller.rb +17 -8
  12. data/app/controllers/katello/api/v2/content_view_repositories_controller.rb +1 -0
  13. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +65 -71
  14. data/app/controllers/katello/api/v2/content_views_controller.rb +37 -26
  15. data/app/controllers/katello/api/v2/environments_controller.rb +8 -8
  16. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +5 -5
  17. data/app/controllers/katello/api/v2/host_collections_controller.rb +19 -16
  18. data/app/controllers/katello/api/v2/host_debs_controller.rb +1 -0
  19. data/app/controllers/katello/api/v2/host_errata_controller.rb +2 -2
  20. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +35 -6
  21. data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
  22. data/app/controllers/katello/api/v2/products_controller.rb +9 -9
  23. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +1 -1
  24. data/app/controllers/katello/api/v2/repositories_controller.rb +10 -5
  25. data/app/controllers/katello/api/v2/repository_sets_controller.rb +24 -14
  26. data/app/controllers/katello/api/v2/subscriptions_controller.rb +1 -1
  27. data/app/controllers/katello/api/v2/sync_plans_controller.rb +8 -9
  28. data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +9 -2
  29. data/app/controllers/katello/concerns/api/v2/authorization.rb +19 -5
  30. data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +22 -18
  31. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +21 -0
  32. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +1 -1
  33. data/app/controllers/katello/concerns/organizations_controller_extensions.rb +2 -1
  34. data/app/controllers/katello/concerns/registration_controller_extensions.rb +16 -0
  35. data/app/helpers/katello/katello_urls_helper.rb +5 -2
  36. data/app/lib/actions/candlepin/product/content_create.rb +2 -0
  37. data/app/lib/actions/candlepin/product/content_update.rb +2 -0
  38. data/app/lib/actions/helpers/smart_proxy_sync_history_helper.rb +24 -0
  39. data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +6 -2
  40. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  41. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +16 -7
  42. data/app/lib/actions/katello/content_view/promote_to_environment.rb +1 -1
  43. data/app/lib/actions/katello/content_view/publish.rb +9 -9
  44. data/app/lib/actions/katello/content_view_version/import.rb +8 -13
  45. data/app/lib/actions/katello/content_view_version/import_library.rb +17 -0
  46. data/app/lib/actions/katello/content_view_version/incremental_update.rb +18 -3
  47. data/app/lib/actions/katello/host/hypervisors_update.rb +18 -0
  48. data/app/lib/actions/katello/host/update_system_purpose.rb +31 -0
  49. data/app/lib/actions/katello/host/upload_package_profile.rb +3 -1
  50. data/app/lib/actions/katello/host/upload_profiles.rb +8 -6
  51. data/app/lib/actions/katello/organization/manifest_delete.rb +0 -1
  52. data/app/lib/actions/katello/organization/manifest_import.rb +0 -1
  53. data/app/lib/actions/katello/organization/manifest_refresh.rb +0 -1
  54. data/app/lib/actions/katello/product/content_create.rb +7 -6
  55. data/app/lib/actions/katello/repository/filtered_index_content.rb +10 -1
  56. data/app/lib/actions/katello/repository/import_upload.rb +4 -1
  57. data/app/lib/actions/katello/repository/remove_content.rb +1 -1
  58. data/app/lib/actions/katello/repository/sync.rb +3 -1
  59. data/app/lib/actions/katello/repository/update.rb +5 -1
  60. data/app/lib/actions/katello/repository/upload_files.rb +1 -0
  61. data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +15 -0
  62. data/app/lib/actions/pulp/consumer/sync_capsule.rb +4 -2
  63. data/app/lib/actions/pulp/repository/distributor_publish.rb +1 -1
  64. data/app/lib/actions/pulp3/capsule_content/sync.rb +1 -0
  65. data/app/lib/actions/pulp3/content_migration.rb +10 -0
  66. data/app/lib/actions/pulp3/content_migration_presenter.rb +59 -0
  67. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -1
  68. data/app/lib/actions/pulp3/content_view_version/create_importer.rb +7 -3
  69. data/app/lib/actions/pulp3/content_view_version/export.rb +7 -1
  70. data/app/lib/actions/pulp3/content_view_version/import.rb +7 -3
  71. data/app/lib/actions/pulp3/import_migration.rb +6 -1
  72. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +2 -1
  73. data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +38 -14
  74. data/app/lib/actions/pulp3/orchestration/content_view_version/export_library.rb +60 -0
  75. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +16 -10
  76. data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +4 -1
  77. data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +16 -3
  78. data/app/lib/actions/pulp3/repository/commit_upload.rb +2 -1
  79. data/app/lib/actions/pulp3/repository/copy_content.rb +1 -1
  80. data/app/lib/actions/pulp3/repository/delete.rb +1 -1
  81. data/app/lib/actions/pulp3/repository/save_artifact.rb +1 -1
  82. data/app/lib/actions/pulp3/repository/save_version.rb +1 -1
  83. data/app/lib/actions/pulp3/repository/upload_tag.rb +18 -0
  84. data/app/lib/katello/resources/candlepin/consumer.rb +2 -2
  85. data/app/lib/katello/resources/candlepin/owner.rb +5 -0
  86. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +6 -0
  87. data/app/lib/katello/resources/registry.rb +3 -3
  88. data/app/models/katello/authorization/activation_key.rb +4 -0
  89. data/app/models/katello/authorization/content_view.rb +13 -0
  90. data/app/models/katello/authorization/content_view_component.rb +15 -0
  91. data/app/models/katello/authorization/content_view_filter.rb +15 -0
  92. data/app/models/katello/authorization/content_view_version.rb +25 -2
  93. data/app/models/katello/authorization/content_view_version_export_history.rb +1 -1
  94. data/app/models/katello/authorization/gpg_key.rb +12 -4
  95. data/app/models/katello/authorization/lifecycle_environment.rb +8 -0
  96. data/app/models/katello/authorization/organization.rb +8 -0
  97. data/app/models/katello/authorization/sync_plan.rb +16 -0
  98. data/app/models/katello/concerns/operatingsystem_extensions.rb +2 -0
  99. data/app/models/katello/concerns/organization_extensions.rb +4 -5
  100. data/app/models/katello/concerns/smart_proxy_extensions.rb +6 -4
  101. data/app/models/katello/content_migration_progress.rb +4 -0
  102. data/app/models/katello/content_view.rb +30 -4
  103. data/app/models/katello/content_view_component.rb +2 -0
  104. data/app/models/katello/content_view_filter.rb +5 -0
  105. data/app/models/katello/content_view_history.rb +2 -1
  106. data/app/models/katello/content_view_package_filter.rb +1 -1
  107. data/app/models/katello/content_view_puppet_module.rb +8 -0
  108. data/app/models/katello/content_view_repository.rb +13 -1
  109. data/app/models/katello/content_view_version_export_history.rb +8 -1
  110. data/app/models/katello/glue/candlepin/pool.rb +9 -14
  111. data/app/models/katello/glue/pulp/repo.rb +8 -0
  112. data/app/models/katello/gpg_key.rb +1 -1
  113. data/app/models/katello/ping.rb +8 -3
  114. data/app/models/katello/repository.rb +33 -0
  115. data/app/models/katello/root_repository.rb +26 -1
  116. data/app/models/katello/smart_proxy_sync_history.rb +8 -0
  117. data/app/services/katello/candlepin/event_handler.rb +2 -0
  118. data/app/services/katello/candlepin/message_handler.rb +34 -0
  119. data/app/services/katello/candlepin/upstream_consumer.rb +28 -0
  120. data/app/services/katello/host_status_manager.rb +9 -0
  121. data/app/services/katello/pulp3/api/apt.rb +57 -0
  122. data/app/services/katello/pulp3/api/core.rb +8 -0
  123. data/app/services/katello/pulp3/api/docker.rb +4 -0
  124. data/app/services/katello/pulp3/content_view_version/export.rb +125 -8
  125. data/app/services/katello/pulp3/content_view_version/import.rb +39 -34
  126. data/app/services/katello/pulp3/content_view_version/import_export_common.rb +6 -16
  127. data/app/services/katello/pulp3/content_view_version/import_validator.rb +114 -0
  128. data/app/services/katello/pulp3/deb.rb +38 -0
  129. data/app/services/katello/pulp3/docker_manifest.rb +1 -0
  130. data/app/services/katello/pulp3/docker_tag.rb +1 -0
  131. data/app/services/katello/pulp3/migration.rb +51 -10
  132. data/app/services/katello/pulp3/pulp_content_unit.rb +5 -0
  133. data/app/services/katello/pulp3/repository.rb +10 -4
  134. data/app/services/katello/pulp3/repository/ansible_collection.rb +9 -0
  135. data/app/services/katello/pulp3/repository/apt.rb +63 -0
  136. data/app/services/katello/pulp3/repository/docker.rb +9 -0
  137. data/app/services/katello/pulp3/repository/yum.rb +14 -9
  138. data/app/services/katello/pulp3/repository_mirror.rb +9 -4
  139. data/app/services/katello/pulp3/task.rb +4 -0
  140. data/app/services/katello/pulp3/task_group.rb +4 -0
  141. data/app/services/katello/repository_type.rb +2 -1
  142. data/app/services/katello/smart_proxy_helper.rb +9 -0
  143. data/app/views/dashboard/_subscription_widget.html.erb +0 -5
  144. data/app/views/foreman/hosts/_registration.html.erb +12 -0
  145. data/app/views/katello/api/v2/content_view_version_export_histories/show.json.rabl +1 -1
  146. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  147. data/app/views/katello/api/v2/repositories/base.json.rabl +1 -1
  148. data/app/views/katello/layouts/react.html.erb +3 -2
  149. data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -5
  150. data/app/views/overrides/organizations/_index_row_override.html.erb +1 -1
  151. data/config/routes/api/v2.rb +24 -2
  152. data/config/routes/overrides.rb +1 -0
  153. data/db/migrate/20200929200357_create_katello_smart_proxy_sync_history.rb +13 -0
  154. data/db/migrate/20201008204114_add_os_versions_to_katello_root_repositories.rb +5 -0
  155. data/db/migrate/20201012172713_remove_gpg_key_perms.rb +23 -0
  156. data/db/migrate/20201012192035_add_metadata_to_katello_content_view_version_export_history.rb +5 -0
  157. data/db/migrate/20201021150008_add_import_only_to_katello_content_view.rb +5 -0
  158. data/db/migrate/20201119211133_pulp3_migration_progress.rb +9 -0
  159. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  160. data/engines/bastion/app/assets/javascripts/bastion/components/notification.service.js +1 -1
  161. data/engines/bastion/app/assets/javascripts/bastion/components/nutupane.factory.js +8 -13
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-system-purpose-modal.controller.js +112 -0
  163. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-system-purpose-modal.html +78 -0
  164. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-host-modal-helper.service.js +11 -0
  165. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +5 -0
  166. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-installed.controller.js +2 -42
  167. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +4 -0
  168. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.controller.js +6 -2
  169. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-details.controller.js +12 -0
  170. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +7 -7
  171. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-info.html +7 -1
  172. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/content-view-new.controller.js +17 -3
  173. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/views/content-view-new.html +16 -2
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/views/content-views.html +5 -0
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-details.controller.js +4 -0
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/views/host-collection-info.html +6 -0
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-bulk-action.factory.js +2 -1
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +92 -19
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +17 -20
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +17 -24
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +1292 -1170
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +17 -20
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +858 -807
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +18 -19
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +17 -24
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +17 -18
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +986 -971
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +19 -20
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +9 -9
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/products-bulk-advanced-sync-modal.controller.js +6 -7
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +168 -155
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +17 -2
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +125 -113
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +15 -3
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/os-versions.service.js +46 -0
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository-types.service.js +8 -1
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +1 -1
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-details.html +1 -1
  199. data/lib/katello/engine.rb +2 -0
  200. data/lib/katello/permission_creator.rb +98 -69
  201. data/lib/katello/permissions/host_permissions.rb +1 -0
  202. data/lib/katello/plugin.rb +10 -2
  203. data/lib/katello/repository_types/deb.rb +9 -1
  204. data/lib/katello/tasks/pulp3_migration.rake +17 -3
  205. data/lib/katello/tasks/pulp3_migration_abort.rake +22 -0
  206. data/lib/katello/tasks/pulp3_migration_stats.rake +41 -0
  207. data/lib/katello/tasks/receptor/extract_orgs.rake +1 -1
  208. data/lib/katello/tasks/reset.rake +2 -1
  209. data/lib/katello/tasks/upgrades/3.18/add_cvv_export_history_metadata.rb +18 -0
  210. data/lib/katello/version.rb +1 -1
  211. data/locale/action_names.rb +51 -44
  212. data/locale/bn/katello.po +279 -55
  213. data/locale/cs/katello.po +278 -51
  214. data/locale/de/katello.po +279 -52
  215. data/locale/en/katello.po +278 -49
  216. data/locale/es/katello.po +279 -51
  217. data/locale/fr/katello.po +279 -51
  218. data/locale/gu/katello.po +279 -55
  219. data/locale/hi/katello.po +279 -55
  220. data/locale/it/katello.po +279 -51
  221. data/locale/ja/katello.po +279 -52
  222. data/locale/katello.pot +1379 -971
  223. data/locale/kn/katello.po +279 -55
  224. data/locale/ko/katello.po +279 -51
  225. data/locale/mr/katello.po +279 -55
  226. data/locale/or/katello.po +279 -55
  227. data/locale/pa/katello.po +279 -55
  228. data/locale/pt/katello.po +278 -52
  229. data/locale/pt_BR/katello.po +279 -51
  230. data/locale/ru/katello.po +279 -51
  231. data/locale/ta/katello.po +279 -55
  232. data/locale/te/katello.po +279 -55
  233. data/locale/zh_CN/katello.po +279 -51
  234. data/locale/zh_TW/katello.po +279 -52
  235. data/webpack/components/ActionableDetail.js +2 -1
  236. data/webpack/components/Search/Search.js +1 -1
  237. data/webpack/components/Table/MainTable.js +6 -2
  238. data/webpack/components/Table/TableWrapper.js +46 -9
  239. data/webpack/scenes/ContentViews/ContentViewSelectors.js +7 -3
  240. data/webpack/scenes/ContentViews/ContentViewsConstants.js +8 -0
  241. data/webpack/scenes/ContentViews/ContentViewsPage.js +2 -9
  242. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +25 -3
  243. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +14 -4
  244. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +2 -1
  245. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +56 -0
  246. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +169 -0
  247. data/webpack/scenes/ContentViews/Details/Repositories/LastSync.js +47 -0
  248. data/webpack/scenes/ContentViews/Details/Repositories/RepoAddedStatus.js +17 -0
  249. data/webpack/scenes/ContentViews/Details/Repositories/RepoIcon.js +23 -0
  250. data/webpack/scenes/ContentViews/Details/Repositories/SelectableDropdown.js +49 -0
  251. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.fixtures.json +154 -0
  252. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.test.js +131 -0
  253. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +3 -0
  254. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +4 -1
  255. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +2 -2
  256. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +29 -19
  257. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +17 -0
  258. data/webpack/scenes/Subscriptions/Manifest/ManifestConstants.js +4 -0
  259. data/webpack/scenes/Subscriptions/Manifest/SimpleContentAccess.js +19 -2
  260. data/webpack/scenes/Subscriptions/Manifest/__tests__/SimpleContentAccess.test.js +9 -1
  261. data/webpack/scenes/Subscriptions/Manifest/index.js +2 -1
  262. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -1
  263. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +3 -0
  264. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +8 -2
  265. data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +3 -0
  266. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +3 -0
  267. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +6 -0
  268. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +6 -0
  269. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -13
  270. data/webpack/test-utils/react-testing-lib-wrapper.js +3 -0
  271. metadata +74 -13
  272. data/webpack/__mocks__/foremanReact/components/common/Fill/GlobalFill.js +0 -3
@@ -0,0 +1,47 @@
1
+ import React, { Fragment } from 'react';
2
+ import { CheckCircleIcon, ExclamationTriangleIcon, CloseIcon } from '@patternfly/react-icons';
3
+ import { foremanUrl } from 'foremanReact/common/helpers';
4
+ import PropTypes from 'prop-types';
5
+
6
+ const LastSync = ({ lastSyncWords, lastSync }) => {
7
+ if (lastSync && lastSyncWords) {
8
+ let Icon;
9
+ let color = 'black';
10
+ const { result, id } = lastSync;
11
+
12
+ if (result === 'success') {
13
+ Icon = CheckCircleIcon;
14
+ color = 'green';
15
+ } else if (result === 'warning') {
16
+ Icon = ExclamationTriangleIcon;
17
+ color = 'orange';
18
+ } else if (result === 'error') {
19
+ Icon = CloseIcon;
20
+ color = 'red';
21
+ } else {
22
+ Icon = Fragment;
23
+ }
24
+
25
+ return (
26
+ <a href={foremanUrl(`/foreman_tasks/tasks/${id}/`)}>
27
+ <Icon style={{ color }} />&nbsp;{`${lastSyncWords} ago`}
28
+ </a>
29
+ );
30
+ }
31
+ return <div>Not Synced</div>;
32
+ };
33
+
34
+ LastSync.propTypes = {
35
+ lastSyncWords: PropTypes.string,
36
+ lastSync: PropTypes.shape({
37
+ id: PropTypes.string, // API returns string
38
+ result: PropTypes.string,
39
+ }),
40
+ };
41
+
42
+ LastSync.defaultProps = {
43
+ lastSyncWords: null,
44
+ lastSync: null,
45
+ };
46
+
47
+ export default LastSync;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Label } from '@patternfly/react-core';
3
+ import { CheckCircleIcon } from '@patternfly/react-icons';
4
+ import { ADDED, NOT_ADDED } from '../../ContentViewsConstants';
5
+
6
+ const RepoAddedStatus = ({ added }) => {
7
+ if (added) {
8
+ return (
9
+ <Label variant="outline" color="green" icon={<CheckCircleIcon />}>
10
+ {ADDED}
11
+ </Label>
12
+ );
13
+ }
14
+ return NOT_ADDED;
15
+ };
16
+
17
+ export default RepoAddedStatus;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { Tooltip } from '@patternfly/react-core';
3
+ import { BundleIcon, MiddlewareIcon, BoxIcon, CodeBranchIcon, FanIcon, TenantIcon } from '@patternfly/react-icons';
4
+ import PropTypes from 'prop-types';
5
+
6
+ const RepoIcon = ({ type }) => {
7
+ const iconMap = {
8
+ yum: BundleIcon,
9
+ docker: MiddlewareIcon,
10
+ ostree: CodeBranchIcon,
11
+ file: TenantIcon,
12
+ deb: FanIcon,
13
+ };
14
+ const Icon = iconMap[type] || BoxIcon;
15
+
16
+ return <Tooltip content={<div>{type}</div>}><Icon /></Tooltip>;
17
+ };
18
+
19
+ RepoIcon.propTypes = {
20
+ type: PropTypes.string.isRequired,
21
+ };
22
+
23
+ export default RepoIcon;
@@ -0,0 +1,49 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Select, SelectOption, SelectVariant, Level, LevelItem } from '@patternfly/react-core';
4
+
5
+ const SelectableDropdown = ({
6
+ items, title, selected, setSelected,
7
+ }) => {
8
+ const [isOpen, setIsOpen] = useState(false);
9
+ const onSelect = (event, selection) => {
10
+ setSelected(selection);
11
+ setIsOpen(false);
12
+ };
13
+ const onToggle = open => setIsOpen(open);
14
+
15
+ const selectItems = items.map(item => <SelectOption key={item} value={item} aria-label={`select ${item}`} />);
16
+
17
+ return (
18
+ <Level>
19
+ <LevelItem>
20
+ <label htmlFor={`select ${title}`} style={{ margin: '0px 5px' }}>
21
+ {`${title}:`}
22
+ </label>
23
+ </LevelItem>
24
+ <LevelItem aria-label={`select ${title} container`}>
25
+ <Select
26
+ id={`select ${title}`}
27
+ key="type-dropdown"
28
+ variant={SelectVariant.single}
29
+ onToggle={onToggle}
30
+ onSelect={onSelect}
31
+ selections={selected}
32
+ isOpen={isOpen}
33
+ >
34
+ {selectItems}
35
+ </Select>
36
+ </LevelItem>
37
+ </Level>
38
+ );
39
+ };
40
+
41
+ SelectableDropdown.propTypes = {
42
+ items: PropTypes.arrayOf(PropTypes.string).isRequired,
43
+ title: PropTypes.string.isRequired,
44
+ selected: PropTypes.string.isRequired,
45
+ setSelected: PropTypes.func.isRequired,
46
+ };
47
+
48
+
49
+ export default SelectableDropdown;
@@ -0,0 +1,154 @@
1
+ {
2
+ "total": 14,
3
+ "subtotal": 14,
4
+ "page": 1,
5
+ "per_page": 20,
6
+ "error": null,
7
+ "search": null,
8
+ "sort": {
9
+ "by": null,
10
+ "order": null
11
+ },
12
+ "results": [
13
+ {
14
+ "backend_identifier": "dbe0d30c-e77b-47aa-8bb7-c0e1a2697eb5",
15
+ "relative_path": "Orion/Library/custom/Lagoon_Nebula/Butterfly",
16
+ "container_repository_name": null,
17
+ "full_path": "http://centos7-katello-devel-stable.example.com/pulp/repos/Orion/Library/custom/Lagoon_Nebula/Butterfly/",
18
+ "library_instance_id": null,
19
+ "version_href": "/pulp/api/v3/repositories/rpm/rpm/ce16107a-b912-4d78-a5d1-9f90066acf8e/versions/1/",
20
+ "remote_href": "/pulp/api/v3/remotes/rpm/rpm/b491c3fb-d9e6-4b7e-a95a-312a8856bf1c/",
21
+ "publication_href": "/pulp/api/v3/publications/rpm/rpm/65b57edc-2e21-4742-be99-28ae6eeb588e/",
22
+ "id": 107,
23
+ "name": "Butterfly",
24
+ "label": "Butterfly",
25
+ "description": null,
26
+ "last_sync": {
27
+ "id": "0ea3e395-4be0-4b75-96be-9b2abf4bba78",
28
+ "username": "admin",
29
+ "started_at": "2020-08-17 13:33:27 -0400",
30
+ "ended_at": "2020-08-17 13:33:33 -0400",
31
+ "state": "stopped",
32
+ "result": "success",
33
+ "progress": 1
34
+ },
35
+ "content_view": {
36
+ "id": 9,
37
+ "name": "Default Organization View"
38
+ },
39
+ "content_view_version": {
40
+ "id": 19,
41
+ "name": "Default Organization View 1.0",
42
+ "content_view_id": 9
43
+ },
44
+ "kt_environment": {
45
+ "id": 15,
46
+ "name": "Library"
47
+ },
48
+ "content_type": "yum",
49
+ "url": "https://jlsherrill.fedorapeople.org/fake-repos/needed-errata/",
50
+ "arch": "noarch",
51
+ "content_id": "1597685535659",
52
+ "auto_enabled": true,
53
+ "major": null,
54
+ "minor": null,
55
+ "product": {
56
+ "id": 3,
57
+ "cp_id": "370238709909",
58
+ "name": "Lagoon Nebula",
59
+ "orphaned": false,
60
+ "redhat": false,
61
+ "sync_plan": null
62
+ },
63
+ "content_label": "Orion_Lagoon_Nebula_Butterfly",
64
+ "content_counts": {
65
+ "ostree_branch": 0,
66
+ "docker_manifest": 0,
67
+ "docker_manifest_list": 0,
68
+ "docker_tag": 0,
69
+ "rpm": 32,
70
+ "srpm": 0,
71
+ "package": 32,
72
+ "package_group": 0,
73
+ "erratum": 4,
74
+ "puppet_module": 0,
75
+ "file": 0,
76
+ "deb": 0,
77
+ "module_stream": 0,
78
+ "ansible_collection": 0
79
+ },
80
+ "last_sync_words": "30 days",
81
+ "added_to_content_view": true
82
+ },
83
+ {
84
+ "backend_identifier": "e0aff6e3-f187-452a-9d7b-f624adf7684d",
85
+ "relative_path": "Orion/Library/custom/Lagoon_Nebula/Coma",
86
+ "container_repository_name": null,
87
+ "full_path": "http://centos7-katello-devel-stable.example.com/pulp/repos/Orion/Library/custom/Lagoon_Nebula/Coma/",
88
+ "library_instance_id": null,
89
+ "version_href": "/pulp/api/v3/repositories/rpm/rpm/a6b32606-0e72-43e5-8470-adc33a7b23d4/versions/1/",
90
+ "remote_href": "/pulp/api/v3/remotes/rpm/rpm/8f194340-7bfa-4af5-8a61-95f3e9a13fb3/",
91
+ "publication_href": "/pulp/api/v3/publications/rpm/rpm/1666923a-3269-46bd-a948-0f4f21474327/",
92
+ "id": 106,
93
+ "name": "Coma",
94
+ "label": "Coma",
95
+ "description": null,
96
+ "last_sync": {
97
+ "id": "8fd554ff-e795-4662-ab16-97466618fd2e",
98
+ "username": "admin",
99
+ "started_at": "2020-08-17 13:33:17 -0400",
100
+ "ended_at": "2020-08-17 13:33:23 -0400",
101
+ "state": "stopped",
102
+ "result": "success",
103
+ "progress": 1
104
+ },
105
+ "content_view": {
106
+ "id": 9,
107
+ "name": "Default Organization View"
108
+ },
109
+ "content_view_version": {
110
+ "id": 19,
111
+ "name": "Default Organization View 1.0",
112
+ "content_view_id": 9
113
+ },
114
+ "kt_environment": {
115
+ "id": 15,
116
+ "name": "Library"
117
+ },
118
+ "content_type": "yum",
119
+ "url": "https://inecas.fedorapeople.org/fakerepos/zoo3/",
120
+ "arch": "noarch",
121
+ "content_id": "1597685531082",
122
+ "auto_enabled": true,
123
+ "major": null,
124
+ "minor": null,
125
+ "product": {
126
+ "id": 3,
127
+ "cp_id": "370238709909",
128
+ "name": "Lagoon Nebula",
129
+ "orphaned": false,
130
+ "redhat": false,
131
+ "sync_plan": null
132
+ },
133
+ "content_label": "Orion_Lagoon_Nebula_Coma",
134
+ "content_counts": {
135
+ "ostree_branch": 1,
136
+ "docker_manifest": 2,
137
+ "docker_manifest_list": 2,
138
+ "docker_tag": 0,
139
+ "rpm": 32,
140
+ "srpm": 2,
141
+ "package": 32,
142
+ "package_group": 2,
143
+ "erratum": 4,
144
+ "puppet_module": 2,
145
+ "file": 2,
146
+ "deb": 2,
147
+ "module_stream": 2,
148
+ "ansible_collection": 2
149
+ },
150
+ "last_sync_words": "30 days",
151
+ "added_to_content_view": true
152
+ }
153
+ ]
154
+ }
@@ -0,0 +1,131 @@
1
+ import React from 'react';
2
+ import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
3
+
4
+ import nock, { nockInstance, assertNockRequest, mockAutocomplete, mockSetting } from '../../../../../test-utils/nockWrapper';
5
+ import api from '../../../../../services/api';
6
+ import CONTENT_VIEWS_KEY from '../../../ContentViewsConstants';
7
+ import ContentViewRepositories from '../ContentViewRepositories';
8
+
9
+ const repoData = require('./contentViewDetailRepos.fixtures.json');
10
+
11
+ const autocompleteUrl = '/repositories/auto_complete_search';
12
+ const renderOptions = { apiNamespace: `${CONTENT_VIEWS_KEY}_1` };
13
+ const cvAllRepos = api.getApiUrl('/content_views/1/repositories/show_all');
14
+ const cvRepos = api.getApiUrl('/content_views/1/repositories');
15
+
16
+ let firstRepo;
17
+ let searchDelayScope;
18
+ let autoSearchScope;
19
+ beforeEach(() => {
20
+ const { results } = repoData;
21
+ [firstRepo] = results;
22
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 500);
23
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', true);
24
+ });
25
+
26
+ afterEach(() => {
27
+ nock.cleanAll();
28
+ assertNockRequest(searchDelayScope);
29
+ assertNockRequest(autoSearchScope);
30
+ });
31
+
32
+ test('Can call API and show repositories on page load', async (done) => {
33
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
34
+
35
+ const scope = nockInstance
36
+ .get(cvAllRepos)
37
+ .query(true)
38
+ .reply(200, repoData);
39
+
40
+ const { getByText, queryByText } = renderWithRedux(
41
+ <ContentViewRepositories cvId={1} />,
42
+ renderOptions,
43
+ );
44
+
45
+ // Nothing will show at first, page is loading
46
+ expect(queryByText(firstRepo.name)).toBeNull();
47
+ // Assert that the repo name is now showing on the screen, but wait for it to appear.
48
+ await patientlyWaitFor(() => expect(getByText(firstRepo.name)).toBeTruthy());
49
+
50
+
51
+ assertNockRequest(autocompleteScope);
52
+ assertNockRequest(scope, done);
53
+ });
54
+
55
+ test('Can filter by repository type', async (done) => {
56
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
57
+
58
+ const allTypesScope = nockInstance
59
+ .get(cvAllRepos)
60
+ .query(true)
61
+ .reply(200, repoData);
62
+
63
+ // With the yum checkbox unchecked, we can expect the query params to not include 'yum'
64
+ const noYumScope = nockInstance
65
+ .get(cvAllRepos)
66
+ .query(queryObj => queryObj.content_type === 'yum')
67
+ .reply(200, repoData);
68
+
69
+ const { getByLabelText } = renderWithRedux(<ContentViewRepositories cvId={1} />, renderOptions);
70
+
71
+ // Patternfly's Select component makes it hard to attach a label, the existing options aren't
72
+ // working as expected, so querying by container label and getting first button to open dropdown
73
+ const toggleContainer = getByLabelText('select Type container');
74
+ const toggleButton = toggleContainer.querySelector('button');
75
+ fireEvent.click(toggleButton); // Open type dropdown
76
+ fireEvent.click(getByLabelText('select Yum repositories')); // select yum repos
77
+
78
+ assertNockRequest(autocompleteScope);
79
+ assertNockRequest(allTypesScope);
80
+ assertNockRequest(noYumScope, done);
81
+ });
82
+
83
+ test('Can filter by Not added status', async (done) => {
84
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
85
+
86
+ const allStatusScope = nockInstance
87
+ .get(cvAllRepos)
88
+ .query(true)
89
+ .reply(200, repoData);
90
+
91
+ const notAddedScope = nockInstance
92
+ .get(cvRepos)
93
+ .query(params => params.available_for === 'content_view')
94
+ .reply(200, repoData);
95
+
96
+ const { getByLabelText } = renderWithRedux(<ContentViewRepositories cvId={1} />, renderOptions);
97
+
98
+ const toggleContainer = getByLabelText('select Status container');
99
+ const toggleButton = toggleContainer.querySelector('button');
100
+ fireEvent.click(toggleButton);
101
+ fireEvent.click(getByLabelText('select Not added'));
102
+
103
+ assertNockRequest(autocompleteScope);
104
+ assertNockRequest(allStatusScope);
105
+ assertNockRequest(notAddedScope, done);
106
+ });
107
+
108
+ test('Can filter by Added status', async (done) => {
109
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
110
+
111
+ const allStatusScope = nockInstance
112
+ .get(cvAllRepos)
113
+ .query(true)
114
+ .reply(200, repoData);
115
+
116
+ const addedScope = nockInstance
117
+ .get(cvRepos)
118
+ .query(true)
119
+ .reply(200, repoData);
120
+
121
+ const { getByLabelText } = renderWithRedux(<ContentViewRepositories cvId={1} />, renderOptions);
122
+
123
+ const toggleContainer = getByLabelText('select Status container');
124
+ const toggleButton = toggleContainer.querySelector('button');
125
+ fireEvent.click(toggleButton);
126
+ fireEvent.click(getByLabelText('select Added'));
127
+
128
+ assertNockRequest(autocompleteScope);
129
+ assertNockRequest(allStatusScope);
130
+ assertNockRequest(addedScope, done);
131
+ });
@@ -11,6 +11,9 @@ const cvDetailData = require('./contentViewDetails.fixtures.json');
11
11
  const renderOptions = { apiNamespace: `${CONTENT_VIEWS_KEY}_1` };
12
12
  const cvDetailsPath = api.getApiUrl('/content_views/1');
13
13
 
14
+ // The Repositories tab will load in the background, prevent this by mocking
15
+ jest.mock('../Repositories/ContentViewRepositories.js', () => () => 'mocked!');
16
+
14
17
  test('Can call API and show details on page load', async (done) => {
15
18
  const { label, name, description } = cvDetailData;
16
19
  const scope = nockInstance
@@ -11,6 +11,7 @@ import getContentViews from '../ContentViewsActions';
11
11
  const ContentViewTable = ({ response, status, error }) => {
12
12
  const [table, setTable] = useState({ rows: [], columns: [] });
13
13
  const [rowMapping, setRowMapping] = useState({});
14
+ const [searchQuery, updateSearchQuery] = useState('');
14
15
  const { results, ...metadata } = response;
15
16
  const loadingResponse = status === STATUS.PENDING;
16
17
 
@@ -28,7 +29,7 @@ const ContentViewTable = ({ response, status, error }) => {
28
29
  [results, JSON.stringify(rowMapping)], // use JSON to check obj values eq not reference eq
29
30
  );
30
31
 
31
- const onSelect = (event, isSelected, rowId) => {
32
+ const onSelect = (_event, isSelected, rowId) => {
32
33
  let rows;
33
34
  if (rowId === -1) {
34
35
  rows = table.rows.map(row => ({ ...row, selected: isSelected }));
@@ -90,6 +91,8 @@ const ContentViewTable = ({ response, status, error }) => {
90
91
  onSelect,
91
92
  onExpand,
92
93
  actionResolver,
94
+ searchQuery,
95
+ updateSearchQuery,
93
96
  }}
94
97
  status={tableStatus()}
95
98
  fetchItems={getContentViews}