diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/gfm_auto_complete.js | 34 | ||||
-rw-r--r-- | app/graphql/resolvers/ci/config_resolver.rb | 2 | ||||
-rw-r--r-- | app/graphql/resolvers/full_path_resolver.rb | 2 | ||||
-rw-r--r-- | app/graphql/types/query_type.rb | 2 | ||||
-rw-r--r-- | app/models/concerns/protected_ref.rb | 16 | ||||
-rw-r--r-- | app/models/group.rb | 1 | ||||
-rw-r--r-- | app/models/iteration.rb | 28 | ||||
-rw-r--r-- | app/models/iterations/cadence.rb | 14 | ||||
-rw-r--r-- | app/services/pages/legacy_storage_lease.rb | 9 |
9 files changed, 85 insertions, 23 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index d209a971c39..84007fd4510 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -266,6 +266,7 @@ class GfmAutoComplete { }, // eslint-disable-next-line no-template-curly-in-string insertTpl: '${atwho-at}${username}', + limit: 10, searchKey: 'search', alwaysHighlightFirst: true, skipSpecialCharacterTest: true, @@ -311,6 +312,31 @@ class GfmAutoComplete { return data; }, + sorter(query, items) { + if (!query) { + return items; + } + + const lowercaseQuery = query.toLowerCase(); + const members = items.slice(); + const { nameOrUsernameStartsWith, nameOrUsernameIncludes } = GfmAutoComplete.Members; + + return members.sort((a, b) => { + if (nameOrUsernameStartsWith(a, lowercaseQuery)) { + return -1; + } + if (nameOrUsernameStartsWith(b, lowercaseQuery)) { + return 1; + } + if (nameOrUsernameIncludes(a, lowercaseQuery)) { + return -1; + } + if (nameOrUsernameIncludes(b, lowercaseQuery)) { + return 1; + } + return 0; + }); + }, }, }); } @@ -772,6 +798,14 @@ GfmAutoComplete.Members = { title, )}${availabilityStatus}</small> ${icon}</li>`; }, + nameOrUsernameStartsWith(member, query) { + // `member.search` is a name:username string like `MargeSimpson msimpson` + return member.search.split(' ').some((name) => name.toLowerCase().startsWith(query)); + }, + nameOrUsernameIncludes(member, query) { + // `member.search` is a name:username string like `MargeSimpson msimpson` + return member.search.toLowerCase().includes(query); + }, }; GfmAutoComplete.Labels = { templateFunction(color, title) { diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb index 852bb47e215..f8670649e48 100644 --- a/app/graphql/resolvers/ci/config_resolver.rb +++ b/app/graphql/resolvers/ci/config_resolver.rb @@ -16,7 +16,7 @@ module Resolvers argument :content, GraphQL::STRING_TYPE, required: true, - description: "Contents of '.gitlab-ci.yml'." + description: "Contents of `.gitlab-ci.yml`." argument :dry_run, GraphQL::BOOLEAN_TYPE, required: false, diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb index d01cdf749a1..b5e90da78b2 100644 --- a/app/graphql/resolvers/full_path_resolver.rb +++ b/app/graphql/resolvers/full_path_resolver.rb @@ -7,7 +7,7 @@ module Resolvers prepended do argument :full_path, GraphQL::ID_TYPE, required: true, - description: 'The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".' + description: 'The full path of the project, group or namespace, e.g., `gitlab-org/gitlab-foss`.' end def model_by_full_path(model, full_path) diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 1d1ab4f2e17..95805d016f1 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -78,7 +78,7 @@ module Types field :issue, Types::IssueType, null: true, - description: 'Find an issue.' do + description: 'Find an Issue.' do argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue.' end diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb index cf23a27244c..65195a8d5aa 100644 --- a/app/models/concerns/protected_ref.rb +++ b/app/models/concerns/protected_ref.rb @@ -40,26 +40,20 @@ module ProtectedRef end def protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil) - all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level| + access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level| access_level.check_access(user) end end def developers_can?(action, ref, protected_refs: nil) - all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level| + access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level| access_level.access_level == Gitlab::Access::DEVELOPER end end - def all_matching_rules_allow?(ref, action:, protected_refs: nil, &block) - access_levels_groups = - self.matching(ref, protected_refs: protected_refs).map(&:"#{action}_access_levels") - - return false if access_levels_groups.blank? - - access_levels_groups.all? do |access_levels| - access_levels.any?(&block) - end + def access_levels_for_ref(ref, action:, protected_refs: nil) + self.matching(ref, protected_refs: protected_refs) + .flat_map(&:"#{action}_access_levels") end # Returns all protected refs that match the given ref name. diff --git a/app/models/group.rb b/app/models/group.rb index 1eaa4499eb5..739d90649f9 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -34,6 +34,7 @@ class Group < Namespace has_many :milestones has_many :iterations + has_many :iterations_cadences, class_name: 'Iterations::Cadence' has_many :services has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink' has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink' diff --git a/app/models/iteration.rb b/app/models/iteration.rb index 7a35bb1cd1f..012a062712f 100644 --- a/app/models/iteration.rb +++ b/app/models/iteration.rb @@ -16,6 +16,7 @@ class Iteration < ApplicationRecord belongs_to :project belongs_to :group + belongs_to :iterations_cadence, class_name: 'Iterations::Cadence', foreign_key: :iterations_cadence_id, inverse_of: :iterations has_internal_id :iid, scope: :project has_internal_id :iid, scope: :group @@ -26,6 +27,9 @@ class Iteration < ApplicationRecord validate :dates_do_not_overlap, if: :start_or_due_dates_changed? validate :future_date, if: :start_or_due_dates_changed?, unless: :skip_future_date_validation validate :no_project, unless: :skip_project_validation + validate :validate_group + + before_create :set_iterations_cadence scope :upcoming, -> { with_state(:upcoming) } scope :started, -> { with_state(:started) } @@ -135,6 +139,30 @@ class Iteration < ApplicationRecord errors.add(:project_id, s_("is not allowed. We do not currently support project-level iterations")) end + + # TODO: this method should be removed as part of https://gitlab.com/gitlab-org/gitlab/-/issues/296099 + def set_iterations_cadence + return if iterations_cadence + # For now we support only group iterations + # issue to clarify project iterations: https://gitlab.com/gitlab-org/gitlab/-/issues/299864 + return unless group + + self.iterations_cadence = group.iterations_cadences.first || create_default_cadence + end + + def create_default_cadence + cadence_title = "#{group.name} Iterations" + + Iterations::Cadence.create!(group: group, title: cadence_title, start_date: start_date) + end + + # TODO: remove this as part of https://gitlab.com/gitlab-org/gitlab/-/issues/296100 + def validate_group + return unless iterations_cadence + return if iterations_cadence.group_id == group_id + + errors.add(:group, s_('is not valid. The iteration group has to match the iteration cadence group.')) + end end Iteration.prepend_if_ee('EE::Iteration') diff --git a/app/models/iterations/cadence.rb b/app/models/iterations/cadence.rb new file mode 100644 index 00000000000..4f8e148d18f --- /dev/null +++ b/app/models/iterations/cadence.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class Iterations::Cadence < ApplicationRecord + self.table_name = 'iterations_cadences' + + belongs_to :group + has_many :iterations, foreign_key: :iterations_cadence_id, inverse_of: :iterations_cadence + + validates :title, presence: true + validates :start_date, presence: true + validates :group_id, presence: true + validates :active, presence: true + validates :automatic, presence: true +end diff --git a/app/services/pages/legacy_storage_lease.rb b/app/services/pages/legacy_storage_lease.rb index 3f42fc8c63b..1849def0183 100644 --- a/app/services/pages/legacy_storage_lease.rb +++ b/app/services/pages/legacy_storage_lease.rb @@ -8,15 +8,6 @@ module Pages LEASE_TIMEOUT = 1.hour - # override method from exclusive lease guard to guard it by feature flag - # TODO: just remove this method after testing this in production - # https://gitlab.com/gitlab-org/gitlab/-/issues/282464 - def try_obtain_lease - return yield unless Feature.enabled?(:pages_use_legacy_storage_lease, project, default_enabled: true) - - super - end - def lease_key "pages_legacy_storage:#{project.id}" end |