Skip to content

Commit fc872a8

Browse files
committed
Merge branch 'release/15.5' into dev
2 parents 298a53d + 391061c commit fc872a8

File tree

17 files changed

+194
-94
lines changed

17 files changed

+194
-94
lines changed

app/services/work_packages/set_attributes_service.rb

+13-18
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ def set_calculated_attributes(attributes)
7070
update_dates
7171
end
7272
shift_dates_to_soonest_working_days
73-
update_duration
74-
update_derivable
73+
update_duration_to_one_day_for_milestones
74+
update_derivable_date_attribute
7575
update_progress_attributes
7676
update_project_dependent_attributes
7777
reassign_invalid_status_if_type_changed
7878
set_templated_description
7979
set_cause_for_readonly_attributes
8080
end
8181

82-
def derivable_attribute
83-
derivable_attribute_by_others_presence || derivable_attribute_by_others_absence
82+
def derivable_date_attribute
83+
derivable_date_attribute_by_others_presence || derivable_date_attribute_by_others_absence
8484
end
8585

8686
# Returns a field derivable by the presence of the two others, or +nil+ if
@@ -91,13 +91,8 @@ def derivable_attribute
9191
#
9292
# If +ignore_non_working_days+ has been changed, try deriving +due_date+ and
9393
# +start_date+ before +duration+.
94-
def derivable_attribute_by_others_presence
95-
fields =
96-
if work_package.ignore_non_working_days_changed?
97-
%i[due_date start_date duration]
98-
else
99-
%i[duration due_date start_date]
100-
end
94+
def derivable_date_attribute_by_others_presence
95+
fields = %i[duration due_date start_date]
10196
fields.find { |field| derivable_by_others_presence?(field) }
10297
end
10398

@@ -116,7 +111,7 @@ def derivable_by_others_presence?(field)
116111
#
117112
# Matching is done in the order :duration, :due_date, :start_date. The first
118113
# one to match is returned.
119-
def derivable_attribute_by_others_absence
114+
def derivable_date_attribute_by_others_absence
120115
%i[duration due_date start_date].find { |field| derivable_by_others_absence?(field) }
121116
end
122117

@@ -145,8 +140,8 @@ def only_one_present?(*fields)
145140
end
146141

147142
# rubocop:disable Metrics/AbcSize
148-
def update_derivable
149-
case derivable_attribute
143+
def update_derivable_date_attribute
144+
case derivable_date_attribute
150145
when :duration
151146
work_package.duration =
152147
if work_package.milestone?
@@ -320,7 +315,7 @@ def shift_dates_to_soonest_working_days
320315
work_package.due_date = days.soonest_working_day(work_package.due_date)
321316
end
322317

323-
def update_duration
318+
def update_duration_to_one_day_for_milestones
324319
work_package.duration = 1 if work_package.milestone?
325320
end
326321

@@ -365,7 +360,7 @@ def assign_default_type
365360
available_types = work_package.project.types.order(:position)
366361

367362
work_package.type = available_types.first
368-
update_duration
363+
update_duration_to_one_day_for_milestones
369364
unify_milestone_dates
370365

371366
reassign_status assignable_statuses
@@ -470,14 +465,14 @@ def parent_start_earlier_than_due?
470465
start = work_package.parent&.start_date
471466
due = work_package.due_date || work_package.parent&.due_date
472467

473-
(start && !due) || ((due && start) && (start < due))
468+
(start && !due) || (due && start && (start < due))
474469
end
475470

476471
def parent_due_later_than_start?
477472
due = work_package.parent&.due_date
478473
start = work_package.start_date || work_package.parent&.start_date
479474

480-
(due && !start) || ((due && start) && (due > start))
475+
(due && !start) || (due && start && (due > start))
481476
end
482477

483478
def set_cause_for_readonly_attributes

docs/release-notes/15-5-0/README.md

+92-14
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,98 @@ title: OpenProject 15.5.0
33
sidebar_navigation:
44
title: 15.5.0
55
release_version: 15.5.0
6-
release_date: 2025-04-03
6+
release_date: 2025-04-16
77
---
88

99
# OpenProject 15.5.0
1010

