Skip to content

Commit 31ceb4e

Browse files
committed
Merge branch 'release/14.2' into dev
2 parents 091775e + 622c27e commit 31ceb4e

File tree

139 files changed

+1867
-1170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+1867
-1170
lines changed

Gemfile

-2
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,6 @@ gem "turbo-rails", "~> 2.0.0"
230230

231231
gem "httpx"
232232

233-
gem "gitlab_chronic_duration"
234-
235233
group :test do
236234
gem "launchy", "~> 3.0.0"
237235
gem "rack-test", "~> 2.1.0"

Gemfile.lock

-3
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,6 @@ GEM
556556
fuubar (2.5.1)
557557
rspec-core (~> 3.0)
558558
ruby-progressbar (~> 1.4)
559-
gitlab_chronic_duration (0.12.0)
560-
numerizer (~> 0.2)
561559
glob (0.4.0)
562560
globalid (1.2.1)
563561
activesupport (>= 6.1)
@@ -1208,7 +1206,6 @@ DEPENDENCIES
12081206
fog-aws
12091207
friendly_id (~> 5.5.0)
12101208
fuubar (~> 2.5.0)
1211-
gitlab_chronic_duration
12121209
gon (~> 6.4.0)
12131210
good_job (= 3.26.2)
12141211
google-apis-gmail_v1

