Merge remote-tracking branch 'origin/release/11.3' into dev

pull/9390/head
ulferts 3 years ago
commit d458232b51
No known key found for this signature in database
GPG Key ID: A205708DE1284017
  1. 2
      Gemfile.lock
  2. 4
      app/views/admin/settings/authentication_settings/show.html.erb
  3. 2
      docs/installation-and-operations/misc/custom-openid-connect-providers/README.md
  4. 14
      docs/installation-and-operations/operation/control/README.md
  5. 28
      docs/release-notes/11-3-2/README.md
  6. 7
      docs/release-notes/README.md
  7. 10
      docs/user-guide/agile-boards/README.md
  8. 7
      docs/user-guide/project-overview/README.md
  9. 21
      frontend/src/app/features/invite-user-modal/principal/principal.component.ts
  10. 15
      frontend/src/app/features/projects/components/copy-project/copy-project.component.ts
  11. 4
      frontend/src/app/features/projects/components/projects/projects.component.ts
  12. 20
      frontend/src/app/features/work-packages/components/filters/filter-searchable-multiselect-value/filter-searchable-multiselect-value.component.ts
  13. 2
      modules/overviews/config/locales/crowdin/pt.yml
  14. 76
      spec/lib/i18n/pluralization_spec.rb

@ -27,7 +27,7 @@ GIT
GIT GIT
remote: https://github.com/opf/openproject-translations.git remote: https://github.com/opf/openproject-translations.git
revision: ec6fbe6ef86f82e65f37adb17f37aa5addc17ac4 revision: b28dbe0bc4f347e79f34cd5b42cff2f03f2f7404
branch: dev branch: dev
specs: specs:
openproject-translations (7.4.0) openproject-translations (7.4.0)

@ -81,10 +81,10 @@ See docs/COPYRIGHT.rdoc for more details.
<div class="form--field -wide-label"> <div class="form--field -wide-label">
<label><b><%= I18n.t :note %>: </b> <label><b><%= I18n.t :note %>: </b>
<%= <%=
url = 'https://github.com/opf/openproject/blob/dev/doc/CONFIGURATION.md#disable-password-login' url = 'https://docs.openproject.org/installation-and-operations/configuration/#disable-password-login'
explanation = I18n.t :note_password_login_disabled, explanation = I18n.t :note_password_login_disabled,
configuration: "<a href=\"#{url}\"> #{I18n.t('label_configuration')}</a>" configuration: "<a target=\"_blank\" href=\"#{url}\"> #{I18n.t('label_configuration')}</a>"
explanation.html_safe explanation.html_safe
%> %>

