From efc1c713acae1ce7aaea87c7302d92a671e5f9ac Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Thu, 8 Feb 2024 09:54:30 +0100 Subject: [PATCH 001/165] Update Primer to version 0.22.1 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- frontend/package-lock.json | 48 +++++++++++++++++++------------------- frontend/package.json | 4 ++-- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Gemfile b/Gemfile index 2c9db7c6e658..3ac0f6305848 100644 --- a/Gemfile +++ b/Gemfile @@ -382,4 +382,4 @@ end gem 'openproject-octicons', '~>19.8.0' gem 'openproject-octicons_helper', '~>19.8.0' -gem 'openproject-primer_view_components', '~>0.20.0' +gem 'openproject-primer_view_components', '~>0.22.1' diff --git a/Gemfile.lock b/Gemfile.lock index 720531b1b0cd..f332354f81b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -756,7 +756,7 @@ GEM actionview openproject-octicons (= 19.8.0) railties - openproject-primer_view_components (0.20.0) + openproject-primer_view_components (0.22.1) actionview (>= 5.0.0) activesupport (>= 5.0.0) openproject-octicons (>= 19.8.0) @@ -1227,7 +1227,7 @@ DEPENDENCIES openproject-octicons (~> 19.8.0) openproject-octicons_helper (~> 19.8.0) openproject-openid_connect! - openproject-primer_view_components (~> 0.20.0) + openproject-primer_view_components (~> 0.22.1) openproject-recaptcha! openproject-reporting! openproject-storages! diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8724aacec69b..5f438d0585f3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "@ngneat/content-loader": "^7.0.0", "@ngx-formly/core": "^6.1.4", "@openproject/octicons-angular": "^19.8.0", - "@openproject/primer-view-components": "^0.20.0", + "@openproject/primer-view-components": "^0.22.1", "@openproject/reactivestates": "^3.0.1", "@primer/css": "^21.1.1", "@uirouter/angular": "^12.0.0", @@ -4491,9 +4491,9 @@ } }, "node_modules/@oddbird/popover-polyfill": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@oddbird/popover-polyfill/-/popover-polyfill-0.3.7.tgz", - "integrity": "sha512-WNthEIPPXnFQkumLby6yVxhyOcA/GtMnlByHwEglMO9WZckoaqidnpLp2JFzAh2RDOZxn+Xt3ffSMKId9cPjOQ==" + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@oddbird/popover-polyfill/-/popover-polyfill-0.3.8.tgz", + "integrity": "sha512-+aK7EHL3VggfsWGVqUwvtli2+kP5OWyseAsrefhzR2XWoi2oALUCeoDn63i5WS3ZOmLiXHRNBwHPeta8w+aM1g==" }, "node_modules/@openproject/octicons-angular": { "version": "19.8.0", @@ -4510,9 +4510,9 @@ } }, "node_modules/@openproject/primer-view-components": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.20.0.tgz", - "integrity": "sha512-RWSLLS3PvyXyqXB53l4foQcb4hfOd8l+LWVedOHbYa+8nWVotkgi1TUrZCeIRjIOuTQrmLNx2xyBcmANcktQAw==", + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.22.1.tgz", + "integrity": "sha512-WYGvo5j60fhe0wQAQBLTekQbpOFQERAszMXN8H5Koil2GkTmyBnsGhYvujAbapb0JuFigtZ9YMLby6D6f6j7FA==", "dependencies": { "@github/auto-check-element": "^5.2.0", "@github/auto-complete-element": "^3.6.0", @@ -4523,7 +4523,7 @@ "@github/include-fragment-element": "^6.1.1", "@github/relative-time-element": "^4.0.0", "@github/tab-container-element": "^3.1.2", - "@oddbird/popover-polyfill": "^0.3.6", + "@oddbird/popover-polyfill": "^0.3.8", "@primer/behaviors": "^1.3.4" } }, @@ -4595,9 +4595,9 @@ }, "node_modules/@primer/view-components": { "name": "@openproject/primer-view-components", - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.20.0.tgz", - "integrity": "sha512-RWSLLS3PvyXyqXB53l4foQcb4hfOd8l+LWVedOHbYa+8nWVotkgi1TUrZCeIRjIOuTQrmLNx2xyBcmANcktQAw==", + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.22.1.tgz", + "integrity": "sha512-WYGvo5j60fhe0wQAQBLTekQbpOFQERAszMXN8H5Koil2GkTmyBnsGhYvujAbapb0JuFigtZ9YMLby6D6f6j7FA==", "dependencies": { "@github/auto-check-element": "^5.2.0", "@github/auto-complete-element": "^3.6.0", @@ -4608,7 +4608,7 @@ "@github/include-fragment-element": "^6.1.1", "@github/relative-time-element": "^4.0.0", "@github/tab-container-element": "^3.1.2", - "@oddbird/popover-polyfill": "^0.3.6", + "@oddbird/popover-polyfill": "^0.3.8", "@primer/behaviors": "^1.3.4" } }, @@ -23681,9 +23681,9 @@ "optional": true }, "@oddbird/popover-polyfill": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@oddbird/popover-polyfill/-/popover-polyfill-0.3.7.tgz", - "integrity": "sha512-WNthEIPPXnFQkumLby6yVxhyOcA/GtMnlByHwEglMO9WZckoaqidnpLp2JFzAh2RDOZxn+Xt3ffSMKId9cPjOQ==" + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@oddbird/popover-polyfill/-/popover-polyfill-0.3.8.tgz", + "integrity": "sha512-+aK7EHL3VggfsWGVqUwvtli2+kP5OWyseAsrefhzR2XWoi2oALUCeoDn63i5WS3ZOmLiXHRNBwHPeta8w+aM1g==" }, "@openproject/octicons-angular": { "version": "19.8.0", @@ -23694,9 +23694,9 @@ } }, "@openproject/primer-view-components": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.20.0.tgz", - "integrity": "sha512-RWSLLS3PvyXyqXB53l4foQcb4hfOd8l+LWVedOHbYa+8nWVotkgi1TUrZCeIRjIOuTQrmLNx2xyBcmANcktQAw==", + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.22.1.tgz", + "integrity": "sha512-WYGvo5j60fhe0wQAQBLTekQbpOFQERAszMXN8H5Koil2GkTmyBnsGhYvujAbapb0JuFigtZ9YMLby6D6f6j7FA==", "requires": { "@github/auto-check-element": "^5.2.0", "@github/auto-complete-element": "^3.6.0", @@ -23707,7 +23707,7 @@ "@github/include-fragment-element": "^6.1.1", "@github/relative-time-element": "^4.0.0", "@github/tab-container-element": "^3.1.2", - "@oddbird/popover-polyfill": "^0.3.6", + "@oddbird/popover-polyfill": "^0.3.8", "@primer/behaviors": "^1.3.4" } }, @@ -23752,7 +23752,7 @@ "integrity": "sha512-1XRx8FwWxrr8SSZit2C9KxaofTi0CELKbGmHGpmYQmRIAECIa912Emp4BlAC7iQmf3Tb5oZOkke5zuAt+seDxg==", "requires": { "@primer/primitives": "^7.12.0", - "@primer/view-components": "npm:@openproject/primer-view-components@^0.20.0" + "@primer/view-components": "npm:@openproject/primer-view-components@^0.22.1" } }, "@primer/primitives": { @@ -23761,9 +23761,9 @@ "integrity": "sha512-tiJEMxy5hDi9a3YxgrBeJScLPUQSLuWsKDNuoXXiX7zLzejnYdxXXG3qOaNHzNyyn8TkSQkzmKx0ioaSLR2zNw==" }, "@primer/view-components": { - "version": "npm:@openproject/primer-view-components@0.20.0", - "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.20.0.tgz", - "integrity": "sha512-RWSLLS3PvyXyqXB53l4foQcb4hfOd8l+LWVedOHbYa+8nWVotkgi1TUrZCeIRjIOuTQrmLNx2xyBcmANcktQAw==", + "version": "npm:@openproject/primer-view-components@0.22.1", + "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.22.1.tgz", + "integrity": "sha512-WYGvo5j60fhe0wQAQBLTekQbpOFQERAszMXN8H5Koil2GkTmyBnsGhYvujAbapb0JuFigtZ9YMLby6D6f6j7FA==", "requires": { "@github/auto-check-element": "^5.2.0", "@github/auto-complete-element": "^3.6.0", @@ -23774,7 +23774,7 @@ "@github/include-fragment-element": "^6.1.1", "@github/relative-time-element": "^4.0.0", "@github/tab-container-element": "^3.1.2", - "@oddbird/popover-polyfill": "^0.3.6", + "@oddbird/popover-polyfill": "^0.3.8", "@primer/behaviors": "^1.3.4" } }, diff --git a/frontend/package.json b/frontend/package.json index 66462226a544..39f8595686d7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -97,7 +97,7 @@ "@ngneat/content-loader": "^7.0.0", "@ngx-formly/core": "^6.1.4", "@openproject/octicons-angular": "^19.8.0", - "@openproject/primer-view-components": "^0.20.0", + "@openproject/primer-view-components": "^0.22.1", "@openproject/reactivestates": "^3.0.1", "@primer/css": "^21.1.1", "@uirouter/angular": "^12.0.0", @@ -175,6 +175,6 @@ "generate-typings": "tsc -d -p src/tsconfig.app.json" }, "overrides": { - "@primer/view-components": "npm:@openproject/primer-view-components@^0.20.0" + "@primer/view-components": "npm:@openproject/primer-view-components@^0.22.1" } } From 0ef47db88826da90e56d76d5fede1ab77986167e Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Fri, 9 Feb 2024 13:06:12 +0100 Subject: [PATCH 002/165] Append the ngSelect dropdown to the dialog as it would otherwise be invisible behind the dialog --- .../_autocomplete_select_decoration.html.erb | 3 +- ...utocomplete-select-decoration.component.ts | 52 +++++++++---------- .../op-autocompleter.component.ts | 2 +- .../open_project/forms/autocompleter.html.erb | 3 +- ...package_to_meeting_form_component.html.erb | 2 +- .../forms/meeting_agenda_item/meeting_form.rb | 10 +++- 6 files changed, 39 insertions(+), 33 deletions(-) diff --git a/app/views/augmented/_autocomplete_select_decoration.html.erb b/app/views/augmented/_autocomplete_select_decoration.html.erb index 030e04b84df9..e96307d43051 100644 --- a/app/views/augmented/_autocomplete_select_decoration.html.erb +++ b/app/views/augmented/_autocomplete_select_decoration.html.erb @@ -2,9 +2,10 @@ <%= content_tag :'opce-select-decoration', {}, data: { - "multiselect": multiple, + multiple:, "input-name": input_name, "input-id": input_id, + "append-to": defined?(append_to) ? append_to : 'body', key:, options: JSON.dump(select_options), } %> diff --git a/frontend/src/app/shared/components/autocompleter/autocomplete-select-decoration/autocomplete-select-decoration.component.ts b/frontend/src/app/shared/components/autocompleter/autocomplete-select-decoration/autocomplete-select-decoration.component.ts index 4b25578cfe8b..57c912fad341 100644 --- a/frontend/src/app/shared/components/autocompleter/autocomplete-select-decoration/autocomplete-select-decoration.component.ts +++ b/frontend/src/app/shared/components/autocompleter/autocomplete-select-decoration/autocomplete-select-decoration.component.ts @@ -27,13 +27,17 @@ //++ import { - Component, ElementRef, OnInit, ViewChild, + AfterViewInit, + Component, + OnInit, + ViewChild, } from '@angular/core'; import { NgSelectComponent } from '@ng-select/ng-select'; -import { I18nService } from 'core-app/core/i18n/i18n.service'; -import { HalResource } from 'core-app/features/hal/resources/hal-resource'; -import { IProjectAutocompleterData } from 'core-app/shared/components/autocompleter/project-autocompleter/project-autocompleter.component'; import { IProjectAutocompleteItem } from 'core-app/shared/components/autocompleter/project-autocompleter/project-autocomplete-item'; +import { + IAutocompleteItem, + OpAutocompleterComponent, +} from 'core-app/shared/components/autocompleter/op-autocompleter/op-autocompleter.component'; type SelectItem = { label:string, value:string, selected?:boolean }; @@ -44,10 +48,10 @@ export const autocompleteSelectDecorationSelector = 'autocomplete-select-decorat @@ -56,10 +60,10 @@ export const autocompleteSelectDecorationSelector = 'autocomplete-select-decorat [items]="options" [labelForId]="labelForId" bindLabel="label" - [multiple]="multiselect" + [multiple]="multiple" [virtualScroll]="true" [ngModel]="selected" - appendTo="body" + [appendTo]="appendTo" [placeholder]="text.placeholder" (ngModelChange)="updateSelection($event)"> @@ -69,14 +73,11 @@ export const autocompleteSelectDecorationSelector = 'autocomplete-select-decorat `, selector: autocompleteSelectDecorationSelector, }) -export class AutocompleteSelectDecorationComponent implements OnInit { +export class AutocompleteSelectDecorationComponent extends OpAutocompleterComponent implements OnInit, AfterViewInit { @ViewChild(NgSelectComponent) public ngSelectComponent:NgSelectComponent; public options:SelectItem[]; - /** Whether we're a multiselect */ - public multiselect = false; - /** Get the selected options */ public selected:SelectItem|SelectItem[]; @@ -86,9 +87,6 @@ export class AutocompleteSelectDecorationComponent implements OnInit { /** The input name we're syncing selections to */ private syncInputFieldName:string; - /** The input id used for label */ - public labelForId:string; - /** The field key (e.g. status, type, or project) */ public key:string; @@ -96,24 +94,19 @@ export class AutocompleteSelectDecorationComponent implements OnInit { placeholder: this.I18n.t('js.placeholders.selection'), }; - constructor( - protected elementRef:ElementRef, - readonly I18n:I18nService, - ) { - } - ngOnInit():void { const element = this.elementRef.nativeElement as HTMLElement; // Set options - this.multiselect = element.dataset.multiselect === 'true'; - this.labelForId = element.dataset.inputId!; + this.multiple = element.dataset.multiple === 'true'; + this.labelForId = element.dataset.inputId; this.key = element.dataset.key!; + this.appendTo = element.dataset.appendTo; // Get the sync target this.syncInputFieldName = element.dataset.inputName!; - // Add Rails multiple identifier if multiselect - if (this.multiselect) { + // Add Rails multiple identifier if multiple + if (this.multiple) { this.syncInputFieldName += '[]'; } @@ -127,7 +120,7 @@ export class AutocompleteSelectDecorationComponent implements OnInit { this.setInitialProjectSelection(); } - if (!this.multiselect) { + if (!this.multiple) { this.selected = (this.selected as SelectItem[])[0]; } @@ -137,6 +130,11 @@ export class AutocompleteSelectDecorationComponent implements OnInit { element.parentElement!.hidden = false; } + // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method + ngAfterViewInit():void { + // do nothing and prevent the parent hook to be called + } + setInitialSelection(data:SelectItem[]):void { this.updateSelection(data.filter((element) => element.selected)); } @@ -185,7 +183,7 @@ export class AutocompleteSelectDecorationComponent implements OnInit { const items = _.castArray(this.selected); if (items.length === 0) return; - if (this.multiselect) { + if (this.multiple) { this.currentProjectSelection = items.map((item:SelectItem) => ({ id: item.value, name: item.label, 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 65a810354fb0..d7cbb1e966b7 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 @@ -195,7 +195,7 @@ export class OpAutocompleterComponent <% else %> <%= angular_component_tag 'opce-autocompleter', diff --git a/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_form_component.html.erb b/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_form_component.html.erb index f663caa2b5de..6a449f6915ab 100644 --- a/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_form_component.html.erb +++ b/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_form_component.html.erb @@ -16,7 +16,7 @@ end end flex.with_row do - render(MeetingAgendaItem::MeetingForm.new(f)) + render(MeetingAgendaItem::MeetingForm.new(f, wrapper_id: 'add-work-package-to-meeting-dialog')) end flex.with_row(mt: 3) do render(MeetingAgendaItem::Notes.new(f)) diff --git a/modules/meeting/app/forms/meeting_agenda_item/meeting_form.rb b/modules/meeting/app/forms/meeting_agenda_item/meeting_form.rb index 40b19297e2b6..3617285ef9e5 100644 --- a/modules/meeting/app/forms/meeting_agenda_item/meeting_form.rb +++ b/modules/meeting/app/forms/meeting_agenda_item/meeting_form.rb @@ -38,7 +38,8 @@ class MeetingAgendaItem::MeetingForm < ApplicationForm caption: I18n.t("label_meeting_selection_caption"), autocomplete_options: { multiple: false, - decorated: true + decorated: true, + append_to: append_to_container } ) do |select| MeetingAgendaItems::CreateContract @@ -53,8 +54,13 @@ class MeetingAgendaItem::MeetingForm < ApplicationForm end end - def initialize(disabled: false) + def initialize(disabled: false, wrapper_id: nil) super() @disabled = disabled + @wrapper_id = wrapper_id + end + + def append_to_container + @wrapper_id.nil? ? 'body' : "##{@wrapper_id}" end end From 33652f5fb0a70ca162088a6e3cb354b1d563d343 Mon Sep 17 00:00:00 2001 From: Pavel Balashou Date: Tue, 13 Feb 2024 11:54:33 +0100 Subject: [PATCH 003/165] [#52287] Consent always shown in Browser language despite user's language being set differently https://community.openproject.org/work_packages/52287 --- .../accounts/authentication_stages.rb | 28 +++++++++++++++++++ app/helpers/user_consent_helper.rb | 6 ++-- app/services/set_localization_service.rb | 28 +++++++++++++++++++ .../account/_user_consent_check.html.erb | 2 +- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/app/controllers/concerns/accounts/authentication_stages.rb b/app/controllers/concerns/accounts/authentication_stages.rb index 1ddb7bf5fbd4..c2524f58e16d 100644 --- a/app/controllers/concerns/accounts/authentication_stages.rb +++ b/app/controllers/concerns/accounts/authentication_stages.rb @@ -1,3 +1,31 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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. +#++ + module Accounts::AuthenticationStages def successful_authentication(user, reset_stages: true, just_registered: false) stages = authentication_stages after_activation: just_registered, reset: reset_stages diff --git a/app/helpers/user_consent_helper.rb b/app/helpers/user_consent_helper.rb index dbf945c51c1d..0b4bdbdfe89f 100644 --- a/app/helpers/user_consent_helper.rb +++ b/app/helpers/user_consent_helper.rb @@ -37,16 +37,14 @@ def user_consent_required? end ## - # Gets consent instructions for the given user. + # Gets consent instructions. # - # @param user [User] The user to get instructions for. # @param locale [String] ISO-639-1 code for the desired locale (e.g. de, en, fr). # `I18n.locale` is set for each request individually depending # among other things on the user's Accept-Language headers. # @return [String] Instructions in the respective language. - def user_consent_instructions(_user, locale: I18n.locale) + def user_consent_instructions(locale) all = Setting.consent_info - all.fetch(locale.to_s) { all.values.first } end diff --git a/app/services/set_localization_service.rb b/app/services/set_localization_service.rb index 9249a5342640..013aeab942b2 100644 --- a/app/services/set_localization_service.rb +++ b/app/services/set_localization_service.rb @@ -1,3 +1,31 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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. +#++ + class SetLocalizationService attr_reader :user, :http_accept_header diff --git a/app/views/account/_user_consent_check.html.erb b/app/views/account/_user_consent_check.html.erb index c59978007828..62ec2b7cf441 100644 --- a/app/views/account/_user_consent_check.html.erb +++ b/app/views/account/_user_consent_check.html.erb @@ -1,6 +1,6 @@