Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-13 21:08:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-13 21:08:57 +0300
commite9606d7f51144274f9a390c9dd683200daab8eed (patch)
treeb87cf29dc2fb63ea6ed519dabb3f46b06981c737 /app
parente1189e4c3b8bd5535104f458f5af7505789eac00 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue95
-rw-r--r--app/assets/javascripts/jira_connect/branches/components/source_branch_dropdown.vue134
-rw-r--r--app/assets/javascripts/jira_connect/branches/constants.js2
-rw-r--r--app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql17
-rw-r--r--app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql34
-rw-r--r--app/controllers/projects/mattermosts_controller.rb1
-rw-r--r--app/controllers/projects/service_hook_logs_controller.rb1
-rw-r--r--app/controllers/projects/services_controller.rb2
-rw-r--r--app/helpers/sidebars_helper.rb57
-rw-r--r--app/views/projects/mattermosts/_no_teams.html.haml2
-rw-r--r--app/views/projects/mattermosts/_team_selection.html.haml4
-rw-r--r--app/views/shared/nav/_scope_menu.html.haml4
-rw-r--r--app/views/shared/nav/_sidebar.html.haml2
13 files changed, 339 insertions, 16 deletions
diff --git a/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue b/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue
new file mode 100644
index 00000000000..c1f57be7f97
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { PROJECTS_PER_PAGE } from '../constants';
+import getProjectsQuery from '../graphql/queries/get_projects.query.graphql';
+
+export default {
+ PROJECTS_PER_PAGE,
+ projectQueryPageInfo: {
+ endCursor: '',
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ },
+ props: {
+ selectedProject: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ initialProjectsLoading: true,
+ projectSearchQuery: '',
+ };
+ },
+ apollo: {
+ projects: {
+ query: getProjectsQuery,
+ variables() {
+ return {
+ search: this.projectSearchQuery,
+ first: this.$options.PROJECTS_PER_PAGE,
+ after: this.$options.projectQueryPageInfo.endCursor,
+ searchNamespaces: true,
+ sort: 'similarity',
+ };
+ },
+ update(data) {
+ return data?.projects?.nodes.filter((project) => !project.repository.empty) ?? [];
+ },
+ result() {
+ this.initialProjectsLoading = false;
+ },
+ error() {
+ this.onError({ message: __('Failed to load projects') });
+ },
+ },
+ },
+ computed: {
+ projectsLoading() {
+ return Boolean(this.$apollo.queries.projects.loading);
+ },
+ projectDropdownText() {
+ return this.selectedProject?.nameWithNamespace || __('Select a project');
+ },
+ },
+ methods: {
+ async onProjectSelect(project) {
+ this.$emit('change', project);
+ },
+ onError({ message } = {}) {
+ this.$emit('error', { message });
+ },
+ isProjectSelected(project) {
+ return project.id === this.selectedProject?.id;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown :text="projectDropdownText" :loading="initialProjectsLoading">
+ <template #header>
+ <gl-search-box-by-type v-model.trim="projectSearchQuery" :debounce="250" />
+ </template>
+
+ <gl-loading-icon v-show="projectsLoading" />
+ <template v-if="!projectsLoading">
+ <gl-dropdown-item
+ v-for="project in projects"
+ :key="project.id"
+ is-check-item
+ :is-checked="isProjectSelected(project)"
+ @click="onProjectSelect(project)"
+ >
+ {{ project.nameWithNamespace }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/jira_connect/branches/components/source_branch_dropdown.vue b/app/assets/javascripts/jira_connect/branches/components/source_branch_dropdown.vue
new file mode 100644
index 00000000000..0e2d8821f36
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/branches/components/source_branch_dropdown.vue
@@ -0,0 +1,134 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { BRANCHES_PER_PAGE } from '../constants';
+import getProjectQuery from '../graphql/queries/get_project.query.graphql';
+
+export default {
+ BRANCHES_PER_PAGE,
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ },
+ props: {
+ selectedProject: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ selectedBranchName: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ sourceBranchSearchQuery: '',
+ initialSourceBranchNamesLoading: false,
+ sourceBranchNamesLoading: false,
+ sourceBranchNames: [],
+ };
+ },
+ computed: {
+ hasSelectedProject() {
+ return Boolean(this.selectedProject);
+ },
+ hasSelectedSourceBranch() {
+ return Boolean(this.selectedBranchName);
+ },
+ branchDropdownText() {
+ return this.selectedBranchName || __('Select a branch');
+ },
+ },
+ watch: {
+ selectedProject: {
+ immediate: true,
+ async handler(selectedProject) {
+ if (!selectedProject) return;
+
+ this.initialSourceBranchNamesLoading = true;
+ await this.fetchSourceBranchNames({ projectPath: selectedProject.fullPath });
+ this.initialSourceBranchNamesLoading = false;
+ },
+ },
+ },
+ methods: {
+ onSourceBranchSelect(branchName) {
+ this.$emit('change', branchName);
+ },
+ onSourceBranchSearchQuery(branchSearchQuery) {
+ this.branchSearchQuery = branchSearchQuery;
+ this.fetchSourceBranchNames({
+ projectPath: this.selectedProject.fullPath,
+ searchPattern: this.branchSearchQuery,
+ });
+ },
+ onError({ message } = {}) {
+ this.$emit('error', { message });
+ },
+ async fetchSourceBranchNames({ projectPath, searchPattern } = {}) {
+ this.sourceBranchNamesLoading = true;
+ try {
+ const { data } = await this.$apollo.query({
+ query: getProjectQuery,
+ variables: {
+ projectPath,
+ branchNamesLimit: this.$options.BRANCHES_PER_PAGE,
+ branchNamesOffset: 0,
+ branchNamesSearchPattern: searchPattern ? `*${searchPattern}*` : '*',
+ },
+ });
+
+ const { branchNames, rootRef } = data?.project.repository || {};
+ this.sourceBranchNames = branchNames || [];
+
+ // Use root ref as the default selection
+ if (rootRef && !this.hasSelectedSourceBranch) {
+ this.onSourceBranchSelect(rootRef);
+ }
+ } catch (err) {
+ this.onError({
+ message: __('Something went wrong while fetching source branches.'),
+ });
+ } finally {
+ this.sourceBranchNamesLoading = false;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown
+ :text="branchDropdownText"
+ :loading="initialSourceBranchNamesLoading"
+ :disabled="!hasSelectedProject"
+ :class="{ 'gl-font-monospace': hasSelectedSourceBranch }"
+ >
+ <template #header>
+ <gl-search-box-by-type
+ :debounce="250"
+ :value="sourceBranchSearchQuery"
+ @input="onSourceBranchSearchQuery"
+ />
+ </template>
+
+ <gl-loading-icon v-show="sourceBranchNamesLoading" />
+ <template v-if="!sourceBranchNamesLoading">
+ <gl-dropdown-item
+ v-for="branchName in sourceBranchNames"
+ v-show="!sourceBranchNamesLoading"
+ :key="branchName"
+ :is-checked="branchName === selectedBranchName"
+ is-check-item
+ class="gl-font-monospace"
+ @click="onSourceBranchSelect(branchName)"
+ >
+ {{ branchName }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/jira_connect/branches/constants.js b/app/assets/javascripts/jira_connect/branches/constants.js
new file mode 100644
index 00000000000..987c8d356b4
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/branches/constants.js
@@ -0,0 +1,2 @@
+export const BRANCHES_PER_PAGE = 20;
+export const PROJECTS_PER_PAGE = 20;
diff --git a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql
new file mode 100644
index 00000000000..f3428e816d7
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql
@@ -0,0 +1,17 @@
+query getProject(
+ $projectPath: ID!
+ $branchNamesLimit: Int!
+ $branchNamesOffset: Int!
+ $branchNamesSearchPattern: String!
+) {
+ project(fullPath: $projectPath) {
+ repository {
+ branchNames(
+ limit: $branchNamesLimit
+ offset: $branchNamesOffset
+ searchPattern: $branchNamesSearchPattern
+ )
+ rootRef
+ }
+ }
+}
diff --git a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
new file mode 100644
index 00000000000..e768154e210
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
@@ -0,0 +1,34 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getProjects(
+ $search: String!
+ $after: String = ""
+ $first: Int!
+ $searchNamespaces: Boolean = false
+ $sort: String
+ $membership: Boolean = true
+) {
+ projects(
+ search: $search
+ after: $after
+ first: $first
+ membership: $membership
+ searchNamespaces: $searchNamespaces
+ sort: $sort
+ ) {
+ nodes {
+ id
+ name
+ nameWithNamespace
+ fullPath
+ avatarUrl
+ path
+ repository {
+ empty
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+}
diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb
index aeca350d4ed..ebba20b285a 100644
--- a/app/controllers/projects/mattermosts_controller.rb
+++ b/app/controllers/projects/mattermosts_controller.rb
@@ -41,6 +41,5 @@ class Projects::MattermostsController < Projects::ApplicationController
def integration
@integration ||= @project.find_or_initialize_integration('mattermost_slash_commands')
- @service = @integration # TODO: remove when https://gitlab.com/gitlab-org/gitlab/-/issues/330300 is complete
end
end
diff --git a/app/controllers/projects/service_hook_logs_controller.rb b/app/controllers/projects/service_hook_logs_controller.rb
index 0db72d12012..93ba3eedddb 100644
--- a/app/controllers/projects/service_hook_logs_controller.rb
+++ b/app/controllers/projects/service_hook_logs_controller.rb
@@ -16,6 +16,5 @@ class Projects::ServiceHookLogsController < Projects::HookLogsController
def integration
@integration ||= @project.find_or_initialize_integration(params[:service_id])
- @service = @integration # TODO: remove when https://gitlab.com/gitlab-org/gitlab/-/issues/330300 is complete
end
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index e53fd55396b..ef6d96e8737 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -112,7 +112,7 @@ class Projects::ServicesController < Projects::ApplicationController
return if !integration.is_a?(::Integrations::Prometheus) || !Feature.enabled?(:settings_operations_prometheus_service, project)
operations_link_start = "<a href=\"#{project_settings_operations_path(project)}\">"
- message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" }
+ message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page have been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" }
flash.now[:alert] = message.html_safe
end
end
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 0fc306a3f2e..9e3a6a60d75 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -2,25 +2,68 @@
module SidebarsHelper
def sidebar_tracking_attributes_by_object(object)
+ sidebar_attributes_for_object(object).fetch(:tracking_attrs, {})
+ end
+
+ def sidebar_qa_selector(object)
+ sidebar_attributes_for_object(object).fetch(:sidebar_qa_selector, nil)
+ end
+
+ def scope_qa_menu_item(object)
+ sidebar_attributes_for_object(object).fetch(:scope_qa_menu_item, nil)
+ end
+
+ def scope_avatar_classes(object)
+ %w[avatar-container rect-avatar s32].tap do |klasses|
+ klass = sidebar_attributes_for_object(object).fetch(:scope_avatar_class, nil)
+ klasses << klass if klass
+ end
+ end
+
+ def project_sidebar_context(project, user, current_ref)
+ context_data = project_sidebar_context_data(project, user, current_ref)
+
+ Sidebars::Projects::Context.new(**context_data)
+ end
+
+ private
+
+ def sidebar_attributes_for_object(object)
case object
when Project
- sidebar_project_tracking_attrs
+ sidebar_project_attributes
when Group
- sidebar_group_tracking_attrs
+ sidebar_group_attributes
when User
- sidebar_user_profile_tracking_attrs
+ sidebar_user_attributes
else
{}
end
end
- def project_sidebar_context(project, user, current_ref)
- context_data = project_sidebar_context_data(project, user, current_ref)
+ def sidebar_project_attributes
+ {
+ tracking_attrs: sidebar_project_tracking_attrs,
+ sidebar_qa_selector: 'project_sidebar',
+ scope_qa_menu_item: 'Project scope',
+ scope_avatar_class: 'project_avatar'
+ }
+ end
- Sidebars::Projects::Context.new(**context_data)
+ def sidebar_group_attributes
+ {
+ tracking_attrs: sidebar_group_tracking_attrs,
+ sidebar_qa_selector: 'group_sidebar',
+ scope_qa_menu_item: 'Group scope',
+ scope_avatar_class: 'group_avatar'
+ }
end
- private
+ def sidebar_user_attributes
+ {
+ tracking_attrs: sidebar_user_profile_tracking_attrs
+ }
+ end
def sidebar_project_tracking_attrs
tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation')
diff --git a/app/views/projects/mattermosts/_no_teams.html.haml b/app/views/projects/mattermosts/_no_teams.html.haml
index f375222e311..adef11f315a 100644
--- a/app/views/projects/mattermosts/_no_teams.html.haml
+++ b/app/views/projects/mattermosts/_no_teams.html.haml
@@ -15,4 +15,4 @@
and try again.
%hr
.clearfix
- = link_to 'Go back', edit_project_service_path(@project, @service), class: 'gl-button btn btn-lg float-right'
+ = link_to 'Go back', edit_project_service_path(@project, @integration), class: 'gl-button btn btn-lg float-right'
diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml
index ea04a55a77c..4109fdfc13b 100644
--- a/app/views/projects/mattermosts/_team_selection.html.haml
+++ b/app/views/projects/mattermosts/_team_selection.html.haml
@@ -2,7 +2,7 @@
This service will be installed on the Mattermost instance at
%strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host
%hr
-= form_for(:mattermost, method: :post, url: project_mattermost_path(@project), html: { class: 'js-requires-input'} ) do |f|
+= form_for(:mattermost, method: :post, url: project_mattermost_path(@project), html: { class: 'js-requires-input' }) do |f|
%h4 Team
%p
= @teams.one? ? 'The team' : 'Select the team'
@@ -42,5 +42,5 @@
%hr
.clearfix
.float-right
- = link_to 'Cancel', edit_project_service_path(@project, @service), class: 'gl-button btn btn-lg'
+ = link_to 'Cancel', edit_project_service_path(@project, @integration), class: 'gl-button btn btn-lg'
= f.submit 'Install', class: 'gl-button btn btn-success btn-lg'
diff --git a/app/views/shared/nav/_scope_menu.html.haml b/app/views/shared/nav/_scope_menu.html.haml
index 0a544ec5fa6..1a7089fb570 100644
--- a/app/views/shared/nav/_scope_menu.html.haml
+++ b/app/views/shared/nav/_scope_menu.html.haml
@@ -1,6 +1,6 @@
= nav_link(**scope_menu.active_routes, html_options: scope_menu.nav_link_html_options) do
- = link_to scope_menu.link, **scope_menu.container_html_options, data: { qa_selector: 'project_scope_link' } do
- %span{ class: ['avatar-container', 'rect-avatar', 'project-avatar', 's32'] }
+ = link_to scope_menu.link, **scope_menu.container_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: scope_qa_menu_item(scope_menu.container) } do
+ %span{ class: scope_avatar_classes(scope_menu.container) }
= source_icon(scope_menu.container, alt: scope_menu.title, class: ['avatar', 'avatar-tile', 's32'], width: 32, height: 32)
%span.sidebar-context-title
= scope_menu.title
diff --git a/app/views/shared/nav/_sidebar.html.haml b/app/views/shared/nav/_sidebar.html.haml
index 82a64272a95..a52c2f8dd4b 100644
--- a/app/views/shared/nav/_sidebar.html.haml
+++ b/app/views/shared/nav/_sidebar.html.haml
@@ -3,7 +3,7 @@
- if sidebar.render_raw_scope_menu_partial
= render sidebar.render_raw_scope_menu_partial
- %ul.sidebar-top-level-items.qa-project-sidebar
+ %ul.sidebar-top-level-items{ data: { qa_selector: sidebar_qa_selector(sidebar.container) } }
- if sidebar.scope_menu
= render partial: 'shared/nav/scope_menu', object: sidebar.scope_menu
- if sidebar.renderable_menus.any?