Skip to content

Commit 05afd6d

Browse files
committed
Merge branch 'release/15.1' into dev
2 parents d0fe86f + 0b31ada commit 05afd6d

File tree

19 files changed

+173
-36
lines changed

19 files changed

+173
-36
lines changed

app/components/work_package_relations_tab/add_work_package_child_dialog_component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
size: :large,
44
id: DIALOG_ID)) do |d|
55
d.with_header(variant: :large)
6-
d.with_body(classes: "Overlay-body_autocomplete_height") do
6+
d.with_body(classes: body_classes) do
77
render(WorkPackageRelationsTab::AddWorkPackageChildFormComponent.new(
88
work_package: @work_package
99
))

app/components/work_package_relations_tab/add_work_package_child_dialog_component.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,8 @@ def dialog_title
5151
child_label = t("#{I18N_NAMESPACE}.relations.label_child_singular")
5252
t("#{I18N_NAMESPACE}.label_add_x", x: child_label)
5353
end
54+
55+
def body_classes
56+
"Overlay-body_autocomplete_height"
57+
end
5458
end

app/components/work_package_relations_tab/work_package_relation_dialog_component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
size: :large,
44
id: DIALOG_ID)) do |d|
55
d.with_header(variant: :large)
6-
d.with_body(classes: "Overlay-body_autocomplete_height") do
6+
d.with_body(classes: body_classes) do
77
render(WorkPackageRelationsTab::WorkPackageRelationFormComponent.new(
88
work_package: @work_package,
99
relation: @relation

app/components/work_package_relations_tab/work_package_relation_dialog_component.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ def dialog_title
5858
t("#{I18N_NAMESPACE}.label_add_x", x: relation_label)
5959
end
6060
end
61+
62+
def body_classes
63+
@relation.persisted? ? nil : "Overlay-body_autocomplete_height"
64+
end
6165
end

app/helpers/journals_helper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def back_to_activity_page_url(activity_page)
3838
in ["users", user_id]
3939
user_url(user_id)
4040
in ["work_packages", work_package_id]
41-
work_package_url(work_package_id)
41+
# Sometimes the parameter provided is erroneous (having an extra ') for unknown reasons.
42+
work_package_url(work_package_id.chomp("'"))
4243
else
4344
nil
4445
end

config/initializers/03-db_check.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
if (db_config = ActiveRecord::Base.configurations.configs_for(env_name: env)[0]) &&
3232
db_config.configuration_hash["adapter"]&.start_with?("mysql")
33-
warn <<~ERROR
33+
abort <<~ERROR
3434
======= INCOMPATIBLE DATABASE DETECTED =======
3535
Your database is set up for use with a MySQL or MySQL-compatible variant.
3636
This installation of OpenProject no longer supports these variants.
@@ -45,8 +45,4 @@
4545
4646
==============================================
4747
ERROR
48-
49-
# rubocop:disable Rails/Exit
50-
Kernel.exit 1
51-
# rubocop:enable Rails/Exit
5248
end
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) 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+
29+
if ENV["OPENPROJECT_SKIP_DB_ENCODING_CHECK"].blank?
30+
icu_incompatible_encodings = %w[
31+
EUC_JIS_2004
32+
LATIN10
33+
MULE_INTERNAL
34+
SQL_ASCII
35+
WIN874
36+
]
37+
38+
database_encoding = ActiveRecord::Base.connection.select_value("SHOW SERVER_ENCODING")
39+
40+
if database_encoding.in?(icu_incompatible_encodings)
41+
abort <<~ERROR
42+
INCOMPATIBLE DATABASE ENCODING DETECTED
43+
44+
Your database encoding is #{database_encoding}, which is incompatible with ICU
45+
collation used in OpenProject v15.
46+
47+
Please check the instructions on how to change database encoding:
48+
https://www.openproject.org/docs/installation-and-operations/misc/changing-database-encoding/
49+
50+
This check can be skipped by setting environment variable OPENPROJECT_SKIP_DB_ENCODING_CHECK=true
51+
ERROR
52+
end
53+
end

db/migrate/20240920152544_set_versions_name_collation.rb

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
class SetVersionsNameCollation < ActiveRecord::Migration[7.1]
22
def up
3-
execute <<-SQL.squish
4-
CREATE COLLATION IF NOT EXISTS versions_name (provider = icu, locale = 'und-u-kn-true');
5-
SQL
3+
begin
4+
execute <<-SQL.squish
5+
CREATE COLLATION IF NOT EXISTS versions_name (provider = icu, locale = 'und-u-kn-true');
6+
SQL
7+
rescue StandardError => e
8+
raise unless e.message.include?("encoding")
9+
10+
abort <<~MESSAGE
11+
\e[31mERROR:\e[0m Failed to create an ICU collation with current database encoding.
12+
You need to change the database encoding before proceeding.
13+
14+
Please check the instructions on how to do it:
15+
https://www.openproject.org/docs/installation-and-operations/misc/changing-database-encoding/
16+
17+
Original error:
18+
#{e.message}
19+
MESSAGE
20+
end
621

722
change_column :versions, :name, :string, collation: "versions_name"
823
end
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Changing database encoding
2+
3+
This instructions are primarily intended to help with an error encountered when migrating to OpenProject 15.
4+
The error happens when migration tries to create an ICU collation and database encoding doesn't support it.
5+
We suggest to use unicode encoding for maximum compatibility.
6+
7+
## Preconditions
8+
9+
* Credentials with the permission to create a database in the database server the OpenProject installation is running against.
10+
* Shell access to the OpenProject server.
11+
12+
## 1. Create a database dump
13+
14+
This and following steps assume that you are using built in `openproject` command.
15+
16+
```shell
17+
openproject run backup
18+
```
19+
20+
Ensure it finished successfully and note down the path after `Generating database backup` that should normally be
21+
in form `/var/db/openproject/backup/postgresql-dump-<DATE_TIME_DIGITS>.pgdump`.
22+
23+
See also [Backing up your OpenProject installation page](../../operation/backing-up).
24+
25+
## 2. Create a new database with different encoding
26+
27+
Note down the database connection URL that should be in form `postgres://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<DATABASE>`:
28+
29+
```shell
30+
openproject config:get DATABASE_URL
31+
```
32+
33+
Create new database using `psql` command, after deciding on the name, for example `openproject-unicode`:
34+
35+
```shell
36+
psql '<DATABASE_URL>' -c 'CREATE DATABASE "<NEW_DATABASE_NAME>" ENCODING UNICODE'
37+
```
38+
39+
Options for `CREATE DATABASE` can be found at [PostgreSQL documentation page](https://www.postgresql.org/docs/current/sql-createdatabase.html).
40+
41+
Or alternatively using `createdb` command:
42+
43+
```shell
44+
su postgres -c createdb -E UNICODE -O <dbusernamer> openproject_backup
45+
```
46+
47+
Instructions for `createdb` command can be found at [PostgreSQL documentation page](https://www.postgresql.org/docs/17/app-createdb.html).
48+
49+
## 3. Restore the dump to the new database
50+
51+
To get the new database URL you need to replace the old database name with the new database name in the connection URL that you got in the previous step.
52+
For example if it was `postgres://openproject:hard-password@some-host:5432/openproject` and new database name was chosen to be `openproject-unicode`, then
53+
new database URL will be `postgres://openproject:hard-password@some-host:5432/openproject-unicode`.
54+
55+
```shell
56+
pg_restore -d '<NEW_DATABASE_URL>' '<PATH_TO_THE_DATABASE_DUMP>'
57+
```
58+
59+
See also [Restoring an OpenProject backup](../../operation/restoring/).
60+
61+
## 4. Change configuration to use the new database
62+
63+
Using the new database URL from previous step:
64+
65+
```shell
66+
openproject config:set DATABASE_URL=<NEW_DATABASE_URL>
67+
```
68+
69+
See also [Configuring a custom database server page](../../configuration/database/).

frontend/src/assets/images/15_1_features.svg

Lines changed: 1 addition & 1 deletion
Loading

frontend/src/stimulus/controllers/dynamic/work-packages/export/form.controller.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,16 @@ export default class FormController extends Controller<HTMLFormElement> {
4141
return result.job_id;
4242
}
4343

44+
generateExportURL():string {
45+
const actionURL = this.element.getAttribute('action') as string;
46+
const searchParams = this.getExportParams();
47+
const append = actionURL.includes('?') ? '&' : '?';
48+
return `${actionURL}${append}${searchParams.toString()}`;
49+
}
50+
4451
submitForm(evt:CustomEvent) {
4552
evt.preventDefault(); // Don't submit
46-
const formatURL = this.element.getAttribute('action');
47-
const searchParams = this.getExportParams();
48-
const exportURL = `${formatURL}?${searchParams.toString()}`;
49-
this.requestExport(exportURL)
53+
this.requestExport(this.generateExportURL())
5054
.then((job_id) => this.showJobModal(job_id))
5155
.catch((error:HttpErrorResponse) => this.handleError(error));
5256
}

spec/features/members/error_messages_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
require "spec_helper"
3030

31-
RSpec.describe "Group memberships through groups page" do
31+
RSpec.describe "Group memberships through groups page", :js, :with_cuprite do
3232
shared_let(:admin) { create(:admin) }
3333
let!(:project) { create(:project, name: "Project 1", identifier: "project1") }
3434

spec/features/members/pagination_spec.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,9 @@
5959
members_page.set_items_per_page! 2
6060

6161
members_page.visit!
62-
SeleniumHubWaiter.wait
6362
expect(members_page).to have_user "Alice Alison" # members are sorted by last name desc
6463
members_page.add_user! "Peter Pan", as: "Manager"
6564

66-
SeleniumHubWaiter.wait
6765
members_page.go_to_page! 2
6866
expect(members_page).to have_user "Peter Pan"
6967
end
@@ -82,12 +80,10 @@
8280
members_page.set_items_per_page! 1
8381

8482
members_page.visit!
85-
SeleniumHubWaiter.wait
8683
members_page.remove_user! "Alice Alison"
8784
expect_and_dismiss_flash message: "Removed Alice Alison from project"
8885
expect(members_page).to have_user "Bob Bobbit"
8986

90-
SeleniumHubWaiter.wait
9187
members_page.go_to_page! 2
9288
expect(members_page).to have_user "Peter Pan"
9389
end
@@ -98,13 +94,11 @@
9894
members_page.set_items_per_page! 1
9995

10096
members_page.visit!
101-
SeleniumHubWaiter.wait
10297
members_page.go_to_page! 2
10398
members_page.edit_user! "Bob Bobbit", add_roles: ["Developer"]
10499
expect(page).to have_text "Successful update"
105100
expect(members_page).to have_user "Bob Bobbit", roles: ["Developer", "Manager"]
106101

107-
SeleniumHubWaiter.wait
108102
members_page.go_to_page! 1
109103
expect(members_page).to have_user "Alice Alison"
110104
end

spec/features/work_packages/export_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def export!
126126
context "with activated options" do
127127
let(:query) do
128128
create(
129-
:query, user: current_user, project:,
129+
:query, id: 1234, user: current_user, project:,
130130
display_sums: true,
131131
include_subprojects: true,
132132
show_hierarchies: true,
@@ -135,6 +135,7 @@ def export!
135135
end
136136
let(:expected_params) do
137137
default_expected_params.merge({
138+
query_id: "1234",
138139
showSums: "true",
139140
includeSubprojects: "true",
140141
showHierarchies: "true"

spec/helpers/journals_helper_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"unsupported_gizmo" => nil,
3939
"users/5" => "http://test.host/users/5",
4040
"work_packages/42" => "http://test.host/work_packages/42",
41+
# Sometimes the url is erroneous (having an extra ') for unknown reasons.
42+
"work_packages/42'" => "http://test.host/work_packages/42",
4143
nil => nil
4244
}.each do |activity_page, expected_url|
4345
context "when activity page is #{activity_page.inspect}" do

spec/support/pages/groups.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def group(group_name)
6969
end
7070
end
7171

72-
class Group < Pages::Page
72+
class Group < Page
7373
include ::Components::Autocompleter::NgSelectAutocompleteHelpers
7474
attr_reader :id
7575

spec/support/pages/members.rb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ def initialize(project_identifier)
4040
@project_identifier = project_identifier
4141
end
4242

43-
def visit!
44-
super
45-
46-
self
47-
end
48-
4943
def path
5044
"/projects/#{project_identifier}/members"
5145
end
@@ -61,7 +55,7 @@ def open_filters!
6155
def search_for_name(name)
6256
fill_in "name", with: name
6357
find(".simple-filters--controls input[type=submit]").click
64-
wait_for_network_idle
58+
wait_for_reload
6559
end
6660

6761
def expect_menu_item(text, selected: false)
@@ -193,7 +187,7 @@ def edit_user!(name, add_roles: [], remove_roles: [])
193187
Array(remove_roles).each { |role| uncheck role }
194188

195189
click_on "Change"
196-
wait_for_network_idle
190+
wait_for_reload
197191
end
198192

199193
def has_group_membership?(user_name)
@@ -276,7 +270,7 @@ def expect_role(role_name, present: true)
276270

277271
def go_to_page!(number)
278272
find(".op-pagination--pages a", text: number.to_s).click
279-
wait_for_network_idle
273+
wait_for_reload
280274
end
281275
end
282276
end

spec/support/pages/page.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def current_page?
4646
def visit!
4747
raise "No path defined" unless path
4848

49-
visit path
49+
visit(path)
5050

51-
self
51+
wait_for_reload
5252
end
5353

5454
def reload!

0 commit comments

Comments
 (0)