diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-06 06:08:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-06 06:08:18 +0300 |
commit | 53a3791717e8925078f074b976a561c7a72b1b22 (patch) | |
tree | 826aea342691595c3d3cdc716019a81e09c05873 /app | |
parent | a807e50ade2a78add0c13b75575203d7d99e8a4c (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb | 3 | ||||
-rw-r--r-- | app/graphql/types/work_items/widgets/labels_update_input_type.rb | 20 | ||||
-rw-r--r-- | app/helpers/appearances_helper.rb | 8 | ||||
-rw-r--r-- | app/helpers/wiki_helper.rb | 5 | ||||
-rw-r--r-- | app/models/wiki.rb | 116 | ||||
-rw-r--r-- | app/models/wiki_page.rb | 11 | ||||
-rw-r--r-- | app/services/concerns/work_items/widgetable_service.rb | 12 | ||||
-rw-r--r-- | app/services/issuable_base_service.rb | 5 | ||||
-rw-r--r-- | app/services/work_items/update_service.rb | 11 | ||||
-rw-r--r-- | app/services/work_items/widgets/base_service.rb | 5 | ||||
-rw-r--r-- | app/services/work_items/widgets/labels_service/update_service.rb | 15 | ||||
-rw-r--r-- | app/views/layouts/devise.html.haml | 4 | ||||
-rw-r--r-- | app/views/shared/wikis/pages.html.haml | 3 |
13 files changed, 188 insertions, 30 deletions
diff --git a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb index 1f90f394521..e42e59de78f 100644 --- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb +++ b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb @@ -30,6 +30,9 @@ module Mutations argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType, required: false, description: 'Input for start and due date widget.' + argument :labels_widget, ::Types::WorkItems::Widgets::LabelsUpdateInputType, + required: false, + description: 'Input for labels widget.' end end end diff --git a/app/graphql/types/work_items/widgets/labels_update_input_type.rb b/app/graphql/types/work_items/widgets/labels_update_input_type.rb new file mode 100644 index 00000000000..d38b8cefa63 --- /dev/null +++ b/app/graphql/types/work_items/widgets/labels_update_input_type.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Types + module WorkItems + module Widgets + class LabelsUpdateInputType < BaseInputObject + graphql_name 'WorkItemWidgetLabelsUpdateInput' + + argument :add_label_ids, [Types::GlobalIDType[::Label]], + required: false, + description: 'Global IDs of labels to be added to the work item.', + prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) } + argument :remove_label_ids, [Types::GlobalIDType[::Label]], + required: false, + description: 'Global IDs of labels to be removed from the work item.', + prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) } + end + end + end +end diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index 6dbd0f7bd7b..957c2afb6d2 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -14,7 +14,13 @@ module AppearancesHelper end def brand_image - image_tag(current_appearance.logo_path) if current_appearance&.logo? + image_tag(brand_image_path, alt: brand_title, class: 'gl-w-10') + end + + def brand_image_path + return current_appearance.logo_path if current_appearance&.logo? + + image_path('logo.svg') end def brand_text diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index d6ffd3deafe..c42e3a5ff99 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -65,7 +65,10 @@ module WikiHelper reversed_direction = direction == 'desc' ? 'asc' : 'desc' icon_class = direction == 'desc' ? 'highest' : 'lowest' - link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction), + link_options = { action: :pages, direction: reversed_direction } + link_options[:sort] = sort unless wiki.disable_sorting? + + link_to(wiki_path(wiki, **link_options), type: 'button', class: link_class, title: _('Sort direction')) do sprite_icon("sort-#{icon_class}") end diff --git a/app/models/wiki.rb b/app/models/wiki.rb index afdac86d9c7..11ff4333a07 100644 --- a/app/models/wiki.rb +++ b/app/models/wiki.rb @@ -173,7 +173,7 @@ class Wiki end def empty? - !repository_exists? || list_pages(limit: 1).empty? + !repository_exists? || list_page_paths.empty? end def exists? @@ -191,13 +191,11 @@ class Wiki # Returns an Array of GitLab WikiPage instances or an # empty Array if this Wiki has no pages. def list_pages(limit: 0, sort: nil, direction: DIRECTION_ASC, load_content: false) - wiki.list_pages( - limit: limit, - sort: sort, - direction_desc: direction == DIRECTION_DESC, - load_content: load_content - ).map do |page| - WikiPage.new(self, page) + if list_pages_with_repository_rpcs? + create_wiki_repository unless repository_exists? + list_pages_with_repository_rpcs(limit: limit, sort: sort, direction: direction, load_content: load_content) + else + list_pages_with_legacy_wiki_service(limit: limit, sort: sort, direction: direction, load_content: load_content) end end @@ -383,6 +381,10 @@ class Wiki false end + def disable_sorting? + list_pages_with_repository_rpcs? + end + private def multi_commit_options(action, message = nil, title = nil) @@ -452,14 +454,7 @@ class Wiki def find_matched_file(title, version) escaped_path = RE2::Regexp.escape(sluggified_title(title)) - # We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with - # Regexp.union. The result combination complicated modifiers: - # /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../ - # Regexp used by Gitaly is Go's Regexp package. It does not support those - # features. So, we have to compose another more-friendly regexp to pass to - # Gitaly side. - extension_regexp = Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|") - path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{extension_regexp})$") + path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{file_extension_regexp})$") matched_files = repository.search_files_by_regexp(path_regexp, version) return if matched_files.blank? @@ -487,7 +482,7 @@ class Wiki format = find_page_format(path) page = Gitlab::Git::WikiPage.new( - url_path: sluggified_title(path.sub(/\.[^.]+\z/, "")), + url_path: sluggified_title(strip_extension(path)), title: canonicalize_filename(path), format: format, path: sluggified_title(path), @@ -509,6 +504,93 @@ class Wiki Feature.enabled?(:wiki_find_page_with_normal_repository_rpcs, group, type: :development) end + + def file_extension_regexp + # We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with + # Regexp.union. The result combination complicated modifiers: + # /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../ + # Regexp used by Gitaly is Go's Regexp package. It does not support those + # features. So, we have to compose another more-friendly regexp to pass to + # Gitaly side. + Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|") + end + + def strip_extension(path) + path.sub(/\.[^.]+\z/, "") + end + + def list_pages_with_repository_rpcs? + group = + if container.is_a?(::Group) + container + else + container.group + end + + Feature.enabled?(:wiki_list_pages_with_normal_repository_rpcs, group, type: :development) + end + + def list_page_paths + return [] if repository.empty? + + path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)\\.(#{file_extension_regexp})$") + repository.search_files_by_regexp(path_regexp, default_branch) + end + + def list_pages_with_repository_rpcs(limit:, sort:, direction:, load_content:) + paths = list_page_paths + return [] if paths.empty? + + pages = paths.map do |path| + page = Gitlab::Git::WikiPage.new( + url_path: sluggified_title(strip_extension(path)), + title: canonicalize_filename(path), + format: find_page_format(path), + path: sluggified_title(path), + raw_data: '', + name: canonicalize_filename(path), + historical: false + ) + WikiPage.new(self, page) + end + sort_pages!(pages, sort, direction) + pages = pages.take(limit) if limit > 0 + fetch_pages_content!(pages) if load_content + + pages + end + + def list_pages_with_legacy_wiki_service(limit:, sort:, direction:, load_content:) + wiki.list_pages( + limit: limit, + sort: sort, + direction_desc: direction == DIRECTION_DESC, + load_content: load_content + ).map do |page| + WikiPage.new(self, page) + end + end + + # After migrating to normal repository RPCs, it's very expensive to sort the + # pages by created_at. We have to either ListLastCommitsForTree RPC call or + # N+1 LastCommitForPath. Either are efficient for a large repository. + # Therefore, we decide to sort the title only. + def sort_pages!(pages, _sort, direction) + # Sort by path to ensure the files inside a sub-folder are grouped and sorted together + pages.sort_by!(&:path) + pages.reverse! if direction == DIRECTION_DESC + end + + def fetch_pages_content!(pages) + blobs = + repository + .blobs_at(pages.map { |page| [default_branch, page.path] } ) + .to_h { |blob| [blob.path, blob.data] } + + pages.each do |page| + page.raw_content = blobs[page.path] + end + end end Wiki.prepend_mod_with('Wiki') diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 5cdd1fdadcb..ad07e0269f6 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -99,6 +99,13 @@ class WikiPage attributes[:content] ||= page&.text_data end + def raw_content=(content) + return if page.nil? + + page.raw_data = content + attributes[:content] = page.text_data + end + # The hierarchy of the directory this page is contained in. def directory wiki.page_title_and_dir(slug)&.last.to_s @@ -118,7 +125,7 @@ class WikiPage def version return unless persisted? - @version ||= @page.version + @version ||= @page.version || last_version end def path @@ -151,7 +158,7 @@ class WikiPage end def last_version - @last_version ||= versions(limit: 1).first + @last_version ||= wiki.repository.last_commit_for_path(wiki.default_branch, page.path) if page end def last_commit_sha diff --git a/app/services/concerns/work_items/widgetable_service.rb b/app/services/concerns/work_items/widgetable_service.rb index beb614c7b76..24ade9336b2 100644 --- a/app/services/concerns/work_items/widgetable_service.rb +++ b/app/services/concerns/work_items/widgetable_service.rb @@ -2,18 +2,22 @@ module WorkItems module WidgetableService - def execute_widgets(work_item:, callback:, widget_params: {}) + def execute_widgets(work_item:, callback:, widget_params: {}, service_params: {}) work_item.widgets.each do |widget| - widget_service(widget).try(callback, params: widget_params[widget.class.api_symbol]) + widget_service(widget, service_params).try(callback, params: widget_params[widget.class.api_symbol]) end end # rubocop:disable Gitlab/ModuleWithInstanceVariables - def widget_service(widget) + def widget_service(widget, service_params) @widget_services ||= {} return @widget_services[widget] if @widget_services.has_key?(widget) - @widget_services[widget] = widget_service_class(widget)&.new(widget: widget, current_user: current_user) + @widget_services[widget] = widget_service_class(widget)&.new( + widget: widget, + current_user: current_user, + service_params: service_params + ) end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index febb2f56e86..40c7742a3aa 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -266,6 +266,10 @@ class IssuableBaseService < ::BaseProjectService # To be overridden by subclasses end + def prepare_update_params(issuable) + # To be overridden by subclasses + end + def after_update(issuable) handle_description_updated(issuable) end @@ -277,6 +281,7 @@ class IssuableBaseService < ::BaseProjectService end def update(issuable) + prepare_update_params(issuable) handle_quick_actions(issuable) filter_params(issuable) diff --git a/app/services/work_items/update_service.rb b/app/services/work_items/update_service.rb index 2deb8c82741..e87a19422cb 100644 --- a/app/services/work_items/update_service.rb +++ b/app/services/work_items/update_service.rb @@ -26,6 +26,17 @@ module WorkItems private + def prepare_update_params(work_item) + execute_widgets( + work_item: work_item, + callback: :prepare_update_params, + widget_params: @widget_params, + service_params: params + ) + + super + end + def before_update(work_item, skip_spam_check: false) execute_widgets(work_item: work_item, callback: :before_update_callback, widget_params: @widget_params) diff --git a/app/services/work_items/widgets/base_service.rb b/app/services/work_items/widgets/base_service.rb index 37ed2bf4b05..1ff03a09f9f 100644 --- a/app/services/work_items/widgets/base_service.rb +++ b/app/services/work_items/widgets/base_service.rb @@ -5,12 +5,13 @@ module WorkItems class BaseService < ::BaseService WidgetError = Class.new(StandardError) - attr_reader :widget, :work_item, :current_user + attr_reader :widget, :work_item, :current_user, :service_params - def initialize(widget:, current_user:) + def initialize(widget:, current_user:, service_params: {}) @widget = widget @work_item = widget.work_item @current_user = current_user + @service_params = service_params end private diff --git a/app/services/work_items/widgets/labels_service/update_service.rb b/app/services/work_items/widgets/labels_service/update_service.rb new file mode 100644 index 00000000000..f00ea5c95ca --- /dev/null +++ b/app/services/work_items/widgets/labels_service/update_service.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module WorkItems + module Widgets + module LabelsService + class UpdateService < WorkItems::Widgets::BaseService + def prepare_update_params(params: {}) + return if params.blank? + + service_params.merge!(params.slice(:add_label_ids, :remove_label_ids)) + end + end + end + end +end diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 6650e07be2a..3532c6638ce 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -13,9 +13,9 @@ = render "layouts/flash" .mt-3 .col-sm-12.gl-text-center - %img.gl-w-10{ :alt => _("GitLab Logo"), :src => image_path('logo.svg') } + = brand_image %h1.mb-3.gl-font-size-h2 - = current_appearance&.title.presence || _('GitLab') + = brand_title - if current_appearance&.description? = brand_text = render_if_exists 'layouts/devise_help_text' diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml index 21d63a6db3d..79c5bb62f28 100644 --- a/app/views/shared/wikis/pages.html.haml +++ b/app/views/shared/wikis/pages.html.haml @@ -15,7 +15,8 @@ .dropdown.inline.wiki-sort-dropdown .btn-group{ role: 'group' } - = gl_redirect_listbox_tag wiki_sort_options, params[:sort], data: { right: true } + - unless @wiki.disable_sorting? + = gl_redirect_listbox_tag wiki_sort_options, params[:sort], data: { right: true } = wiki_sort_controls(@wiki, params[:sort], params[:direction]) %ul.wiki-pages-list.content-list |