From 47f4c511aac36f5a5c24d871f02b770e8ca177d6 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Fri, 17 Jan 2025 12:53:50 -0300 Subject: [PATCH 01/14] [#60649] Change op-autocompleter debounce to 250ms Increases the debounce to a more typical value (200-300ms) for a complex web application. The current value (50ms) results in a large number of unnecessary API requests - on installatons with large numbers of work packages, this can lead to severe performance degradation. This partially reverts a change made in commit b0fffbc4e8784f0ff5ee882388fc7ea93b05fffc Signed-off-by: Alexander Brandon Coles --- .../op-autocompleter/op-autocompleter.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts index 40fc8dad28fa..240dd5facbf2 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts @@ -527,7 +527,7 @@ export class OpAutocompleterComponent Date: Fri, 17 Jan 2025 14:14:47 -0300 Subject: [PATCH 02/14] Fix TS error in PollForChangesController Fixes `Type 'Timer' is not assignable to type 'number' error when running `npm run test:watch`. node typings for `setInterval()` specify `Timer` as its return type. This patch explicitly calls the browser variant, which returns `number`. See also https://github.com/TypeStrong/atom-typescript/issues/1053 --- .../src/stimulus/controllers/poll-for-changes.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/stimulus/controllers/poll-for-changes.controller.ts b/frontend/src/stimulus/controllers/poll-for-changes.controller.ts index ba6712479da3..4b24bb4e64c0 100644 --- a/frontend/src/stimulus/controllers/poll-for-changes.controller.ts +++ b/frontend/src/stimulus/controllers/poll-for-changes.controller.ts @@ -56,7 +56,7 @@ export default class PollForChangesController extends ApplicationController { super.connect(); if (this.intervalValue !== 0) { - this.interval = setInterval(() => { + this.interval = window.setInterval(() => { void this.triggerTurboStream(); }, this.intervalValue || 10_000); } From 1e54f2f7f38032a1df315e6e130f76a85110cc3e Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Fri, 17 Jan 2025 16:29:24 -0300 Subject: [PATCH 03/14] Make debounce time configurable Implements a `debounceTimeMs` input property, allowing us to tweak the time in component subclasses and individual instances if need be. This also reverts the zero initial debounce (also introduced in commit b0fffbc4). --- .../op-autocompleter.component.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts index 240dd5facbf2..87b2c56212ad 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts @@ -23,8 +23,8 @@ import { ViewContainerRef, } from '@angular/core'; import { DropdownPosition, NgSelectComponent } from '@ng-select/ng-select'; -import { BehaviorSubject, merge, NEVER, Observable, of, Subject, timer } from 'rxjs'; -import { debounce, distinctUntilChanged, filter, switchMap, tap, map } from 'rxjs/operators'; +import { BehaviorSubject, merge, NEVER, Observable, of, Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, filter, switchMap, tap, map } from 'rxjs/operators'; import { AddTagFn, GroupValueFn } from '@ng-select/ng-select/lib/ng-select.component'; import { HalResource } from 'core-app/features/hal/resources/hal-resource'; @@ -228,6 +228,8 @@ export class OpAutocompleterComponent(); @Output() public close = new EventEmitter(); @@ -284,8 +286,6 @@ export class OpAutocompleterComponent; - initialDebounce = true; - private opAutocompleterService = new OpAutocompleterService(this.apiV3Service); constructor( @@ -466,7 +466,7 @@ export class OpAutocompleterComponent !!(this.defaultData || this.getOptionsFn)), distinctUntilChanged(), tap(() => this.loading$.next(true)), - debounce(() => timer(this.getDebounceTimeout())), + debounceTime(this.debounceTimeMs), switchMap((queryString:string) => { if (this.relations && this.url) { return this.fetchFromUrl(queryString); @@ -522,14 +522,6 @@ export class OpAutocompleterComponent Date: Fri, 17 Jan 2025 16:30:22 -0300 Subject: [PATCH 04/14] Set debounce to 0ms in op-autocompleter spec --- .../autocompleter/op-autocompleter/op-autocompleter.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts index 18f4037bc297..f11cf76723d3 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts @@ -80,6 +80,7 @@ describe('autocompleter', () => { fixture.componentInstance.virtualScroll = true; fixture.componentInstance.classes = 'wp-relations-autocomplete'; fixture.componentInstance.defaultData = true; + fixture.componentInstance.debounceTimeMs = 0; // @ts-ignore opAutocompleterServiceSpy.loadData.and.returnValue(of(workPackagesStub)); From f932f06a0ff141dfe73d5ebd3441c2d87b055810 Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Mon, 6 Jan 2025 10:57:19 +0000 Subject: [PATCH 05/14] cache vendor/bundle in docker workflow 'seed' ppc64 bundle cache with state from release/15.2 --- .github/workflows/docker.yml | 24 ++++++++++++++++++++++++ docker/prod/Dockerfile | 11 ++--------- docker/prod/setup/bundle-install.sh | 18 ++++++++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) mode change 100644 => 100755 docker/prod/Dockerfile create mode 100644 docker/prod/setup/bundle-install.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index de098ef7b263..d730336dadf5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -186,6 +186,16 @@ jobs: type=semver,pattern={{version}},value=${{ needs.setup.outputs.version }} images: | ${{ env.REGISTRY_IMAGE }} + - name: Restore vendor/bundle + id: restore-vendor-bundle + uses: actions/cache/restore@v4 + with: + path: | + vendor/bundle + key: ${{ matrix.platform }}-vendor-bundle-${{ github.ref }} + - name: Include vendor/bundle in this build (so we can use it from the cache above) + run: | + sed -i 's/vendor\/bundle//g' .dockerignore - name: Build image id: build uses: docker/build-push-action@v6 @@ -195,12 +205,26 @@ jobs: target: ${{ matrix.target }} build-args: | BIM_SUPPORT=${{ matrix.bim_support }} + BUILDKIT_PROGRESS=plain pull: true load: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=s3,blobs_prefix=cache/${{ github.repository }}/,manifests_prefix=cache/${{ github.repository }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }} cache-to: type=s3,blobs_prefix=cache/${{ github.repository }}/,manifests_prefix=cache/${{ github.repository }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }},mode=max + - name: Extract vendor/bundle from container + run: | + docker create --name bundle ${{ steps.build.outputs.imageid }} + rm -rf vendor/bundle || true + docker cp bundle:/app/vendor/bundle vendor/bundle + docker rm bundle + - name: Save vendor/bundle + id: save-vendor-bundle + uses: actions/cache/save@v4 + with: + path: | + vendor/bundle + key: ${{ steps.restore-vendor-bundle.outputs.cache-primary-key }} - name: Test # We only test the native container. If that fails the builds for the others # will be cancelled as well. diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile old mode 100644 new mode 100755 index 828c7e6ec711..4bb22a22851a --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -58,15 +58,8 @@ COPY vendor ./vendor # Add lib in case a plugin tries to load VERSION file under lib COPY lib ./lib -RUN \ - bundle config set --local path 'vendor/bundle' && \ - bundle config set --local without 'test development' && \ - bundle install --quiet --no-cache --jobs=8 --retry=3 && \ - bundle config set deployment 'true' && \ - cp Gemfile.lock Gemfile.lock.bak && \ - rm -rf vendor/bundle/ruby/*/cache && \ - rm -rf vendor/bundle/ruby/*/gems/*/spec && \ - rm -rf vendor/bundle/ruby/*/gems/*/test +COPY ./docker/prod/setup/bundle-install.sh ./vendor/bundle* ./vendor/ +RUN bash vendor/bundle-install.sh && rm vendor/bundle-install.sh COPY . . diff --git a/docker/prod/setup/bundle-install.sh b/docker/prod/setup/bundle-install.sh new file mode 100644 index 000000000000..d2c0d740ee15 --- /dev/null +++ b/docker/prod/setup/bundle-install.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e + +# temporary 'seed' for working ppc64 cached vendor/bundle +if [ ! -d vendor/bundle ] && [ -n "$(uname -a | grep ppc64)" ]; then + wget https://openproject-public.s3.eu-central-1.amazonaws.com/ruby/bundle/openproject-release-15.2-836aec00b1-vendor-bundle.tar.gz + tar -xf openproject-release-15.2-836aec00b1-vendor-bundle.tar.gz +fi + +bundle config set --local path 'vendor/bundle' +bundle config set --local without 'test development' +bundle install --jobs=8 --retry=3 +bundle config set deployment 'true' +cp Gemfile.lock Gemfile.lock.bak +rm -rf vendor/bundle/ruby/*/cache +rm -rf vendor/bundle/ruby/*/gems/*/spec +rm -rf vendor/bundle/ruby/*/gems/*/test From 449b14e6c1dfadc904f8507aa0514a2cf76c3576 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Tue, 21 Jan 2025 12:50:34 -0300 Subject: [PATCH 06/14] Set debounce to 0ms in (Rails) test environment Ensures feature specs run without debounce. --- .../op-autocompleter/op-autocompleter.component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts index 87b2c56212ad..86696c1e2c30 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component.ts @@ -466,7 +466,7 @@ export class OpAutocompleterComponent !!(this.defaultData || this.getOptionsFn)), distinctUntilChanged(), tap(() => this.loading$.next(true)), - debounceTime(this.debounceTimeMs), + debounceTime(this.debounceTimeForCurrentEnvironment), switchMap((queryString:string) => { if (this.relations && this.url) { return this.fetchFromUrl(queryString); @@ -522,6 +522,10 @@ export class OpAutocompleterComponent Date: Tue, 21 Jan 2025 12:53:13 -0300 Subject: [PATCH 07/14] Rehabilitate broken op-autocompleter ng spec --- .../op-autocompleter/op-autocompleter.spec.ts | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts index f11cf76723d3..7fd0b1196f19 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts @@ -1,16 +1,16 @@ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { States } from 'core-app/core/states/states.service'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; -import { of } from 'rxjs'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { of, map } from 'rxjs'; import { NgSelectModule } from '@ng-select/ng-select'; -import { By } from '@angular/platform-browser'; -import { OpAutocompleterService } from './services/op-autocompleter.service'; import { OpAutocompleterComponent } from './op-autocompleter.component'; +import { By } from '@angular/platform-browser'; describe('autocompleter', () => { let fixture:ComponentFixture; - let opAutocompleterServiceSpy:jasmine.SpyObj; + let getOptionsFnSpy: jasmine.Spy; const workPackagesStub = [ { id: 1, @@ -51,26 +51,20 @@ describe('autocompleter', () => { ]; beforeEach(() => { - opAutocompleterServiceSpy = jasmine.createSpyObj('OpAutocompleterService', ['loadData']); - TestBed.configureTestingModule({ - declarations: [ - OpAutocompleterComponent], - providers: [ - // { provide: OpAutocompleterService, useValue: opAutocompleterServiceSpyFactory } - ], + declarations: [OpAutocompleterComponent], + providers: [States], imports: [HttpClientTestingModule, NgSelectModule], schemas: [NO_ERRORS_SCHEMA], - }) - .overrideComponent( - OpAutocompleterComponent, - { set: { providers: [{ provide: OpAutocompleterService, useValue: opAutocompleterServiceSpy }] } }, - ) - .compileComponents(); + }).compileComponents(); fixture = TestBed.createComponent(OpAutocompleterComponent); + getOptionsFnSpy = jasmine.createSpy("getOptionsFn").and.callFake((searchTerm:string) => { + return of(workPackagesStub).pipe( + map((wps) => wps.filter((wp) => searchTerm !== "" && wp.subject.includes(searchTerm))) + ) + }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment fixture.componentInstance.resource = 'work_packages' as TOpAutocompleterResource; fixture.componentInstance.filters = []; fixture.componentInstance.searchKey = 'subjectOrId'; @@ -79,11 +73,8 @@ describe('autocompleter', () => { fixture.componentInstance.closeOnSelect = true; fixture.componentInstance.virtualScroll = true; fixture.componentInstance.classes = 'wp-relations-autocomplete'; - fixture.componentInstance.defaultData = true; + fixture.componentInstance.getOptionsFn = getOptionsFnSpy; fixture.componentInstance.debounceTimeMs = 0; - - // @ts-ignore - opAutocompleterServiceSpy.loadData.and.returnValue(of(workPackagesStub)); }); it('should load the ng-select correctly', () => { @@ -101,20 +92,36 @@ describe('autocompleter', () => { tick(1000); fixture.detectChanges(); const select = fixture.componentInstance.ngSelectInstance; - expect(fixture.componentInstance.ngSelectInstance.isOpen).toBeFalse(); - fixture.componentInstance.ngSelectInstance.open(); - fixture.componentInstance.ngSelectInstance.focus(); - expect(fixture.componentInstance.ngSelectInstance.isOpen).toBeTrue(); - select.filter('a'); + expect(select.isOpen).toBeFalse(); + select.open(); + select.focus(); + expect(select.isOpen).toBeTrue(); + + expect(select.itemsList.items.length).toEqual(0); + + const inputDebugElement = fixture.debugElement.query(By.css('input[role=combobox]')); + const inputElement = inputDebugElement.nativeElement as HTMLInputElement; fixture.detectChanges(); - tick(1000); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith(""); + + inputElement.value = "Wor"; + inputElement.dispatchEvent(new Event('input')); fixture.detectChanges(); - tick(1000); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith("Wor"); - expect(opAutocompleterServiceSpy.loadData).toHaveBeenCalledWith('a', - fixture.componentInstance.resource, fixture.componentInstance.filters, fixture.componentInstance.searchKey); + fixture.detectChanges(); + expect(select.itemsList.items.length).toEqual(2); - expect(fixture.componentInstance.ngSelectInstance.itemsList.items.length).toEqual(2); + inputElement.value = "package 2"; + inputElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith("package 2"); + + fixture.detectChanges(); + expect(select.itemsList.items.length).toEqual(1); })); }); From 197022b4a6b032209b5d1087838a46ceb71be37a Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Tue, 21 Jan 2025 21:15:40 -0300 Subject: [PATCH 08/14] Add specs for op-autocompleter with debounce --- .../op-autocompleter/op-autocompleter.spec.ts | 105 ++++++++++++------ 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts index 7fd0b1196f19..4fa871f9a4b0 100644 --- a/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts +++ b/frontend/src/app/shared/components/autocompleter/op-autocompleter/op-autocompleter.spec.ts @@ -85,43 +85,84 @@ describe('autocompleter', () => { }); }); - it('should load WorkPackages', fakeAsync(() => { - tick(); - fixture.detectChanges(); - fixture.componentInstance.ngAfterViewInit(); - tick(1000); - fixture.detectChanges(); - const select = fixture.componentInstance.ngSelectInstance; - expect(select.isOpen).toBeFalse(); - select.open(); - select.focus(); - expect(select.isOpen).toBeTrue(); + describe('without debounce', () => { + it('should load items', fakeAsync(() => { + tick(); + fixture.detectChanges(); + fixture.componentInstance.ngAfterViewInit(); + tick(1000); + fixture.detectChanges(); + const select = fixture.componentInstance.ngSelectInstance; + expect(select.isOpen).toBeFalse(); + select.open(); + select.focus(); + expect(select.isOpen).toBeTrue(); - expect(select.itemsList.items.length).toEqual(0); + expect(select.itemsList.items.length).toEqual(0); - const inputDebugElement = fixture.debugElement.query(By.css('input[role=combobox]')); - const inputElement = inputDebugElement.nativeElement as HTMLInputElement; + const inputDebugElement = fixture.debugElement.query(By.css('input[role=combobox]')); + const inputElement = inputDebugElement.nativeElement as HTMLInputElement; - fixture.detectChanges(); - tick(); - expect(getOptionsFnSpy).toHaveBeenCalledWith(""); + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith(""); - inputElement.value = "Wor"; - inputElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - tick(); - expect(getOptionsFnSpy).toHaveBeenCalledWith("Wor"); + inputElement.value = "Wor"; + inputElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith("Wor"); - fixture.detectChanges(); - expect(select.itemsList.items.length).toEqual(2); + fixture.detectChanges(); + expect(select.itemsList.items.length).toEqual(2); - inputElement.value = "package 2"; - inputElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - tick(); - expect(getOptionsFnSpy).toHaveBeenCalledWith("package 2"); + inputElement.value = "package 2"; + inputElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).toHaveBeenCalledWith("package 2"); - fixture.detectChanges(); - expect(select.itemsList.items.length).toEqual(1); - })); + fixture.detectChanges(); + expect(select.itemsList.items.length).toEqual(1); + })); + }); + + describe('with debounce', () => { + beforeEach(() => { + fixture.componentInstance.debounceTimeMs = 50; + }); + + it('should load items with debounce', fakeAsync(() => { + tick(); + fixture.detectChanges(); + fixture.componentInstance.ngAfterViewInit(); + tick(1000); + fixture.detectChanges(); + const select = fixture.componentInstance.ngSelectInstance; + expect(select.isOpen).toBeFalse(); + select.open(); + select.focus(); + expect(select.isOpen).toBeTrue(); + + expect(select.itemsList.items.length).toEqual(0); + + const inputDebugElement = fixture.debugElement.query(By.css('input[role=combobox]')); + const inputElement = inputDebugElement.nativeElement as HTMLInputElement; + + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).not.toHaveBeenCalled(); + tick(50); + expect(getOptionsFnSpy).toHaveBeenCalledWith(""); + getOptionsFnSpy.calls.reset(); + + inputElement.value = "Wor"; + inputElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + tick(); + expect(getOptionsFnSpy).not.toHaveBeenCalled(); + tick(50); + expect(getOptionsFnSpy).toHaveBeenCalledWith("Wor"); + })); + }); }); From 8163a315699fb81493c82e35093d9055870f3cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 22 Jan 2025 07:18:31 +0100 Subject: [PATCH 09/14] Update languages available in crowdin --- publiccode.yml | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/publiccode.yml b/publiccode.yml index fd4d1c2a50c1..d28e06a50130 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -51,17 +51,47 @@ legal: localisation: localisationReady: true availableLanguages: + - af + - ar + - bg + - ca + - cs + - da - de - - fr - - co + - el + - en + - eo - es - - mm - - mn + - et + - fa + - fi + - fil + - fr + - hr + - hu + - id + - it + - ja + - ko + - lt + - ms - nl - - at - - gr - - se - - us + - no + - pl + - pt-BR + - pt-PT + - ro + - ru + - si + - sk + - sl + - sv + - th + - tr + - uk + - vi + - zh-CN + - zh-TW description: en: localisedName: OpenProject From 4b360b84e3f644cd9346b9b67ea53d6b5a3042a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 22 Jan 2025 07:22:39 +0100 Subject: [PATCH 10/14] Update release notes --- docs/release-notes/15-2-0/README.md | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/15-2-0/README.md b/docs/release-notes/15-2-0/README.md index e7e9fc4a20b1..41fedc9923f3 100644 --- a/docs/release-notes/15-2-0/README.md +++ b/docs/release-notes/15-2-0/README.md @@ -3,12 +3,12 @@ title: OpenProject 15.2.0 sidebar_navigation: title: 15.2.0 release_version: 15.2.0 -release_date: 2024-12-23 +release_date: 2025-01-22 --- # OpenProject 15.2.0 -Release date: 2024-12-23 +Release date: 2025-01-22 We released [OpenProject 15.2.0](https://community.openproject.org/versions/2143). 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. @@ -90,16 +90,35 @@ We continued introducing standardized components for page headers and subheaders - Feature: When adding new relations, auto-scroll to show the newly added relation \[[#59769](https://community.openproject.org/wp/59769)\] - Feature: Create new icon for setting reminders \[[#59793](https://community.openproject.org/wp/59793)\] - Feature: Export cost query as timesheet PDF \[[#59824](https://community.openproject.org/wp/59824)\] -- Feature: Generate PDF document from a work package description \[[#45896](https://community.openproject.org/wp/45896)\] +- Feature: Improve comprehensibility of the "Add relations" modal \[[#60462](https://community.openproject.org/wp/60462)\] - Bugfix: Mobile: tap twice on comment input to start typing \[[#57107](https://community.openproject.org/wp/57107)\] +- Bugfix: Activity panel (Notification center goes into mobile layout even on a desktop when the browser on desktop \[[#59235](https://community.openproject.org/wp/59235)\] - Bugfix: Folders missing in log lines for "Unexpected Content Error" \[[#59346](https://community.openproject.org/wp/59346)\] - Bugfix: Activity tab does not scroll to the bottom or correct comment on mobile \[[#59458](https://community.openproject.org/wp/59458)\] +- Bugfix: Activity only shows 1 value even if several were updated \[[#59855](https://community.openproject.org/wp/59855)\] +- Bugfix: User Hovercard rendering is bumpy \[[#59879](https://community.openproject.org/wp/59879)\] +- Bugfix: User hovercard is showing on User own profile page and other users profile page \[[#59898](https://community.openproject.org/wp/59898)\] +- Bugfix: User hovercard is showing behind the Meeting participants overlay \[[#59907](https://community.openproject.org/wp/59907)\] +- Bugfix: Impossible to group by CF hierarchy multi-select \[[#59920](https://community.openproject.org/wp/59920)\] - Bugfix: Proto plugin dose not work with OpenProject 15 \[[#59931](https://community.openproject.org/wp/59931)\] - Bugfix: Project membership in group administration lists global roles \[[#59934](https://community.openproject.org/wp/59934)\] - Bugfix: Internal server error on Azure OIDC login with expired client secret \[[#59960](https://community.openproject.org/wp/59960)\] - Bugfix: OpenID setup fails due to Claims is not a valid JSON object \[[#59962](https://community.openproject.org/wp/59962)\] +- Bugfix: Wrong locale of error message while personal API access token creation \[[#60025](https://community.openproject.org/wp/60025)\] - Bugfix: Filter translations for Meetings Module missing \[[#60113](https://community.openproject.org/wp/60113)\] -- Bugfix: New WP form doesn't open in split view when on the WP list page \[[#60274](https://community.openproject.org/wp/60274)\] +- Bugfix: Saving a new WP triggers browser warning message \[[#60133](https://community.openproject.org/wp/60133)\] +- Bugfix: Meeting creator is not added as invitee by default + All meetings menu point should not have a filter by default \[[#60287](https://community.openproject.org/wp/60287)\] +- Bugfix: Titles do not always use App Title \[[#60371](https://community.openproject.org/wp/60371)\] +- Bugfix: No connection error after folder creation in file picker \[[#60384](https://community.openproject.org/wp/60384)\] +- Bugfix: Non working days not shown on calendar widget \[[#60410](https://community.openproject.org/wp/60410)\] +- Bugfix: Distance between sticky buttons and form field above is too small in scrollable modals \[[#60430](https://community.openproject.org/wp/60430)\] +- Bugfix: Reminders generate two or more lines for a work package in notification center, clicking one selects all \[[#60449](https://community.openproject.org/wp/60449)\] +- Bugfix: The 'set reminder' action is available to users who are not signed in \[[#60458](https://community.openproject.org/wp/60458)\] +- Bugfix: ActionView::Template::Error happening in MessagesController#show \[[#60478](https://community.openproject.org/wp/60478)\] +- Bugfix: Reminder menu item is not placed correctly \[[#60501](https://community.openproject.org/wp/60501)\] +- Bugfix: Vanishing filters in "Work package table"-widgets \[[#60546](https://community.openproject.org/wp/60546)\] +- Bugfix: Remove permission restriction for users to set their own reminders \[[#60568](https://community.openproject.org/wp/60568)\] +- Bugfix: Relations dropdown capitalizes wrong in German \[[#60627](https://community.openproject.org/wp/60627)\] From 909509a9d882c113e50ac56135e5467946479426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 22 Jan 2025 07:22:39 +0100 Subject: [PATCH 11/14] Add release-notes file --- docs/release-notes/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md index cdca676d40d3..71adb167afa1 100644 --- a/docs/release-notes/README.md +++ b/docs/release-notes/README.md @@ -13,6 +13,13 @@ Stay up to date and get an overview of the new features included in the releases +## 15.2.0 + +Release date: 2025-01-22 + +[Release Notes](15-2-0/) + + ## 15.1.1 Release date: 2025-01-13 From 9220493af1026c717f8112490064e97f2bf015e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 22 Jan 2025 07:22:39 +0100 Subject: [PATCH 12/14] Update publiccode.yml --- publiccode.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/publiccode.yml b/publiccode.yml index d28e06a50130..a78fc47fe74a 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -7,8 +7,8 @@ name: OpenProject applicationSuite: openDesk url: 'https://github.com/opf/openproject' roadmap: 'https://www.openproject.org/roadmap' -releaseDate: '2025-01-21' -softwareVersion: '15.1.1' +releaseDate: '2025-01-22' +softwareVersion: '15.2.0' developmentStatus: stable softwareType: standalone/web platforms: From e8ec335df33163342787125fd1d7e2ea0771c5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 22 Jan 2025 07:22:41 +0100 Subject: [PATCH 13/14] Bumped version to 15.2.1 [ci skip] --- lib/open_project/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 0cc92323beb0..4c9dbff1eddc 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -33,7 +33,7 @@ module OpenProject module VERSION # :nodoc: MAJOR = 15 MINOR = 2 - PATCH = 0 + PATCH = 1 class << self # Used by semver to define the special version (if any). From ae7cfe0b631f5af4d14cdc71ef3dbd35e5d573a1 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Thu, 23 Jan 2025 03:12:35 +0000 Subject: [PATCH 14/14] update locales from crowdin [ci skip] --- modules/auth_saml/config/locales/crowdin/ja.yml | 12 ++++++------ modules/calendar/config/locales/crowdin/js-ja.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/auth_saml/config/locales/crowdin/ja.yml b/modules/auth_saml/config/locales/crowdin/ja.yml index 14d2ae752710..d8a442c4228b 100644 --- a/modules/auth_saml/config/locales/crowdin/ja.yml +++ b/modules/auth_saml/config/locales/crowdin/ja.yml @@ -5,7 +5,7 @@ ja: display_name: Name identifier: Identifier secret: Secret - scope: Scope + scope: スコープ assertion_consumer_service_url: ACS (Assertion consumer service) URL limit_self_registration: Limit self registration sp_entity_id: Service entity ID @@ -32,8 +32,8 @@ ja: certificate_expired: "is expired and can no longer be used." unmatched_private_key: "does not belong to the given certificate" saml: - menu_title: SAML providers - delete_title: Delete SAML provider + menu_title: SAML プロバイダ + delete_title: SAML プロバイダの削除 info: title: "SAML Protocol Configuration Parameters" description: > @@ -45,15 +45,15 @@ ja: providers: label_empty_title: "No SAML providers configured yet." label_empty_description: "Add a provider to see them here." - label_automatic_configuration: Automatic configuration - label_metadata: Metadata + label_automatic_configuration: 自動設定 + label_metadata: メタデータ label_metadata_endpoint: OpenProject metadata endpoint label_openproject_information: OpenProject information label_configuration_details: "Identity provider endpoints and certificates" label_configuration_encryption: "Signatures and Encryption" label_add_new: New SAML identity provider label_edit: Edit SAML identity provider %{name} - label_uid: Internal user id + label_uid: 内部ユーザーID label_mapping: Mapping label_requested_attribute_for: "Requested attribute for: %{attribute}" no_results_table: No SAML identity providers have been defined yet. diff --git a/modules/calendar/config/locales/crowdin/js-ja.yml b/modules/calendar/config/locales/crowdin/js-ja.yml index a5b4d1b19951..3db814f32943 100644 --- a/modules/calendar/config/locales/crowdin/js-ja.yml +++ b/modules/calendar/config/locales/crowdin/js-ja.yml @@ -5,4 +5,4 @@ ja: create_new: '新しいカレンダーを作成' title: 'カレンダー' too_many: '全部で %{count} 個の作業項目がありますが、 %{max} 個しか表示できません。' - unsaved_title: '未命名カレンダー' + unsaved_title: '新しいカレンダー'