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>2022-02-01 21:17:05 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-01 21:17:05 +0300
commit143a33345cf3607ad35ec31130cec4922bc1113c (patch)
tree33b0a2658928f06d4ab20f8ec7d3aeadfbdd08d9 /app
parent3bdc719293f08ed357ef452f3e2a11a9b29531e7 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/diffs/components/app.vue4
-rw-r--r--app/assets/javascripts/groups/components/transfer_group_form.vue3
-rw-r--r--app/assets/javascripts/groups/init_transfer_group_form.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue19
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/graphql/mutations/work_items/delete.rb48
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/policies/work_item_policy.rb7
-rw-r--r--app/services/projects/destroy_service.rb5
-rw-r--r--app/services/work_items/delete_service.rb17
-rw-r--r--app/views/projects/_merge_request_merge_checks_settings.html.haml4
-rw-r--r--app/views/projects/notes/_actions.html.haml30
-rw-r--r--app/views/shared/icons/_icon_resolve_discussion.svg1
-rw-r--r--app/views/shared/icons/_icon_status_success_solid.svg1
15 files changed, 100 insertions, 50 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 45f8676a1d2..a8ca17ab4dd 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -524,7 +524,7 @@ export default {
if (
window.gon?.features?.diffsVirtualScrolling ||
- window.gon?.features?.diffSearchingUsageData
+ window.gon?.features?.usageDataDiffSearches
) {
let keydownTime;
Mousetrap.bind(['mod+f', 'mod+g'], () => {
@@ -540,7 +540,7 @@ export default {
if (delta >= 0 && delta < 1000) {
this.disableVirtualScroller();
- if (window.gon?.features?.diffSearchingUsageData) {
+ if (window.gon?.features?.usageDataDiffSearches) {
api.trackRedisHllUserEvent('i_code_review_user_searches_diff');
api.trackRedisCounterEvent('diff_searches');
}
diff --git a/app/assets/javascripts/groups/components/transfer_group_form.vue b/app/assets/javascripts/groups/components/transfer_group_form.vue
index ba8de2b0203..2d0d6b41c99 100644
--- a/app/assets/javascripts/groups/components/transfer_group_form.vue
+++ b/app/assets/javascripts/groups/components/transfer_group_form.vue
@@ -43,9 +43,6 @@ export default {
};
},
computed: {
- selectedNamespaceId() {
- return this.selectedId;
- },
disableSubmitButton() {
return this.isPaidGroup || !this.selectedId;
},
diff --git a/app/assets/javascripts/groups/init_transfer_group_form.js b/app/assets/javascripts/groups/init_transfer_group_form.js
index c60255e6ec3..c9a1e46de72 100644
--- a/app/assets/javascripts/groups/init_transfer_group_form.js
+++ b/app/assets/javascripts/groups/init_transfer_group_form.js
@@ -4,6 +4,10 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import TransferGroupForm, { i18n } from './components/transfer_group_form.vue';
const prepareGroups = (rawGroups) => {
+ if (!rawGroups) {
+ return { group: [] };
+ }
+
const group = JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
id,
humanName,
@@ -22,7 +26,7 @@ export default () => {
targetFormId = null,
buttonText: confirmButtonText = '',
groupName = '',
- parentGroups = [],
+ parentGroups,
isPaidGroup,
} = el.dataset;
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 6f61afe6e68..11de58aa344 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -578,7 +578,7 @@ export default {
:endpoint="mr.accessibilityReportPath"
/>
- <div class="mr-widget-section">
+ <div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
diff --git a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
index 806212f0f2e..3d5baca5338 100644
--- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
@@ -16,8 +16,13 @@ export const i18n = {
USERS: __('Users'),
};
-const filterByName = (data, searchTerm = '') =>
- data.filter((d) => d.humanName.toLowerCase().includes(searchTerm));
+const filterByName = (data, searchTerm = '') => {
+ if (!searchTerm) {
+ return data;
+ }
+
+ return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase()));
+};
export default {
name: 'NamespaceSelect',
@@ -85,7 +90,15 @@ export default {
},
filteredEmptyNamespaceTitle() {
const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
- return includeEmptyNamespace && emptyNamespaceTitle.toLowerCase().includes(searchTerm);
+
+ if (!includeEmptyNamespace) {
+ return '';
+ }
+ if (!searchTerm) {
+ return emptyNamespaceTitle;
+ }
+
+ return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase());
},
},
methods: {
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index bb951a54aeb..9007db05431 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -47,7 +47,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)
- push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:usage_data_diff_searches, @project, default_enabled: :yaml)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
diff --git a/app/graphql/mutations/work_items/delete.rb b/app/graphql/mutations/work_items/delete.rb
new file mode 100644
index 00000000000..6a3e651bdd5
--- /dev/null
+++ b/app/graphql/mutations/work_items/delete.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Mutations
+ module WorkItems
+ class Delete < BaseMutation
+ description "Deletes a work item." \
+ " Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice."
+
+ graphql_name 'WorkItemDelete'
+
+ authorize :delete_work_item
+
+ argument :id, ::Types::GlobalIDType[::WorkItem],
+ required: true,
+ description: 'Global ID of the work item.'
+
+ field :project, Types::ProjectType,
+ null: true,
+ description: 'Project the deleted work item belonged to.'
+
+ def resolve(id:)
+ work_item = authorized_find!(id: id)
+
+ unless Feature.enabled?(:work_items, work_item.project)
+ return { errors: ['`work_items` feature flag disabled for this project'] }
+ end
+
+ result = ::WorkItems::DeleteService.new(
+ project: work_item.project,
+ current_user: current_user
+ ).execute(work_item)
+
+ {
+ project: result.success? ? work_item.project : nil,
+ errors: result.errors
+ }
+ end
+
+ private
+
+ def find_object(id:)
+ # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 021a023cb88..bcf64b79a85 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -126,6 +126,7 @@ module Types
mount_mutation Mutations::Packages::DestroyFile
mount_mutation Mutations::Echo
mount_mutation Mutations::WorkItems::Create, feature_flag: :work_items
+ mount_mutation Mutations::WorkItems::Delete
mount_mutation Mutations::WorkItems::Update
end
end
diff --git a/app/policies/work_item_policy.rb b/app/policies/work_item_policy.rb
index 9cacd495e6c..7ba5102a406 100644
--- a/app/policies/work_item_policy.rb
+++ b/app/policies/work_item_policy.rb
@@ -2,4 +2,11 @@
class WorkItemPolicy < BasePolicy
delegate { @subject.project }
+
+ desc 'User is author of the work item'
+ condition(:author) do
+ @user && @user == @subject.author
+ end
+
+ rule { can?(:owner_access) | author }.enable :delete_work_item
end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 5f777a74adb..733a4b45cb2 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -139,10 +139,7 @@ module Projects
destroy_web_hooks!
destroy_project_bots!
destroy_ci_records!
-
- if ::Feature.enabled?(:extract_mr_diff_commit_deletions, default_enabled: :yaml)
- destroy_mr_diff_commits!
- end
+ destroy_mr_diff_commits!
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
diff --git a/app/services/work_items/delete_service.rb b/app/services/work_items/delete_service.rb
new file mode 100644
index 00000000000..1093a403a1c
--- /dev/null
+++ b/app/services/work_items/delete_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class DeleteService < Issuable::DestroyService
+ def execute(work_item)
+ unless current_user.can?(:delete_work_item, work_item)
+ return ::ServiceResponse.error(message: 'User not authorized to delete work item')
+ end
+
+ if super
+ ::ServiceResponse.success
+ else
+ ::ServiceResponse.error(message: work_item.errors.full_messages)
+ end
+ end
+ end
+end
diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml
index b9ddb93c664..4f9af40f711 100644
--- a/app/views/projects/_merge_request_merge_checks_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml
@@ -8,9 +8,7 @@
= form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do
= s_('ProjectSettings|Pipelines must succeed')
.text-secondary
- - configuring_pipelines_for_merge_requests_help_link_url = help_page_path('ci/pipelines/merge_request_pipelines.md', anchor: 'prerequisites')
- - configuring_pipelines_for_merge_requests_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configuring_pipelines_for_merge_requests_help_link_url }
- = s_('ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure merge request pipelines?%{link_end}').html_safe % { link_start: configuring_pipelines_for_merge_requests_help_link_start, link_end: '</a>'.html_safe }
+ = s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.")
.form-check.mb-2
.gl-pl-6
= form.check_box :allow_merge_on_skipped_pipeline, class: 'form-check-input'
diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml
index d11b61466e2..31c14aaad50 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -6,36 +6,6 @@
- elsif note.contributor?
%span{ class: 'note-role user-access-role has-tooltip', title: _("This user has previously committed to the %{name} project.") % { name: note.project_name } }= _("Contributor")
-- if note.resolvable?
- - can_resolve = can?(current_user, :resolve_note, note)
- %resolve-btn{ "project-path" => project_path(note.project),
- "discussion-id" => note.discussion_id(@noteable),
- ":note-id" => note.id,
- ":resolved" => note.resolved?,
- ":can-resolve" => can_resolve,
- ":author-name" => "'#{j(note.author.name)}'",
- "author-avatar" => note.author.avatar_url,
- ":note-truncated" => "'#{j(truncate(note.note, length: 17))}'",
- ":resolved-by" => "'#{j(note.resolved_by.try(:name))}'",
- "v-show" => "#{can_resolve || note.resolved?}",
- "inline-template" => true,
- "ref" => "note_#{note.id}" }
-
- .note-actions-item
- %button.note-action-button.line-resolve-btn{ type: "button",
- class: ("is-disabled" unless can_resolve),
- ":class" => "{ 'is-active': isResolved }",
- ":aria-label" => "buttonText",
- "@click" => "resolve",
- ":title" => "buttonText",
- ":ref" => "'button'" }
-
- %div
- %template{ 'v-if' => 'isResolved' }
- = render 'shared/icons/icon_status_success_solid.svg'
- %template{ 'v-else' => '' }
- = render 'shared/icons/icon_resolve_discussion.svg'
-
- if can?(current_user, :award_emoji, note)
- if note.emoji_awardable?
.note-actions-item
diff --git a/app/views/shared/icons/_icon_resolve_discussion.svg b/app/views/shared/icons/_icon_resolve_discussion.svg
deleted file mode 100644
index 845562e9320..00000000000
--- a/app/views/shared/icons/_icon_resolve_discussion.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill-rule="evenodd"/><path d="M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_success_solid.svg b/app/views/shared/icons/_icon_status_success_solid.svg
deleted file mode 100644
index 0aac6d933e1..00000000000
--- a/app/views/shared/icons/_icon_status_success_solid.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z" fill-rule="evenodd"/></svg>