11-
Release date: 2025-04-03
11+
Release date: 2025-04-16
1212

13-
We released OpenProject [OpenProject 15.5.0](https://community.openproject.org/versions/2171).
14-
The release contains several bug fixes and we recommend updating to the newest version.
15-
In these Release Notes, we will give an overview of important feature changes.
16-
At the end, you will find a complete list of all changes and bug fixes.
13+
We released [OpenProject 15.5.0](https://community.openproject.org/versions/2171). The release contains several bug fixes, and we recommend updating to the newest version. In these Release Notes, we will give an overview of important feature changes. At the end, you will find a complete list of all changes and bug fixes.
1714

1815
## Important feature changes
1916

20-
<!-- Inform about the major features in this section -->
17+
### Filter for descendants (children and grandchildren) of work packages
18+
19+
In OpenProject 15.5, you can now filter for all descendants of a work package — including children, grandchildren, and deeper levels. This is especially helpful when focusing on a specific part of a project that includes multiple levels of work packages.
20+
21+
The new filter option **Descendants of** allows you to select one or more parent work packages by ID and display all their subordinate items. It is available wherever filters are supported — such as work package tables or agile boards.
22+
23+
Previously, it was only possible to filter for parent work packages, not their lower-level hierarchy.
24+
25+
![Work package table filtered for descendants of a phase](openproject-15-5-descendants-filter-highlighted.png)
26+
27+
### % Complete included in work package table sums
28+
29+
The **% Complete** value is now included in the sum row of work package tables. This complements the existing Work and Remaining work columns and gives a quick, consistent overview of project progress.
30+
31+
All three values — Work, Remaining work, and % Complete — are calculated in alignment with the selected progress reporting mode.
32+
33+
![Work package table showing % Complete, Work and Remaining work – with highlighted sums](openproject-15-5-percentage-complete-sum-highlighted.png)
34+
35+
### Column for children in work package tables (Enterprise add-on)
36+
37+
OpenProject 15.5 introduces a new **Children** column in work package tables. Similar to other relation columns, this column provides an expandable view showing related child work packages directly in the table — without needing to filter for them separately.
38+
39+
This makes it easier to get a quick overview of a parent work package and its structure, especially when working with large datasets or filtered views.
40+
41+
The column displays the number of children next to each parent, along with a clickable dropdown symbol.
42+
43+
![Work package table with a highlighted 'Children' column - the number of children being displayed next to each parent, along with a dropdown-symbol](openproject-15-5-children-work-package-table-highlighted.png)
44+
45+
Clicking on the dropdown symbol expands the view to show all related child work packages, each marked with a **Child** label:
46+
47+
![Work package table with expanded children work packages in the children column](openproject-15-5-children-work-package-table-unfolded.png)
48+
49+
> [!NOTE]
50+
> All relationship columns are [Enterprise add-ons](https://www.openproject.org/enterprise-edition/).
51+
52+
### Advanced accessibility in the date picker
53+
54+
Accessibility remains a key focus in OpenProject, and with version 15.5, we’ve enhanced support for screen readers. These improvements ensure that users relying on assistive technologies receive meaningful feedback during manual date input.
55+
56+
- Informative announcements are now triggered when switching between manual and automatic scheduling.
57+
- Changes in one date field (e.g., Start date or Duration) are announced as they update related fields.
58+
- The “Today” shortcuts include ARIA labels to give clear context, such as “Select today as start date.”
59+
60+
This update is part of our ongoing ARIA implementation strategy, with [further accessibility enhancements planned in upcoming versions](https://community.openproject.org/wp/62708).
61+
62+
### Improved date picker rendering in mobile screens
63+
64+
The date picker now uses the native mobile date input and **opens in a full-screen modal on small screens**. This improves accessibility and interaction. The mini calendar has been removed to reduce clutter and improve usability on mobile devices.
65+
66+
### PDF exports matching configured form layout
67+
68+
Single work package PDF exports now **follow the configured form layout**, including attribute groups, field order, and long text fields. For example, if the Date field is grouped with other scheduling fields in your form configuration, it will appear the same way in the PDF — not split into separate start and end dates.
69+
70+
You can also **export in portrait or landscape orientation**, and **query group tables are included if configured**. If a table doesn’t fit on the page, a note is displayed instead.
71+
72+
### Chronological ordering of relations
73+
74+
Relations in the Relations tab and date picker are now consistently ordered by their creation date, regardless of whether the related work packages are fully visible or permission-restricted.
75+
76+
This change improves clarity by showing relations in the exact order they were added — with the oldest first — and removes the previous grouping by visibility status.
77+
78+
### Work package related project settings grouped in a new entry
79+
80+
To improve navigation, related project settings have been grouped under a new **Work packages** section in the project settings. This section includes three tabs:
81+
82+
- [Types](../../user-guide/projects/project-settings/work-packages/#work-package-types)
83+
- [Categories](../../user-guide/projects/project-settings/work-packages/#work-package-categories)
84+
- [Custom fields](../../user-guide/projects/project-settings/work-packages/#work-package-custom-fields)
85+
86+
The previous individual entries have been moved into this grouped view. Existing URLs now redirect to their new locations, ensuring a smooth transition. This is a structural improvement only — no changes were made to permissions or underlying functionality.
87+
88+
### Classic meetings marked as unsupported — removal planned for the next release
89+
90+
With the recent improvements to One-time and Recurring meetings, the older Classic meetings are now considered outdated and will be removed in the next OpenProject release (16.0). This change has been planned and communicated since the introduction of what were then called Dynamic meetings (now One-time and Recurring).
91+
92+
To prepare for this transition, the **Classic option in the + Meeting dropdown is now marked as unsupported**, accompanied by the following notice: “Classic meetings will be removed in the next version of OpenProject.”
93+
94+
![Dropdown menu in the OpenProject Meetings module, with highlighted option of "Classic (unsupported)"](openproject-15-5-classic-meetings-highlighted.png)
95+
96+
> [!NOTE]
97+
> We recommend switching to the newer Meeting types to benefit from the latest features and ensure a smooth transition. [Read this article to learn more about the reasons and what will happen to your existing Classic meetings](https://www.openproject.org/blog/).
2198
2299
## Important updates and breaking changes
23100

@@ -80,12 +157,13 @@ At the end, you will find a complete list of all changes and bug fixes.
80157
<!-- Warning: Anything above this line will be automatically removed by the release script -->
81158

82159
## Contributions
83-
A very special thank you goes to our sponsors for this release.
84-
Also a big thanks to our Community members for reporting bugs and helping us identify and provide fixes.
85-
Special thanks for reporting and finding bugs go to Abhiyan Paudyal, Andreas H., Paul Kernstock, Patrick Stapf, Stefan Weiberg.
160+
A very special thank you goes to City of Cologne, Deutsche Bahn and ZenDiS for sponsoring released or upcoming features. Your support, alongside the efforts of our amazing Community, helps drive these innovations.
161+
162+
Special thanks for reporting and finding bugs go to Abhiyan Paudyal, Andreas H., Paul Kernstock, Patrick Stapf, and Stefan Weiberg.
86163

87-
Last but not least, we are very grateful for our very engaged translation contributors on Crowdin, who translated quite a few OpenProject strings!
88-
Would you like to help out with translations yourself?
89-
Then take a look at our translation guide and find out exactly how you can contribute.
90-
It is very much appreciated!
164+
Last but not least, we are very grateful for our very engaged translation contributors on Crowdin, who translated quite a few OpenProject strings! This release we would like to particularly thank the following users:
165+
- [NCAA](https://crowdin.com/profile/ncaa), for a great number of translations into Danish.
166+
- [greench](https://crowdin.com/profile/greench), for a great number of translations into Turkish.
167+
- [Adam Siemienski](https://crowdin.com/profile/siemienas), for a great number of translations into Polish.
91168

169+
Would you like to help out with translations yourself? Then take a look at our [translation guide](../../contributions-guide/translate-openproject/) and find out exactly how you can contribute. It is very much appreciated!
Loading
Loading
Loading
Loading
Loading

frontend/src/app/features/work-packages/components/wp-fast-table/builders/relations/relation-row-builder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public readonly injector:Injector,
7272
commonRowClassName,
7373
tableRowClassName,
7474
'issue',
75-
'wp-table--relations-aditional-row',
75+
'wp-table--relations-additional-row',
7676
identifier,
7777
`${identifier}-table`,
7878
relationGroupClass(from.id!),

frontend/src/app/features/work-packages/components/wp-fast-table/builders/relations/relations-render-pass.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class RelationsRenderPass {
117117
`.${this.relationRowBuilder.classIdentifier(from)},.${relationGroupClass(from.id as string)}`,
118118
{
119119
classIdentifier: this.relationRowBuilder.relationClassIdentifier(from, to),
120-
additionalClasses: row.additionalClasses.concat(['wp-table--relations-aditional-row']),
120+
additionalClasses: row.additionalClasses.concat(['wp-table--relations-additional-row']),
121121
workPackage: to,
122122
belongsTo: from,
123123
renderType: this.renderType,

frontend/src/app/features/work-packages/components/wp-fast-table/helpers/wp-table-row-helpers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function rowId(workPackageId:string):string {
88
}
99

1010
export function relationRowClass():string {
11-
return `wp-table--relations-aditional-row`;
11+
return 'wp-table--relations-additional-row';
1212
}
1313

1414
export function locateTableRow(workPackageId:string):JQuery {

frontend/src/app/shared/components/modal/modal.component.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export abstract class OpModalComponent extends UntilDestroyedMixin implements On
9494
this.updateAppHeight();
9595
this.cdRef.detectChanges();
9696

97-
window.addEventListener('resize', this.onResize);
97+
// It is important to check for visualViewport changes as that includes also keyboard opening (especially on iOS)
98+
window.visualViewport?.addEventListener('resize', this.onResize);
9899
window.addEventListener('orientationchange', this.onResize);
99100
}
100101

frontend/src/app/spot/styles/sass/components/modal-overlay.sass

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
align-items: center
1111
display: none
1212

13+
.-browser-safari &
14+
// Again, iOS and Safari are being special. When the keyboard opens, that pushes the whole viewport to the top.
15+
// Thus, when using `top: 0` half of the modal is pushed out of the screen.
16+
// Instead, we only set `bottom: 0` and set the height to the app height which is set programmatically on every screen resize
17+
height: var(--app-height)
18+
top: unset
19+
1320
&_active
1421
display: flex
1522
flex-direction: column-reverse

frontend/src/global_styles/content/work_packages/_table_relations.sass

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
$table-row-relations-row-background-color: rgba(220, 235, 244, 0.6)
2-
31
body
4-
.wp-table--relations-aditional-row,
2+
.wp-table--relations-additional-row,
53
.wp-table--relation-cell-td.-expanded
6-
background: $table-row-relations-row-background-color
4+
background: var(--bgColor-neutral-muted)
75

86
.wp-table--relation-cell-td.-expanded
9-
border-bottom: 1px solid $table-row-relations-row-background-color
7+
border-bottom: 1px solid var(--borderColor-neutral-muted) !important
108

119

1210
// Show the correct icon for the current expansion state

frontend/src/stimulus/controllers/dynamic/work-packages/date-picker/preview.controller.ts

+4
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ export default class PreviewController extends DialogPreviewController {
373373
const fieldToHighlight = e.target as HTMLInputElement;
374374
if (fieldToHighlight) {
375375
this.highlightField(fieldToHighlight);
376+
window.setTimeout(() => {
377+
// For mobile, we have to make sure that the active field is scrolled into view after the keyboard is opened
378+
fieldToHighlight.scrollIntoView(true);
379+
}, 200);
376380
// Datepicker can need an update when the focused field changes. This
377381
// allows to switch between single and range mode in certain edge cases.
378382
this.readCurrentValues();

spec/features/work_packages/datepicker/datepicker_editable_finish_date_logic_spec.rb

-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,6 @@
381381

382382
describe "and change finish and non-working days, switching back to automatic (scenario 14b)" do
383383
it "preserves the finish date" do
384-
pending "Enable when #62641 has been fixed"
385384
datepicker.set_date "2025-04-25"
386385

387386
datepicker.expect_working_days_only(true)

0 commit comments

Comments
 (0)