Skip to content

Commit

Permalink
Merge branch 'release/15.1' into documentation/59798-151-documentatio…
Browse files Browse the repository at this point in the history
…n-multi-level-selection-fields-to-support-custom-hierarchical-attributes
  • Loading branch information
MayaBerd authored Dec 6, 2024
2 parents b6a67e4 + 4d7bff2 commit c54e586
Show file tree
Hide file tree
Showing 25 changed files with 242 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
size: :large,
id: DIALOG_ID)) do |d|
d.with_header(variant: :large)
d.with_body(classes: "Overlay-body_autocomplete_height") do
d.with_body(classes: body_classes) do
render(WorkPackageRelationsTab::AddWorkPackageChildFormComponent.new(
work_package: @work_package
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ def dialog_title
child_label = t("#{I18N_NAMESPACE}.relations.label_child_singular")
t("#{I18N_NAMESPACE}.label_add_x", x: child_label)
end

def body_classes
"Overlay-body_autocomplete_height"
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
size: :large,
id: DIALOG_ID)) do |d|
d.with_header(variant: :large)
d.with_body(classes: "Overlay-body_autocomplete_height") do
d.with_body(classes: body_classes) do
render(WorkPackageRelationsTab::WorkPackageRelationFormComponent.new(
work_package: @work_package,
relation: @relation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ def dialog_title
t("#{I18N_NAMESPACE}.label_add_x", x: relation_label)
end
end

def body_classes
@relation.persisted? ? nil : "Overlay-body_autocomplete_height"
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class UpdateItemContract < Dry::Validation::Contract

rule(:short) do
next if schema_error?(:item)
next unless key?

key.failure(:not_unique) if values[:item].siblings.exists?(short: value)
end
Expand Down
18 changes: 18 additions & 0 deletions app/controllers/sys_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ def repo_auth
end
end

def fetch_changesets
projects = []
if params[:id]
projects << Project.active.has_module(:repository).find_by!(identifier: params[:id])
else
projects = Project.active.has_module(:repository)
.includes(:repository).references(:repositories)
end
projects.each do |project|
if project.repository
project.repository.fetch_changesets
end
end
head :ok
rescue ActiveRecord::RecordNotFound
head :not_found
end

private

def authorized?(project, user)
Expand Down
3 changes: 2 additions & 1 deletion app/helpers/journals_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ def back_to_activity_page_url(activity_page)
in ["users", user_id]
user_url(user_id)
in ["work_packages", work_package_id]
work_package_url(work_package_id)
# Sometimes the parameter provided is erroneous (having an extra ') for unknown reasons.
work_package_url(work_package_id.chomp("'"))
else
nil
end
Expand Down
6 changes: 1 addition & 5 deletions config/initializers/03-db_check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

if (db_config = ActiveRecord::Base.configurations.configs_for(env_name: env)[0]) &&
db_config.configuration_hash["adapter"]&.start_with?("mysql")
warn <<~ERROR
abort <<~ERROR
======= INCOMPATIBLE DATABASE DETECTED =======
Your database is set up for use with a MySQL or MySQL-compatible variant.
This installation of OpenProject no longer supports these variants.
Expand All @@ -45,8 +45,4 @@
==============================================
ERROR

# rubocop:disable Rails/Exit
Kernel.exit 1
# rubocop:enable Rails/Exit
end
File renamed without changes.
53 changes: 53 additions & 0 deletions config/initializers/05-check_db_encoding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

if ENV["OPENPROJECT_SKIP_DB_ENCODING_CHECK"].blank?
icu_incompatible_encodings = %w[
EUC_JIS_2004
LATIN10
MULE_INTERNAL
SQL_ASCII
WIN874
]

database_encoding = ActiveRecord::Base.connection.select_value("SHOW SERVER_ENCODING")

if database_encoding.in?(icu_incompatible_encodings)
abort <<~ERROR
INCOMPATIBLE DATABASE ENCODING DETECTED
Your database encoding is #{database_encoding}, which is incompatible with ICU
collation used in OpenProject v15.
Please check the instructions on how to change database encoding:
https://www.openproject.org/docs/installation-and-operations/misc/changing-database-encoding/
This check can be skipped by setting environment variable OPENPROJECT_SKIP_DB_ENCODING_CHECK=true
ERROR
end
end
2 changes: 1 addition & 1 deletion config/locales/crowdin/js-de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ de:
"15_1":
standard:
new_features_html: >
Die Version bringt verschiedene Funktionen und Verbesserungen für Sie, z.B. <br> <ul class="%{list_styling_class}"> <li>Benutzerdefinierte Felder vom Typ Hierarchie (Enterprise Add-on).</li> <li>Neugestaltung des Beziehungen-Tabs in Arbeitspaketen.</li> <li>Neugestaltung der Meeting-Indexseite.</li> <li>Manuelle Seitenumbrüche beim Export von PDF-Arbeitspaketen.</li> <li>Zen-Modus für Projektlisten.</li> </ul>
Die Version bringt verschiedene Funktionen und Verbesserungen für Sie, z.B. <br> <ul class="%{list_styling_class}"> <li>Selbstdefinierte Felder vom Typ Hierarchie (Enterprise Add-on).</li> <li>Neugestaltung des Beziehungen-Tabs in Arbeitspaketen.</li> <li>Neugestaltung der Besprechungen-Indexseite.</li> <li>Manuelle Seitenumbrüche beim PDF-Export von Arbeitspaketen.</li> <li>Zen-Modus für Projektlisten.</li> </ul>
ical_sharing_modal:
title: "Kalender abonnieren"
inital_setup_error_message: "Beim Abrufen der Daten ist ein Fehler aufgetreten."
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -703,8 +703,8 @@

scope controller: "sys" do
match "/sys/repo_auth", action: "repo_auth", via: %i[get post]
get "/sys/fetch_changesets", action: "fetch_changesets"
match "/sys/projects", to: proc { [410, {}, [""]] }, via: :all
match "/sys/fetch_changesets", to: proc { [410, {}, [""]] }, via: :all
match "/sys/projects/:id/repository/update_storage", to: proc { [410, {}, [""]] }, via: :all
end

Expand Down
21 changes: 18 additions & 3 deletions db/migrate/20240920152544_set_versions_name_collation.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
class SetVersionsNameCollation < ActiveRecord::Migration[7.1]
def up
execute <<-SQL.squish
CREATE COLLATION IF NOT EXISTS versions_name (provider = icu, locale = 'und-u-kn-true');
SQL
begin
execute <<-SQL.squish
CREATE COLLATION IF NOT EXISTS versions_name (provider = icu, locale = 'und-u-kn-true');
SQL
rescue StandardError => e
raise unless e.message.include?("encoding")

abort <<~MESSAGE
\e[31mERROR:\e[0m Failed to create an ICU collation with current database encoding.
You need to change the database encoding before proceeding.
Please check the instructions on how to do it:
https://www.openproject.org/docs/installation-and-operations/misc/changing-database-encoding/
Original error:
#{e.message}
MESSAGE
end

change_column :versions, :name, :string, collation: "versions_name"
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Changing database encoding

This instructions are primarily intended to help with an error encountered when migrating to OpenProject 15.
The error happens when migration tries to create an ICU collation and database encoding doesn't support it.
We suggest to use unicode encoding for maximum compatibility.

## Preconditions

* Credentials with the permission to create a database in the database server the OpenProject installation is running against.
* Shell access to the OpenProject server.

## 1. Create a database dump

This and following steps assume that you are using built in `openproject` command.

```shell
openproject run backup
```

Ensure it finished successfully and note down the path after `Generating database backup` that should normally be
in form `/var/db/openproject/backup/postgresql-dump-<DATE_TIME_DIGITS>.pgdump`.

See also [Backing up your OpenProject installation page](../../operation/backing-up).

## 2. Create a new database with different encoding

Note down the database connection URL that should be in form `postgres://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<DATABASE>`:

```shell
openproject config:get DATABASE_URL
```

Create new database using `psql` command, after deciding on the name, for example `openproject-unicode`:

```shell
psql '<DATABASE_URL>' -c 'CREATE DATABASE "<NEW_DATABASE_NAME>" ENCODING UNICODE'
```

Options for `CREATE DATABASE` can be found at [PostgreSQL documentation page](https://www.postgresql.org/docs/current/sql-createdatabase.html).

Or alternatively using `createdb` command:

```shell
su postgres -c createdb -E UNICODE -O <dbusernamer> openproject_backup
```

Instructions for `createdb` command can be found at [PostgreSQL documentation page](https://www.postgresql.org/docs/17/app-createdb.html).

## 3. Restore the dump to the new database

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.
For example if it was `postgres://openproject:hard-password@some-host:5432/openproject` and new database name was chosen to be `openproject-unicode`, then
new database URL will be `postgres://openproject:hard-password@some-host:5432/openproject-unicode`.

```shell
pg_restore -d '<NEW_DATABASE_URL>' '<PATH_TO_THE_DATABASE_DUMP>'
```

See also [Restoring an OpenProject backup](../../operation/restoring/).

## 4. Change configuration to use the new database

Using the new database URL from previous step:

```shell
openproject config:set DATABASE_URL=<NEW_DATABASE_URL>
```

See also [Configuring a custom database server page](../../configuration/database/).
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,16 @@ export default class FormController extends Controller<HTMLFormElement> {
return result.job_id;
}

generateExportURL():string {
const actionURL = this.element.getAttribute('action') as string;
const searchParams = this.getExportParams();
const append = actionURL.includes('?') ? '&' : '?';
return `${actionURL}${append}${searchParams.toString()}`;
}

submitForm(evt:CustomEvent) {
evt.preventDefault(); // Don't submit
const formatURL = this.element.getAttribute('action');
const searchParams = this.getExportParams();
const exportURL = `${formatURL}?${searchParams.toString()}`;
this.requestExport(exportURL)
this.requestExport(this.generateExportURL())
.then((job_id) => this.showJobModal(job_id))
.catch((error:HttpErrorResponse) => this.handleError(error));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
let!(:vader) { create(:hierarchy_item) }
let!(:luke) { create(:hierarchy_item, label: "luke", short: "ls", parent: vader) }
let!(:leia) { create(:hierarchy_item, label: "leia", short: "lo", parent: vader) }
let!(:starkiller) { create(:hierarchy_item, label: "starkiller", parent: vader) }

context "when all required fields are valid" do
it "is valid" do
Expand Down
48 changes: 48 additions & 0 deletions spec/controllers/sys_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -493,4 +493,52 @@
end
end
end

describe "#fetch_changesets" do
let(:params) { { id: repository_project.identifier } }

before do
request.env["HTTP_AUTHORIZATION"] =
ActionController::HttpAuthentication::Basic.encode_credentials(
valid_user.login,
valid_user_password
)

allow_any_instance_of(Repository::Subversion).to receive(:fetch_changesets).and_return(true)

get "fetch_changesets", params: params.merge({ key: api_key })
end

context "with a project identifier" do
it "is successful" do
expect(response)
.to have_http_status(:ok)
end
end

context "without a project identifier" do
let(:params) { {} }

it "is successful" do
expect(response)
.to have_http_status(:ok)
end
end

context "for an unknown project" do
let(:params) { { id: 0 } }

it "returns 404" do
expect(response)
.to have_http_status(:not_found)
end
end

context "when disabled", with_settings: { sys_api_enabled?: false } do
it "is 403 forbidden" do
expect(response)
.to have_http_status(:forbidden)
end
end
end
end
1 change: 0 additions & 1 deletion spec/factories/hierarchy_item_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,5 @@
FactoryBot.define do
factory :hierarchy_item, class: "CustomField::Hierarchy::Item" do
sequence(:label) { |n| "Item #{n}" }
sequence(:short) { |n| "I #{n}" }
end
end
2 changes: 1 addition & 1 deletion spec/features/members/error_messages_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

require "spec_helper"

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

Expand Down
Loading

0 comments on commit c54e586

Please sign in to comment.