From b7dfe2ae4054aa40e15182fd3c6cb7dd39f131db Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Fri, 13 Sep 2019 13:26:31 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- app/assets/javascripts/boards/models/list.js | 2 +- app/assets/javascripts/clusters/clusters_bundle.js | 19 +++ .../clusters/services/clusters_service.js | 4 + .../javascripts/clusters/stores/clusters_store.js | 7 +- app/assets/javascripts/gl_dropdown.js | 134 +++-------------- app/assets/javascripts/gl_dropdown/render.js | 158 +++++++++++++++++++++ app/assets/javascripts/groups/transfer_dropdown.js | 2 +- .../jobs/components/environments_block.vue | 35 ++++- app/assets/javascripts/labels_select.js | 4 +- app/assets/javascripts/milestone_select.js | 2 +- app/assets/javascripts/namespace_select.js | 2 +- .../pages/profiles/two_factor_auths/index.js | 2 +- .../permissions/components/settings_panel.vue | 1 + app/assets/javascripts/pages/search/show/search.js | 4 +- app/assets/javascripts/search_autocomplete.js | 10 +- app/assets/javascripts/users_select.js | 7 +- .../components/mr_widget_pipeline.vue | 2 +- .../vue_shared/components/gl_countdown.vue | 1 + .../sidebar/collapsed_grouped_date_picker.vue | 4 +- app/controllers/admin/application_controller.rb | 2 + .../admin/application_settings_controller.rb | 2 + app/controllers/admin/dashboard_controller.rb | 2 + app/controllers/admin/groups_controller.rb | 2 + app/controllers/admin/health_check_controller.rb | 2 + app/controllers/admin/logs_controller.rb | 2 + app/controllers/admin/projects_controller.rb | 2 + app/controllers/admin/users_controller.rb | 2 + app/controllers/application_controller.rb | 2 + app/controllers/autocomplete_controller.rb | 2 + app/controllers/boards/lists_controller.rb | 2 + app/controllers/clusters/clusters_controller.rb | 2 + app/controllers/concerns/boards_actions.rb | 2 + app/controllers/concerns/boards_responses.rb | 2 + app/controllers/concerns/cycle_analytics_params.rb | 2 + app/controllers/concerns/internal_redirect.rb | 2 + app/controllers/concerns/issuable_actions.rb | 2 + app/controllers/concerns/issuable_collections.rb | 2 + app/controllers/concerns/lfs_request.rb | 2 + app/controllers/concerns/routable_actions.rb | 2 + app/controllers/concerns/service_params.rb | 2 + app/controllers/confirmations_controller.rb | 2 + app/controllers/dashboard/projects_controller.rb | 2 + app/controllers/groups/application_controller.rb | 2 + app/controllers/groups/clusters_controller.rb | 2 + app/controllers/groups/group_members_controller.rb | 2 + app/controllers/groups/milestones_controller.rb | 2 + app/controllers/groups_controller.rb | 4 +- app/controllers/ide_controller.rb | 2 + app/controllers/import/github_controller.rb | 2 + .../ldap/omniauth_callbacks_controller.rb | 2 + app/controllers/omniauth_callbacks_controller.rb | 2 + app/controllers/passwords_controller.rb | 2 + app/controllers/profiles/accounts_controller.rb | 2 + app/controllers/profiles/preferences_controller.rb | 2 + .../projects/autocomplete_sources_controller.rb | 2 + .../projects/environments_controller.rb | 2 + .../projects/git_http_client_controller.rb | 2 + app/controllers/projects/git_http_controller.rb | 2 + app/controllers/projects/group_links_controller.rb | 2 + app/controllers/projects/imports_controller.rb | 2 + app/controllers/projects/issues_controller.rb | 2 + app/controllers/projects/jobs_controller.rb | 2 + app/controllers/projects/lfs_api_controller.rb | 2 + .../merge_requests/application_controller.rb | 2 + .../projects/merge_requests/diffs_controller.rb | 2 + .../projects/merge_requests_controller.rb | 2 + app/controllers/projects/mirrors_controller.rb | 2 + app/controllers/projects/pipelines_controller.rb | 2 + .../projects/project_members_controller.rb | 2 + .../projects/prometheus/metrics_controller.rb | 2 + .../projects/protected_refs_controller.rb | 2 + .../projects/repositories_controller.rb | 2 + .../projects/settings/ci_cd_controller.rb | 2 + .../projects/settings/integrations_controller.rb | 2 + .../projects/settings/operations_controller.rb | 2 + .../projects/settings/repository_controller.rb | 2 + app/controllers/projects_controller.rb | 2 + app/controllers/registrations_controller.rb | 2 + app/controllers/root_controller.rb | 2 + app/controllers/sent_notifications_controller.rb | 2 + app/controllers/sessions_controller.rb | 2 + app/controllers/users_controller.rb | 2 + app/finders/autocomplete/users_finder.rb | 2 + app/finders/group_members_finder.rb | 2 + app/finders/group_projects_finder.rb | 2 + app/finders/issues_finder.rb | 2 + app/finders/license_template_finder.rb | 2 + app/finders/merge_requests_finder.rb | 2 + app/finders/notes_finder.rb | 2 + app/finders/projects_finder.rb | 2 + app/finders/template_finder.rb | 2 + app/finders/users_finder.rb | 2 + app/graphql/resolvers/echo_resolver.rb | 2 +- app/graphql/resolvers/issues_resolver.rb | 4 +- app/graphql/types/ci/detailed_status_type.rb | 16 +-- app/graphql/types/ci/pipeline_type.rb | 22 +-- app/graphql/types/commit_type.rb | 16 +-- app/graphql/types/group_type.rb | 8 +- app/graphql/types/issue_type.rb | 48 ++++--- app/graphql/types/label_type.rb | 8 +- app/graphql/types/merge_request_type.rb | 84 +++++------ app/graphql/types/metadata_type.rb | 4 +- app/graphql/types/milestone_type.rb | 14 +- app/graphql/types/mutation_type.rb | 2 + app/graphql/types/namespace_type.rb | 20 +-- app/graphql/types/notes/diff_position_type.rb | 4 +- app/graphql/types/notes/discussion_type.rb | 4 +- app/graphql/types/notes/note_type.rb | 8 +- app/graphql/types/notes/noteable_type.rb | 2 + .../types/permission_types/base_permission_type.rb | 2 +- app/graphql/types/permission_types/issue.rb | 2 + app/graphql/types/permission_types/project.rb | 2 + app/graphql/types/project_statistics_type.rb | 14 +- app/graphql/types/project_type.rb | 78 +++++----- app/graphql/types/query_type.rb | 2 +- app/graphql/types/repository_type.rb | 8 +- app/graphql/types/task_completion_status.rb | 4 +- app/graphql/types/tree/blob_type.rb | 4 +- app/graphql/types/tree/entry_type.rb | 10 +- app/graphql/types/tree/submodule_type.rb | 4 +- app/graphql/types/tree/tree_entry_type.rb | 2 +- app/graphql/types/tree/tree_type.rb | 8 +- app/graphql/types/user_type.rb | 8 +- app/helpers/appearances_helper.rb | 2 + app/helpers/application_helper.rb | 2 + app/helpers/application_settings_helper.rb | 6 + app/helpers/auth_helper.rb | 6 + app/helpers/award_emoji_helper.rb | 2 + app/helpers/boards_helper.rb | 2 + app/helpers/branches_helper.rb | 2 + app/helpers/button_helper.rb | 2 + app/helpers/clusters_helper.rb | 2 + app/helpers/dashboard_helper.rb | 2 + app/helpers/emails_helper.rb | 2 + app/helpers/environments_helper.rb | 2 + app/helpers/form_helper.rb | 2 + app/helpers/gitlab_routing_helper.rb | 2 + app/helpers/groups/group_members_helper.rb | 4 +- app/helpers/groups_helper.rb | 2 + app/helpers/issuables_helper.rb | 2 + app/helpers/issues_helper.rb | 20 +++ app/helpers/kerberos_spnego_helper.rb | 2 + app/helpers/labels_helper.rb | 2 + app/helpers/merge_requests_helper.rb | 2 + app/helpers/milestones_helper.rb | 2 + app/helpers/mirror_helper.rb | 2 + app/helpers/namespaces_helper.rb | 2 + app/helpers/nav_helper.rb | 2 + app/helpers/notes_helper.rb | 2 + app/helpers/onboarding_experiment_helper.rb | 4 +- app/helpers/preferences_helper.rb | 2 + app/helpers/projects_helper.rb | 2 + app/helpers/recaptcha_experiment_helper.rb | 2 + app/helpers/runners_helper.rb | 2 + app/helpers/search_helper.rb | 2 + app/helpers/selects_helper.rb | 2 + app/helpers/services_helper.rb | 6 + app/helpers/sorting_helper.rb | 2 + app/helpers/system_note_helper.rb | 6 + app/helpers/tab_helper.rb | 2 + app/helpers/todos_helper.rb | 2 + app/helpers/tree_helper.rb | 2 + app/helpers/user_callouts_helper.rb | 2 + app/helpers/users_helper.rb | 2 + app/helpers/version_check_helper.rb | 2 + app/mailers/emails/merge_requests.rb | 2 + app/mailers/emails/notes.rb | 2 + app/mailers/emails/projects.rb | 2 + app/mailers/notify.rb | 2 + app/mailers/previews/notify_preview.rb | 2 + app/models/application_setting.rb | 2 + app/models/audit_event.rb | 2 + app/models/blob.rb | 2 + app/models/board.rb | 2 + app/models/broadcast_message.rb | 2 + app/models/ci/bridge.rb | 2 + app/models/ci/build.rb | 2 + app/models/ci/build_runner_session.rb | 2 + app/models/ci/job_artifact.rb | 2 + app/models/ci/pipeline.rb | 2 + app/models/ci/pipeline_enums.rb | 2 + app/models/ci/runner.rb | 4 +- app/models/clusters/applications/prometheus.rb | 2 + app/models/clusters/cluster.rb | 2 + app/models/clusters/platforms/kubernetes.rb | 2 + app/models/commit_status.rb | 2 + app/models/commit_status_enums.rb | 2 + app/models/concerns/issuable.rb | 3 + app/models/concerns/mentionable.rb | 2 + .../concerns/mentionable/reference_regexes.rb | 2 + app/models/concerns/noteable.rb | 3 + app/models/concerns/participable.rb | 3 +- app/models/concerns/prometheus_adapter.rb | 2 + app/models/concerns/protected_ref.rb | 6 + app/models/concerns/protected_ref_access.rb | 11 +- app/models/concerns/sha_attribute.rb | 2 + app/models/container_repository.rb | 2 + app/models/diff_note.rb | 2 + app/models/discussion_note.rb | 3 + app/models/environment.rb | 2 + app/models/epic.rb | 2 + app/models/event.rb | 2 + app/models/global_milestone.rb | 1 + app/models/group.rb | 2 + app/models/group_milestone.rb | 1 + app/models/hooks/project_hook.rb | 2 + app/models/identity.rb | 2 + app/models/identity/uniqueness_scopes.rb | 2 + app/models/issue.rb | 7 + app/models/issue_assignee.rb | 2 + app/models/key.rb | 2 + app/models/label.rb | 2 + app/models/label_note.rb | 2 + app/models/legacy_diff_note.rb | 2 + app/models/lfs_object.rb | 2 + app/models/list.rb | 2 + app/models/member.rb | 2 + app/models/members/group_member.rb | 2 + app/models/members/project_member.rb | 2 + app/models/members_preloader.rb | 2 + app/models/merge_request.rb | 2 + app/models/milestone.rb | 2 + app/models/namespace.rb | 2 + app/models/note.rb | 2 + app/models/notification_setting.rb | 2 + app/models/pool_repository.rb | 2 + app/models/project.rb | 2 + app/models/project_authorization.rb | 1 + app/models/project_ci_cd_setting.rb | 2 + app/models/project_feature.rb | 2 + app/models/project_group_link.rb | 2 + app/models/project_import_data.rb | 2 + app/models/project_import_state.rb | 2 + .../project_services/chat_message/merge_message.rb | 2 + app/models/project_services/hipchat_service.rb | 2 + .../project_services/issue_tracker_service.rb | 2 + .../project_services/mock_deployment_service.rb | 2 + app/models/project_statistics.rb | 2 + app/models/project_team.rb | 2 + app/models/project_wiki.rb | 2 + app/models/prometheus_metric.rb | 2 + app/models/prometheus_metric_enums.rb | 2 + app/models/protected_branch.rb | 2 + app/models/push_event_payload.rb | 2 + app/models/remote_mirror.rb | 2 + app/models/repository.rb | 2 + app/models/resource_label_event.rb | 2 + app/models/service.rb | 2 + app/models/snippet.rb | 2 + app/models/system_note_metadata.rb | 2 + app/models/todo.rb | 2 + app/models/upload.rb | 2 + app/models/user.rb | 2 + app/models/user_callout_enums.rb | 2 + app/models/user_preference.rb | 2 + app/policies/base_policy.rb | 2 + app/policies/ci/build_policy.rb | 2 + app/policies/concerns/policy_actor.rb | 2 + app/policies/environment_policy.rb | 2 + app/policies/global_policy.rb | 2 + app/policies/group_member_policy.rb | 2 + app/policies/group_policy.rb | 2 + app/policies/identity_provider_policy.rb | 2 + app/policies/issue_policy.rb | 2 + app/policies/merge_request_policy.rb | 2 + app/policies/namespace_policy.rb | 2 + app/policies/project_policy.rb | 2 + app/policies/project_snippet_policy.rb | 2 + app/policies/protected_branch_policy.rb | 2 + app/presenters/ci/pipeline_presenter.rb | 2 + app/presenters/clusterable_presenter.rb | 2 + app/presenters/commit_status_presenter.rb | 3 +- app/presenters/group_clusterable_presenter.rb | 2 + app/presenters/group_member_presenter.rb | 2 + app/presenters/instance_clusterable_presenter.rb | 2 + app/presenters/label_presenter.rb | 2 + app/presenters/member_presenter.rb | 2 + app/presenters/merge_request_presenter.rb | 2 + app/presenters/project_clusterable_presenter.rb | 2 + app/presenters/project_member_presenter.rb | 2 + app/presenters/project_presenter.rb | 2 + app/serializers/blob_entity.rb | 2 + app/serializers/board_simple_entity.rb | 2 + app/serializers/build_details_entity.rb | 2 + app/serializers/cluster_basic_entity.rb | 10 ++ app/serializers/current_board_entity.rb | 2 + app/serializers/deployment_entity.rb | 2 + app/serializers/discussion_serializer.rb | 2 + app/serializers/environment_entity.rb | 2 + app/serializers/issuable_sidebar_basic_entity.rb | 2 + app/serializers/issue_board_entity.rb | 2 + app/serializers/issue_entity.rb | 9 +- app/serializers/issue_sidebar_basic_entity.rb | 2 + app/serializers/issue_sidebar_extras_entity.rb | 2 + .../merge_request_poll_widget_entity.rb | 2 + app/serializers/merge_request_widget_entity.rb | 2 + app/serializers/pipeline_details_entity.rb | 2 + app/serializers/pipeline_serializer.rb | 2 + app/serializers/project_mirror_entity.rb | 2 + app/serializers/user_preference_entity.rb | 2 + .../application_settings/update_service.rb | 2 + app/services/applications/create_service.rb | 2 + app/services/audit_event_service.rb | 2 + app/services/auto_merge_service.rb | 2 + app/services/base_count_service.rb | 2 + app/services/boards/base_service.rb | 2 + app/services/boards/create_service.rb | 2 + app/services/boards/issues/create_service.rb | 2 + app/services/boards/issues/list_service.rb | 2 + app/services/boards/issues/move_service.rb | 2 + app/services/boards/list_service.rb | 2 + app/services/boards/lists/create_service.rb | 2 + app/services/boards/lists/list_service.rb | 2 + app/services/boards/update_service.rb | 2 + app/services/ci/create_pipeline_service.rb | 2 + app/services/ci/expire_pipeline_cache_service.rb | 2 + app/services/ci/pipeline_trigger_service.rb | 2 + app/services/ci/process_build_service.rb | 2 + app/services/ci/register_job_service.rb | 2 + app/services/clusters/create_service.rb | 2 + app/services/commits/create_service.rb | 2 + app/services/deploy_keys/create_service.rb | 2 + app/services/emails/create_service.rb | 2 + app/services/emails/destroy_service.rb | 2 + app/services/event_create_service.rb | 2 + app/services/git/branch_hooks_service.rb | 2 + app/services/git/branch_push_service.rb | 2 + app/services/git/tag_hooks_service.rb | 2 + app/services/git/wiki_push_service.rb | 2 + app/services/groups/create_service.rb | 2 + app/services/groups/destroy_service.rb | 2 + app/services/groups/update_service.rb | 2 + app/services/import/github_service.rb | 2 + app/services/issuable/clone/base_service.rb | 2 + .../issuable/common_system_notes_service.rb | 2 + app/services/issuable_base_service.rb | 2 + app/services/issues/build_service.rb | 2 + app/services/issues/create_service.rb | 2 + app/services/issues/duplicate_service.rb | 1 + app/services/issues/move_service.rb | 2 + app/services/issues/update_service.rb | 2 + app/services/keys/create_service.rb | 2 + app/services/keys/destroy_service.rb | 2 + app/services/lfs/lock_file_service.rb | 2 + app/services/lfs/unlock_file_service.rb | 2 + .../members/approve_access_request_service.rb | 2 + app/services/members/create_service.rb | 2 + app/services/members/destroy_service.rb | 2 + app/services/members/update_service.rb | 2 + app/services/merge_request_metrics_service.rb | 2 + app/services/merge_requests/base_service.rb | 2 + app/services/merge_requests/build_service.rb | 2 + .../merge_requests/create_pipeline_service.rb | 2 + app/services/merge_requests/create_service.rb | 2 + app/services/merge_requests/merge_base_service.rb | 2 + app/services/merge_requests/post_merge_service.rb | 2 + app/services/merge_requests/refresh_service.rb | 2 + app/services/merge_requests/update_service.rb | 2 + app/services/milestones/promote_service.rb | 2 + app/services/milestones/update_service.rb | 2 + app/services/notes/quick_actions_service.rb | 2 + app/services/notification_recipient_service.rb | 3 + app/services/notification_service.rb | 2 + app/services/projects/after_rename_service.rb | 2 + app/services/projects/autocomplete_service.rb | 2 + app/services/projects/cleanup_service.rb | 2 + .../projects/create_from_template_service.rb | 2 + app/services/projects/create_service.rb | 2 + app/services/projects/destroy_service.rb | 2 + .../projects/disable_deploy_key_service.rb | 2 + app/services/projects/enable_deploy_key_service.rb | 2 + .../projects/gitlab_projects_import_service.rb | 2 + .../projects/group_links/create_service.rb | 2 + .../projects/group_links/destroy_service.rb | 2 + .../hashed_storage/migrate_attachments_service.rb | 2 + .../hashed_storage/migrate_repository_service.rb | 2 + app/services/projects/operations/update_service.rb | 2 + app/services/projects/transfer_service.rb | 2 + app/services/projects/update_service.rb | 2 + .../protected_branches/access_level_params.rb | 2 + app/services/protected_branches/api_service.rb | 2 + app/services/protected_branches/create_service.rb | 2 + .../legacy_api_update_service.rb | 2 + app/services/quick_actions/interpret_service.rb | 2 + .../resource_events/change_labels_service.rb | 2 + app/services/search/global_service.rb | 2 + app/services/search/group_service.rb | 2 + app/services/search/project_service.rb | 2 + app/services/search/snippet_service.rb | 2 + app/services/search_service.rb | 2 + app/services/system_hooks_service.rb | 2 + app/services/system_note_service.rb | 2 + app/services/todo_service.rb | 2 + app/services/update_deployment_service.rb | 2 + .../user_project_access_changed_service.rb | 2 + app/services/users/build_service.rb | 2 + app/services/users/destroy_service.rb | 2 + .../users/migrate_to_ghost_user_service.rb | 2 + app/services/users/update_service.rb | 2 + app/services/wiki_pages/base_service.rb | 2 + app/uploaders/object_storage.rb | 2 + app/views/clusters/clusters/show.html.haml | 1 + .../group_members/_new_group_member.html.haml | 2 +- app/views/groups/settings/_general.html.haml | 4 +- app/views/groups/settings/_lfs.html.haml | 2 +- .../settings/_project_creation_level.html.haml | 2 +- .../groups/settings/_two_factor_auth.html.haml | 2 +- app/views/projects/_export.html.haml | 4 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/edit.html.haml | 8 +- app/views/projects/issues/show.html.haml | 8 +- .../project_members/_new_project_group.html.haml | 4 +- app/views/projects/project_members/index.html.haml | 2 +- app/views/shared/_allow_request_access.html.haml | 2 +- app/views/shared/_visibility_radios.html.haml | 2 +- app/views/shared/members/_group.html.haml | 4 +- app/views/shared/members/_member.html.haml | 8 +- app/workers/build_finished_worker.rb | 2 + app/workers/new_note_worker.rb | 2 + app/workers/post_receive.rb | 2 + app/workers/project_cache_worker.rb | 3 +- app/workers/repository_check/batch_worker.rb | 2 + .../repository_check/single_repository_worker.rb | 2 + app/workers/repository_import_worker.rb | 2 + 424 files changed, 1293 insertions(+), 372 deletions(-) create mode 100644 app/assets/javascripts/gl_dropdown/render.js create mode 100644 app/serializers/cluster_basic_entity.rb (limited to 'app') diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index 080841ee82b..1edaf971afd 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -3,7 +3,7 @@ import { __ } from '~/locale'; import ListLabel from './label'; import ListAssignee from './assignee'; -import ListIssue from './issue'; +import ListIssue from 'ee_else_ce/boards/models/issue'; import { urlParamsToObject } from '~/lib/utils/common_utils'; import boardsStore from '../stores/boards_store'; import ListMilestone from './milestone'; diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 1f213d5aaf2..28850710f80 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -39,6 +39,7 @@ export default class Clusters { updateKnativePath, installPrometheusPath, managePrometheusPath, + clusterEnvironmentsPath, hasRbac, clusterType, clusterStatus, @@ -79,6 +80,7 @@ export default class Clusters { installJupyterEndpoint: installJupyterPath, installKnativeEndpoint: installKnativePath, updateKnativeEndpoint: updateKnativePath, + clusterEnvironmentsEndpoint: clusterEnvironmentsPath, }); this.installApplication = this.installApplication.bind(this); @@ -109,6 +111,10 @@ export default class Clusters { this.initApplications(clusterType); this.initEnvironments(); + if (clusterEnvironmentsPath) { + this.fetchEnvironments(); + } + this.updateContainer(null, this.store.state.status, this.store.state.statusReason); this.addListeners(); @@ -162,6 +168,7 @@ export default class Clusters { render(createElement) { return createElement(Environments, { props: { + isFetching: this.state.fetchingEnvironments, environments: this.state.environments, environmentsHelpPath: this.state.environmentsHelpPath, clustersHelpPath: this.state.clustersHelpPath, @@ -172,6 +179,18 @@ export default class Clusters { }); } + fetchEnvironments() { + this.store.toggleFetchEnvironments(true); + + this.service + .fetchClusterEnvironments() + .then(data => { + this.store.toggleFetchEnvironments(false); + this.store.updateEnvironments(data.data); + }) + .catch(() => Clusters.handleError()); + } + static initDismissableCallout() { const callout = document.querySelector('.js-cluster-security-warning'); PersistentUserCallout.factory(callout); diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index 01f3732de7e..9139e0beafb 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -33,6 +33,10 @@ export default class ClusterService { return axios.delete(this.appInstallEndpointMap[appId], params); } + fetchClusterEnvironments() { + return axios.get(this.options.clusterEnvironmentsEndpoint); + } + static updateCluster(endpoint, data) { return axios.put(endpoint, data); } diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 83533c88f69..a032f589ee4 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -84,6 +84,7 @@ export default class ClusterStore { }, }, environments: [], + fetchingEnvironments: false, }; } @@ -206,6 +207,10 @@ export default class ClusterStore { }); } + toggleFetchEnvironments(isFetching) { + this.state.fetchingEnvironments = isFetching; + } + updateEnvironments(environments = []) { this.state.environments = environments.map(environment => ({ name: environment.name, @@ -215,7 +220,7 @@ export default class ClusterStore { rolloutStatus: { instances: environment.rollout_status ? environment.rollout_status.instances : [], }, - updatedAt: environment.updatedAt, + updatedAt: environment.updated_at, })); } } diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index bdb50606a53..515402fc506 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -7,6 +7,7 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus'; import axios from './lib/utils/axios_utils'; import { visitUrl } from './lib/utils/url_utility'; import { isObject } from './lib/utils/type_utility'; +import renderItem from './gl_dropdown/render'; var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote, GitLabDropdownInput; @@ -521,8 +522,8 @@ GitLabDropdown = (function() { html.push( this.renderItem( { - header: name, - // Add header for each group + content: name, + type: 'header', }, name, ), @@ -542,16 +543,7 @@ GitLabDropdown = (function() { }; GitLabDropdown.prototype.renderData = function(data, group) { - if (group == null) { - group = false; - } - return data.map( - (function(_this) { - return function(obj, index) { - return _this.renderItem(obj, group, index); - }; - })(this), - ); + return data.map((obj, index) => this.renderItem(obj, group || false, index)); }; GitLabDropdown.prototype.shouldPropagate = function(e) { @@ -688,104 +680,25 @@ GitLabDropdown = (function() { }; GitLabDropdown.prototype.renderItem = function(data, group, index) { - var field, html, selected, text, url, value, rowHidden; - - if (!this.options.renderRow) { - value = this.options.id ? this.options.id(data) : data.id; - - if (value) { - value = value.toString().replace(/'/g, "\\'"); - } - } - - // Hide element - if (this.options.hideRow && this.options.hideRow(value)) { - rowHidden = true; - } - if (group == null) { - group = false; - } - if (index == null) { - // Render the row - index = false; - } - html = document.createElement('li'); - - if (rowHidden) { - html.style.display = 'none'; - } - - if (data === 'divider' || data === 'separator') { - html.className = data; - return html; - } - // Header - if (data.header != null) { - html.className = 'dropdown-header'; - html.innerHTML = data.header; - return html; - } - if (this.options.renderRow) { - // Call the render function - html = this.options.renderRow.call(this.options, data, this); - } else { - if (!selected) { - const { fieldName } = this.options; - - if (value) { - field = this.dropdown.parent().find(`input[name='${fieldName}'][value='${value}']`); - if (field.length) { - selected = true; - } - } else { - field = this.dropdown.parent().find(`input[name='${fieldName}']`); - selected = !field.length; - } - } - // Set URL - if (this.options.url != null) { - url = this.options.url(data); - } else { - url = data.url != null ? data.url : '#'; - } - // Set Text - if (this.options.text != null) { - text = this.options.text(data); - } else { - text = data.text != null ? data.text : ''; - } - if (this.highlight) { - text = data.template - ? this.highlightTemplate(text, data.template) - : this.highlightTextMatches(text, this.filterInput.val()); - } - // Create the list item & the link - var link = document.createElement('a'); - - link.href = url; - - if (this.icon) { - text = `${text}`; - link.classList.add('d-flex', 'align-items-center'); - link.innerHTML = data.icon ? data.icon + text : text; - } else if (this.highlight) { - link.innerHTML = text; - } else { - link.textContent = text; - } - - if (selected) { - link.classList.add('is-active'); - } - - if (group) { - link.dataset.group = group; - link.dataset.index = index; - } - - html.appendChild(link); - } - return html; + let parent; + + if (this.dropdown && this.dropdown[0]) { + parent = this.dropdown[0].parentNode; + } + + return renderItem({ + instance: this, + options: Object.assign({}, this.options, { + icon: this.icon, + highlight: this.highlight, + highlightText: text => this.highlightTextMatches(text, this.filterInput.val()), + highlightTemplate: this.highlightTemplate.bind(this), + parent, + }), + data, + group, + index, + }); }; GitLabDropdown.prototype.highlightTemplate = function(text, template) { @@ -809,7 +722,6 @@ GitLabDropdown = (function() { }; GitLabDropdown.prototype.noResults = function() { - var html; return ''; }; diff --git a/app/assets/javascripts/gl_dropdown/render.js b/app/assets/javascripts/gl_dropdown/render.js new file mode 100644 index 00000000000..66546aa834f --- /dev/null +++ b/app/assets/javascripts/gl_dropdown/render.js @@ -0,0 +1,158 @@ +const renderersByType = { + divider(element) { + element.classList.add('divider'); + + return element; + }, + separator(element) { + element.classList.add('separator'); + + return element; + }, + header(element, data) { + element.classList.add('dropdown-header'); + element.innerHTML = data.content; + + return element; + }, +}; + +function getPropertyWithDefault(data, options, property, defaultValue = '') { + let result; + + if (options[property] != null) { + result = options[property](data); + } else { + result = data[property] != null ? data[property] : defaultValue; + } + + return result; +} + +function getHighlightTextBuilder(text, data, options) { + if (options.highlight) { + return data.template + ? options.highlightTemplate(text, data.template) + : options.highlightText(text); + } + + return text; +} + +function getIconTextBuilder(text, data, options) { + if (options.icon) { + const wrappedText = `${text}`; + return data.icon ? `${data.icon}${wrappedText}` : wrappedText; + } + + return text; +} + +function getLinkText(data, options) { + const text = getPropertyWithDefault(data, options, 'text'); + + return [getHighlightTextBuilder, getIconTextBuilder].reduce( + (acc, fn) => fn(acc, data, options), + text, + ); +} + +function escape(text) { + return text ? String(text).replace(/'/g, "\\'") : text; +} + +function getOptionValue(data, options) { + if (options.renderRow) { + return undefined; + } + + return escape(options.id ? options.id(data) : data.id); +} + +function shouldHide(data, { options }) { + const value = getOptionValue(data, options); + + return options.hideRow && options.hideRow(value); +} + +function hideElement(element) { + element.style.display = 'none'; + + return element; +} + +function checkSelected(data, options) { + const value = getOptionValue(data, options); + + if (!options.parent) { + return !data.id; + } else if (value) { + return ( + options.parent.querySelector(`input[name='${options.fieldName}'][value='${value}']`) != null + ); + } + + return options.parent.querySelector(`input[name='${options.fieldName}']`) == null; +} + +function createLink(url, selected, options) { + const link = document.createElement('a'); + + link.href = url; + + if (options.icon) { + link.classList.add('d-flex', 'align-items-center'); + } + + link.classList.toggle('is-active', selected); + + return link; +} + +function assignTextToLink(el, data, options) { + const text = getLinkText(data, options); + + if (options.icon || options.highlight) { + el.innerHTML = text; + } else { + el.textContent = text; + } + + return el; +} + +function renderLink(row, data, { options, group, index }) { + const selected = checkSelected(data, options); + const url = getPropertyWithDefault(data, options, 'url', '#'); + const link = createLink(url, selected, options); + + assignTextToLink(link, data, options); + + if (group) { + link.dataset.group = group; + link.dataset.index = index; + } + + row.appendChild(link); + + return row; +} + +function getOptionRenderer({ options, instance }) { + return options.renderRow && ((li, data) => options.renderRow(data, instance)); +} + +function getRenderer(data, params) { + return renderersByType[data.type] || getOptionRenderer(params) || renderLink; +} + +export default function item({ data, ...params }) { + const renderer = getRenderer(data, params); + const li = document.createElement('li'); + + if (shouldHide(data, params)) { + hideElement(li); + } + + return renderer(li, data, params); +} diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js index cec824a529c..e94b163dfb1 100644 --- a/app/assets/javascripts/groups/transfer_dropdown.js +++ b/app/assets/javascripts/groups/transfer_dropdown.js @@ -14,7 +14,7 @@ export default class TransferDropdown { } buildDropdown() { - const extraOptions = [{ id: '-1', text: __('No parent group') }, 'divider']; + const extraOptions = [{ id: '-1', text: __('No parent group') }, { type: 'divider' }]; this.groupDropdown.glDropdown({ selectable: true, diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue index 132e50e5715..8cda7dac51f 100644 --- a/app/assets/javascripts/jobs/components/environments_block.vue +++ b/app/assets/javascripts/jobs/components/environments_block.vue @@ -79,7 +79,9 @@ export default { default: break; } - return environmentText; + return environmentText && this.hasCluster + ? `${environmentText} ${this.clusterText}` + : environmentText; }, environmentLink() { if (this.hasEnvironment) { @@ -109,6 +111,37 @@ export default { ? this.lastDeployment.deployable.build_path : ''; }, + hasCluster() { + return this.hasLastDeployment && this.lastDeployment.cluster; + }, + clusterNameOrLink() { + if (!this.hasCluster) { + return ''; + } + + const { name, path } = this.lastDeployment.cluster; + const escapedName = _.escape(name); + const escapedPath = _.escape(path); + + if (!escapedPath) { + return escapedName; + } + + return sprintf( + '%{startLink}%{name}%{endLink}', + { + startLink: ``, + name: escapedName, + endLink: '', + }, + false, + ); + }, + clusterText() { + return this.hasCluster + ? sprintf(__('Cluster %{cluster} was used.'), { cluster: this.clusterNameOrLink }, false) + : ''; + }, }, methods: { deploymentLink(name) { diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index f50a6e3b19d..177aa02b8e0 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -231,7 +231,7 @@ export default class LabelsSelect { }); } if (extraData.length) { - extraData.push('divider'); + extraData.push({ type: 'divider' }); data = extraData.concat(data); } } @@ -243,7 +243,7 @@ export default class LabelsSelect { }) .catch(() => flash(__('Error fetching labels.'))); }, - renderRow: function(label, instance) { + renderRow: function(label) { var linkEl, listItemEl, color, diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js index 43949d5cc86..8f077685b07 100644 --- a/app/assets/javascripts/milestone_select.js +++ b/app/assets/javascripts/milestone_select.js @@ -100,7 +100,7 @@ export default class MilestoneSelect { }); } if (extraOptions.length) { - extraOptions.push('divider'); + extraOptions.push({ type: 'divider' }); } callback(extraOptions.concat(data)); diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js index 03d349ac714..2ef081837e6 100644 --- a/app/assets/javascripts/namespace_select.js +++ b/app/assets/javascripts/namespace_select.js @@ -34,7 +34,7 @@ export default class NamespaceSelect { id: null, }; namespaces.unshift(anyNamespace); - namespaces.splice(1, 0, 'divider'); + namespaces.splice(1, 0, { type: 'divider' }); } return dataCallback(namespaces); }); diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js index 0d377eb9c68..95936c2d1db 100644 --- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js +++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js @@ -7,7 +7,7 @@ document.addEventListener('DOMContentLoaded', () => { const skippable = parseBoolean(twoFactorNode.dataset.twoFactorSkippable); if (skippable) { - const button = `Configure it later`; + const button = `Configure it later`; const flashAlert = document.querySelector('.flash-alert'); if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button); } diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index ea867d30ce8..89cac42abae 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -215,6 +215,7 @@ export default { :disabled="!canChangeVisibilityLevel" name="project[visibility_level]" class="form-control select-control" + data-qa-selector="project_visibility_dropdown" >