katello 3.16.2 → 3.17.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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/katello/katello.scss +3 -7
- data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
- data/app/controllers/katello/api/v2/activation_keys_controller.rb +8 -0
- data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +10 -4
- data/app/controllers/katello/api/v2/host_tracer_controller.rb +33 -8
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +11 -11
- data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +0 -15
- data/app/controllers/katello/api/v2/repositories_controller.rb +5 -11
- data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +16 -0
- data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +4 -4
- data/app/controllers/katello/concerns/api/v2/hostgroups_controller_extensions.rb +1 -1
- data/app/controllers/katello/concerns/hosts_controller_extensions.rb +5 -11
- data/app/helpers/katello/concerns/dashboard_helper_extensions.rb +10 -0
- data/app/helpers/katello/hosts_and_hostgroups_helper.rb +6 -7
- data/app/lib/actions/candlepin/product/content_add.rb +2 -1
- data/app/lib/actions/candlepin/product/content_update_enablement.rb +18 -0
- data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +2 -6
- data/app/lib/actions/katello/capsule_content/refresh_repos.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +3 -17
- data/app/lib/actions/katello/content_view_version/incremental_update.rb +2 -3
- data/app/lib/actions/katello/organization/simple_content_access/disable.rb +17 -0
- data/app/lib/actions/katello/organization/simple_content_access/enable.rb +17 -0
- data/app/lib/actions/katello/organization/simple_content_access/toggle.rb +36 -0
- data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +13 -0
- data/app/lib/actions/katello/product/content_create.rb +3 -3
- data/app/lib/actions/katello/product/destroy.rb +4 -25
- data/app/lib/actions/katello/repository/content_update.rb +41 -0
- data/app/lib/actions/katello/repository/destroy.rb +1 -5
- data/app/lib/actions/katello/repository/export.rb +1 -1
- data/app/lib/actions/katello/repository/multi_clone_contents.rb +15 -13
- data/app/lib/actions/katello/repository/sync.rb +25 -35
- data/app/lib/actions/katello/repository/update.rb +19 -30
- data/app/lib/actions/katello/repository/update_cv_repo_cert_guard.rb +17 -0
- data/app/lib/actions/pulp/orchestration/repository/smart_proxy_sync.rb +1 -0
- data/app/lib/actions/pulp/orchestration/repository/sync.rb +1 -2
- data/app/lib/actions/pulp/repository/sync.rb +1 -2
- data/app/lib/actions/pulp3/abstract_async_task.rb +0 -1
- data/app/lib/actions/pulp3/capsule_content/sync.rb +1 -3
- data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -1
- data/app/lib/actions/pulp3/orchestration/repository/copy_all_units.rb +2 -1
- data/app/lib/actions/pulp3/orchestration/repository/sync.rb +1 -3
- data/app/lib/actions/pulp3/repository/copy_content.rb +1 -0
- data/app/lib/actions/pulp3/repository/delete.rb +1 -1
- data/app/lib/actions/pulp3/repository/multi_copy_content.rb +1 -1
- data/app/lib/actions/pulp3/repository/save_version.rb +16 -20
- data/app/lib/actions/pulp3/repository/sync.rb +1 -1
- data/app/lib/actions/pulp3/repository/update_cv_repository_cert_guard.rb +2 -6
- data/app/lib/actions/pulp3/repository/upload_file.rb +1 -1
- data/app/lib/katello/resources/candlepin/product.rb +11 -0
- data/app/lib/katello/resources/cdn.rb +2 -3
- data/app/lib/katello/util/cdn_var_substitutor.rb +7 -9
- data/app/lib/katello/validators/hostgroup_kickstart_repository_validator.rb +11 -11
- data/app/models/katello/activation_key.rb +1 -1
- data/app/models/katello/concerns/content_facet_host_extensions.rb +7 -0
- data/app/models/katello/concerns/host_managed_extensions.rb +39 -0
- data/app/models/katello/concerns/hostgroup_extensions.rb +46 -24
- data/app/models/katello/concerns/smart_proxy_extensions.rb +5 -19
- data/app/models/katello/concerns/widget_extensions.rb +23 -0
- data/app/models/katello/content_view.rb +9 -1
- data/app/models/katello/content_view_package_filter.rb +1 -1
- data/app/models/katello/content_view_version.rb +7 -0
- data/app/models/katello/erratum.rb +13 -0
- data/app/models/katello/erratum_cve.rb +8 -0
- data/app/models/katello/glue/pulp/repo.rb +1 -1
- data/app/models/katello/host/content_facet.rb +18 -1
- data/app/models/katello/host_collection.rb +6 -0
- data/app/models/katello/hostgroup/content_facet.rb +18 -0
- data/app/models/katello/installed_package.rb +8 -0
- data/app/models/katello/kt_environment.rb +9 -1
- data/app/models/katello/model.rb +16 -0
- data/app/models/katello/pool.rb +17 -0
- data/app/models/katello/product.rb +6 -0
- data/app/models/katello/purpose_addons_status.rb +1 -0
- data/app/models/katello/purpose_role_status.rb +1 -0
- data/app/models/katello/purpose_sla_status.rb +1 -0
- data/app/models/katello/purpose_usage_status.rb +1 -0
- data/app/models/katello/repository.rb +3 -6
- data/app/models/katello/root_repository.rb +24 -16
- data/app/models/katello/subscription_status.rb +1 -1
- data/app/models/katello/trace_status.rb +1 -1
- data/app/models/setting/content.rb +6 -2
- data/app/services/cert/certs.rb +2 -10
- data/app/services/katello/event_daemon.rb +7 -8
- data/app/services/katello/host_status_manager.rb +13 -0
- data/app/services/katello/pulp3/migration.rb +1 -1
- data/app/services/katello/pulp3/repository/yum.rb +6 -72
- data/app/services/katello/pulp3/repository.rb +11 -10
- data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +1 -1
- data/app/services/katello/pulp3/task.rb +3 -3
- data/app/services/katello/pulp3/task_group.rb +0 -6
- data/app/services/katello/smart_proxy_helper.rb +16 -13
- data/app/views/foreman/smart_proxies/_content_sync.html.erb +1 -1
- data/app/views/katello/api/v2/repositories/base.json.rabl +1 -1
- data/config/routes/api/rhsm.rb +0 -1
- data/config/routes/api/v2.rb +8 -2
- data/config/routes/overrides.rb +0 -4
- data/db/migrate/20141222151001_add_host_content_view_environment.rb +1 -1
- data/db/migrate/20180904122343_create_hostgroup_content_facet.katello.rb +16 -0
- data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +53 -0
- data/db/migrate/20200610112009_remove_audits_of_root_repo_with_content_id.rb +9 -0
- data/db/migrate/20200701150946_add_auto_enabled_to_root_repository.rb +5 -0
- data/db/seeds.d/75-job_templates.rb +2 -2
- data/engines/bastion/app/assets/javascripts/bastion/components/nutupane.factory.js +3 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-associations.controller.js +5 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-details.controller.js +4 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-add-subscriptions.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-associations-content-hosts.html +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-details.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +4 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-packages-modal.controller.js +4 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-subscriptions-modal.controller.js +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-traces-modal.controller.js +4 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-environment-modal.html +7 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-packages-modal.html +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +4 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.routes.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details-info.controller.js +7 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +4 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-add-subscriptions.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-details.html +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +14 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-subscriptions-list.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +6 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-details.controller.js +5 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/views/host-collection-info.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-bulk-action.factory.js +1 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-traces-resolve.factory.js +18 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +45 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/product-bulk-action.factory.js +0 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +0 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +1 -7
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +11 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +16 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository.factory.js +0 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.controller.js +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/views/products.html +0 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +1 -1
- data/lib/katello/engine.rb +6 -5
- data/lib/katello/permission_creator.rb +3 -3
- data/lib/katello/permissions/host_permissions.rb +0 -1
- data/lib/katello/plugin.rb +20 -16
- data/lib/katello/tasks/pulp3_post_migration_check.rake +1 -2
- data/lib/katello/tasks/reimport.rake +1 -1
- data/lib/katello/tasks/reports.rake +0 -12
- data/lib/katello/tasks/test.rake +15 -0
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +48 -48
- data/locale/bn/katello.po +137 -14
- data/locale/cs/katello.po +137 -14
- data/locale/de/katello.po +138 -15
- data/locale/en/katello.po +137 -14
- data/locale/es/katello.po +138 -15
- data/locale/fr/katello.po +138 -15
- data/locale/gu/katello.po +137 -14
- data/locale/hi/katello.po +137 -14
- data/locale/it/katello.po +138 -15
- data/locale/ja/katello.po +138 -15
- data/locale/katello.pot +969 -769
- data/locale/kn/katello.po +137 -14
- data/locale/ko/katello.po +138 -15
- data/locale/mr/katello.po +137 -14
- data/locale/or/katello.po +137 -14
- data/locale/pa/katello.po +137 -14
- data/locale/pt/katello.po +137 -14
- data/locale/pt_BR/katello.po +138 -15
- data/locale/ru/katello.po +138 -15
- data/locale/ta/katello.po +137 -14
- data/locale/te/katello.po +137 -14
- data/locale/zh_CN/katello.po +138 -15
- data/locale/zh_TW/katello.po +138 -15
- data/package.json +8 -25
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +3 -0
- data/webpack/components/ActionableDetail.js +63 -0
- data/webpack/components/Content/ContentTable.js +2 -2
- data/webpack/components/Content/Details/ContentDetailRepositoryTableSchema.js +1 -1
- data/webpack/components/Content/Details/ContentDetails.js +1 -1
- data/webpack/components/Content/__tests__/ContentTable.test.js +2 -2
- data/webpack/components/Content/__tests__/__snapshots__/ContentPage.test.js.snap +1 -1
- data/webpack/components/EditableSwitch.js +30 -0
- data/webpack/components/EditableTextInput/EditableTextInput.js +120 -0
- data/webpack/components/EditableTextInput/__tests__/editableTextInput.test.js +52 -0
- data/webpack/components/EditableTextInput/editableTextInput.scss +14 -0
- data/webpack/components/EditableTextInput/index.js +3 -0
- data/webpack/{scenes/ContentViews/components → components}/Loading.js +8 -5
- data/webpack/{move_to_pf → components}/LoadingState/LoadingState.js +0 -0
- data/webpack/{move_to_pf → components}/LoadingState/LoadingState.scss +0 -0
- data/webpack/{move_to_pf → components}/LoadingState/LoadingState.test.js +0 -0
- data/webpack/{move_to_pf → components}/LoadingState/__snapshots__/LoadingState.test.js.snap +0 -0
- data/webpack/{move_to_pf → components}/LoadingState/index.js +0 -0
- data/webpack/components/MultiSelect/index.js +1 -1
- data/webpack/{move_to_pf → components}/OptionTooltip/OptionTooltip.scss +0 -0
- data/webpack/{move_to_pf → components}/OptionTooltip/__tests__/OptionTooltip.test.js +0 -0
- data/webpack/{move_to_pf → components}/OptionTooltip/__tests__/__snapshots__/OptionTooltip.test.js.snap +0 -0
- data/webpack/{move_to_pf → components}/OptionTooltip/index.js +0 -0
- data/webpack/components/Search/Search.js +124 -0
- data/webpack/components/Search/Search.test.js +2 -1
- data/webpack/components/Search/__snapshots__/Search.test.js.snap +2 -0
- data/webpack/components/Search/__tests__/search.test.js +124 -0
- data/webpack/components/Search/index.js +11 -87
- data/webpack/{move_to_pf → components}/Select/Select.js +0 -0
- data/webpack/components/SelectOrg/SetOrganization.js +2 -2
- data/webpack/components/TabWrapper/TabWrapper.js +26 -0
- data/webpack/components/TabWrapper/index.js +3 -0
- data/webpack/components/TabbedView/TabbedView.js +38 -0
- data/webpack/components/TabbedView/TabbedView.scss +3 -0
- data/webpack/components/TabbedView/index.js +3 -0
- data/webpack/components/Table/EmptyStateMessage.js +61 -0
- data/webpack/{scenes/ContentViews/Table/TableWrapper.js → components/Table/MainTable.js} +23 -12
- data/webpack/components/Table/TableWrapper.js +94 -0
- data/webpack/{move_to_pf → components}/TooltipButton/TooltipButton.js +0 -0
- data/webpack/{move_to_pf → components}/TooltipButton/TooltipButton.scss +0 -0
- data/webpack/{move_to_pf → components}/TooltipButton/TooltipButton.test.js +0 -0
- data/webpack/{move_to_pf → components}/TooltipButton/__snapshots__/TooltipButton.test.js.snap +0 -0
- data/webpack/{move_to_pf → components}/TooltipButton/index.js +0 -0
- data/webpack/components/TypeAhead/TypeAhead.js +109 -0
- data/webpack/{move_to_pf → components}/TypeAhead/TypeAhead.scss +0 -0
- data/webpack/components/TypeAhead/helpers/commonPropTypes.js +35 -0
- data/webpack/components/TypeAhead/helpers/helpers.js +32 -0
- data/webpack/components/TypeAhead/index.js +3 -0
- data/webpack/{move_to_pf/TypeAhead → components/TypeAhead/pf3Search}/TypeAheadInput.js +3 -6
- data/webpack/{move_to_pf/TypeAhead → components/TypeAhead/pf3Search}/TypeAheadItems.js +3 -7
- data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +52 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +44 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.scss +11 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadItems.js +57 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +66 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.scss +5 -0
- data/webpack/components/extensions/about/__tests__/SystemStatuses.test.js +1 -1
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/CollapseSubscriptionGroupButton.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/CollapseSubscriptionGroupButton.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/Table.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/Table.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableBody.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableBody.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableBodyMessage.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableBodyMessage.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableFixtures.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableSelectionCell.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableSelectionCell.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableSelectionHeaderCell.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/TableSelectionHeaderCell.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/Table.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/TableBody.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/TableBodyMessage.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/TableSelectionCell.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/components/index.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/EntitlementsInlineEditFormatter.js +1 -1
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/__tests__/EntitlementsInlineEditFormatter.test.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/cellFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/collapseableAndSelectionCellFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/ellipsisCellFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/headerFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/index.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/selectionCellFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/formatters/selectionHeaderCellFormatter.js +0 -0
- data/webpack/{move_to_foreman/components/common/table → components/pf3Table}/index.js +0 -0
- data/webpack/{move_to_pf → components}/react-bootstrap-select/index.js +0 -0
- data/webpack/containers/Application/config.js +5 -0
- data/webpack/containers/Application/overrides.scss +5 -0
- data/webpack/global_test_setup.js +3 -1
- data/webpack/redux/OrganizationProducts/OrganizationProductsActions.js +1 -1
- data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsActions.test.js +2 -2
- data/webpack/redux/actions/RedHatRepositories/enabled.js +1 -1
- data/webpack/redux/actions/RedHatRepositories/helpers.js +1 -1
- data/webpack/redux/actions/RedHatRepositories/repositorySetRepositories.js +1 -1
- data/webpack/redux/reducers/index.js +2 -0
- data/webpack/scenes/AnsibleCollections/AnsibleCollectionsActions.js +1 -1
- data/webpack/scenes/AnsibleCollections/AnsibleCollectionsTableSchema.js +1 -1
- data/webpack/scenes/AnsibleCollections/Details/AnsibleCollectionDetailsActions.js +1 -1
- data/webpack/scenes/AnsibleCollections/Details/__tests__/AnsibleCollectionDetailsActions.test.js +2 -2
- data/webpack/scenes/AnsibleCollections/__tests__/AnsibleCollectionsTable.test.js +1 -1
- data/webpack/scenes/ContentViews/ContentViewSelectors.js +1 -2
- data/webpack/scenes/ContentViews/ContentViewsActions.js +4 -4
- data/webpack/scenes/ContentViews/ContentViewsConstants.js +4 -1
- data/webpack/scenes/ContentViews/ContentViewsPage.js +12 -6
- data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +44 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetailReducer.js +23 -0
- data/webpack/scenes/ContentViews/{details → Details}/ContentViewDetailSelectors.js +3 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +70 -0
- data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +116 -0
- data/webpack/scenes/ContentViews/{details → Details}/DetailsContainer.js +8 -4
- data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +101 -0
- data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetails.fixtures.json +106 -0
- data/webpack/scenes/ContentViews/Details/contentViewInfo.scss +8 -0
- data/webpack/scenes/ContentViews/Details/index.js +7 -0
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +51 -36
- data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +47 -44
- data/webpack/scenes/ContentViews/__tests__/basicContentViews.fixtures.js +31 -0
- data/webpack/scenes/ContentViews/__tests__/contentViewList.fixtures.json +2 -1
- data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +173 -23
- data/webpack/scenes/ContentViews/components/ContentViewIcon.js +26 -0
- data/webpack/scenes/ContentViews/components/{contentViewName.scss → contentViewIcon.scss} +0 -0
- data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetailsActions.js +1 -1
- data/webpack/scenes/ModuleStreams/Details/Profiles/TableSchema.js +1 -1
- data/webpack/scenes/ModuleStreams/Details/__tests__/ModuleStreamDetailsActions.test.js +2 -2
- data/webpack/scenes/ModuleStreams/ModuleStreamsActions.js +1 -1
- data/webpack/scenes/ModuleStreams/ModuleStreamsTableSchema.js +1 -1
- data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamsTable.test.js +1 -1
- data/webpack/scenes/Organizations/OrganizationSelectors.js +14 -0
- data/webpack/scenes/Products/ProductActions.js +1 -1
- data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +1 -1
- data/webpack/scenes/Settings/SettingsConstants.js +3 -0
- data/webpack/scenes/Settings/SettingsReducer.js +33 -0
- data/webpack/scenes/Settings/SettingsSelectors.js +4 -0
- data/webpack/scenes/Settings/index.js +2 -1
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +1 -1
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +1 -1
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +59 -73
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.scss +15 -0
- data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +43 -1
- data/webpack/scenes/Subscriptions/Manifest/ManifestConstants.js +8 -0
- data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryTableSchema.js +1 -1
- data/webpack/scenes/Subscriptions/Manifest/SimpleContentAccess.js +78 -0
- data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +2 -0
- data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestActions.test.js +56 -1
- data/webpack/scenes/Subscriptions/Manifest/__tests__/SimpleContentAccess.test.js +114 -0
- data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +6 -6
- data/webpack/scenes/Subscriptions/Manifest/__tests__/manifest.fixtures.js +36 -0
- data/webpack/scenes/Subscriptions/Manifest/index.js +3 -1
- data/webpack/scenes/Subscriptions/SubscriptionActions.js +1 -1
- data/webpack/scenes/Subscriptions/SubscriptionConstants.js +4 -0
- data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +0 -3
- data/webpack/scenes/Subscriptions/SubscriptionReducer.js +38 -11
- data/webpack/scenes/Subscriptions/SubscriptionsPage.js +30 -18
- data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +0 -3
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsActions.js +1 -1
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +2 -2
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsTableSchema.js +1 -1
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionHelpers.test.js +0 -11
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +2 -2
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +4 -4
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +26 -1
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionTypeFormatter.js +2 -2
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +27 -21
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +6 -2
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionTypeFormatter.test.js.snap +3 -3
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +1 -1
- data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +28 -3
- data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/__snapshots__/SubscriptionsToolbar.test.js.snap +5 -10
- data/webpack/scenes/Subscriptions/index.js +6 -2
- data/webpack/test-utils/nockWrapper.js +39 -5
- data/webpack/test-utils/react-testing-lib-wrapper.js +35 -9
- data/webpack/{move_to_foreman/common → utils}/helpers.js +12 -8
- data/webpack/utils/useEventListener.js +37 -0
- metadata +143 -83
- data/app/lib/actions/katello/repository/verify_checksum.rb +0 -28
- data/app/lib/actions/pulp3/orchestration/repository/trigger_update_repo_cert_guard.rb +0 -22
- data/app/lib/actions/pulp3/repository/presenters/repair_presenter.rb +0 -85
- data/app/lib/actions/pulp3/repository/repair.rb +0 -29
- data/app/services/katello/host_trace_manager.rb +0 -38
- data/vendor/assets/stylesheets/katello/jquery.loadmask.css.scss +0 -40
- data/vendor/assets/stylesheets/katello/ui.spinner.css.scss +0 -3
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +0 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalSelectors.js +0 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +0 -4
- data/webpack/__mocks__/foremanReact/components/Settings/SettingsActions.js +0 -4
- data/webpack/__mocks__/foremanReact/components/Settings/SettingsConstants.js +0 -2
- data/webpack/move_to_pf/TypeAhead/TypeAhead.js +0 -138
- data/webpack/move_to_pf/TypeAhead/helpers.js +0 -5
- data/webpack/scenes/ContentViews/components/ContentViewName.js +0 -33
- data/webpack/scenes/ContentViews/components/EmptyStateMessage.js +0 -43
- data/webpack/scenes/ContentViews/details/ContentViewDetailActions.js +0 -12
- data/webpack/scenes/ContentViews/expansions/RepositoriesExpansion.js +0 -12
@@ -0,0 +1,120 @@
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
2
|
+
import { TextInput, TextArea, Text, TextVariants, Button, Split, SplitItem } from '@patternfly/react-core';
|
3
|
+
import { TimesIcon, CheckIcon, PencilAltIcon } from '@patternfly/react-icons';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
5
|
+
import PropTypes from 'prop-types';
|
6
|
+
import Loading from '../Loading';
|
7
|
+
import './editableTextInput.scss';
|
8
|
+
|
9
|
+
const EditableTextInput = ({
|
10
|
+
onEdit, value, textArea, attribute,
|
11
|
+
}) => {
|
12
|
+
// Tracks input box state
|
13
|
+
const [inputValue, setInputValue] = useState(value);
|
14
|
+
const [editing, setEditing] = useState(false);
|
15
|
+
const [submitting, setSubmitting] = useState(false);
|
16
|
+
|
17
|
+
// Setting didCancel to avoid actions from happening after component has been unmounted
|
18
|
+
// see https://overreacted.io/a-complete-guide-to-useeffect/#speaking-of-race-conditions
|
19
|
+
useEffect(() => {
|
20
|
+
let didCancel = false;
|
21
|
+
|
22
|
+
const onSubmit = async () => {
|
23
|
+
if (submitting) {
|
24
|
+
await onEdit(inputValue, attribute);
|
25
|
+
if (!didCancel) {
|
26
|
+
setSubmitting(false);
|
27
|
+
setEditing(false);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
};
|
31
|
+
onSubmit();
|
32
|
+
|
33
|
+
return () => {
|
34
|
+
didCancel = true;
|
35
|
+
};
|
36
|
+
}, [submitting]);
|
37
|
+
|
38
|
+
// Listen for enter and trigger submit workflow on enter
|
39
|
+
useEffect(() => {
|
40
|
+
const listener = (event) => {
|
41
|
+
if (event.code === 'Enter' || event.code === 'NumpadEnter') {
|
42
|
+
if (editing) setSubmitting(true);
|
43
|
+
}
|
44
|
+
};
|
45
|
+
document.addEventListener('keydown', listener);
|
46
|
+
return () => {
|
47
|
+
document.removeEventListener('keydown', listener);
|
48
|
+
};
|
49
|
+
}, [editing]);
|
50
|
+
|
51
|
+
const onClear = () => {
|
52
|
+
setInputValue(value);
|
53
|
+
setEditing(false);
|
54
|
+
};
|
55
|
+
|
56
|
+
const inputProps = {
|
57
|
+
value: inputValue || '',
|
58
|
+
onChange: v => setInputValue(v),
|
59
|
+
};
|
60
|
+
|
61
|
+
if (submitting) return <Loading size="sm" />;
|
62
|
+
if (editing) {
|
63
|
+
return (
|
64
|
+
<Split>
|
65
|
+
<SplitItem>
|
66
|
+
{textArea ?
|
67
|
+
(<TextArea {...inputProps} aria-label={`${attribute} text area`} />) :
|
68
|
+
(<TextInput {...inputProps} type="text" aria-label={`${attribute} text input`} />)}
|
69
|
+
</SplitItem>
|
70
|
+
<SplitItem>
|
71
|
+
<Button
|
72
|
+
aria-label={`submit ${attribute}`}
|
73
|
+
variant="plain"
|
74
|
+
onClick={() => setSubmitting(true)}
|
75
|
+
>
|
76
|
+
<CheckIcon />
|
77
|
+
</Button>
|
78
|
+
</SplitItem>
|
79
|
+
<SplitItem>
|
80
|
+
<Button aria-label={`clear ${attribute}`} variant="plain" onClick={onClear}>
|
81
|
+
<TimesIcon />
|
82
|
+
</Button>
|
83
|
+
</SplitItem>
|
84
|
+
</Split>
|
85
|
+
);
|
86
|
+
}
|
87
|
+
return (
|
88
|
+
<Split>
|
89
|
+
<SplitItem>
|
90
|
+
<Text aria-label={`${attribute} text value`} component={TextVariants.p}>
|
91
|
+
{value || (<i>{__('None provided')}</i>)}
|
92
|
+
</Text>
|
93
|
+
</SplitItem>
|
94
|
+
<SplitItem>
|
95
|
+
<Button
|
96
|
+
className="foreman-edit-icon"
|
97
|
+
aria-label={`edit ${attribute}`}
|
98
|
+
variant="plain"
|
99
|
+
onClick={() => setEditing(true)}
|
100
|
+
>
|
101
|
+
<PencilAltIcon />
|
102
|
+
</Button>
|
103
|
+
</SplitItem>
|
104
|
+
</Split>
|
105
|
+
);
|
106
|
+
};
|
107
|
+
|
108
|
+
EditableTextInput.propTypes = {
|
109
|
+
onEdit: PropTypes.func.isRequired,
|
110
|
+
value: PropTypes.string,
|
111
|
+
attribute: PropTypes.string.isRequired,
|
112
|
+
textArea: PropTypes.bool, // Is a text area instead of input when editing
|
113
|
+
};
|
114
|
+
|
115
|
+
EditableTextInput.defaultProps = {
|
116
|
+
textArea: false,
|
117
|
+
value: '', // API can return null, so default to empty string
|
118
|
+
};
|
119
|
+
|
120
|
+
export default EditableTextInput;
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
|
3
|
+
import EditableTextInput from '../EditableTextInput';
|
4
|
+
|
5
|
+
const actualValue = 'burger';
|
6
|
+
const attribute = 'favorite_food';
|
7
|
+
const defaultProps = {
|
8
|
+
onEdit: jest.fn(),
|
9
|
+
value: actualValue,
|
10
|
+
attribute,
|
11
|
+
};
|
12
|
+
|
13
|
+
test('Passed function is called after editing and clicking submit', async () => {
|
14
|
+
const mockEdit = jest.fn();
|
15
|
+
const { getByLabelText } = render(<EditableTextInput {...defaultProps} onEdit={mockEdit} />);
|
16
|
+
|
17
|
+
getByLabelText(`edit ${attribute}`).click();
|
18
|
+
fireEvent.change(getByLabelText(`${attribute} text input`), { target: { value: actualValue } });
|
19
|
+
getByLabelText(`submit ${attribute}`).click();
|
20
|
+
|
21
|
+
await patientlyWaitFor(() => expect(mockEdit.mock.calls).toHaveLength(1));
|
22
|
+
expect(mockEdit.mock.calls[0][0]).toBe(actualValue); // first arg
|
23
|
+
});
|
24
|
+
|
25
|
+
test('Passed function is called after editing and hitting enter', async () => {
|
26
|
+
const mockEdit = jest.fn();
|
27
|
+
const { getByLabelText } = render(<EditableTextInput {...defaultProps} onEdit={mockEdit} />);
|
28
|
+
|
29
|
+
getByLabelText(`edit ${attribute}`).click();
|
30
|
+
const textInputLabel = `${attribute} text input`;
|
31
|
+
fireEvent.change(getByLabelText(textInputLabel), { target: { value: actualValue } });
|
32
|
+
fireEvent.keyDown(getByLabelText(textInputLabel), { key: 'Enter', code: 'Enter' });
|
33
|
+
|
34
|
+
await patientlyWaitFor(() => expect(mockEdit.mock.calls).toHaveLength(1));
|
35
|
+
expect(mockEdit.mock.calls[0][0]).toBe(actualValue); // first arg
|
36
|
+
});
|
37
|
+
|
38
|
+
test('input is set back to original value after clearing', () => {
|
39
|
+
const value = 'Sandwich';
|
40
|
+
const { getByLabelText } = render(<EditableTextInput {...defaultProps} />);
|
41
|
+
|
42
|
+
// Show original value on load
|
43
|
+
expect(getByLabelText(`${attribute} text value`)).toHaveTextContent(actualValue);
|
44
|
+
getByLabelText(`edit ${attribute}`).click();
|
45
|
+
// Update text input
|
46
|
+
fireEvent.change(getByLabelText(`${attribute} text input`), { target: { value } });
|
47
|
+
expect(getByLabelText(`${attribute} text input`)).toHaveValue(value);
|
48
|
+
// Clear text
|
49
|
+
getByLabelText(`clear ${attribute}`).click();
|
50
|
+
// Original value is still showing even though it's been edited
|
51
|
+
expect(getByLabelText(`${attribute} text value`)).toHaveTextContent(actualValue);
|
52
|
+
});
|
@@ -8,23 +8,26 @@ import {
|
|
8
8
|
Spinner,
|
9
9
|
} from '@patternfly/react-core';
|
10
10
|
|
11
|
-
const Loading = ({ size }) => (
|
11
|
+
const Loading = ({ size, showText }) => (
|
12
12
|
<Bullseye>
|
13
13
|
<EmptyState>
|
14
|
-
<EmptyStateIcon variant="container" component={Spinner} />
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
<EmptyStateIcon size={size} variant="container" component={Spinner} />
|
15
|
+
{showText && (
|
16
|
+
<Title size={size} headingLevel="h4">
|
17
|
+
Loading
|
18
|
+
</Title>)}
|
18
19
|
</EmptyState>
|
19
20
|
</Bullseye>
|
20
21
|
);
|
21
22
|
|
22
23
|
Loading.propTypes = {
|
23
24
|
size: PropTypes.string,
|
25
|
+
showText: PropTypes.bool,
|
24
26
|
};
|
25
27
|
|
26
28
|
Loading.defaultProps = {
|
27
29
|
size: 'lg',
|
30
|
+
showText: true,
|
28
31
|
};
|
29
32
|
|
30
33
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import { translate as __ } from 'foremanReact/common/I18n';
|
4
4
|
import { FormGroup, ControlLabel } from 'react-bootstrap';
|
5
|
-
import BootstrapSelect from '../../
|
5
|
+
import BootstrapSelect from '../../components/react-bootstrap-select';
|
6
6
|
|
7
7
|
function MultiSelect(props) {
|
8
8
|
const {
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,124 @@
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
2
|
+
import React, { Component } from 'react';
|
3
|
+
import { ControlLabel } from 'react-bootstrap';
|
4
|
+
import PropTypes from 'prop-types';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
import TypeAhead from '../TypeAhead';
|
7
|
+
import api from '../../services/api';
|
8
|
+
import { stringIncludes } from './helpers';
|
9
|
+
import {
|
10
|
+
AUTOSEARCH_DELAY,
|
11
|
+
AUTOSEARCH_WHILE_TYPING,
|
12
|
+
} from '../../scenes/Settings/SettingsConstants';
|
13
|
+
|
14
|
+
class Search extends Component {
|
15
|
+
constructor(props) {
|
16
|
+
super(props);
|
17
|
+
this.state = { items: [], typingTimeout: 0 };
|
18
|
+
}
|
19
|
+
|
20
|
+
componentDidMount() {
|
21
|
+
this.onInputUpdate();
|
22
|
+
this.props.loadSetting(AUTOSEARCH_DELAY);
|
23
|
+
this.props.loadSetting(AUTOSEARCH_WHILE_TYPING);
|
24
|
+
}
|
25
|
+
|
26
|
+
onInputUpdate = async (searchTerm = '') => {
|
27
|
+
const { getAutoCompleteParams, settings: { autoSearchEnabled }, patternfly4 } = this.props;
|
28
|
+
const items = this.state.items.filter(({ text }) => stringIncludes(text, searchTerm));
|
29
|
+
|
30
|
+
if (items.length !== this.state.items.length) {
|
31
|
+
this.setState({ items });
|
32
|
+
}
|
33
|
+
|
34
|
+
const params = getAutoCompleteParams(searchTerm);
|
35
|
+
const autoCompleteParams = [
|
36
|
+
params.endpoint,
|
37
|
+
params.headers || {},
|
38
|
+
params.params || {},
|
39
|
+
];
|
40
|
+
|
41
|
+
if (autoCompleteParams[0] !== '') {
|
42
|
+
const { data } = await api.get(...autoCompleteParams);
|
43
|
+
this.setState({
|
44
|
+
items: data.filter(({ error }) => !error).map(({ label }) => ({
|
45
|
+
text: label.trim(),
|
46
|
+
})),
|
47
|
+
});
|
48
|
+
}
|
49
|
+
|
50
|
+
if (autoSearchEnabled && patternfly4 && searchTerm.length > 0) {
|
51
|
+
this.autoSearch(searchTerm);
|
52
|
+
}
|
53
|
+
};
|
54
|
+
|
55
|
+
onSearch = (search) => {
|
56
|
+
if (this.props.updateSearchQuery) this.props.updateSearchQuery(search);
|
57
|
+
this.props.onSearch(search);
|
58
|
+
};
|
59
|
+
|
60
|
+
// Continually clear and set the timeout as the user types. When the typing pauses, perform the
|
61
|
+
// search. This allows us to not overload the server by requesting on each keystroke.
|
62
|
+
autoSearch(searchTerm) {
|
63
|
+
const { settings: { autoSearchDelay } } = this.props;
|
64
|
+
if (this.state.typingTimeout) clearTimeout(this.state.typingTimeout);
|
65
|
+
|
66
|
+
this.setState({
|
67
|
+
typingTimeout: setTimeout(() => this.props.onSearch(searchTerm), autoSearchDelay),
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
render() {
|
72
|
+
const { initialInputValue, patternfly4, settings: { autoSearchEnabled } } = this.props;
|
73
|
+
return (
|
74
|
+
<div>
|
75
|
+
<ControlLabel srOnly>{__('Search')}</ControlLabel>
|
76
|
+
<TypeAhead
|
77
|
+
items={this.state.items}
|
78
|
+
onInputUpdate={this.onInputUpdate}
|
79
|
+
onSearch={this.onSearch}
|
80
|
+
initialInputValue={initialInputValue}
|
81
|
+
patternfly4={patternfly4}
|
82
|
+
autoSearchEnabled={autoSearchEnabled}
|
83
|
+
/>
|
84
|
+
</div>
|
85
|
+
);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
Search.propTypes = {
|
90
|
+
/** Callback function when the "Search" button is pressed:
|
91
|
+
onSearch(searchQuery)
|
92
|
+
*/
|
93
|
+
onSearch: PropTypes.func.isRequired,
|
94
|
+
/** Function returning params for the scoped-search complete api call:
|
95
|
+
getAutoCompleteParams(searchQuery)
|
96
|
+
|
97
|
+
Should return a shape { headers, params, endpoint }, e.g.:
|
98
|
+
{
|
99
|
+
headers: {},
|
100
|
+
params: { organization_id, search },
|
101
|
+
endpoint: '/subscriptions/auto_complete_search'
|
102
|
+
}
|
103
|
+
*/
|
104
|
+
getAutoCompleteParams: PropTypes.func.isRequired,
|
105
|
+
loadSetting: PropTypes.func.isRequired,
|
106
|
+
updateSearchQuery: PropTypes.func,
|
107
|
+
initialInputValue: PropTypes.string,
|
108
|
+
patternfly4: PropTypes.bool,
|
109
|
+
settings: PropTypes.shape({
|
110
|
+
autoSearchEnabled: PropTypes.bool,
|
111
|
+
autoSearchDelay: PropTypes.number,
|
112
|
+
}),
|
113
|
+
};
|
114
|
+
|
115
|
+
Search.defaultProps = {
|
116
|
+
updateSearchQuery: undefined,
|
117
|
+
initialInputValue: '',
|
118
|
+
patternfly4: false,
|
119
|
+
settings: {
|
120
|
+
autoSearchEnabled: true,
|
121
|
+
},
|
122
|
+
};
|
123
|
+
|
124
|
+
export default Search;
|
@@ -3,12 +3,13 @@ import { shallow } from 'enzyme';
|
|
3
3
|
import toJson from 'enzyme-to-json';
|
4
4
|
import { mock as mockApi } from '../../mockRequest';
|
5
5
|
|
6
|
-
import Search from '../Search';
|
6
|
+
import Search from '../Search/Search';
|
7
7
|
|
8
8
|
describe('Search component', () => {
|
9
9
|
const getBaseProps = () => ({
|
10
10
|
onSearch: () => {},
|
11
11
|
getAutoCompleteParams: () => ({ endpoint: '/fake' }),
|
12
|
+
loadSetting: jest.fn(),
|
12
13
|
});
|
13
14
|
|
14
15
|
describe('rendering', () => {
|
@@ -10,10 +10,12 @@ exports[`Search component rendering renders correctly 1`] = `
|
|
10
10
|
</ControlLabel>
|
11
11
|
<TypeAhead
|
12
12
|
actionText="Search"
|
13
|
+
autoSearchEnabled={true}
|
13
14
|
initialInputValue=""
|
14
15
|
items={Array []}
|
15
16
|
onInputUpdate={[Function]}
|
16
17
|
onSearch={[Function]}
|
18
|
+
patternfly4={false}
|
17
19
|
/>
|
18
20
|
</div>
|
19
21
|
`;
|
@@ -0,0 +1,124 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
|
3
|
+
import nock, {
|
4
|
+
nockInstance, assertNockRequest, mockAutocomplete, mockSetting,
|
5
|
+
} from '../../../test-utils/nockWrapper';
|
6
|
+
import { AUTOSEARCH_WHILE_TYPING, AUTOSEARCH_DELAY } from '../../../scenes/Settings/SettingsConstants.js';
|
7
|
+
import Search from '../../Search';
|
8
|
+
|
9
|
+
const endpoint = '/fake_endpoint';
|
10
|
+
const searchButtonLabel = 'search button';
|
11
|
+
const props = {
|
12
|
+
onSearch: jest.fn(),
|
13
|
+
getAutoCompleteParams: search => ({
|
14
|
+
params: { organization_id: 1, search },
|
15
|
+
endpoint,
|
16
|
+
}),
|
17
|
+
patternfly4: true,
|
18
|
+
};
|
19
|
+
|
20
|
+
let searchDelayScope;
|
21
|
+
beforeEach(() => {
|
22
|
+
searchDelayScope = mockSetting(nockInstance, AUTOSEARCH_DELAY, 500);
|
23
|
+
});
|
24
|
+
|
25
|
+
afterEach(() => {
|
26
|
+
assertNockRequest(searchDelayScope);
|
27
|
+
nock.cleanAll();
|
28
|
+
});
|
29
|
+
|
30
|
+
test('Autocomplete shows on input', async (done) => {
|
31
|
+
const suggestion = 'suggestedQuery';
|
32
|
+
const response = [
|
33
|
+
{
|
34
|
+
completed: '', part: ` ${suggestion} `, label: ` ${suggestion} `, category: '',
|
35
|
+
},
|
36
|
+
];
|
37
|
+
const query = { organization_id: 1, search: 'foo' };
|
38
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
|
39
|
+
const initialScope = mockAutocomplete(nockInstance, endpoint, { ...query, search: '' }, []);
|
40
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint, query, response);
|
41
|
+
|
42
|
+
const { getByLabelText, getByText, queryByText } = renderWithRedux(<Search {...props} />);
|
43
|
+
|
44
|
+
expect(queryByText(`${suggestion}`)).not.toBeInTheDocument();
|
45
|
+
|
46
|
+
fireEvent.change(getByLabelText(/text input for search/i), { target: { value: 'foo' } });
|
47
|
+
|
48
|
+
await patientlyWaitFor(() => expect(getByText(`${suggestion}`)).toBeInTheDocument());
|
49
|
+
|
50
|
+
assertNockRequest(initialScope);
|
51
|
+
assertNockRequest(autoSearchScope);
|
52
|
+
assertNockRequest(autocompleteScope, done);
|
53
|
+
});
|
54
|
+
|
55
|
+
test('autosearch turned on does not show patternfly 4 search button', async (done) => {
|
56
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
|
57
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint);
|
58
|
+
|
59
|
+
const { queryByLabelText } = renderWithRedux(<Search {...props} />);
|
60
|
+
|
61
|
+
await patientlyWaitFor(() => expect(queryByLabelText(searchButtonLabel)).not.toBeInTheDocument());
|
62
|
+
|
63
|
+
assertNockRequest(autocompleteScope);
|
64
|
+
assertNockRequest(autoSearchScope, done);
|
65
|
+
});
|
66
|
+
|
67
|
+
test('autosearch turned off does show patternfly 4 search button', async (done) => {
|
68
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, false);
|
69
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint);
|
70
|
+
|
71
|
+
const { getByLabelText } = renderWithRedux(<Search {...props} />);
|
72
|
+
|
73
|
+
// Using patientlyWaitFor as the autoSearch setting defaults to true,
|
74
|
+
// it won't be changed until http call
|
75
|
+
await patientlyWaitFor(() => expect(getByLabelText(searchButtonLabel)).toBeInTheDocument());
|
76
|
+
|
77
|
+
assertNockRequest(autoSearchScope);
|
78
|
+
assertNockRequest(autocompleteScope, done);
|
79
|
+
});
|
80
|
+
|
81
|
+
test('autosearch turned on does not affect patternfly 3 buttons', async (done) => {
|
82
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
|
83
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint);
|
84
|
+
|
85
|
+
const { getByLabelText } = renderWithRedux(<Search {...{ ...props, patternfly4: false }} />);
|
86
|
+
|
87
|
+
await patientlyWaitFor(() => expect(getByLabelText('patternfly 3 search button')).toBeInTheDocument());
|
88
|
+
|
89
|
+
assertNockRequest(autoSearchScope);
|
90
|
+
assertNockRequest(autocompleteScope, done);
|
91
|
+
});
|
92
|
+
|
93
|
+
test('search function is called when search is typed into with autosearch', async (done) => {
|
94
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, true);
|
95
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint, true, [], 2);
|
96
|
+
const mockSearch = jest.fn();
|
97
|
+
|
98
|
+
const { getByLabelText } = renderWithRedux(<Search {...{ ...props, onSearch: mockSearch }} />);
|
99
|
+
fireEvent.change(getByLabelText(/text input for search/i), { target: { value: 'foo' } });
|
100
|
+
await patientlyWaitFor(() => expect(mockSearch.mock.calls).toHaveLength(1));
|
101
|
+
|
102
|
+
assertNockRequest(autoSearchScope);
|
103
|
+
assertNockRequest(autocompleteScope, done);
|
104
|
+
});
|
105
|
+
|
106
|
+
test('search function is called by clicking search button without autosearch', async (done) => {
|
107
|
+
const autoSearchScope = mockSetting(nockInstance, AUTOSEARCH_WHILE_TYPING, false);
|
108
|
+
const autocompleteScope = mockAutocomplete(nockInstance, endpoint, true, [], 2);
|
109
|
+
const mockSearch = jest.fn();
|
110
|
+
|
111
|
+
const { getByLabelText } = renderWithRedux(<Search {...{ ...props, onSearch: mockSearch }} />);
|
112
|
+
|
113
|
+
fireEvent.change(getByLabelText(/text input for search/i), { target: { value: 'foo' } });
|
114
|
+
let searchButton;
|
115
|
+
await patientlyWaitFor(() => {
|
116
|
+
searchButton = getByLabelText(searchButtonLabel);
|
117
|
+
expect(searchButton).toBeInTheDocument();
|
118
|
+
});
|
119
|
+
searchButton.click();
|
120
|
+
expect(mockSearch.mock.calls).toHaveLength(1);
|
121
|
+
|
122
|
+
assertNockRequest(autoSearchScope);
|
123
|
+
assertNockRequest(autocompleteScope, done);
|
124
|
+
});
|
@@ -1,91 +1,15 @@
|
|
1
|
-
|
2
|
-
import
|
3
|
-
import
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import TypeAhead from '../../move_to_pf/TypeAhead/TypeAhead';
|
7
|
-
import api from '../../services/api';
|
8
|
-
import { stringIncludes } from './helpers';
|
1
|
+
import { bindActionCreators } from 'redux';
|
2
|
+
import { connect } from 'react-redux';
|
3
|
+
import * as settingActions from 'foremanReact/components/Settings/SettingsActions';
|
4
|
+
import { selectSettings } from '../../scenes/Settings/SettingsSelectors';
|
5
|
+
import Search from './Search';
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
this.state = { items: [] };
|
14
|
-
this.onInputUpdate = this.onInputUpdate.bind(this);
|
15
|
-
this.onSearch = this.onSearch.bind(this);
|
16
|
-
}
|
7
|
+
const mapStateToProps = state => ({
|
8
|
+
settings: selectSettings(state),
|
9
|
+
});
|
17
10
|
|
18
|
-
|
19
|
-
this.onInputUpdate();
|
20
|
-
}
|
11
|
+
const actions = { ...settingActions };
|
21
12
|
|
22
|
-
|
23
|
-
const items = this.state.items.filter(({ text }) => stringIncludes(text, searchTerm));
|
13
|
+
const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
|
24
14
|
|
25
|
-
|
26
|
-
this.setState({ items });
|
27
|
-
}
|
28
|
-
|
29
|
-
const params = this.props.getAutoCompleteParams(searchTerm);
|
30
|
-
const autoCompleteParams = [
|
31
|
-
params.endpoint,
|
32
|
-
params.headers || {},
|
33
|
-
params.params || {},
|
34
|
-
];
|
35
|
-
|
36
|
-
if (autoCompleteParams[0] !== '') {
|
37
|
-
const { data } = await api.get(...autoCompleteParams);
|
38
|
-
this.setState({
|
39
|
-
items: data.filter(({ error }) => !error).map(({ label }) => ({
|
40
|
-
text: label.trim(),
|
41
|
-
})),
|
42
|
-
});
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
onSearch(search) {
|
47
|
-
if (this.props.updateSearchQuery) this.props.updateSearchQuery(search);
|
48
|
-
this.props.onSearch(search);
|
49
|
-
}
|
50
|
-
|
51
|
-
render() {
|
52
|
-
const { initialInputValue } = this.props;
|
53
|
-
return (
|
54
|
-
<div>
|
55
|
-
<ControlLabel srOnly>{__('Search')}</ControlLabel>
|
56
|
-
<TypeAhead
|
57
|
-
items={this.state.items}
|
58
|
-
onInputUpdate={this.onInputUpdate}
|
59
|
-
onSearch={this.onSearch}
|
60
|
-
initialInputValue={initialInputValue}
|
61
|
-
/>
|
62
|
-
</div>
|
63
|
-
);
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
Search.propTypes = {
|
68
|
-
/** Callback function when the "Search" button is pressed:
|
69
|
-
onSearch(searchQuery)
|
70
|
-
*/
|
71
|
-
onSearch: PropTypes.func.isRequired,
|
72
|
-
/** Function returning params for the scoped-search complete api call:
|
73
|
-
getAutoCompleteParams(searchQuery)
|
74
|
-
|
75
|
-
Should return a shape { headers, params, endpoint }, e.g.:
|
76
|
-
{
|
77
|
-
headers: {},
|
78
|
-
params: { organization_id, search },
|
79
|
-
endpoint: '/subscriptions/auto_complete_search'
|
80
|
-
}
|
81
|
-
*/
|
82
|
-
getAutoCompleteParams: PropTypes.func.isRequired,
|
83
|
-
updateSearchQuery: PropTypes.func,
|
84
|
-
initialInputValue: PropTypes.string,
|
85
|
-
};
|
86
|
-
|
87
|
-
Search.defaultProps = {
|
88
|
-
updateSearchQuery: undefined,
|
89
|
-
initialInputValue: '',
|
90
|
-
};
|
91
|
-
export default Search;
|
15
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Search);
|
File without changes
|
@@ -5,10 +5,10 @@ import { Form, Button } from 'patternfly-react';
|
|
5
5
|
import { withRouter } from 'react-router-dom';
|
6
6
|
import { bindActionCreators } from 'redux';
|
7
7
|
import { connect } from 'react-redux';
|
8
|
-
import Select from '../../
|
8
|
+
import Select from '../../components/Select/Select';
|
9
9
|
import * as SelectOrgActions from './SelectOrgAction';
|
10
10
|
import reducer from './SelectOrgReducer';
|
11
|
-
import { LoadingState } from '../../
|
11
|
+
import { LoadingState } from '../../components/LoadingState';
|
12
12
|
import './SelectOrg.scss';
|
13
13
|
|
14
14
|
class SetOrganization extends Component {
|