diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/pages/search/show/search.js | 16 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/search.scss | 16 | ||||
-rw-r--r-- | app/controllers/graphql_controller.rb | 4 | ||||
-rw-r--r-- | app/graphql/mutations/award_emojis/base.rb | 7 | ||||
-rw-r--r-- | app/graphql/mutations/design_management/move.rb | 2 | ||||
-rw-r--r-- | app/graphql/mutations/metrics/dashboard/annotations/create.rb | 17 | ||||
-rw-r--r-- | app/graphql/mutations/notes/base.rb | 5 | ||||
-rw-r--r-- | app/graphql/mutations/notes/create/base.rb | 9 | ||||
-rw-r--r-- | app/graphql/mutations/notes/destroy.rb | 6 | ||||
-rw-r--r-- | app/graphql/mutations/todos/base.rb | 7 | ||||
-rw-r--r-- | app/graphql/mutations/todos/restore_many.rb | 18 | ||||
-rw-r--r-- | app/views/projects/merge_requests/_merge_request.html.haml | 3 | ||||
-rw-r--r-- | app/views/search/_filter.html.haml | 24 | ||||
-rw-r--r-- | app/views/search/_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/shared/issuable/_reviewers.html.haml | 11 |
15 files changed, 100 insertions, 47 deletions
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js index 6ff74325a5e..2cd333f26e1 100644 --- a/app/assets/javascripts/pages/search/show/search.js +++ b/app/assets/javascripts/pages/search/show/search.js @@ -4,6 +4,7 @@ import { deprecatedCreateFlash as Flash } from '~/flash'; import Api from '~/api'; import { __ } from '~/locale'; import Project from '~/pages/projects/project'; +import { visitUrl } from '~/lib/utils/url_utility'; import refreshCounts from './refresh_counts'; import setHighlightClass from './highlight_blob_search_result'; @@ -86,6 +87,10 @@ export default class Search { $(document) .off('click', this.searchClear) .on('click', this.searchClear, this.clearSearchField.bind(this)); + + $('a.js-search-clear') + .off('click', this.clearSearchFilter) + .on('click', this.clearSearchFilter); } static submitSearch() { @@ -108,6 +113,17 @@ export default class Search { .focus(); } + // We need to manually follow the link on the anchors + // that have this event bound, as their `click` default + // behavior is prevented by the toggle logic. + /* eslint-disable-next-line class-methods-use-this */ + clearSearchFilter(ev) { + const $target = $(ev.currentTarget); + + visitUrl($target.href); + ev.stopPropagation(); + } + getProjectsData(term) { return new Promise(resolve => { if (this.groupId) { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 86caed329b4..a62e28a9b8a 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -198,6 +198,15 @@ input[type='checkbox']:hover { } } + .search-clear { + position: absolute; + right: 10px; + top: 9px; + padding: 0; + line-height: 0; + background: none; + border: 0; + } .search-icon { position: absolute; @@ -247,14 +256,7 @@ input[type='checkbox']:hover { } .search-clear { - position: absolute; - right: 10px; - top: 9px; - padding: 0; color: $gray-darkest; - line-height: 0; - background: none; - border: 0; &:hover, &:focus { diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 5edad410724..b5deed70380 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -48,6 +48,10 @@ class GraphqlController < ApplicationController render_error(exception.message, status: :unprocessable_entity) end + rescue_from ::GraphQL::CoercionError do |exception| + render_error(exception.message, status: :unprocessable_entity) + end + private def set_user_last_activity diff --git a/app/graphql/mutations/award_emojis/base.rb b/app/graphql/mutations/award_emojis/base.rb index 583744c3884..df6b883529e 100644 --- a/app/graphql/mutations/award_emojis/base.rb +++ b/app/graphql/mutations/award_emojis/base.rb @@ -6,7 +6,7 @@ module Mutations authorize :award_emoji argument :awardable_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Awardable], required: true, description: 'The global id of the awardable resource' @@ -23,7 +23,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Awardable].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end # Called by mutations methods after performing an authorization check diff --git a/app/graphql/mutations/design_management/move.rb b/app/graphql/mutations/design_management/move.rb index 43e2e542408..aed4cfec0fd 100644 --- a/app/graphql/mutations/design_management/move.rb +++ b/app/graphql/mutations/design_management/move.rb @@ -38,7 +38,7 @@ module Mutations # TODO: remove this line when the compatibility layer is removed # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 id = DesignID.coerce_isolated_input(id) - GitlabSchema.object_from_id(id) + GitlabSchema.find_by_gid(id) end def not_found(gid) diff --git a/app/graphql/mutations/metrics/dashboard/annotations/create.rb b/app/graphql/mutations/metrics/dashboard/annotations/create.rb index 6f316e76e2a..b064f55825f 100644 --- a/app/graphql/mutations/metrics/dashboard/annotations/create.rb +++ b/app/graphql/mutations/metrics/dashboard/annotations/create.rb @@ -18,12 +18,12 @@ module Mutations description: 'The created annotation' argument :environment_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Environment], required: false, description: 'The global id of the environment to add an annotation to' argument :cluster_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Clusters::Cluster], required: false, description: 'The global id of the cluster to add an annotation to' @@ -84,7 +84,7 @@ module Mutations end def find_object(id:) - GitlabSchema.object_from_id(id) + GitlabSchema.find_by_gid(id) end def annotation_create_params(args) @@ -96,7 +96,16 @@ module Mutations end def annotation_source(args) - annotation_source_id = args[:cluster_id] || args[:environment_id] + # TODO: remove these lines when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + annotation_source_id = if args[:cluster_id] + ::Types::GlobalIDType[::Clusters::Cluster].coerce_isolated_input(args[:cluster_id]) + else + ::Types::GlobalIDType[::Environment].coerce_isolated_input(args[:environment_id]) + end + + # TODO: uncomment following line once lines above are removed + # annotation_source_id = args[:cluster_id] || args[:environment_id] authorized_find!(id: annotation_source_id) end end diff --git a/app/graphql/mutations/notes/base.rb b/app/graphql/mutations/notes/base.rb index 31dabc0a660..d6d5f1e760d 100644 --- a/app/graphql/mutations/notes/base.rb +++ b/app/graphql/mutations/notes/base.rb @@ -11,7 +11,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) + # TODO: remove explicit coercion once compatibility layer has been removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Note].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end def check_object_is_noteable!(object) diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb index f081eac368e..530c15f0c10 100644 --- a/app/graphql/mutations/notes/create/base.rb +++ b/app/graphql/mutations/notes/create/base.rb @@ -9,7 +9,7 @@ module Mutations authorize :create_note argument :noteable_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Noteable], required: true, description: 'The global id of the resource to add a note to' @@ -42,6 +42,13 @@ module Mutations private + def find_object(id:) + # TODO: remove explicit coercion once compatibility layer has been removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Noteable].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) + end + def create_note_params(noteable, args) { noteable: noteable, diff --git a/app/graphql/mutations/notes/destroy.rb b/app/graphql/mutations/notes/destroy.rb index a81322bc9b7..83a91f07896 100644 --- a/app/graphql/mutations/notes/destroy.rb +++ b/app/graphql/mutations/notes/destroy.rb @@ -8,9 +8,9 @@ module Mutations authorize :admin_note argument :id, - GraphQL::ID_TYPE, - required: true, - description: 'The global id of the note to destroy' + ::Types::GlobalIDType[::Note], + required: true, + description: 'The global id of the note to destroy' def resolve(id:) note = authorized_find!(id: id) diff --git a/app/graphql/mutations/todos/base.rb b/app/graphql/mutations/todos/base.rb index 2a72019fbac..6db863796bc 100644 --- a/app/graphql/mutations/todos/base.rb +++ b/app/graphql/mutations/todos/base.rb @@ -6,7 +6,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Todo].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end def map_to_global_ids(ids) @@ -16,7 +19,7 @@ module Mutations end def to_global_id(id) - ::URI::GID.build(app: GlobalID.app, model_name: Todo.name, model_id: id, params: nil).to_s + Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s end end end diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb index c5e2750768c..ea5f5414134 100644 --- a/app/graphql/mutations/todos/restore_many.rb +++ b/app/graphql/mutations/todos/restore_many.rb @@ -8,7 +8,7 @@ module Mutations MAX_UPDATE_AMOUNT = 50 argument :ids, - [GraphQL::ID_TYPE], + [::Types::GlobalIDType[::Todo]], required: true, description: 'The global ids of the todos to restore (a maximum of 50 is supported at once)' @@ -37,24 +37,18 @@ module Mutations private def gids_of(ids) - ids.map { |id| ::URI::GID.build(app: GlobalID.app, model_name: Todo.name, model_id: id, params: nil).to_s } + ids.map { |id| Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s } end def model_ids_of(ids) ids.map do |gid| - parsed_gid = ::URI::GID.parse(gid) - parsed_gid.model_id.to_i if accessible_todo?(parsed_gid) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + gid = ::Types::GlobalIDType[::Todo].coerce_isolated_input(gid) + gid.model_id.to_i end.compact end - def accessible_todo?(gid) - gid.app == GlobalID.app && todo?(gid) - end - - def todo?(gid) - GlobalID.parse(gid)&.model_class&.ancestors&.include?(Todo) - end - def raise_too_many_todos_requested_error raise Gitlab::Graphql::Errors::ArgumentError, 'Too many todos requested.' end diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index ad0f4d03f9a..d55850b5673 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -55,6 +55,9 @@ - if merge_request.assignees.any? %li.d-flex = render 'shared/issuable/assignees', project: merge_request.project, issuable: merge_request + - if Feature.enabled?(:merge_request_reviewers, @project) && merge_request.reviewers.any? + %li.gl-display-flex.issuable-reviewers + = render 'shared/issuable/reviewers', project: merge_request.project, issuable: merge_request = render 'projects/merge_requests/approvals_count', merge_request: merge_request = render 'shared/issuable_meta_data', issuable: merge_request diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml index bee4aff605f..e7febd4638b 100644 --- a/app/views/search/_filter.html.haml +++ b/app/views/search/_filter.html.haml @@ -2,15 +2,14 @@ = hidden_field_tag :group_id, params[:group_id] - if params[:project_id].present? = hidden_field_tag :project_id, params[:project_id] -.dropdown.form-group.mb-lg-0.mx-lg-1 +.dropdown.form-group.mb-lg-0.mx-lg-1{ data: { testid: "group-filter" } } %label.d-block{ for: "dashboard_search_group" } = _("Group") - %button.dropdown-menu-toggle.js-search-group-dropdown.mt-0{ type: "button", id: "dashboard_search_group", data: { toggle: "dropdown", group_id: params[:group_id] } } - %span.dropdown-toggle-text - - if @group.present? - = @group.name - - else - = _("Any") + %button.dropdown-menu-toggle.gl-display-inline-flex.js-search-group-dropdown.gl-mt-0{ type: "button", id: "dashboard_search_group", data: { toggle: "dropdown", group_id: params[:group_id] } } + %span.dropdown-toggle-text.gl-flex-grow-1.str-truncated-100 + = @group&.name || _("Any") + - if @group.present? + = link_to sprite_icon("clear"), url_for(safe_params.except(:project_id, :group_id)), class: 'search-clear js-search-clear has-tooltip', title: _('Clear') = icon("chevron-down") .dropdown-menu.dropdown-select.dropdown-menu-selectable.dropdown-menu-right = dropdown_title(_("Filter results by group")) @@ -21,12 +20,11 @@ .dropdown.project-filter.form-group.mb-lg-0.mx-lg-1 %label.d-block{ for: "dashboard_search_project" } = _("Project") - %button.dropdown-menu-toggle.js-search-project-dropdown.mt-0{ type: "button", id: "dashboard_search_project", data: { toggle: "dropdown"} } - %span.dropdown-toggle-text - - if @project.present? - = @project.full_name - - else - = _("Any") + %button.dropdown-menu-toggle.gl-display-inline-flex.js-search-project-dropdown.gl-mt-0{ type: "button", id: "dashboard_search_project", data: { toggle: "dropdown", target: '.project-filter' } } + %span.dropdown-toggle-text.gl-flex-grow-1.str-truncated-100 + = @project&.full_name || _("Any") + - if @project.present? + = link_to sprite_icon("clear"), url_for(safe_params.except(:project_id)), class: 'search-clear js-search-clear has-tooltip', title: _('Clear') = icon("chevron-down") .dropdown-menu.dropdown-select.dropdown-menu-selectable.dropdown-menu-right = dropdown_title(_("Filter results by project")) diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml index 30ca9d3f5ab..c8fa016662f 100644 --- a/app/views/search/_form.html.haml +++ b/app/views/search/_form.html.haml @@ -10,7 +10,7 @@ .position-relative = search_field_tag :search, params[:search], placeholder: _("Search for projects, issues, etc."), class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false = sprite_icon('search', css_class: 'search-icon') - %button.search-clear.js-search-clear{ class: ("hidden" if !params[:search].present?), type: "button", tabindex: "-1" } + %button.search-clear.js-search-clear{ class: [("hidden" if params[:search].blank?), "has-tooltip"], type: "button", tabindex: "-1", title: _('Clear') } = sprite_icon('clear') %span.sr-only = _("Clear search") diff --git a/app/views/shared/issuable/_reviewers.html.haml b/app/views/shared/issuable/_reviewers.html.haml new file mode 100644 index 00000000000..8e66135a20b --- /dev/null +++ b/app/views/shared/issuable/_reviewers.html.haml @@ -0,0 +1,11 @@ +- max_render = 4 +- reviewers_rendering_overflow = issuable.reviewers.size > max_render +- render_count = reviewers_rendering_overflow ? max_render - 1 : max_render +- more_reviewers_count = issuable.reviewers.size - render_count + +- issuable.reviewers.take(render_count).each do |reviewer| # rubocop: disable CodeReuse/ActiveRecord + = link_to_member(@project, reviewer, name: false, title: _("Review requested from %{name}") % { name: reviewer.name}) + +- if more_reviewers_count > 0 + %span{ class: 'avatar-counter has-tooltip', data: { container: 'body', placement: 'bottom', 'line-type' => 'old' }, title: _("+%{more_reviewers_count} more reviewers") % { more_reviewers_count: more_reviewers_count} } + = _("+%{more_reviewers_count}") % { more_reviewers_count: more_reviewers_count} |