@ -49,7 +49,7 @@ You can copy that into the console to get the URL you need.
Finally you can the write the actual setting like this: Finally you can the write the actual setting like this:
```ruby ```ruby
Setting.plugin_openproject_openid_connect = Hash(Setting.plugin_openproject_openid_connect).deep_merge({ Setting.plugin_openproject_openid_connect = Hash(Setting.plugin_openproject_openid_connect || {}).deep_merge({
"providers" => { "providers" => {
"okta" => options "okta" => options
} }

@ -76,7 +76,7 @@ sudo openproject restart web
## Docker-based installation ## All-in-one Docker-based installation
#### Run commands like rake tasks or rails console #### Run commands like rake tasks or rails console
@ -124,3 +124,15 @@ Launch an interactive console to directly interact with the underlying Ruby on R
docker exec -it $CIT bash -c "RAILS_ENV=production rails console" docker exec -it $CIT bash -c "RAILS_ENV=production rails console"
``` ```
## docker-compose based installation
#### Spawn a rails console
You can spawn an interactive shell in your docker-compose setup container to run commands in the OpenProject environment.
The following command will spawn a Rails console in the container:
```bash
docker-compose run web bash -c "RAILS_ENV=production bundle exec rails console"
```

@ -0,0 +1,28 @@
---
title: OpenProject 11.3.2
sidebar_navigation:
title: 11.3.2
release_version: 11.3.2
release_date: 2021-06-10
---
# OpenProject 11.3.2
Release date: 2021-06-10
We released [OpenProject 11.3.2](https://community.openproject.com/versions/1480).
The release contains several bug fixes and we recommend updating to the newest version.
<!--more-->
#### Bug fixes and changes
- Fixed: Not possible to create or edit projects if relative url root configured \[[#37571](https://community.openproject.com/wp/37571)\]
- Fixed: Internal server error on custom fields view when using Slovene language \[[#37607](https://community.openproject.com/wp/37607)\]
- Fixed: Not possible to invite users via modal if relative url root configured \[[#37618](https://community.openproject.com/wp/37618)\]
#### Contributions
A big thanks to community members for reporting bugs and helping us identifying and providing fixes.
Special thanks for reporting and finding bugs go to
Christina Vechkanova

@ -12,6 +12,13 @@ Stay up to date and get an overview of the new features included in the releases
<!--- New release notes are generated below. Do not remove comment. --> <!--- New release notes are generated below. Do not remove comment. -->
<!--- RELEASE MARKER --> <!--- RELEASE MARKER -->
## 11.3.2
Release date: 2021-06-10
[Release Notes](11-3-2/)
## 11.3.1 ## 11.3.1
Release date: 2021-06-08 Release date: 2021-06-08

@ -63,17 +63,17 @@ After [adding lists to your board](#add-lists-to-your-board) they will automatic
There are several **types of Action boards** available: There are several **types of Action boards** available:
**Status board:** Each list represents a status. That means that e.g. all work packages with the status "New" will be automatically displayed in the column "New". #### Status board: Each list represents a status. That means that e.g. all work packages with the status "New" will be automatically displayed in the column "New".
When creating a new Status board a list with all work packages in the default status (usually this is the status "New") will be added automatically, while additional lists need to be added manually. When creating a new Status board a list with all work packages in the default status (usually this is the status "New") will be added automatically, while additional lists need to be added manually.
Please note: You can't move work packages from or to every status. Please find out more about the work-flow logics restricting this here: [Allowed transitions between status](../../system-admin-guide/manage-work-packages/work-package-workflows/) Please note: You can't move work packages from or to every status. Please find out more about the work-flow logics restricting this here: [Allowed transitions between status](../../system-admin-guide/manage-work-packages/work-package-workflows/)
**Assignee board:** Every list represents one assignee. You can choose regular users, [placeholder users](../../system-admin-guide/users-permissions/placeholder-users) and groups as assignees. #### Assignee board: Every list represents one assignee. You can choose regular users, [placeholder users](../../system-admin-guide/users-permissions/placeholder-users) and groups as assignees.
**Version board:** Every list represents a version. This board is ideal for product development or planning software releases. When creating a new Version board a list with all work packages in the version(s) belonging to the current project will be added automatically, while additional lists need to be added manually. #### Version board: Every list represents a version. This board is ideal for product development or planning software releases. When creating a new Version board a list with all work packages in the version(s) belonging to the current project will be added automatically, while additional lists need to be added manually.
**Subproject board:** Every list represents a subproject. Within the list you will find the subproject's work packages. #### Subproject board: Every list represents a subproject. Within the list you will find the subproject's work packages.
**Parent-Child board:** Every list represents a parent work package. Within the list you will find the work package's children. #### Parent-Child board: Every list represents a parent work package. Within the list you will find the work package's children.
Only work packages from the current project can be selected as a list, i.e. can be chosen as the name of the list. Only work packages from the current project can be selected as a list, i.e. can be chosen as the name of the list.
The Parent-Child board is ideal for depicting a **work breakdown structure (WBS)**. The Parent-Child board is ideal for depicting a **work breakdown structure (WBS)**.
Please note: This will only display one hierarchy level below the displayed work package, i.e. only immediate children and no grandchildren. Please note: This will only display one hierarchy level below the displayed work package, i.e. only immediate children and no grandchildren.

@ -15,6 +15,7 @@ The **Project overview** page is a dashboard with important information about yo
| ------------------------------------------------------------ | -------------------------------------------------------- | | ------------------------------------------------------------ | -------------------------------------------------------- |
| [What is the project overview?](#what-is-the-project-overview) | What can I do with the project overview page? | | [What is the project overview?](#what-is-the-project-overview) | What can I do with the project overview page? |
| [Add a widget to the project overview](#add-a-widget-to-the-project-overview) | How can I add a new widget to the project overview? | | [Add a widget to the project overview](#add-a-widget-to-the-project-overview) | How can I add a new widget to the project overview? |
| [Project status](#project-status) | Set your project status |
| [Available project overview widgets](#available-project-overview-widgets) | What kind of widgets can I add to the project overview? | | [Available project overview widgets](#available-project-overview-widgets) | What kind of widgets can I add to the project overview? |
| [Re-size and re-order widgets](#re-size-and-re-order-widgets) | How can I re-order or re-size the widgets? | | [Re-size and re-order widgets](#re-size-and-re-order-widgets) | How can I re-order or re-size the widgets? |
| [Remove widgets](#remove-widget-from-project-overview-page) | How can I remove widgets from the project overview page? | | [Remove widgets](#remove-widget-from-project-overview-page) | How can I remove widgets from the project overview page? |
@ -49,6 +50,12 @@ Choose the most appropriate type of widget from the list.
## Project status
On the project overview page, you can set your project status and give a detailed description. The project status is a widget that you add to your project overview. Find the description [below](#project-status-widget).
## Available project overview widgets ## Available project overview widgets
You can add various widgets to your project overview. You can add various widgets to your project overview.

@ -1,15 +1,19 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, } from '@angular/core'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, } from '@angular/core';
import { HttpClient } from "@angular/common/http"; import { HttpClient } from "@angular/common/http";
import { FormControl, FormGroup, Validators, } from '@angular/forms'; import {
import { I18nService } from "core-app/core/i18n/i18n.service"; FormGroup,
import { HalResource } from "core-app/features/hal/resources/hal-resource"; FormControl,
import { PrincipalData, PrincipalLike } from "core-app/shared/components/principal/principal-types"; Validators,
import { ProjectResource } from "core-app/features/hal/resources/project-resource"; } from '@angular/forms';
import { DynamicFormComponent } from "core-app/shared/components/dynamic-forms/components/dynamic-form/dynamic-form.component"
import { PrincipalType } from '../invite-user.component'; import { PrincipalType } from '../invite-user.component';
import { take } from 'rxjs/internal/operators/take'; import { take } from 'rxjs/internal/operators/take';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { APIV3Service } from "core-app/core/apiv3/api-v3.service"; import { APIV3Service } from 'core-app/core/apiv3/api-v3.service';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { DynamicFormComponent } from "core-app/shared/components/dynamic-forms/components/dynamic-form/dynamic-form.component";
import { PrincipalData, PrincipalLike } from "core-app/shared/components/principal/principal-types";
import { ProjectResource } from "core-app/features/hal/resources/project-resource";
import { HalResource } from "core-app/features/hal/resources/hal-resource";
function extractCustomFieldsFromSchema(schema:IOPFormSettings['_embedded']['schema']) { function extractCustomFieldsFromSchema(schema:IOPFormSettings['_embedded']['schema']) {
return Object.keys(schema) return Object.keys(schema)
@ -120,8 +124,7 @@ export class PrincipalComponent implements OnInit {
readonly httpClient:HttpClient, readonly httpClient:HttpClient,
readonly apiV3Service:APIV3Service, readonly apiV3Service:APIV3Service,
readonly cdRef:ChangeDetectorRef, readonly cdRef:ChangeDetectorRef,
) { ) {}
}
ngOnInit() { ngOnInit() {
this.principalControl?.setValue(this.principalData.principal); this.principalControl?.setValue(this.principalData.principal);

@ -1,18 +1,17 @@
import { Component, OnInit } from '@angular/core';
import { StateService } from "@uirouter/core";
import { UntilDestroyedMixin } from "core-app/shared/helpers/angular/until-destroyed.mixin";
import { PathHelperService } from "core-app/core/path-helper/path-helper.service";
import { HalSource } from "core-app/features/hal/resources/hal-resource";
import { import {
IDynamicFieldGroupConfig, IDynamicFieldGroupConfig,
IOPFormlyFieldSettings, IOPFormlyFieldSettings,
IOPFormlyTemplateOptions, IOPFormlyTemplateOptions,
} from "core-app/shared/components/dynamic-forms/typings"; } from "core-app/shared/components/dynamic-forms/typings";
import { I18nService } from "core-app/core/i18n/i18n.service";
import { APIV3Service } from "core-app/core/apiv3/api-v3.service";
import { JobStatusModal } from "core-app/features/job-status/job-status-modal/job-status.modal"; import { JobStatusModal } from "core-app/features/job-status/job-status-modal/job-status.modal";
import { OpModalService } from "core-app/shared/components/modal/modal.service"; import { APIV3Service } from "core-app/core/apiv3/api-v3.service";
import { I18nService } from "core-app/core/i18n/i18n.service";
import { PathHelperService } from "core-app/core/path-helper/path-helper.service";
import { UntilDestroyedMixin } from "core-app/shared/helpers/angular/until-destroyed.mixin";
import { CurrentProjectService } from "core-app/core/current-project/current-project.service"; import { CurrentProjectService } from "core-app/core/current-project/current-project.service";
import { OpModalService } from "core-app/shared/components/modal/modal.service";
import { Component, OnInit } from "@angular/core";
import { StateService } from "@uirouter/core/lib/state/stateService";
@Component({ @Component({
selector: 'op-copy-project', selector: 'op-copy-project',

@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { StateService } from "@uirouter/core"; import { StateService } from "@uirouter/core";
import { UntilDestroyedMixin } from "core-app/shared/helpers/angular/until-destroyed.mixin";
import { PathHelperService } from "core-app/core/path-helper/path-helper.service";
import { IOPFormlyFieldSettings } from "core-app/shared/components/dynamic-forms/typings"; import { IOPFormlyFieldSettings } from "core-app/shared/components/dynamic-forms/typings";
import { UntilDestroyedMixin } from "core-app/shared/helpers/angular/until-destroyed.mixin";
import { CurrentProjectService } from "core-app/core/current-project/current-project.service"; import { CurrentProjectService } from "core-app/core/current-project/current-project.service";
import { PathHelperService } from "core-app/core/path-helper/path-helper.service";
@Component({ @Component({
selector: 'app-projects', selector: 'app-projects',

@ -1,8 +1,3 @@
import { HalResource } from "core-app/features/hal/resources/hal-resource";
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { AngularTrackingHelpers } from 'core-app/shared/helpers/angular/tracking-functions';
import { NgSelectComponent } from '@ng-select/ng-select'; import { NgSelectComponent } from '@ng-select/ng-select';
import { APIV3Service } from 'core-app/core/apiv3/api-v3.service'; import { APIV3Service } from 'core-app/core/apiv3/api-v3.service';
import { DebouncedRequestSwitchmap, errorNotificationHandler } from 'core-app/shared/helpers/rxjs/debounced-input-switchmap'; import { DebouncedRequestSwitchmap, errorNotificationHandler } from 'core-app/shared/helpers/rxjs/debounced-input-switchmap';
@ -18,6 +13,12 @@ import { QueryFilterInstanceResource } from "core-app/features/hal/resources/que
import { HalResourceService } from "core-app/features/hal/services/hal-resource.service"; import { HalResourceService } from "core-app/features/hal/services/hal-resource.service";
import { HalResourceSortingService } from "core-app/features/hal/services/hal-resource-sorting.service"; import { HalResourceSortingService } from "core-app/features/hal/services/hal-resource-sorting.service";
import { HalResourceNotificationService } from "core-app/features/hal/services/hal-resource-notification.service"; import { HalResourceNotificationService } from "core-app/features/hal/services/hal-resource-notification.service";
import { AfterViewInit, ChangeDetectionStrategy,
ChangeDetectorRef,
Component, EventEmitter, Input, NgZone, OnInit, Output, ViewChild } from '@angular/core';
import { AngularTrackingHelpers } from "core-app/shared/helpers/angular/tracking-functions";
import { HalResource } from "core-app/features/hal/resources/hal-resource";
import { I18nService } from "core-app/core/i18n/i18n.service";
@Component({ @Component({
selector: 'filter-searchable-multiselect-value', selector: 'filter-searchable-multiselect-value',
@ -65,7 +66,8 @@ export class FilterSearchableMultiselectValueComponent extends UntilDestroyedMix
readonly cdRef:ChangeDetectorRef, readonly cdRef:ChangeDetectorRef,
readonly I18n:I18nService, readonly I18n:I18nService,
protected currentProject:CurrentProjectService, protected currentProject:CurrentProjectService,
readonly halNotification:HalResourceNotificationService) { readonly halNotification:HalResourceNotificationService,
readonly ngZone:NgZone) {
super(); super();
} }
@ -127,7 +129,13 @@ export class FilterSearchableMultiselectValueComponent extends UntilDestroyedMix
if (this.ngSelectInstance) { if (this.ngSelectInstance) {
const component = (this.ngSelectInstance) as any; const component = (this.ngSelectInstance) as any;
if (component && component.dropdownPanel) { if (component && component.dropdownPanel) {
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
component.dropdownPanel._updatePosition(); component.dropdownPanel._updatePosition();
}, 25);
});
} }
} }
} }

@ -1,4 +1,4 @@
pt: pt:
overviews: overviews:
label: 'Visão geral' label: 'Visão geral'
permission_manage_overview: 'Gerenciar a página de visão geral' permission_manage_overview: 'Gerenciar página de visão geral'

@ -0,0 +1,76 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe I18n, 'pluralization', type: :helper do
describe 'with slowenian language and the :two plural key missing' do
before do
I18n.locale = :sl
allow(I18n.backend)
.to(receive(:lookup))
.and_call_original
allow(I18n.backend)
.to(receive(:lookup))
.with(:sl, :label_x_projects, any_args)
.and_return({one: "1 projekt", other: "%{count} projektov", zero: "Brez projektov"})
end
it 'allows to pluralize without exceptions (Regression #37607)', :aggregate_failures do
expect(I18n.t(:label_x_projects, count: 0)).to eq 'Brez projektov'
expect(I18n.t(:label_x_projects, count: 1)).to eq '1 projekt'
expect(I18n.t(:label_x_projects, count: 2)).to eq '2 projektov'
expect(I18n.t(:label_x_projects, count: 10)).to eq '10 projektov'
expect(I18n.t(:label_x_projects, count: 20)).to eq '20 projektov'
end
end
describe 'with slowenian language and the :other plural key missing' do
before do
I18n.locale = :sl
allow(I18n.backend)
.to(receive(:lookup))
.and_call_original
allow(I18n.backend)
.to(receive(:lookup))
.with(:sl, :label_x_projects, any_args)
.and_return({one: "1 projekt", zero: "Brez projektov"})
end
it 'falls back to english translation (Regression #37607)', :aggregate_failures do
expect(I18n.t(:label_x_projects, count: 0)).to eq 'Brez projektov'
expect(I18n.t(:label_x_projects, count: 1)).to eq '1 projekt'
expect(I18n.t(:label_x_projects, count: 2)).to eq '2 projects'
expect(I18n.t(:label_x_projects, count: 10)).to eq '10 projects'
expect(I18n.t(:label_x_projects, count: 20)).to eq '20 projects'
end
end
end
Loading…
Cancel
Save