app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.html.erb

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
) do |form|
2828
concat(render(Primer::Alpha::Dialog::Body.new(
2929
id: dialog_body_id, test_selector: dialog_body_id, aria: { label: title },
30+
classes: "FormControl-horizontalGroup--sm-vertical FormControl-horizontalGroup--center-aligned",
3031
style: "min-height: 300px"
3132
)) do
3233
render(Projects::CustomFields::CustomFieldMappingForm.new(form, project_custom_field: @project_custom_field))

app/contracts/settings/working_days_and_hours_params_contract.rb

+3-40
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,8 @@ class WorkingDaysAndHoursParamsContract < ::ParamsContract
3232

3333
validate :working_days_are_present
3434
validate :hours_per_day_are_present
35-
validate :days_per_week_are_present
36-
validate :days_per_month_are_present
3735
validate :durations_are_positive_values
3836
validate :durations_are_within_bounds
39-
validate :days_per_week_and_days_per_month_are_consistent
4037
validate :unique_job
4138

4239
protected
@@ -53,45 +50,19 @@ def hours_per_day_are_present
5350
end
5451
end
5552

56-
def days_per_week_are_present
57-
if days_per_week.blank?
58-
errors.add :base, :days_per_week_are_missing
59-
end
60-
end
61-
62-
def days_per_month_are_present
63-
if days_per_month.blank?
64-
errors.add :base, :days_per_month_are_missing
65-
end
66-
end
67-
6853
def durations_are_positive_values
6954
if hours_per_day &&
70-
days_per_week &&
71-
days_per_month &&
72-
any_duration_is_negative_or_zero?
55+
hours_per_day_is_negative_or_zero?
7356
errors.add :base, :durations_are_not_positive_numbers
7457
end
7558
end
7659

7760
def durations_are_within_bounds
7861
errors.add :base, :hours_per_day_is_out_of_bounds if hours_per_day.to_i > 24
79-
errors.add :base, :days_per_week_is_out_of_bounds if days_per_week.to_i > 7
80-
errors.add :base, :days_per_month_is_out_of_bounds if days_per_month.to_i > 31
8162
end
8263

83-
def any_duration_is_negative_or_zero?
84-
!hours_per_day.to_i.positive? ||
85-
!days_per_week.to_i.positive? ||
86-
!days_per_month.to_i.positive?
87-
end
88-
89-
def days_per_week_and_days_per_month_are_consistent
90-
if days_per_week &&
91-
days_per_month &&
92-
days_per_week.to_i != days_per_month.to_i / ChronicDuration::FULL_WEEKS_PER_MONTH
93-
errors.add :base, :days_per_week_and_days_per_month_are_inconsistent
94-
end
64+
def hours_per_day_is_negative_or_zero?
65+
!hours_per_day.to_i.positive?
9566
end
9667

9768
def unique_job
@@ -107,13 +78,5 @@ def working_days
10778
def hours_per_day
10879
params[:hours_per_day]
10980
end
110-
111-
def days_per_week
112-
params[:days_per_week]
113-
end
114-
115-
def days_per_month
116-
params[:days_per_month]
117-
end
11881
end
11982
end

app/controllers/admin/settings/project_custom_fields_controller.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class ProjectCustomFieldsController < ::Admin::SettingsController
4343
before_action :prepare_custom_option_position, only: %i(update create)
4444
before_action :find_custom_option, only: :delete_option
4545
before_action :project_custom_field_mappings_query, only: %i[project_mappings unlink]
46-
before_action :find_link_project_custom_field_mapping, only: :link
46+
before_action :find_custom_field_projects_to_link, only: :link
4747
before_action :find_unlink_project_custom_field_mapping, only: :unlink
4848
# rubocop:enable Rails/LexicallyScopedActionFilter
4949

@@ -75,15 +75,15 @@ def project_mappings
7575

7676
def link
7777
create_service = ProjectCustomFieldProjectMappings::BulkCreateService
78-
.new(user: current_user, project: @project, project_custom_field: @custom_field,
78+
.new(user: current_user, projects: @projects, project_custom_field: @custom_field,
7979
include_sub_projects: include_sub_projects?)
8080
.call
8181

8282
create_service.on_success { render_project_list }
8383

8484
create_service.on_failure do
8585
update_flash_message_via_turbo_stream(
86-
message: join_flash_messages(create_service.errors.full_messages),
86+
message: join_flash_messages(create_service.errors),
8787
full: true, dismiss_scheme: :hide, scheme: :danger
8888
)
8989
end
@@ -195,8 +195,8 @@ def find_unlink_project_custom_field_mapping
195195
respond_with_turbo_streams
196196
end
197197

198-
def find_link_project_custom_field_mapping
199-
@project = Project.find(permitted_params.project_custom_field_project_mapping[:project_id])
198+
def find_custom_field_projects_to_link
199+
@projects = Project.find(params.to_unsafe_h[:project_custom_field_project_mapping][:project_ids])
200200
rescue ActiveRecord::RecordNotFound
201201
update_flash_message_via_turbo_stream(
202202
message: t(:notice_file_not_found), full: true, dismiss_scheme: :hide, scheme: :danger
@@ -220,7 +220,7 @@ def drop_success_streams(call)
220220
end
221221

222222
def include_sub_projects?
223-
ActiveRecord::Type::Boolean.new.cast(permitted_params.project_custom_field_project_mapping[:include_sub_projects])
223+
ActiveRecord::Type::Boolean.new.cast(params.to_unsafe_h[:project_custom_field_project_mapping][:include_sub_projects])
224224
end
225225
end
226226
end

app/controllers/my_controller.rb

+12-6
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@ def account; end
6666

6767
def update_account
6868
write_settings
69-
70-
# If mail changed, expire all other sessions
71-
if @user.previous_changes['mail'] && ::Sessions::DropOtherSessionsService.call(@user, session)
72-
flash[:info] = "#{flash[:notice]} #{t(:notice_account_other_session_expired)}"
73-
flash.delete :notice
74-
end
7569
end
7670

7771
def settings; end
@@ -219,6 +213,7 @@ def write_settings
219213

220214
if result&.success
221215
flash[:notice] = notice_account_updated
216+
handle_email_changes
222217
else
223218
flash[:error] = error_account_update_failed(result)
224219
end
@@ -228,6 +223,17 @@ def write_settings
228223

229224
helper_method :has_tokens?
230225

226+
def handle_email_changes
227+
# If mail changed, expire all other sessions
228+
if @user.previous_changes['mail']
229+
Users::DropTokensService.new(current_user: @user).call!
230+
Sessions::DropOtherSessionsService.call!(@user, session)
231+
232+
flash[:info] = "#{flash[:notice]} #{t(:notice_account_other_session_expired)}"
233+
flash.delete :notice
234+
end
235+
end
236+
231237
def has_tokens?
232238
Setting.feeds_enabled? || Setting.rest_api_enabled? || current_user.ical_tokens.any?
233239
end

app/controllers/users_controller.rb

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ def show
7777
.where.not(project_id: nil)
7878
.where(id: Member.visible(current_user))
7979

80+
@groups = @user.groups.visible
81+
8082
if can_show_user?
8183
@events = events
8284
render layout: (can_manage_or_create_users? ? "admin" : "no_menu")

app/forms/projects/custom_fields/custom_field_mapping_form.rb

+6-5
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,23 @@
2828

2929
module Projects::CustomFields
3030
class CustomFieldMappingForm < ApplicationForm
31-
form do |f|
32-
f.group(layout: :horizontal) do |f_group|
33-
f_group.project_autocompleter(
31+
form do |form|
32+
form.group(layout: :horizontal) do |group|
33+
group.project_autocompleter(
3434
name: :id,
3535
label: Project.model_name.human,
3636
visually_hide_label: true,
3737
autocomplete_options: {
3838
openDirectly: false,
3939
focusDirectly: false,
40+
multiple: true,
4041
dropdownPosition: "bottom",
4142
disabledProjects: projects_with_custom_field_mapping,
42-
inputName: "project_custom_field_project_mapping[project_id]"
43+
inputName: "project_custom_field_project_mapping[project_ids]"
4344
}
4445
)
4546

46-
f_group.check_box(
47+
group.check_box(
4748
name: :include_sub_projects,
4849
label: I18n.t("projects.settings.project_custom_fields.new_project_mapping_form.include_sub_projects"),
4950
checked: false,

app/helpers/omniauth_helper.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ def omniauth_direct_login?
4242
# If this option is active /login will lead directly to the configured omniauth provider
4343
# and so will a click on 'Sign in' (as opposed to opening the drop down menu).
4444
def direct_login_provider
45-
Setting.omniauth_direct_login_provider
45+
Setting.omniauth_direct_login_provider.presence
4646
end
4747
end

app/models/work_package/exports/formatters/derived_remaining_hours.rb app/models/work_package/exports/formatters/compound_hours.rb

+14-9
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,30 @@
2727
#++
2828
module WorkPackage::Exports
2929
module Formatters
30-
class DerivedRemainingHours < ::Exports::Formatters::Default
30+
class CompoundHours < ::Exports::Formatters::Default
3131
def self.apply?(name, _export_format)
32-
%i[derived_remaining_time derived_remaining_hours].include?(name.to_sym)
32+
name.to_sym == key
3333
end
3434

3535
def format(work_package, **)
36-
formatted_derived_hours(work_package)
36+
hours = format_value(work_package.public_send(attribute))
37+
derived_hours = total_prefix(format_value(work_package.public_send(:"derived_#{attribute}")))
38+
39+
[hours, derived_hours].compact.join(" ").presence
40+
end
41+
42+
def format_value(value, _options = nil)
43+
DurationConverter.output(value)
3744
end
3845

3946
private
4047

41-
def formatted_hours(value)
42-
value.nil? ? nil : "#{value} #{I18n.t('export.units.hours')}"
48+
def attribute
49+
self.class.key
4350
end
4451

45-
def formatted_derived_hours(work_package)
46-
if (derived_estimated_value = work_package.derived_estimated_hours)
47-
formatted_hours(derived_estimated_value)
48-
end
52+
def total_prefix(value)
53+
value && "· Σ #{value}"
4954
end
5055
end
5156
end

app/models/work_package/exports/formatters/estimated_hours.rb

+1-31
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,7 @@
2727
#++
2828
module WorkPackage::Exports
2929
module Formatters
30-
class EstimatedHours < ::Exports::Formatters::Default
31-
def self.apply?(name, _export_format)
32-
name.to_sym == :estimated_hours
33-
end
34-
35-
def format(work_package, **)
36-
estimated_hours = formatted_hours(work_package.estimated_hours)
37-
derived_hours = formatted_derived_hours(work_package)
38-
39-
if estimated_hours.nil? || derived_hours.nil?
40-
return estimated_hours || derived_hours
41-
end
42-
43-
"#{estimated_hours} #{derived_hours}"
44-
end
45-
46-
def format_value(value, _options)
47-
formatted_hours(value)
48-
end
49-
50-
private
51-
52-
def formatted_hours(value)
53-
value.nil? ? nil : "#{value} #{I18n.t('export.units.hours')}"
54-
end
55-
56-
def formatted_derived_hours(work_package)
57-
if (derived_estimated_value = work_package.derived_estimated_hours)
58-
"· Σ #{formatted_hours(derived_estimated_value)}"
59-
end
60-
end
30+
class EstimatedHours < ::WorkPackage::Exports::Formatters::CompoundHours
6131
end
6232
end
6333
end

app/models/work_package/exports/formatters/hours.rb

+2-8
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,11 @@ module WorkPackage::Exports
2929
module Formatters
3030
class Hours < ::Exports::Formatters::Default
3131
def self.apply?(name, export_format)
32-
%i[remaining_hours spent_hours].include?(name.to_sym) && export_format == :pdf
32+
name.to_sym == :spent_hours && export_format == :pdf
3333
end
3434

3535
def format_value(value, _options)
36-
formatted_hours(value)
37-
end
38-
39-
private
40-
41-
def formatted_hours(value)
42-
value.nil? ? "" : "#{value} #{I18n.t('export.units.hours')}"
36+
DurationConverter.output(value)
4337
end
4438
end
4539
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) 2012-2024 the OpenProject GmbH
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License version 3.
7+
#
8+
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
# Copyright (C) 2006-2013 Jean-Philippe Lang
10+
# Copyright (C) 2010-2013 the ChiliProject Team
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
#
26+
# See COPYRIGHT and LICENSE files for more details.
27+
#++
28+
module WorkPackage::Exports
29+
module Formatters
30+
class RemainingHours < ::WorkPackage::Exports::Formatters::CompoundHours
31+
end
32+
end
33+
end

0 commit comments

Comments
 (0)