diff options
Diffstat (limited to 'app')
21 files changed, 133 insertions, 102 deletions
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index a933370427c..7a92aed720d 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -10,7 +10,7 @@ import { } from '@gitlab/ui'; import { mapActions, mapState } from 'vuex'; import { isListDraggable } from '~/boards/boards_util'; -import { isScopedLabel } from '~/lib/utils/common_utils'; +import { isScopedLabel, parseBoolean } from '~/lib/utils/common_utils'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { n__, s__, __ } from '~/locale'; import sidebarEventHub from '~/sidebar/event_hub'; @@ -69,7 +69,7 @@ export default { }, }, computed: { - ...mapState(['activeId']), + ...mapState(['activeId', 'isEpicBoard']), isLoggedIn() { return Boolean(this.currentUserId); }, @@ -97,11 +97,14 @@ export default { showListDetails() { return !this.list.collapsed || !this.isSwimlanesHeader; }, - issuesCount() { + itemsCount() { return this.list.issuesCount; }, - issuesTooltipLabel() { - return n__(`%d issue`, `%d issues`, this.issuesCount); + countIcon() { + return 'issues'; + }, + itemsTooltipLabel() { + return n__(`%d issue`, `%d issues`, this.itemsCount); }, chevronTooltip() { return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse; @@ -110,7 +113,7 @@ export default { return this.list.collapsed ? 'chevron-down' : 'chevron-right'; }, isNewIssueShown() { - return this.listType === ListType.backlog || this.showListHeaderButton; + return (this.listType === ListType.backlog || this.showListHeaderButton) && !this.isEpicBoard; }, isSettingsShown() { return ( @@ -131,8 +134,14 @@ export default { return !this.disabled && isListDraggable(this.list); }, }, + created() { + const localCollapsed = parseBoolean(localStorage.getItem(`${this.uniqueKey}.collapsed`)); + if ((!this.isLoggedIn || this.isEpicBoard) && localCollapsed) { + this.toggleListCollapsed({ listId: this.list.id, collapsed: true }); + } + }, methods: { - ...mapActions(['updateList', 'setActiveId']), + ...mapActions(['updateList', 'setActiveId', 'toggleListCollapsed']), openSidebarSettings() { if (this.activeId === inactiveId) { sidebarEventHub.$emit('sidebar.closeAll'); @@ -148,10 +157,10 @@ export default { eventHub.$emit(`toggle-issue-form-${this.list.id}`); }, toggleExpanded() { - // eslint-disable-next-line vue/no-mutating-props - this.list.collapsed = !this.list.collapsed; + const collapsed = !this.list.collapsed; + this.toggleListCollapsed({ listId: this.list.id, collapsed }); - if (!this.isLoggedIn) { + if (!this.isLoggedIn || this.isEpicBoard) { this.addToLocalStorage(); } else { this.updateListFunction(); @@ -163,7 +172,7 @@ export default { }, addToLocalStorage() { if (AccessorUtilities.isLocalStorageAccessSafe()) { - localStorage.setItem(`${this.uniqueKey}.expanded`, !this.list.collapsed); + localStorage.setItem(`${this.uniqueKey}.collapsed`, this.list.collapsed); } }, updateListFunction() { @@ -203,6 +212,7 @@ export default { class="board-title-caret no-drag gl-cursor-pointer" category="tertiary" size="small" + data-testid="board-title-caret" @click="toggleExpanded" /> <!-- EE start --> @@ -301,11 +311,11 @@ export default { <div v-if="list.maxIssueCount !== 0"> • <gl-sprintf :message="__('%{issuesSize} with a limit of %{maxIssueCount}')"> - <template #issuesSize>{{ issuesTooltipLabel }}</template> + <template #issuesSize>{{ itemsTooltipLabel }}</template> <template #maxIssueCount>{{ list.maxIssueCount }}</template> </gl-sprintf> </div> - <div v-else>• {{ issuesTooltipLabel }}</div> + <div v-else>• {{ itemsTooltipLabel }}</div> <div v-if="weightFeatureAvailable"> • <gl-sprintf :message="__('%{totalWeight} total weight')"> @@ -323,13 +333,13 @@ export default { }" > <span class="gl-display-inline-flex"> - <gl-tooltip :target="() => $refs.issueCount" :title="issuesTooltipLabel" /> - <span ref="issueCount" class="issue-count-badge-count"> - <gl-icon class="gl-mr-2" name="issues" /> - <issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" /> + <gl-tooltip :target="() => $refs.itemCount" :title="itemsTooltipLabel" /> + <span ref="itemCount" class="issue-count-badge-count"> + <gl-icon class="gl-mr-2" :name="countIcon" /> + <issue-count :issues-size="itemsCount" :max-issue-count="list.maxIssueCount" /> </span> <!-- EE start --> - <template v-if="weightFeatureAvailable"> + <template v-if="weightFeatureAvailable && !isEpicBoard"> <gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" /> <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3"> <gl-icon class="gl-mr-2" name="weight" /> diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue index 7e3f36c8a17..73ec008c2b6 100644 --- a/app/assets/javascripts/boards/components/issue_due_date.vue +++ b/app/assets/javascripts/boards/components/issue_due_date.vue @@ -86,7 +86,11 @@ export default { <template> <span> <span ref="issueDueDate" :class="cssClass" class="board-card-info card-number"> - <gl-icon :class="{ 'text-danger': isPastDue }" class="board-card-info-icon" name="calendar" /> + <gl-icon + :class="{ 'text-danger': isPastDue }" + class="board-card-info-icon gl-mr-2" + name="calendar" + /> <time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{ body }}</time> diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue index 42d187b9b40..1ab7deebfaf 100644 --- a/app/assets/javascripts/boards/components/issue_time_estimate.vue +++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue @@ -37,7 +37,7 @@ export default { <template> <span> <span ref="issueTimeEstimate" class="board-card-info card-number"> - <gl-icon name="hourglass" class="board-card-info-icon" /> + <gl-icon name="hourglass" class="board-card-info-icon gl-mr-2" /> <time class="board-card-info-text">{{ timeEstimate }}</time> </span> <gl-tooltip diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index e0460f18dd1..f5f2bd6b74c 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -256,6 +256,10 @@ export default { }); }, + toggleListCollapsed: ({ commit }, { listId, collapsed }) => { + commit(types.TOGGLE_LIST_COLLAPSED, { listId, collapsed }); + }, + removeList: ({ state, commit }, listId) => { const listsBackup = { ...state.boardLists }; diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js index 2a748d122d9..e7c034fb087 100644 --- a/app/assets/javascripts/boards/stores/mutation_types.js +++ b/app/assets/javascripts/boards/stores/mutation_types.js @@ -14,6 +14,7 @@ export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS'; export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR'; export const MOVE_LIST = 'MOVE_LIST'; export const UPDATE_LIST_FAILURE = 'UPDATE_LIST_FAILURE'; +export const TOGGLE_LIST_COLLAPSED = 'TOGGLE_LIST_COLLAPSED'; export const REMOVE_LIST = 'REMOVE_LIST'; export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE'; export const REQUEST_ITEMS_FOR_LIST = 'REQUEST_ITEMS_FOR_LIST'; diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 5b8bf5b5357..99a3f3c8f86 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -105,6 +105,10 @@ export default { Vue.set(state, 'boardLists', backupList); }, + [mutationTypes.TOGGLE_LIST_COLLAPSED]: (state, { listId, collapsed }) => { + Vue.set(state.boardLists[listId], 'collapsed', collapsed); + }, + [mutationTypes.REMOVE_LIST]: (state, listId) => { Vue.delete(state.boardLists, listId); }, diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue index a59a8afa4de..fd35c16ab63 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue @@ -200,9 +200,9 @@ export default { <gl-form-input id="fork-name" v-model="fork.name" data-testid="fork-name-input" required /> </gl-form-group> - <div class="gl-display-flex"> - <div class="gl-w-half"> - <gl-form-group label="Project URL" label-for="fork-url" class="gl-pr-2"> + <div class="gl-md-display-flex"> + <div class="gl-flex-basis-half"> + <gl-form-group label="Project URL" label-for="fork-url" class="gl-md-mr-3"> <gl-form-input-group> <template #prepend> <gl-input-group-text> @@ -225,8 +225,8 @@ export default { </gl-form-input-group> </gl-form-group> </div> - <div class="gl-w-half"> - <gl-form-group label="Project slug" label-for="fork-slug" class="gl-pl-2"> + <div class="gl-flex-basis-half"> + <gl-form-group label="Project slug" label-for="fork-slug" class="gl-md-ml-3"> <gl-form-input id="fork-slug" v-model="fork.slug" diff --git a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue index 18a7d4ad218..e6aa3be0371 100644 --- a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue +++ b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue @@ -55,7 +55,12 @@ export default { > <div class="d-flex align-items-center"> <gl-icon :size="16" :name="option.icon" /> - <span class="font-weight-bold ml-1 js-visibility-option">{{ option.label }}</span> + <span + class="font-weight-bold ml-1 js-visibility-option" + data-qa-selector="visibility_content" + :data-qa-visibility="option.label" + >{{ option.label }}</span + > </div> <template #help>{{ isProjectSnippet && option.description_project diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss index 20ff78d32d3..e55654e84d8 100644 --- a/app/assets/stylesheets/_page_specific_files.scss +++ b/app/assets/stylesheets/_page_specific_files.scss @@ -35,5 +35,4 @@ @import './pages/sherlock'; @import './pages/storage_quota'; @import './pages/tree'; -@import './pages/trials'; @import './pages/users'; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 089f130843f..1aa4177c902 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -830,8 +830,8 @@ $ci-variable-remove-button-width: calc(1em + #{2 * $gl-padding}); /* GitLab Plans */ -$gl-gold-plan: #d4af37; -$gl-silver-plan: #91a1ab; +$gl-ultimate-plan: #d4af37; +$gl-premium-plan: #91a1ab; $gl-bronze-plan: #cd7f32; /* diff --git a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss index b148cc8f0e7..0d40159f6de 100644 --- a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss +++ b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss @@ -339,3 +339,19 @@ display: inline; } } + +.gl-select2-html5-required-fix { + .select2-container { + + .select2 { + @include gl-opacity-0; + @include gl-border-0; + @include gl-bg-none; + @include gl-bg-transparent; + display: block !important; + width: 1px; + height: 1px; + z-index: -1; + margin: -3px auto 0; + } + } +} diff --git a/app/assets/stylesheets/pages/trials.scss b/app/assets/stylesheets/pages/trials.scss deleted file mode 100644 index 55f323b7df7..00000000000 --- a/app/assets/stylesheets/pages/trials.scss +++ /dev/null @@ -1,15 +0,0 @@ -/* -* A CSS cross-browser fix for Select2 failire to display HTML5 required warnings -* MR link https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22716 -*/ -.gl-select2-html5-required-fix div.select2-container+select.select2 { - @include gl-opacity-0; - @include gl-border-0; - @include gl-bg-none; - @include gl-bg-transparent; - display: block !important; - width: 1px; - height: 1px; - z-index: -1; - margin: -3px auto 0; -} diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss index d49b58df69b..024162eba3e 100644 --- a/app/assets/stylesheets/utilities.scss +++ b/app/assets/stylesheets/utilities.scss @@ -117,6 +117,7 @@ flex-basis: 25%; } +// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1168 .gl-md-ml-3 { @media (min-width: $breakpoint-md) { margin-left: $gl-spacing-scale-3; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 7f7d38a09c5..7c6a444ce7a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -237,7 +237,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController [ *::ApplicationSettingsHelper.visible_attributes, *::ApplicationSettingsHelper.external_authorization_service_attributes, - *ApplicationSetting.repository_storages_weighted_attributes, *ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym }, :lets_encrypt_notification_email, :lets_encrypt_terms_of_service_accepted, @@ -248,8 +247,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :default_branch_name, disabled_oauth_sign_in_sources: [], import_sources: [], - repository_storages: [], - restricted_visibility_levels: [] + restricted_visibility_levels: [], + repository_storages_weighted: {} ] end diff --git a/app/graphql/mutations/boards/issues/issue_move_list.rb b/app/graphql/mutations/boards/issues/issue_move_list.rb index 6df4250fc67..096ac89db1c 100644 --- a/app/graphql/mutations/boards/issues/issue_move_list.rb +++ b/app/graphql/mutations/boards/issues/issue_move_list.rb @@ -5,35 +5,38 @@ module Mutations module Issues class IssueMoveList < Mutations::Issues::Base graphql_name 'IssueMoveList' + BoardGID = ::Types::GlobalIDType[::Board] + ListID = ::GraphQL::ID_TYPE + IssueID = ::GraphQL::ID_TYPE - argument :board_id, GraphQL::ID_TYPE, - required: true, - loads: Types::BoardType, - description: 'Global ID of the board that the issue is in.' + argument :board_id, BoardGID, + required: true, + loads: Types::BoardType, + description: 'Global ID of the board that the issue is in.' argument :project_path, GraphQL::ID_TYPE, - required: true, - description: 'Project the issue to mutate is in.' + required: true, + description: 'Project the issue to mutate is in.' argument :iid, GraphQL::STRING_TYPE, - required: true, - description: 'IID of the issue to mutate.' + required: true, + description: 'IID of the issue to mutate.' - argument :from_list_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of the board list that the issue will be moved from.' + argument :from_list_id, ListID, + required: false, + description: 'ID of the board list that the issue will be moved from.' - argument :to_list_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of the board list that the issue will be moved to.' + argument :to_list_id, ListID, + required: false, + description: 'ID of the board list that the issue will be moved to.' - argument :move_before_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of issue that should be placed before the current issue.' + argument :move_before_id, IssueID, + required: false, + description: 'ID of issue that should be placed before the current issue.' - argument :move_after_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of issue that should be placed after the current issue.' + argument :move_after_id, IssueID, + required: false, + description: 'ID of issue that should be placed after the current issue.' def ready?(**args) if move_arguments(args).blank? diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 244238e246d..551e08d1e31 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -37,13 +37,8 @@ module ApplicationSettingsHelper end def storage_weights - ApplicationSetting.repository_storages_weighted_attributes.map do |attribute| - storage = attribute.to_s.delete_prefix('repository_storages_weighted_') - { - name: attribute, - label: storage, - value: @application_setting.repository_storages_weighted[storage] || 0 - } + Gitlab.config.repositories.storages.keys.each_with_object(OpenStruct.new) do |storage, weights| + weights[storage.to_sym] = @application_setting.repository_storages_weighted[storage] || 0 end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 33c058dab96..44eb2fefb3f 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -25,10 +25,6 @@ class ApplicationSetting < ApplicationRecord alias_attribute :instance_group_id, :instance_administrators_group_id alias_attribute :instance_administrators_group, :instance_group - def self.repository_storages_weighted_attributes - @repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze - end - def self.kroki_formats_attributes { blockdiag: { @@ -44,7 +40,6 @@ class ApplicationSetting < ApplicationRecord end store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true - store_accessor :repository_storages_weighted, *Gitlab.config.repositories.storages.keys, prefix: true # Include here so it can override methods from # `add_authentication_token_field` @@ -58,8 +53,9 @@ class ApplicationSetting < ApplicationRecord serialize :domain_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize serialize :domain_denylist, Array # rubocop:disable Cop/ActiveRecordSerialize serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize - serialize :asset_proxy_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize + # See https://gitlab.com/gitlab-org/gitlab/-/issues/300916 + serialize :asset_proxy_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize serialize :asset_proxy_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize cache_markdown_field :sign_in_text @@ -502,6 +498,7 @@ class ApplicationSetting < ApplicationRecord inclusion: { in: [true, false], message: _('must be a boolean value') } before_validation :ensure_uuid! + before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed? before_save :ensure_runners_registration_token before_save :ensure_health_check_access_token @@ -582,12 +579,6 @@ class ApplicationSetting < ApplicationRecord recaptcha_enabled || login_recaptcha_protection_enabled end - repository_storages_weighted_attributes.each do |attribute| - define_method :"#{attribute}=" do |value| - super(value.to_i) - end - end - kroki_formats_attributes.keys.each do |key| define_method :"kroki_formats_#{key}=" do |value| super(::Gitlab::Utils.to_boolean(value)) diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 2911ae6b1c8..731a3b5fed8 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -280,21 +280,22 @@ module ApplicationSettingImplementation self.notes_create_limit_allowlist = strings_to_array(values).map(&:downcase) end - def asset_proxy_allowlist=(values) + def asset_proxy_whitelist=(values) values = strings_to_array(values) if values.is_a?(String) # make sure we always allow the running host values << Gitlab.config.gitlab.host unless values.include?(Gitlab.config.gitlab.host) - self[:asset_proxy_allowlist] = values + self[:asset_proxy_whitelist] = values end + alias_method :asset_proxy_allowlist=, :asset_proxy_whitelist= - def repository_storages - Array(read_attribute(:repository_storages)) + def asset_proxy_allowlist + read_attribute(:asset_proxy_whitelist) end - def repository_storages_weighted - read_attribute(:repository_storages_weighted) + def repository_storages + Array(read_attribute(:repository_storages)) end def commit_email_hostname @@ -328,9 +329,10 @@ module ApplicationSettingImplementation def normalized_repository_storage_weights strong_memoize(:normalized_repository_storage_weights) do - weights_total = repository_storages_weighted.values.reduce(:+) + repository_storages_weights = repository_storages_weighted.slice(*Gitlab.config.repositories.storages.keys) + weights_total = repository_storages_weights.values.reduce(:+) - repository_storages_weighted.transform_values do |w| + repository_storages_weights.transform_values do |w| next w if weights_total == 0 w.to_f / weights_total @@ -468,16 +470,20 @@ module ApplicationSettingImplementation invalid.empty? end + def coerce_repository_storages_weighted + repository_storages_weighted.transform_values!(&:to_i) + end + def check_repository_storages_weighted invalid = repository_storages_weighted.keys - Gitlab.config.repositories.storages.keys - errors.add(:repository_storages_weighted, "can't include: %{invalid_storages}" % { invalid_storages: invalid.join(", ") }) unless + errors.add(:repository_storages_weighted, _("can't include: %{invalid_storages}") % { invalid_storages: invalid.join(", ") }) unless invalid.empty? repository_storages_weighted.each do |key, val| next unless val.present? - errors.add(:"repository_storages_weighted_#{key}", "value must be an integer") unless val.is_a?(Integer) - errors.add(:"repository_storages_weighted_#{key}", "value must be between 0 and 100") unless val.between?(0, 100) + errors.add(:repository_storages_weighted, _("value for '%{storage}' must be an integer") % { storage: key }) unless val.is_a?(Integer) + errors.add(:repository_storages_weighted, _("value for '%{storage}' must be between 0 and 100") % { storage: key }) unless val.between?(0, 100) end end diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb index 5e5c8ae2177..7792b811b4e 100644 --- a/app/services/application_settings/update_service.rb +++ b/app/services/application_settings/update_service.rb @@ -6,7 +6,7 @@ module ApplicationSettings attr_reader :params, :application_setting - MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_allowlist).freeze + MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_whitelist).freeze def execute result = update_settings diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 217679e733c..4bc7823faaa 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -31,6 +31,7 @@ module MergeRequests old_mentioned_users = old_associations.fetch(:mentioned_users, []) old_assignees = old_associations.fetch(:assignees, []) old_reviewers = old_associations.fetch(:reviewers, []) + old_timelogs = old_associations.fetch(:timelogs, []) changed_fields = merge_request.previous_changes.keys resolve_todos(merge_request, old_labels, old_assignees, old_reviewers) @@ -48,6 +49,7 @@ module MergeRequests track_title_and_desc_edits(changed_fields) track_discussion_lock_toggle(merge_request, changed_fields) + track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields) notify_if_labels_added(merge_request, old_labels) notify_if_mentions_added(merge_request, old_mentioned_users) @@ -106,6 +108,11 @@ module MergeRequests end end + def track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields) + merge_request_activity_counter.track_time_estimate_changed_action(user: current_user) if changed_fields.include?('time_estimate') + merge_request_activity_counter.track_time_spent_changed_action(user: current_user) if old_timelogs != merge_request.timelogs + end + def notify_if_labels_added(merge_request, old_labels) added_labels = merge_request.labels - old_labels diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml index 0862d1bf0b6..437189cf47f 100644 --- a/app/views/admin/application_settings/_repository_storage.html.haml +++ b/app/views/admin/application_settings/_repository_storage.html.haml @@ -18,8 +18,9 @@ = _('Enter weights for storages for new repositories.') = link_to sprite_icon('question-o'), help_page_path('administration/repository_storage_paths') .form-check - - storage_weights.each do |attribute| - = f.text_field attribute[:name], class: 'form-text-input', value: attribute[:value] - = f.label attribute[:label], attribute[:label], class: 'label-bold form-check-label' - %br + = f.fields_for :repository_storages_weighted, storage_weights do |storage_form| + - Gitlab.config.repositories.storages.keys.each do |storage| + = storage_form.text_field storage, class: 'form-text-input' + = storage_form.label storage, storage, class: 'label-bold form-check-label' + %br = f.submit _('Save changes'), class: "gl-button btn btn-success qa-save-changes-button" |