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
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js12
-rw-r--r--app/assets/stylesheets/framework/mixins.scss10
-rw-r--r--app/assets/stylesheets/framework/variables_overrides.scss1
-rw-r--r--app/assets/stylesheets/performance_bar.scss3
-rw-r--r--app/controllers/groups/labels_controller.rb3
-rw-r--r--app/controllers/projects/labels_controller.rb1
-rw-r--r--app/finders/group_labels_finder.rb16
-rw-r--r--app/finders/labels_finder.rb13
-rw-r--r--app/helpers/boards_helper.rb4
-rw-r--r--app/helpers/labels_helper.rb20
-rw-r--r--app/models/label.rb9
-rw-r--r--app/views/groups/labels/index.html.haml21
-rw-r--r--app/views/projects/labels/index.html.haml23
-rw-r--r--app/views/shared/boards/_show.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml2
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml2
-rw-r--r--app/views/shared/labels/_nav.html.haml20
-rw-r--r--app/views/shared/labels/_sort_dropdown.html.haml2
-rw-r--r--changelogs/unreleased/48222-fix-todos-status-button.yml6
-rw-r--r--changelogs/unreleased/50552-unable-to-close-performance-bar.yml5
-rw-r--r--changelogs/unreleased/52178-markdown-table-borders.yml5
-rw-r--r--changelogs/unreleased/dz-labels-subscribe-filter.yml5
-rw-r--r--doc/api/merge_requests.md682
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/features/groups/labels/subscription_spec.rb50
-rw-r--r--spec/finders/group_labels_finder_spec.rb19
-rw-r--r--spec/finders/labels_finder_spec.rb10
-rw-r--r--spec/models/label_spec.rb36
30 files changed, 724 insertions, 272 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2a299ea79ef..c652b6c75e2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -606,7 +606,7 @@ static-analysis:
docs lint:
<<: *dedicated-runner
<<: *except-qa
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-docs-lint"
stage: test
cache: {}
dependencies: []
@@ -614,8 +614,8 @@ docs lint:
script:
- scripts/lint-doc.sh
- scripts/lint-changelog-yaml
- - mv doc/ /nanoc/content/
- - cd /nanoc
+ - mv doc/ /tmp/gitlab-docs/content/
+ - cd /tmp/gitlab-docs
# Build HTML from Markdown
- bundle exec nanoc
# Check the internal links
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index 9aa83ce6269..72f3f70b98f 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -79,10 +79,13 @@ export default class Todos {
.then(({ data }) => {
this.updateRowState(target);
this.updateBadges(data);
- }).catch(() => flash(__('Error updating todo status.')));
+ }).catch(() => {
+ this.updateRowState(target, true);
+ return flash(__('Error updating todo status.'));
+ });
}
- updateRowState(target) {
+ updateRowState(target, isInactive = false) {
const row = target.closest('li');
const restoreBtn = row.querySelector('.js-undo-todo');
const doneBtn = row.querySelector('.js-done-todo');
@@ -91,7 +94,10 @@ export default class Todos {
target.removeAttribute('disabled');
target.classList.remove('disabled');
- if (target === doneBtn) {
+ if (isInactive === true) {
+ restoreBtn.classList.add('hidden');
+ doneBtn.classList.remove('hidden');
+ } else if (target === doneBtn) {
row.classList.add('done-reversible');
restoreBtn.classList.remove('hidden');
} else if (target === restoreBtn) {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 11597c7e85e..be41dbfc61f 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -20,20 +20,24 @@
display: inline-block;
overflow-x: auto;
border: 0;
- border-color: $gray-100;
+ border-color: $gl-gray-100;
@supports (width: fit-content) {
display: block;
width: fit-content;
}
+ tbody {
+ background-color: $white-light;
+ }
+
tr {
th {
- border-bottom: solid 2px $gray-100;
+ border-bottom: solid 2px $gl-gray-100;
}
td {
- border-color: $gray-100;
+ border-color: $gl-gray-100;
}
}
}
diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss
index 7d90452e1f4..759b4f333ca 100644
--- a/app/assets/stylesheets/framework/variables_overrides.scss
+++ b/app/assets/stylesheets/framework/variables_overrides.scss
@@ -18,3 +18,4 @@ $success: $green-500;
$info: $blue-500;
$warning: $orange-500;
$danger: $red-500;
+$zindex-modal-backdrop: 1040;
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index 2e2ab8532d2..59fdbf31fe9 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -1,4 +1,5 @@
@import 'framework/variables';
+@import 'framework/variables_overrides';
@import 'peek/views/rblineprof';
#js-peek {
@@ -6,7 +7,7 @@
left: 0;
top: 0;
width: 100%;
- z-index: 1039;
+ z-index: #{$zindex-modal-backdrop + 1};
height: $performance-bar-height;
background: $black;
diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb
index cb9ab35de85..26768c628ca 100644
--- a/app/controllers/groups/labels_controller.rb
+++ b/app/controllers/groups/labels_controller.rb
@@ -12,7 +12,8 @@ class Groups::LabelsController < Groups::ApplicationController
def index
respond_to do |format|
format.html do
- @labels = GroupLabelsFinder.new(@group, params.merge(sort: sort)).execute
+ @labels = GroupLabelsFinder
+ .new(current_user, @group, params.merge(sort: sort)).execute
end
format.json do
render json: LabelSerializer.new.represent_appearance(available_labels)
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index a0ce3b08d9f..640038818f2 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -163,6 +163,7 @@ class Projects::LabelsController < Projects::ApplicationController
project_id: @project.id,
include_ancestor_groups: params[:include_ancestor_groups],
search: params[:search],
+ subscribed: params[:subscribed],
sort: sort).execute
end
diff --git a/app/finders/group_labels_finder.rb b/app/finders/group_labels_finder.rb
index 903023033ed..a668a0f0fae 100644
--- a/app/finders/group_labels_finder.rb
+++ b/app/finders/group_labels_finder.rb
@@ -1,17 +1,29 @@
# frozen_string_literal: true
class GroupLabelsFinder
- attr_reader :group, :params
+ attr_reader :current_user, :group, :params
- def initialize(group, params = {})
+ def initialize(current_user, group, params = {})
+ @current_user = current_user
@group = group
@params = params
end
def execute
group.labels
+ .optionally_subscribed_by(subscriber_id)
.optionally_search(params[:search])
.order_by(params[:sort])
.page(params[:page])
end
+
+ private
+
+ def subscriber_id
+ current_user&.id if subscribed?
+ end
+
+ def subscribed?
+ params[:subscribed] == 'true'
+ end
end
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index 08fc2968e77..82e0b2ed9e1 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -17,6 +17,7 @@ class LabelsFinder < UnionFinder
@skip_authorization = skip_authorization
items = find_union(label_ids, Label) || Label.none
items = with_title(items)
+ items = by_subscription(items)
items = by_search(items)
sort(items)
end
@@ -84,6 +85,18 @@ class LabelsFinder < UnionFinder
labels.search(params[:search])
end
+ def by_subscription(labels)
+ labels.optionally_subscribed_by(subscriber_id)
+ end
+
+ def subscriber_id
+ current_user&.id if subscribed?
+ end
+
+ def subscribed?
+ params[:subscribed] == 'true'
+ end
+
# Gets redacted array of group ids
# which can include the ancestors and descendants of the requested group.
def group_ids_for(group)
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index e3b74f443f7..be1e7016a1e 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -59,8 +59,8 @@ module BoardsHelper
{
toggle: "dropdown",
- list_labels_path: labels_filter_path(true, include_ancestor_groups: true),
- labels: labels_filter_path(true, include_descendant_groups: include_descendant_groups),
+ list_labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_ancestor_groups: true),
+ labels: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: include_descendant_groups),
labels_endpoint: @labels_endpoint,
namespace_path: @namespace_path,
project_path: @project&.path,
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 6c51739ba1a..76ed8efe2c6 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -131,20 +131,26 @@ module LabelsHelper
end
end
- def labels_filter_path(only_group_labels = false, include_ancestor_groups: true, include_descendant_groups: false)
- project = @target_project || @project
-
+ def labels_filter_path_with_defaults(only_group_labels: false, include_ancestor_groups: true, include_descendant_groups: false)
options = {}
options[:include_ancestor_groups] = include_ancestor_groups if include_ancestor_groups
options[:include_descendant_groups] = include_descendant_groups if include_descendant_groups
+ options[:only_group_labels] = only_group_labels if only_group_labels && @group
+ options[:format] = :json
+
+ labels_filter_path(options)
+ end
+
+ def labels_filter_path(options = {})
+ project = @target_project || @project
+ format = options.delete(:format) || :html
if project
- project_labels_path(project, :json, options)
+ project_labels_path(project, format, options)
elsif @group
- options[:only_group_labels] = only_group_labels if only_group_labels
- group_labels_path(@group, :json, options)
+ group_labels_path(@group, format, options)
else
- dashboard_labels_path(:json)
+ dashboard_labels_path(format, options)
end
end
diff --git a/app/models/label.rb b/app/models/label.rb
index 9ef57a05b3e..43b49445765 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -45,6 +45,7 @@ class Label < ActiveRecord::Base
scope :on_project_boards, ->(project_id) { with_lists_and_board.where(boards: { project_id: project_id }) }
scope :order_name_asc, -> { reorder(title: :asc) }
scope :order_name_desc, -> { reorder(title: :desc) }
+ scope :subscribed_by, ->(user_id) { joins(:subscriptions).where(subscriptions: { user_id: user_id, subscribed: true }) }
def self.prioritized(project)
joins(:priorities)
@@ -74,6 +75,14 @@ class Label < ActiveRecord::Base
joins(label_priorities)
end
+ def self.optionally_subscribed_by(user_id)
+ if user_id
+ subscribed_by(user_id)
+ else
+ all
+ end
+ end
+
alias_attribute :name, :title
def self.reference_prefix
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 003bd25dd06..5b78ce910b8 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -3,29 +3,23 @@
- can_admin_label = can?(current_user, :admin_label, @group)
- issuables = ['issues', 'merge requests']
- search = params[:search]
+- subscribed = params[:subscribed]
+- labels_or_filters = @labels.exists? || search.present? || subscribed.present?
- if can_admin_label
- content_for(:header_content) do
.nav-controls
= link_to _('New label'), new_group_label_path(@group), class: "btn btn-success"
-- if @labels.exists? || search.present?
+- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- .top-area.adjust
- .nav-text
- = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuables.to_sentence }
- .nav-controls
- = form_tag group_labels_path(@group), method: :get do
- .input-group
- = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
- %span.input-group-append
- %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
- = icon("search")
- = render 'shared/labels/sort_dropdown'
+ = render 'shared/labels/nav'
.labels-container.prepend-top-5
- if @labels.any?
+ .text-muted
+ = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuables.to_sentence }
.other-labels
%h5= _('Labels')
%ul.content-list.manage-labels-list.js-other-labels
@@ -34,6 +28,9 @@
- elsif search.present?
.nothing-here-block
= _('No labels with such name or description')
+ - elsif subscribed.present?
+ .nothing-here-block
+ = _('You do not have any subscriptions yet')
- else
= render 'shared/empty_states/labels'
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 683dda4f166..11a05eada30 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -2,32 +2,25 @@
- page_title "Labels"
- can_admin_label = can?(current_user, :admin_label, @project)
- search = params[:search]
+- subscribed = params[:subscribed]
+- labels_or_filters = @labels.exists? || @prioritized_labels.exists? || search.present? || subscribed.present?
- if can_admin_label
- content_for(:header_content) do
.nav-controls
= link_to _('New label'), new_project_label_path(@project), class: "btn btn-success"
-- if @labels.exists? || @prioritized_labels.exists? || search.present?
+- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- .top-area.adjust
- .nav-text
- = _('Labels can be applied to issues and merge requests.')
-
- .nav-controls
- = form_tag project_labels_path(@project), method: :get do
- .input-group
- = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
- %span.input-group-append
- %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
- = icon("search")
- = render 'shared/labels/sort_dropdown'
+ = render 'shared/labels/nav'
.labels-container.prepend-top-10
- if can_admin_label
- if search.blank?
%p.text-muted
+ = _('Labels can be applied to issues and merge requests.')
+ %br
= _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.')
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
@@ -59,7 +52,9 @@
- else
.nothing-here-block
= _('No labels with such name or description')
-
+ - elsif subscribed.present?
+ .nothing-here-block
+ = _('You do not have any subscriptions yet')
- else
= render 'shared/empty_states/labels'
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index 28e6fe1b16d..0d2f6bb77d6 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -33,7 +33,7 @@
- if @project
%board-add-issues-modal{ "new-issue-path" => new_project_issue_path(@project),
"milestone-path" => milestones_filter_dropdown_path,
- "label-path" => labels_filter_path,
+ "label-path" => labels_filter_path_with_defaults,
"empty-state-svg" => image_path('illustrations/issues.svg'),
":issue-link-base" => "issueLinkBase",
":root-path" => "rootPath",
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index 532045f3697..6138914206b 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -25,7 +25,7 @@
show_no: "true",
show_any: "true",
project_id: @project&.try(:id),
- labels: labels_filter_path(false),
+ labels: labels_filter_path_with_defaults,
namespace_path: @namespace_path,
project_path: @project.try(:path) } }
%span.dropdown-toggle-text
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index 0b42b33581a..6eb1f8f0853 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -8,7 +8,7 @@
- classes = local_assigns.fetch(:classes, [])
- selected = local_assigns.fetch(:selected, nil)
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by label")
-- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), labels: labels_filter_path, default_label: "Labels"}
+- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), labels: labels_filter_path_with_defaults, default_label: "Labels"}
- dropdown_data.merge!(data_options)
- label_name = local_assigns.fetch(:label_name, "Labels")
- no_default_styles = local_assigns.fetch(:no_default_styles, false)
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 32b609eed0d..aa136af1955 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -109,7 +109,7 @@
- selected_labels.each do |label|
= hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
.dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path(false) if @project), display: 'static' } }
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path_with_defaults if @project), display: 'static' } }
%span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
= multi_label_name(selected_labels, "Labels")
= icon('chevron-down', 'aria-hidden': 'true')
diff --git a/app/views/shared/labels/_nav.html.haml b/app/views/shared/labels/_nav.html.haml
new file mode 100644
index 00000000000..98572db738b
--- /dev/null
+++ b/app/views/shared/labels/_nav.html.haml
@@ -0,0 +1,20 @@
+- subscribed = params[:subscribed]
+
+.top-area.adjust
+ %ul.nav-links.nav.nav-tabs
+ %li{ class: active_when(subscribed != 'true') }>
+ = link_to labels_filter_path do
+ = _('All')
+ - if current_user
+ %li{ class: active_when(subscribed == 'true') }>
+ = link_to labels_filter_path(subscribed: 'true') do
+ = _('Subscribed')
+ .nav-controls
+ = form_tag labels_filter_path, method: :get do
+ = hidden_field_tag :subscribed, params[:subscribed]
+ .input-group
+ = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
+ %span.input-group-append
+ %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
+ = icon("search")
+ = render 'shared/labels/sort_dropdown'
diff --git a/app/views/shared/labels/_sort_dropdown.html.haml b/app/views/shared/labels/_sort_dropdown.html.haml
index ff6e2947ffd..8a7d037e15b 100644
--- a/app/views/shared/labels/_sort_dropdown.html.haml
+++ b/app/views/shared/labels/_sort_dropdown.html.haml
@@ -6,4 +6,4 @@
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-sort
%li
- label_sort_options_hash.each do |value, title|
- = sortable_item(title, page_filter_path(sort: value, label: true), sort_title)
+ = sortable_item(title, page_filter_path(sort: value, label: true, subscribed: params[:subscribed]), sort_title)
diff --git a/changelogs/unreleased/48222-fix-todos-status-button.yml b/changelogs/unreleased/48222-fix-todos-status-button.yml
new file mode 100644
index 00000000000..2f7c79a07d0
--- /dev/null
+++ b/changelogs/unreleased/48222-fix-todos-status-button.yml
@@ -0,0 +1,6 @@
+---
+title: Fix the state of the Done button when there is an error in the GitLab Todos
+ section
+merge_request:
+author: marcos8896
+type: fixed
diff --git a/changelogs/unreleased/50552-unable-to-close-performance-bar.yml b/changelogs/unreleased/50552-unable-to-close-performance-bar.yml
new file mode 100644
index 00000000000..e3619149d2a
--- /dev/null
+++ b/changelogs/unreleased/50552-unable-to-close-performance-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Fix performance bar modal position
+merge_request: 21577
+author:
+type: fixed
diff --git a/changelogs/unreleased/52178-markdown-table-borders.yml b/changelogs/unreleased/52178-markdown-table-borders.yml
new file mode 100644
index 00000000000..965f21f2a97
--- /dev/null
+++ b/changelogs/unreleased/52178-markdown-table-borders.yml
@@ -0,0 +1,5 @@
+---
+title: Add borders and white background to markdown tables
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-labels-subscribe-filter.yml b/changelogs/unreleased/dz-labels-subscribe-filter.yml
new file mode 100644
index 00000000000..768c20c77c7
--- /dev/null
+++ b/changelogs/unreleased/dz-labels-subscribe-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Add subscribe filter to group and project labels pages
+merge_request: 21965
+author:
+type: added
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index b37e7698ab4..862ee398a84 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -54,35 +54,38 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -93,23 +96,28 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -169,35 +177,38 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -208,24 +219,28 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -275,35 +290,38 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -314,23 +332,26 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-10-22",
+ "start_date": "2018-09-08",
+ "web_url": "gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -359,35 +380,38 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "merged",
+ "description": "fixed login page css paddings",
+ "state": "opened",
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
+ "state": "active",
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
+ "state": "active",
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -398,50 +422,55 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": "9999999999999999999999999999999999999999",
+ "merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
},
- "closed_at": "2018-01-19T14:36:11.086Z",
- "latest_build_started_at": null,
- "latest_build_finished_at": null,
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
"first_deployed_to_production_at": null,
"pipeline": {
- "id": 8,
- "ref": "master",
- "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0",
- "status": "created"
- },
- "merged_by": null,
- "merged_at": null,
- "closed_by": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
},
"diff_refs": {
- "base_sha": "1111111111111111111111111111111111111111",
- "head_sha": "2222222222222222222222222222222222222222",
- "start_sha": "3333333333333333333333333333333333333333"
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
"diverged_commits_count": 2
}
@@ -663,65 +692,99 @@ POST /projects/:id/merge_requests
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
- "project_id": 4,
+ "project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 3,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
- "user_notes_count": 0,
- "changes_count": "1",
+ "user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -756,64 +819,99 @@ Must include at least one non-required attribute from above.
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "project_id": 4,
+ "project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 3,
- "target_project_id": 4,
- "labels": [ ],
- "description": "description1",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -857,70 +955,106 @@ Parameters:
- `merge_request_iid` (required) - Internal ID of MR
- `merge_commit_message` (optional) - Custom merge commit message
- `should_remove_source_branch` (optional) - if `true` removes the source branch
-- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
+- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
```json
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "merged",
+ "description": "fixed login page css paddings",
+ "state": "opened",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 4,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": "9999999999999999999999999999999999999999",
+ "merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -937,69 +1071,105 @@ PUT /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_s
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - Internal ID of MR
+- `merge_request_iid` (required) - Internal ID of MR
```json
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 4,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": true,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "can_be_merged",
- "subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -1067,7 +1237,7 @@ Example response when the GitLab issue tracker is used:
"labels" : [],
"user_notes_count": 1,
"changes_count": "1"
- },
+ }
]
```
@@ -1104,54 +1274,101 @@ Example response:
```json
{
- "id": 17,
+ "id": 1,
"iid": 1,
- "project_id": 5,
- "title": "Et et sequi est impedit nulla ut rem et voluptatem.",
- "description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
+ "project_id": 3,
+ "title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
- "created_at": "2016-04-05T21:42:23.233Z",
- "updated_at": "2016-04-05T22:11:52.900Z",
- "target_branch": "ui-dev-kit",
- "source_branch": "version-1-9",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "name": "Eileen Skiles",
- "username": "leila",
- "id": 19,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/leila"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "name": "Celine Wehner",
- "username": "carli",
- "id": 16,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/carli"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 5,
- "target_project_id": 5,
- "labels": [],
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
- "id": 7,
+ "id": 5,
"iid": 1,
- "project_id": 5,
+ "project_id": 3,
"title": "v2.0",
- "description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
+ "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
- "created_at": "2016-04-05T21:41:40.905Z",
- "updated_at": "2016-04-05T21:41:40.905Z",
- "due_date": null
+ "created_at": "2015-02-02T19:49:26.013Z",
+ "updated_at": "2015-02-02T19:49:26.013Z",
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": false,
- "merge_status": "cannot_be_merged",
- "subscribed": true,
+ "merge_when_pipeline_succeeds": true,
+ "merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": null
+ "merge_commit_sha": null,
+ "user_notes_count": 1,
+ "discussion_locked": null,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -1178,54 +1395,101 @@ Example response:
```json
{
- "id": 17,
+ "id": 1,
"iid": 1,
- "project_id": 5,
- "title": "Et et sequi est impedit nulla ut rem et voluptatem.",
- "description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
+ "project_id": 3,
+ "title": "test1",
+ "description": "fixed login page css paddings",
"state": "opened",
- "created_at": "2016-04-05T21:42:23.233Z",
- "updated_at": "2016-04-05T22:11:52.900Z",
- "target_branch": "ui-dev-kit",
- "source_branch": "version-1-9",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "name": "Eileen Skiles",
- "username": "leila",
- "id": 19,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/leila"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "name": "Celine Wehner",
- "username": "carli",
- "id": 16,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/carli"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 5,
- "target_project_id": 5,
- "labels": [],
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
- "id": 7,
+ "id": 5,
"iid": 1,
- "project_id": 5,
+ "project_id": 3,
"title": "v2.0",
- "description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
+ "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
- "created_at": "2016-04-05T21:41:40.905Z",
- "updated_at": "2016-04-05T21:41:40.905Z",
- "due_date": null
+ "created_at": "2015-02-02T19:49:26.013Z",
+ "updated_at": "2015-02-02T19:49:26.013Z",
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": false,
- "merge_status": "cannot_be_merged",
- "subscribed": false,
+ "merge_when_pipeline_succeeds": true,
+ "merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": null
+ "merge_commit_sha": null,
+ "user_notes_count": 1,
+ "discussion_locked": null,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 92a88c1c794..b56cd5700aa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5786,6 +5786,9 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
msgstr ""
@@ -6956,6 +6959,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb
index d9543bfa97f..22b51b297a6 100644
--- a/spec/features/groups/labels/subscription_spec.rb
+++ b/spec/features/groups/labels/subscription_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
describe 'Labels subscription' do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let!(:feature) { create(:group_label, group: group, title: 'feature') }
+ let!(:label1) { create(:group_label, group: group, title: 'foo') }
+ let!(:label2) { create(:group_label, group: group, title: 'bar') }
context 'when signed in' do
before do
@@ -14,9 +15,9 @@ describe 'Labels subscription' do
it 'users can subscribe/unsubscribe to group labels', :js do
visit group_labels_path(group)
- expect(page).to have_content('feature')
+ expect(page).to have_content(label1.title)
- within "#group_label_#{feature.id}" do
+ within "#group_label_#{label1.id}" do
expect(page).not_to have_button 'Unsubscribe'
click_button 'Subscribe'
@@ -30,15 +31,48 @@ describe 'Labels subscription' do
expect(page).not_to have_button 'Unsubscribe'
end
end
+
+ context 'subscription filter' do
+ before do
+ visit group_labels_path(group)
+ end
+
+ it 'shows only subscribed labels' do
+ label1.subscribe(user)
+
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).to have_content label1.title
+ end
+ end
+
+ it 'shows no subscribed labels message' do
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).not_to have_content label1.title
+ expect(page).to have_content('You do not have any subscriptions yet')
+ end
+ end
+ end
end
context 'when not signed in' do
- it 'users can not subscribe/unsubscribe to labels' do
+ before do
visit group_labels_path(group)
+ end
- expect(page).to have_content 'feature'
+ it 'users can not subscribe/unsubscribe to labels' do
+ expect(page).to have_content label1.title
expect(page).not_to have_button('Subscribe')
end
+
+ it 'does not show subscribed tab' do
+ page.within('.nav-tabs') do
+ expect(page).not_to have_link 'Subscribed'
+ end
+ end
end
def click_link_on_dropdown(text)
@@ -48,4 +82,10 @@ describe 'Labels subscription' do
find('a.js-subscribe-button', text: text).click
end
end
+
+ def click_subscribed_tab
+ page.within('.nav-tabs') do
+ click_link 'Subscribed'
+ end
+ end
end
diff --git a/spec/finders/group_labels_finder_spec.rb b/spec/finders/group_labels_finder_spec.rb
index ef68fc105e4..7bdd312eff0 100644
--- a/spec/finders/group_labels_finder_spec.rb
+++ b/spec/finders/group_labels_finder_spec.rb
@@ -4,29 +4,38 @@ require 'spec_helper'
describe GroupLabelsFinder, '#execute' do
let!(:group) { create(:group) }
+ let!(:user) { create(:user) }
let!(:label1) { create(:group_label, title: 'Foo', description: 'Lorem ipsum', group: group) }
let!(:label2) { create(:group_label, title: 'Bar', description: 'Fusce consequat', group: group) }
it 'returns all group labels sorted by name if no params' do
- result = described_class.new(group).execute
+ result = described_class.new(user, group).execute
expect(result.to_a).to match_array([label2, label1])
end
it 'returns all group labels sorted by name desc' do
- result = described_class.new(group, sort: 'name_desc').execute
+ result = described_class.new(user, group, sort: 'name_desc').execute
expect(result.to_a).to match_array([label2, label1])
end
- it 'returns group labels that march search' do
- result = described_class.new(group, search: 'Foo').execute
+ it 'returns group labels that match search' do
+ result = described_class.new(user, group, search: 'Foo').execute
expect(result.to_a).to match_array([label1])
end
+ it 'returns group labels user subscribed to' do
+ label2.subscribe(user)
+
+ result = described_class.new(user, group, subscribed: 'true').execute
+
+ expect(result.to_a).to match_array([label2])
+ end
+
it 'returns second page of labels' do
- result = described_class.new(group, page: '2').execute
+ result = described_class.new(user, group, page: '2').execute
expect(result.to_a).to match_array([])
end
diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb
index f5cec8e349a..9abc52aa664 100644
--- a/spec/finders/labels_finder_spec.rb
+++ b/spec/finders/labels_finder_spec.rb
@@ -210,5 +210,15 @@ describe LabelsFinder do
expect(finder.execute).to eq [project_label_1]
end
end
+
+ context 'filter by subscription' do
+ it 'returns labels user subscribed to' do
+ project_label_1.subscribe(user)
+
+ finder = described_class.new(user, subscribed: 'true')
+
+ expect(finder.execute).to eq [project_label_1]
+ end
+ end
end
end
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index 99670af786a..3fc6c06b7fa 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -155,4 +155,40 @@ describe Label do
expect(described_class.search('feature')).to be_empty
end
end
+
+ describe '.subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns nothing' do
+ expect(described_class.subscribed_by(0)).to be_empty
+ end
+ end
+
+ describe '.optionally_subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.optionally_subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns all labels if user_id is nil' do
+ expect(described_class.optionally_subscribed_by(nil)).to match_array([label, label2])
+ end
+ end
end