katello 4.17.0 → 4.18.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of katello might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/katello/locale/bn/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/bn_IN/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ca/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/cs/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/de/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/de_AT/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/de_DE/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/el/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/en/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/en_GB/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/en_US/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/es/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/et_EE/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/fr/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/gl/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/gu/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/he_IL/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/hi/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/id/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/it/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ja/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/ka/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/kn/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ko/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/ml_IN/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/mr/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/nl_NL/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/or/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/pa/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/pl/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/pl_PL/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/pt/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/pt_BR/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/ro/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ro_RO/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ru/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/sl/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/sv_SE/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ta/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/ta_IN/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/te/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/tr/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/vi/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/vi_VN/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/zh/katello.js +148 -4
- data/app/assets/javascripts/katello/locale/zh_CN/katello.js +147 -3
- data/app/assets/javascripts/katello/locale/zh_TW/katello.js +148 -4
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +14 -14
- data/app/controllers/katello/api/v2/content_uploads_controller.rb +2 -1
- data/app/controllers/katello/api/v2/errata_controller.rb +16 -0
- data/app/controllers/katello/api/v2/flatpak_remote_repositories_controller.rb +20 -3
- data/app/controllers/katello/api/v2/flatpak_remotes_controller.rb +7 -3
- data/app/controllers/katello/api/v2/generic_content_units_controller.rb +1 -2
- data/app/controllers/katello/api/v2/products_controller.rb +18 -0
- data/app/controllers/katello/api/v2/repositories_controller.rb +5 -3
- data/app/controllers/katello/concerns/api/v2/hosts_bulk_actions_controller_extensions.rb +10 -0
- data/app/controllers/katello/concerns/api/v2/registration_commands_controller_extensions.rb +1 -0
- data/app/controllers/katello/concerns/filtered_auto_complete_search.rb +17 -0
- data/app/lib/actions/helpers/smart_proxy_sync_helper.rb +12 -0
- data/app/lib/actions/katello/content_view/add_rolling_repo_clone.rb +4 -4
- data/app/lib/actions/katello/content_view/capsule_sync.rb +8 -3
- data/app/lib/actions/katello/content_view/publish.rb +39 -12
- data/app/lib/actions/katello/flatpak/mirror_remote_repository.rb +2 -1
- data/app/lib/actions/katello/repository/capsule_sync.rb +11 -1
- data/app/lib/actions/katello/repository/destroy.rb +3 -0
- data/app/lib/actions/katello/repository/import_upload.rb +2 -3
- data/app/lib/actions/katello/repository/sync.rb +2 -1
- data/app/lib/actions/katello/repository/upload_files.rb +2 -1
- data/app/lib/katello/concerns/bookmark_controller_validator_extensions.rb +1 -1
- data/app/lib/katello/resources/cdn.rb +1 -1
- data/app/models/katello/concerns/smart_proxy_extensions.rb +46 -8
- data/app/models/katello/content_view_environment.rb +1 -1
- data/app/models/katello/erratum.rb +26 -1
- data/app/models/katello/flatpak_remote.rb +0 -1
- data/app/models/katello/flatpak_remote_repository.rb +24 -0
- data/app/models/katello/glue/pulp/repos.rb +1 -1
- data/app/models/katello/root_repository.rb +1 -0
- data/app/presenters/katello/flatpak_remote_mirror_status_presenter.rb +41 -0
- data/app/services/katello/repository_type_manager.rb +2 -0
- data/app/views/foreman/job_templates/flatpak_install.erb +17 -2
- data/app/views/foreman/job_templates/flatpak_login_action.erb +17 -3
- data/app/views/foreman/job_templates/install_errata_by_search_query.erb +1 -1
- data/app/views/foreman/job_templates/install_errata_by_search_query_-_katello_ansible_default.erb +1 -1
- data/app/views/foreman/job_templates/install_packages_by_search_query_-_katello_ansible_default.erb +6 -14
- data/app/views/foreman/job_templates/remove_packages_by_search_query_-_katello_ansible_default.erb +2 -15
- data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +5 -13
- data/app/views/katello/api/v2/flatpak_remote_repositories/base.json.rabl +3 -1
- data/app/views/katello/api/v2/flatpak_remotes/base.json.rabl +5 -0
- data/app/views/katello/api/v2/flatpak_remotes/permissions.json.rabl +1 -0
- data/config/routes/api/v2.rb +1 -1
- data/config/routes.rb +3 -0
- data/db/migrate/20240924161240_katello_recreate_evr_constructs.rb +20 -0
- data/db/migrate/20250613210050_use_big_int_for_erratum_packages_id.rb +11 -0
- data/db/migrate/20250714190050_add_missing_rpms_evr_index.rb +14 -0
- data/db/seeds.d/108-subcription-bookmarks.rb +2 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/views/errata.html +5 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +4 -5
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/bn.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/bn_IN.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ca.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/cs_CZ.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de_AT.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de_DE.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/el.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/en_GB.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/en_US.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/et_EE.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/gl.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/gu.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/he_IL.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/hi.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/id.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ka.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/kn.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ml_IN.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/mr.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/nl_NL.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/or.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pa.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pl.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pl_PL.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ro.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ro_RO.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/sl.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/sv_SE.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ta.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ta_IN.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/te.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/tr.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/vi.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/vi_VN.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +13 -3
- data/engines/bastion_katello/lib/bastion_katello/engine.rb +2 -0
- data/lib/katello/engine.rb +0 -1
- data/lib/katello/permission_creator.rb +1 -1
- data/lib/katello/plugin.rb +26 -2
- data/lib/katello/version.rb +1 -1
- data/lib/katello.rb +0 -1
- data/lib/proxy_api/container_gateway.rb +24 -0
- data/locale/bn/LC_MESSAGES/katello.mo +0 -0
- data/locale/bn/katello.po +148 -4
- data/locale/bn_IN/LC_MESSAGES/katello.mo +0 -0
- data/locale/bn_IN/katello.po +148 -4
- data/locale/ca/LC_MESSAGES/katello.mo +0 -0
- data/locale/ca/katello.po +148 -4
- data/locale/cs/LC_MESSAGES/katello.mo +0 -0
- data/locale/cs/katello.po +148 -4
- data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
- data/locale/cs_CZ/katello.po +148 -4
- data/locale/de/katello.po +147 -3
- data/locale/de_AT/LC_MESSAGES/katello.mo +0 -0
- data/locale/de_AT/katello.po +148 -4
- data/locale/de_DE/LC_MESSAGES/katello.mo +0 -0
- data/locale/de_DE/katello.po +148 -4
- data/locale/el/LC_MESSAGES/katello.mo +0 -0
- data/locale/el/katello.po +148 -4
- data/locale/en/LC_MESSAGES/katello.mo +0 -0
- data/locale/en/katello.po +148 -4
- data/locale/en_GB/LC_MESSAGES/katello.mo +0 -0
- data/locale/en_GB/katello.po +148 -4
- data/locale/en_US/LC_MESSAGES/katello.mo +0 -0
- data/locale/en_US/katello.po +148 -4
- data/locale/es/katello.po +147 -3
- data/locale/et_EE/LC_MESSAGES/katello.mo +0 -0
- data/locale/et_EE/katello.po +148 -4
- data/locale/fr/katello.po +147 -3
- data/locale/gl/LC_MESSAGES/katello.mo +0 -0
- data/locale/gl/katello.po +148 -4
- data/locale/gu/LC_MESSAGES/katello.mo +0 -0
- data/locale/gu/katello.po +148 -4
- data/locale/he_IL/LC_MESSAGES/katello.mo +0 -0
- data/locale/he_IL/katello.po +148 -4
- data/locale/hi/LC_MESSAGES/katello.mo +0 -0
- data/locale/hi/katello.po +148 -4
- data/locale/id/LC_MESSAGES/katello.mo +0 -0
- data/locale/id/katello.po +148 -4
- data/locale/it/LC_MESSAGES/katello.mo +0 -0
- data/locale/it/katello.po +148 -4
- data/locale/ja/katello.po +147 -3
- data/locale/ka/katello.po +147 -3
- data/locale/katello.pot +703 -428
- data/locale/kn/LC_MESSAGES/katello.mo +0 -0
- data/locale/kn/katello.po +148 -4
- data/locale/ko/katello.po +147 -3
- data/locale/ml_IN/LC_MESSAGES/katello.mo +0 -0
- data/locale/ml_IN/katello.po +148 -4
- data/locale/mr/LC_MESSAGES/katello.mo +0 -0
- data/locale/mr/katello.po +148 -4
- data/locale/nl_NL/LC_MESSAGES/katello.mo +0 -0
- data/locale/nl_NL/katello.po +148 -4
- data/locale/or/LC_MESSAGES/katello.mo +0 -0
- data/locale/or/katello.po +148 -4
- data/locale/pa/LC_MESSAGES/katello.mo +0 -0
- data/locale/pa/katello.po +148 -4
- data/locale/pl/LC_MESSAGES/katello.mo +0 -0
- data/locale/pl/katello.po +148 -4
- data/locale/pl_PL/LC_MESSAGES/katello.mo +0 -0
- data/locale/pl_PL/katello.po +148 -4
- data/locale/pt/LC_MESSAGES/katello.mo +0 -0
- data/locale/pt/katello.po +148 -4
- data/locale/pt_BR/katello.po +147 -3
- data/locale/ro/LC_MESSAGES/katello.mo +0 -0
- data/locale/ro/katello.po +148 -4
- data/locale/ro_RO/LC_MESSAGES/katello.mo +0 -0
- data/locale/ro_RO/katello.po +148 -4
- data/locale/ru/LC_MESSAGES/katello.mo +0 -0
- data/locale/ru/katello.po +148 -4
- data/locale/sl/LC_MESSAGES/katello.mo +0 -0
- data/locale/sl/katello.po +148 -4
- data/locale/sv_SE/LC_MESSAGES/katello.mo +0 -0
- data/locale/sv_SE/katello.po +148 -4
- data/locale/ta/LC_MESSAGES/katello.mo +0 -0
- data/locale/ta/katello.po +148 -4
- data/locale/ta_IN/LC_MESSAGES/katello.mo +0 -0
- data/locale/ta_IN/katello.po +148 -4
- data/locale/te/LC_MESSAGES/katello.mo +0 -0
- data/locale/te/katello.po +148 -4
- data/locale/tr/LC_MESSAGES/katello.mo +0 -0
- data/locale/tr/katello.po +148 -4
- data/locale/vi/LC_MESSAGES/katello.mo +0 -0
- data/locale/vi/katello.po +148 -4
- data/locale/vi_VN/LC_MESSAGES/katello.mo +0 -0
- data/locale/vi_VN/katello.po +148 -4
- data/locale/zh/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh/katello.po +148 -4
- data/locale/zh_CN/katello.po +147 -3
- data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_TW/katello.po +148 -4
- data/package.json +0 -1
- data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +2 -2
- data/webpack/components/OptionTooltip/OptionTooltip.scss +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +6 -1
- data/webpack/components/extensions/Hosts/ActionsBar/index.js +11 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +1 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +1 -2
- data/webpack/components/extensions/Hosts/BulkActions/BulkErrataWizard/04_ReviewFooter.js +1 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkPackagesWizard/04_ReviewFooter.js +1 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/01_BulkRepositorySetsTable.js +371 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/03_Review.js +79 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/03_ReviewFooter.js +73 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/BulkRepositorySetsWizard.js +170 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/actions.js +23 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/helpers.js +28 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/index.js +23 -0
- data/webpack/components/extensions/RegistrationCommands/fields/SetupContainerRegistryCerts.js +39 -0
- data/webpack/components/extensions/RegistrationCommands/index.js +7 -0
- data/webpack/components/pf3Table/formatters/ellipsisCellFormatter.js +3 -2
- data/webpack/containers/Application/config.js +11 -0
- data/webpack/global_index.js +3 -1
- data/webpack/scenes/FlatpakRemotes/CreateEdit/CreateFlatpakRemoteModal.js +30 -0
- data/webpack/scenes/FlatpakRemotes/CreateEdit/EditFlatpakRemotesModal.js +38 -0
- data/webpack/scenes/FlatpakRemotes/CreateEdit/FlatpakRemoteform.js +218 -0
- data/webpack/scenes/FlatpakRemotes/CreateEdit/__tests__/flatpakRemoteform.test.js +117 -0
- data/webpack/scenes/FlatpakRemotes/Delete/DeleteFlatpakModal.js +59 -0
- data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetailActions.js +87 -0
- data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetailReducers.js +23 -0
- data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetailSelectors.js +16 -0
- data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetails.js +167 -0
- data/webpack/scenes/FlatpakRemotes/Details/Mirror/MirrorRepositoryModal.js +135 -0
- data/webpack/scenes/FlatpakRemotes/Details/Mirror/__tests__/mirrorRepositoryModal.test.js +167 -0
- data/webpack/scenes/FlatpakRemotes/Details/RemoteRepositories/RemoteRepositoriesTable.js +171 -0
- data/webpack/scenes/FlatpakRemotes/Details/__tests__/flatpakRemoteDetails.fixtures.json +58 -0
- data/webpack/scenes/FlatpakRemotes/Details/__tests__/flatpakRemoteDetails.test.js +90 -0
- data/webpack/scenes/FlatpakRemotes/Details/index.js +4 -0
- data/webpack/scenes/FlatpakRemotes/FlatpakRemotesActions.js +26 -0
- data/webpack/scenes/FlatpakRemotes/FlatpakRemotesConstants.js +15 -0
- data/webpack/scenes/FlatpakRemotes/FlatpakRemotesPage.js +202 -0
- data/webpack/scenes/FlatpakRemotes/FlatpakRemotesSelectors.js +24 -0
- data/webpack/scenes/FlatpakRemotes/__tests__/flatpakRemotesList.fixtures.json +55 -0
- data/webpack/scenes/FlatpakRemotes/__tests__/flatpakRemotesPage.test.js +74 -0
- data/webpack/scenes/FlatpakRemotes/index.js +4 -0
- data/webpack/scenes/Hosts/ChangeContentSource/components/Hosts.js +2 -2
- data/webpack/scenes/RedHatRepositories/components/RecommendedRepositorySetsToggler.scss +1 -1
- data/webpack/scenes/RedHatRepositories/index.scss +1 -1
- data/webpack/scenes/Settings/SettingsSelectors.js +3 -3
- data/webpack/scenes/Settings/index.js +1 -3
- data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +2 -2
- data/webpack/scenes/Subscriptions/SubscriptionsPage.scss +1 -1
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +0 -21
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +0 -44
- data/webpack/scenes/Subscriptions/index.js +1 -3
- metadata +39 -21
- data/webpack/scenes/Settings/SettingsConstants.js +0 -2
- data/webpack/scenes/Settings/SettingsReducer.js +0 -19
@@ -0,0 +1,371 @@
|
|
1
|
+
import React, { useState, useContext } from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import {
|
4
|
+
Alert, Dropdown, DropdownItem, DropdownList,
|
5
|
+
Divider, MenuToggle, MenuToggleAction, ToolbarItem,
|
6
|
+
} from '@patternfly/react-core';
|
7
|
+
import {
|
8
|
+
Tr, Td, Tbody,
|
9
|
+
} from '@patternfly/react-table';
|
10
|
+
import { STATUS } from 'foremanReact/constants';
|
11
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
12
|
+
import { getPageStats, getColumnHelpers } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
|
13
|
+
import { useSet } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
|
14
|
+
import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableIndexPage';
|
15
|
+
import { Table } from 'foremanReact/components/PF4/TableIndexPage/Table/Table';
|
16
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
17
|
+
import { RowSelectTd } from 'foremanReact/components/HostsIndex/RowSelectTd';
|
18
|
+
import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/SelectAllCheckbox';
|
19
|
+
import { noop } from 'foremanReact/common/helpers';
|
20
|
+
|
21
|
+
import katelloApi from '../../../../../services/api';
|
22
|
+
import { repoSetsUrlForOrg, BulkRepositorySetsWizardContext } from './BulkRepositorySetsWizard';
|
23
|
+
|
24
|
+
export const dropdownValues = {
|
25
|
+
0: __('No change'),
|
26
|
+
1: __('Override to enabled'),
|
27
|
+
2: __('Override to disabled'),
|
28
|
+
3: __('Reset to default'),
|
29
|
+
};
|
30
|
+
|
31
|
+
const ContentOverrideDropdown =
|
32
|
+
({
|
33
|
+
repoLabel, pendingOverrides, setPendingOverrides, setShouldValidateStep1,
|
34
|
+
}) => {
|
35
|
+
const [isOpen, setIsOpen] = useState(false);
|
36
|
+
|
37
|
+
const currentValue = pendingOverrides[repoLabel] ?? 0;
|
38
|
+
const currentLabel = dropdownValues[currentValue];
|
39
|
+
const onToggleClick = () => {
|
40
|
+
setIsOpen(!isOpen);
|
41
|
+
};
|
42
|
+
const onSelect = (_event, value) => {
|
43
|
+
setIsOpen(false);
|
44
|
+
setShouldValidateStep1(true);
|
45
|
+
setPendingOverrides({
|
46
|
+
...pendingOverrides,
|
47
|
+
[repoLabel]: value,
|
48
|
+
});
|
49
|
+
};
|
50
|
+
return (
|
51
|
+
<Dropdown
|
52
|
+
key={`pf-ContentOverrideDropdown-${repoLabel}`}
|
53
|
+
isOpen={isOpen}
|
54
|
+
onSelect={onSelect}
|
55
|
+
onOpenChange={openVal => setIsOpen(!openVal)}
|
56
|
+
toggle={toggleRef => (
|
57
|
+
<MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
|
58
|
+
{currentLabel}
|
59
|
+
</MenuToggle>)}
|
60
|
+
ouiaId={`ContentOverrideDropdown-${repoLabel}`}
|
61
|
+
shouldFocusToggleOnSelect
|
62
|
+
>
|
63
|
+
<DropdownList>
|
64
|
+
<DropdownItem value={0} key={`content-override-dropdown-${repoLabel}-no-change`} ouiaId={`content-override-dropdown-${repoLabel}-no-change`}>
|
65
|
+
{__('No change')}
|
66
|
+
</DropdownItem>
|
67
|
+
<DropdownItem value={1} key={`content-override-dropdown-${repoLabel}-enable`} ouiaId={`content-override-dropdown-${repoLabel}-enable`}>
|
68
|
+
{__('Override to enabled')}
|
69
|
+
</DropdownItem>
|
70
|
+
<DropdownItem value={2} key={`content-override-dropdown-${repoLabel}-disable`} ouiaId={`content-override-dropdown-${repoLabel}-disable`}>
|
71
|
+
{__('Override to disabled')}
|
72
|
+
</DropdownItem>
|
73
|
+
<Divider key="divider" />
|
74
|
+
<DropdownItem value={3} key={`content-override-dropdown-${repoLabel}-reset-to-default`} ouiaId={`content-override-dropdown-${repoLabel}-reset-to-default`}>
|
75
|
+
{__('Reset to default')}
|
76
|
+
</DropdownItem>
|
77
|
+
</DropdownList>
|
78
|
+
</Dropdown>
|
79
|
+
);
|
80
|
+
};
|
81
|
+
|
82
|
+
ContentOverrideDropdown.propTypes = {
|
83
|
+
repoLabel: PropTypes.string.isRequired,
|
84
|
+
pendingOverrides: PropTypes.shape({
|
85
|
+
[PropTypes.string]: PropTypes.number,
|
86
|
+
}).isRequired,
|
87
|
+
setPendingOverrides: PropTypes.func.isRequired,
|
88
|
+
setShouldValidateStep1: PropTypes.func.isRequired,
|
89
|
+
};
|
90
|
+
|
91
|
+
export const BulkRepositorySetsTable = ({
|
92
|
+
repoSetsBulkSelect,
|
93
|
+
repoSetsResults,
|
94
|
+
repoSetsMetadata,
|
95
|
+
repoSetsResponse,
|
96
|
+
}) => {
|
97
|
+
const {
|
98
|
+
selectPage,
|
99
|
+
selectNone,
|
100
|
+
selectOne,
|
101
|
+
isSelected,
|
102
|
+
selectedCount,
|
103
|
+
selectedResults,
|
104
|
+
areAllRowsSelected,
|
105
|
+
areAllRowsOnPageSelected,
|
106
|
+
updateSearchQuery,
|
107
|
+
} = repoSetsBulkSelect;
|
108
|
+
|
109
|
+
const repoSetsWizardContext = useContext(BulkRepositorySetsWizardContext);
|
110
|
+
const {
|
111
|
+
pendingOverrides, setPendingOverrides, shouldValidateStep1,
|
112
|
+
setShouldValidateStep1, repoSetsSelectionIsValid,
|
113
|
+
setRepoSetsParamsAndAPI,
|
114
|
+
} = repoSetsWizardContext;
|
115
|
+
const orgId = useForemanOrganization()?.id;
|
116
|
+
const [actionDropdownValue, setActionDropdownValue] = useState(0);
|
117
|
+
const [actionToggleOpen, setActionToggleOpen] = useState(false);
|
118
|
+
|
119
|
+
const {
|
120
|
+
total, page, subtotal, per_page: perPage,
|
121
|
+
} = repoSetsMetadata;
|
122
|
+
const apiOptions = { key: 'BULK_HOST_REPO_SETS' };
|
123
|
+
const { status: repoSetsLoadingStatus } = repoSetsResponse;
|
124
|
+
const pageStats = getPageStats({ total: subtotal, page, perPage });
|
125
|
+
|
126
|
+
const expandedRepos = useSet([]);
|
127
|
+
const repoIsExpanded = id => expandedRepos.has(id);
|
128
|
+
|
129
|
+
const columns = {
|
130
|
+
name: {
|
131
|
+
title: __('Name'),
|
132
|
+
wrapper: (repo) => {
|
133
|
+
const productId = repo?.product?.id;
|
134
|
+
const href = `/products/${productId}/repositories/`;
|
135
|
+
return (
|
136
|
+
<a target="_blank" href={href} rel="noreferrer">{repo.name}</a>
|
137
|
+
);
|
138
|
+
},
|
139
|
+
isSorted: true,
|
140
|
+
weight: 50,
|
141
|
+
},
|
142
|
+
enabled_by_default: {
|
143
|
+
title: __('Status'),
|
144
|
+
wrapper: ({ label }) => (
|
145
|
+
<ContentOverrideDropdown
|
146
|
+
key={label ?? 'no-label'}
|
147
|
+
repoLabel={label}
|
148
|
+
pendingOverrides={pendingOverrides}
|
149
|
+
setPendingOverrides={setPendingOverrides}
|
150
|
+
setShouldValidateStep1={setShouldValidateStep1}
|
151
|
+
/>
|
152
|
+
),
|
153
|
+
isSorted: false,
|
154
|
+
weight: 100,
|
155
|
+
},
|
156
|
+
};
|
157
|
+
|
158
|
+
const selectionToolbar = (
|
159
|
+
<ToolbarItem key="selectAll">
|
160
|
+
<SelectAllCheckbox
|
161
|
+
{...{
|
162
|
+
selectAll: noop,
|
163
|
+
selectOne,
|
164
|
+
updateSearchQuery,
|
165
|
+
selectNone,
|
166
|
+
selectPage,
|
167
|
+
selectedCount,
|
168
|
+
pageRowCount: pageStats.pageRowCount,
|
169
|
+
areAllRowsSelected,
|
170
|
+
areAllRowsOnPageSelected,
|
171
|
+
}}
|
172
|
+
totalCount={total}
|
173
|
+
areAllRowsOnPageSelected={areAllRowsOnPageSelected()}
|
174
|
+
areAllRowsSelected={areAllRowsSelected()}
|
175
|
+
/>
|
176
|
+
</ToolbarItem>
|
177
|
+
);
|
178
|
+
|
179
|
+
const onToggleClick = () => {
|
180
|
+
setActionToggleOpen(!actionToggleOpen);
|
181
|
+
};
|
182
|
+
const handleActionToggle = (value) => {
|
183
|
+
const result = {};
|
184
|
+
selectedResults.forEach((repo) => {
|
185
|
+
result[repo.label] = value;
|
186
|
+
});
|
187
|
+
setPendingOverrides({ ...pendingOverrides, ...result });
|
188
|
+
setShouldValidateStep1(true);
|
189
|
+
};
|
190
|
+
const onSelect = (_event, value) => {
|
191
|
+
handleActionToggle(value);
|
192
|
+
setActionToggleOpen(false);
|
193
|
+
};
|
194
|
+
|
195
|
+
const actionButton = (
|
196
|
+
<Dropdown
|
197
|
+
isOpen={actionToggleOpen}
|
198
|
+
onSelect={onSelect}
|
199
|
+
onOpenChange={val => setActionToggleOpen(!val)}
|
200
|
+
key="content-override-action-dropdown"
|
201
|
+
ouiaId="content-override-action-dropdown"
|
202
|
+
toggle={toggleRef => (
|
203
|
+
<MenuToggle
|
204
|
+
ref={toggleRef}
|
205
|
+
onClick={onToggleClick}
|
206
|
+
isExpanded={actionToggleOpen}
|
207
|
+
variant="primary"
|
208
|
+
splitButtonOptions={{
|
209
|
+
variant: 'action',
|
210
|
+
items: [
|
211
|
+
<MenuToggleAction
|
212
|
+
isDisabled={selectedCount === 0}
|
213
|
+
id="split-button-action-example-with-toggle-button"
|
214
|
+
key="split-action"
|
215
|
+
aria-label="Action"
|
216
|
+
onClick={() => handleActionToggle(actionDropdownValue)}
|
217
|
+
>
|
218
|
+
{dropdownValues[actionDropdownValue]}
|
219
|
+
</MenuToggleAction>],
|
220
|
+
}}
|
221
|
+
aria-label="Content override action to apply to all selected repositories"
|
222
|
+
isDisabled={selectedCount === 0}
|
223
|
+
/>
|
224
|
+
)}
|
225
|
+
>
|
226
|
+
<DropdownList>
|
227
|
+
{Object.entries(dropdownValues).map(([key, value]) => (
|
228
|
+
<DropdownItem
|
229
|
+
key={key}
|
230
|
+
value={key}
|
231
|
+
ouiaId={`content-override-action-dropdown-${key}`}
|
232
|
+
onClick={() => setActionDropdownValue(key)}
|
233
|
+
>
|
234
|
+
{value}
|
235
|
+
</DropdownItem>
|
236
|
+
))}
|
237
|
+
</DropdownList>
|
238
|
+
</Dropdown>
|
239
|
+
);
|
240
|
+
|
241
|
+
const [columnNamesKeys, keysToColumnNames] = getColumnHelpers(columns);
|
242
|
+
|
243
|
+
return (
|
244
|
+
<>
|
245
|
+
{shouldValidateStep1 && !repoSetsSelectionIsValid && (
|
246
|
+
<Alert
|
247
|
+
ouiaId="no-reposet-changes-alert"
|
248
|
+
variant="info"
|
249
|
+
isInline
|
250
|
+
title={__('Change the status of at least one repository.')}
|
251
|
+
style={{ marginBottom: '1rem' }}
|
252
|
+
/>
|
253
|
+
)}
|
254
|
+
<TableIndexPage
|
255
|
+
customToolbarItems={[actionButton]}
|
256
|
+
selectionToolbar={selectionToolbar}
|
257
|
+
results={repoSetsResults}
|
258
|
+
metadata={repoSetsMetadata}
|
259
|
+
response={repoSetsResponse}
|
260
|
+
tableType="repository_sets"
|
261
|
+
apiUrl={repoSetsUrlForOrg(orgId)}
|
262
|
+
apiOptions={apiOptions}
|
263
|
+
selectedCount={selectedCount}
|
264
|
+
selectPage={selectPage}
|
265
|
+
selectNone={selectNone}
|
266
|
+
customSearchProps={{
|
267
|
+
autocomplete: {
|
268
|
+
url: katelloApi.getApiUrl('/repository_sets/auto_complete_search'),
|
269
|
+
},
|
270
|
+
}}
|
271
|
+
bulkSelect={repoSetsBulkSelect}
|
272
|
+
updateParamsByUrl={false}
|
273
|
+
>
|
274
|
+
<Table
|
275
|
+
childrenOutsideTbody
|
276
|
+
showCheckboxes
|
277
|
+
rowSelectTd={RowSelectTd}
|
278
|
+
selectOne={selectOne}
|
279
|
+
isSelected={isSelected}
|
280
|
+
isEmbedded
|
281
|
+
idColumn="label"
|
282
|
+
columns={columns}
|
283
|
+
refreshData={noop}
|
284
|
+
url=""
|
285
|
+
results={repoSetsResults}
|
286
|
+
isPending={repoSetsLoadingStatus === STATUS.PENDING}
|
287
|
+
params={{ ...repoSetsMetadata, perPage, page }}
|
288
|
+
setParams={setRepoSetsParamsAndAPI}
|
289
|
+
page={page}
|
290
|
+
perPage={perPage}
|
291
|
+
itemCount={subtotal}
|
292
|
+
>
|
293
|
+
{repoSetsResults.map((result, rowIndex) => {
|
294
|
+
const repoLabel = result.label;
|
295
|
+
const isExpanded = repoIsExpanded(repoLabel);
|
296
|
+
return (
|
297
|
+
<Tbody isExpanded={isExpanded} key={`tbody1-${repoLabel}`}>
|
298
|
+
<Tr
|
299
|
+
key={repoLabel}
|
300
|
+
ouiaId={`table-row-${rowIndex}`}
|
301
|
+
isClickable
|
302
|
+
>
|
303
|
+
<Td
|
304
|
+
expand={{
|
305
|
+
rowIndex,
|
306
|
+
isExpanded,
|
307
|
+
onToggle: (_event, _rInx, isOpen) =>
|
308
|
+
expandedRepos.onToggle(isOpen, repoLabel),
|
309
|
+
}}
|
310
|
+
/>
|
311
|
+
<RowSelectTd
|
312
|
+
rowData={result}
|
313
|
+
selectOne={selectOne}
|
314
|
+
isSelected={isSelected}
|
315
|
+
idColumnName="label"
|
316
|
+
/>
|
317
|
+
{columnNamesKeys.map(k => (
|
318
|
+
<Td key={k} dataLabel={keysToColumnNames[k]}>
|
319
|
+
{columns[k].wrapper
|
320
|
+
? columns[k].wrapper(result)
|
321
|
+
: result[k]}
|
322
|
+
</Td>
|
323
|
+
))}
|
324
|
+
</Tr>
|
325
|
+
<Tr key={`child-row-${repoLabel}`} ouiaId={`child-row-${repoLabel}`} isExpanded={isExpanded}>
|
326
|
+
<Td />
|
327
|
+
<Td />
|
328
|
+
<Td colSpan={2}>
|
329
|
+
<pre style={{ marginTop: '0.63rem' }} id={`pre-repo-label-${repoLabel}`}>{repoLabel}</pre>
|
330
|
+
</Td>
|
331
|
+
</Tr>
|
332
|
+
</Tbody>
|
333
|
+
);
|
334
|
+
})}
|
335
|
+
</Table>
|
336
|
+
</TableIndexPage>
|
337
|
+
</>
|
338
|
+
);
|
339
|
+
};
|
340
|
+
|
341
|
+
BulkRepositorySetsTable.propTypes = {
|
342
|
+
repoSetsBulkSelect: PropTypes.shape({
|
343
|
+
selectAll: PropTypes.func.isRequired,
|
344
|
+
selectPage: PropTypes.func.isRequired,
|
345
|
+
selectNone: PropTypes.func.isRequired,
|
346
|
+
selectOne: PropTypes.func.isRequired,
|
347
|
+
isSelected: PropTypes.func.isRequired,
|
348
|
+
selectedCount: PropTypes.number.isRequired,
|
349
|
+
areAllRowsSelected: PropTypes.func.isRequired,
|
350
|
+
areAllRowsOnPageSelected: PropTypes.func.isRequired,
|
351
|
+
updateSearchQuery: PropTypes.func.isRequired,
|
352
|
+
selectedResults: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
353
|
+
}).isRequired,
|
354
|
+
repoSetsResults: PropTypes.arrayOf(PropTypes.shape({})),
|
355
|
+
repoSetsMetadata: PropTypes.shape({
|
356
|
+
total: PropTypes.number,
|
357
|
+
page: PropTypes.number,
|
358
|
+
subtotal: PropTypes.number,
|
359
|
+
per_page: PropTypes.number,
|
360
|
+
}).isRequired,
|
361
|
+
repoSetsResponse: PropTypes.shape({
|
362
|
+
response: PropTypes.shape({}),
|
363
|
+
status: PropTypes.string,
|
364
|
+
}).isRequired,
|
365
|
+
};
|
366
|
+
|
367
|
+
BulkRepositorySetsTable.defaultProps = {
|
368
|
+
repoSetsResults: [],
|
369
|
+
};
|
370
|
+
|
371
|
+
export default BulkRepositorySetsTable;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import {
|
3
|
+
Badge,
|
4
|
+
Button,
|
5
|
+
Flex,
|
6
|
+
FlexItem,
|
7
|
+
Text,
|
8
|
+
TextContent,
|
9
|
+
TextVariants,
|
10
|
+
Grid,
|
11
|
+
GridItem,
|
12
|
+
useWizardContext,
|
13
|
+
} from '@patternfly/react-core';
|
14
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
15
|
+
import { BulkRepositorySetsWizardContext } from './BulkRepositorySetsWizard';
|
16
|
+
import { dropdownValues } from './01_BulkRepositorySetsTable';
|
17
|
+
|
18
|
+
export const BulkRepositorySetsReview = () => {
|
19
|
+
const { goToStepById } = useWizardContext();
|
20
|
+
const {
|
21
|
+
pendingOverrides,
|
22
|
+
} = useContext(BulkRepositorySetsWizardContext);
|
23
|
+
const overridesEntries = Object.entries(pendingOverrides);
|
24
|
+
const overridesTexts = overridesEntries
|
25
|
+
.filter(([_repoLabel, value]) => Number(value) !== 0)
|
26
|
+
.map(([repoLabel, value]) => [repoLabel, dropdownValues[value]]);
|
27
|
+
|
28
|
+
return (
|
29
|
+
<>
|
30
|
+
<TextContent>
|
31
|
+
<Text component={TextVariants.h3} ouiaId="bulk-repo-sets-wizard-review-header">
|
32
|
+
{__('Review')}
|
33
|
+
</Text>
|
34
|
+
<Text component={TextVariants.p} ouiaId="bulk-repo-sets-wizard-review-description">
|
35
|
+
{__('Review and then click \'Set content overrides.\' Status will be changed for the selected repository sets on the selected hosts.')}
|
36
|
+
</Text>
|
37
|
+
</TextContent>
|
38
|
+
<Grid>
|
39
|
+
<GridItem span={8}>
|
40
|
+
<Flex>
|
41
|
+
<FlexItem>
|
42
|
+
<Text component={TextVariants.h4} ouiaId="bulk-repo-sets-wizard-review-header">
|
43
|
+
<strong>{__('Changed status')}</strong>
|
44
|
+
</Text>
|
45
|
+
</FlexItem>
|
46
|
+
<FlexItem>
|
47
|
+
<Badge isRead>
|
48
|
+
{overridesTexts.length}
|
49
|
+
</Badge>
|
50
|
+
</FlexItem>
|
51
|
+
</Flex>
|
52
|
+
</GridItem>
|
53
|
+
<GridItem span={4}>
|
54
|
+
<Text component={TextVariants.p} ouiaId="brsw-review-step-edit-wrapper">
|
55
|
+
<Button variant="link" onClick={() => goToStepById('brsw-step-1')} ouiaId="brsw-review-step-edit-btn">
|
56
|
+
{__('Edit')}
|
57
|
+
</Button>
|
58
|
+
</Text>
|
59
|
+
</GridItem>
|
60
|
+
{overridesTexts.map(([repoLabel, actionText]) => (
|
61
|
+
<React.Fragment key={repoLabel}>
|
62
|
+
<GridItem span={8}>
|
63
|
+
<Text component={TextVariants.p} ouiaId="brsw-review-step-repo-label">
|
64
|
+
{repoLabel}
|
65
|
+
</Text>
|
66
|
+
</GridItem>
|
67
|
+
<GridItem span={4}>
|
68
|
+
<Text component={TextVariants.p} ouiaId="brsw-review-step-action-text">
|
69
|
+
{actionText}
|
70
|
+
</Text>
|
71
|
+
</GridItem>
|
72
|
+
</React.Fragment>
|
73
|
+
))}
|
74
|
+
</Grid>
|
75
|
+
</>
|
76
|
+
);
|
77
|
+
};
|
78
|
+
|
79
|
+
export default BulkRepositorySetsReview;
|
data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/03_ReviewFooter.js
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { useDispatch } from 'react-redux';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
import {
|
5
|
+
Button,
|
6
|
+
WizardFooterWrapper,
|
7
|
+
useWizardContext,
|
8
|
+
} from '@patternfly/react-core';
|
9
|
+
import { BulkRepositorySetsWizardContext } from './BulkRepositorySetsWizard';
|
10
|
+
import { bulkUpdateHostContentOverrides } from './actions';
|
11
|
+
import { pendingOverrideToApiParamItem } from './helpers';
|
12
|
+
|
13
|
+
export const BulkRepositorySetsReviewFooter = () => {
|
14
|
+
const {
|
15
|
+
pendingOverrides,
|
16
|
+
finishButtonText,
|
17
|
+
allStepsValid,
|
18
|
+
finishButtonLoading,
|
19
|
+
setFinishButtonLoading,
|
20
|
+
closeModal,
|
21
|
+
hostsBulkSelect,
|
22
|
+
} = useContext(BulkRepositorySetsWizardContext);
|
23
|
+
|
24
|
+
const { goToStepById } = useWizardContext();
|
25
|
+
const dispatch = useDispatch();
|
26
|
+
|
27
|
+
const overridesEntries = Object.entries(pendingOverrides);
|
28
|
+
const apiParams = overridesEntries
|
29
|
+
.map(([repoLabel, value]) => pendingOverrideToApiParamItem({ repoLabel, value }))
|
30
|
+
.filter(item => item);
|
31
|
+
|
32
|
+
const saveContentOverrides = () => {
|
33
|
+
const requestBody = {
|
34
|
+
included: {
|
35
|
+
search: hostsBulkSelect.fetchBulkParams(),
|
36
|
+
},
|
37
|
+
content_overrides: apiParams,
|
38
|
+
};
|
39
|
+
dispatch(bulkUpdateHostContentOverrides(
|
40
|
+
requestBody,
|
41
|
+
closeModal, closeModal,
|
42
|
+
));
|
43
|
+
};
|
44
|
+
|
45
|
+
const handleFinishButtonClick = () => {
|
46
|
+
setFinishButtonLoading(true);
|
47
|
+
saveContentOverrides();
|
48
|
+
closeModal();
|
49
|
+
};
|
50
|
+
return (
|
51
|
+
<WizardFooterWrapper>
|
52
|
+
<Button variant="secondary" onClick={() => goToStepById('brsw-step-2')} isDisabled={finishButtonLoading} ouiaId="bulk-reposets-wiz-step3-back">
|
53
|
+
{__('Back')}
|
54
|
+
</Button>
|
55
|
+
<Button
|
56
|
+
key="bulk-repo-sets-wizard-finish-button"
|
57
|
+
ouiaId="bulk-repo-sets-wizard-finish-button"
|
58
|
+
type="submit"
|
59
|
+
variant="primary"
|
60
|
+
isLoading={finishButtonLoading}
|
61
|
+
isDisabled={finishButtonLoading || !allStepsValid}
|
62
|
+
onClick={handleFinishButtonClick}
|
63
|
+
>
|
64
|
+
{finishButtonText}
|
65
|
+
</Button>
|
66
|
+
<Button variant="link" onClick={closeModal} isDisabled={finishButtonLoading} ouiaId="bulk-repo-sets-wiz-step3-cancel">
|
67
|
+
{__('Cancel')}
|
68
|
+
</Button>
|
69
|
+
</WizardFooterWrapper>
|
70
|
+
);
|
71
|
+
};
|
72
|
+
|
73
|
+
export default BulkRepositorySetsReviewFooter;
|
@@ -0,0 +1,170 @@
|
|
1
|
+
import React, { useState, createContext, useContext } from 'react';
|
2
|
+
import {
|
3
|
+
Text,
|
4
|
+
TextVariants,
|
5
|
+
TextContent,
|
6
|
+
Wizard,
|
7
|
+
WizardHeader,
|
8
|
+
WizardStep,
|
9
|
+
} from '@patternfly/react-core';
|
10
|
+
|
11
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
12
|
+
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
13
|
+
import { useBulkSelect } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
|
14
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
15
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
16
|
+
import { useTableIndexAPIResponse, useSetParamsAndApiAndSearch } from 'foremanReact/components/PF4/TableIndexPage/Table/TableIndexHooks';
|
17
|
+
|
18
|
+
import { BulkRepositorySetsTable } from './01_BulkRepositorySetsTable';
|
19
|
+
import { BulkRepositorySetsReview } from './03_Review';
|
20
|
+
import HostReview from '../HostReview';
|
21
|
+
import katelloApi from '../../../../../services/api';
|
22
|
+
import { useHostsBulkSelect } from '../BulkPackagesWizard/BulkPackagesWizard';
|
23
|
+
import { BulkRepositorySetsReviewFooter } from './03_ReviewFooter';
|
24
|
+
|
25
|
+
const DEFAULT_PER_PAGE = 5;
|
26
|
+
export const BulkRepositorySetsWizardContext = createContext({});
|
27
|
+
export const repoSetsUrlForOrg = orgId =>
|
28
|
+
katelloApi.getApiUrl(`/repository_sets?per_page=${DEFAULT_PER_PAGE}&include_permissions=true&enabled=true&with_custom=true&organization_id=${orgId}`);
|
29
|
+
|
30
|
+
const BulkRepositorySetsWizard = () => {
|
31
|
+
const { modalOpen, setModalClosed: closeModal } = useForemanModal({ id: 'bulk-repo-sets-wizard' });
|
32
|
+
const orgId = useForemanOrganization()?.id;
|
33
|
+
const [pendingOverrides, setPendingOverrides] = useState({}); // { repo_label: 1 }
|
34
|
+
const [shouldValidateStep2, setShouldValidateStep2] = useState(false);
|
35
|
+
const [shouldValidateStep1, setShouldValidateStep1] = useState(false);
|
36
|
+
const [, setCurrentStep] = useState();
|
37
|
+
const onStepChange = (_event, newStep) => setCurrentStep((oldStep) => {
|
38
|
+
setShouldValidateStep1(true);
|
39
|
+
if (oldStep === 'brsw-step-2') setShouldValidateStep2(true);
|
40
|
+
return newStep?.id;
|
41
|
+
});
|
42
|
+
const apiOptions = { key: 'BULK_HOST_REPO_SETS' };
|
43
|
+
|
44
|
+
const finishButtonText = __('Set content overrides');
|
45
|
+
const replacementResponse = !modalOpen ? { response: {} } : false;
|
46
|
+
const { selectedCount: initialSelectedHostCount, fetchBulkParams }
|
47
|
+
= useContext(ForemanActionsBarContext);
|
48
|
+
const repoSetsResponse = useTableIndexAPIResponse({
|
49
|
+
replacementResponse, // don't fetch data if modal is closed
|
50
|
+
apiUrl: repoSetsUrlForOrg(orgId),
|
51
|
+
apiOptions,
|
52
|
+
defaultParams: { per_page: DEFAULT_PER_PAGE },
|
53
|
+
});
|
54
|
+
|
55
|
+
const {
|
56
|
+
response: {
|
57
|
+
results: repoSetsResults,
|
58
|
+
...repoSetsMetadata
|
59
|
+
},
|
60
|
+
setAPIOptions,
|
61
|
+
} = repoSetsResponse;
|
62
|
+
|
63
|
+
const { total, page, subtotal } = repoSetsMetadata;
|
64
|
+
|
65
|
+
const repoSetsBulkSelect = useBulkSelect({
|
66
|
+
results: repoSetsResults,
|
67
|
+
metadata: { total, page, selectable: subtotal },
|
68
|
+
idColumn: 'label',
|
69
|
+
});
|
70
|
+
|
71
|
+
const {
|
72
|
+
setParamsAndAPI: setRepoSetsParamsAndAPI,
|
73
|
+
} = useSetParamsAndApiAndSearch({
|
74
|
+
defaultParams: { search: '' },
|
75
|
+
apiOptions,
|
76
|
+
setAPIOptions,
|
77
|
+
updateSearchQuery: repoSetsBulkSelect.updateSearchQuery,
|
78
|
+
pushToHistory: false,
|
79
|
+
});
|
80
|
+
|
81
|
+
const initialSelectedHosts = fetchBulkParams();
|
82
|
+
|
83
|
+
const hostsBulkSelect =
|
84
|
+
useHostsBulkSelect({ initialSelectedHosts, modalIsOpen: modalOpen });
|
85
|
+
|
86
|
+
// eslint-disable-next-line no-restricted-globals
|
87
|
+
const selectionIsValid = count => count > 0 || isNaN(count);
|
88
|
+
const pendingOverridesCount =
|
89
|
+
Object.values(pendingOverrides).filter(val => Number(val) !== 0).length;
|
90
|
+
const repoSetsSelectionIsValid =
|
91
|
+
selectionIsValid(pendingOverridesCount);
|
92
|
+
const hostSelectionIsValid = selectionIsValid(hostsBulkSelect.hostsBulkSelect.selectedCount);
|
93
|
+
const step1Valid = shouldValidateStep1 ? repoSetsSelectionIsValid : true;
|
94
|
+
const step2Valid = shouldValidateStep2 ? hostSelectionIsValid : true;
|
95
|
+
const allStepsValid = step1Valid && step2Valid;
|
96
|
+
const [finishButtonLoading, setFinishButtonLoading] = useState(false);
|
97
|
+
|
98
|
+
const BulkRepositorySetsWizardContextData = {
|
99
|
+
pendingOverrides,
|
100
|
+
setPendingOverrides,
|
101
|
+
finishButtonText,
|
102
|
+
initialSelectedHostCount,
|
103
|
+
shouldValidateStep1,
|
104
|
+
setShouldValidateStep1,
|
105
|
+
setShouldValidateStep2,
|
106
|
+
allStepsValid,
|
107
|
+
repoSetsSelectionIsValid,
|
108
|
+
setRepoSetsParamsAndAPI,
|
109
|
+
finishButtonLoading,
|
110
|
+
setFinishButtonLoading,
|
111
|
+
closeModal,
|
112
|
+
repoSetsBulkSelect,
|
113
|
+
repoSetsResults,
|
114
|
+
repoSetsMetadata,
|
115
|
+
repoSetsResponse,
|
116
|
+
hostsBulkSelect: hostsBulkSelect.hostsBulkSelect,
|
117
|
+
};
|
118
|
+
return (
|
119
|
+
<BulkRepositorySetsWizardContext.Provider value={BulkRepositorySetsWizardContextData}>
|
120
|
+
<Wizard
|
121
|
+
header={<WizardHeader title={__('Manage repository sets')} onClose={closeModal} />}
|
122
|
+
onStepChange={onStepChange}
|
123
|
+
>
|
124
|
+
<WizardStep
|
125
|
+
name={__('Select repository sets')}
|
126
|
+
id="brsw-step-1"
|
127
|
+
footer={{ isNextDisabled: !step1Valid, onClose: closeModal }}
|
128
|
+
status={step1Valid ? 'default' : 'error'}
|
129
|
+
>
|
130
|
+
<TextContent>
|
131
|
+
<Text component={TextVariants.h3} ouiaId="bulk-repo-sets-wizard-header">
|
132
|
+
{__('Select repository sets')}
|
133
|
+
</Text>
|
134
|
+
<Text component={TextVariants.p} ouiaId="bulk-repo-sets-wizard-description">
|
135
|
+
{__('Below you can add content overrides, which change whether a repository is enabled or disabled. Change their state one by one, or use the checkboxes and select an action to perform.')}
|
136
|
+
</Text>
|
137
|
+
</TextContent>
|
138
|
+
<BulkRepositorySetsTable
|
139
|
+
repoSetsBulkSelect={repoSetsBulkSelect}
|
140
|
+
repoSetsResults={repoSetsResults}
|
141
|
+
repoSetsMetadata={repoSetsMetadata}
|
142
|
+
repoSetsResponse={repoSetsResponse}
|
143
|
+
/>
|
144
|
+
</WizardStep>
|
145
|
+
<WizardStep
|
146
|
+
name={__('Review hosts')}
|
147
|
+
id="brsw-step-2"
|
148
|
+
footer={{ isNextDisabled: !step2Valid, onClose: closeModal }}
|
149
|
+
status={step2Valid ? 'default' : 'error'}
|
150
|
+
>
|
151
|
+
<HostReview
|
152
|
+
key={modalOpen}
|
153
|
+
hostsBulkSelect={hostsBulkSelect}
|
154
|
+
initialSelectedHosts={initialSelectedHosts}
|
155
|
+
setShouldValidateStep={setShouldValidateStep2}
|
156
|
+
/>
|
157
|
+
</WizardStep>
|
158
|
+
<WizardStep
|
159
|
+
name={__('Review')}
|
160
|
+
id="brsw-step-3"
|
161
|
+
footer={<BulkRepositorySetsReviewFooter />}
|
162
|
+
>
|
163
|
+
<BulkRepositorySetsReview />
|
164
|
+
</WizardStep>
|
165
|
+
</Wizard>
|
166
|
+
</BulkRepositorySetsWizardContext.Provider>
|
167
|
+
);
|
168
|
+
};
|
169
|
+
|
170
|
+
export default BulkRepositorySetsWizard;
|