From 5c7a9434d859b345897cdb942161cfddd80959ef Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Sat, 22 Mar 2025 11:58:56 +0300 Subject: [PATCH 001/260] Define @mention criterion for restricted comments- blueprint https://community.openproject.org/wp/60988 --- .../activities_tab/index_component.rb | 3 +- .../journals/restricted_note_form.rb | 2 +- app/models/queries/principals.rb | 1 + .../mentionable_on_work_package_filter.rb | 5 +-- ...cted_mentionable_on_work_package_filter.rb | 40 +++++++++++++++++++ .../src/app/core/path-helper/apiv3-paths.ts | 13 ++++-- .../quote-comment.controller.ts | 2 +- .../restricted-comment.controller.ts | 13 ++++-- 8 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb diff --git a/app/components/work_packages/activities_tab/index_component.rb b/app/components/work_packages/activities_tab/index_component.rb index ac3749569da..baa6b34dc6e 100644 --- a/app/components/work_packages/activities_tab/index_component.rb +++ b/app/components/work_packages/activities_tab/index_component.rb @@ -80,7 +80,8 @@ module WorkPackages action: index_stimulus_controller(":onSubmit-end@window->#{restricted_comment_stimulus_controller}#onSubmitEnd"), restricted_comment_stimulus_controller("-highlight-class") => "work-packages-activities-tab-journals-new-component--journal-notes-body__restricted-comment", # rubocop:disable Layout/LineLength restricted_comment_stimulus_controller("-hidden-class") => "d-none", - restricted_comment_stimulus_controller("-#{index_stimulus_controller}-outlet") => "##{wrapper_key}" + restricted_comment_stimulus_controller("-#{index_stimulus_controller}-outlet") => "##{wrapper_key}", + restricted_comment_stimulus_controller("-is-restricted-value") => false # Initial value } end diff --git a/app/forms/work_packages/activities_tab/journals/restricted_note_form.rb b/app/forms/work_packages/activities_tab/journals/restricted_note_form.rb index 41a22021e83..30e8b5dd9ba 100644 --- a/app/forms/work_packages/activities_tab/journals/restricted_note_form.rb +++ b/app/forms/work_packages/activities_tab/journals/restricted_note_form.rb @@ -36,7 +36,7 @@ module WorkPackages::ActivitiesTab::Journals checked: false, data: { "work-packages--activities-tab--restricted-comment-target": "restrictedCheckbox", - action: "input->work-packages--activities-tab--restricted-comment#toggleBackgroundColor" + action: "input->work-packages--activities-tab--restricted-comment#toggleRestriction" } ) end diff --git a/app/models/queries/principals.rb b/app/models/queries/principals.rb index 378f53019ef..8197f099cac 100644 --- a/app/models/queries/principals.rb +++ b/app/models/queries/principals.rb @@ -32,6 +32,7 @@ module Queries::Principals filter Filters::TypeFilter filter Filters::MemberFilter filter Filters::MentionableOnWorkPackageFilter + filter Filters::RestrictedMentionableOnWorkPackageFilter filter Filters::StatusFilter filter Filters::NameFilter filter Filters::AnyNameAttributeFilter diff --git a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb index a5d6d0ff847..57858b5c44e 100644 --- a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb @@ -28,8 +28,7 @@ # See COPYRIGHT and LICENSE files for more details. # ++ -class Queries::Principals::Filters::MentionableOnWorkPackageFilter < - Queries::Principals::Filters::PrincipalFilter +class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Principals::Filters::PrincipalFilter def allowed_values raise NotImplementedError, "There would be too many candidates" end @@ -47,7 +46,7 @@ class Queries::Principals::Filters::MentionableOnWorkPackageFilter < end def human_name - "mentionable" # intenral use + "mentionable" # Internal use end def apply_to(query_scope) diff --git a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb new file mode 100644 index 00000000000..4b7c004b84f --- /dev/null +++ b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# -- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +# ++ + +class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < + Queries::Principals::Filters::MentionableOnWorkPackageFilter + def key + :restricted_mentionable_on_work_package + end + + def human_name + "restricted mentionable" # Internal use + end +end diff --git a/frontend/src/app/core/path-helper/apiv3-paths.ts b/frontend/src/app/core/path-helper/apiv3-paths.ts index 8a3bf707569..dfba48f969c 100644 --- a/frontend/src/app/core/path-helper/apiv3-paths.ts +++ b/frontend/src/app/core/path-helper/apiv3-paths.ts @@ -46,8 +46,15 @@ export class ApiV3Paths { // that are members of that project: filters.add('member', '=', [(workPackage.project as HalResource).id as string]); } else { + const addCommentElement = document.getElementById('work-packages-activities-tab-add-comment-component'); + const isRestricted = addCommentElement?.getAttribute('data-work-packages--activities-tab--restricted-comment-is-restricted-value') === 'true'; + // that are mentionable on the work package - filters.add('mentionable_on_work_package', '=', [workPackage.id.toString()]); + if (addCommentElement && isRestricted) { + filters.add('restricted_mentionable_on_work_package', '=', [workPackage.id.toString()]); + } else { + filters.add('mentionable_on_work_package', '=', [workPackage.id.toString()]); + } } // That are users: filters.add('type', '=', ['User', 'Group']); @@ -57,8 +64,6 @@ export class ApiV3Paths { filters.add('name', '~', [term]); } - return `${this.apiV3Base - }/principals?${ - filters.toParams({ sortBy: '[["name","asc"]]', offset: '1', pageSize: '10' })}`; + return `${this.apiV3Base}/principals?${filters.toParams({ sortBy: '[["name","asc"]]', offset: '1', pageSize: '10' })}`; } } diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/quote-comment.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/quote-comment.controller.ts index d516935d742..b6febbd3039 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/quote-comment.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/quote-comment.controller.ts @@ -83,7 +83,7 @@ export default class QuoteCommentController extends Controller { private setCommentRestriction(isRestricted:boolean) { if (isRestricted && !this.workPackagesActivitiesTabRestrictedCommentOutlet.restrictedCheckboxTarget.checked) { this.workPackagesActivitiesTabRestrictedCommentOutlet.restrictedCheckboxTarget.checked = isRestricted; - this.workPackagesActivitiesTabRestrictedCommentOutlet.toggleBackgroundColor(); + this.workPackagesActivitiesTabRestrictedCommentOutlet.toggleRestriction(); } } diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts index fc79466e670..01ed6fc9905 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts @@ -36,23 +36,30 @@ export default class RestrictedCommentController extends Controller { static outlets = ['work-packages--activities-tab--index']; static classes = ['highlight', 'hidden']; + static values = { + isRestricted: { type: Boolean, default: false }, + }; + declare readonly restrictedCheckboxTarget:HTMLInputElement; declare readonly formContainerTarget:HTMLElement; declare readonly learnMoreLinkTarget:HTMLAnchorElement; declare readonly workPackagesActivitiesTabIndexOutlet:IndexController; - declare readonly highlightClass:string; declare readonly hiddenClass:string; + declare isRestrictedValue:boolean; + onSubmitEnd(_event:CustomEvent):void { - this.toggleBackgroundColor(); + this.toggleRestriction(); } - toggleBackgroundColor():void { + toggleRestriction():void { const isChecked = this.restrictedCheckboxTarget.checked; this.formContainerTarget.classList.toggle(this.highlightClass, isChecked); this.toggleLearnMoreLink(isChecked); + + this.isRestrictedValue = isChecked; } private toggleLearnMoreLink(isChecked:boolean):void { From e61b0447ee45b27e71d91bd3e03587f72e0764ee Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Fri, 21 Mar 2025 10:05:22 +0100 Subject: [PATCH 002/260] scaffold settings page for activities --- .../header_component.html.erb | 3 ++ .../work_packages/activities_controller.rb | 37 +++++++++++++++++++ .../settings/work_packages_controller.rb | 2 + .../work_packages/activities/show.html.erb | 32 ++++++++++++++++ .../settings/work_packages/show.html.erb | 5 +++ config/initializers/menus.rb | 3 +- config/initializers/permissions.rb | 1 + config/routes.rb | 1 + .../projects/work_packages_settings_spec.rb | 14 ++++++- spec/routing/project_settings_routing_spec.rb | 14 +++++++ 10 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 app/controllers/projects/settings/work_packages/activities_controller.rb create mode 100644 app/views/projects/settings/work_packages/activities/show.html.erb diff --git a/app/components/settings/project_work_packages/header_component.html.erb b/app/components/settings/project_work_packages/header_component.html.erb index 2e9adcffcc2..46b857b392f 100644 --- a/app/components/settings/project_work_packages/header_component.html.erb +++ b/app/components/settings/project_work_packages/header_component.html.erb @@ -46,6 +46,9 @@ See COPYRIGHT and LICENSE files for more details. tab.with_text { t("attributes.custom_values") } end end + tab_nav.with_tab(selected: selected?(:activities), href: project_settings_work_packages_activities_path) do |tab| + tab.with_text { t("label_activity") } + end end end %> diff --git a/app/controllers/projects/settings/work_packages/activities_controller.rb b/app/controllers/projects/settings/work_packages/activities_controller.rb new file mode 100644 index 00000000000..b1db79446d2 --- /dev/null +++ b/app/controllers/projects/settings/work_packages/activities_controller.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +class Projects::Settings::WorkPackages::ActivitiesController < Projects::SettingsController + menu_item :settings_work_packages + + def update + redirect_to :show + end +end diff --git a/app/controllers/projects/settings/work_packages_controller.rb b/app/controllers/projects/settings/work_packages_controller.rb index 69ef4f49f6c..1f02129df55 100644 --- a/app/controllers/projects/settings/work_packages_controller.rb +++ b/app/controllers/projects/settings/work_packages_controller.rb @@ -38,6 +38,8 @@ class Projects::Settings::WorkPackagesController < Projects::SettingsController redirect_to project_settings_work_packages_categories_path elsif User.current.allowed_in_project?(:select_custom_fields, @project) redirect_to project_settings_work_packages_custom_fields_path + elsif User.current.allowed_in_project?(:edit_project, @project) + redirect_to project_settings_work_packages_activities_path end end end diff --git a/app/views/projects/settings/work_packages/activities/show.html.erb b/app/views/projects/settings/work_packages/activities/show.html.erb new file mode 100644 index 00000000000..1ea3a215e43 --- /dev/null +++ b/app/views/projects/settings/work_packages/activities/show.html.erb @@ -0,0 +1,32 @@ +<%#-- copyright +OpenProject is an open source project management software. +Copyright (C) the OpenProject GmbH + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 3. + +OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +Copyright (C) 2006-2013 Jean-Philippe Lang +Copyright (C) 2010-2013 the ChiliProject Team + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +See COPYRIGHT and LICENSE files for more details. + +++#%> + +<%= render(Settings::ProjectWorkPackages::HeaderComponent.new(@project, selected: :activities)) %> + +Form goes here diff --git a/app/views/projects/settings/work_packages/show.html.erb b/app/views/projects/settings/work_packages/show.html.erb index faf53e6873f..bafacf45d8b 100644 --- a/app/views/projects/settings/work_packages/show.html.erb +++ b/app/views/projects/settings/work_packages/show.html.erb @@ -26,6 +26,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. See COPYRIGHT and LICENSE files for more details. ++#%> + +<% + # this file is a fallback and in normal circunstances should never be rendered +%> + <%= render Primer::OpenProject::PageHeader.new do |header| header.with_title { t(:label_work_package_plural) } diff --git a/config/initializers/menus.rb b/config/initializers/menus.rb index cfa5291483f..28e9b9c535c 100644 --- a/config/initializers/menus.rb +++ b/config/initializers/menus.rb @@ -653,7 +653,8 @@ Redmine::MenuManager.map :project_menu do |menu| work_packages: { caption: :label_work_package_plural, if: ->(project) { - User.current.allowed_in_project?(:manage_types, project) || + User.current.allowed_in_project?(:edit_project, project) || + User.current.allowed_in_project?(:manage_types, project) || User.current.allowed_in_project?(:manage_categories, project) || User.current.allowed_in_project?(:select_custom_fields, project) } diff --git a/config/initializers/permissions.rb b/config/initializers/permissions.rb index eda5478685c..9d32d9f7c47 100644 --- a/config/initializers/permissions.rb +++ b/config/initializers/permissions.rb @@ -101,6 +101,7 @@ Rails.application.reloader.to_prepare do "projects/settings/general": %i[show], "projects/settings/storage": %i[show], "projects/settings/work_packages": %i[show], + "projects/settings/work_packages/activities": %i[show update], "projects/templated": %i[create destroy], "projects/identifier": %i[show update] }, diff --git a/config/routes.rb b/config/routes.rb index 9d448e89d0c..d15b9fed4cd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -280,6 +280,7 @@ Rails.application.routes.draw do get :categories, to: redirect("projects/%{project_id}/settings/work_packages/categories") resource :work_packages, only: %i[show] namespace :work_packages do + resource :activities, only: %i[show update] resource :types, only: %i[show update] resource :custom_fields, only: %i[show update] resource :categories, only: %i[show update] diff --git a/spec/features/projects/work_packages_settings_spec.rb b/spec/features/projects/work_packages_settings_spec.rb index c3cf8bd111c..2c6060306ec 100644 --- a/spec/features/projects/work_packages_settings_spec.rb +++ b/spec/features/projects/work_packages_settings_spec.rb @@ -72,11 +72,23 @@ RSpec.describe "Projects", "work packages settings menu", :js do end end - context "when the user does not have access to any tabs" do + context "when the user has access to the activities tab" do let(:permissions) { %i(edit_project view_work_packages) } current_user { create(:user, member_with_permissions: { project => permissions }) } + it "displays the custom fields tab" do + work_packages_settings_page.visit! + expect(page).to have_css(".tabnav-tab", text: "Activity") + expect(page).to have_css("span", text: "Form goes here") + end + end + + context "when the user does not have access to any tabs" do + let(:permissions) { %i(view_work_packages) } + + current_user { create(:user, member_with_permissions: { project => permissions }) } + it "does not display the menu entry" do general_settings_page.visit! expect(page).to have_no_css(".op-menu--item-title", text: "Work packages") diff --git a/spec/routing/project_settings_routing_spec.rb b/spec/routing/project_settings_routing_spec.rb index a2587c92c29..88880864c68 100644 --- a/spec/routing/project_settings_routing_spec.rb +++ b/spec/routing/project_settings_routing_spec.rb @@ -106,5 +106,19 @@ RSpec.describe Projects::SettingsController do controller: "projects/settings/work_packages/types", action: "update", project_id: "123" ) end + + it do + expect(get("/projects/123/settings/work_packages/activities")) + .to route_to( + controller: "projects/settings/work_packages/activities", action: "show", project_id: "123" + ) + end + + it do + expect(patch("/projects/123/settings/work_packages/activities")) + .to route_to( + controller: "projects/settings/work_packages/activities", action: "update", project_id: "123" + ) + end end end From 31f65ec4ffc53515073d13f14bcf057802779828 Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Fri, 21 Mar 2025 16:11:35 +0100 Subject: [PATCH 003/260] store project settings data and include feature specs --- .../work_packages/activities_controller.rb | 19 ++++++- app/models/project.rb | 1 + .../work_packages/activities/show.html.erb | 13 ++++- config/locales/en.yml | 1 + .../settings/activities_settings_spec.rb | 57 +++++++++++++++++++ .../work_packages_settings_spec.rb | 2 +- .../pages/projects/settings/activities.rb | 51 +++++++++++++++++ 7 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 spec/features/projects/settings/activities_settings_spec.rb rename spec/features/projects/{ => settings}/work_packages_settings_spec.rb (98%) create mode 100644 spec/support/pages/projects/settings/activities.rb diff --git a/app/controllers/projects/settings/work_packages/activities_controller.rb b/app/controllers/projects/settings/work_packages/activities_controller.rb index b1db79446d2..18a756f1174 100644 --- a/app/controllers/projects/settings/work_packages/activities_controller.rb +++ b/app/controllers/projects/settings/work_packages/activities_controller.rb @@ -32,6 +32,23 @@ class Projects::Settings::WorkPackages::ActivitiesController < Projects::Setting menu_item :settings_work_packages def update - redirect_to :show + enabled = ActiveRecord::Type::Boolean.new.cast(expected_params[:enabled_comments_with_restricted_visibility]) + result = Projects::UpdateService + .new(user: current_user, model: @project, contract_class: Projects::SettingsContract) + .call(enabled_comments_with_restricted_visibility: enabled) + + if result.success? + flash[:notice] = t("notice_successful_update") + else + flash[:error] = t("notice_unsuccessful_update") + end + + redirect_to project_settings_work_packages_activities_path + end + + private + + def expected_params + params.expect(project: [:enabled_comments_with_restricted_visibility]) end end diff --git a/app/models/project.rb b/app/models/project.rb index f368c165fa2..79440b6a6fa 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -99,6 +99,7 @@ class Project < ApplicationRecord validates_associated :available_life_cycle_steps, on: :saving_life_cycle_steps store_attribute :settings, :deactivate_work_package_attachments, :boolean + store_attribute :settings, :enabled_comments_with_restricted_visibility, :boolean acts_as_favorable diff --git a/app/views/projects/settings/work_packages/activities/show.html.erb b/app/views/projects/settings/work_packages/activities/show.html.erb index 1ea3a215e43..c8f1b2c66fe 100644 --- a/app/views/projects/settings/work_packages/activities/show.html.erb +++ b/app/views/projects/settings/work_packages/activities/show.html.erb @@ -29,4 +29,15 @@ See COPYRIGHT and LICENSE files for more details. <%= render(Settings::ProjectWorkPackages::HeaderComponent.new(@project, selected: :activities)) %> -Form goes here +<%= + # this could be exctracted into a Form component + form_for @project, + url: project_settings_work_packages_activities_path(@project), + method: :patch, + html: { id: "activities-form" } do |f| +%> + <%= f.check_box :enabled_comments_with_restricted_visibility %> + <%= f.label :enabled_comments_with_restricted_visibility, "Enable comments with restricted visibility" %> +

Helper text here

+ <%= f.submit "Save" %> +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 8afc1681081..42ffa81138b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3367,6 +3367,7 @@ en: notice_successful_delete: "Successful deletion." notice_successful_cancel: "Successful cancellation." notice_successful_update: "Successful update." + notice_unsuccessful_update: "Update failed." notice_successful_update_custom_fields_added_to_project: | Successful update. The custom fields of the activated types are automatically activated on the work package form. See more. diff --git a/spec/features/projects/settings/activities_settings_spec.rb b/spec/features/projects/settings/activities_settings_spec.rb new file mode 100644 index 00000000000..31238e0041b --- /dev/null +++ b/spec/features/projects/settings/activities_settings_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +RSpec.describe "WorkPackages-Settings-Activities", :js do + let!(:project) { create(:project) } + let(:activities_settings_page) { Pages::Projects::Settings::Activities.new(project) } + + current_user { create(:admin) } + + it "enables and disables the settings for the project" do + activities_settings_page.visit! + expect(page).to have_css("#activities-form") + + expect(page).to have_field(:project_enabled_comments_with_restricted_visibility, checked: false) + + check("Enable comments with restricted visibility") + click_link_or_button "Save" + + expect_and_dismiss_flash(message: "Successful update.") + expect(page).to have_field(:project_enabled_comments_with_restricted_visibility, checked: true) + + uncheck("Enable comments with restricted visibility") + click_link_or_button "Save" + + expect_and_dismiss_flash(message: "Successful update.") + expect(page).to have_field(:project_enabled_comments_with_restricted_visibility, checked: false) + end +end diff --git a/spec/features/projects/work_packages_settings_spec.rb b/spec/features/projects/settings/work_packages_settings_spec.rb similarity index 98% rename from spec/features/projects/work_packages_settings_spec.rb rename to spec/features/projects/settings/work_packages_settings_spec.rb index 2c6060306ec..7d7aa81dba3 100644 --- a/spec/features/projects/work_packages_settings_spec.rb +++ b/spec/features/projects/settings/work_packages_settings_spec.rb @@ -80,7 +80,7 @@ RSpec.describe "Projects", "work packages settings menu", :js do it "displays the custom fields tab" do work_packages_settings_page.visit! expect(page).to have_css(".tabnav-tab", text: "Activity") - expect(page).to have_css("span", text: "Form goes here") + expect(page).to have_css("#activities-form") end end diff --git a/spec/support/pages/projects/settings/activities.rb b/spec/support/pages/projects/settings/activities.rb new file mode 100644 index 00000000000..b8c70b9d1cc --- /dev/null +++ b/spec/support/pages/projects/settings/activities.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +# -- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2010-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. +# ++ + +require "support/pages/page" + +module Pages + module Projects + module Settings + class Activities < Pages::Page + attr_accessor :project + + def initialize(project) + super() + + @project = project + end + + def path + "/projects/#{project.identifier}/settings/work_packages/activities" + end + end + end + end +end From caccaaa65cb3472ddc90d29b8ce709645ff3785a Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Mon, 24 Mar 2025 13:59:44 +0100 Subject: [PATCH 004/260] extract form into an actual form, and include enterprise banner --- .../settings/work_packages/activities/form.rb | 51 +++++++++++++++++++ .../work_packages/activities/show.html.erb | 31 +++++++---- config/locales/en.yml | 5 ++ .../settings/activities_settings_spec.rb | 4 +- 4 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 app/forms/projects/settings/work_packages/activities/form.rb diff --git a/app/forms/projects/settings/work_packages/activities/form.rb b/app/forms/projects/settings/work_packages/activities/form.rb new file mode 100644 index 00000000000..8c468c3381c --- /dev/null +++ b/app/forms/projects/settings/work_packages/activities/form.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +module Projects::Settings::WorkPackages::Activities + class Form < ApplicationForm + form do |f| + f.check_box( + name: :enabled_comments_with_restricted_visibility, + label: I18n.t("settings.work_packages.activities.enable_comments_with_restricted_visibility"), + caption: I18n.t("settings.work_packages.activities.helper_text"), + checked: model.project.enabled_comments_with_restricted_visibility + ) + + f.submit( + name: :submit, + label: I18n.t(:button_save), + scheme: :primary + ) + end + + def initialize(**_options) + super() + end + end +end diff --git a/app/views/projects/settings/work_packages/activities/show.html.erb b/app/views/projects/settings/work_packages/activities/show.html.erb index c8f1b2c66fe..8ec7dbe56c6 100644 --- a/app/views/projects/settings/work_packages/activities/show.html.erb +++ b/app/views/projects/settings/work_packages/activities/show.html.erb @@ -29,15 +29,24 @@ See COPYRIGHT and LICENSE files for more details. <%= render(Settings::ProjectWorkPackages::HeaderComponent.new(@project, selected: :activities)) %> -<%= - # this could be exctracted into a Form component - form_for @project, - url: project_settings_work_packages_activities_path(@project), - method: :patch, - html: { id: "activities-form" } do |f| -%> - <%= f.check_box :enabled_comments_with_restricted_visibility %> - <%= f.label :enabled_comments_with_restricted_visibility, "Enable comments with restricted visibility" %> -

Helper text here

- <%= f.submit "Save" %> +<% if EnterpriseToken.allows_to?(:comments_with_restricted_visibility) %> + <%= + primer_form_with( + model: @project, + url: project_settings_work_packages_activities_path(@project), + id: "activities-form" + ) do |f| + %> + <%= render(Projects::Settings::WorkPackages::Activities::Form.new(f)) %> + <% end %> +<% else %> + <%= + render( + EnterpriseEdition::BannerComponent.new( + :comments_with_restricted_visibility, + href: OpenProject::Static::Links.url_for(:user_guides_work_package_activity), + mb: 3 + ) + ) + %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 42ffa81138b..259f2c27f40 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2078,6 +2078,8 @@ en: description: "Customize the form configuration with these additional add-ons:" add_groups: "Add new attribute groups" rename_groups: "Rename attributes groups" + comments_with_restricted_visibility: + description: "To be defined" enumeration_activities: "Time tracking activities" enumeration_work_package_priorities: "Work package priorities" @@ -4016,6 +4018,9 @@ en: section_holidays_and_closures: "Holidays and closures" work_packages: not_allowed_text: "You do not have the necessary permissions to view this page." + activities: + enable_comments_with_restricted_visibility: "Enable restricted visibility comments" + helper_text: "Restricted comments allow an internal team to communicate amongst themselves privately. These are only visible to select roles that have the necessary permissions and will not be visible publicly." text_formatting: markdown: "Markdown" diff --git a/spec/features/projects/settings/activities_settings_spec.rb b/spec/features/projects/settings/activities_settings_spec.rb index 31238e0041b..47023654056 100644 --- a/spec/features/projects/settings/activities_settings_spec.rb +++ b/spec/features/projects/settings/activities_settings_spec.rb @@ -42,13 +42,13 @@ RSpec.describe "WorkPackages-Settings-Activities", :js do expect(page).to have_field(:project_enabled_comments_with_restricted_visibility, checked: false) - check("Enable comments with restricted visibility") + check("Enable restricted visibility comments") click_link_or_button "Save" expect_and_dismiss_flash(message: "Successful update.") expect(page).to have_field(:project_enabled_comments_with_restricted_visibility, checked: true) - uncheck("Enable comments with restricted visibility") + uncheck("Enable restricted visibility comments") click_link_or_button "Save" expect_and_dismiss_flash(message: "Successful update.") From 05237ca11ac054845293e1260167336d0f8307cf Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Mon, 24 Mar 2025 16:59:08 +0100 Subject: [PATCH 005/260] adjust link on caption --- .../settings/work_packages/activities/form.rb | 12 +++++++++++- config/locales/en.yml | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/forms/projects/settings/work_packages/activities/form.rb b/app/forms/projects/settings/work_packages/activities/form.rb index 8c468c3381c..3dd3a1f37ff 100644 --- a/app/forms/projects/settings/work_packages/activities/form.rb +++ b/app/forms/projects/settings/work_packages/activities/form.rb @@ -33,7 +33,7 @@ module Projects::Settings::WorkPackages::Activities f.check_box( name: :enabled_comments_with_restricted_visibility, label: I18n.t("settings.work_packages.activities.enable_comments_with_restricted_visibility"), - caption: I18n.t("settings.work_packages.activities.helper_text"), + caption: caption_text, checked: model.project.enabled_comments_with_restricted_visibility ) @@ -47,5 +47,15 @@ module Projects::Settings::WorkPackages::Activities def initialize(**_options) super() end + + private + + def caption_text + link = render(Primer::Beta::Link.new(href: OpenProject::Static::Links.url_for(:user_guides_work_package_activity))) do + I18n.t("label_learn_more") + end + + I18n.t("settings.work_packages.activities.helper_text", link:).html_safe + end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 259f2c27f40..09366fb45bd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -4020,7 +4020,7 @@ en: not_allowed_text: "You do not have the necessary permissions to view this page." activities: enable_comments_with_restricted_visibility: "Enable restricted visibility comments" - helper_text: "Restricted comments allow an internal team to communicate amongst themselves privately. These are only visible to select roles that have the necessary permissions and will not be visible publicly." + helper_text: "Restricted comments allow an internal team to communicate amongst themselves privately. These are only visible to select roles that have the necessary permissions and will not be visible publicly. %{link}" text_formatting: markdown: "Markdown" From f7d9ddd2450cde079a0960022bf5ba2b89be91b9 Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Mon, 24 Mar 2025 17:25:00 +0100 Subject: [PATCH 006/260] adjust specs --- .../projects/settings/activities_settings_spec.rb | 2 +- .../settings/work_packages_settings_spec.rb | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/spec/features/projects/settings/activities_settings_spec.rb b/spec/features/projects/settings/activities_settings_spec.rb index 47023654056..965cb437f49 100644 --- a/spec/features/projects/settings/activities_settings_spec.rb +++ b/spec/features/projects/settings/activities_settings_spec.rb @@ -36,7 +36,7 @@ RSpec.describe "WorkPackages-Settings-Activities", :js do current_user { create(:admin) } - it "enables and disables the settings for the project" do + it "enables and disables the settings for the project", with_ee: %i[comments_with_restricted_visibility] do activities_settings_page.visit! expect(page).to have_css("#activities-form") diff --git a/spec/features/projects/settings/work_packages_settings_spec.rb b/spec/features/projects/settings/work_packages_settings_spec.rb index 7d7aa81dba3..16b3ac3140d 100644 --- a/spec/features/projects/settings/work_packages_settings_spec.rb +++ b/spec/features/projects/settings/work_packages_settings_spec.rb @@ -72,7 +72,7 @@ RSpec.describe "Projects", "work packages settings menu", :js do end end - context "when the user has access to the activities tab" do + context "when the user has access to the activities tab", with_ee: %i[comments_with_restricted_visibility] do let(:permissions) { %i(edit_project view_work_packages) } current_user { create(:user, member_with_permissions: { project => permissions }) } @@ -84,6 +84,17 @@ RSpec.describe "Projects", "work packages settings menu", :js do end end + context "when the user has access to activities tab but not to enterprise" do + let(:permissions) { %i(edit_project view_work_packages) } + + current_user { create(:user, member_with_permissions: { project => permissions }) } + + it "shows the enterprise banner" do + work_packages_settings_page.visit! + expect(page).to have_test_selector("op-ee-banner-comments-with-restricted-visibility") + end + end + context "when the user does not have access to any tabs" do let(:permissions) { %i(view_work_packages) } From 788f5cac86e96025472d795297c46ee3e7f90eb1 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Mon, 24 Mar 2025 20:15:27 +0300 Subject: [PATCH 007/260] Attempt to simplify mentionable principals filter --- .../mentionable_on_work_package_filter.rb | 52 ++++++------------- ...cted_mentionable_on_work_package_filter.rb | 6 ++- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb index 57858b5c44e..f2f08ad5c13 100644 --- a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb @@ -29,6 +29,8 @@ # ++ class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Principals::Filters::PrincipalFilter + validate :values_are_a_single_work_package_id + def allowed_values raise NotImplementedError, "There would be too many candidates" end @@ -45,58 +47,34 @@ class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Pr :mentionable_on_work_package end + def permission + :add_work_package_notes + end + def human_name - "mentionable" # Internal use + "mentionable" # Only for Internal use, not visible in the UI end def apply_to(query_scope) case operator when "=" - query_scope.where(id: principals_with_a_membership) + query_scope.where(id: User.allowed_members_on_work_package(permission, work_package)) when "!" - query_scope.where(id: visible_scope.where.not(id: principals_with_a_membership.select(:id))) + query_scope.where.not(id: User.allowed_members_on_work_package(permission, work_package)) end end private + def values_are_a_single_work_package_id + errors.add(:base, "You must select a single work package") if values.size > 1 + end + def type_strategy @type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) end - def principals_with_a_membership - visible_scope.where(id: work_package_members.select(:user_id)) - .or(visible_scope.where(id: project_members.select(:user_id))) - end - - def visible_scope - Principal.visible(User.current) - .includes(members: :roles) - .references(members: :roles) - end - - def work_package_members - Member.joins(:member_roles) - .of_work_package(values) - .where(member_roles: { role_id: mentionable_work_package_role_ids }) - end - - def mentionable_work_package_role_ids - Role.where(builtin: [Role::BUILTIN_WORK_PACKAGE_EDITOR, - Role::BUILTIN_WORK_PACKAGE_COMMENTER]) - .select(:id) - end - - def project_members - Member.of_project(projects) - .where(entity: nil) - end - - def work_packages - WorkPackage.where(id: values) - end - - def projects - Project.where(id: work_packages.select(:project_id)) + def work_package + WorkPackage.find(values.first) end end diff --git a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb index 4b7c004b84f..a9da3857114 100644 --- a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb @@ -35,6 +35,10 @@ class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < end def human_name - "restricted mentionable" # Internal use + "restricted mentionable" # Only for Internal use, not visible in the UI + end + + def permission + :view_comments_with_restricted_visibility end end From d00cda7f652856144677f37f123682644c5d2888 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 05:45:50 +0300 Subject: [PATCH 008/260] Revert to previous mentionable version MentionableOnWorkPackageFilter does not depend solely on permissions, rather on project membership whilst RestrictedMentionableOnWorkPackageFilter depends solely on a permission- hence we cannot easily reuse the `User.allowed_members_on_work_package(action, project)` method that would indeed be more concise- it's possible this can be revisitted in the near future --- .../mentionable_on_work_package_filter.rb | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb index f2f08ad5c13..14156cf49ad 100644 --- a/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/mentionable_on_work_package_filter.rb @@ -28,9 +28,8 @@ # See COPYRIGHT and LICENSE files for more details. # ++ -class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Principals::Filters::PrincipalFilter - validate :values_are_a_single_work_package_id - +class Queries::Principals::Filters::MentionableOnWorkPackageFilter < + Queries::Principals::Filters::PrincipalFilter def allowed_values raise NotImplementedError, "There would be too many candidates" end @@ -47,10 +46,6 @@ class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Pr :mentionable_on_work_package end - def permission - :add_work_package_notes - end - def human_name "mentionable" # Only for Internal use, not visible in the UI end @@ -58,23 +53,51 @@ class Queries::Principals::Filters::MentionableOnWorkPackageFilter < Queries::Pr def apply_to(query_scope) case operator when "=" - query_scope.where(id: User.allowed_members_on_work_package(permission, work_package)) + query_scope.where(id: principals_with_a_membership) when "!" - query_scope.where.not(id: User.allowed_members_on_work_package(permission, work_package)) + query_scope.where(id: visible_scope.where.not(id: principals_with_a_membership.select(:id))) end end private - def values_are_a_single_work_package_id - errors.add(:base, "You must select a single work package") if values.size > 1 - end - def type_strategy @type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) end - def work_package - WorkPackage.find(values.first) + def principals_with_a_membership + visible_scope.where(id: work_package_members.select(:user_id)) + .or(visible_scope.where(id: project_members.select(:user_id))) + end + + def visible_scope + Principal.visible(User.current) + .includes(members: :roles) + .references(members: :roles) + end + + def work_package_members + Member.joins(:member_roles) + .of_work_package(values) + .where(member_roles: { role_id: mentionable_work_package_role_ids }) + end + + def mentionable_work_package_role_ids + Role.where(builtin: [Role::BUILTIN_WORK_PACKAGE_EDITOR, + Role::BUILTIN_WORK_PACKAGE_COMMENTER]) + .select(:id) + end + + def project_members + Member.of_project(projects) + .where(entity: nil) + end + + def work_packages + WorkPackage.where(id: values) + end + + def projects + Project.where(id: work_packages.select(:project_id)) end end From dc99d662d8aff602590784e8997dfe52cc01d364 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 05:46:17 +0300 Subject: [PATCH 009/260] Define restricted mentionable on work package filter spec --- ...cted_mentionable_on_work_package_filter.rb | 39 ++++- config/locales/en.yml | 4 + ...mentionable_on_work_package_filter_spec.rb | 133 ++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb diff --git a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb index a9da3857114..e45c9f7a542 100644 --- a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb @@ -29,7 +29,21 @@ # ++ class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < - Queries::Principals::Filters::MentionableOnWorkPackageFilter + Queries::Principals::Filters::PrincipalFilter + validate :values_are_a_single_work_package_id + + def allowed_values + raise NotImplementedError, "There would be too many candidates" + end + + def allowed_values_subset + @allowed_values_subset ||= ::WorkPackage.visible + end + + def type + :list_optional + end + def key :restricted_mentionable_on_work_package end @@ -38,7 +52,30 @@ class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < "restricted mentionable" # Only for Internal use, not visible in the UI end + def apply_to(query_scope) + case operator + when "=" + query_scope.where(id: User.allowed_members_on_work_package(permission, work_package)) + when "!" + query_scope.where.not(id: User.allowed_members_on_work_package(permission, work_package)) + end + end + def permission :view_comments_with_restricted_visibility end + + private + + def values_are_a_single_work_package_id + errors.add(:values, :single_value_requirement) if values.size > 1 + end + + def type_strategy + @type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) + end + + def work_package + WorkPackage.find(values.first) + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 8afc1681081..7266e15f00c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1409,6 +1409,10 @@ en: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb new file mode 100644 index 00000000000..c2b1e5b5435 --- /dev/null +++ b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +# -- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +# ++ + +require "spec_helper" + +RSpec.describe Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter do + it_behaves_like "basic query filter" do + let(:class_key) { :restricted_mentionable_on_work_package } + let(:type) { :list_optional } + let(:human_name) { "restricted mentionable" } + + shared_let(:project) { create(:project) } + shared_let(:work_package) { create(:work_package, project:) } + shared_let(:other_work_package) { create(:work_package, project:) } + + shared_let(:user_without_restricted_comments_view_permissions) { create_user_without_restricted_comments_view_permissions } + shared_let(:user_with_restricted_comments_view_permissions) { create_user_with_restricted_comments_view_permissions } + shared_let(:user_with_restricted_comments_view_and_write_permissions) do + create_user_with_restricted_comments_view_and_write_permissions + end + + let(:user) { user_with_restricted_comments_view_permissions } + + before { allow(User).to receive(:current).and_return(user) } + + describe "#validate" do + it "is valid with a single work package id" do + instance.values = [work_package.id.to_s] + expect(instance).to be_valid + end + + it "is invalid with multiple work package ids" do + instance.values = [work_package.id.to_s, other_work_package.id.to_s] + expect(instance).not_to be_valid + expect(instance.errors.messages).to eq(values: ["must be a single work package"]) + end + + it "is invalid with no work package id" do + instance.values = [] + expect(instance).not_to be_valid + expect(instance.errors.messages).to eq(values: ["can't be blank.", "filter has invalid values."]) + end + end + + describe "#scope" do + subject { instance.apply_to(Principal.visible(user)) } + + let(:values) { [work_package.id.to_s] } + + let(:instance) do + described_class.create!.tap do |filter| + filter.values = values + filter.operator = operator + end + end + + context "with an = operator" do + let(:operator) { "=" } + + it "returns all mentionable principals on the work package and its project" do + expect(subject) + .to contain_exactly(user_with_restricted_comments_view_permissions, + user_with_restricted_comments_view_and_write_permissions) + end + end + + context "with a ! operator" do + let(:operator) { "!" } + + it "returns all non-mentionable users on the work package and its project" do + expect(subject) + .to contain_exactly(user_without_restricted_comments_view_permissions) + end + end + end + + def create_user_without_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages]) + create(:user, + firstname: "A", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_with_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_with_restricted_comments_view_and_write_permissions + viewer_role_with_commenting_permission = create(:project_role, + permissions: %i[view_work_packages add_work_package_notes + edit_own_work_package_notes + view_comments_with_restricted_visibility + add_comments_with_restricted_visibility + edit_own_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "ViewerCommenter", + member_with_roles: { project => viewer_role_with_commenting_permission }) + end + end +end From 4046ca5e62cb18edc39f41c68628d31f20b2cedd Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 07:08:05 +0300 Subject: [PATCH 010/260] Add feature specs for restricted comments @mentions --- .../restricted_visibility_comments_spec.rb | 72 ++++++++++++++++--- .../components/work_packages/activities.rb | 23 ++++-- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index 1b9fbecfc41..a5f73fc0cdb 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -32,13 +32,12 @@ require "spec_helper" RSpec.describe "Work package comments with restricted visibility", :js, - :with_cuprite, with_flag: { comments_with_restricted_visibility: true } do - let(:project) { create(:project) } - let(:admin) { create(:admin) } - let(:viewer) { create_user_with_restricted_comments_view_permissions } - let(:viewer_with_commenting_permission) { create_user_with_restricted_comments_view_and_write_permissions } - let(:project_admin) { create_user_as_project_admin } + shared_let(:project) { create(:project) } + shared_let(:admin) { create(:admin) } + shared_let(:viewer) { create_user_with_restricted_comments_view_permissions } + shared_let(:viewer_with_commenting_permission) { create_user_with_restricted_comments_view_and_write_permissions } + shared_let(:project_admin) { create_user_as_project_admin } let(:work_package) { create(:work_package, project:, author: admin) } let(:first_comment) do @@ -173,6 +172,61 @@ RSpec.describe "Work package comments with restricted visibility", end end + describe "mentioning users in comments" do + current_user { project_admin } + + shared_let(:user_without_restricted_comments_view_permissions) do + create_user_without_restricted_comments_view_permissions + end + + shared_let(:group) { create(:group, firstname: "A", lastname: "Group") } + shared_let(:group_member) do + group_role = create(:project_role) + create(:member, + principal: group, + project:, + roles: [group_role]) + end + + before do + wp_page.visit! + wait_for_reload + expect_angular_frontend_initialized + wp_page.wait_for_activity_tab + end + + context "with restricted comments enabled" do + it "restricts mentions to project members with view comments with restricted visibility permission" do + activity_tab.open_new_comment_editor + expect(page).to have_test_selector("op-work-package-journal-form-element") + + activity_tab.check_restricted_visibility_comment_checkbox + activity_tab.refocus_editor + activity_tab.type_comment("@") + + expect(page.all(".mention-list-item").map(&:text)) + .to contain_exactly("Project Admin", "Restricted Viewer", "Restricted ViewerCommenter") + end + end + + context "with restricted comments disabled" do + it "allows mentioning project members" do + activity_tab.type_comment("@") + + expect(page.all(".mention-list-item").map(&:text)) + .to contain_exactly("A Viewer", "Group", "Project Admin", "Restricted Viewer", "Restricted ViewerCommenter") + end + end + end + + def create_user_without_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages]) + create(:user, + firstname: "A", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + def create_user_as_project_admin member_role = create(:project_role, permissions: %i[view_work_packages add_work_package_notes @@ -188,7 +242,7 @@ RSpec.describe "Work package comments with restricted visibility", def create_user_with_restricted_comments_view_permissions viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) create(:user, - firstname: "A", + firstname: "Restricted", lastname: "Viewer", member_with_roles: { project => viewer_role }) end @@ -201,8 +255,8 @@ RSpec.describe "Work package comments with restricted visibility", add_comments_with_restricted_visibility edit_own_comments_with_restricted_visibility]) create(:user, - firstname: "A", - lastname: "Viewer", + firstname: "Restricted", + lastname: "ViewerCommenter", member_with_roles: { project => viewer_role_with_commenting_permission }) end end diff --git a/spec/support/components/work_packages/activities.rb b/spec/support/components/work_packages/activities.rb index 57f49354219..7c050740762 100644 --- a/spec/support/components/work_packages/activities.rb +++ b/spec/support/components/work_packages/activities.rb @@ -183,9 +183,14 @@ module Components page.find_test_selector("op-open-work-package-journal-form-trigger").click end + def refocus_editor + ckeditor.refocus + expect_focus_on_editor + end + def expect_focus_on_editor page.within_test_selector("op-work-package-journal-form-element") do - expect(page).to have_css(".ck-content:focus") + expect(page).to have_css(".ck-content:focus", wait: 10) end end @@ -201,7 +206,11 @@ module Components end def type_comment(text) - open_new_comment_editor if page.find_test_selector("op-open-work-package-journal-form-trigger") + begin + open_new_comment_editor if page.find_test_selector("op-open-work-package-journal-form-trigger") + rescue Capybara::ElementNotFound + # If the editor is already open, we don't need to open it again + end # Wait for the editor form to be present and ready wait_for { page }.to have_test_selector("op-work-package-journal-form-element") @@ -242,10 +251,7 @@ module Components page.within_test_selector("op-work-package-journal-form-element") do get_editor_form_field_element.set_value(text) - if restricted - expect(page).to have_test_selector("op-work-package-journal-restricted-comment-checkbox") - page.check("Restrict visibility") - end + check_restricted_visibility_comment_checkbox if restricted page.find_test_selector("op-submit-work-package-journal-form").click if save end @@ -300,6 +306,11 @@ module Components expect(page).to have_test_selector("op-work-package-journal-form-element") end + def check_restricted_visibility_comment_checkbox + expect(page).to have_test_selector("op-work-package-journal-restricted-comment-checkbox") + page.check("Restrict visibility") + end + def dismiss_comment_editor_with_esc page.find_test_selector("op-work-package-journal-form-element").send_keys(:escape) end From 3c4902ccb7f2edf41a2b73406b1138daf9ac46fb Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 20:10:10 +0300 Subject: [PATCH 011/260] Add restricted mentions sanitizing service --- .../restricted_mentions_sanitizer.rb | 63 +++++++++ .../restricted_mentions_sanitizer_spec.rb | 131 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb create mode 100644 spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb diff --git a/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb new file mode 100644 index 00000000000..e926a0b263d --- /dev/null +++ b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +class WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer + def initialize(work_package, notes) + @work_package = work_package + @parser = Nokogiri::HTML.fragment(notes) + end + + def call + convert_unmentionable_principals_to_plain_text + CGI.unescapeHTML(parser.to_html) + end + + private + + attr_reader :work_package, :parser + + def convert_unmentionable_principals_to_plain_text + mentionable_principals_ids = mentionable_principals.pluck(:id) + + parser.css("mention").each do |mention| + unless mentionable_principals_ids.include?(mention["data-id"].to_i) + mention.replace(mention.content) + end + end + end + + def mentionable_principals + @mentionable_principals ||= Queries::Principals::PrincipalQuery.new(user: User.current) + .where(:restricted_mentionable_on_work_package, "=", [work_package.id]) + .where(:status, "!", [Principal.statuses[:locked]]) + .where(:type, "=", %w[User Group]) + .results + end +end diff --git a/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb new file mode 100644 index 00000000000..94e009cc058 --- /dev/null +++ b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +RSpec.describe WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer do + shared_let(:project) { create(:project) } + shared_let(:admin_but_non_member) { create(:admin) } + shared_let(:viewer) { create_user_without_restricted_comments_view_permissions } + shared_let(:user_with_restricted_comments_view_and_write_permissions) do + create_user_with_restricted_comments_view_and_write_permissions + end + shared_let(:project_admin) { create_user_as_project_admin } + shared_let(:work_package) { create(:work_package, project:) } + + let(:input) do + <<~HTML + @#{admin_but_non_member.firstname} wrote: + + > Well Done! + + @#{viewer.firstname} wrote: + + > @#{user_with_restricted_comments_view_and_write_permissions.firstname} wrote: + > + > > @#{project_admin.firstname} wrote: + > > + > > > FooBar + > > + > > @Firstname wrote: + > > + > > > BooBar + HTML + end + + let(:expected_output) do + <<~HTML + @#{admin_but_non_member.firstname} wrote: + + > Well Done! + + @#{viewer.firstname} wrote: + + > @#{user_with_restricted_comments_view_and_write_permissions.firstname} wrote: + > + > > @#{project_admin.firstname} wrote: + > > + > > > FooBar + > > + > > @Firstname wrote: + > > + > > > BooBar + HTML + end + + subject { described_class.new(work_package, input).call } + + before { allow(User).to receive(:current).and_return(user_with_restricted_comments_view_and_write_permissions) } + + it "sanitizes the notes" do + expect(subject).to eq(expected_output) + end + + def create_user_without_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages]) + create(:user, + firstname: "A", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_as_project_admin + member_role = create(:project_role, + permissions: %i[view_work_packages add_work_package_notes + edit_own_work_package_notes + view_comments_with_restricted_visibility + add_comments_with_restricted_visibility + edit_own_comments_with_restricted_visibility + edit_others_comments_with_restricted_visibility]) + create(:user, firstname: "Project", lastname: "Admin", + member_with_roles: { project => member_role }) + end + + def create_user_with_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_with_restricted_comments_view_and_write_permissions + viewer_role_with_commenting_permission = create(:project_role, + permissions: %i[view_work_packages add_work_package_notes + edit_own_work_package_notes + view_comments_with_restricted_visibility + add_comments_with_restricted_visibility + edit_own_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "ViewerCommenter", + member_with_roles: { project => viewer_role_with_commenting_permission }) + end +end From 3433e7ea639fb04c8242bafe1424b929ad7d438a Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 21:46:34 +0300 Subject: [PATCH 012/260] Sanitize mentions on wp restricted comments --- .../activities_tab_controller.rb | 7 ++++ config/initializers/permissions.rb | 2 +- config/routes.rb | 2 ++ .../restricted-comment.controller.ts | 35 ++++++++++++++++++- .../restricted_visibility_comments_spec.rb | 21 +++++++++-- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/app/controllers/work_packages/activities_tab_controller.rb b/app/controllers/work_packages/activities_tab_controller.rb index e96e4725049..67ffac1bcf3 100644 --- a/app/controllers/work_packages/activities_tab_controller.rb +++ b/app/controllers/work_packages/activities_tab_controller.rb @@ -139,6 +139,13 @@ class WorkPackages::ActivitiesTabController < ApplicationController respond_with_turbo_streams end + def sanitize_restricted_mentions + sanitizer = WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer.new(@work_package, journal_params[:notes]) + sanitized_notes = sanitizer.call + + render plain: sanitized_notes + end + def toggle_reaction # rubocop:disable Metrics/AbcSize emoji_reaction_service = if @journal.emoji_reactions.exists?(user: User.current, reaction: params[:reaction]) diff --git a/config/initializers/permissions.rb b/config/initializers/permissions.rb index eda5478685c..f0bd66ab8f8 100644 --- a/config/initializers/permissions.rb +++ b/config/initializers/permissions.rb @@ -289,7 +289,7 @@ Rails.application.reloader.to_prepare do # FIXME: Although the endpoint is removed, the code checking whether a user # is eligible to add work packages through the API still seems to rely on this. journals: [:new], - "work_packages/activities_tab": %i[create toggle_reaction] + "work_packages/activities_tab": %i[create toggle_reaction sanitize_restricted_mentions] }, permissible_on: %i[work_package project], dependencies: :view_work_packages diff --git a/config/routes.rb b/config/routes.rb index 9d448e89d0c..1284f54a8e7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -650,10 +650,12 @@ Rails.application.routes.draw do get :cancel_edit put :toggle_reaction end + collection do get :update_streams get :update_filter # filter not persisted put :update_sorting # sorting is persisted + post :sanitize_restricted_mentions end end diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts index 01ed6fc9905..7e697d3b47f 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts @@ -58,8 +58,11 @@ export default class RestrictedCommentController extends Controller { this.formContainerTarget.classList.toggle(this.highlightClass, isChecked); this.toggleLearnMoreLink(isChecked); - this.isRestrictedValue = isChecked; + + if (isChecked) { + void this.sanitizeRestrictedMentions(); + } } private toggleLearnMoreLink(isChecked:boolean):void { @@ -67,4 +70,34 @@ export default class RestrictedCommentController extends Controller { this.learnMoreLinkTarget.classList.toggle(this.hiddenClass, !isChecked); } + + private async sanitizeRestrictedMentions():Promise { + if (this.ckEditorInstance) { + const editorData = this.ckEditorInstance.getData({ trim: false }); + if (editorData.length === 0) return; + + const sanitizePath = `/work_packages/${this.workPackagesActivitiesTabIndexOutlet.workPackageIdValue}/activities/sanitize_restricted_mentions`; + const csrfToken = (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement).content; + + const response = await fetch(sanitizePath, { + method: 'POST', + body: JSON.stringify({ journal: { notes: editorData } }), + headers: { + 'X-CSRF-Token': csrfToken, + 'Content-Type': 'application/json', + }, + }); + + if (response.ok) { + const sanitizedNotes = await response.text(); + this.ckEditorInstance.setData(sanitizedNotes); + } else { + console.error('Failed to sanitize restricted mentions'); + } + } + } + + private get ckEditorInstance() { + return this.workPackagesActivitiesTabIndexOutlet.getCkEditorInstance(); + } } diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index a5f73fc0cdb..24002af32db 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -195,7 +195,7 @@ RSpec.describe "Work package comments with restricted visibility", wp_page.wait_for_activity_tab end - context "with restricted comments enabled" do + context "with restricted comments initially enabled" do it "restricts mentions to project members with view comments with restricted visibility permission" do activity_tab.open_new_comment_editor expect(page).to have_test_selector("op-work-package-journal-form-element") @@ -209,12 +209,27 @@ RSpec.describe "Work package comments with restricted visibility", end end - context "with restricted comments disabled" do - it "allows mentioning project members" do + context "with restricted comments initially disabled" do + it "allows mentioning project members but they are sanitized when the checkbox is checked" do activity_tab.type_comment("@") expect(page.all(".mention-list-item").map(&:text)) .to contain_exactly("A Viewer", "Group", "Project Admin", "Restricted Viewer", "Restricted ViewerCommenter") + + page.find(".mention-list-item", text: "A Viewer").click + activity_tab.type_comment("@Restricted") + page.first(".mention-list-item", text: "Restricted Viewer").click + activity_tab.type_comment("@Group") + page.find(".mention-list-item", text: "Group").click + + activity_tab.check_restricted_visibility_comment_checkbox + + page.within_test_selector("op-work-package-journal-form-element") do + expect(page.all("a.mention").map(&:text)) + .to contain_exactly("@Restricted Viewer") + + expect(page).to have_text("@A Viewer") & have_text("@Group") + end end end end From 84820890cfb59173c593e785c01f111857adb7f6 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 22:15:43 +0300 Subject: [PATCH 013/260] Use more graceful error handling --- .../restricted-comment.controller.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts index 7e697d3b47f..b11b91f03b0 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts @@ -79,20 +79,20 @@ export default class RestrictedCommentController extends Controller { const sanitizePath = `/work_packages/${this.workPackagesActivitiesTabIndexOutlet.workPackageIdValue}/activities/sanitize_restricted_mentions`; const csrfToken = (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement).content; - const response = await fetch(sanitizePath, { - method: 'POST', - body: JSON.stringify({ journal: { notes: editorData } }), - headers: { - 'X-CSRF-Token': csrfToken, - 'Content-Type': 'application/json', - }, - }); + try { + const response = await fetch(sanitizePath, { + method: 'POST', + body: JSON.stringify({ journal: { notes: editorData } }), + headers: { + 'X-CSRF-Token': csrfToken, + 'Content-Type': 'application/json', + }, + }); - if (response.ok) { const sanitizedNotes = await response.text(); this.ckEditorInstance.setData(sanitizedNotes); - } else { - console.error('Failed to sanitize restricted mentions'); + } catch (error) { + console.error(`Failed to sanitize restricted mentions: ${error}`); } } } From ee42e9e49d14b9f200f33afb0621f04845e6ae06 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 22:16:06 +0300 Subject: [PATCH 014/260] Ensure journals are always sanitized --- .../activities_tab_controller.rb | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/controllers/work_packages/activities_tab_controller.rb b/app/controllers/work_packages/activities_tab_controller.rb index 67ffac1bcf3..c8978df026b 100644 --- a/app/controllers/work_packages/activities_tab_controller.rb +++ b/app/controllers/work_packages/activities_tab_controller.rb @@ -140,10 +140,7 @@ class WorkPackages::ActivitiesTabController < ApplicationController end def sanitize_restricted_mentions - sanitizer = WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer.new(@work_package, journal_params[:notes]) - sanitized_notes = sanitizer.call - - render plain: sanitized_notes + render plain: sanitized_journal_notes end def toggle_reaction # rubocop:disable Metrics/AbcSize @@ -228,6 +225,10 @@ class WorkPackages::ActivitiesTabController < ApplicationController User.current.preference&.comments_sorting || OpenProject::Configuration.default_comment_sort_order end + def sanitized_journal_notes + WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer.new(@work_package, journal_params[:notes]).call + end + def journal_params params.expect(journal: %i[notes restricted]) end @@ -302,12 +303,15 @@ class WorkPackages::ActivitiesTabController < ApplicationController end def create_journal_service_call + restricted = to_boolean(journal_params[:restricted], false) + notes = restricted ? sanitized_journal_notes : journal_params[:notes] + AddWorkPackageNoteService .new(user: User.current, work_package: @work_package) - .call(journal_params[:notes], + .call(notes, send_notifications: to_boolean(params[:notify], true), - restricted: to_boolean(journal_params[:restricted], false)) + restricted:) end def to_boolean(value, default) @@ -315,9 +319,8 @@ class WorkPackages::ActivitiesTabController < ApplicationController end def update_journal_service_call - Journals::UpdateService.new(model: @journal, user: User.current).call( - notes: journal_params[:notes] - ) + notes = @journal.restricted? ? sanitized_journal_notes : journal_params[:notes] + Journals::UpdateService.new(model: @journal, user: User.current).call(notes:) end def generate_time_based_update_streams(last_update_timestamp) From 6fc0c6c73075379290a14db2083ff1df5f66e028 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 22:40:15 +0300 Subject: [PATCH 015/260] Ensure edit state uses restriction The downside is that if the user has both an edit editor open and one adding a comment, the restriction prevails so they would not be able to mention non restricted users. Unless they close out the restricted editor. This is mainly because we are using a singular function to retrieve the mentions- the could be a better way that I didn't yet think about but my reckoning is this is a rare edge case- and I much prefer the secure by default approach --- .../journals/item_component/edit.html.erb | 2 +- .../journals/item_component/edit.rb | 7 +++++++ .../src/app/core/path-helper/apiv3-paths.ts | 8 +++++--- .../restricted_visibility_comments_spec.rb | 18 ++++++++++++++++-- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/components/work_packages/activities_tab/journals/item_component/edit.html.erb b/app/components/work_packages/activities_tab/journals/item_component/edit.html.erb index 34b292dadc0..bb97da905c3 100644 --- a/app/components/work_packages/activities_tab/journals/item_component/edit.html.erb +++ b/app/components/work_packages/activities_tab/journals/item_component/edit.html.erb @@ -1,5 +1,5 @@ <%= - component_wrapper(class: "work-packages-activities-tab-journals-item-component-edit") do + component_wrapper(class: "work-packages-activities-tab-journals-item-component-edit", data: wrapper_data_attributes) do render(Primer::Box.new(my: 3)) do primer_form_with( id: "work-package-journal-form-element", # required for specs diff --git a/app/components/work_packages/activities_tab/journals/item_component/edit.rb b/app/components/work_packages/activities_tab/journals/item_component/edit.rb index bfb45e59d52..628c1cab98e 100644 --- a/app/components/work_packages/activities_tab/journals/item_component/edit.rb +++ b/app/components/work_packages/activities_tab/journals/item_component/edit.rb @@ -33,6 +33,7 @@ module WorkPackages include ApplicationHelper include OpPrimer::ComponentHelpers include OpTurbo::Streamable + include WorkPackages::ActivitiesTab::StimulusControllers def initialize(journal:, filter:) super @@ -49,6 +50,12 @@ module WorkPackages def wrapper_uniq_by journal.id end + + def wrapper_data_attributes + { + restricted_comment_stimulus_controller("-is-restricted-value") => journal.restricted? + } + end end end end diff --git a/frontend/src/app/core/path-helper/apiv3-paths.ts b/frontend/src/app/core/path-helper/apiv3-paths.ts index dfba48f969c..3bf3efbba48 100644 --- a/frontend/src/app/core/path-helper/apiv3-paths.ts +++ b/frontend/src/app/core/path-helper/apiv3-paths.ts @@ -46,11 +46,13 @@ export class ApiV3Paths { // that are members of that project: filters.add('member', '=', [(workPackage.project as HalResource).id as string]); } else { - const addCommentElement = document.getElementById('work-packages-activities-tab-add-comment-component'); - const isRestricted = addCommentElement?.getAttribute('data-work-packages--activities-tab--restricted-comment-is-restricted-value') === 'true'; + const isRestrictedAttribute = 'data-work-packages--activities-tab--restricted-comment-is-restricted-value'; + const addCommentIsRestricted = document.getElementById('work-packages-activities-tab-add-comment-component')?.getAttribute(isRestrictedAttribute) === 'true'; + const editorIsRestricted = document.querySelector('.work-packages-activities-tab-journals-item-component-edit')?.getAttribute(isRestrictedAttribute) === 'true'; + const isRestricted = addCommentIsRestricted || editorIsRestricted; // that are mentionable on the work package - if (addCommentElement && isRestricted) { + if (isRestricted) { filters.add('restricted_mentionable_on_work_package', '=', [workPackage.id.toString()]); } else { filters.add('mentionable_on_work_package', '=', [workPackage.id.toString()]); diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index 24002af32db..4a26587bb02 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -39,8 +39,8 @@ RSpec.describe "Work package comments with restricted visibility", shared_let(:viewer_with_commenting_permission) { create_user_with_restricted_comments_view_and_write_permissions } shared_let(:project_admin) { create_user_as_project_admin } - let(:work_package) { create(:work_package, project:, author: admin) } - let(:first_comment) do + shared_let(:work_package) { create(:work_package, project:, author: admin) } + shared_let(:first_comment) do create(:work_package_journal, user: admin, notes: "A (restricted) comment by admin", journable: work_package, version: 2, restricted: true) end @@ -232,6 +232,20 @@ RSpec.describe "Work package comments with restricted visibility", end end end + + context "when editing a restricted comment" do + it "honors mentionable principals" do + activity_tab.within_journal_entry(first_comment) do + page.find_test_selector("op-wp-journal-#{first_comment.id}-action-menu").click + page.find_test_selector("op-wp-journal-#{first_comment.id}-edit").click + + activity_tab.type_comment(" @") + end + + expect(page.all(".mention-list-item").map(&:text)) + .to contain_exactly("Project Admin", "Restricted Viewer", "Restricted ViewerCommenter") + end + end end def create_user_without_restricted_comments_view_permissions From 5d34f9b5de09aff2d77ae9921f4ce95766364a22 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 25 Mar 2025 23:16:00 +0300 Subject: [PATCH 016/260] Add a guard clause to sanitizer --- .../activities_tab/restricted_mentions_sanitizer.rb | 10 ++++++++-- .../restricted_mentions_sanitizer_spec.rb | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb index e926a0b263d..5dee938a469 100644 --- a/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb +++ b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb @@ -31,17 +31,19 @@ class WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer def initialize(work_package, notes) @work_package = work_package - @parser = Nokogiri::HTML.fragment(notes) + @notes = notes end def call + return "" if notes.blank? + convert_unmentionable_principals_to_plain_text CGI.unescapeHTML(parser.to_html) end private - attr_reader :work_package, :parser + attr_reader :work_package, :notes def convert_unmentionable_principals_to_plain_text mentionable_principals_ids = mentionable_principals.pluck(:id) @@ -53,6 +55,10 @@ class WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer end end + def parser + @parser ||= Nokogiri::HTML.fragment(notes) + end + def mentionable_principals @mentionable_principals ||= Queries::Principals::PrincipalQuery.new(user: User.current) .where(:restricted_mentionable_on_work_package, "=", [work_package.id]) diff --git a/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb index 94e009cc058..0b093fa5dcc 100644 --- a/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb +++ b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb @@ -88,6 +88,14 @@ RSpec.describe WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer do expect(subject).to eq(expected_output) end + context "when the notes are empty" do + let(:input) { "" } + + it "returns an empty string" do + expect(subject).to eq("") + end + end + def create_user_without_restricted_comments_view_permissions viewer_role = create(:project_role, permissions: %i[view_work_packages]) create(:user, From 994d49c84368930b6e371db8c37928f0485311e6 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Wed, 26 Mar 2025 08:57:19 +0300 Subject: [PATCH 017/260] Deduplicate restricted visibility comment spec helpers --- .../restricted_visibility_comments_spec.rb | 43 +---------- ...mentionable_on_work_package_filter_spec.rb | 31 +------- .../restricted_mentions_sanitizer_spec.rb | 43 +---------- .../restricted_visibility_comments_helpers.rb | 73 +++++++++++++++++++ 4 files changed, 79 insertions(+), 111 deletions(-) create mode 100644 spec/support/work_packages/activities_tab/restricted_visibility_comments_helpers.rb diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index 4a26587bb02..2f52ff9030b 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -33,6 +33,8 @@ require "spec_helper" RSpec.describe "Work package comments with restricted visibility", :js, with_flag: { comments_with_restricted_visibility: true } do + include RestrictedVisibilityCommentsHelpers + shared_let(:project) { create(:project) } shared_let(:admin) { create(:admin) } shared_let(:viewer) { create_user_with_restricted_comments_view_permissions } @@ -247,45 +249,4 @@ RSpec.describe "Work package comments with restricted visibility", end end end - - def create_user_without_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages]) - create(:user, - firstname: "A", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_as_project_admin - member_role = create(:project_role, - permissions: %i[view_work_packages add_work_package_notes - edit_own_work_package_notes - view_comments_with_restricted_visibility - add_comments_with_restricted_visibility - edit_own_comments_with_restricted_visibility - edit_others_comments_with_restricted_visibility]) - create(:user, firstname: "Project", lastname: "Admin", - member_with_roles: { project => member_role }) - end - - def create_user_with_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_with_restricted_comments_view_and_write_permissions - viewer_role_with_commenting_permission = create(:project_role, - permissions: %i[view_work_packages add_work_package_notes - edit_own_work_package_notes - view_comments_with_restricted_visibility - add_comments_with_restricted_visibility - edit_own_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "ViewerCommenter", - member_with_roles: { project => viewer_role_with_commenting_permission }) - end end diff --git a/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb index c2b1e5b5435..dd888d7cffa 100644 --- a/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb +++ b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb @@ -32,6 +32,8 @@ require "spec_helper" RSpec.describe Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter do it_behaves_like "basic query filter" do + include RestrictedVisibilityCommentsHelpers + let(:class_key) { :restricted_mentionable_on_work_package } let(:type) { :list_optional } let(:human_name) { "restricted mentionable" } @@ -100,34 +102,5 @@ RSpec.describe Queries::Principals::Filters::RestrictedMentionableOnWorkPackageF end end end - - def create_user_without_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages]) - create(:user, - firstname: "A", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_with_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_with_restricted_comments_view_and_write_permissions - viewer_role_with_commenting_permission = create(:project_role, - permissions: %i[view_work_packages add_work_package_notes - edit_own_work_package_notes - view_comments_with_restricted_visibility - add_comments_with_restricted_visibility - edit_own_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "ViewerCommenter", - member_with_roles: { project => viewer_role_with_commenting_permission }) - end end end diff --git a/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb index 0b093fa5dcc..cbf6473d41d 100644 --- a/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb +++ b/spec/services/work_packages/activities_tab/restricted_mentions_sanitizer_spec.rb @@ -31,6 +31,8 @@ require "spec_helper" RSpec.describe WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer do + include RestrictedVisibilityCommentsHelpers + shared_let(:project) { create(:project) } shared_let(:admin_but_non_member) { create(:admin) } shared_let(:viewer) { create_user_without_restricted_comments_view_permissions } @@ -95,45 +97,4 @@ RSpec.describe WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer do expect(subject).to eq("") end end - - def create_user_without_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages]) - create(:user, - firstname: "A", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_as_project_admin - member_role = create(:project_role, - permissions: %i[view_work_packages add_work_package_notes - edit_own_work_package_notes - view_comments_with_restricted_visibility - add_comments_with_restricted_visibility - edit_own_comments_with_restricted_visibility - edit_others_comments_with_restricted_visibility]) - create(:user, firstname: "Project", lastname: "Admin", - member_with_roles: { project => member_role }) - end - - def create_user_with_restricted_comments_view_permissions - viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "Viewer", - member_with_roles: { project => viewer_role }) - end - - def create_user_with_restricted_comments_view_and_write_permissions - viewer_role_with_commenting_permission = create(:project_role, - permissions: %i[view_work_packages add_work_package_notes - edit_own_work_package_notes - view_comments_with_restricted_visibility - add_comments_with_restricted_visibility - edit_own_comments_with_restricted_visibility]) - create(:user, - firstname: "Restricted", - lastname: "ViewerCommenter", - member_with_roles: { project => viewer_role_with_commenting_permission }) - end end diff --git a/spec/support/work_packages/activities_tab/restricted_visibility_comments_helpers.rb b/spec/support/work_packages/activities_tab/restricted_visibility_comments_helpers.rb new file mode 100644 index 00000000000..c5b51e39af3 --- /dev/null +++ b/spec/support/work_packages/activities_tab/restricted_visibility_comments_helpers.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +require "spec_helper" + +module RestrictedVisibilityCommentsHelpers + def create_user_without_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages]) + create(:user, + firstname: "A", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_as_project_admin + member_role = create(:project_role, + permissions: %i[view_work_packages add_work_package_notes + edit_own_work_package_notes + view_comments_with_restricted_visibility + add_comments_with_restricted_visibility + edit_own_comments_with_restricted_visibility + edit_others_comments_with_restricted_visibility]) + create(:user, firstname: "Project", lastname: "Admin", + member_with_roles: { project => member_role }) + end + + def create_user_with_restricted_comments_view_permissions + viewer_role = create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "Viewer", + member_with_roles: { project => viewer_role }) + end + + def create_user_with_restricted_comments_view_and_write_permissions + viewer_role_with_commenting_permission = create(:project_role, + permissions: %i[view_work_packages add_work_package_notes + edit_own_work_package_notes + view_comments_with_restricted_visibility + add_comments_with_restricted_visibility + edit_own_comments_with_restricted_visibility]) + create(:user, + firstname: "Restricted", + lastname: "ViewerCommenter", + member_with_roles: { project => viewer_role_with_commenting_permission }) + end +end From cc75dc117b766f3cc88f545b7652e71e104c1d92 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Wed, 26 Mar 2025 16:39:02 +0300 Subject: [PATCH 018/260] Fallback to project members query so as to include groups. Once more relying on the User.allowed_members_* helper did not fit the bill as we need to also include Groups in mentionables which are direct decendants of Principal- the resulting query is also much simpler and loosely decoupled- so I favour retaining this approach for the time being. Follows: https://github.com/opf/openproject/commit/d00cda7f652856144677f37f123682644c5d2888 --- ...cted_mentionable_on_work_package_filter.rb | 14 ++++++++---- ...mentionable_on_work_package_filter_spec.rb | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb index e45c9f7a542..b3c442f849c 100644 --- a/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb +++ b/app/models/queries/principals/filters/restricted_mentionable_on_work_package_filter.rb @@ -55,9 +55,9 @@ class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < def apply_to(query_scope) case operator when "=" - query_scope.where(id: User.allowed_members_on_work_package(permission, work_package)) + query_scope.where(id: project_members.select(:user_id)) when "!" - query_scope.where.not(id: User.allowed_members_on_work_package(permission, work_package)) + query_scope.where.not(id: project_members.select(:user_id)) end end @@ -67,12 +67,18 @@ class Queries::Principals::Filters::RestrictedMentionableOnWorkPackageFilter < private + def type_strategy + @type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) + end + def values_are_a_single_work_package_id errors.add(:values, :single_value_requirement) if values.size > 1 end - def type_strategy - @type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) + def project_members + Member.of_project(work_package.project) + .joins(roles: :role_permissions) + .where(role_permissions: { permission: }) end def work_package diff --git a/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb index dd888d7cffa..98b52ab5c23 100644 --- a/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb +++ b/spec/models/queries/principals/filters/restricted_mentionable_on_work_package_filter_spec.rb @@ -91,6 +91,28 @@ RSpec.describe Queries::Principals::Filters::RestrictedMentionableOnWorkPackageF .to contain_exactly(user_with_restricted_comments_view_permissions, user_with_restricted_comments_view_and_write_permissions) end + + context "with users and groups" do + let(:group_member1) { create(:user) } + let(:group_member2) { create(:user) } + let(:group_role) { create(:project_role, permissions: %i[view_work_packages view_comments_with_restricted_visibility]) } + let(:group) do + create(:group, members: [group_member1, group_member2]) do |group| + Members::CreateService + .new(user: User.system, contract_class: EmptyContract) + .call(project:, principal: group, roles: [group_role]) + end + end + + it "returns all mentionable principals including group and group members" do + expect(subject) + .to contain_exactly(user_with_restricted_comments_view_permissions, + user_with_restricted_comments_view_and_write_permissions, + group, + group_member1, + group_member2) + end + end end context "with a ! operator" do From ac5b0eb2f6a0284c1aa1de85e6facdec2e7918e0 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Wed, 26 Mar 2025 16:49:05 +0300 Subject: [PATCH 019/260] Attempt to improve var names --- frontend/src/app/core/path-helper/apiv3-paths.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/core/path-helper/apiv3-paths.ts b/frontend/src/app/core/path-helper/apiv3-paths.ts index 3bf3efbba48..2c21c1ac787 100644 --- a/frontend/src/app/core/path-helper/apiv3-paths.ts +++ b/frontend/src/app/core/path-helper/apiv3-paths.ts @@ -46,13 +46,12 @@ export class ApiV3Paths { // that are members of that project: filters.add('member', '=', [(workPackage.project as HalResource).id as string]); } else { - const isRestrictedAttribute = 'data-work-packages--activities-tab--restricted-comment-is-restricted-value'; - const addCommentIsRestricted = document.getElementById('work-packages-activities-tab-add-comment-component')?.getAttribute(isRestrictedAttribute) === 'true'; - const editorIsRestricted = document.querySelector('.work-packages-activities-tab-journals-item-component-edit')?.getAttribute(isRestrictedAttribute) === 'true'; - const isRestricted = addCommentIsRestricted || editorIsRestricted; + const isRestrictedAttributeValue = 'data-work-packages--activities-tab--restricted-comment-is-restricted-value'; + const addingCommentIsRestricted = document.getElementById('work-packages-activities-tab-add-comment-component')?.getAttribute(isRestrictedAttributeValue) === 'true'; + const editingCommentIsRestricted = document.querySelector('.work-packages-activities-tab-journals-item-component-edit')?.getAttribute(isRestrictedAttributeValue) === 'true'; // that are mentionable on the work package - if (isRestricted) { + if (addingCommentIsRestricted || editingCommentIsRestricted) { filters.add('restricted_mentionable_on_work_package', '=', [workPackage.id.toString()]); } else { filters.add('mentionable_on_work_package', '=', [workPackage.id.toString()]); From b9c3a7de9e9491569b8efeea0076ea4bb9cf8868 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Mon, 31 Mar 2025 14:19:14 +0200 Subject: [PATCH 020/260] [#62217] allow custom fields that are not enabled in project - https://community.openproject.org/work_packages/62217 - rescue when sending custom field methods --- app/models/types/patterns/token_property_mapper.rb | 1 + .../types/patterns/token_property_mapper_spec.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/app/models/types/patterns/token_property_mapper.rb b/app/models/types/patterns/token_property_mapper.rb index a739a0e3fec..f9e8aa18118 100644 --- a/app/models/types/patterns/token_property_mapper.rb +++ b/app/models/types/patterns/token_property_mapper.rb @@ -33,6 +33,7 @@ module Types class TokenPropertyMapper DEFAULT_FUNCTION = ->(key, context) do return nil if context.nil? + return nil unless context.respond_to?(key.to_sym) context.public_send(key.to_sym) end.curry diff --git a/spec/models/types/patterns/token_property_mapper_spec.rb b/spec/models/types/patterns/token_property_mapper_spec.rb index 8a4c9b8b318..3340c3d71d6 100644 --- a/spec/models/types/patterns/token_property_mapper_spec.rb +++ b/spec/models/types/patterns/token_property_mapper_spec.rb @@ -66,6 +66,12 @@ RSpec.describe Types::Patterns::TokenPropertyMapper do end end + shared_let(:not_activated_custom_field) do + create(:boolean_wp_custom_field).tap do |custom_field| + work_package.type.custom_fields << custom_field + end + end + described_class::TOKEN_PROPERTY_MAP.each_pair do |key, details| it "the token named #{key} resolves successfully" do expect { details[:fn].call(work_package) }.not_to raise_error @@ -78,6 +84,12 @@ RSpec.describe Types::Patterns::TokenPropertyMapper do expect(function.call(work_package)).to eq(%w[A B]) end + it "must return nil if custom field is not activated in project" do + function = described_class.new.fetch :"custom_field_#{not_activated_custom_field.id}" + expect { function.call(work_package) }.not_to raise_error + expect(function.call(work_package)).to be_nil + end + it "returns all possible tokens" do cf = string_custom_field tokens = described_class.new.tokens_for_type(work_package.type) From 3533a5a12f2cb3d824e6b9c06edee07610b64ad4 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Tue, 1 Apr 2025 18:54:48 +0200 Subject: [PATCH 021/260] First draft of docs for BorderBox --- lookbook/docs/components/borderBox.md.erb | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lookbook/docs/components/borderBox.md.erb diff --git a/lookbook/docs/components/borderBox.md.erb b/lookbook/docs/components/borderBox.md.erb new file mode 100644 index 00000000000..5d08b83e85c --- /dev/null +++ b/lookbook/docs/components/borderBox.md.erb @@ -0,0 +1,40 @@ +The Border Box element is used to display structured items in a list, each with a set of actions. It is used for example: + +- to display a list of meetings +- to display individual meeting agenda items in a meeting +- to display the a list of project attributes +- to display a list of configured OAuth applications + +## Anatomy + +The Border Box element is made up of + +1. The **header** acts as a container for the items below it. It's often to distinguish between sections. It is optional. +2. Individual **items** below can vary in what information they show. + +If a page uses a Border Box with a header, all sections must use headers. + +## Options + +- **Collapsible header**: A collapsible header has an arrow next to the title and allows collapsing and expanding the contents below. When collapsed, the bottom border is slightly thicker to indicate something is hidden. +- **Header description**: When collapsed, the optional header description is hidden. +- **Header counter**: The counter can display the number of items that that particular section contains. +- **Draggable**: Both header and items can have drag handles. Individual items can be dragged up and down and into other sections. The sections themselves can also be moved up and down. +- **More button**: A more button can have contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). + +## Best practices + +**Do** + +- Use sections (with headers) to better organise content if they have logical categories (eg. Open and Planned meetings). + +**Don't** + +- Don't mix sections with and without headers. If one section has a header, they must all have headers. +- Don't make sections collapsible if they do not need to be. + + +## Technical notes + + +### Code structure From 01c9afcf106822412e82fbd914e6dd76f90c64f9 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Tue, 1 Apr 2025 19:01:37 +0200 Subject: [PATCH 022/260] Filename update --- lookbook/docs/components/{borderBox.md.erb => border-box.md.erb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lookbook/docs/components/{borderBox.md.erb => border-box.md.erb} (100%) diff --git a/lookbook/docs/components/borderBox.md.erb b/lookbook/docs/components/border-box.md.erb similarity index 100% rename from lookbook/docs/components/borderBox.md.erb rename to lookbook/docs/components/border-box.md.erb From 8a522f577ac50426f3c5056c3550d79122e7a8c1 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 2 Apr 2025 10:51:06 +0200 Subject: [PATCH 023/260] Split tables documentation into TableComponent and BorderBoxComponent --- .../docs/components/borde-box-table.md.erb | 81 +++++++++ lookbook/docs/components/tables.md.erb | 120 ++++---------- .../deprecated/table_preview/default.html.erb | 156 +++++++----------- 3 files changed, 169 insertions(+), 188 deletions(-) create mode 100644 lookbook/docs/components/borde-box-table.md.erb diff --git a/lookbook/docs/components/borde-box-table.md.erb b/lookbook/docs/components/borde-box-table.md.erb new file mode 100644 index 00000000000..c633001424e --- /dev/null +++ b/lookbook/docs/components/borde-box-table.md.erb @@ -0,0 +1,81 @@ +## Overview + +<%= embed OpPrimer::BorderBoxTableComponentPreview, :default %> + +## Anatomy + +**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility support). If you want or need that, please use the [TableComponent docs](./tables)) + +## Best practices + +**Do** + +- Use a BorderBox table if you have a *few* entries of unsorted data, that does not require pagination +- Use up to two actions using the `:secondary` scheme of `Primer::Beta::Button` and `Primer::Beta::IconButton`. +- OR: Use an action menu with `:invisible` scheme + +**Don't** + +- Use the BorderBox table for a lot of items that require sorting or pagination + +## Technical notes + +Since the `BorderBoxTable` is a sub-class of our normal `TableComponent` it follows the same architecture. For the basic usage please visit the [TableComponent docs](./tables). The following docs are only about the additional specifics of the `BorderBoxTable`. + +### Mobile behavior + +On mobile, the BorderBoxTable does not scroll, but collapse into two columns (content columns and actions). You can control which columns are shown using the `mobile_columns` method. + +As the columns are collapsed, some information might need an additional label, which you can prepend with `mobile_labels`. + +```ruby +# On desktop, show these columns +columns :title, :users, :created_at + +# On mobile, only two columns are visible +mobile_columns :title, :users + +# For users, show the label using the header caption +mobile_labels :users +``` + +### Mobile headers + +On mobile, the usual table headers are replaced with a single `mobile_title` property that you have to set on the table. + +### Text wrapping behaviour + +By default, text longer than the column width will truncate with ellipsis. Only the main column has text that wraps around to display the full string. + +### Main column + +Use the `main_column` helper to make a column 2 times as wide as the others and also display the full text: + +```ruby +# On desktop, show these columns +columns :title, :users, :created_at + +# Make title column wider than the others (factor 2 using grid span) +main_column :title +``` +Note: Ideally, one one main column will be present for each table. + +### Footer + +Set `has_footer?` to true to add a footer to the table, defining the component/content to be rendered with the `footer` method. + +```ruby +def has_footer? + true +end + +def footer + render CustomFooterComponent.new(...) +end +``` + +### Examples + +<%= embed OpPrimer::BorderBoxTableComponentPreview, :default, panels: %i[source] %> + +For detailed examples have a look at the other [preview examples](/lookbook/inspect/OpenProject/Primer/border_box_table/default) of the component. diff --git a/lookbook/docs/components/tables.md.erb b/lookbook/docs/components/tables.md.erb index 447a3e0ba4d..bf466391a56 100644 --- a/lookbook/docs/components/tables.md.erb +++ b/lookbook/docs/components/tables.md.erb @@ -1,104 +1,46 @@ ## Overview -### Border Box Table +We currently have two components for implementing a table view: -<%= embed OpPrimer::BorderBoxTableComponentPreview, :default %> +* a (sortable) `TableComponent` +* a (unsortable, primer based) `BorderBoxTableComponent` -### Sortable table +**Sortable table** <%= embed OpenProject::Deprecated::TablePreview, :default %> -## Usage +**Border Box Table** -To use either table implementation, you need to subclass into your own namespace: +<%= embed OpPrimer::BorderBoxTableComponentPreview, :default %> + +For the specifics of that component please have a look at the [BorderBoxTableComponent docs](./border_box_table). + +## Anatomy + +**Sortable table** + +* The Sortable Table results in a standard HTML table with some classes applied for styling. +* If `sortable` is set to true, all sortable column headers are clickable to change the sort order. When a sort is applied, that is indicated via an arrow. + +**Border Box Table** + +* The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. + +## Technical notes + +The `BorderBoxTableComponent` is a subclass of the `TableComponent`, so the following notes apply to both components. There are however some additional things to consider, for that please visit the [BorderBoxTableComponent docs](./border_box_table). + +To use either table implementation, you need to subclass the following classes onto your own namespace: - **Regular table:** `TableComponent` and `RowComponent` - **BorderBox table:** `OpPrimer::BorderBoxTableComponent` and `OpPrimer::BorderBoxRowComponent` -**Columns:** Define the columns of the table as class method `columns :a, :b, :c` +**Columns** -**Headers:** Define the headers of the component like so +Define the columns of the table as class method: ```ruby -def headers - [ - [:a, { caption: 'Column A' }], - [:b, { caption: 'Column B' }], - [:c, { caption: 'Column C' }] - ] -end -``` - -**Actions:** Define the actions in the row component as `button_links`. See the example code - -<%= embed OpPrimer::BorderBoxTableComponentPreview, :default, panels: %i[source] %> - -### Border Box Table specifics - -#### Mobile behavior - -On mobile, the BorderBoxTable does not scroll, but collapse into two columns (content columns and actions). You can control which columns are shown using the `mobile_columns` method. - -As the columns are collapsed, some information might need an additional label, which you can prepend with `mobile_labels`. - -```ruby -# On desktop, show these columns -columns :title, :users, :created_at - -# On mobile, only two columns are visible -mobile_columns :title, :users - -# For users, show the label using the header caption -mobile_labels :users -``` - -#### Mobile headers - -On mobile, the usual table headers are replaced with a single `mobile_title` property that you have to set on the table. - -#### Text wrapping behaviour - -By default, text longer than the column width will truncate with ellipsis. Only the main column has text that wraps around to display the full string. - -#### Main column - -Use the `main_column` helper to make a column 2 times as wide as the others and also display the full text: - -```ruby -# On desktop, show these columns -columns :title, :users, :created_at - -# Make title column wider than the others (factor 2 using grid span) -main_column :title -``` -Note: Ideally, one one main column will be present for each table. - -#### Footer - -Set `has_footer?` to true to add a footer to the table, defining the component/content to be rendered with the `footer` method. - -```ruby -def has_footer? - true -end - -def footer - render CustomFooterComponent.new(...) -end -``` - -## Best practices - -**Do** - -- Use a BorderBox table if you have a *few* entries of unsorted data, that does not require pagination -- Use up to two actions using the `:secondary` scheme of `Primer::Beta::Button` and `Primer::Beta::IconButton`. -- OR: Use an action menu with `:invisible` scheme - -**Don't** - -- Use the BorderBox table for a lot of items that require sorting or pagination - -## Examples - -For detailed examples have a look at the other [preview examples](/lookbook/inspect/OpenProject/Primer/border_box_table/default) of the component. +module ModuleA + class TableComponent <::TableComponent + columns :name +<%= embed OpenProject::Deprecated::TablePreview, :default, panels: %i[source] %> diff --git a/lookbook/previews/open_project/deprecated/table_preview/default.html.erb b/lookbook/previews/open_project/deprecated/table_preview/default.html.erb index 66bd797a8d8..5cd87af4c8c 100644 --- a/lookbook/previews/open_project/deprecated/table_preview/default.html.erb +++ b/lookbook/previews/open_project/deprecated/table_preview/default.html.erb @@ -1,100 +1,58 @@ -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - First - -
-
-
-
-
- - Second - -
-
-
-
-
- - Third - -
-
-
-
-
- - Fourth - -
-
-
-
-
- - Fifth - -
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elitNullam a sem et metus congue placerat.Mauris ut augue viverra, consequat eros eu, maximus quam.Maecenas elementum orci a varius suscipit.Nunc molestie neque sit amet eros semper dapibus.
Nullam a sem et metus congue placerat.Lorem ipsum dolor sit amet, consectetur adipiscing elitMauris ut augue viverra, consequat eros eu, maximus quam.Maecenas elementum orci a varius suscipit.Nunc molestie neque sit amet eros semper dapibus.
Nullam a sem et metus congue placerat.Mauris ut augue viverra, consequat eros eu, maximus quam.Lorem ipsum dolor sit amet, consectetur adipiscing elitMaecenas elementum orci a varius suscipit.Nunc molestie neque sit amet eros semper dapibus.
Nullam a sem et metus congue placerat.Mauris ut augue viverra, consequat eros eu, maximus quam.Maecenas elementum orci a varius suscipit.Lorem ipsum dolor sit amet, consectetur adipiscing elitNunc molestie neque sit amet eros semper dapibus.
Nullam a sem et metus congue placerat.Mauris ut augue viverra, consequat eros eu, maximus quam.Maecenas elementum orci a varius suscipit.Lorem ipsum dolor sit amet, consectetur adipiscing elitNunc molestie neque sit amet eros semper dapibus.
+<%= + table = Class.new(TableComponent) do + columns :foo, :bar -
-
+ def self.name + "MyTable" + end + + ## This method is just a hack used for the preview + ## Create your components under your namespace like so instead + ## MyNamespace::TableComponent + ## MyNamespace::RowComponent + ## and the other class will be autoloaded + def row_class + @row_class ||= Class.new(RowComponent) do + def self.name + "Row" + end + + def button_links + [ + delete_button + ] + end + + def delete_button + render(Primer::Beta::IconButton.new(icon: :trash, scheme: :danger, tag: :a, href: "#", "aria-label": "Delete")) + end + + def foo + render(Primer::Beta::Text.new(tag: :p)) { "Hello there" } + end + + def bar + "bar" + end + end + end + + def has_actions? + true + end + + def headers + [ + [:foo, { caption: "Foo column" }], + [:bar, { caption: "Bar column" }] + ] + end + + def sortable? + # True per default but for this preview disabled + false + end + end + + render(table.new(rows: [1, 2])) +%> From 1f5ce4215e108cfca84bcfee23623ee1f1ed87d2 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 2 Apr 2025 11:56:23 +0200 Subject: [PATCH 024/260] Update en.yml --- modules/meeting/config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/meeting/config/locales/en.yml b/modules/meeting/config/locales/en.yml index a3ee01a3079..c6adaa50775 100644 --- a/modules/meeting/config/locales/en.yml +++ b/modules/meeting/config/locales/en.yml @@ -452,7 +452,7 @@ en: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." From 0ffc60cb2409e40b0e88c8c2e5fd1d930a392ba2 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 2 Apr 2025 12:18:38 +0200 Subject: [PATCH 025/260] Undo rubocop changes which messed up the preview --- ...x-table.md.erb => border-box-table.md.erb} | 9 +++-- lookbook/docs/components/border-box.md.erb | 18 +++++---- lookbook/docs/components/tables.md.erb | 37 ++++++++++++++++++- .../deprecated/table_preview/default.html.erb | 4 +- 4 files changed, 54 insertions(+), 14 deletions(-) rename lookbook/docs/components/{borde-box-table.md.erb => border-box-table.md.erb} (88%) diff --git a/lookbook/docs/components/borde-box-table.md.erb b/lookbook/docs/components/border-box-table.md.erb similarity index 88% rename from lookbook/docs/components/borde-box-table.md.erb rename to lookbook/docs/components/border-box-table.md.erb index c633001424e..63d40fc521c 100644 --- a/lookbook/docs/components/borde-box-table.md.erb +++ b/lookbook/docs/components/border-box-table.md.erb @@ -4,19 +4,19 @@ ## Anatomy -**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility support). If you want or need that, please use the [TableComponent docs](./tables)) +**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility short cuts). If you want or need that, please use the [TableComponent docs](./tables)) ## Best practices **Do** -- Use a BorderBox table if you have a *few* entries of unsorted data, that does not require pagination +- Use a BorderBoxTable if you have a *few* entries of unsorted data, that does not require pagination - Use up to two actions using the `:secondary` scheme of `Primer::Beta::Button` and `Primer::Beta::IconButton`. - OR: Use an action menu with `:invisible` scheme **Don't** -- Use the BorderBox table for a lot of items that require sorting or pagination +- Use the BorderBoxTable for a lot of items that require sorting or pagination ## Technical notes @@ -79,3 +79,6 @@ end <%= embed OpPrimer::BorderBoxTableComponentPreview, :default, panels: %i[source] %> For detailed examples have a look at the other [preview examples](/lookbook/inspect/OpenProject/Primer/border_box_table/default) of the component. + +Note for Henriette: +Example with CollapsibleHeader??? diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index 5d08b83e85c..eff5dc17faa 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -1,7 +1,7 @@ The Border Box element is used to display structured items in a list, each with a set of actions. It is used for example: -- to display a list of meetings -- to display individual meeting agenda items in a meeting +- to display a list of meetings +- to display individual meeting agenda items in a meeting - to display the a list of project attributes - to display a list of configured OAuth applications @@ -14,12 +14,15 @@ The Border Box element is made up of If a page uses a Border Box with a header, all sections must use headers. -## Options +## Header + +Note for Parimal: +You can chose between a collapsibleHeader and a free-chosen Header. The collapsible Header consists of Title, counter(optional) and description(optional). - **Collapsible header**: A collapsible header has an arrow next to the title and allows collapsing and expanding the contents below. When collapsed, the bottom border is slightly thicker to indicate something is hidden. -- **Header description**: When collapsed, the optional header description is hidden. -- **Header counter**: The counter can display the number of items that that particular section contains. -- **Draggable**: Both header and items can have drag handles. Individual items can be dragged up and down and into other sections. The sections themselves can also be moved up and down. + - **Header description**: When collapsed, the optional header description is hidden. + - **Header counter**: The counter can display the number of items that that particular section contains. + - **More button**: A more button can have contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). ## Best practices @@ -27,11 +30,12 @@ If a page uses a Border Box with a header, all sections must use headers. **Do** - Use sections (with headers) to better organise content if they have logical categories (eg. Open and Planned meetings). +- - **Draggable**: Both header and items can have drag handles. Individual items can be dragged up and down and into other sections. The sections themselves can also be moved up and down. **Don't** - Don't mix sections with and without headers. If one section has a header, they must all have headers. -- Don't make sections collapsible if they do not need to be. +- Don't make sections collapsible if they do not need to be. ## Technical notes diff --git a/lookbook/docs/components/tables.md.erb b/lookbook/docs/components/tables.md.erb index bf466391a56..559ffea6bb6 100644 --- a/lookbook/docs/components/tables.md.erb +++ b/lookbook/docs/components/tables.md.erb @@ -41,6 +41,39 @@ Define the columns of the table as class method: ```ruby module ModuleA - class TableComponent <::TableComponent - columns :name + class TableComponent < ::TableComponent + columns :name, :description, :sort + # ... + end +end +``` + +**Headers** + +Define the headers of the component as a method retu + +```ruby +module ModuleA + class TableComponent < ::TableComponent + # ... + + def headers + [ + [:a, { caption: 'Column A' }], + [:b, { caption: 'Column B' }], + [:c, { caption: 'Column C' }] + ] + end + + # ... + end +end +``` + +**Actions** + +Define the actions in the row component as `button_links`. See the example code + +### Full example + <%= embed OpenProject::Deprecated::TablePreview, :default, panels: %i[source] %> diff --git a/lookbook/previews/open_project/deprecated/table_preview/default.html.erb b/lookbook/previews/open_project/deprecated/table_preview/default.html.erb index 5cd87af4c8c..882ef8f21ca 100644 --- a/lookbook/previews/open_project/deprecated/table_preview/default.html.erb +++ b/lookbook/previews/open_project/deprecated/table_preview/default.html.erb @@ -28,11 +28,11 @@ end def foo - render(Primer::Beta::Text.new(tag: :p)) { "Hello there" } + render(Primer::Beta::Text.new(tag: :p)) { "Lorem ipsum dolor sit amet, consetetur sadipscing elitr" } end def bar - "bar" + "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." end end end From a1997eeba659e2e9dc79b751267e451a6ac8ab40 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 2 Apr 2025 13:00:17 +0200 Subject: [PATCH 026/260] Update test --- modules/meeting/spec/support/pages/structured_meeting/show.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/meeting/spec/support/pages/structured_meeting/show.rb b/modules/meeting/spec/support/pages/structured_meeting/show.rb index 2368a5fb0a6..dbbbe0ef758 100644 --- a/modules/meeting/spec/support/pages/structured_meeting/show.rb +++ b/modules/meeting/spec/support/pages/structured_meeting/show.rb @@ -331,7 +331,7 @@ module Pages::StructuredMeeting def reopen_meeting click_on("Reopen meeting") - expect(page).to have_link("Mark as in progress") + expect(page).to have_link("Start meeting") end def close_dialog From 4c6e0ea599289a8cfbe423ed199b46732612d89d Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 2 Apr 2025 15:01:16 +0200 Subject: [PATCH 027/260] Clean-up comments --- lookbook/docs/components/border-box-table.md.erb | 3 --- .../op_primer/border_box_table_component_preview.rb | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lookbook/docs/components/border-box-table.md.erb b/lookbook/docs/components/border-box-table.md.erb index 63d40fc521c..72a53164520 100644 --- a/lookbook/docs/components/border-box-table.md.erb +++ b/lookbook/docs/components/border-box-table.md.erb @@ -79,6 +79,3 @@ end <%= embed OpPrimer::BorderBoxTableComponentPreview, :default, panels: %i[source] %> For detailed examples have a look at the other [preview examples](/lookbook/inspect/OpenProject/Primer/border_box_table/default) of the component. - -Note for Henriette: -Example with CollapsibleHeader??? diff --git a/lookbook/previews/op_primer/border_box_table_component_preview.rb b/lookbook/previews/op_primer/border_box_table_component_preview.rb index d37449ccfe1..48402b2a59e 100644 --- a/lookbook/previews/op_primer/border_box_table_component_preview.rb +++ b/lookbook/previews/op_primer/border_box_table_component_preview.rb @@ -4,17 +4,17 @@ module OpPrimer # @logical_path OpenProject/Primer # @display min_height 300px class BorderBoxTableComponentPreview < Lookbook::Preview - # See the [component documentation](/lookbook/pages/components/tables) for more details. + # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. def default render_with_template end - # See the [component documentation](/lookbook/pages/components/tables) for more details. + # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. def custom_column_widths render_with_template end - # See the [component documentation](/lookbook/pages/components/tables) for more details. + # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. def with_action_menu render_with_template end From 13e15459a7d50aa9c1a6f59ff85530d91a853e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 3 Apr 2025 07:52:20 +0200 Subject: [PATCH 028/260] Bumped version to 15.6.0 [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 02e39033f3e..390c784aef8 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -32,7 +32,7 @@ require "open3" module OpenProject module VERSION # :nodoc: MAJOR = 15 - MINOR = 5 + MINOR = 6 PATCH = 0 class << self From f1073606062ff4a6e2633b260ffc58ce6ac8a54d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 05:21:04 +0000 Subject: [PATCH 029/260] Bump the fullcalendar group in /frontend with 8 updates Bumps the fullcalendar group in /frontend with 8 updates: | Package | From | To | | --- | --- | --- | | [@fullcalendar/angular](https://github.com/fullcalendar/fullcalendar-angular) | `6.1.16` | `6.1.17` | | [@fullcalendar/core](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/core) | `6.1.15` | `6.1.17` | | [@fullcalendar/daygrid](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/daygrid) | `6.1.15` | `6.1.17` | | [@fullcalendar/interaction](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/interaction) | `6.1.15` | `6.1.17` | | [@fullcalendar/list](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/list) | `6.1.15` | `6.1.17` | | [@fullcalendar/resource](https://github.com/fullcalendar/fullcalendar-workspace/tree/HEAD/premium/packages/resource) | `6.1.15` | `6.1.17` | | [@fullcalendar/resource-timeline](https://github.com/fullcalendar/fullcalendar-workspace/tree/HEAD/premium/packages/resource-timeline) | `6.1.15` | `6.1.17` | | [@fullcalendar/timegrid](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/timegrid) | `6.1.15` | `6.1.17` | Updates `@fullcalendar/angular` from 6.1.16 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar-angular/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar-angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar-angular/compare/v6.1.16...v6.1.17) Updates `@fullcalendar/core` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.17/packages/core) Updates `@fullcalendar/daygrid` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.17/packages/daygrid) Updates `@fullcalendar/interaction` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.17/packages/interaction) Updates `@fullcalendar/list` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.17/packages/list) Updates `@fullcalendar/resource` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar-workspace/releases) - [Commits](https://github.com/fullcalendar/fullcalendar-workspace/commits/v6.1.17/premium/packages/resource) Updates `@fullcalendar/resource-timeline` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar-workspace/releases) - [Commits](https://github.com/fullcalendar/fullcalendar-workspace/commits/v6.1.17/premium/packages/resource-timeline) Updates `@fullcalendar/timegrid` from 6.1.15 to 6.1.17 - [Release notes](https://github.com/fullcalendar/fullcalendar/releases) - [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md) - [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.17/packages/timegrid) --- updated-dependencies: - dependency-name: "@fullcalendar/angular" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/core" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/daygrid" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/interaction" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/list" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/resource" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/resource-timeline" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar - dependency-name: "@fullcalendar/timegrid" dependency-version: 6.1.17 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fullcalendar ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 197 ++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 93 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 741df5d4c03..c0126af3a2a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3221,16 +3221,17 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" }, "node_modules/@fullcalendar/angular": { - "version": "6.1.16", - "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.16.tgz", - "integrity": "sha512-Qqs0MZPlIDretmWgtOr0H+uiLO6DKeqxqH1Y2oeWufwEbQTaAxhH7mivdTmxL596JkiuJ/1dhCm+v4tVbFb40w==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.17.tgz", + "integrity": "sha512-1XSiT62/KItFZCtecuqcxd0mxctQQcJuJbXfLFPjGG9Ycz6+af+bC0Ch89W+uYSPkGrmk7tczELouckJLSJm2Q==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "12 - 19", "@angular/core": "12 - 19", - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/common": { @@ -3242,54 +3243,60 @@ } }, "node_modules/@fullcalendar/core": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.15.tgz", - "integrity": "sha512-BuX7o6ALpLb84cMw1FCB9/cSgF4JbVO894cjJZ6kP74jzbUZNjtwffwRdA+Id8rrLjT30d/7TrkW90k4zbXB5Q==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.17.tgz", + "integrity": "sha512-0W7lnIrv18ruJ5zeWBeNZXO8qCWlzxDdp9COFEsZnyNjiEhUVnrW/dPbjRKYpL0edGG0/Lhs0ghp1z/5ekt8ZA==", + "license": "MIT", "dependencies": { "preact": "~10.12.1" } }, "node_modules/@fullcalendar/daygrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.15.tgz", - "integrity": "sha512-j8tL0HhfiVsdtOCLfzK2J0RtSkiad3BYYemwQKq512cx6btz6ZZ2RNc/hVnIxluuWFyvx5sXZwoeTJsFSFTEFA==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.17.tgz", + "integrity": "sha512-K7m+pd7oVJ9fW4h7CLDdDGJbc9szJ1xDU1DZ2ag+7oOo1aCNLv44CehzkkknM6r8EYlOOhgaelxQpKAI4glj7A==", + "license": "MIT", "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/interaction": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.15.tgz", - "integrity": "sha512-DOTSkofizM7QItjgu7W68TvKKvN9PSEEvDJceyMbQDvlXHa7pm/WAVtAc6xSDZ9xmB1QramYoWGLHkCYbTW1rQ==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.17.tgz", + "integrity": "sha512-AudvQvgmJP2FU89wpSulUUjeWv24SuyCx8FzH2WIPVaYg+vDGGYarI7K6PcM3TH7B/CyaBjm5Rqw9lXgnwt5YA==", + "license": "MIT", "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/list": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.15.tgz", - "integrity": "sha512-U1bce04tYDwkFnuVImJSy2XalYIIQr6YusOWRPM/5ivHcJh67Gm8CIMSWpi3KdRSNKFkqBxLPkfZGBMaOcJYug==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.17.tgz", + "integrity": "sha512-fkyK49F9IxwlGUBVhJGsFpd/LTi/vRVERLIAe1HmBaGkjwpxnynm8TMLb9mZip97wvDk3CmZWduMe6PxscAlow==", + "license": "MIT", "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/premium-common": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.15.tgz", - "integrity": "sha512-IwUHptHNzWDOgAsXLoBntGxmbfCKvUy6iYFMCP3F3ahbG58E0PJMYsXvgw+NaA7Cz4gcQoVHioGjIFgQqs3Keg==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.17.tgz", + "integrity": "sha512-zoN7fMwGMcP6Xu+2YudRAGfdwD2J+V+A/xAieXgYDSZT+5ekCsjZiwb2rmvthjt+HVnuZcqs6sGp7rnJ8Ie/mA==", + "license": "SEE LICENSE IN LICENSE.md", "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/resource": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.15.tgz", - "integrity": "sha512-s9Rz3HNDQWBYCG+V4wqg8x5+UTD5kC3S2poq+5zwbPeyWT8+FEILikQZIgfESX70Z4fn8bBlLJ04Jd/LijfqWw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.17.tgz", + "integrity": "sha512-hWnbOWlroIN5Wt4NJmHAJh/F7ge2cV6S0PdGSmLFoZJZJA0hJX9GeYRzyz4MlUoj7f4dGzBlesy2RdC+t5FEMw==", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@fullcalendar/premium-common": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/resource-common": { @@ -3312,51 +3319,55 @@ } }, "node_modules/@fullcalendar/resource-timeline": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.15.tgz", - "integrity": "sha512-3bvGNDE84ZEV6RLZcYWvMWaViLm22Uw182PMXmFjvq2Vh/bPrrzeLkmyocPsyiT2Bbv5THxwLyzMd7X3Qi/v3Q==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.17.tgz", + "integrity": "sha512-QMrtc1mLs4c6DtlBNmWICef8Lr4CmzE47uWS/rcJBd9K2kBzvusTp7AQQ1qn3RX5UnjNHqT8pkKO/wE4yspJQw==", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@fullcalendar/premium-common": "~6.1.15", - "@fullcalendar/scrollgrid": "~6.1.15", - "@fullcalendar/timeline": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17", + "@fullcalendar/scrollgrid": "~6.1.17", + "@fullcalendar/timeline": "~6.1.17" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.15", - "@fullcalendar/resource": "~6.1.15" + "@fullcalendar/core": "~6.1.17", + "@fullcalendar/resource": "~6.1.17" } }, "node_modules/@fullcalendar/scrollgrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.15.tgz", - "integrity": "sha512-z7q6eh9bUSQ60YwgztPlJzQAMr6XQgky6bxNQR9cMqfzcwyo/ww11G7OZUp840VIXyqT3g8XPziEDbS5zB4VVQ==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.17.tgz", + "integrity": "sha512-lzphEKwxWMS4xQVEuimzZjKFLijlSn49ExvzkYZls0VLDwOa3BYHcRlDJBjQ0LP6kauz9aatg3MfRIde/LAazA==", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@fullcalendar/premium-common": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/timegrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.15.tgz", - "integrity": "sha512-61ORr3A148RtxQ2FNG7JKvacyA/TEVZ7z6I+3E9Oeu3dqTf6M928bFcpehRTIK6zIA6Yifs7BeWHgOE9dFnpbw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.17.tgz", + "integrity": "sha512-K4PlA3L3lclLOs3IX8cvddeiJI9ZVMD7RA9IqaWwbvac771971foc9tFze9YY+Pqesf6S+vhS2dWtEVlERaGlQ==", + "license": "MIT", "dependencies": { - "@fullcalendar/daygrid": "~6.1.15" + "@fullcalendar/daygrid": "~6.1.17" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@fullcalendar/timeline": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.15.tgz", - "integrity": "sha512-VWylStpFFS8lZVUqu0c1b0MF5gkuVH2lzyCK/gopMsbrppqr97sHDTfWEYDHaQXCeO7cd4gKXSliQ0dc9GMlUw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.17.tgz", + "integrity": "sha512-UhL2OOph/S0cEKs3lzbXjS2gTxmQwaNug2XFjdljvO/ERj10v7OBXj/zvJrPyhjvWR/CSgjNgBaUpngkCu4JtQ==", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@fullcalendar/premium-common": "~6.1.15", - "@fullcalendar/scrollgrid": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17", + "@fullcalendar/scrollgrid": "~6.1.17" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.15" + "@fullcalendar/core": "~6.1.17" } }, "node_modules/@github/auto-check-element": { @@ -24243,9 +24254,9 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" }, "@fullcalendar/angular": { - "version": "6.1.16", - "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.16.tgz", - "integrity": "sha512-Qqs0MZPlIDretmWgtOr0H+uiLO6DKeqxqH1Y2oeWufwEbQTaAxhH7mivdTmxL596JkiuJ/1dhCm+v4tVbFb40w==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.17.tgz", + "integrity": "sha512-1XSiT62/KItFZCtecuqcxd0mxctQQcJuJbXfLFPjGG9Ycz6+af+bC0Ch89W+uYSPkGrmk7tczELouckJLSJm2Q==", "requires": { "tslib": "^2.3.0" } @@ -24259,39 +24270,39 @@ } }, "@fullcalendar/core": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.15.tgz", - "integrity": "sha512-BuX7o6ALpLb84cMw1FCB9/cSgF4JbVO894cjJZ6kP74jzbUZNjtwffwRdA+Id8rrLjT30d/7TrkW90k4zbXB5Q==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.17.tgz", + "integrity": "sha512-0W7lnIrv18ruJ5zeWBeNZXO8qCWlzxDdp9COFEsZnyNjiEhUVnrW/dPbjRKYpL0edGG0/Lhs0ghp1z/5ekt8ZA==", "requires": { "preact": "~10.12.1" } }, "@fullcalendar/daygrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.15.tgz", - "integrity": "sha512-j8tL0HhfiVsdtOCLfzK2J0RtSkiad3BYYemwQKq512cx6btz6ZZ2RNc/hVnIxluuWFyvx5sXZwoeTJsFSFTEFA==" + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.17.tgz", + "integrity": "sha512-K7m+pd7oVJ9fW4h7CLDdDGJbc9szJ1xDU1DZ2ag+7oOo1aCNLv44CehzkkknM6r8EYlOOhgaelxQpKAI4glj7A==" }, "@fullcalendar/interaction": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.15.tgz", - "integrity": "sha512-DOTSkofizM7QItjgu7W68TvKKvN9PSEEvDJceyMbQDvlXHa7pm/WAVtAc6xSDZ9xmB1QramYoWGLHkCYbTW1rQ==" + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.17.tgz", + "integrity": "sha512-AudvQvgmJP2FU89wpSulUUjeWv24SuyCx8FzH2WIPVaYg+vDGGYarI7K6PcM3TH7B/CyaBjm5Rqw9lXgnwt5YA==" }, "@fullcalendar/list": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.15.tgz", - "integrity": "sha512-U1bce04tYDwkFnuVImJSy2XalYIIQr6YusOWRPM/5ivHcJh67Gm8CIMSWpi3KdRSNKFkqBxLPkfZGBMaOcJYug==" + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.17.tgz", + "integrity": "sha512-fkyK49F9IxwlGUBVhJGsFpd/LTi/vRVERLIAe1HmBaGkjwpxnynm8TMLb9mZip97wvDk3CmZWduMe6PxscAlow==" }, "@fullcalendar/premium-common": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.15.tgz", - "integrity": "sha512-IwUHptHNzWDOgAsXLoBntGxmbfCKvUy6iYFMCP3F3ahbG58E0PJMYsXvgw+NaA7Cz4gcQoVHioGjIFgQqs3Keg==" + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.17.tgz", + "integrity": "sha512-zoN7fMwGMcP6Xu+2YudRAGfdwD2J+V+A/xAieXgYDSZT+5ekCsjZiwb2rmvthjt+HVnuZcqs6sGp7rnJ8Ie/mA==" }, "@fullcalendar/resource": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.15.tgz", - "integrity": "sha512-s9Rz3HNDQWBYCG+V4wqg8x5+UTD5kC3S2poq+5zwbPeyWT8+FEILikQZIgfESX70Z4fn8bBlLJ04Jd/LijfqWw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.17.tgz", + "integrity": "sha512-hWnbOWlroIN5Wt4NJmHAJh/F7ge2cV6S0PdGSmLFoZJZJA0hJX9GeYRzyz4MlUoj7f4dGzBlesy2RdC+t5FEMw==", "requires": { - "@fullcalendar/premium-common": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17" } }, "@fullcalendar/resource-common": { @@ -24316,38 +24327,38 @@ } }, "@fullcalendar/resource-timeline": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.15.tgz", - "integrity": "sha512-3bvGNDE84ZEV6RLZcYWvMWaViLm22Uw182PMXmFjvq2Vh/bPrrzeLkmyocPsyiT2Bbv5THxwLyzMd7X3Qi/v3Q==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.17.tgz", + "integrity": "sha512-QMrtc1mLs4c6DtlBNmWICef8Lr4CmzE47uWS/rcJBd9K2kBzvusTp7AQQ1qn3RX5UnjNHqT8pkKO/wE4yspJQw==", "requires": { - "@fullcalendar/premium-common": "~6.1.15", - "@fullcalendar/scrollgrid": "~6.1.15", - "@fullcalendar/timeline": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17", + "@fullcalendar/scrollgrid": "~6.1.17", + "@fullcalendar/timeline": "~6.1.17" } }, "@fullcalendar/scrollgrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.15.tgz", - "integrity": "sha512-z7q6eh9bUSQ60YwgztPlJzQAMr6XQgky6bxNQR9cMqfzcwyo/ww11G7OZUp840VIXyqT3g8XPziEDbS5zB4VVQ==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.17.tgz", + "integrity": "sha512-lzphEKwxWMS4xQVEuimzZjKFLijlSn49ExvzkYZls0VLDwOa3BYHcRlDJBjQ0LP6kauz9aatg3MfRIde/LAazA==", "requires": { - "@fullcalendar/premium-common": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17" } }, "@fullcalendar/timegrid": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.15.tgz", - "integrity": "sha512-61ORr3A148RtxQ2FNG7JKvacyA/TEVZ7z6I+3E9Oeu3dqTf6M928bFcpehRTIK6zIA6Yifs7BeWHgOE9dFnpbw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.17.tgz", + "integrity": "sha512-K4PlA3L3lclLOs3IX8cvddeiJI9ZVMD7RA9IqaWwbvac771971foc9tFze9YY+Pqesf6S+vhS2dWtEVlERaGlQ==", "requires": { - "@fullcalendar/daygrid": "~6.1.15" + "@fullcalendar/daygrid": "~6.1.17" } }, "@fullcalendar/timeline": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.15.tgz", - "integrity": "sha512-VWylStpFFS8lZVUqu0c1b0MF5gkuVH2lzyCK/gopMsbrppqr97sHDTfWEYDHaQXCeO7cd4gKXSliQ0dc9GMlUw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.17.tgz", + "integrity": "sha512-UhL2OOph/S0cEKs3lzbXjS2gTxmQwaNug2XFjdljvO/ERj10v7OBXj/zvJrPyhjvWR/CSgjNgBaUpngkCu4JtQ==", "requires": { - "@fullcalendar/premium-common": "~6.1.15", - "@fullcalendar/scrollgrid": "~6.1.15" + "@fullcalendar/premium-common": "~6.1.17", + "@fullcalendar/scrollgrid": "~6.1.17" } }, "@github/auto-check-element": { From c96734da4d50ee04c53124e1a55c2f52e181d32a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 05:19:24 +0000 Subject: [PATCH 030/260] Bump the angular group in /frontend with 2 updates Bumps the angular group in /frontend with 2 updates: [@angular/cli](https://github.com/angular/angular-cli) and [@angular-devkit/build-angular](https://github.com/angular/angular-cli). Updates `@angular/cli` from 17.3.14 to 17.3.15 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.14...17.3.15) Updates `@angular-devkit/build-angular` from 17.3.14 to 17.3.15 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.14...17.3.15) --- updated-dependencies: - dependency-name: "@angular/cli" dependency-version: 17.3.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-devkit/build-angular" dependency-version: 17.3.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 496 ++++++++++++++++++------------------- 1 file changed, 248 insertions(+), 248 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c0126af3a2a..7064785ec56 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -265,12 +265,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1703.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.14.tgz", - "integrity": "sha512-9Uri50NwmsHbhGfkr948m04Hp82OFW5Ejbqv0kagoFAKz4+5LkBGvEnXJptoIy71dxMlYM0iSjWzdrz1AXUGGQ==", + "version": "0.1703.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.15.tgz", + "integrity": "sha512-7N7wLi/zdqTcWYMfLox2pL9Vqclve8dnNulVmuI/An8Wr35OSu2DhiHcQGR9fcLatyuMTFy/yXiqNr1l05IVkw==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.14", + "@angular-devkit/core": "17.3.15", "rxjs": "7.8.1" }, "engines": { @@ -289,15 +289,15 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.14.tgz", - "integrity": "sha512-+09b1pF9Q7OFANUxZvjK3CYKlEUpBfEWy2SuefIhdQS5KoyKiPp01iWNTnAPiMqi+3JV18ETMUS8wRfrg/RndA==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.15.tgz", + "integrity": "sha512-RM3zQb0SQmW7lrGHBA18EC8DhbKZViSiUZxaus5iZahbgRP3kpMA+Mbn3JlOyfojMO9GZ27zx4LoF/FYo1bDTw==", "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1703.14", - "@angular-devkit/build-webpack": "0.1703.14", - "@angular-devkit/core": "17.3.14", + "@angular-devkit/architect": "0.1703.15", + "@angular-devkit/build-webpack": "0.1703.15", + "@angular-devkit/core": "17.3.15", "@babel/core": "7.26.10", "@babel/generator": "7.26.10", "@babel/helper-annotate-as-pure": "7.25.9", @@ -308,7 +308,7 @@ "@babel/preset-env": "7.26.9", "@babel/runtime": "7.26.10", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "17.3.14", + "@ngtools/webpack": "17.3.15", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.18", @@ -350,7 +350,7 @@ "tree-kill": "1.2.2", "tslib": "2.6.2", "undici": "6.11.1", - "vite": "5.4.15", + "vite": "5.4.16", "watchpack": "2.4.0", "webpack": "5.94.0", "webpack-dev-middleware": "6.1.2", @@ -552,12 +552,12 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1703.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.14.tgz", - "integrity": "sha512-CxPUiTKsHduUDpvQ6TPWFvOciH4GdtJVmIxu4jj6qFw/UUCz+y0kH7aBjYEM+khKt87diu7urRdRN4IkaAboKw==", + "version": "0.1703.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.15.tgz", + "integrity": "sha512-BpqybfdfeLgW9km7CrnuwMVuuShCwNF0mUEUlv49eb2m/S59beMbER5R46PcHXaJSjc5haIGaipDn/jw+27a7Q==", "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1703.14", + "@angular-devkit/architect": "0.1703.15", "rxjs": "7.8.1" }, "engines": { @@ -580,9 +580,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.14.tgz", - "integrity": "sha512-HXnWlQjvXU4/cnu2vcp4iYuL3N2PBsDXXIElTNFHi0LjDBQSbWS4ndokEAEzikXZUcY3gealBcR51DBNQkf1tw==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.15.tgz", + "integrity": "sha512-0VUf7QR/Xv7x/YafATcI3WzSYgKbos8oF8IiBR3OFGhwpEB8XT4rUDcdT9fN11j7ZidTqJlot7DPpSIZzt3j2g==", "license": "MIT", "dependencies": { "ajv": "8.12.0", @@ -627,12 +627,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.14.tgz", - "integrity": "sha512-NS24F4fxOkakiRqg2RN0HGNr6hEThtHuKm9iLtT8Qv3ncq1F7iGkJzzAJgvJTsi7ZqBCDumLUs+Boor/x4bGyA==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.15.tgz", + "integrity": "sha512-MKOJg7d1dect8mzQ69QJQJrd0Bpb/1nt6V9VFCUlewngtVQ5S//iaxhpOJ9qB1SX9aGu1fTsiOaOWKUiNT+lOQ==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.14", + "@angular-devkit/core": "17.3.15", "jsonc-parser": "3.2.1", "magic-string": "0.30.8", "ora": "5.4.1", @@ -884,15 +884,15 @@ } }, "node_modules/@angular/cli": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.14.tgz", - "integrity": "sha512-PsNkofWubUfRZxsBkpRzflncCLfISxta2YerzhN/AlTa/L0Br2iY5XiXl6Kb1a5f/vg7pqT5qpleSu8O8KUiCw==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.15.tgz", + "integrity": "sha512-DYdvWsHphdQfN/XH1QMIOpivu7+n80Mj6x9S/wt1NbNFeLAAM4j60dicdr/U9bw/LjgN/qobLlak6JTioApT1Q==", "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1703.14", - "@angular-devkit/core": "17.3.14", - "@angular-devkit/schematics": "17.3.14", - "@schematics/angular": "17.3.14", + "@angular-devkit/architect": "0.1703.15", + "@angular-devkit/core": "17.3.15", + "@angular-devkit/schematics": "17.3.15", + "@schematics/angular": "17.3.15", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -3959,9 +3959,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.14.tgz", - "integrity": "sha512-ej9lv4UJPscVXNw9NNHwmzXWhDvSXKMggiMSLh35Ahk1UvMI0y8LGtvy7Egzvgk5P1hD9xw4sp05dKLN63SyVg==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.15.tgz", + "integrity": "sha512-6WVRr9vIndTLvrU9ygtvI/QpBO3/DazSrXi2TUZ27Tku5csLqHqGHSXrwd0a5zumKY8A0yK54vOx3vTqGj/YnQ==", "license": "MIT", "engines": { "node": "^18.13.0 || >=20.9.0", @@ -4865,9 +4865,9 @@ "integrity": "sha512-ybBsUrIsu5geM8BtqnpM7ZA9D8uzSz+e1B4JR57NaCmasHKWap6AX5DT7NHIbp21opVet1qqoVSdsoLDqXeB2A==" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", - "integrity": "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", + "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", "cpu": [ "arm" ], @@ -4878,9 +4878,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz", - "integrity": "sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", + "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", "cpu": [ "arm64" ], @@ -4891,9 +4891,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz", - "integrity": "sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", + "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", "cpu": [ "arm64" ], @@ -4904,9 +4904,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz", - "integrity": "sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", + "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", "cpu": [ "x64" ], @@ -4917,9 +4917,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz", - "integrity": "sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", + "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", "cpu": [ "arm64" ], @@ -4930,9 +4930,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz", - "integrity": "sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", + "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", "cpu": [ "x64" ], @@ -4943,9 +4943,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz", - "integrity": "sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", + "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", "cpu": [ "arm" ], @@ -4956,9 +4956,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz", - "integrity": "sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", + "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", "cpu": [ "arm" ], @@ -4969,9 +4969,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz", - "integrity": "sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", + "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", "cpu": [ "arm64" ], @@ -4982,9 +4982,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz", - "integrity": "sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", + "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", "cpu": [ "arm64" ], @@ -4995,9 +4995,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz", - "integrity": "sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", + "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", "cpu": [ "loong64" ], @@ -5008,9 +5008,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz", - "integrity": "sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", + "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", "cpu": [ "ppc64" ], @@ -5021,9 +5021,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz", - "integrity": "sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", + "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", "cpu": [ "riscv64" ], @@ -5034,9 +5034,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz", - "integrity": "sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", + "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", "cpu": [ "riscv64" ], @@ -5047,9 +5047,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz", - "integrity": "sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", + "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", "cpu": [ "s390x" ], @@ -5060,9 +5060,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz", - "integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", + "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", "cpu": [ "x64" ], @@ -5073,9 +5073,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz", - "integrity": "sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", + "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", "cpu": [ "x64" ], @@ -5086,9 +5086,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz", - "integrity": "sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", + "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", "cpu": [ "arm64" ], @@ -5099,9 +5099,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz", - "integrity": "sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", + "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", "cpu": [ "ia32" ], @@ -5112,9 +5112,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz", - "integrity": "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", + "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", "cpu": [ "x64" ], @@ -5131,13 +5131,13 @@ "dev": true }, "node_modules/@schematics/angular": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.14.tgz", - "integrity": "sha512-udffrlrXmfW52pMGMp2P9nM/LN42c3GuUqCiLSEJB0v/YqL962V+QOgrjTPrjzh5DiJv5oLdsE0dJH+oTediWg==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.15.tgz", + "integrity": "sha512-6IbvlKggDeZ7C//rVM9XbksWj9hFx56zZH3ndJ0vZ1FbrlFIxuWRjmB8bhHy5kk9xRobhzKFSVEHZexwdmOfWw==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.14", - "@angular-devkit/schematics": "17.3.14", + "@angular-devkit/core": "17.3.15", + "@angular-devkit/schematics": "17.3.15", "jsonc-parser": "3.2.1" }, "engines": { @@ -18020,9 +18020,9 @@ } }, "node_modules/rollup": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", - "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", + "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", "license": "MIT", "dependencies": { "@types/estree": "1.0.7" @@ -18035,26 +18035,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.38.0", - "@rollup/rollup-android-arm64": "4.38.0", - "@rollup/rollup-darwin-arm64": "4.38.0", - "@rollup/rollup-darwin-x64": "4.38.0", - "@rollup/rollup-freebsd-arm64": "4.38.0", - "@rollup/rollup-freebsd-x64": "4.38.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.38.0", - "@rollup/rollup-linux-arm-musleabihf": "4.38.0", - "@rollup/rollup-linux-arm64-gnu": "4.38.0", - "@rollup/rollup-linux-arm64-musl": "4.38.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.38.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-musl": "4.38.0", - "@rollup/rollup-linux-s390x-gnu": "4.38.0", - "@rollup/rollup-linux-x64-gnu": "4.38.0", - "@rollup/rollup-linux-x64-musl": "4.38.0", - "@rollup/rollup-win32-arm64-msvc": "4.38.0", - "@rollup/rollup-win32-ia32-msvc": "4.38.0", - "@rollup/rollup-win32-x64-msvc": "4.38.0", + "@rollup/rollup-android-arm-eabi": "4.39.0", + "@rollup/rollup-android-arm64": "4.39.0", + "@rollup/rollup-darwin-arm64": "4.39.0", + "@rollup/rollup-darwin-x64": "4.39.0", + "@rollup/rollup-freebsd-arm64": "4.39.0", + "@rollup/rollup-freebsd-x64": "4.39.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", + "@rollup/rollup-linux-arm-musleabihf": "4.39.0", + "@rollup/rollup-linux-arm64-gnu": "4.39.0", + "@rollup/rollup-linux-arm64-musl": "4.39.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-musl": "4.39.0", + "@rollup/rollup-linux-s390x-gnu": "4.39.0", + "@rollup/rollup-linux-x64-gnu": "4.39.0", + "@rollup/rollup-linux-x64-musl": "4.39.0", + "@rollup/rollup-win32-arm64-msvc": "4.39.0", + "@rollup/rollup-win32-ia32-msvc": "4.39.0", + "@rollup/rollup-win32-x64-msvc": "4.39.0", "fsevents": "~2.3.2" } }, @@ -21125,9 +21125,9 @@ } }, "node_modules/vite": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", - "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", + "version": "5.4.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.16.tgz", + "integrity": "sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==", "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -22453,11 +22453,11 @@ } }, "@angular-devkit/architect": { - "version": "0.1703.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.14.tgz", - "integrity": "sha512-9Uri50NwmsHbhGfkr948m04Hp82OFW5Ejbqv0kagoFAKz4+5LkBGvEnXJptoIy71dxMlYM0iSjWzdrz1AXUGGQ==", + "version": "0.1703.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.15.tgz", + "integrity": "sha512-7N7wLi/zdqTcWYMfLox2pL9Vqclve8dnNulVmuI/An8Wr35OSu2DhiHcQGR9fcLatyuMTFy/yXiqNr1l05IVkw==", "requires": { - "@angular-devkit/core": "17.3.14", + "@angular-devkit/core": "17.3.15", "rxjs": "7.8.1" }, "dependencies": { @@ -22472,14 +22472,14 @@ } }, "@angular-devkit/build-angular": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.14.tgz", - "integrity": "sha512-+09b1pF9Q7OFANUxZvjK3CYKlEUpBfEWy2SuefIhdQS5KoyKiPp01iWNTnAPiMqi+3JV18ETMUS8wRfrg/RndA==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.15.tgz", + "integrity": "sha512-RM3zQb0SQmW7lrGHBA18EC8DhbKZViSiUZxaus5iZahbgRP3kpMA+Mbn3JlOyfojMO9GZ27zx4LoF/FYo1bDTw==", "requires": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1703.14", - "@angular-devkit/build-webpack": "0.1703.14", - "@angular-devkit/core": "17.3.14", + "@angular-devkit/architect": "0.1703.15", + "@angular-devkit/build-webpack": "0.1703.15", + "@angular-devkit/core": "17.3.15", "@babel/core": "7.26.10", "@babel/generator": "7.26.10", "@babel/helper-annotate-as-pure": "7.25.9", @@ -22490,7 +22490,7 @@ "@babel/preset-env": "7.26.9", "@babel/runtime": "7.26.10", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "17.3.14", + "@ngtools/webpack": "17.3.15", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.18", @@ -22533,7 +22533,7 @@ "tree-kill": "1.2.2", "tslib": "2.6.2", "undici": "6.11.1", - "vite": "5.4.15", + "vite": "5.4.16", "watchpack": "2.4.0", "webpack": "5.94.0", "webpack-dev-middleware": "6.1.2", @@ -22620,11 +22620,11 @@ } }, "@angular-devkit/build-webpack": { - "version": "0.1703.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.14.tgz", - "integrity": "sha512-CxPUiTKsHduUDpvQ6TPWFvOciH4GdtJVmIxu4jj6qFw/UUCz+y0kH7aBjYEM+khKt87diu7urRdRN4IkaAboKw==", + "version": "0.1703.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.15.tgz", + "integrity": "sha512-BpqybfdfeLgW9km7CrnuwMVuuShCwNF0mUEUlv49eb2m/S59beMbER5R46PcHXaJSjc5haIGaipDn/jw+27a7Q==", "requires": { - "@angular-devkit/architect": "0.1703.14", + "@angular-devkit/architect": "0.1703.15", "rxjs": "7.8.1" }, "dependencies": { @@ -22639,9 +22639,9 @@ } }, "@angular-devkit/core": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.14.tgz", - "integrity": "sha512-HXnWlQjvXU4/cnu2vcp4iYuL3N2PBsDXXIElTNFHi0LjDBQSbWS4ndokEAEzikXZUcY3gealBcR51DBNQkf1tw==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.15.tgz", + "integrity": "sha512-0VUf7QR/Xv7x/YafATcI3WzSYgKbos8oF8IiBR3OFGhwpEB8XT4rUDcdT9fN11j7ZidTqJlot7DPpSIZzt3j2g==", "requires": { "ajv": "8.12.0", "ajv-formats": "2.1.1", @@ -22667,11 +22667,11 @@ } }, "@angular-devkit/schematics": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.14.tgz", - "integrity": "sha512-NS24F4fxOkakiRqg2RN0HGNr6hEThtHuKm9iLtT8Qv3ncq1F7iGkJzzAJgvJTsi7ZqBCDumLUs+Boor/x4bGyA==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.15.tgz", + "integrity": "sha512-MKOJg7d1dect8mzQ69QJQJrd0Bpb/1nt6V9VFCUlewngtVQ5S//iaxhpOJ9qB1SX9aGu1fTsiOaOWKUiNT+lOQ==", "requires": { - "@angular-devkit/core": "17.3.14", + "@angular-devkit/core": "17.3.15", "jsonc-parser": "3.2.1", "magic-string": "0.30.8", "ora": "5.4.1", @@ -22848,14 +22848,14 @@ } }, "@angular/cli": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.14.tgz", - "integrity": "sha512-PsNkofWubUfRZxsBkpRzflncCLfISxta2YerzhN/AlTa/L0Br2iY5XiXl6Kb1a5f/vg7pqT5qpleSu8O8KUiCw==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.15.tgz", + "integrity": "sha512-DYdvWsHphdQfN/XH1QMIOpivu7+n80Mj6x9S/wt1NbNFeLAAM4j60dicdr/U9bw/LjgN/qobLlak6JTioApT1Q==", "requires": { - "@angular-devkit/architect": "0.1703.14", - "@angular-devkit/core": "17.3.14", - "@angular-devkit/schematics": "17.3.14", - "@schematics/angular": "17.3.14", + "@angular-devkit/architect": "0.1703.15", + "@angular-devkit/core": "17.3.15", + "@angular-devkit/schematics": "17.3.15", + "@schematics/angular": "17.3.15", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -24836,9 +24836,9 @@ } }, "@ngtools/webpack": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.14.tgz", - "integrity": "sha512-ej9lv4UJPscVXNw9NNHwmzXWhDvSXKMggiMSLh35Ahk1UvMI0y8LGtvy7Egzvgk5P1hD9xw4sp05dKLN63SyVg==" + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.15.tgz", + "integrity": "sha512-6WVRr9vIndTLvrU9ygtvI/QpBO3/DazSrXi2TUZ27Tku5csLqHqGHSXrwd0a5zumKY8A0yK54vOx3vTqGj/YnQ==" }, "@ngx-formly/core": { "version": "6.3.12", @@ -25454,123 +25454,123 @@ "integrity": "sha512-ybBsUrIsu5geM8BtqnpM7ZA9D8uzSz+e1B4JR57NaCmasHKWap6AX5DT7NHIbp21opVet1qqoVSdsoLDqXeB2A==" }, "@rollup/rollup-android-arm-eabi": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", - "integrity": "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", + "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", "optional": true }, "@rollup/rollup-android-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz", - "integrity": "sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", + "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", "optional": true }, "@rollup/rollup-darwin-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz", - "integrity": "sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", + "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", "optional": true }, "@rollup/rollup-darwin-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz", - "integrity": "sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", + "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", "optional": true }, "@rollup/rollup-freebsd-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz", - "integrity": "sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", + "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", "optional": true }, "@rollup/rollup-freebsd-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz", - "integrity": "sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", + "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", "optional": true }, "@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz", - "integrity": "sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", + "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", "optional": true }, "@rollup/rollup-linux-arm-musleabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz", - "integrity": "sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", + "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", "optional": true }, "@rollup/rollup-linux-arm64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz", - "integrity": "sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", + "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", "optional": true }, "@rollup/rollup-linux-arm64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz", - "integrity": "sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", + "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", "optional": true }, "@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz", - "integrity": "sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", + "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", "optional": true }, "@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz", - "integrity": "sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", + "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", "optional": true }, "@rollup/rollup-linux-riscv64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz", - "integrity": "sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", + "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", "optional": true }, "@rollup/rollup-linux-riscv64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz", - "integrity": "sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", + "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", "optional": true }, "@rollup/rollup-linux-s390x-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz", - "integrity": "sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", + "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", "optional": true }, "@rollup/rollup-linux-x64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz", - "integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", + "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", "optional": true }, "@rollup/rollup-linux-x64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz", - "integrity": "sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", + "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", "optional": true }, "@rollup/rollup-win32-arm64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz", - "integrity": "sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", + "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", "optional": true }, "@rollup/rollup-win32-ia32-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz", - "integrity": "sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", + "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", "optional": true }, "@rollup/rollup-win32-x64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz", - "integrity": "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", + "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", "optional": true }, "@rtsao/scc": { @@ -25580,12 +25580,12 @@ "dev": true }, "@schematics/angular": { - "version": "17.3.14", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.14.tgz", - "integrity": "sha512-udffrlrXmfW52pMGMp2P9nM/LN42c3GuUqCiLSEJB0v/YqL962V+QOgrjTPrjzh5DiJv5oLdsE0dJH+oTediWg==", + "version": "17.3.15", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.15.tgz", + "integrity": "sha512-6IbvlKggDeZ7C//rVM9XbksWj9hFx56zZH3ndJ0vZ1FbrlFIxuWRjmB8bhHy5kk9xRobhzKFSVEHZexwdmOfWw==", "requires": { - "@angular-devkit/core": "17.3.14", - "@angular-devkit/schematics": "17.3.14", + "@angular-devkit/core": "17.3.15", + "@angular-devkit/schematics": "17.3.15", "jsonc-parser": "3.2.1" } }, @@ -35147,30 +35147,30 @@ } }, "rollup": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", - "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", + "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", "requires": { - "@rollup/rollup-android-arm-eabi": "4.38.0", - "@rollup/rollup-android-arm64": "4.38.0", - "@rollup/rollup-darwin-arm64": "4.38.0", - "@rollup/rollup-darwin-x64": "4.38.0", - "@rollup/rollup-freebsd-arm64": "4.38.0", - "@rollup/rollup-freebsd-x64": "4.38.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.38.0", - "@rollup/rollup-linux-arm-musleabihf": "4.38.0", - "@rollup/rollup-linux-arm64-gnu": "4.38.0", - "@rollup/rollup-linux-arm64-musl": "4.38.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.38.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-musl": "4.38.0", - "@rollup/rollup-linux-s390x-gnu": "4.38.0", - "@rollup/rollup-linux-x64-gnu": "4.38.0", - "@rollup/rollup-linux-x64-musl": "4.38.0", - "@rollup/rollup-win32-arm64-msvc": "4.38.0", - "@rollup/rollup-win32-ia32-msvc": "4.38.0", - "@rollup/rollup-win32-x64-msvc": "4.38.0", + "@rollup/rollup-android-arm-eabi": "4.39.0", + "@rollup/rollup-android-arm64": "4.39.0", + "@rollup/rollup-darwin-arm64": "4.39.0", + "@rollup/rollup-darwin-x64": "4.39.0", + "@rollup/rollup-freebsd-arm64": "4.39.0", + "@rollup/rollup-freebsd-x64": "4.39.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", + "@rollup/rollup-linux-arm-musleabihf": "4.39.0", + "@rollup/rollup-linux-arm64-gnu": "4.39.0", + "@rollup/rollup-linux-arm64-musl": "4.39.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-musl": "4.39.0", + "@rollup/rollup-linux-s390x-gnu": "4.39.0", + "@rollup/rollup-linux-x64-gnu": "4.39.0", + "@rollup/rollup-linux-x64-musl": "4.39.0", + "@rollup/rollup-win32-arm64-msvc": "4.39.0", + "@rollup/rollup-win32-ia32-msvc": "4.39.0", + "@rollup/rollup-win32-x64-msvc": "4.39.0", "@types/estree": "1.0.7", "fsevents": "~2.3.2" } @@ -37471,9 +37471,9 @@ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "vite": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", - "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", + "version": "5.4.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.16.tgz", + "integrity": "sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==", "requires": { "esbuild": "^0.21.3", "fsevents": "~2.3.3", From 0ff47c2656cfa43471352fe497b1d65ec33749b5 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Wed, 26 Mar 2025 16:45:02 +0100 Subject: [PATCH 031/260] [#57388] create table: export_settings --- app/models/export_setting.rb | 49 ++++++++++++++++++++ app/models/query.rb | 1 + db/migrate/20250326151553_export_settings.rb | 43 +++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 app/models/export_setting.rb create mode 100644 db/migrate/20250326151553_export_settings.rb diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb new file mode 100644 index 00000000000..ae18d027c9c --- /dev/null +++ b/app/models/export_setting.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +class ExportSetting < ApplicationRecord + belongs_to :query + + POSSIBLE_FORMATS = %w[csv xls pdf_table pdf_report pdf_gantt].freeze + + validates :query_id, presence: true + validates :format, presence: true, inclusion: { in: POSSIBLE_FORMATS } + validates :settings, presence: true + + validate :unique_format_per_query + + private + + def unique_format_per_query + if ExportSetting.exists?(query_id: query_id, format: format) && (new_record? || format_changed?) + errors.add(:format, "there already is an export setting for this query with this format") + end + end +end diff --git a/app/models/query.rb b/app/models/query.rb index e3572776494..0ede8c5c42b 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -43,6 +43,7 @@ class Query < ApplicationRecord has_many :ical_tokens, through: :ical_token_query_assignments, class_name: "Token::ICal" + has_many :export_settings, dependent: :destroy # no `dependent: :destroy` as the ical_tokens are destroyed in the following before_destroy callback # dependent: :destroy is not possible as this would only delete the ical_token_query_assignments before_destroy :destroy_ical_tokens diff --git a/db/migrate/20250326151553_export_settings.rb b/db/migrate/20250326151553_export_settings.rb new file mode 100644 index 00000000000..36f4b2e037b --- /dev/null +++ b/db/migrate/20250326151553_export_settings.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +class ExportSettings < ActiveRecord::Migration[8.0] + def change + create_table :export_settings do |t| + t.references :query, null: false, foreign_key: true + t.string :format, null: false + t.jsonb :settings, default: {}, null: false + + t.timestamps + end + + add_index :export_settings, %i[query_id format], unique: true + end +end From 97222c303d39bd5b33ae96d5fa9dcfa4cd2d92a0 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 10:09:37 +0100 Subject: [PATCH 032/260] [#57388] work with symbolized keys where possible --- app/models/export_setting.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb index ae18d027c9c..58bdbf12c60 100644 --- a/app/models/export_setting.rb +++ b/app/models/export_setting.rb @@ -39,6 +39,16 @@ class ExportSetting < ApplicationRecord validate :unique_format_per_query + def settings + # Read idiomatic symbol keys for JSONB column + super.symbolize_keys + end + + def settings=(value) + # Provide database with string keys + super(value.stringify_keys) + end + private def unique_format_per_query From ab2ae3ac4b8cff6de8d9be80775ea12e1bc66974 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 11:00:13 +0100 Subject: [PATCH 033/260] [#57388] CSV export reads from ExportSetting --- .../exports/base_export_settings_component.rb | 4 ++++ .../exports/column_selection_component.rb | 20 ++++++++++++++----- .../csv/export_settings_component.html.erb | 3 ++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/components/work_packages/exports/base_export_settings_component.rb b/app/components/work_packages/exports/base_export_settings_component.rb index 16fdbc293dd..ee154d96f01 100644 --- a/app/components/work_packages/exports/base_export_settings_component.rb +++ b/app/components/work_packages/exports/base_export_settings_component.rb @@ -42,6 +42,10 @@ module WorkPackages @query = query end + + def export_settings + @export_settings ||= query.export_settings.where(format: "csv").first_or_initialize + end end end end diff --git a/app/components/work_packages/exports/column_selection_component.rb b/app/components/work_packages/exports/column_selection_component.rb index 0ac1182a797..6f519162949 100644 --- a/app/components/work_packages/exports/column_selection_component.rb +++ b/app/components/work_packages/exports/column_selection_component.rb @@ -33,14 +33,16 @@ module WorkPackages class ColumnSelectionComponent < ApplicationComponent include WorkPackagesHelper - attr_reader :query, :id, :caption, :label + attr_reader :export_settings, :query, :id, :caption, :label - def initialize(query, id, caption, + def initialize(export_settings, id, caption, label = I18n.t(:"queries.configure_view.columns.input_label"), required: true) super() - @query = query + @export_settings = export_settings + # TODO: respond_to can be removed once all ExportSettingComponents have been migrated + @query = export_settings.respond_to?(:query) ? export_settings.query : export_settings @id = id @caption = caption @label = label @@ -59,8 +61,16 @@ module WorkPackages end def selected_columns - query - .columns + # TODO: respond_to can be removed once all ExportSettingComponents have been migrated + if export_settings.respond_to?(:settings) && export_settings.settings.key?(:columns) + saved_cols = export_settings.settings[:columns] + query + .columns + .select { |column| saved_cols.include?(column.name.to_s) } + else + query + .columns + end .map { |column| { id: column.name.to_s, name: column.caption } } end end diff --git a/app/components/work_packages/exports/csv/export_settings_component.html.erb b/app/components/work_packages/exports/csv/export_settings_component.html.erb index 387bbccad53..6e5f518d60b 100644 --- a/app/components/work_packages/exports/csv/export_settings_component.html.erb +++ b/app/components/work_packages/exports/csv/export_settings_component.html.erb @@ -1,7 +1,7 @@ <%= flex_layout do |container| %> <%= container.with_row do |_columns| %> <%= render WorkPackages::Exports::ColumnSelectionComponent.new( - query, + export_settings, "columns-select-export-csv", I18n.t("export.dialog.columns.input_caption_table") ) %> @@ -14,6 +14,7 @@ name: "show_descriptions", value: "true", unchecked_value: "false", + checked: export_settings.settings.fetch(:show_descriptions, false), label: I18n.t("export.dialog.xls.include_descriptions.label"), caption: I18n.t("export.dialog.xls.include_descriptions.caption"), visually_hide_label: false From 2c2ee12a99874a52203ab420fd2cde15ae17a3cf Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 14:50:38 +0100 Subject: [PATCH 034/260] [#57388] use ApplicationComponent pattern for the BaseExportSettingsComponent --- .../exports/base_export_settings_component.rb | 12 ++++++------ .../exports/csv/export_settings_component.rb | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/components/work_packages/exports/base_export_settings_component.rb b/app/components/work_packages/exports/base_export_settings_component.rb index ee154d96f01..4d71041296b 100644 --- a/app/components/work_packages/exports/base_export_settings_component.rb +++ b/app/components/work_packages/exports/base_export_settings_component.rb @@ -35,16 +35,16 @@ module WorkPackages include OpTurbo::Streamable include WorkPackagesHelper - attr_reader :query + def query + model + end - def initialize(query) - super - - @query = query + def format + raise NotImplementedError, "Must be overridden in subclass" end def export_settings - @export_settings ||= query.export_settings.where(format: "csv").first_or_initialize + @export_settings ||= query.export_settings.where(format:).first_or_initialize end end end diff --git a/app/components/work_packages/exports/csv/export_settings_component.rb b/app/components/work_packages/exports/csv/export_settings_component.rb index 1ca563e7dc1..0084440ea17 100644 --- a/app/components/work_packages/exports/csv/export_settings_component.rb +++ b/app/components/work_packages/exports/csv/export_settings_component.rb @@ -32,6 +32,9 @@ module WorkPackages module Exports module CSV class ExportSettingsComponent < BaseExportSettingsComponent + def format + "csv" + end end end end From ac92820994010de77839b95d0dfe14360e4173e4 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 14:50:48 +0100 Subject: [PATCH 035/260] [#57388] XLS export reads from ExportSetting --- .../exports/xls/export_settings_component.html.erb | 4 +++- .../work_packages/exports/xls/export_settings_component.rb | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/components/work_packages/exports/xls/export_settings_component.html.erb b/app/components/work_packages/exports/xls/export_settings_component.html.erb index 7077876b9c9..4faf6dbdd8e 100644 --- a/app/components/work_packages/exports/xls/export_settings_component.html.erb +++ b/app/components/work_packages/exports/xls/export_settings_component.html.erb @@ -1,7 +1,7 @@ <%= flex_layout do |container| %> <%= container.with_row do |_columns| %> <%= render WorkPackages::Exports::ColumnSelectionComponent.new( - query, + export_settings, "columns-select-export-xls", I18n.t("export.dialog.columns.input_caption_table") ) %> @@ -14,6 +14,7 @@ name: "show_relations", value: "true", unchecked_value: "false", + checked: export_settings.settings.fetch(:show_relations, false), label: I18n.t("export.dialog.xls.include_relations.label"), caption: I18n.t("export.dialog.xls.include_relations.caption"), visually_hide_label: false @@ -28,6 +29,7 @@ name: "show_descriptions", value: "true", unchecked_value: "false", + checked: export_settings.settings.fetch(:show_descriptions, false), label: I18n.t("export.dialog.xls.include_descriptions.label"), caption: I18n.t("export.dialog.xls.include_descriptions.caption"), visually_hide_label: false diff --git a/app/components/work_packages/exports/xls/export_settings_component.rb b/app/components/work_packages/exports/xls/export_settings_component.rb index eb42c268054..3bbdbde2300 100644 --- a/app/components/work_packages/exports/xls/export_settings_component.rb +++ b/app/components/work_packages/exports/xls/export_settings_component.rb @@ -32,6 +32,9 @@ module WorkPackages module Exports module XLS class ExportSettingsComponent < BaseExportSettingsComponent + def format + "xls" + end end end end From f23d7a311a6912b279e044f70023e9be30316edb Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 16:24:07 +0100 Subject: [PATCH 036/260] [#57388] PDF table export reads from ExportSetting --- .../exports/pdf/table/export_settings_component.html.erb | 2 +- .../exports/pdf/table/export_settings_component.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/components/work_packages/exports/pdf/table/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/table/export_settings_component.html.erb index 64eb44bb3e7..cc5f7543a9a 100644 --- a/app/components/work_packages/exports/pdf/table/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/table/export_settings_component.html.erb @@ -1,5 +1,5 @@ <%= render WorkPackages::Exports::ColumnSelectionComponent.new( - query, + export_settings, "columns-select-export-pdf-table", I18n.t("export.dialog.columns.input_caption_table") ) %> diff --git a/app/components/work_packages/exports/pdf/table/export_settings_component.rb b/app/components/work_packages/exports/pdf/table/export_settings_component.rb index b8020bebacd..40519785397 100644 --- a/app/components/work_packages/exports/pdf/table/export_settings_component.rb +++ b/app/components/work_packages/exports/pdf/table/export_settings_component.rb @@ -33,6 +33,9 @@ module WorkPackages module PDF module Table class ExportSettingsComponent < BaseExportSettingsComponent + def format + "pdf_table" + end end end end From 32a12efd4235e81f33cd2ccd23b2c8d60e16422b Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 27 Mar 2025 17:17:01 +0100 Subject: [PATCH 037/260] [#57388] PDF report export reads from ExportSetting --- .../report/export_settings_component.html.erb | 4 ++-- .../pdf/report/export_settings_component.rb | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb index bdd6ed4f8f5..f1b81ba086d 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb @@ -1,7 +1,7 @@ <%= flex_layout do |container| %> <% container.with_row do |_columns| %> <%= render WorkPackages::Exports::ColumnSelectionComponent.new( - query, + export_settings, "columns-select-export-pdf-report", I18n.t("export.dialog.columns.input_caption_report"), I18n.t("export.dialog.columns.input_label_report"), @@ -31,7 +31,7 @@ <%= render( Primer::Alpha::CheckBox.new( name: "show_images", - checked: true, + checked: export_settings.settings.fetch(:show_images, true), value: "true", unchecked_value: "false", label: I18n.t("export.dialog.pdf.include_images.label"), diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.rb b/app/components/work_packages/exports/pdf/report/export_settings_component.rb index b540b3fd3ce..b6c41b22495 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.rb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.rb @@ -35,13 +35,27 @@ module WorkPackages class ExportSettingsComponent < BaseExportSettingsComponent DESCRIPTION_CF = { id: "description", name: WorkPackage.human_attribute_name("description") }.freeze + def format + "pdf_report" + end + def available_long_text_fields [DESCRIPTION_CF] + WorkPackageCustomField.where(field_format: "text") .map { |cf| { id: cf.id, name: cf.name } } end def selected_long_text_fields - available_long_text_fields + default_long_text_fields = [DESCRIPTION_CF] + WorkPackageCustomField.where(field_format: "text") + + saved_long_text_fields = if export_settings.settings.key?(:long_text_fields) + saved = export_settings.settings.fetch(:long_text_fields, "").split + default_long_text_fields.select do |cf| + saved.include?(cf.respond_to?(:id) ? cf.id.to_s : cf[:id].to_s) + end + end + + (saved_long_text_fields || default_long_text_fields) + .map { |cf| { id: cf.id, name: cf.name } } end def protected_long_text_fields From 2007af06bfc7eb9389665e7639595436695c6ab3 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Fri, 28 Mar 2025 11:05:48 +0100 Subject: [PATCH 038/260] [#57388] PDF gantt export reads from ExportSetting --- .../gantt/export_settings_component.html.erb | 6 ++--- .../pdf/gantt/export_settings_component.rb | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/components/work_packages/exports/pdf/gantt/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/gantt/export_settings_component.html.erb index 5fbfbf17a05..eaea64b4869 100644 --- a/app/components/work_packages/exports/pdf/gantt/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/gantt/export_settings_component.html.erb @@ -8,9 +8,9 @@ size: :medium, input_width: :small )) do |component| - selected = entry[:options].find { |e| e[:default] }[:value] - entry[:options].each do |entry| - component.option(label: entry[:label], value: entry[:value], selected: selected == entry[:value]) + selected = find_selected_option(entry) + entry[:options].each do |e| + component.option(label: e[:label], value: e[:value], selected: selected[:value] == e[:value]) end end %> <% end %> diff --git a/app/components/work_packages/exports/pdf/gantt/export_settings_component.rb b/app/components/work_packages/exports/pdf/gantt/export_settings_component.rb index 3f1a2497d10..d409b9acf90 100644 --- a/app/components/work_packages/exports/pdf/gantt/export_settings_component.rb +++ b/app/components/work_packages/exports/pdf/gantt/export_settings_component.rb @@ -33,6 +33,10 @@ module WorkPackages module PDF module Gantt class ExportSettingsComponent < BaseExportSettingsComponent + def format + "pdf_gantt" + end + def gantt_selects [ { @@ -55,6 +59,26 @@ module WorkPackages ] end + # Reads the saved value from the export settings and returns the selected option. + # When there is no saved value, returns the default option. + # @param [Hash] entry one entry from `gantt_selects` + def find_selected_option(entry) + select_name = entry[:name].to_sym + if export_settings.settings.key?(select_name) + saved_value = export_settings.settings[select_name] + + entry[:options].find { |option| option[:value] == saved_value } || find_default_option(entry) + else + find_default_option(entry) + end + end + + # Returns the default option for a gantt_select entry. + # @param [Hash] entry one entry from `gantt_selects` + def find_default_option(entry) + entry[:options].find { |option| option[:default] } + end + def gantt_zoom_levels [ { label: t("export.dialog.pdf.gantt_zoom_levels.options.days"), value: "day", default: true }, From a036245c5580ba49ec665b063d228c971c795452 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Fri, 28 Mar 2025 15:32:33 +0100 Subject: [PATCH 039/260] [#57388] render (and send) checkbox within dialog The position is not correct yet. --- .../exports/modal_dialog_component.html.erb | 12 +++++++++++- .../work_packages/exports/modal_dialog_component.rb | 4 ++++ config/locales/en.yml | 2 ++ .../dynamic/work-packages/export/form.controller.ts | 9 +++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/components/work_packages/exports/modal_dialog_component.html.erb b/app/components/work_packages/exports/modal_dialog_component.html.erb index c27c7a4e1a7..410e27c5766 100644 --- a/app/components/work_packages/exports/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/modal_dialog_component.html.erb @@ -51,7 +51,17 @@ <% end %> <% end %> <% end %> - <% dialog.with_footer do %> + <% dialog.with_footer(show_divider: true) do %> + <%= render( + Primer::Alpha::CheckBox.new( + id: "#{EXPORT_FORM_ID}-save_export_settings", + name: "save_export_settings", + value: "true", + unchecked_value: "false", + checked: has_saved_export_settings?, + label: I18n.t("export.dialog.save_export_settings.label") + ) + ) %> <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( Primer::ButtonComponent.new( diff --git a/app/components/work_packages/exports/modal_dialog_component.rb b/app/components/work_packages/exports/modal_dialog_component.rb index 0707cb75ca6..6007cfc8739 100644 --- a/app/components/work_packages/exports/modal_dialog_component.rb +++ b/app/components/work_packages/exports/modal_dialog_component.rb @@ -56,6 +56,10 @@ module WorkPackages end end + def has_saved_export_settings? + @query.export_settings.any? + end + def export_formats_settings [ { id: "pdf", icon: :"op-pdf", diff --git a/config/locales/en.yml b/config/locales/en.yml index 04e686ff685..2b963fee3cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2142,6 +2142,8 @@ en: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/export/form.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/export/form.controller.ts index 4e1f9852f0d..617aa86e68c 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/export/form.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/export/form.controller.ts @@ -53,17 +53,26 @@ export default class FormController extends Controller { submitForm(evt:CustomEvent) { evt.preventDefault(); // Don't submit const formData = new FormData(this.element); + const columns = formData.get('columns'); if (!columns && this.mustHaveColumns(formData)) { return false; // Error is already displayed on the element } + + const saveExportSettingsCheckbox = document.getElementById('op-work-packages-export-dialog-form-save_export_settings') as HTMLInputElement; + if (saveExportSettingsCheckbox) { + formData.set('save_export_settings', saveExportSettingsCheckbox.checked ? 'true' : 'false'); + } + this.requestExport(this.generateExportURL(formData)) .then((job_id) => this.showJobModal(job_id)) .catch((error:HttpErrorResponse) => this.handleError(error)); + const dialog = document.getElementById(this.jobStatusDialogIdValue) as HTMLDialogElement; if (dialog) { dialog.close(); } + return true; } From 84027523923f6d86f2fb6acf7452874e0d077b78 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 10:33:29 +0200 Subject: [PATCH 040/260] [#57388] save export settings to database if checkbox is checked --- .../exports/base_export_settings_component.rb | 2 +- .../exports/column_selection_component.rb | 14 ++++++-------- .../csv/export_settings_component.html.erb | 2 +- .../report/export_settings_component.html.erb | 2 +- .../xls/export_settings_component.html.erb | 4 ++-- app/controllers/work_packages_controller.rb | 17 +++++++++++++++++ app/models/export_setting.rb | 6 ++++++ app/models/query.rb | 4 ++++ 8 files changed, 38 insertions(+), 13 deletions(-) diff --git a/app/components/work_packages/exports/base_export_settings_component.rb b/app/components/work_packages/exports/base_export_settings_component.rb index 4d71041296b..8f9be5894b4 100644 --- a/app/components/work_packages/exports/base_export_settings_component.rb +++ b/app/components/work_packages/exports/base_export_settings_component.rb @@ -44,7 +44,7 @@ module WorkPackages end def export_settings - @export_settings ||= query.export_settings.where(format:).first_or_initialize + @export_settings ||= query.export_settings_for(format) end end end diff --git a/app/components/work_packages/exports/column_selection_component.rb b/app/components/work_packages/exports/column_selection_component.rb index 6f519162949..3412854af4f 100644 --- a/app/components/work_packages/exports/column_selection_component.rb +++ b/app/components/work_packages/exports/column_selection_component.rb @@ -41,8 +41,7 @@ module WorkPackages super() @export_settings = export_settings - # TODO: respond_to can be removed once all ExportSettingComponents have been migrated - @query = export_settings.respond_to?(:query) ? export_settings.query : export_settings + @query = @export_settings.query @id = id @caption = caption @label = label @@ -61,17 +60,16 @@ module WorkPackages end def selected_columns - # TODO: respond_to can be removed once all ExportSettingComponents have been migrated - if export_settings.respond_to?(:settings) && export_settings.settings.key?(:columns) + if export_settings.settings.key?(:columns) + # FIXME: the order of the columns is not preserved saved_cols = export_settings.settings[:columns] - query - .columns - .select { |column| saved_cols.include?(column.name.to_s) } + available_columns + .select { |column| saved_cols.include?(column[:id]) } else query .columns + .map { |column| { id: column.name.to_s, name: column.caption } } end - .map { |column| { id: column.name.to_s, name: column.caption } } end end end diff --git a/app/components/work_packages/exports/csv/export_settings_component.html.erb b/app/components/work_packages/exports/csv/export_settings_component.html.erb index 6e5f518d60b..a3c90de0ed4 100644 --- a/app/components/work_packages/exports/csv/export_settings_component.html.erb +++ b/app/components/work_packages/exports/csv/export_settings_component.html.erb @@ -14,7 +14,7 @@ name: "show_descriptions", value: "true", unchecked_value: "false", - checked: export_settings.settings.fetch(:show_descriptions, false), + checked: export_settings.true?(:show_descriptions), label: I18n.t("export.dialog.xls.include_descriptions.label"), caption: I18n.t("export.dialog.xls.include_descriptions.caption"), visually_hide_label: false diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb index f1b81ba086d..4bd8abc39ae 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb @@ -31,7 +31,7 @@ <%= render( Primer::Alpha::CheckBox.new( name: "show_images", - checked: export_settings.settings.fetch(:show_images, true), + checked: export_settings.settings.fetch(:show_images, true).to_bool, value: "true", unchecked_value: "false", label: I18n.t("export.dialog.pdf.include_images.label"), diff --git a/app/components/work_packages/exports/xls/export_settings_component.html.erb b/app/components/work_packages/exports/xls/export_settings_component.html.erb index 4faf6dbdd8e..73b40c2bbe4 100644 --- a/app/components/work_packages/exports/xls/export_settings_component.html.erb +++ b/app/components/work_packages/exports/xls/export_settings_component.html.erb @@ -14,7 +14,7 @@ name: "show_relations", value: "true", unchecked_value: "false", - checked: export_settings.settings.fetch(:show_relations, false), + checked: export_settings.true?(:show_relations), label: I18n.t("export.dialog.xls.include_relations.label"), caption: I18n.t("export.dialog.xls.include_relations.caption"), visually_hide_label: false @@ -29,7 +29,7 @@ name: "show_descriptions", value: "true", unchecked_value: "false", - checked: export_settings.settings.fetch(:show_descriptions, false), + checked: export_settings.true?(:show_descriptions), label: I18n.t("export.dialog.xls.include_descriptions.label"), caption: I18n.t("export.dialog.xls.include_descriptions.caption"), visually_hide_label: false diff --git a/app/controllers/work_packages_controller.rb b/app/controllers/work_packages_controller.rb index 3cce30d327f..a8074869c3c 100644 --- a/app/controllers/work_packages_controller.rb +++ b/app/controllers/work_packages_controller.rb @@ -135,6 +135,8 @@ class WorkPackagesController < ApplicationController end def export_list(mime_type) + save_export_settings if params[:save_export_settings].to_bool + job_id = WorkPackages::Exports::ScheduleService .new(user: current_user) .call(query: @query, mime_type:, params:) @@ -169,6 +171,21 @@ class WorkPackagesController < ApplicationController private + def save_export_settings + relevant_keys = %i[format columns show_relations show_descriptions long_text_fields + show_images gantt_mode gantt_width paper_size] + + user_settings = params.slice(*relevant_keys) + + if user_settings[:format] == "pdf" + user_settings[:format] = "pdf_#{params[:pdf_export_type]}" + end + + export_settings = @query.export_settings_for(user_settings[:format]) + export_settings.settings = user_settings + export_settings.save! + end + def authorize_on_work_package deny_access(not_found: true) unless work_package end diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb index 58bdbf12c60..fb1d9eaf291 100644 --- a/app/models/export_setting.rb +++ b/app/models/export_setting.rb @@ -49,6 +49,12 @@ class ExportSetting < ApplicationRecord super(value.stringify_keys) end + # Some boolean settings are saved as string. Use this method to conveniently check if they are + # set to true. Assumes that all boolean settings default to false. + def true?(key) + settings.fetch(key, false).to_bool + end + private def unique_format_per_query diff --git a/app/models/query.rb b/app/models/query.rb index 0ede8c5c42b..1e3d99bdc64 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -421,6 +421,10 @@ class Query < ApplicationRecord subproject_filter end + def export_settings_for(format) + export_settings.where(format: format).first_or_initialize + end + private ## From e56d3c975ef49cf77368ee86018d238b333be4e8 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 11:04:15 +0200 Subject: [PATCH 041/260] [#57388] restore column order from last save --- .../work_packages/exports/column_selection_component.rb | 7 ++++--- .../exports/pdf/report/export_settings_component.html.erb | 2 +- app/models/export_setting.rb | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/components/work_packages/exports/column_selection_component.rb b/app/components/work_packages/exports/column_selection_component.rb index 3412854af4f..ea6b2db5582 100644 --- a/app/components/work_packages/exports/column_selection_component.rb +++ b/app/components/work_packages/exports/column_selection_component.rb @@ -61,10 +61,11 @@ module WorkPackages def selected_columns if export_settings.settings.key?(:columns) - # FIXME: the order of the columns is not preserved saved_cols = export_settings.settings[:columns] - available_columns - .select { |column| saved_cols.include?(column[:id]) } + # Restore the saved columns, retaining the saved order + saved_cols.filter_map do |col| + available_columns.find { |c| c[:id] == col } + end else query .columns diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb index 4bd8abc39ae..e56ce7c089e 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb @@ -31,7 +31,7 @@ <%= render( Primer::Alpha::CheckBox.new( name: "show_images", - checked: export_settings.settings.fetch(:show_images, true).to_bool, + checked: export_settings.settings.fetch(:show_images, true).to_s.to_bool, value: "true", unchecked_value: "false", label: I18n.t("export.dialog.pdf.include_images.label"), diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb index fb1d9eaf291..1eee4a68dc4 100644 --- a/app/models/export_setting.rb +++ b/app/models/export_setting.rb @@ -52,7 +52,7 @@ class ExportSetting < ApplicationRecord # Some boolean settings are saved as string. Use this method to conveniently check if they are # set to true. Assumes that all boolean settings default to false. def true?(key) - settings.fetch(key, false).to_bool + settings.fetch(key, false).to_s.to_bool end private From d3c753d2816277801a3bc1c83c9d9ecd1335033b Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 11:52:49 +0200 Subject: [PATCH 042/260] [#57388] move save checkbox to the left --- .../exports/modal_dialog_component.html.erb | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/components/work_packages/exports/modal_dialog_component.html.erb b/app/components/work_packages/exports/modal_dialog_component.html.erb index 410e27c5766..a2be3d1c279 100644 --- a/app/components/work_packages/exports/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/modal_dialog_component.html.erb @@ -52,16 +52,18 @@ <% end %> <% end %> <% dialog.with_footer(show_divider: true) do %> - <%= render( - Primer::Alpha::CheckBox.new( - id: "#{EXPORT_FORM_ID}-save_export_settings", - name: "save_export_settings", - value: "true", - unchecked_value: "false", - checked: has_saved_export_settings?, - label: I18n.t("export.dialog.save_export_settings.label") - ) - ) %> + <%= render(Primer::BaseComponent.new(tag: :span, mr: :auto)) do %> + <%= render( + Primer::Alpha::CheckBox.new( + id: "#{EXPORT_FORM_ID}-save_export_settings", + name: "save_export_settings", + value: "true", + unchecked_value: "false", + checked: has_saved_export_settings?, + label: I18n.t("export.dialog.save_export_settings.label") + ) + ) %> + <% end %> <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( Primer::ButtonComponent.new( From d12129c287f16defb2cfabcd0f603ce477f86034 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 14:02:06 +0200 Subject: [PATCH 043/260] [#57388] provide default value to `true?` --- .../exports/pdf/report/export_settings_component.html.erb | 2 +- app/models/export_setting.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb index e56ce7c089e..a81056fb77f 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.html.erb @@ -31,7 +31,7 @@ <%= render( Primer::Alpha::CheckBox.new( name: "show_images", - checked: export_settings.settings.fetch(:show_images, true).to_s.to_bool, + checked: export_settings.true?(:show_images, default: true), value: "true", unchecked_value: "false", label: I18n.t("export.dialog.pdf.include_images.label"), diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb index 1eee4a68dc4..3d04b7e9128 100644 --- a/app/models/export_setting.rb +++ b/app/models/export_setting.rb @@ -51,8 +51,8 @@ class ExportSetting < ApplicationRecord # Some boolean settings are saved as string. Use this method to conveniently check if they are # set to true. Assumes that all boolean settings default to false. - def true?(key) - settings.fetch(key, false).to_s.to_bool + def true?(key, default: false) + settings.fetch(key, default).to_s.to_bool end private From 015da098391b0340fda3b6897df0af87e2908b16 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 14:19:32 +0200 Subject: [PATCH 044/260] [#57388] fix: allow default text fields --- .../exports/pdf/report/export_settings_component.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.rb b/app/components/work_packages/exports/pdf/report/export_settings_component.rb index b6c41b22495..2d50676cb66 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.rb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.rb @@ -45,17 +45,18 @@ module WorkPackages end def selected_long_text_fields - default_long_text_fields = [DESCRIPTION_CF] + WorkPackageCustomField.where(field_format: "text") + default_long_text_fields = [DESCRIPTION_CF] + WorkPackageCustomField + .where(field_format: "text") + .map { |cf| { id: cf.id, name: cf.name } } saved_long_text_fields = if export_settings.settings.key?(:long_text_fields) saved = export_settings.settings.fetch(:long_text_fields, "").split default_long_text_fields.select do |cf| - saved.include?(cf.respond_to?(:id) ? cf.id.to_s : cf[:id].to_s) + saved.include?(cf[:id].to_s) end end - (saved_long_text_fields || default_long_text_fields) - .map { |cf| { id: cf.id, name: cf.name } } + saved_long_text_fields || default_long_text_fields end def protected_long_text_fields From 8be005793ea32dfeda91156d1e95f9b873607d72 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 14:21:30 +0200 Subject: [PATCH 045/260] [#57388] fix: don't break without 'save export settings' checkbox --- app/controllers/work_packages_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/work_packages_controller.rb b/app/controllers/work_packages_controller.rb index a8074869c3c..3e409c8ff65 100644 --- a/app/controllers/work_packages_controller.rb +++ b/app/controllers/work_packages_controller.rb @@ -135,7 +135,7 @@ class WorkPackagesController < ApplicationController end def export_list(mime_type) - save_export_settings if params[:save_export_settings].to_bool + save_export_settings if params[:save_export_settings]&.to_bool job_id = WorkPackages::Exports::ScheduleService .new(user: current_user) From b3854702109b0d069e26df4f2c1ef19c505a61f9 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 31 Mar 2025 14:26:25 +0200 Subject: [PATCH 046/260] [#57388] require a saved query for saving export settings --- .../exports/modal_dialog_component.html.erb | 24 ++++++++++--------- .../exports/modal_dialog_component.rb | 7 +++++- app/controllers/work_packages_controller.rb | 5 +++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/components/work_packages/exports/modal_dialog_component.html.erb b/app/components/work_packages/exports/modal_dialog_component.html.erb index a2be3d1c279..275ed1a9c85 100644 --- a/app/components/work_packages/exports/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/modal_dialog_component.html.erb @@ -52,17 +52,19 @@ <% end %> <% end %> <% dialog.with_footer(show_divider: true) do %> - <%= render(Primer::BaseComponent.new(tag: :span, mr: :auto)) do %> - <%= render( - Primer::Alpha::CheckBox.new( - id: "#{EXPORT_FORM_ID}-save_export_settings", - name: "save_export_settings", - value: "true", - unchecked_value: "false", - checked: has_saved_export_settings?, - label: I18n.t("export.dialog.save_export_settings.label") - ) - ) %> + <% if offer_to_save_export_settings? %> + <%= render(Primer::BaseComponent.new(tag: :span, mr: :auto)) do %> + <%= render( + Primer::Alpha::CheckBox.new( + id: "#{EXPORT_FORM_ID}-save_export_settings", + name: "save_export_settings", + value: "true", + unchecked_value: "false", + checked: saved_export_settings?, + label: I18n.t("export.dialog.save_export_settings.label") + ) + ) %> + <% end %> <% end %> <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( diff --git a/app/components/work_packages/exports/modal_dialog_component.rb b/app/components/work_packages/exports/modal_dialog_component.rb index 6007cfc8739..c586e85950e 100644 --- a/app/components/work_packages/exports/modal_dialog_component.rb +++ b/app/components/work_packages/exports/modal_dialog_component.rb @@ -56,7 +56,12 @@ module WorkPackages end end - def has_saved_export_settings? + # Users can save their export settings, but only for saved queries. + def offer_to_save_export_settings? + @query.persisted? + end + + def saved_export_settings? @query.export_settings.any? end diff --git a/app/controllers/work_packages_controller.rb b/app/controllers/work_packages_controller.rb index 3e409c8ff65..1e74f5fc110 100644 --- a/app/controllers/work_packages_controller.rb +++ b/app/controllers/work_packages_controller.rb @@ -172,6 +172,9 @@ class WorkPackagesController < ApplicationController private def save_export_settings + # Saving export settings is only allowed for saved queries + return false if @query.new_record? + relevant_keys = %i[format columns show_relations show_descriptions long_text_fields show_images gantt_mode gantt_width paper_size] @@ -183,7 +186,7 @@ class WorkPackagesController < ApplicationController export_settings = @query.export_settings_for(user_settings[:format]) export_settings.settings = user_settings - export_settings.save! + export_settings.save end def authorize_on_work_package From 216c0c64d89b497fbd5392b3bd48ba10fb001cb4 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Tue, 1 Apr 2025 08:57:25 +0200 Subject: [PATCH 047/260] [#57388] spec: query export settings --- .../query/query_export_settings_spec.rb | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 spec/models/query/query_export_settings_spec.rb diff --git a/spec/models/query/query_export_settings_spec.rb b/spec/models/query/query_export_settings_spec.rb new file mode 100644 index 00000000000..01a20f10afc --- /dev/null +++ b/spec/models/query/query_export_settings_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +RSpec.describe "query export settings" do # rubocop:disable RSpec/DescribeClass + let(:query) { create(:query) } + + describe "export_settings_for" do + it "creates a new export setting for the given format" do + setting = query.export_settings_for("csv") + + expect(setting).to be_a_new_record + end + + context "with an existing export setting" do + let!(:export_setting) { ExportSetting.create(query_id: query.id, settings: { some_key: :some_value }, format: "xls") } + + it "is returned" do + setting = query.export_settings_for("xls") + + expect(setting).to be_persisted + expect(setting.settings).to eq({ some_key: "some_value" }) + end + + it "is not returned for a different format" do + setting = query.export_settings_for("pdf_report") + + expect(setting).to be_a_new_record + end + end + end +end From a46096232f7621c84aa54c625422e97840674375 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Tue, 1 Apr 2025 16:28:53 +0200 Subject: [PATCH 048/260] [#57388] feature-spec: query export settings --- .../csv/export_settings_component.html.erb | 5 +- .../exports/modal_dialog_component.html.erb | 5 +- .../exports/modal_dialog_component.rb | 2 +- spec/features/work_packages/export_spec.rb | 87 ++++++++++++++++++- 4 files changed, 94 insertions(+), 5 deletions(-) diff --git a/app/components/work_packages/exports/csv/export_settings_component.html.erb b/app/components/work_packages/exports/csv/export_settings_component.html.erb index a3c90de0ed4..0bb18b9f16b 100644 --- a/app/components/work_packages/exports/csv/export_settings_component.html.erb +++ b/app/components/work_packages/exports/csv/export_settings_component.html.erb @@ -17,7 +17,10 @@ checked: export_settings.true?(:show_descriptions), label: I18n.t("export.dialog.xls.include_descriptions.label"), caption: I18n.t("export.dialog.xls.include_descriptions.caption"), - visually_hide_label: false + visually_hide_label: false, + data: { + test_selector: "show-descriptions-csv" + } ) ) %> <% end %> diff --git a/app/components/work_packages/exports/modal_dialog_component.html.erb b/app/components/work_packages/exports/modal_dialog_component.html.erb index 275ed1a9c85..e4ad7a825e1 100644 --- a/app/components/work_packages/exports/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/modal_dialog_component.html.erb @@ -61,7 +61,10 @@ value: "true", unchecked_value: "false", checked: saved_export_settings?, - label: I18n.t("export.dialog.save_export_settings.label") + label: I18n.t("export.dialog.save_export_settings.label"), + data: { + test_selector: "#{EXPORT_FORM_ID}-save-export-settings" + } ) ) %> <% end %> diff --git a/app/components/work_packages/exports/modal_dialog_component.rb b/app/components/work_packages/exports/modal_dialog_component.rb index c586e85950e..4076050fa1f 100644 --- a/app/components/work_packages/exports/modal_dialog_component.rb +++ b/app/components/work_packages/exports/modal_dialog_component.rb @@ -62,7 +62,7 @@ module WorkPackages end def saved_export_settings? - @query.export_settings.any? + @query.export_settings.any?(&:persisted?) end def export_formats_settings diff --git a/spec/features/work_packages/export_spec.rb b/spec/features/work_packages/export_spec.rb index dbbd962b71e..19a8cef569d 100644 --- a/spec/features/work_packages/export_spec.rb +++ b/spec/features/work_packages/export_spec.rb @@ -102,10 +102,19 @@ RSpec.describe "work package export", :js, :selenium do end end - def open_export_dialog! - wp_table.visit_query query + def open_export_dialog!(query_target = :query) + case query_target + when :query + wp_table.visit_query query + when :default + wp_table.visit_with_params "" + else + raise ArgumentError, "query_target must be :query or :default" + end + work_packages_page.ensure_loaded settings_menu.open_and_choose I18n.t("js.toolbar.settings.export") + expect(page).to have_css("#op-work-packages-export-dialog", wait: 5) click_on export_type sleep 0.1 end @@ -115,6 +124,18 @@ RSpec.describe "work package export", :js, :selenium do expect(page).to have_no_button(I18n.t("export.dialog.submit"), wait: 1) end + def close_export_dialog! + expect(page).to have_button(I18n.t("js.button_close")) + click_on I18n.t("js.button_close") + expect(page).to have_no_button(I18n.t("js.button_close")) + end + + def export_and_reopen_dialog!(query_target = :query) + export! + close_export_dialog! + open_export_dialog!(query_target) + end + context "with Query options" do let(:export_type) { I18n.t("export.dialog.format.options.pdf.label") } let(:expected_mime_type) { :pdf } @@ -182,6 +203,7 @@ RSpec.describe "work package export", :js, :selenium do let(:expected_params) { default_expected_params } before do + query.export_settings.delete_all open_export_dialog! end @@ -204,6 +226,67 @@ RSpec.describe "work package export", :js, :selenium do end end + context "with a saved query" do + let!(:query) { create(:query, name: "saved settings query", user: current_user, project:) } + let(:export_type) { I18n.t("export.dialog.format.options.csv.label") } + let(:expected_mime_type) { :csv } + let(:expected_params) { default_expected_params.merge({ title: "saved settings query", show_descriptions: "true" }) } + + before do + open_export_dialog! + end + + it "saves the export settings" do + # Ensure that the option to save export settings is there and both checkboxes are unchecked + expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).not_to be_checked + expect(page.find_test_selector("show-descriptions-csv")).not_to be_checked + + # Save settings and include descriptions + check I18n.t("export.dialog.save_export_settings.label") + check I18n.t("export.dialog.xls.include_descriptions.label") + + export_and_reopen_dialog! + # Last settings are remembered + expect(page.find_test_selector("show-descriptions-csv")).to be_checked + expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).to be_checked + + # Uncheck both checkboxes again (do not include descriptions, do not save changes) + uncheck I18n.t("export.dialog.save_export_settings.label") + uncheck I18n.t("export.dialog.xls.include_descriptions.label") + expected_params[:show_descriptions] = "false" # adjust expectation + + export_and_reopen_dialog! + + # Last saved settings are restored + expect(page.find_test_selector("show-descriptions-csv")).to be_checked + expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).to be_checked + end + end + + context "with an unsaved query" do + let(:export_type) { I18n.t("export.dialog.format.options.csv.label") } + let(:expected_mime_type) { :csv } + let(:expected_params) { default_expected_params.merge({ title: "All open", show_descriptions: "true" }) } + + before do + open_export_dialog!(:default) + end + + it "does not offer to save export settings" do + # There is no save option + expect(page).not_to have_test_selector("op-work-packages-export-dialog-form-save-export-settings") + # show_descriptions is unchecked by default + expect(page.find_test_selector("show-descriptions-csv")).not_to be_checked + + # Check show_descriptions and export, then reopen dialog + check I18n.t("export.dialog.xls.include_descriptions.label") + export_and_reopen_dialog!(:default) + + # show_descriptions is still unchecked + expect(page.find_test_selector("show-descriptions-csv")).not_to be_checked + end + end + context "with XLS export" do let(:export_type) { I18n.t("export.dialog.format.options.xls.label") } let(:expected_mime_type) { :xls } From 64c67641918d522ecb7f1ebd325e9364ed56c036 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Tue, 1 Apr 2025 20:09:31 +0200 Subject: [PATCH 049/260] [#57388] reduce code complexity --- .../exports/column_selection_component.rb | 24 +++++++++++-------- .../pdf/report/export_settings_component.rb | 4 +--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/components/work_packages/exports/column_selection_component.rb b/app/components/work_packages/exports/column_selection_component.rb index ea6b2db5582..accc783a382 100644 --- a/app/components/work_packages/exports/column_selection_component.rb +++ b/app/components/work_packages/exports/column_selection_component.rb @@ -60,16 +60,20 @@ module WorkPackages end def selected_columns - if export_settings.settings.key?(:columns) - saved_cols = export_settings.settings[:columns] - # Restore the saved columns, retaining the saved order - saved_cols.filter_map do |col| - available_columns.find { |c| c[:id] == col } - end - else - query - .columns - .map { |column| { id: column.name.to_s, name: column.caption } } + return columns_from_saved_export_settings if export_settings.settings.key?(:columns) + + query + .columns + .map { |column| { id: column.name.to_s, name: column.caption } } + end + + private + + def columns_from_saved_export_settings + saved_cols = export_settings.settings[:columns] + # Restore the saved columns, retaining the saved order + saved_cols.filter_map do |col| + available_columns.find { |c| c[:id] == col } end end end diff --git a/app/components/work_packages/exports/pdf/report/export_settings_component.rb b/app/components/work_packages/exports/pdf/report/export_settings_component.rb index 2d50676cb66..46b2a7bf97c 100644 --- a/app/components/work_packages/exports/pdf/report/export_settings_component.rb +++ b/app/components/work_packages/exports/pdf/report/export_settings_component.rb @@ -45,9 +45,7 @@ module WorkPackages end def selected_long_text_fields - default_long_text_fields = [DESCRIPTION_CF] + WorkPackageCustomField - .where(field_format: "text") - .map { |cf| { id: cf.id, name: cf.name } } + default_long_text_fields = available_long_text_fields saved_long_text_fields = if export_settings.settings.key?(:long_text_fields) saved = export_settings.settings.fetch(:long_text_fields, "").split From 86c916921f5d9ace44af571e9435305a7be3a89d Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Wed, 2 Apr 2025 10:05:11 +0200 Subject: [PATCH 050/260] [#57388] feature-spec: also expect the correct columns --- spec/features/work_packages/export_spec.rb | 38 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/spec/features/work_packages/export_spec.rb b/spec/features/work_packages/export_spec.rb index 19a8cef569d..6057e1ef758 100644 --- a/spec/features/work_packages/export_spec.rb +++ b/spec/features/work_packages/export_spec.rb @@ -136,6 +136,14 @@ RSpec.describe "work package export", :js, :selenium do open_export_dialog!(query_target) end + def expect_selected_columns(columns = %w[]) + selected_columns = page.within(".op-draggable-autocomplete--selected") do + all(".op-draggable-autocomplete--item-text").map(&:text) + end + + expect(selected_columns).to eq(columns) + end + context "with Query options" do let(:export_type) { I18n.t("export.dialog.format.options.pdf.label") } let(:expected_mime_type) { :pdf } @@ -230,7 +238,19 @@ RSpec.describe "work package export", :js, :selenium do let!(:query) { create(:query, name: "saved settings query", user: current_user, project:) } let(:export_type) { I18n.t("export.dialog.format.options.csv.label") } let(:expected_mime_type) { :csv } - let(:expected_params) { default_expected_params.merge({ title: "saved settings query", show_descriptions: "true" }) } + let(:expected_columns) { %w[ID Subject Type Status Assignee Priority] } + let(:expected_params) do + default_expected_params.merge( + { + title: "saved settings query", + show_descriptions: "true", + columns: %w[subject type status assigned_to priority] + } + ) + end + let(:query_columns) do + query.displayable_columns.filter_map { |c| c.name.to_s if expected_columns.include?(c.name.to_s) } + end before do open_export_dialog! @@ -240,26 +260,38 @@ RSpec.describe "work package export", :js, :selenium do # Ensure that the option to save export settings is there and both checkboxes are unchecked expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).not_to be_checked expect(page.find_test_selector("show-descriptions-csv")).not_to be_checked + expect_selected_columns(expected_columns) # Save settings and include descriptions check I18n.t("export.dialog.save_export_settings.label") check I18n.t("export.dialog.xls.include_descriptions.label") + # Remove the first column + page.within(".op-draggable-autocomplete--selected") do + first(".op-draggable-autocomplete--remove-item").click + end export_and_reopen_dialog! # Last settings are remembered expect(page.find_test_selector("show-descriptions-csv")).to be_checked expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).to be_checked + expect_selected_columns(expected_columns - ["ID"]) # Uncheck both checkboxes again (do not include descriptions, do not save changes) uncheck I18n.t("export.dialog.save_export_settings.label") uncheck I18n.t("export.dialog.xls.include_descriptions.label") - expected_params[:show_descriptions] = "false" # adjust expectation - + # Remove the last column + page.within(".op-draggable-autocomplete--selected") do + all(".op-draggable-autocomplete--remove-item").last.click + end + # Adjust expectation and export + expected_params[:show_descriptions] = "false" + expected_params[:columns].pop export_and_reopen_dialog! # Last saved settings are restored expect(page.find_test_selector("show-descriptions-csv")).to be_checked expect(page.find_test_selector("op-work-packages-export-dialog-form-save-export-settings")).to be_checked + expect_selected_columns(expected_columns - ["ID"]) end end From 549eb2f2c05093976a03f92f99e104cf044f7c80 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Wed, 2 Apr 2025 10:51:59 +0200 Subject: [PATCH 051/260] [#57388] feature-spec: expect the correct long text fields --- spec/features/work_packages/export_spec.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/spec/features/work_packages/export_spec.rb b/spec/features/work_packages/export_spec.rb index 6057e1ef758..010db9763a1 100644 --- a/spec/features/work_packages/export_spec.rb +++ b/spec/features/work_packages/export_spec.rb @@ -414,12 +414,25 @@ RSpec.describe "work package export", :js, :selenium do end context "with long text fields selection" do - let(:expected_params) { default_params_report.merge({ long_text_fields: "description 43" }) } + let(:expected_params) { default_params_report.merge({ long_text_fields: "description #{cf_text_b.id}" }) } it "exports a pdf report with all remaining custom fields" do - find("span.op-draggable-autocomplete--item-text", text: "Long text custom field") - .sibling(".op-draggable-autocomplete--remove-item").click - export! + # Remove one custom field + page.within(".op-angular-component[data-id='\"ltf-select-export-pdf-report\"']") do + find(".op-draggable-autocomplete--item-text", text: "Long text custom field") + .sibling(".op-draggable-autocomplete--remove-item").click + end + + # Save export settings, export and reopen dialog + check I18n.t("export.dialog.save_export_settings.label") + export_and_reopen_dialog! + choose export_sub_type + + selected_long_fields = page.within(".op-angular-component[data-id='\"ltf-select-export-pdf-report\"']") do + all(".op-draggable-autocomplete--item-text").map(&:text) + end + # The removed field has been saved + expect(selected_long_fields).to contain_exactly("Description", cf_text_b.name) end end From ddf27024a5f61f47158923f7ffd29a305aef7c62 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Wed, 2 Apr 2025 13:05:26 +0200 Subject: [PATCH 052/260] [#57388] unit tests for export_settings --- app/models/export_setting.rb | 4 +- app/models/query.rb | 2 +- .../export_settings/export_setting_spec.rb | 147 ++++++++++++++++++ 3 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 spec/models/export_settings/export_setting_spec.rb diff --git a/app/models/export_setting.rb b/app/models/export_setting.rb index 3d04b7e9128..9a1a831d8be 100644 --- a/app/models/export_setting.rb +++ b/app/models/export_setting.rb @@ -50,9 +50,9 @@ class ExportSetting < ApplicationRecord end # Some boolean settings are saved as string. Use this method to conveniently check if they are - # set to true. Assumes that all boolean settings default to false. + # set to true. def true?(key, default: false) - settings.fetch(key, default).to_s.to_bool + %w[true 1].include?(settings.fetch(key, default).to_s) end private diff --git a/app/models/query.rb b/app/models/query.rb index 1e3d99bdc64..4049933269b 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -422,7 +422,7 @@ class Query < ApplicationRecord end def export_settings_for(format) - export_settings.where(format: format).first_or_initialize + export_settings.where(format:).first_or_initialize end private diff --git a/spec/models/export_settings/export_setting_spec.rb b/spec/models/export_settings/export_setting_spec.rb new file mode 100644 index 00000000000..504767d11a5 --- /dev/null +++ b/spec/models/export_settings/export_setting_spec.rb @@ -0,0 +1,147 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +RSpec.shared_examples "a successful creation" do |format| + it "creates successfully with format #{format}" do + expect(described_class.create(query:, settings:, format:)).to be_persisted + end +end + +RSpec.describe ExportSetting do + let(:query) { create(:query, name: "some query") } + let(:format) { "csv" } + let(:settings) { { "columns" => %w[id subject], "show_descriptions" => "true" } } + + it "returns its settings with symbol keys" do + export_settings = described_class.create(query:, settings:, format:) + + expect(export_settings.settings).to eq({ columns: %w[id subject], show_descriptions: "true" }) + + export_settings.settings = { "foo" => "bar" } + expect(export_settings.settings).to eq({ foo: "bar" }) + end + + describe "creating" do + formats = %w[csv xls pdf_report pdf_table pdf_gantt] + + formats.each do |format| + include_examples "a successful creation", format + end + + it "fails with an invalid format" do + expect(described_class.create(query:, settings:, format: "invalid_format")).not_to be_persisted + end + + it "fails without format" do + expect(described_class.create(query:, settings:)).not_to be_persisted + end + + it "fails without settings" do + expect(described_class.create(query:, format:)).not_to be_persisted + end + + it "fails without query" do + expect(described_class.create(settings:, format:)).not_to be_persisted + end + + it "fails when there already is this query/format combination" do + expect(described_class.create(query:, settings:, format: "csv")).to be_persisted + + duplicate = described_class.create(query:, settings:, format: "csv") + expect(duplicate).not_to be_persisted + expect(duplicate.errors[:format]).to include("there already is an export setting for this query with this format") + + new_query = create(:query, name: "another query") + expect(described_class.create(query: new_query, settings:, format: "csv")).to be_persisted + end + end + + describe "#true?" do + let(:settings) do + { + string_true: "true", + real_true: true, + string_one_true: "1", + one_true: 1, + string_false: "false", + real_false: false, + string_zero_false: "0", + zero_false: 0, + truthy_string: "any string is truthy", + truthy_array: [] + } + end + let(:instance) { described_class.new(query:, settings:, format:) } + + it "returns true for a value that looks like it should be true" do + true_keys = %i[ + string_true + real_true + string_one_true + one_true + ] + + true_keys.each do |key| + expect(instance.true?(key)).to be true + end + end + + it "returns false for a value that looks like it should be false" do + false_keys = %i[ + string_false + real_false + string_zero_false + zero_false + ] + + false_keys.each do |key| + expect(instance.true?(key)).to be false + end + end + + it "returns false for values that are truthy in Ruby" do + truthy_keys = %i[truthy_string truthy_array] + + truthy_keys.each do |key| + expect(instance.true?(key)).to be false + end + end + + it "returns false for keys that do not exist" do + expect(instance.true?(:non_existent_key)).to be false + end + + it "returns a default value for non existent keys" do + expect(instance.true?(:non_existent_key, default: true)).to be true + end + end +end From c330e592f5e1f8e62e99d90a7de52df3756c0f05 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Thu, 3 Apr 2025 10:46:49 +0200 Subject: [PATCH 053/260] [#57388] ensure a saved query is considered for the global wp list --- .../work_packages/exports/modal_dialog_component.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/work_packages/exports/modal_dialog_component.rb b/app/components/work_packages/exports/modal_dialog_component.rb index 4076050fa1f..492553704b8 100644 --- a/app/components/work_packages/exports/modal_dialog_component.rb +++ b/app/components/work_packages/exports/modal_dialog_component.rb @@ -48,11 +48,11 @@ module WorkPackages def export_format_url(format) if @project.nil? - index_work_packages_path(format:) - elsif @query.id.present? - project_work_packages_path(project, query_id: @query.id, format:) + # Global work package list. The query_id might be nil for unsaved queries. + index_work_packages_path(format:, query_id: @query.id) else - project_work_packages_path(project, format:) + # Project work package list. The query_id might be nil for unsaved queries. + project_work_packages_path(project, query_id: @query.id, format:) end end From 3705751c3d7d0ef848b541f50e94ac25a3f3391c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 3 Apr 2025 13:32:34 +0200 Subject: [PATCH 054/260] Bump ng-select to 14.2 --- frontend/package-lock.json | 39 +++++++++++++++++++------------------- frontend/package.json | 4 ++-- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7064785ec56..e579696afc4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -43,8 +43,8 @@ "@hotwired/turbo": "^8.0.10", "@hotwired/turbo-rails": "^8.0.10", "@kolkov/ngx-gallery": "^2.0.1", - "@ng-select/ng-option-highlight": "13.2.0", - "@ng-select/ng-select": "^13.2.0", + "@ng-select/ng-option-highlight": "14.2.6", + "@ng-select/ng-select": "^14.2.6", "@ngneat/content-loader": "^7.0.0", "@ngx-formly/core": "^6.1.4", "@openproject/octicons-angular": "^19.23.0", @@ -3918,22 +3918,23 @@ "integrity": "sha512-3uWLVXHY3jQxsXCr/UCNPSc2BG0hNUljhmOBt9l+lNFDp7zHgm0cK2Tw4kj2XfkJy4TgwZTBGwRDQgWEbLbdTA==" }, "node_modules/@ng-select/ng-option-highlight": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/@ng-select/ng-option-highlight/-/ng-option-highlight-13.2.0.tgz", - "integrity": "sha512-B10PiJbCur48R5OTm5hgToJ0c+xAyN4EkklUFd1TfVT+GkxSePQW312gdE3NOQK0ddFdi9xohGaGx5nJRIalWg==", + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@ng-select/ng-option-highlight/-/ng-option-highlight-14.2.6.tgz", + "integrity": "sha512-/BZNItpaMduFcQyAMLWDaWM7D/doB37j7JYOnrVfNBK7JqkKLYqRuesdU3Z+eBs1x3+FhiQGudi7nhEo68MFaw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^18.0.0", - "@angular/core": "^18.0.0" + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0" } }, "node_modules/@ng-select/ng-select": { - "version": "13.9.1", - "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-13.9.1.tgz", - "integrity": "sha512-+DzQkQp8coGWZREflJM/qx7BXipV6HEVpZCXoa6fJJRHJfmUMsxa5uV6kUVmClUE98Rkffk9CPHt6kZcj8PuqQ==", + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-14.2.6.tgz", + "integrity": "sha512-7JZ+jdsZLwK3GpPDdL0tmnX/yFeHcOLlH+b77UFUTLrmAXBQFHkWC7tkvBhV6I7ocwkygGeHXfKmTHZhk/jQOQ==", + "license": "MIT", "dependencies": { "tslib": "^2.3.1" }, @@ -3942,9 +3943,9 @@ "npm": ">= 8" }, "peerDependencies": { - "@angular/common": "^18.0.0", - "@angular/core": "^18.0.0", - "@angular/forms": "^18.0.0" + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0" } }, "node_modules/@ngneat/content-loader": { @@ -24812,17 +24813,17 @@ "integrity": "sha512-3uWLVXHY3jQxsXCr/UCNPSc2BG0hNUljhmOBt9l+lNFDp7zHgm0cK2Tw4kj2XfkJy4TgwZTBGwRDQgWEbLbdTA==" }, "@ng-select/ng-option-highlight": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/@ng-select/ng-option-highlight/-/ng-option-highlight-13.2.0.tgz", - "integrity": "sha512-B10PiJbCur48R5OTm5hgToJ0c+xAyN4EkklUFd1TfVT+GkxSePQW312gdE3NOQK0ddFdi9xohGaGx5nJRIalWg==", + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@ng-select/ng-option-highlight/-/ng-option-highlight-14.2.6.tgz", + "integrity": "sha512-/BZNItpaMduFcQyAMLWDaWM7D/doB37j7JYOnrVfNBK7JqkKLYqRuesdU3Z+eBs1x3+FhiQGudi7nhEo68MFaw==", "requires": { "tslib": "^2.3.0" } }, "@ng-select/ng-select": { - "version": "13.9.1", - "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-13.9.1.tgz", - "integrity": "sha512-+DzQkQp8coGWZREflJM/qx7BXipV6HEVpZCXoa6fJJRHJfmUMsxa5uV6kUVmClUE98Rkffk9CPHt6kZcj8PuqQ==", + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-14.2.6.tgz", + "integrity": "sha512-7JZ+jdsZLwK3GpPDdL0tmnX/yFeHcOLlH+b77UFUTLrmAXBQFHkWC7tkvBhV6I7ocwkygGeHXfKmTHZhk/jQOQ==", "requires": { "tslib": "^2.3.1" } diff --git a/frontend/package.json b/frontend/package.json index 06c06b87096..d81f22b21e0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -95,8 +95,8 @@ "@hotwired/turbo": "^8.0.10", "@hotwired/turbo-rails": "^8.0.10", "@kolkov/ngx-gallery": "^2.0.1", - "@ng-select/ng-option-highlight": "13.2.0", - "@ng-select/ng-select": "^13.2.0", + "@ng-select/ng-option-highlight": "14.2.6", + "@ng-select/ng-select": "^14.2.6", "@ngneat/content-loader": "^7.0.0", "@ngx-formly/core": "^6.1.4", "@openproject/octicons-angular": "^19.23.0", From 1f68d176c3d6efeb611d96b7fdd2ccc60ef25e91 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:53:31 +0200 Subject: [PATCH 055/260] Update to the docs --- .../docs/components/border-box-table.md.erb | 8 +++-- lookbook/docs/components/border-box.md.erb | 31 +++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/lookbook/docs/components/border-box-table.md.erb b/lookbook/docs/components/border-box-table.md.erb index 72a53164520..16ed52ee1af 100644 --- a/lookbook/docs/components/border-box-table.md.erb +++ b/lookbook/docs/components/border-box-table.md.erb @@ -4,19 +4,21 @@ ## Anatomy -**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility short cuts). If you want or need that, please use the [TableComponent docs](./tables)) +**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility short cuts). + +If you want or need that, please use the [TableComponent docs](./tables)) ## Best practices **Do** -- Use a BorderBoxTable if you have a *few* entries of unsorted data, that does not require pagination +- Use a BorderBoxTable if you have a *few* entries of unsorted data that does not require pagination - Use up to two actions using the `:secondary` scheme of `Primer::Beta::Button` and `Primer::Beta::IconButton`. - OR: Use an action menu with `:invisible` scheme **Don't** -- Use the BorderBoxTable for a lot of items that require sorting or pagination +- Don't use the BorderBoxTable when the table consists of a large number of items that require sorting or pagination ## Technical notes diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index eff5dc17faa..ebac0d79411 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -1,15 +1,11 @@ The Border Box element is used to display structured items in a list, each with a set of actions. It is used for example: -- to display a list of meetings -- to display individual meeting agenda items in a meeting -- to display the a list of project attributes -- to display a list of configured OAuth applications ## Anatomy The Border Box element is made up of -1. The **header** acts as a container for the items below it. It's often to distinguish between sections. It is optional. +1. The **header**, which acts as a container for the items below and helps distinguish between sections. It is optional. 2. Individual **items** below can vary in what information they show. If a page uses a Border Box with a header, all sections must use headers. @@ -19,18 +15,33 @@ If a page uses a Border Box with a header, all sections must use headers. Note for Parimal: You can chose between a collapsibleHeader and a free-chosen Header. The collapsible Header consists of Title, counter(optional) and description(optional). -- **Collapsible header**: A collapsible header has an arrow next to the title and allows collapsing and expanding the contents below. When collapsed, the bottom border is slightly thicker to indicate something is hidden. - - **Header description**: When collapsed, the optional header description is hidden. - - **Header counter**: The counter can display the number of items that that particular section contains. +The header can either be static or collapsible. -- **More button**: A more button can have contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). +The collapsibleHeader brings additional functionality: + +- an **arrow indicator** next to the title indicates if the section is collapsed or expanded. +- a **header description** (optional) to give additional context to the content of that section. Hidden when collapsed. +- a **counter** (optional) displays the number of items that that particular section contains. + +When collapsed, the bottom border is slightly thicker to indicate something is hidden. + +Both the collapsible header and static heads can accept additional actions. For example, a **more button** can offer additional contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). + +## Uses + +- to display a list of meetings +- to display individual meeting agenda items in a meeting +- to display the a list of project attributes +- to display a list of configured OAuth applications + +If the content needs to be more structured (with columns and column headers), please use the [Border Box Table](border-box-table) component instead. ## Best practices **Do** - Use sections (with headers) to better organise content if they have logical categories (eg. Open and Planned meetings). -- - **Draggable**: Both header and items can have drag handles. Individual items can be dragged up and down and into other sections. The sections themselves can also be moved up and down. +- Do make the header and items draggable if the user should be able to drag individual items up and down and into other sections. The sections themselves can also be dragged up and down to change order. **Don't** From 7a0a04da31f7c3736c10acd3b945e593a80347f2 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:56:45 +0200 Subject: [PATCH 056/260] Update to uses --- lookbook/docs/components/border-box-table.md.erb | 10 ++++++++++ lookbook/docs/components/border-box.md.erb | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lookbook/docs/components/border-box-table.md.erb b/lookbook/docs/components/border-box-table.md.erb index 16ed52ee1af..349eb098882 100644 --- a/lookbook/docs/components/border-box-table.md.erb +++ b/lookbook/docs/components/border-box-table.md.erb @@ -20,6 +20,16 @@ If you want or need that, please use the [TableComponent docs](./tables)) - Don't use the BorderBoxTable when the table consists of a large number of items that require sorting or pagination +## Uses + +- to display a list of meetings +- to display a list of configured SAML providers +- to display a list of configured OpenID providers +- to display a list of configured SCIM clients + +If the content does not need a table structure with column headers and grids, please use the simpler [Border Box](border-box-table) component instead. + + ## Technical notes Since the `BorderBoxTable` is a sub-class of our normal `TableComponent` it follows the same architecture. For the basic usage please visit the [TableComponent docs](./tables). The following docs are only about the additional specifics of the `BorderBoxTable`. diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index ebac0d79411..4f72d012134 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -29,9 +29,8 @@ Both the collapsible header and static heads can accept additional actions. For ## Uses -- to display a list of meetings - to display individual meeting agenda items in a meeting -- to display the a list of project attributes +- to display the a list of project attributes in Project settings - to display a list of configured OAuth applications If the content needs to be more structured (with columns and column headers), please use the [Border Box Table](border-box-table) component instead. From a1cb5b933db0a4e0b58f1a099555de3688add41d Mon Sep 17 00:00:00 2001 From: ulferts Date: Wed, 2 Apr 2025 17:37:13 +0200 Subject: [PATCH 057/260] use component for global and project definition administration --- .../projects/life_cycle_component.html.erb | 8 ------ .../phase_definition_component.html.erb | 15 ++++++++++ ...onent.rb => phase_definition_component.rb} | 26 +++++++++++++---- .../life_cycle_steps/step_component.html.erb | 18 ++++++------ .../life_cycle_steps/step_component.rb | 26 ----------------- .../row_component.html.erb | 28 +++++-------------- .../row_component.rb | 26 ----------------- .../phase.html.erb | 6 ---- ... => phase_definition_component_preview.rb} | 8 ++++-- .../phase.html.erb | 6 ++++ 10 files changed, 62 insertions(+), 105 deletions(-) delete mode 100644 app/components/projects/life_cycle_component.html.erb create mode 100644 app/components/projects/phase_definition_component.html.erb rename app/components/projects/{life_cycle_component.rb => phase_definition_component.rb} (82%) delete mode 100644 lookbook/previews/open_project/projects/life_cycle_component_preview/phase.html.erb rename lookbook/previews/open_project/projects/{life_cycle_component_preview.rb => phase_definition_component_preview.rb} (86%) create mode 100644 lookbook/previews/open_project/projects/phase_definition_component_preview/phase.html.erb diff --git a/app/components/projects/life_cycle_component.html.erb b/app/components/projects/life_cycle_component.html.erb deleted file mode 100644 index 3f9a0f06e6f..00000000000 --- a/app/components/projects/life_cycle_component.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -<%= flex_layout(align_items: :center) do |type_container| - type_container.with_column(mr: 1, classes: icon_color_class) do - render Primer::Beta::Octicon.new(icon: icon) - end - type_container.with_column do - render(Primer::Beta::Text.new(**text_options)) { text } - end - end %> diff --git a/app/components/projects/phase_definition_component.html.erb b/app/components/projects/phase_definition_component.html.erb new file mode 100644 index 00000000000..0b3092e71ee --- /dev/null +++ b/app/components/projects/phase_definition_component.html.erb @@ -0,0 +1,15 @@ +<%= flex_layout(align_items: :center) do |type_container| + type_container.with_column(classes: icon_color_class, mr: 1) do + render Primer::Beta::Octicon.new(icon: icon) + end + type_container.with_column(test_selector: "project-life-cycle-step-definition-name", classes: "ellipsis") do + if edit_link? + render(Primer::Beta::Link.new(href: phase_href, **phase_text_options)) { phase_text } + else + render(Primer::Beta::Text.new(**phase_text_options)) { phase_text } + end + end + type_container.with_column(ml: 2, classes: "no-wrap") do + render(Primer::Beta::Text.new(**gates_text_options)) { gates_text } + end + end %> diff --git a/app/components/projects/life_cycle_component.rb b/app/components/projects/phase_definition_component.rb similarity index 82% rename from app/components/projects/life_cycle_component.rb rename to app/components/projects/phase_definition_component.rb index f96e1453c73..09e87404243 100644 --- a/app/components/projects/life_cycle_component.rb +++ b/app/components/projects/phase_definition_component.rb @@ -28,14 +28,22 @@ # See COPYRIGHT and LICENSE files for more details. # ++ module Projects - class LifeCycleComponent < ApplicationComponent + class PhaseDefinitionComponent < ApplicationComponent include OpPrimer::ComponentHelpers # TODO: This component is currently not in use! It should be a shared component # between the Projects::Settings::LifeCycleSteps::StepComponent and the # Settings::ProjectLifeCycleStepDefinitions::RowComponent. # It should hold the icon, definition name and gate text information. - def text + def phase_text + model.name + end + + def phase_href + edit_admin_settings_project_phase_definition_path(model) + end + + def gates_text if model.start_gate? && model.finish_gate? I18n.t("settings.project_phase_definitions.both_gate") elsif model.start_gate? @@ -52,14 +60,22 @@ module Projects end def icon_color_class - helpers.hl_inline_class("project_phase_definition", model) + helpers.hl_inline_class("project_phase_definition", model.id) end - def text_options + def gates_text_options # The tag: :div is is a hack to fix the line height difference # caused by font_size: :small. That line height difference # would otherwise lead to the text being not on the same height as the icon - { color: :muted, font_size: :small, tag: :div }.merge(options) + { color: :muted, font_size: :small, tag: :div }.merge(options[:gates_text_options] || {}) + end + + def phase_text_options + { font_weight: :bold }.merge(options[:phase_text_options] || {}) + end + + def edit_link? + options[:edit_link] end end end diff --git a/app/components/projects/settings/life_cycle_steps/step_component.html.erb b/app/components/projects/settings/life_cycle_steps/step_component.html.erb index 7d777ea72c5..c198e9f52bf 100644 --- a/app/components/projects/settings/life_cycle_steps/step_component.html.erb +++ b/app/components/projects/settings/life_cycle_steps/step_component.html.erb @@ -3,16 +3,14 @@ align_items: :center, justify_content: :space_between ) do |step_container| - step_container.with_column(flex_layout: true, mr: 2, classes: "min-width-0") do |title_container| - title_container.with_column(pt: 1, mr: 1, classes: icon_color_class) do - render Primer::Beta::Octicon.new(icon: icon) - end - title_container.with_column(pt: 1, mr: 2, classes: "ellipsis") do - render(Primer::Beta::Text.new(classes: "filter-target-visible-text")) { definition.name } - end - title_container.with_column(pt: 1, classes: "no-wrap") do - render(Primer::Beta::Text.new(**gate_text_options)) { gate_info } - end + step_container.with_column(mr: 2, classes: "min-width-0") do + render( + Projects::PhaseDefinitionComponent.new( + definition, + edit_link: User.current.admin?, + phase_text_options: { classes: "filter-target-visible-text" } + ) + ) end # py: 1 quick fix: prevents the row from bouncing as the toggle switch currently changes height while toggling step_container.with_column(py: 1, mr: 2) do diff --git a/app/components/projects/settings/life_cycle_steps/step_component.rb b/app/components/projects/settings/life_cycle_steps/step_component.rb index 08a2cf32264..2dd0f59b647 100644 --- a/app/components/projects/settings/life_cycle_steps/step_component.rb +++ b/app/components/projects/settings/life_cycle_steps/step_component.rb @@ -37,32 +37,6 @@ module Projects options :definition, :active? - # TODO: Remove these helper methods once the Projects::LifeCycleComponent - # has been refactored. - def icon - :"op-phase" - end - - def icon_color_class - helpers.hl_inline_class("project_phase_definition", definition) - end - - def gate_info - if definition.start_gate? && definition.finish_gate? - I18n.t("settings.project_phase_definitions.both_gate") - elsif definition.start_gate? - I18n.t("settings.project_phase_definitions.start_gate") - elsif definition.finish_gate? - I18n.t("settings.project_phase_definitions.finish_gate") - else - I18n.t("settings.project_phase_definitions.no_gate") - end - end - - def gate_text_options - { color: :muted, font_size: :small }.merge(options) - end - def toggle_aria_label I18n.t("projects.settings.life_cycle.step.use_in_project", step: definition.name) end diff --git a/app/components/settings/project_life_cycle_step_definitions/row_component.html.erb b/app/components/settings/project_life_cycle_step_definitions/row_component.html.erb index 9c40ff194f1..ae6983e7de3 100644 --- a/app/components/settings/project_life_cycle_step_definitions/row_component.html.erb +++ b/app/components/settings/project_life_cycle_step_definitions/row_component.html.erb @@ -39,28 +39,14 @@ See COPYRIGHT and LICENSE files for more details. ) end end - title_container.with_column(classes: icon_color_class) do - render Primer::Beta::Octicon.new(icon: icon) - end - title_container.with_column(classes: "ellipsis", test_selector: "project-life-cycle-step-definition-name") do - render( - if allowed_to_customize_life_cycle? - Primer::Beta::Link.new( - classes: "filter-target-visible-text", - href: edit_admin_settings_project_phase_definition_path(definition), - font_weight: :bold - ) - else - Primer::Beta::Text.new( - font_weight: :bold - ) - end - ) do - definition.name - end - end title_container.with_column do - render(Primer::Beta::Text.new(**gate_text_options)) { gate_info } + render( + Projects::PhaseDefinitionComponent.new( + definition, + edit_link: allowed_to_customize_life_cycle?, + phase_text_options: { classes: "filter-target-visible-text" } + ) + ) end title_container.with_column(classes: "no-wrap") do render(Primer::Beta::Text.new) { t("project.count", count: definition.project_count) } diff --git a/app/components/settings/project_life_cycle_step_definitions/row_component.rb b/app/components/settings/project_life_cycle_step_definitions/row_component.rb index 7f92dd5684f..777fcf1b76c 100644 --- a/app/components/settings/project_life_cycle_step_definitions/row_component.rb +++ b/app/components/settings/project_life_cycle_step_definitions/row_component.rb @@ -39,32 +39,6 @@ module Settings options :first?, :last? - # TODO: Remove these helper classes once the Projects::LifeCycleComponent - # has been refactored. - def icon - :"op-phase" - end - - def icon_color_class - helpers.hl_inline_class("project_phase_definition", definition) - end - - def gate_info - if definition.start_gate? && definition.finish_gate? - I18n.t("settings.project_phase_definitions.both_gate") - elsif definition.start_gate? - I18n.t("settings.project_phase_definitions.start_gate") - elsif definition.finish_gate? - I18n.t("settings.project_phase_definitions.finish_gate") - else - I18n.t("settings.project_phase_definitions.no_gate") - end - end - - def gate_text_options - { color: :muted, font_size: :small }.merge(options) - end - private def move_action(menu:, move_to:, label:, icon:) diff --git a/lookbook/previews/open_project/projects/life_cycle_component_preview/phase.html.erb b/lookbook/previews/open_project/projects/life_cycle_component_preview/phase.html.erb deleted file mode 100644 index ffd42d8cf05..00000000000 --- a/lookbook/previews/open_project/projects/life_cycle_component_preview/phase.html.erb +++ /dev/null @@ -1,6 +0,0 @@ - - - -<%= render(::Projects::LifeCycleComponent.new(model)) %> diff --git a/lookbook/previews/open_project/projects/life_cycle_component_preview.rb b/lookbook/previews/open_project/projects/phase_definition_component_preview.rb similarity index 86% rename from lookbook/previews/open_project/projects/life_cycle_component_preview.rb rename to lookbook/previews/open_project/projects/phase_definition_component_preview.rb index fa5daee61ab..f20d20201e7 100644 --- a/lookbook/previews/open_project/projects/life_cycle_component_preview.rb +++ b/lookbook/previews/open_project/projects/phase_definition_component_preview.rb @@ -31,12 +31,14 @@ module OpenProject module Projects # @logical_path OpenProject/Projects - class LifeCycleComponentPreview < Lookbook::Preview + class PhaseDefinitionComponentPreview < Lookbook::Preview + # @param edit_link [boolean] # @param start_gate [boolean] # @param finish_gate [boolean] - def phase(start_gate: false, finish_gate: false) + def phase(edit_link: false, start_gate: false, finish_gate: false) model = Project::PhaseDefinition.new(id: 1, name: "The first phase", start_gate:, finish_gate:) - render_with_template(locals: { model: }) + + render_with_template(locals: { model:, edit_link: }) end end end diff --git a/lookbook/previews/open_project/projects/phase_definition_component_preview/phase.html.erb b/lookbook/previews/open_project/projects/phase_definition_component_preview/phase.html.erb new file mode 100644 index 00000000000..7cc860782cf --- /dev/null +++ b/lookbook/previews/open_project/projects/phase_definition_component_preview/phase.html.erb @@ -0,0 +1,6 @@ + + + +<%= render(::Projects::PhaseDefinitionComponent.new(model, edit_link:)) %> From 3eda83fcd7dd8222840d8acf133c3857610f2703 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Thu, 3 Apr 2025 15:27:48 +0200 Subject: [PATCH 058/260] Add a code example for the collapsibleHeader and do some cleanup --- lookbook/docs/components/border-box.md.erb | 18 +++---- .../{ => tables}/border-box-table.md.erb | 7 ++- .../components/{ => tables}/tables.md.erb | 0 .../op_primer/border_box_component_preview.rb | 22 +++++++++ .../collapsible.html.erb | 49 +++++++++++++++++++ 5 files changed, 83 insertions(+), 13 deletions(-) rename lookbook/docs/components/{ => tables}/border-box-table.md.erb (96%) rename lookbook/docs/components/{ => tables}/tables.md.erb (100%) create mode 100644 lookbook/previews/op_primer/border_box_component_preview.rb create mode 100644 lookbook/previews/op_primer/border_box_component_preview/collapsible.html.erb diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index 4f72d012134..da05770e02e 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -1,5 +1,6 @@ -The Border Box element is used to display structured items in a list, each with a set of actions. It is used for example: +The Border Box element is used to display structured items in a list, each with a set of actions. +<%= embed OpPrimer::BorderBoxComponentPreview, :default %> ## Anatomy @@ -12,21 +13,20 @@ If a page uses a Border Box with a header, all sections must use headers. ## Header -Note for Parimal: -You can chose between a collapsibleHeader and a free-chosen Header. The collapsible Header consists of Title, counter(optional) and description(optional). - -The header can either be static or collapsible. +The header can either be static or collapsible. The collapsibleHeader brings additional functionality: -- an **arrow indicator** next to the title indicates if the section is collapsed or expanded. +- an **arrow indicator** next to the title indicates if the section is collapsed or expanded. - a **header description** (optional) to give additional context to the content of that section. Hidden when collapsed. - a **counter** (optional) displays the number of items that that particular section contains. - + When collapsed, the bottom border is slightly thicker to indicate something is hidden. Both the collapsible header and static heads can accept additional actions. For example, a **more button** can offer additional contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). +<%= embed OpPrimer::BorderBoxComponentPreview, :collapsible %> + ## Uses - to display individual meeting agenda items in a meeting @@ -47,8 +47,8 @@ If the content needs to be more structured (with columns and column headers), pl - Don't mix sections with and without headers. If one section has a header, they must all have headers. - Don't make sections collapsible if they do not need to be. - ## Technical notes +<%= embed OpPrimer::BorderBoxComponentPreview, :collapsible, panels: %i[source] %> -### Code structure +For detailed examples have a look at the other [border box preview examples](/lookbook/inspect/primer/beta/border_box/playground) or the [collapsible header preview examples](/lookbook/inspect/primer/open_project/border_box/collapsible_header/playground). diff --git a/lookbook/docs/components/border-box-table.md.erb b/lookbook/docs/components/tables/border-box-table.md.erb similarity index 96% rename from lookbook/docs/components/border-box-table.md.erb rename to lookbook/docs/components/tables/border-box-table.md.erb index 349eb098882..52202789d4f 100644 --- a/lookbook/docs/components/border-box-table.md.erb +++ b/lookbook/docs/components/tables/border-box-table.md.erb @@ -4,9 +4,9 @@ ## Anatomy -**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility short cuts). +**Note:** The BorderBoxTable is based on the `Primer::Beta::BorderBox` with a CSS grid applied inside to align the individual rows and make it look like a table. Please note, that it is technically not a table and has therefore none of the benefits a normal HTML table would have (e.g automatic column width adjustments or accessibility short cuts). -If you want or need that, please use the [TableComponent docs](./tables)) +If you want or need that, please use the [TableComponent docs](./tables) ## Best practices @@ -27,8 +27,7 @@ If you want or need that, please use the [TableComponent docs](./tables)) - to display a list of configured OpenID providers - to display a list of configured SCIM clients -If the content does not need a table structure with column headers and grids, please use the simpler [Border Box](border-box-table) component instead. - +If the content does not need a table structure with column headers and grids, please use the simpler [Border Box](../border_box) component instead. ## Technical notes diff --git a/lookbook/docs/components/tables.md.erb b/lookbook/docs/components/tables/tables.md.erb similarity index 100% rename from lookbook/docs/components/tables.md.erb rename to lookbook/docs/components/tables/tables.md.erb diff --git a/lookbook/previews/op_primer/border_box_component_preview.rb b/lookbook/previews/op_primer/border_box_component_preview.rb new file mode 100644 index 00000000000..0e5e5c55e90 --- /dev/null +++ b/lookbook/previews/op_primer/border_box_component_preview.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module OpPrimer + # @hidden + # @display min_height 400px + class BorderBoxComponentPreview < Lookbook::Preview + def default + render(Primer::Beta::BorderBox.new) do |component| + component.with_header { "Header" } + component.with_body { "Body" } + component.with_row { "Row one" } + component.with_row { "Row two" } + component.with_row { "Row three" } + component.with_footer { "Footer" } + end + end + + def collapsible + render_with_template + end + end +end diff --git a/lookbook/previews/op_primer/border_box_component_preview/collapsible.html.erb b/lookbook/previews/op_primer/border_box_component_preview/collapsible.html.erb new file mode 100644 index 00000000000..f9e33ee6d13 --- /dev/null +++ b/lookbook/previews/op_primer/border_box_component_preview/collapsible.html.erb @@ -0,0 +1,49 @@ +<%= render(Primer::Beta::BorderBox.new) do |component| %> + <% component.with_header do %> + <%= render( + Primer::OpenProject::BorderBox::CollapsibleHeader.new( + box: component, + title: "Collapsible header", + count: 3 + ) + ) %> + <% end %> + <% component.with_body { "Body" } %> + <% component.with_row do %> + <%= render(Primer::OpenProject::FlexLayout.new(justify_content: :space_between, align_items: :center)) do |flex| %> + <%= flex.with_column { "Row 1" } %> + <%= flex.with_column do %> + <%= render(Primer::Alpha::ActionMenu.new) do |menu| + menu.with_show_button(icon: "kebab-horizontal", "aria-label": "More", scheme: :invisible) + menu.with_item( + tag: :a, + label: "Edit", + href: "#" + ) do |item| + item.with_leading_visual_icon(icon: :pencil) + "foo" + end + end %> + <% end %> + <% end %> + <% end %> + <% component.with_row do %> + <%= render(Primer::OpenProject::FlexLayout.new(justify_content: :space_between, align_items: :center)) do |flex| %> + <%= flex.with_column { "Row 2" } %> + <%= flex.with_column do %> + <%= render(Primer::Alpha::ActionMenu.new) do |menu| + menu.with_show_button(icon: "kebab-horizontal", "aria-label": "More", scheme: :invisible) + menu.with_item( + tag: :a, + label: "Edit", + href: "#" + ) do |item| + item.with_leading_visual_icon(icon: :pencil) + "foo" + end + end %> + <% end %> + <% end %> + <% end %> + <% component.with_footer { "Footer" } %> +<% end %> From 83d37b135a35f4107892460627e280f75373c533 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:47:45 +0200 Subject: [PATCH 059/260] Minor update --- lookbook/docs/components/tables/border-box-table.md.erb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lookbook/docs/components/tables/border-box-table.md.erb b/lookbook/docs/components/tables/border-box-table.md.erb index 52202789d4f..449221682ba 100644 --- a/lookbook/docs/components/tables/border-box-table.md.erb +++ b/lookbook/docs/components/tables/border-box-table.md.erb @@ -22,6 +22,8 @@ If you want or need that, please use the [TableComponent docs](./tables) ## Uses +Some examples of where we already use the Border Box table: + - to display a list of meetings - to display a list of configured SAML providers - to display a list of configured OpenID providers From d44c0f8642ed42635f102ea7d4ec7368db2b0a23 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:48:54 +0200 Subject: [PATCH 060/260] Minor --- lookbook/docs/components/border-box.md.erb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index da05770e02e..c3176219af1 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -29,6 +29,8 @@ Both the collapsible header and static heads can accept additional actions. For ## Uses +Some places in which we already use the Border Box: + - to display individual meeting agenda items in a meeting - to display the a list of project attributes in Project settings - to display a list of configured OAuth applications From 2974b02a72ef8be832915a4481e49142b4d33b31 Mon Sep 17 00:00:00 2001 From: Mir Bhatia Date: Thu, 3 Apr 2025 16:36:03 +0200 Subject: [PATCH 061/260] Add with_footer example for BorderBoxTable --- .../border_box_table_component_preview.rb | 5 ++ .../with_footer.html.erb | 66 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 lookbook/previews/op_primer/border_box_table_component_preview/with_footer.html.erb diff --git a/lookbook/previews/op_primer/border_box_table_component_preview.rb b/lookbook/previews/op_primer/border_box_table_component_preview.rb index 48402b2a59e..c9c4365cc78 100644 --- a/lookbook/previews/op_primer/border_box_table_component_preview.rb +++ b/lookbook/previews/op_primer/border_box_table_component_preview.rb @@ -18,5 +18,10 @@ module OpPrimer def with_action_menu render_with_template end + + # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. + def with_footer + render_with_template + end end end diff --git a/lookbook/previews/op_primer/border_box_table_component_preview/with_footer.html.erb b/lookbook/previews/op_primer/border_box_table_component_preview/with_footer.html.erb new file mode 100644 index 00000000000..50077e2dbeb --- /dev/null +++ b/lookbook/previews/op_primer/border_box_table_component_preview/with_footer.html.erb @@ -0,0 +1,66 @@ +<%= + table = Class.new(OpPrimer::BorderBoxTableComponent) do + columns :foo, :bar + + mobile_labels :bar + + def self.name + "MyTable" + end + + def mobile_title + "Mobile foo" + end + + def row_class + @row_class ||= Class.new(OpPrimer::BorderBoxRowComponent) do + def self.name + "MyRow" + end + + def button_links + [ + edit_button, + delete_button + ] + end + + def edit_button + render(Primer::Beta::Button.new(scheme: :secondary, tag: :a, href: "#")) { "Edit" } + end + + def delete_button + render(Primer::Beta::IconButton.new(icon: :trash, scheme: :danger, tag: :a, href: "#", "aria-label": "Delete")) + end + + def foo + "foo" + end + + def bar + "bar" + end + end + end + + def has_footer? + true + end + + def footer + render(Primer::BaseComponent.new(tag: :span)) do + concat render(Primer::Beta::Text.new) { "This can be a custom footer component " } + concat render(Primer::Beta::Link.new(href: "#")) { "with all sorts of things" } + end + end + + def headers + [ + [:foo, { caption: "Foo column" }], + [:bar, { caption: "Bar column" }] + ] + end + end + + render(table.new(rows: [1, 2])) +%> From 951ae05cd6f395369bdb43a5d6b87cf1cecaa524 Mon Sep 17 00:00:00 2001 From: Mir Bhatia Date: Thu, 3 Apr 2025 16:38:49 +0200 Subject: [PATCH 062/260] Clean up --- lookbook/docs/components/border-box.md.erb | 4 ++-- lookbook/docs/components/tables/border-box-table.md.erb | 2 +- lookbook/docs/components/tables/tables.md.erb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index c3176219af1..176cae0e1ac 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -15,7 +15,7 @@ If a page uses a Border Box with a header, all sections must use headers. The header can either be static or collapsible. -The collapsibleHeader brings additional functionality: +The CollapsibleHeader brings additional functionality: - an **arrow indicator** next to the title indicates if the section is collapsed or expanded. - a **header description** (optional) to give additional context to the content of that section. Hidden when collapsed. @@ -23,7 +23,7 @@ The collapsibleHeader brings additional functionality: When collapsed, the bottom border is slightly thicker to indicate something is hidden. -Both the collapsible header and static heads can accept additional actions. For example, a **more button** can offer additional contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). +Both the collapsible and static headers can accept additional actions. For example, a **more button** can offer additional contextual actions such as edit, delete and move (move up, move to top, move down, move to the end). <%= embed OpPrimer::BorderBoxComponentPreview, :collapsible %> diff --git a/lookbook/docs/components/tables/border-box-table.md.erb b/lookbook/docs/components/tables/border-box-table.md.erb index 449221682ba..ed4c30bed60 100644 --- a/lookbook/docs/components/tables/border-box-table.md.erb +++ b/lookbook/docs/components/tables/border-box-table.md.erb @@ -71,7 +71,7 @@ columns :title, :users, :created_at # Make title column wider than the others (factor 2 using grid span) main_column :title ``` -Note: Ideally, one one main column will be present for each table. +Note: Ideally, only one main column will be present for each table. ### Footer diff --git a/lookbook/docs/components/tables/tables.md.erb b/lookbook/docs/components/tables/tables.md.erb index 559ffea6bb6..08a226eb140 100644 --- a/lookbook/docs/components/tables/tables.md.erb +++ b/lookbook/docs/components/tables/tables.md.erb @@ -50,7 +50,7 @@ end **Headers** -Define the headers of the component as a method retu +Define the headers of the component as a method: ```ruby module ModuleA @@ -72,7 +72,7 @@ end **Actions** -Define the actions in the row component as `button_links`. See the example code +Define the actions in the row component as `button_links`. See the example code: ### Full example From 0a26f9cf126a3a7ec4cc734c2981f1a525829814 Mon Sep 17 00:00:00 2001 From: ulferts Date: Thu, 3 Apr 2025 18:28:51 +0200 Subject: [PATCH 063/260] correct next version - 16.0 --- lib/open_project/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 390c784aef8..ee877f11a2f 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -31,8 +31,8 @@ require "open3" module OpenProject module VERSION # :nodoc: - MAJOR = 15 - MINOR = 6 + MAJOR = 16 + MINOR = 0 PATCH = 0 class << self From 114f4a8c193f62b9265ec5e56707a0a6386df730 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Thu, 3 Apr 2025 18:50:19 +0200 Subject: [PATCH 064/260] First draft --- lookbook/docs/components/side-panel.md.erb | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 lookbook/docs/components/side-panel.md.erb diff --git a/lookbook/docs/components/side-panel.md.erb b/lookbook/docs/components/side-panel.md.erb new file mode 100644 index 00000000000..8e160374c60 --- /dev/null +++ b/lookbook/docs/components/side-panel.md.erb @@ -0,0 +1,55 @@ +The Side panel is right-side pane that is used to show information relevant to the current page. This information normally concerns the contents of the entire page and can generally directly be modified or adjusted via the side panel. + +A good example is a meeting occurrence; the side panel is used to show key meeting details (time, location, duration...), status, a list of participants and attachments. + +## Anatomy + +The side panel consists of a series of sections (or just one section). Each section has a fixed format and contains: + +- A section header + - with counter (optional) +- An action button or more icon (optional) +- Content slot +- An action link (optional) +- A divider at the end + +These sections are stacked vertically. + +The content slot can take a number of different types of content and is relatively free. However, the content has to make sense in visual and semantic hierarchy. It's also best to make sure all objects are aligned to the left edge of the panel. + +The content of the side panel should always be secondary to the main content area. + +## Best practices + +**Do** + +- Do use the side panel for contextual information on the page +- Ensure that elements on a side panel respect the hierarchy of the page and elements in other side panels (the content in each side panel should roughly be at the same hierarchical and visual level) +- Use `color-fg-subtle` if the text is meant to be helpful guideline text or a caption; use `color-fg-default` for key information. + +**Don't** + +- Do not use it as a way to create columns +- Do not make a certain section too long, compared to others. If necessary, use a 'Show more' link to expand it (eg. Participant list in a meeting occurence ) + +## Used in + +Some pages where the side panel is used: + +- Meeting occurence (displays meeting details, meeting status, participants and attachments) +- Project overview (displays project attributes) +- Project list +- Some admin index pages (eg. SAML or OpenID provider details page; file storage details page) + +## Mobile considerations + +By default, side panel move to the bottom of the main content area on mobile. However, there are other considerations to keep in mind: + +- Some sections have to manually be moved to the top if they contain critical information (eg. the meeting details for a meeting occurence go to the top, but the participant list goes to the bottom) +- Sections can be simplified (certain actions hidden) or indeed completely left out on mobile if they are judged to be not critical on smaller screens + + +## Technical notes + +## Examples + From 4259d199a4db2764eb35d7306d28c39858ee63ed Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Fri, 4 Apr 2025 03:19:18 +0000 Subject: [PATCH 065/260] update locales from crowdin [ci skip] --- config/locales/crowdin/af.yml | 2 + config/locales/crowdin/ar.yml | 2 + config/locales/crowdin/az.yml | 2 + config/locales/crowdin/be.yml | 2 + config/locales/crowdin/bg.yml | 2 + config/locales/crowdin/ca.yml | 2 + config/locales/crowdin/ckb-IR.yml | 2 + config/locales/crowdin/cs.yml | 2 + config/locales/crowdin/da.yml | 2 + config/locales/crowdin/de.yml | 4 +- config/locales/crowdin/el.yml | 2 + config/locales/crowdin/eo.yml | 2 + config/locales/crowdin/es.yml | 2 + config/locales/crowdin/et.yml | 2 + config/locales/crowdin/eu.yml | 2 + config/locales/crowdin/fa.yml | 2 + config/locales/crowdin/fi.yml | 2 + config/locales/crowdin/fil.yml | 2 + config/locales/crowdin/fr.yml | 2 + config/locales/crowdin/he.yml | 2 + config/locales/crowdin/hi.yml | 2 + config/locales/crowdin/hr.yml | 2 + config/locales/crowdin/hu.yml | 2 + config/locales/crowdin/id.yml | 2 + config/locales/crowdin/it.yml | 2 + config/locales/crowdin/ja.yml | 2 + config/locales/crowdin/js-pt-PT.yml | 6 +- config/locales/crowdin/ka.yml | 2 + config/locales/crowdin/kk.yml | 2 + config/locales/crowdin/ko.yml | 2 + config/locales/crowdin/lt.yml | 2 + config/locales/crowdin/lv.yml | 2 + config/locales/crowdin/mn.yml | 2 + config/locales/crowdin/ms.yml | 2 + config/locales/crowdin/ne.yml | 2 + config/locales/crowdin/nl.yml | 2 + config/locales/crowdin/no.yml | 2 + config/locales/crowdin/pl.yml | 2 + config/locales/crowdin/pt-BR.yml | 2 + config/locales/crowdin/pt-PT.seeders.yml | 30 ++--- config/locales/crowdin/pt-PT.yml | 106 +++++++++--------- config/locales/crowdin/ro.yml | 2 + config/locales/crowdin/ru.yml | 4 +- config/locales/crowdin/rw.yml | 2 + config/locales/crowdin/si.yml | 2 + config/locales/crowdin/sk.yml | 2 + config/locales/crowdin/sl.yml | 2 + config/locales/crowdin/sr.yml | 2 + config/locales/crowdin/sv.yml | 2 + config/locales/crowdin/th.yml | 2 + config/locales/crowdin/tr.yml | 2 + config/locales/crowdin/uk.yml | 2 + config/locales/crowdin/uz.yml | 2 + config/locales/crowdin/vi.yml | 2 + config/locales/crowdin/zh-CN.seeders.yml | 24 ++-- config/locales/crowdin/zh-CN.yml | 106 +++++++++--------- config/locales/crowdin/zh-TW.yml | 2 + .../backlogs/config/locales/crowdin/pt-PT.yml | 30 ++--- .../bim/config/locales/crowdin/js-pt-PT.yml | 2 +- .../config/locales/crowdin/js-pt-PT.yml | 10 +- .../boards/config/locales/crowdin/pt-PT.yml | 4 +- .../calendar/config/locales/crowdin/pt-PT.yml | 4 +- modules/costs/config/locales/crowdin/fr.yml | 8 +- modules/meeting/config/locales/crowdin/af.yml | 2 +- modules/meeting/config/locales/crowdin/ar.yml | 2 +- modules/meeting/config/locales/crowdin/az.yml | 2 +- modules/meeting/config/locales/crowdin/be.yml | 2 +- modules/meeting/config/locales/crowdin/bg.yml | 2 +- modules/meeting/config/locales/crowdin/ca.yml | 2 +- .../meeting/config/locales/crowdin/ckb-IR.yml | 2 +- modules/meeting/config/locales/crowdin/cs.yml | 2 +- modules/meeting/config/locales/crowdin/da.yml | 2 +- modules/meeting/config/locales/crowdin/de.yml | 2 +- modules/meeting/config/locales/crowdin/el.yml | 2 +- modules/meeting/config/locales/crowdin/eo.yml | 2 +- modules/meeting/config/locales/crowdin/es.yml | 2 +- modules/meeting/config/locales/crowdin/et.yml | 2 +- modules/meeting/config/locales/crowdin/eu.yml | 2 +- modules/meeting/config/locales/crowdin/fa.yml | 2 +- modules/meeting/config/locales/crowdin/fi.yml | 2 +- .../meeting/config/locales/crowdin/fil.yml | 2 +- modules/meeting/config/locales/crowdin/fr.yml | 2 +- modules/meeting/config/locales/crowdin/he.yml | 2 +- modules/meeting/config/locales/crowdin/hi.yml | 2 +- modules/meeting/config/locales/crowdin/hr.yml | 2 +- modules/meeting/config/locales/crowdin/hu.yml | 2 +- modules/meeting/config/locales/crowdin/id.yml | 2 +- modules/meeting/config/locales/crowdin/it.yml | 2 +- modules/meeting/config/locales/crowdin/ja.yml | 2 +- modules/meeting/config/locales/crowdin/ka.yml | 2 +- modules/meeting/config/locales/crowdin/kk.yml | 2 +- modules/meeting/config/locales/crowdin/ko.yml | 2 +- modules/meeting/config/locales/crowdin/lt.yml | 2 +- modules/meeting/config/locales/crowdin/lv.yml | 2 +- modules/meeting/config/locales/crowdin/mn.yml | 2 +- modules/meeting/config/locales/crowdin/ms.yml | 2 +- modules/meeting/config/locales/crowdin/ne.yml | 2 +- modules/meeting/config/locales/crowdin/nl.yml | 2 +- modules/meeting/config/locales/crowdin/no.yml | 2 +- modules/meeting/config/locales/crowdin/pl.yml | 2 +- .../meeting/config/locales/crowdin/pt-BR.yml | 2 +- .../meeting/config/locales/crowdin/pt-PT.yml | 4 +- modules/meeting/config/locales/crowdin/ro.yml | 2 +- modules/meeting/config/locales/crowdin/ru.yml | 2 +- modules/meeting/config/locales/crowdin/rw.yml | 2 +- modules/meeting/config/locales/crowdin/si.yml | 2 +- modules/meeting/config/locales/crowdin/sk.yml | 2 +- modules/meeting/config/locales/crowdin/sl.yml | 2 +- modules/meeting/config/locales/crowdin/sr.yml | 2 +- modules/meeting/config/locales/crowdin/sv.yml | 2 +- modules/meeting/config/locales/crowdin/th.yml | 2 +- modules/meeting/config/locales/crowdin/tr.yml | 2 +- modules/meeting/config/locales/crowdin/uk.yml | 2 +- modules/meeting/config/locales/crowdin/uz.yml | 2 +- modules/meeting/config/locales/crowdin/vi.yml | 2 +- .../meeting/config/locales/crowdin/zh-CN.yml | 6 +- .../meeting/config/locales/crowdin/zh-TW.yml | 2 +- 117 files changed, 330 insertions(+), 222 deletions(-) diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml index 2c341a2bd72..587e5c54b3d 100644 --- a/config/locales/crowdin/af.yml +++ b/config/locales/crowdin/af.yml @@ -2056,6 +2056,8 @@ af: dialog: title: "Uitvoer" submit: "Uitvoer" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml index 92910610042..f4068a23f22 100644 --- a/config/locales/crowdin/ar.yml +++ b/config/locales/crowdin/ar.yml @@ -2212,6 +2212,8 @@ ar: dialog: title: "تصدير" submit: "تصدير" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml index a31d2b9e375..71255f8add7 100644 --- a/config/locales/crowdin/az.yml +++ b/config/locales/crowdin/az.yml @@ -2056,6 +2056,8 @@ az: dialog: title: "İxrac et" submit: "İxrac et" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml index 5b5f3f50647..2f925203d5e 100644 --- a/config/locales/crowdin/be.yml +++ b/config/locales/crowdin/be.yml @@ -2134,6 +2134,8 @@ be: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index 777bf95f567..ffd42318f81 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -2056,6 +2056,8 @@ bg: dialog: title: "Експортиране" submit: "Експортиране" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index 062a5dfb8fb..28885759162 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -2053,6 +2053,8 @@ ca: dialog: title: "Exportar" submit: "Exportar" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml index 5e7b4086521..cbf56f9c6ba 100644 --- a/config/locales/crowdin/ckb-IR.yml +++ b/config/locales/crowdin/ckb-IR.yml @@ -2056,6 +2056,8 @@ ckb-IR: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index 07bea34fd27..6fa853c0e2d 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -2134,6 +2134,8 @@ cs: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "Formát souboru" options: diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml index 19dc375bd8d..32b6c0babbf 100644 --- a/config/locales/crowdin/da.yml +++ b/config/locales/crowdin/da.yml @@ -2054,6 +2054,8 @@ da: dialog: title: "Eksportér" submit: "Eksportér" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index f63d723df7d..d3898105520 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -2049,6 +2049,8 @@ de: dialog: title: "Exportieren" submit: "Exportieren" + save_export_settings: + label: "Save settings" format: label: "Dateiformat" options: @@ -2140,7 +2142,7 @@ de: caption: Alle Attribute, die in der aktuellen Formularkonfiguration mit der Standardvorlage vorhanden sind. template_contract: label: "Vertrag" - caption: Details des Arbeitspakets im Format der deutschen Standardvertragsform. + caption: Details des Arbeitspakets im Format des deutschen Standardvertragsformulars. dialog: title: PDF generieren submit: Download diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml index e1dd6a2e578..a10c1aeb70f 100644 --- a/config/locales/crowdin/el.yml +++ b/config/locales/crowdin/el.yml @@ -2052,6 +2052,8 @@ el: dialog: title: "Εξαγωγή" submit: "Εξαγωγή" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml index e558758465b..893df3ab326 100644 --- a/config/locales/crowdin/eo.yml +++ b/config/locales/crowdin/eo.yml @@ -2056,6 +2056,8 @@ eo: dialog: title: "Eksporti" submit: "Eksporti" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml index 2ec3ece7bff..d48df8b8284 100644 --- a/config/locales/crowdin/es.yml +++ b/config/locales/crowdin/es.yml @@ -2054,6 +2054,8 @@ es: dialog: title: "Exportar" submit: "Exportar" + save_export_settings: + label: "Save settings" format: label: "Formato del archivo" options: diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml index b6bb46ef780..58238b01efc 100644 --- a/config/locales/crowdin/et.yml +++ b/config/locales/crowdin/et.yml @@ -2056,6 +2056,8 @@ et: dialog: title: "Ekspordi" submit: "Ekspordi" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml index 544d0511c17..1a8c1729e3a 100644 --- a/config/locales/crowdin/eu.yml +++ b/config/locales/crowdin/eu.yml @@ -2056,6 +2056,8 @@ eu: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml index bb8ea0645ce..d18f0bc1744 100644 --- a/config/locales/crowdin/fa.yml +++ b/config/locales/crowdin/fa.yml @@ -2056,6 +2056,8 @@ fa: dialog: title: "خروجی" submit: "خروجی" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml index 5311212185c..cdde77eeefe 100644 --- a/config/locales/crowdin/fi.yml +++ b/config/locales/crowdin/fi.yml @@ -2056,6 +2056,8 @@ fi: dialog: title: "Vie" submit: "Vie" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml index 4f457fa7341..649eeb4e7f6 100644 --- a/config/locales/crowdin/fil.yml +++ b/config/locales/crowdin/fil.yml @@ -2056,6 +2056,8 @@ fil: dialog: title: "I-export" submit: "I-export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index 0366924e2fe..b1da7802691 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -2054,6 +2054,8 @@ fr: dialog: title: "Exporter" submit: "Exporter" + save_export_settings: + label: "Save settings" format: label: "Format de fichier" options: diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml index 436ebc98d66..3c8ab22fae1 100644 --- a/config/locales/crowdin/he.yml +++ b/config/locales/crowdin/he.yml @@ -2134,6 +2134,8 @@ he: dialog: title: "ייצוא" submit: "ייצוא" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml index 36fda1d1e27..4b9ffa1b34e 100644 --- a/config/locales/crowdin/hi.yml +++ b/config/locales/crowdin/hi.yml @@ -2054,6 +2054,8 @@ hi: dialog: title: "निर्यात" submit: "निर्यात" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml index 972aa684322..b152521aed2 100644 --- a/config/locales/crowdin/hr.yml +++ b/config/locales/crowdin/hr.yml @@ -2095,6 +2095,8 @@ hr: dialog: title: "Izvezi" submit: "Izvezi" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml index ec1e8dcc58d..ccae94aa121 100644 --- a/config/locales/crowdin/hu.yml +++ b/config/locales/crowdin/hu.yml @@ -2055,6 +2055,8 @@ hu: dialog: title: "Exportálás" submit: "Exportálás" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml index 601a95e55a7..78539787ded 100644 --- a/config/locales/crowdin/id.yml +++ b/config/locales/crowdin/id.yml @@ -2013,6 +2013,8 @@ id: dialog: title: "Ekspor" submit: "Ekspor" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml index 5460fef8cfe..87add395917 100644 --- a/config/locales/crowdin/it.yml +++ b/config/locales/crowdin/it.yml @@ -2053,6 +2053,8 @@ it: dialog: title: "Esporta" submit: "Esporta" + save_export_settings: + label: "Save settings" format: label: "Formato file" options: diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml index e484afb2f64..890e1816a1e 100644 --- a/config/locales/crowdin/ja.yml +++ b/config/locales/crowdin/ja.yml @@ -2015,6 +2015,8 @@ ja: dialog: title: "外部出力" submit: "外部出力" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/js-pt-PT.yml b/config/locales/crowdin/js-pt-PT.yml index 923c9867d3c..29e5615ec3c 100644 --- a/config/locales/crowdin/js-pt-PT.yml +++ b/config/locales/crowdin/js-pt-PT.yml @@ -365,14 +365,14 @@ pt-PT: ical_sharing_modal: title: "Subscrever o calendário" inital_setup_error_message: "Ocorreu um erro ao recuperar os dados." - description: "Pode utilizar o URL (iCalendar) para subscrever este calendário num cliente externo e visualizar informações atualizadas sobre o pacote de trabalho a partir daí." + description: "Pode utilizar o URL (iCalendar) para subscrever este calendário num cliente externo e ver informações atualizadas sobre o pacote de trabalho a partir daí." warning: "Não partilhe este URL com outros utilizadores. Qualquer pessoa com este link poderá ver os detalhes do pacote de trabalho sem uma conta ou palavra-passe." token_name_label: "Onde irá utilizar isto?" token_name_placeholder: 'Escreva um nome, por exemplo, "Telefone"' token_name_description_text: 'Se subscrever este calendário a partir de vários dispositivos, este nome irá ajudá-lo a distinguir entre eles na sua lista de tokens de acesso.' copy_url_label: "Copiar URL" ical_generation_error_text: "Ocorreu um erro ao gerar o URL do calendário." - success_message: 'O URL "%{name}" foi copiado com sucesso para a área de transferência. Cole-o no seu cliente de calendário para concluir a subscrição.' + success_message: 'O URL "%{name}" foi copiado com sucesso para a área de transferência. Cole-o no seu cliente de Calendários para concluir a subscrição.' label_activate: "Ativar" label_assignee: "Responsável" label_add_column_after: "Adicionar coluna após" @@ -601,7 +601,7 @@ pt-PT: timeline: "Aqui pode editar o seu plano de projeto, criar novos pacotes de trabalho, tais como tarefas, marcos, fases e muito mais, bem como adicionar dependências. Todos os membros da equipa podem ver e atualizar o plano mais recente a qualquer momento." team_planner: overview: "O planeador de equipa permite atribuir tarefas visualmente aos membros da equipa e obter uma visão geral de quem está a trabalhar e no quê (onde)." - calendar: "O quadro de planeamento semanal ou quinzenal exibe todos os pacotes de trabalho atribuídos aos membros de sua equipa." + calendar: "O quadro de planeamento semanal ou quinzenal apresenta todos os pacotes de trabalho atribuídos aos membros da sua equipa." add_assignee: "Para começar, adicione responsáveis ao planeador da equipa." add_existing: "Pesquise pacotes de trabalho existentes e arraste-os para o planeador de equipa para atribuí-los instantaneamente a um membro da equipa e definir as datas de início e término." card: "Arraste os pacotes de trabalho horizontalmente para os mover para trás ou para frente no tempo, arraste as bordas para alterar as datas de início e término, e arraste verticalmente para uma linha diferente para atribuir a outro membro." diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml index 5e42f8b5014..82cb17d882d 100644 --- a/config/locales/crowdin/ka.yml +++ b/config/locales/crowdin/ka.yml @@ -2056,6 +2056,8 @@ ka: dialog: title: "გატანა" submit: "გატანა" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml index 53d3838fd02..f942b2517d3 100644 --- a/config/locales/crowdin/kk.yml +++ b/config/locales/crowdin/kk.yml @@ -2056,6 +2056,8 @@ kk: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml index cda5de2b4d1..a0da7ebd9a1 100644 --- a/config/locales/crowdin/ko.yml +++ b/config/locales/crowdin/ko.yml @@ -2017,6 +2017,8 @@ ko: dialog: title: "내보내기" submit: "내보내기" + save_export_settings: + label: "Save settings" format: label: "파일 형식" options: diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 23d47718ddd..095e5946052 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -2131,6 +2131,8 @@ lt: dialog: title: "Eksportuoti" submit: "Eksportuoti" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml index c8855c2c358..29e7015dd77 100644 --- a/config/locales/crowdin/lv.yml +++ b/config/locales/crowdin/lv.yml @@ -2095,6 +2095,8 @@ lv: dialog: title: "Eksportēt" submit: "Eksportēt" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml index e284c8f70e0..76752b320b6 100644 --- a/config/locales/crowdin/mn.yml +++ b/config/locales/crowdin/mn.yml @@ -2056,6 +2056,8 @@ mn: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml index 63aadcfac11..16fb93e51ea 100644 --- a/config/locales/crowdin/ms.yml +++ b/config/locales/crowdin/ms.yml @@ -2015,6 +2015,8 @@ ms: dialog: title: "Eksport" submit: "Eksport" + save_export_settings: + label: "Save settings" format: label: "Format fail" options: diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml index 89711a57d16..1fcebbd4021 100644 --- a/config/locales/crowdin/ne.yml +++ b/config/locales/crowdin/ne.yml @@ -2056,6 +2056,8 @@ ne: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 9d3ca223141..875d50d255b 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -2052,6 +2052,8 @@ nl: dialog: title: "Exporteren" submit: "Exporteren" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml index abd0ddd6013..9ca3c2f2b1b 100644 --- a/config/locales/crowdin/no.yml +++ b/config/locales/crowdin/no.yml @@ -2055,6 +2055,8 @@ dialog: title: "Eksporter" submit: "Eksporter" + save_export_settings: + label: "Save settings" format: label: "Filformat" options: diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml index 1ea97ccbdfc..e63e07acab6 100644 --- a/config/locales/crowdin/pl.yml +++ b/config/locales/crowdin/pl.yml @@ -2131,6 +2131,8 @@ pl: dialog: title: "Eksport" submit: "Eksportuj" + save_export_settings: + label: "Save settings" format: label: "Format pliku" options: diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml index 6c47fee8388..c144e76b587 100644 --- a/config/locales/crowdin/pt-BR.yml +++ b/config/locales/crowdin/pt-BR.yml @@ -2053,6 +2053,8 @@ pt-BR: dialog: title: "Exportar" submit: "Exportar" + save_export_settings: + label: "Save settings" format: label: "Formato do arquivo" options: diff --git a/config/locales/crowdin/pt-PT.seeders.yml b/config/locales/crowdin/pt-PT.seeders.yml index 11835291fcd..f4a0018e85b 100644 --- a/config/locales/crowdin/pt-PT.seeders.yml +++ b/config/locales/crowdin/pt-PT.seeders.yml @@ -125,7 +125,7 @@ pt-PT: name: Planeador de equipa boards: kanban: - name: Quadro de Kanban + name: Quadro Kanban basic: name: Quadro básico lists: @@ -244,13 +244,13 @@ pt-PT: _Documente aqui os tópicos da reunião de planeamento do Sprint_ * Tempo atribuído (8 h) - * Entrada: Lista de acumulados de produto - * Saída: Lista de acumulados do Sprint + * Entrada: Backlog do produto + * Saída: Backlog do Sprint * Dividido em dois períodos adicionais de 4 h: - * O Proprietário do Produto apresenta a [Lista de acumulados de produto]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e as prioridades para a equipa e explica o Objetivo do Sprint, com o qual a equipa deve concordar. Juntos, dão prioridade aos tópicos da Lista de acumulados de produto que a equipa irá tratar no próximo sprint. A equipa compromete-se com a entrega que foi discutida. - * A equipa planeia autonomamente (sem o Proprietário do Produto) em pormenor e divide as tarefas a partir dos requisitos discutidos para consolidar uma [Lista de acumulados do Sprint]({{opSetting:base_url}}/projects/your-scrum-project/backlogs). + * O Proprietário do Produto apresenta o [Backlog do produto]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e as prioridades à equipa, e explica o objetivo do Sprint, com o qual a equipa deve concordar. Juntos, dão prioridade aos tópicos do backlog de produto que a equipa irá tratar no próximo sprint. A equipa compromete-se com a entrega discutida. + * A equipa planeia autonomamente (sem o Proprietário do Produto) em pormenor, e divide as tarefas a partir dos requisitos discutidos para consolidar um [Backlog do Sprint]({{opSetting:base_url}}/projects/your-scrum-project/backlogs). ### Reunião diária do Scrum @@ -263,7 +263,7 @@ pt-PT: * O que tenciono fazer até à próxima reunião diária do Scrum? * O que é que bloqueou o meu trabalho (Impedimentos)? * O Scrum Master modera e anota [Impedimentos do Sprint](##sprint:scrum_project__version__sprint_1). - * O Proprietário do Produto pode participar para se manter informado. + * O Proprietário do Produto pode participar para se manter a par. ### Reunião de revisão do Sprint @@ -299,7 +299,7 @@ pt-PT: name: Tarefas boards: kanban: - name: Quadro de Kanban + name: Quadro Kanban basic: name: Quadro de tarefas lists: @@ -324,12 +324,12 @@ pt-PT: _Experimente os seguintes passos:_ - 1. *Convidar novos membros para o seu projeto*: → Aceda a [Membros]({{opSetting:base_url}}/projects/your-scrum-project/members) na navegação do projeto. - 2. *Ver o seu repositório de produtos e repositórios de Sprint*: → Aceda a [Repositórios]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) na navegação do projeto. - 3. *Ver o seu quadro de tarefas*: → Aceda a [Repositórios]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) → Clique na seta para a direita em Sprint → Selecione [Quadro de tarefas](##sprint:scrum_project__version__sprint_1). + 1. *Convidar novos membros para o projeto*: → Aceda a [Membros]({{opSetting:base_url}}/projects/your-scrum-project/members) na navegação do projeto. + 2. *Ver o seu backlog de produtos e backlog de sprint*: → Aceda a [Backlogs]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) na navegação do projeto. + 3. *Ver o seu quadro de tarefas*: → Aceda a [Backlogs]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) → Clique na seta para a direita em Sprint → Selecione [Quadro de tarefas](##sprint:scrum_project__version__sprint_1). 4. *Criar um novo pacote de trabalho*: → Aceda a [Pacotes de trabalho → Criar]({{opSetting:base_url}}/projects/your-scrum-project/work_packages/new). 5. *Criar e atualizar um plano de projeto*: → Aceda a [Plano do projeto](##query:scrum_project__query__project_plan) na navegação do projeto. - 6. *Criar uma wiki do Sprint*: → Aceda a [Repositórios]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e abra a wiki do sprint a partir do menu pendente do lado direito num sprint. Pode editar o [modelo da wiki]({{opSetting:base_url}}/projects/your-scrum-project/wiki/) com base nas suas necessidades. + 6. *Criar uma wiki do Sprint*: → Aceda a [Backlogs]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e abra a wiki do sprint a partir do menu pendente do lado direito num sprint. Pode editar o [modelo da wiki]({{opSetting:base_url}}/projects/your-scrum-project/wiki/) mediante as suas necessidades. 7. *Ativar mais módulos*: → Aceda a [Definições do projeto → Módulos]({{opSetting:base_url}}/projects/your-scrum-project/settings/modules). Aqui encontra as nossas [Guias do Utilizador](https://www.openproject.org/docs/user-guide/). @@ -397,13 +397,13 @@ pt-PT: _Documente aqui os tópicos da reunião de planeamento do Sprint_ * Tempo atribuído (8 h) - * Entrada: Lista de acumulados de produto - * Saída: Lista de acumulados do Sprint + * Entrada: Backlog de produto + * Saída: Backlog do Sprint * Dividido em dois períodos adicionais de 4 h: - * O Proprietário do Produto apresenta a [Lista de acumulados de produto]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e as prioridades para a equipa e explica o Objetivo do Sprint, com o qual a equipa deve concordar. Juntos, dão prioridade aos tópicos da Lista de acumulados de produto que a equipa irá tratar no próximo sprint. A equipa compromete-se com a entrega que foi discutida. - * A equipa planeia autonomamente (sem o Proprietário do Produto) em pormenor e divide as tarefas a partir dos requisitos discutidos para consolidar uma [Lista de acumulados do Sprint]({{opSetting:base_url}}/projects/your-scrum-project/backlogs). + * O Proprietário do Produto apresenta ao[Backlog de produto]({{opSetting:base_url}}/projects/your-scrum-project/backlogs) e as prioridades à equipa, e explica o objetivo do Sprint, com o qual a equipa deve concordar. Juntos, dão prioridade aos tópicos do backlog de produto que a equipa irá tratar no próximo sprint. A equipa compromete-se com a entrega discutida. + * A equipa planeia autonomamente (sem o Proprietário do Produto) em pormenor e divide as tarefas a partir dos requisitos discutidos para consolidar um [Backlog do Sprint]({{opSetting:base_url}}/projects/your-scrum-project/backlogs). ### Reunião diária do Scrum diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml index cb64b38d305..9319c670a65 100644 --- a/config/locales/crowdin/pt-PT.yml +++ b/config/locales/crowdin/pt-PT.yml @@ -989,7 +989,7 @@ pt-PT: relation: lag: "Atraso" from: "Pacote de trabalho relacionado" - to: "Tarefas Relacionadas" + to: "Pacote de trabalho relacionado" relation_type: "Tipo de relação" reminder: remindable: "Objeto lembrado" @@ -1003,7 +1003,7 @@ pt-PT: role: permissions: "Permissões" status: - is_closed: "Tarefa fechada" + is_closed: "Pacote de trabalho fechado" is_readonly: "Pacote de trabalho só de leitura" excluded_from_totals: "Excluir do cálculo dos totais na hierarquia" default_done_ratio: "% de conclusão" @@ -1019,7 +1019,7 @@ pt-PT: type: description: "Texto padrão para a descrição" attribute_groups: "" - is_in_roadmap: "Exibido no roteiro por padrão" + is_in_roadmap: "Apresentado no roteiro por defeito" is_default: "Ativado para novos projetos por padrão" is_milestone: "É um marco" color: "Cor" @@ -1505,7 +1505,7 @@ pt-PT: role: one: "Função" other: "Papel" - status: "Estado da tarefa" + status: "Estado do pacote de trabalho" token/api: one: Token de acesso other: Tokens de acesso @@ -1953,9 +1953,9 @@ pt-PT: description_query_sort_criteria_attribute: "Ordenar por atributo" description_query_sort_criteria_direction: "Direção da ordenação" description_search: "Campo de pesquisa" - description_select_work_package: "Selecione tarefa" + description_select_work_package: "Selecionar pacote de trabalho" description_selected_columns: "Colunas selecionadas" - description_sub_work_package: "Sub-tarefa de trabalho de actual" + description_sub_work_package: "Sub-pacote de trabalho do atual" description_toc_toggle: "Mostrar/ocultar a tabela de conteúdos" description_wiki_subpages_reassign: "Escolha a nova página do pai" #Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) @@ -1973,7 +1973,7 @@ pt-PT: add_groups: "Adicionar novos grupos de atributos" rename_groups: "Mudar o nome de grupos de atributos" enumeration_activities: "Atividades de controlo de tempo" - enumeration_work_package_priorities: "Prioridades de tarefas" + enumeration_work_package_priorities: "Prioridades do pacote de trabalho" enumeration_reported_project_statuses: "Estado do projeto reportado" enumeration_caption_order_changed: "Ordem alterada com sucesso." enumeration_could_not_be_moved: "A enumeração não pode ser movida." @@ -1988,7 +1988,7 @@ pt-PT: error_can_not_delete_standard_type: "Tipos de padrão não podem ser eliminados." error_can_not_invite_user: "Falha no envio do convite ao utilizador." error_can_not_remove_role: "Esta função já está a ser utilizada e não pode ser eliminada." - error_can_not_reopen_work_package_on_closed_version: "Uma tarefa atribuída a uma versão fechada não pode ser reaberta" + error_can_not_reopen_work_package_on_closed_version: "Um pacote de trabalho atribuído a uma versão fechada não pode ser reaberto" error_can_not_find_all_resources: "Não foi possível encontrar todos os recursos relacionados a esta solicitação." error_can_not_unarchive_project: "Este projeto não pode ser desarquivado: %{errors}" error_check_user_and_role: "Por favor, escolha um utilizador e uma função." @@ -2007,7 +2007,7 @@ pt-PT: error_pdf_failed_to_export: "Não foi possível guardar a exportação de PDF: %{error}" error_token_authenticity: "Não é possível verificar o token de Cross-Site Request Forgery. Tentou enviar dados em vários navegadores ou abas? Feche todas as abas e tente novamente." error_reminder_not_found: "O lembrete não foi encontrado ou já foi notificado." - error_work_package_not_found_in_project: "A tarefa não foi encontrada ou não pertence a este projecto" + error_work_package_not_found_in_project: "O pacote de trabalho não foi encontrado ou não pertence a este projeto" error_work_package_id_not_found: "O pacote de trabalho não foi encontrado." error_must_be_project_member: "deve ser membro do projeto" error_migrations_are_pending: "A sua instalação do OpenProject tem migrações pendentes da base de dados pendentes. Provavelmente esqueceu-se de fazer as migrações após a última atualização. Por favor, verifique o guia de atualização, de forma a atualizar a sua instalação corretamente." @@ -2020,7 +2020,7 @@ pt-PT: error_scm_command_failed: "Ocorreu um erro ao tentar aceder ao repositório: %{value}" error_scm_not_found: "A entrada ou a revisão não foi encontrado no repositório." error_type_could_not_be_saved: "Não foi possível guardar o tipo" - error_unable_delete_status: "O estado de tarefas não pode ser eliminado, pois ele é utilizado pelo menos por uma tarefa." + error_unable_delete_status: "O estado do pacote de trabalho não pode ser eliminado, visto que é utilizado por pelo menos um pacote de trabalho." error_unable_delete_default_status: "Não foi possível apagar o estado por defeito do pacote de trabalho. Por favor selecione outro estado de pacote de trabalho antes de apagar o atual." error_unable_to_connect: "Não é possível ligar (%{value})" error_unable_delete_wiki: "Não é possível eliminar a página wiki." @@ -2043,9 +2043,9 @@ pt-PT: reply: Respondeu time_entry: "Timelog editado" wiki_page: "Página wiki editada" - work_package_closed: "Tarefa fechada" - work_package_edit: "Tarefa editada" - work_package_note: "Nota da tarefa adicionada" + work_package_closed: "Pacote de trabalho fechado" + work_package_edit: "Pacote de trabalho editado" + work_package_note: "Nota de pacote de trabalho adicionada" title: project: "Projeto: %{name}" subproject: "Subprojeto: %{name}" @@ -2053,6 +2053,8 @@ pt-PT: dialog: title: "Exportar" submit: "Exportar" + save_export_settings: + label: "Save settings" format: label: "Formato do ficheiro" options: @@ -2291,7 +2293,7 @@ pt-PT: title: "iCalendar" text_hint: 'Os tokens iCalendar permitem aos utilizadores subscrever calendários do OpenProject e visualizar informações atualizadas sobre pacotes de trabalho de clientes externos.' disabled_text: "As subscrições do iCalendar não são ativadas pelo administrador. Contacte o seu administrador para utilizar esta funcionalidade." - empty_text_hint: "Para adicionar um token do iCalendar, subscreva um calendário novo ou já existente a partir do módulo Calendário de um projeto. Tem de ter as permissões necessárias." + empty_text_hint: "Para adicionar um token do iCalendar, subscreva um calendário novo ou já existente a partir do módulo Calendários de um projeto. Tem de ter as permissões necessárias." oauth: title: "OAuth" text_hint: "Os tokens de OAuth permitem que as aplicações externas se liguem a esta instância do OpenProject." @@ -2347,7 +2349,7 @@ pt-PT: label_add_columns: "Adicionar colunas selecionadas" label_add_note: "Adicionar uma nota" label_add_projects: "Adicionar projetos" - label_add_related_work_packages: "Adicionar tarefas relacionada" + label_add_related_work_packages: "Adicionar pacotes de trabalho relacionados" label_add_subtask: "Adicionar subtarefa" label_added: "adicionado" label_added_by: "Adicionado por %{author}" @@ -2380,7 +2382,7 @@ pt-PT: label_applied_status: "Status aplicado" label_archive_project: "Arquivar projeto" label_ascending: "Ascendente" - label_assigned_to_me_work_packages: "Tarefas atribuídas a mim" + label_assigned_to_me_work_packages: "Pacotes de trabalho atribuídos a mim" label_associated_revisions: "Revisões associadas" label_attachment_plural: "Anexos" label_attribute: "Atributo" @@ -2416,11 +2418,11 @@ pt-PT: label_board_plural: "Quadros" label_branch: "Ramo" label_browse: "Navegador" - label_bulk_edit_selected_work_packages: "Editar tarefas selecionadas de seguida" + label_bulk_edit_selected_work_packages: "Edição em massa de pacotes de trabalho selecionados" label_bundled: "(Empacotado)" - label_calendar: "Calendário" + label_calendar: "Calendários" label_calendars_and_dates: "Calendários e datas" - label_calendar_show: "Mostrar calendário" + label_calendar_show: "Mostrar Calendários" label_category: "Categoria" label_completed: Concluído label_consent_settings: "Consentimento do utilizador" @@ -2496,7 +2498,7 @@ pt-PT: label_descending: "Descendente" label_details: "Detalhes" label_defaults: "Predefinições" - label_development_roadmap: "Mapa de Desenvolvimento" + label_development_roadmap: "Roteiro de desenvolvimento" label_diff: "diff" label_diff_inline: "em linha" label_diff_side_by_side: "lado a lado" @@ -2579,7 +2581,7 @@ pt-PT: label_hierarchy_leaf: "Folha da hierarquia" label_home: "Início" label_subject_or_id: "ID ou Assunto" - label_calendar_subscriptions: "Subscrições do calendário" + label_calendar_subscriptions: "Subscrições de Calendários" label_identifier: "Identificador" label_in: "em" label_in_less_than: "em menos de" @@ -2678,7 +2680,7 @@ pt-PT: label_more_than_ago: "mais do que dias atrás" label_move_column_left: "Mover coluna esquerda" label_move_column_right: "Mover a coluna direita" - label_move_work_package: "Mover tarefa" + label_move_work_package: "Mover pacote de trabalho" label_my_account: "Definições da conta" label_my_activity: "A minha atividade" label_my_account_data: "Dados da minha conta" @@ -2795,7 +2797,7 @@ pt-PT: label_registration_activation_by_email: "ativação de conta por e-mail" label_registration_automatic_activation: "ativação automática de conta" label_registration_manual_activation: "ativação manual de conta" - label_related_work_packages: "Tarefas relacionados" + label_related_work_packages: "Pacotes de trabalho relacionados" label_relates: "relacionado com" label_relates_to: "relacionado com" label_relation: "Relação" @@ -2812,7 +2814,7 @@ pt-PT: label_report: "Relatório" label_report_bug: "Reportar um erro" label_report_plural: "Relatórios" - label_reported_work_packages: "Relatório de tarefas" + label_reported_work_packages: "Pacotes de trabalho reportados" label_reporting: "A reportar" label_reporting_plural: "Comunicações" label_repository: "Repositório" @@ -2825,9 +2827,9 @@ pt-PT: label_revision: "Revisão" label_revision_id: "Revisão %{value}" label_revision_plural: "Revisões" - label_roadmap: "Planificação" - label_roadmap_edit: "Editar planificação %{name}" - label_roadmap_due_in: "%{value} devido" + label_roadmap: "Roteiro" + label_roadmap_edit: "Editar roteiro %{name}" + label_roadmap_due_in: "Entrega em %{value}" label_roadmap_no_work_packages: "Não há pacotes de trabalho para esta versão" label_roadmap_overdue: "%{value} atrasado" label_role_and_permissions: "Funções e permissões" @@ -2955,17 +2957,17 @@ pt-PT: label_work_package: "Pacote de trabalho" label_work_package_attachments: "Anexos do pacote de trabalho" label_work_package_category_new: "Nova categoria" - label_work_package_category_plural: "Categorias de tarefas" + label_work_package_category_plural: "Categorias de pacotes de trabalho" label_work_package_hierarchy: "Hierarquia de pacotes de trabalho" - label_work_package_new: "Nova tarefa" + label_work_package_new: "Novo pacote de trabalho" label_work_package_edit: "Editar pacote de trabalho %{name}" - label_work_package_plural: "Tarefas" + label_work_package_plural: "Pacotes de trabalho" label_work_package_status: "Estado da tarefa" label_work_package_status_new: "Novo estado" - label_work_package_status_plural: "Estado da tarefa" + label_work_package_status_plural: "Estados dos pacotes de trabalho" label_work_package_types: "Tipos de pacote de trabalho" label_work_package_tracking: "Controle de pacote de trabalho" - label_work_package_view_all: "Ver todas as tarefas" + label_work_package_view_all: "Ver todos os pacotes de trabalho" label_workflow: "Fluxo de trabalho" label_workflow_copy: "Copiar fluxo de trabalho" label_workflow_plural: "Fluxos de Trabalho" @@ -3272,7 +3274,7 @@ pt-PT: welcome: "Bem-vindo ao %{app_title}" select_language: "Selecione o seu idioma" permission_add_work_package_notes: "Adicionar comentários" - permission_add_work_packages: "Adicionar tarefas" + permission_add_work_packages: "Adicionar pacotes de trabalho" permission_add_messages: "Publicar mensagens" permission_add_project: "Criar projetos" permission_add_work_package_attachments: "Adicionar anexos" @@ -3285,17 +3287,17 @@ pt-PT: permission_add_subprojects: "Criar subprojetos" permission_add_work_package_watchers: "Adicionar observadores" permission_assign_versions: "Atribuir versões" - permission_browse_repository: "Acesso somente de leitura ao repositório (browse e check-out)" + permission_browse_repository: "Acesso só de leitura ao repositório (navegar e fazer checkout)" permission_change_wiki_parent_page: "Alterar a página wiki fonte" permission_change_work_package_status: "Altere o estado do pacote de trabalho" permission_change_work_package_status_explanation: "Permite alterar o estado sem permissão de edição de pacotes de trabalho" permission_comment_news: "Comentar notícias" - permission_commit_access: "Acesso de leitura/gravação para o repositório (confirmação)" + permission_commit_access: "Acesso de leitura/escrita ao repositório (comprometer)" permission_copy_projects: "Copiar projeto" permission_copy_work_packages: "Copiar pacotes de trabalho" permission_create_backup: "Criar cópias de segurança" permission_delete_work_package_watchers: "Eliminar observador" - permission_delete_work_packages: "Eliminar tarefas" + permission_delete_work_packages: "Eliminar pacotes de trabalho" permission_delete_messages: "Eliminar mensagens" permission_delete_own_messages: "Eliminar as próprias mensagens" permission_delete_reportings: "Eliminar comunicações" @@ -3304,7 +3306,7 @@ pt-PT: permission_delete_wiki_pages_attachments: "Eliminar anexos" permission_edit_work_package_notes: "Moderar comentários" permission_edit_work_package_notes_explanation: "Atenção: os utilizadores com esta permissão podem editar os comentários de qualquer pessoa." - permission_edit_work_packages: "Editar tarefas" + permission_edit_work_packages: "Editar pacotes de trabalho" permission_edit_messages: "Editar mensagens" permission_edit_own_comments_with_restricted_visibility: "Edit own comments with restricted visibility" permission_edit_own_work_package_notes: "Editar os próprios comentários" @@ -3327,7 +3329,7 @@ pt-PT: permission_manage_forums: "Gerir fóruns" permission_manage_categories: "Gerir categorias de pacote de trabalho" permission_manage_dashboards: "Gerenciar painéis" - permission_manage_work_package_relations: "Gerir relações entre tarefas" + permission_manage_work_package_relations: "Gerir as relações entre os pacotes de trabalho" permission_manage_members: "Gerir Membros" permission_manage_news: "Gerir noticias" permission_manage_project_activities: "Gerir atividades do projeto" @@ -3337,7 +3339,7 @@ pt-PT: permission_manage_versions: "Gerir versões" permission_manage_wiki: "Gerir wiki" permission_manage_wiki_menu: "Gerir menu da wiki" - permission_move_work_packages: "Mover tarefa" + permission_move_work_packages: "Mover pacotes de trabalho" permission_protect_wiki_pages: "Proteger páginas da wiki" permission_rename_wiki_pages: "Renomear páginas da wiki" permission_save_queries: "Guardar visualizações" @@ -3401,7 +3403,7 @@ pt-PT: project_phase_any: "Project phase: Any" project_phase_gate: "Project phase gate: %{gate}" identifier: - warning_one: Os membros do projeto terão de realocar os repositórios do projeto. + warning_one: Os membros do projeto terão de relocalizar os repositórios do projeto. warning_two: Os links existentes para o projeto já não funcionarão. title: Alterar o identificador do projeto not_available: "Projeto N/A" @@ -3521,16 +3523,16 @@ pt-PT: setup_documentation_details_link_text: "Definição de armazenamentos" show_warning_details: "Para usar esse armazenamento de ficheiros, lembre-se de ativar o módulo e o armazenamento específico nas definições do projeto de cada projeto desejado." subversion: - existing_title: "Repositório de subversão existente" - existing_introduction: "Se tem um repositório de Subversion existente, pode vinculá-lo com o OpenProject para aceder a ele dentro da aplicação." + existing_title: "Repositório Subversion existente" + existing_introduction: "Se tiver um repositório Subversion existente, pode ligá-lo ao OpenProject para aceder ao mesmo a partir da aplicação." existing_url: "URL existente" instructions: managed_url: "Esta é a URL do repositório Subversion (local) gerido." url: "Digite a URL do repositório. Isto também pode direcionar um repositório local (começando com %{local_proto}), ou um repositório remoto. São suportados os seguintes esquemas de URL:" managed_title: "Repositório Subversion integrado no OpenProject" - managed_introduction: "Deixe o OpenProject criar e integrar um repositório Subversion local automaticamente." + managed_introduction: "Permita que o OpenProject crie e integre automaticamente um repositório Subversion local." managed_url: "Gerir URL" - password: "Senha do Repositório" + password: "Palavra-passe do repositório" username: "Nome do utilizador do repositório" truncated: "Pedimos desculpa, mas tivemos que truncar este diretório para ficheiros %{limit}. Entradas %{truncated} foram omitidas da lista." named_repository: "%{vendor_name} repositório" @@ -3640,7 +3642,7 @@ pt-PT: Cada estado tem um valor de % de conclusão associado. A alteração do estado altera a % de conclusão. setting_work_package_done_ratio_explanation_html: > No modo baseado no trabalho, a % de conclusão pode ser definida livremente para qualquer valor. Se, opcionalmente, introduzir um valor para Trabalho, o Trabalho restante será automaticamente derivado. No modo baseado no estado, cada estado tem um valor de % de conclusão associado. A alteração do estado altera a % de conclusão. - setting_work_package_properties: "Propriedades das tarefas" + setting_work_package_properties: "Propriedades do pacote de trabalho" setting_work_package_startdate_is_adddate: "Utilizar a data atual como data de início para novos pacotes de trabalho" setting_work_packages_projects_export_limit: "Pacotes de trabalho / limite de exportação de projetos" setting_journal_aggregation_time_minutes: "Ações do utilizador agregadas em" @@ -3685,7 +3687,7 @@ pt-PT: setting_session_ttl_hint: "Valor abaixo de 5 trabalhos como desativado" setting_session_ttl_enabled: "A Sessão expirou" setting_start_of_week: "A semana começa a" - setting_sys_api_enabled: "Habilitar o serviço web de gestão do repositório" + setting_sys_api_enabled: "Ativar o serviço web de gestão de repositórios" setting_sys_api_description: "O serviço de web de gestão de repositório fornece integração e autorização ao utilizador para aceder a repositórios." setting_time_format: "Tempo" setting_total_percent_complete_mode: "Cálculo dos totais da hierarquia da % de conclusão" @@ -3756,7 +3758,7 @@ pt-PT: type: "Linha inteira por tipo" priority: "Linha inteira por prioridade" icalendar: - enable_subscriptions_text_html: Permite que os utilizadores com as permissões necessárias subscrevam os calendários do OpenProject e acedam às informações do pacote de trabalho através de um cliente de calendário externo.Nota: leia sobre as subscrições do iCalendar para entender os possíveis riscos de segurança antes de ativar esta opção. + enable_subscriptions_text_html: Permite que os utilizadores com as permissões necessárias subscrevam os calendários do OpenProject e acedam às informações do pacote de trabalho através de um cliente de Calendários externo.Nota: leia sobre as subscrições do iCalendar para entender os possíveis riscos de segurança antes de ativar esta opção. language_name_being_default: "%{language_name} (padrão)" notifications: events_explanation: "Determina o evento sobre o qual é enviado um e-mail. Os pacotes de trabalho são eliminados desta lista uma vez que as notificações sobre eles podem ser configuradas especificamente para todos os utilizadores." @@ -3878,7 +3880,7 @@ pt-PT: text_hours_between: "Entre %{min} e %{max} horas." text_work_package_added: "O pacote de trabalho %{id} foi reportado por %{author}." text_work_package_category_destroy_assignments: "Remover atribuições da categoria" - text_work_package_category_destroy_question: "Algumas tarefas (%{count}) estão atribuídas a esta categoria. O que é que quer fazer?" + text_work_package_category_destroy_question: "Alguns pacotes de trabalho (%{count}) estão atribuídos a esta categoria. O que quer fazer?" text_work_package_category_reassign_to: "Reatribuir pacotes de trabalho para esta categoria" text_work_package_updated: "O pacote de trabalho %{id} foi atualizado por %{author}." text_work_package_watcher_added: "Foi adicionado como observador do pacote de trabalho %{id} por %{watcher_changer}." @@ -4058,7 +4060,7 @@ pt-PT: #TODO: merge with work_packages top level key work_package: updated_automatically_by_child_changes: | - _Atualizado automaticamente através da alteração de valor na tarefa %{child}_ + _Atualizado automaticamente através da alteração de valores no pacote de trabalho filho %{child}_ destroy: info: "Apagar o pacote de trabalho é uma ação irreversível." title: "Eliminar o pacote de trabalho" @@ -4224,8 +4226,8 @@ pt-PT: context_object_not_found: "Não é possível encontrar o recurso dado como contexto." validation: due_date: "Data de término não pode ser definida em pacotes de trabalho pai." - invalid_user_assigned_to_work_package: "O utilizador escolhido não pode ser '%{property}' para esta tarefa." - start_date: "Data de início não pode ser definida em tarefas do pai." + invalid_user_assigned_to_work_package: "O utilizador escolhido não pode ser \"%{property}\" para este pacote de trabalho." + start_date: "A data de início não pode ser definida nos pacotes de trabalho principais." eprops: invalid_gzip: "é gzip inválido: %{message}" invalid_json: "é json inválido: %{message}" @@ -4269,7 +4271,7 @@ pt-PT: expired: "O token de acesso expirou" unknown: "O token de acesso é inválido" revoke: - unauthorized: "Não está autorizado a executar esta tarefa" + unauthorized: "Não tem autorização para revogar este token." forbidden_token: missing_scope: 'O acesso a este recurso requer o escopo "%{oauth_scopes}".' unsupported_browser: diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index b9f12d57641..9985cf53725 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -2095,6 +2095,8 @@ ro: dialog: title: "Exportă" submit: "Exportă" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml index 3183fe670b3..6d39556681a 100644 --- a/config/locales/crowdin/ru.yml +++ b/config/locales/crowdin/ru.yml @@ -2132,6 +2132,8 @@ ru: dialog: title: "Экспорт" submit: "Экспорт" + save_export_settings: + label: "Save settings" format: label: "Формат файла" options: @@ -3734,7 +3736,7 @@ ru: setting_mail_handler_body_delimiters: "Усечение сообщений после одной из этих линий" setting_mail_handler_body_delimiter_regex: "Сообщение усекается по этому регулярному выражению" setting_mail_handler_ignore_filenames: "Игнорируемые вложения почты" - setting_new_project_user_role_id: "Роль, назначаемая пользователю-создателю проекта" + setting_new_project_user_role_id: "Роль, назначаемая пользователю-создателю проекта, не являющемуся администратором" setting_password_active_rules: "Активные классы символов" setting_password_count_former_banned: "Количество паролей, запрещенных для повторного использования" setting_password_days_valid: "Количество дней, после которого требуется смена пароля" diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml index 3f4a19a1312..5474bf78409 100644 --- a/config/locales/crowdin/rw.yml +++ b/config/locales/crowdin/rw.yml @@ -2056,6 +2056,8 @@ rw: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml index b2bdb30d13e..9a8d5bef692 100644 --- a/config/locales/crowdin/si.yml +++ b/config/locales/crowdin/si.yml @@ -2056,6 +2056,8 @@ si: dialog: title: "අපනයන" submit: "අපනයන" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml index a19e342193c..32ec85e87ce 100644 --- a/config/locales/crowdin/sk.yml +++ b/config/locales/crowdin/sk.yml @@ -2134,6 +2134,8 @@ sk: dialog: title: "Exportovať" submit: "Exportovať" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml index 7bab0e046c9..6a318977d71 100644 --- a/config/locales/crowdin/sl.yml +++ b/config/locales/crowdin/sl.yml @@ -2133,6 +2133,8 @@ sl: dialog: title: "Izvozi" submit: "Izvozi" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml index e0e06a817ea..6e8c9e97455 100644 --- a/config/locales/crowdin/sr.yml +++ b/config/locales/crowdin/sr.yml @@ -2095,6 +2095,8 @@ sr: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml index fdfc62c4de3..986784f24da 100644 --- a/config/locales/crowdin/sv.yml +++ b/config/locales/crowdin/sv.yml @@ -2056,6 +2056,8 @@ sv: dialog: title: "Exportera" submit: "Exportera" + save_export_settings: + label: "Save settings" format: label: "Filformat" options: diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml index ecacf5c5b52..b25c09881b5 100644 --- a/config/locales/crowdin/th.yml +++ b/config/locales/crowdin/th.yml @@ -2017,6 +2017,8 @@ th: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml index 29f1040ab3e..0fb956f1532 100644 --- a/config/locales/crowdin/tr.yml +++ b/config/locales/crowdin/tr.yml @@ -2055,6 +2055,8 @@ tr: dialog: title: "Dışarı aktar" submit: "Dışarı aktar" + save_export_settings: + label: "Save settings" format: label: "Dosya biçimi" options: diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml index 1dd81cd064c..b22ae671340 100644 --- a/config/locales/crowdin/uk.yml +++ b/config/locales/crowdin/uk.yml @@ -2128,6 +2128,8 @@ uk: dialog: title: "Експорт" submit: "Експортувати" + save_export_settings: + label: "Save settings" format: label: "Формат файлу" options: diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml index 78acbe4b27e..a448d0d310d 100644 --- a/config/locales/crowdin/uz.yml +++ b/config/locales/crowdin/uz.yml @@ -2056,6 +2056,8 @@ uz: dialog: title: "Export" submit: "Export" + save_export_settings: + label: "Save settings" format: label: "File format" options: diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml index 1a6f82181ea..09c21145ebe 100644 --- a/config/locales/crowdin/vi.yml +++ b/config/locales/crowdin/vi.yml @@ -2017,6 +2017,8 @@ vi: dialog: title: "Xuất" submit: "Xuất" + save_export_settings: + label: "Save settings" format: label: "Định dạng tệp tin" options: diff --git a/config/locales/crowdin/zh-CN.seeders.yml b/config/locales/crowdin/zh-CN.seeders.yml index a52df5e5edc..c36cab226be 100644 --- a/config/locales/crowdin/zh-CN.seeders.yml +++ b/config/locales/crowdin/zh-CN.seeders.yml @@ -36,13 +36,13 @@ zh-CN: name: 黑色 project_phase_colors: item_0: - name: PM2 Orange + name: PM2 橙 item_1: - name: PM2 Red + name: PM2 红 item_2: - name: PM2 Magenta + name: PM2 品红 item_3: - name: PM2 Green Yellow + name: PM2 绿黄 document_categories: item_0: name: 文档 @@ -81,16 +81,16 @@ zh-CN: standard: project_phases: item_0: - name: Initiating + name: 启动中 item_1: - name: Planning - start_gate: Ready for Planning + name: 计划中 + start_gate: 准备计划 item_2: - name: Executing - start_gate: Ready for Executing + name: 执行中 + start_gate: 准备执行 item_3: - name: Closing - start_gate: Ready for Closing + name: 关闭中 + start_gate: 准备关闭 priorities: item_0: name: 低 @@ -484,7 +484,7 @@ zh-CN: item_1: name: 里程碑 item_2: - name: Summary task + name: 摘要任务 item_3: name: 功能 item_4: diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml index 0bb620df656..850edd509e7 100644 --- a/config/locales/crowdin/zh-CN.yml +++ b/config/locales/crowdin/zh-CN.yml @@ -366,14 +366,14 @@ zh-CN: no_results_title_text: 目前没有可用的自定义字段。 life_cycle: header: - title: "Project life cycle" - description_html: "The active project phases define this project's life cycle and are defined in the administration settings. Enabled phases will be displayed in your project overview." - non_defined: "No phases are currently defined." - section_header: "Phases" + title: "项目生命周期" + description_html: "活动项目阶段定义此项目的生命周期,并在管理设置。已启用的阶段将显示在您的 项目概述中。" + non_defined: "当前没有定义阶段。" + section_header: "阶段" step: use_in_project: "在此项目中使用 %{step}" filter: - label: "Search project phase" + label: "搜索项目阶段" project_custom_fields: header: title: "项目属性" @@ -400,7 +400,7 @@ zh-CN: new_label: "新优先级" project_phase: working_days_count: - other: "Duration: %{count} working days" + other: "时长: %{count} 个工作日" lists: create: success: "已将修改后的列表保存为新列表" @@ -942,15 +942,15 @@ zh-CN: is_required: "在所有项目中应用" custom_field_section: 单元 project/phase: - date_range: "Date range" - definition: "Definition" + date_range: "日期范围" + definition: "定义" project/phase_definition: - name: "Name" - color: "Color" - start_gate: "Start phase gate" - start_gate_name: "Start phase gate name" - finish_gate: "Finish phase gate" - finish_gate_name: "Finish phase gate name" + name: "名称" + color: "颜色" + start_gate: "开始阶段关口" + start_gate_name: "开始阶段关口名称" + finish_gate: "结束阶段关口" + finish_gate_name: "结束阶段关口名称" query: sums: "总和" columns: "列" @@ -1254,9 +1254,9 @@ zh-CN: project/phase: attributes: date_range: - start_date_must_be_before_finish_date: "start date must be before the finish date." - non_continuous_dates: "can't be earlier than the previous phase's end date." - incomplete: "is incomplete." + start_date_must_be_before_finish_date: "开始日期必须早于结束日期。" + non_continuous_dates: "不能早于上一阶段的结束日期。" + incomplete: "不完整。" query: attributes: project: @@ -1540,13 +1540,13 @@ zh-CN: wiki_edit: "维基" work_package: "工作包" project_phase: - activated: "activated" - deactivated: "deactivated" - added_date: "set to %{date}" - changed_date: "changed from %{from} to %{to}" - removed_date: "date deleted %{date}" - phase_and_one_gate: "%{phase_message}. %{gate_message}" - phase_and_both_gates: "%{phase_message}. %{start_gate_message}, and %{finish_gate_message}" + activated: "已激活" + deactivated: "已停用" + added_date: "设为 %{date}" + changed_date: "由 %{from} 变更为 %{to}" + removed_date: "删除日期%{date}" + phase_and_one_gate: "%{phase_message}。%{gate_message}" + phase_and_both_gates: "%{phase_message}。%{start_gate_message},和%{finish_gate_message}" #common attributes of all models attributes: active: "激活" @@ -1927,7 +1927,7 @@ zh-CN: automatic_subject_generation: description: "使用引用的属性和文本自动生成主题。" customize_life_cycle: - description: "Create and organize different project phases than the ones provided by PM2 project cycle planning." + description: "创建和组织与PM2项目周期规划不同的项目阶段。" form_configuration: description: "使用以下附加组件自定义表单配置:" add_groups: "添加新属性组" @@ -2013,6 +2013,8 @@ zh-CN: dialog: title: "导出" submit: "导出" + save_export_settings: + label: "Save settings" format: label: "文件格式" options: @@ -2672,7 +2674,7 @@ zh-CN: label_none_parentheses: "(无)" label_not_contains: "不包含" label_not_equals: "不是" - label_life_cycle_step_plural: "Project life cycle" + label_life_cycle_step_plural: "项目生命周期" label_on: "于" label_operator_all: "不为空" label_operator_none: "为空" @@ -2734,7 +2736,7 @@ zh-CN: label_project_new: "新的项目" label_project_plural: "项目" label_project_list_plural: "项目列表" - label_project_life_cycle: "Project life cycle" + label_project_life_cycle: "项目生命周期" label_project_attributes_plural: "项目属性" label_project_custom_field_plural: "项目属性" label_project_settings: "项目设置" @@ -3270,7 +3272,7 @@ zh-CN: permission_edit_others_comments_with_restricted_visibility_explanation: "注意:具有此权限的用户能够编辑其他用户的可见性受限的评论。" permission_edit_project: "编辑项目" permission_edit_project_attributes: "编辑项目属性" - permission_edit_project_phases: "Edit project phases" + permission_edit_project_phases: "编辑项目阶段" permission_edit_reportings: "编辑报告" permission_edit_time_entries: "编辑其他用户的时间日志" permission_edit_timelines: "编辑时间线" @@ -3300,8 +3302,8 @@ zh-CN: permission_search_project: "搜索项目" permission_select_custom_fields: "选择自定义字段" permission_select_project_custom_fields: "选择项目属性" - permission_select_project_phases: "Select project phases" - permission_select_project_phases_explanation: "Activate/Deactivate the phases in a project. Enables the user to select the life cycle appropriate for the project as inactive phases will not be visible in the project overview page nor the project list." + permission_select_project_phases: "选择项目阶段" + permission_select_project_phases_explanation: "激活/停用项目中的阶段。允许户选择适合项目的生命周期,因为非激活的阶段在项目概览页或项目列表中都不可见。" permission_select_project_modules: "选择项目模块" permission_share_work_packages: "共享工作包" permission_manage_types: "选择类型" @@ -3327,7 +3329,7 @@ zh-CN: permission_work_package_assigned_explanation: "工作包可以分配给在各自项目中拥有此角色的用户和组" permission_view_project_activity: "查看项目活动" permission_view_project_attributes: "查看项目属性" - permission_view_project_phases: "View project phases" + permission_view_project_phases: "查看项目阶段" permission_save_bcf_queries: "保存 BCF 查询" permission_manage_public_bcf_queries: "管理公开的 BCF 查询" permission_edit_attribute_help_texts: "编辑属性帮助文本" @@ -3353,9 +3355,9 @@ zh-CN: subprojects_confirmation: "其 子项目(s): %{value} 也将被删除。" title: "删除项目 %{name}" filters: - project_phase: "Project phase: %{phase}" - project_phase_any: "Project phase: Any" - project_phase_gate: "Project phase gate: %{gate}" + project_phase: "项目阶段:%{phase}" + project_phase_any: "项目阶段:任何阶段" + project_phase_gate: "项目阶段关口:%{gate}" identifier: warning_one: 项目的成员将重新迁移至项目的存储库。 warning_two: 该项目的现有链接将不再有效。 @@ -3734,26 +3736,26 @@ zh-CN: heading: "新建属性" description: "对该项目属性的更改将反映在启用该属性的所有项目中。不能按项目禁用必填属性。" project_phase_definitions: - heading: "Project life cycle" - heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." - label_add: "Add" - label_add_description: "Add life cycle definition" + heading: "项目生命周期" + heading_description: "项目生命周期定义了可以用于您的项目规划并将出现在每个项目的概览页面中的项目阶段。 这些属性可以启用或禁用,但不能在项目一级重新排序。" + label_add: "添加" + label_add_description: "添加生命周期定义" filter: - label: "Search project phase" - section_header: "Phases" - non_defined: "No phases are currently defined." - phase_gates: "Phase gates" + label: "搜索项目阶段" + section_header: "阶段" + non_defined: "当前没有定义阶段。" + phase_gates: "阶段关口" new: - description: "Changes to this project phase will be reflected in all projects where it is enabled." - heading: "New Phase" + description: "对此项目阶段的更改将反映在所有启用的项目中。" + heading: "新阶段" edit: - heading: "Edit Phase" - both_gate: "Start and finish gate" - no_gate: "No gate" - start_gate: "Start gate" - start_gate_caption: "Add a gate with the start date of the phase" - finish_gate: "Finish gate" - finish_gate_caption: "Add a gate with the end date of the phase" + heading: "编辑阶段" + both_gate: "开始和结束关口" + no_gate: "无关口" + start_gate: "开始关口" + start_gate_caption: "添加一个带有阶段开始日期的关口" + finish_gate: "结束关口" + finish_gate_caption: "添加一个带有阶段结束日期的关口" projects: missing_dependencies: "已检查依赖于 %{dependencies} 的项目模块 %{module}。您也需要检查这些依赖项。" section_new_projects: "新项目的设置" @@ -3789,7 +3791,7 @@ zh-CN: text_are_you_sure_continue: "确定要继续吗?" text_are_you_sure_with_children: "删除工作包和所有子工作包吗?" text_are_you_sure_with_project_custom_fields: "删除该属性也会删除其在所有项目中的值。您确定要这样做吗?" - text_are_you_sure_with_project_life_cycle_step: "Deleting this phase will also delete its usages in all projects. Are you sure you want to do this?" + text_are_you_sure_with_project_life_cycle_step: "删除这个阶段也会删除它在所有项目中的使用。您确定要这样做吗?" text_assign_to_project: "分配给项目" text_form_configuration: > 您可以自定义哪些字段将显示在工作包窗体中。您可以自由地对字段进行分组, 以反映您的域的需求。 diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 0a4c74af187..577de55cd58 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -2015,6 +2015,8 @@ zh-TW: dialog: title: "匯出" submit: "匯出" + save_export_settings: + label: "Save settings" format: label: "檔案格式" options: diff --git a/modules/backlogs/config/locales/crowdin/pt-PT.yml b/modules/backlogs/config/locales/crowdin/pt-PT.yml index b28a6104aa6..cd0c9ea12d1 100644 --- a/modules/backlogs/config/locales/crowdin/pt-PT.yml +++ b/modules/backlogs/config/locales/crowdin/pt-PT.yml @@ -21,14 +21,14 @@ #++ pt-PT: plugin_openproject_backlogs: - name: "Repositórios OpenProject" + name: "Backlogs do OpenProject" description: "Este módulo acrescenta funcionalidades que permitem às equipas Agile trabalhar com o OpenProject em projetos Scrum." activerecord: attributes: work_package: position: "Posição" story_points: "Pontos de histórico" - backlogs_work_package_type: "Tipo de acumulados" + backlogs_work_package_type: "Tipo de backlog" errors: models: work_package: @@ -78,9 +78,9 @@ pt-PT: backlogs_any: "qualquer" backlogs_inactive: "Projeto não mostra nenhuma atividade" backlogs_points_burn_direction: "Pontos queimam para cima/para baixo" - backlogs_product_backlog: "Lista de acumulados de produto" - backlogs_product_backlog_is_empty: "Lista de acumulados de produto vazia" - backlogs_product_backlog_unsized: "O topo da lista de acumulados de produto tem histórias sem tamanho" + backlogs_product_backlog: "Backlog do produto" + backlogs_product_backlog_is_empty: "O backlog do produto está vazio" + backlogs_product_backlog_unsized: "O topo do backlog do produto tem histórias sem tamanho" backlogs_sizing_inconsistent: "Os tamanhos de histórias variam em relação às suas estimativas" backlogs_sprint_notes_missing: "Sprints fechados sem revisão retrospectiva/notas" backlogs_sprint_unestimated: "Sprints ativos ou fechados com histórias não estimadas" @@ -93,8 +93,8 @@ pt-PT: backlogs_velocity_missing: "Não foi possível calcular velocidade para este projeto" backlogs_velocity_varies: "A velocidade varia significativamente ao longo dos sprints" backlogs_wiki_template: "Modelo para a página wiki de sprint" - backlogs_empty_title: "Não estão definidas versões para utilizar com os repositórios" - backlogs_empty_action_text: "Para iniciar os repositórios, crie uma nova versão e atribua-a a uma coluna de repositórios." + backlogs_empty_title: "Não há versões definidas para serem utilizadas em backlogs" + backlogs_empty_action_text: "Para começar a utilizar os backlogs, crie uma nova versão e atribua-a a uma coluna de backlogs." button_edit_wiki: "Editar página wiki" error_backlogs_task_cannot_be_story: "As definições são inválidas. O tipo de tarefa selecionado não pode ser também um tipo de história." error_intro_plural: "Os seguintes erros foram encontrados:" @@ -105,22 +105,22 @@ pt-PT: ideal: "ideal" inclusion: "não está incluído na lista" label_back_to_project: "Voltar à página do projeto" - label_backlog: "Repositório" - label_backlogs: "Repositórios" - label_backlogs_unconfigured: "Ainda não configurou os Repositórios. Por favor vá a %{administration} > %{plugins}, e depois clique no link %{configure} para este plugin. Após definir os campos, volte a esta página para começar a utilizar a ferramenta." + label_backlog: "Backlog" + label_backlogs: "Backlogs" + label_backlogs_unconfigured: "Ainda não configurou os backlogs. Vá a %{administration} > %{plugins}, e depois clique no link %{configure} para este plugin. Após definir os campos, volte a esta página para começar a utilizar a ferramenta." label_blocks_ids: "Identificações de pacotes de trabalho bloqueados" label_burndown: "Burndown" - label_column_in_backlog: "Coluna no repositório" + label_column_in_backlog: "Coluna no backlog" label_hours: "horas" label_work_package_hierarchy: "Hierarquia de pacotes de trabalho" - label_master_backlog: "Repositório Master" + label_master_backlog: "Backlog principal" label_not_prioritized: "não priorizada" label_points: "pontos" label_points_burn_down: "Abaixo" label_points_burn_up: "Acima" - label_product_backlog: "repositório de produto" + label_product_backlog: "backlog do produto" label_select_all: "Seleccionar todos" - label_sprint_backlog: "repositório de sprint" + label_sprint_backlog: "backlog de sprint" label_sprint_cards: "Exportar cartões" label_sprint_impediments: "Impedimentos de Sprint" label_sprint_name: "Sprint \"%{name}\"" @@ -132,7 +132,7 @@ pt-PT: label_version: 'Versão' label_webcal: "Webcal Feed" label_wiki: "Wiki" - permission_view_master_backlog: "Ver repositório master" + permission_view_master_backlog: "Ver o backlog principal" permission_view_taskboards: "Ver quadros de tarefas" permission_select_done_statuses: "Selecione os estados concluídos" permission_update_sprints: "Atualizar sprints" diff --git a/modules/bim/config/locales/crowdin/js-pt-PT.yml b/modules/bim/config/locales/crowdin/js-pt-PT.yml index 3c9b05524a1..4821012aff8 100644 --- a/modules/bim/config/locales/crowdin/js-pt-PT.yml +++ b/modules/bim/config/locales/crowdin/js-pt-PT.yml @@ -13,7 +13,7 @@ pt-PT: delete_viewpoint: 'Excluir ponto de vista' management: 'Gestão BCF' refresh: 'Atualizar' - refresh_work_package: 'Atualizar pacote de tarefas' + refresh_work_package: 'Recarregar pacote de trabalho' ifc_models: empty_warning: "Este projeto ainda não tem nenhum modelo IFC." use_this_link_to_manage: "Use este link para fazer upload e gerenciar seus modelos IFC" diff --git a/modules/boards/config/locales/crowdin/js-pt-PT.yml b/modules/boards/config/locales/crowdin/js-pt-PT.yml index d447f2d2081..a86dbc06923 100644 --- a/modules/boards/config/locales/crowdin/js-pt-PT.yml +++ b/modules/boards/config/locales/crowdin/js-pt-PT.yml @@ -23,7 +23,7 @@ pt-PT: locked: 'Bloqueado' closed: 'Fechado' new_board: 'Novo quadro' - add_list: 'Adicionar lista ao qaudro' + add_list: 'Adicionar lista ao quadro' add_card: 'Adicionar cartão' error_attribute_not_writable: "Não é possível mover o pacote de trabalho, %{attribute} não é gravável." error_loading_the_list: "Erro ao carregar a lista: %{error_message}" @@ -34,7 +34,7 @@ pt-PT: board_type: text: 'Tipo de quadro' free: 'básico' - select_board_type: 'Por favor, escolha o tipo de quadro que precisa.' + select_board_type: 'Escolha o tipo de quadro necessário.' free_text: > Comece do zero com um quadro em branco. Adicione manualmente cartões e colunas a este quadro. action: 'Quadro de ação' @@ -42,11 +42,11 @@ pt-PT: action_text: > Um quadro com listas filtradas no atributo %{attribute} . Mover pacotes de trabalho para outras listas irá atualizar o seu atributo. action_text_subprojects: > - Quadro com colunas automatizadas para sub-projetos. Arrastar pacotes de trabalho para outras listas atualiza o (sub-)projeto de acordo. + Quadro com colunas automáticas para sub-projetos. Arrastar pacotes de trabalho para outras listas atualiza o (sub)projeto em conformidade. action_text_subtasks: > - Board com colunas automatizadas para sub-elementos. Arrastar pacotes de trabalho para outras listas atualiza o pai de acordo. + Quadro com colunas automáticas para sub-elementos. Arrastar pacotes de trabalho para outras listas atualiza a lista principal em conformidade. action_text_status: > - Quadro de estilo kanban básico com colunas para status como Por Fazer, Em Progresso, Concluído. + Quadro de estilo kanban básico, com colunas para estado como Por fazer, Em curso, Concluído. action_text_assignee: > Quadro com colunas automatizadas baseadas em utilizadores atribuídos. Ideal para despacho de pacotes de trabalho. action_text_version: > diff --git a/modules/boards/config/locales/crowdin/pt-PT.yml b/modules/boards/config/locales/crowdin/pt-PT.yml index 45805106c57..a88e3d5bf33 100644 --- a/modules/boards/config/locales/crowdin/pt-PT.yml +++ b/modules/boards/config/locales/crowdin/pt-PT.yml @@ -2,7 +2,7 @@ pt-PT: plugin_openproject_boards: name: "Quadros do OpenProject" - description: "Fornece vistas do quadro." + description: "Fornece vistas de quadro." permission_show_board_views: "Ver quadros" permission_manage_board_views: "Gerir quadros" project_module_board_view: "Quadros" @@ -35,5 +35,5 @@ pt-PT: subtasks: > Quadro com colunas automatizadas para sub-elementos. Arrastar pacotes de trabalho para outras listas atualiza o elemento principal de acordo. upsale: - teaser_text: 'Gostaria de automatizar os seus fluxos de trabalho com os Quadros? Os Quadros avançados são um complemento de Enterprise. Faça upgrade para um plano pago.' + teaser_text: 'Gostaria de automatizar os seus fluxos de trabalho com Quadros? Os quadros avançados são um complemento Enterprise. Faça upgrade para um plano pago.' upgrade: 'Fazer o upgrade agora' diff --git a/modules/calendar/config/locales/crowdin/pt-PT.yml b/modules/calendar/config/locales/crowdin/pt-PT.yml index 2ce4bfac061..3d0bc060945 100644 --- a/modules/calendar/config/locales/crowdin/pt-PT.yml +++ b/modules/calendar/config/locales/crowdin/pt-PT.yml @@ -2,8 +2,8 @@ pt-PT: plugin_openproject_calendar: name: "Calendário OpenProject" - description: "Fornece visualizações do calendário." - label_calendar: "Calendário" + description: "Fornece vistas de calendários." + label_calendar: "Calendários" label_calendar_plural: "Calendários" label_new_calendar: "Novo calendário" permission_view_calendar: "Ver calendários" diff --git a/modules/costs/config/locales/crowdin/fr.yml b/modules/costs/config/locales/crowdin/fr.yml index d58410d6be0..2c12937d870 100644 --- a/modules/costs/config/locales/crowdin/fr.yml +++ b/modules/costs/config/locales/crowdin/fr.yml @@ -58,11 +58,11 @@ fr: end_time: Heure de fin models: time_entry: - one: "Time entry" - other: "Time entries" + one: "Saisie du temps" + other: "Saisies du temps" cost_entry: - one: "Cost entry" - other: "Cost entries" + one: "Saisie du coût" + other: "Saisies de coûts" cost_type: one: "Types de coût" other: "Types de coûts" diff --git a/modules/meeting/config/locales/crowdin/af.yml b/modules/meeting/config/locales/crowdin/af.yml index 31081ae0a72..c634cfbf539 100644 --- a/modules/meeting/config/locales/crowdin/af.yml +++ b/modules/meeting/config/locales/crowdin/af.yml @@ -401,7 +401,7 @@ af: label_meeting_state_in_progress: "In-vordering" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ar.yml b/modules/meeting/config/locales/crowdin/ar.yml index 8c6765c2c95..9471d1a588c 100644 --- a/modules/meeting/config/locales/crowdin/ar.yml +++ b/modules/meeting/config/locales/crowdin/ar.yml @@ -417,7 +417,7 @@ ar: label_meeting_state_in_progress: "بصدد الإنجاز" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/az.yml b/modules/meeting/config/locales/crowdin/az.yml index 2f479c13a1c..fc15dddf6fa 100644 --- a/modules/meeting/config/locales/crowdin/az.yml +++ b/modules/meeting/config/locales/crowdin/az.yml @@ -401,7 +401,7 @@ az: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/be.yml b/modules/meeting/config/locales/crowdin/be.yml index 99352088246..20050652efa 100644 --- a/modules/meeting/config/locales/crowdin/be.yml +++ b/modules/meeting/config/locales/crowdin/be.yml @@ -409,7 +409,7 @@ be: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/bg.yml b/modules/meeting/config/locales/crowdin/bg.yml index f6fe4974715..b9733b227e0 100644 --- a/modules/meeting/config/locales/crowdin/bg.yml +++ b/modules/meeting/config/locales/crowdin/bg.yml @@ -401,7 +401,7 @@ bg: label_meeting_state_in_progress: "В изпълнение" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Затваряне на срещата" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Тази среща е закрита. Вече не можете да добавяте или изтривате точки от дневния ред." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ca.yml b/modules/meeting/config/locales/crowdin/ca.yml index 2f4de73c05c..5076da8e29b 100644 --- a/modules/meeting/config/locales/crowdin/ca.yml +++ b/modules/meeting/config/locales/crowdin/ca.yml @@ -401,7 +401,7 @@ ca: label_meeting_state_in_progress: "En progrés" label_meeting_reopen_action: "Reobrir reunió" label_meeting_close_action: "Tancar reunió" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Aquesta reunió està tancada. Ja no es poden afegir o eliminar elements de l'agenda." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ckb-IR.yml b/modules/meeting/config/locales/crowdin/ckb-IR.yml index 18b02a00d60..91bd32a7227 100644 --- a/modules/meeting/config/locales/crowdin/ckb-IR.yml +++ b/modules/meeting/config/locales/crowdin/ckb-IR.yml @@ -401,7 +401,7 @@ ckb-IR: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/cs.yml b/modules/meeting/config/locales/crowdin/cs.yml index c36fd8d68c5..482ccfee765 100644 --- a/modules/meeting/config/locales/crowdin/cs.yml +++ b/modules/meeting/config/locales/crowdin/cs.yml @@ -409,7 +409,7 @@ cs: label_meeting_state_in_progress: "Probíhá" label_meeting_reopen_action: "Znovu otevřít schůzku" label_meeting_close_action: "Ukončit schůzku" - label_meeting_in_progress_action: "Označit jako probíhající" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Tato schůzka je ukončena. Položky agendy již nelze přidávat/odstranit." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/da.yml b/modules/meeting/config/locales/crowdin/da.yml index 99a891a9cb6..58ee6a313b1 100644 --- a/modules/meeting/config/locales/crowdin/da.yml +++ b/modules/meeting/config/locales/crowdin/da.yml @@ -401,7 +401,7 @@ da: label_meeting_state_in_progress: "Igangværende" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/de.yml b/modules/meeting/config/locales/crowdin/de.yml index 08639c06bae..615eed6c56e 100644 --- a/modules/meeting/config/locales/crowdin/de.yml +++ b/modules/meeting/config/locales/crowdin/de.yml @@ -401,7 +401,7 @@ de: label_meeting_state_in_progress: "In Durchführung" label_meeting_reopen_action: "Besprechung wiedereröffnen" label_meeting_close_action: "Besprechung schließen" - label_meeting_in_progress_action: "Besprechung beginnen" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Diese Besprechung ist offen. Sie können Tagesordnungspunkte hinzufügen oder entfernen und bearbeiten. Sobald die Tagesordnung fertig ist, wechseln Sie auf In Durchführung, um Ergebnisse zu dokumentieren." text_meeting_closed_description: "Diese Besprechung ist abgeschlossen. Sie können keine Tagesordnungspunkte mehr hinzufügen/entfernen." text_meeting_in_progress_description: "Diese Besprechung befindet sich in Durchführung. Sie können die Ergebnisse für jeden Tagesordnungspunkt dokumentieren, neu anordnen und neue Punkte hinzufügen. Sobald die Besprechung abgeschlossen ist, können Sie es als geschlossen markieren, um es zu sperren." diff --git a/modules/meeting/config/locales/crowdin/el.yml b/modules/meeting/config/locales/crowdin/el.yml index 5492644c459..57b2ca4f11f 100644 --- a/modules/meeting/config/locales/crowdin/el.yml +++ b/modules/meeting/config/locales/crowdin/el.yml @@ -401,7 +401,7 @@ el: label_meeting_state_in_progress: "Σε εξέλιξη" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/eo.yml b/modules/meeting/config/locales/crowdin/eo.yml index a22d4210f36..e852fb94ae2 100644 --- a/modules/meeting/config/locales/crowdin/eo.yml +++ b/modules/meeting/config/locales/crowdin/eo.yml @@ -401,7 +401,7 @@ eo: label_meeting_state_in_progress: "Farata" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/es.yml b/modules/meeting/config/locales/crowdin/es.yml index 6bf0d27a164..bfe0d03f75c 100644 --- a/modules/meeting/config/locales/crowdin/es.yml +++ b/modules/meeting/config/locales/crowdin/es.yml @@ -401,7 +401,7 @@ es: label_meeting_state_in_progress: "En curso" label_meeting_reopen_action: "Reabrir reunión" label_meeting_close_action: "Cerrar reunión" - label_meeting_in_progress_action: "Marcar como en curso" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Esta reunión es abierta. Puede añadir/eliminar puntos del orden del día y editarlos a su antojo. Una vez que la agenda esté lista, márquela como en curso para documentar los resultados." text_meeting_closed_description: "Esta reunión está cerrada. Ya no puede añadir/eliminar elementos de la agenda." text_meeting_in_progress_description: "Esta reunión está en curso. Puede documentar los resultados de cada punto del orden del día, reorganizarlos e incluso añadir otros nuevos. Una vez finalizada la reunión, puede marcarla como cerrada para bloquearla." diff --git a/modules/meeting/config/locales/crowdin/et.yml b/modules/meeting/config/locales/crowdin/et.yml index dab5aa3015d..b5dece23b35 100644 --- a/modules/meeting/config/locales/crowdin/et.yml +++ b/modules/meeting/config/locales/crowdin/et.yml @@ -401,7 +401,7 @@ et: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/eu.yml b/modules/meeting/config/locales/crowdin/eu.yml index 2d45a67aa66..f165b581bcc 100644 --- a/modules/meeting/config/locales/crowdin/eu.yml +++ b/modules/meeting/config/locales/crowdin/eu.yml @@ -401,7 +401,7 @@ eu: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/fa.yml b/modules/meeting/config/locales/crowdin/fa.yml index 412069233b6..57e9144f041 100644 --- a/modules/meeting/config/locales/crowdin/fa.yml +++ b/modules/meeting/config/locales/crowdin/fa.yml @@ -401,7 +401,7 @@ fa: label_meeting_state_in_progress: "در حال انجام" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/fi.yml b/modules/meeting/config/locales/crowdin/fi.yml index 32be0363c9c..4a93b890305 100644 --- a/modules/meeting/config/locales/crowdin/fi.yml +++ b/modules/meeting/config/locales/crowdin/fi.yml @@ -401,7 +401,7 @@ fi: label_meeting_state_in_progress: "Käynnissä" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/fil.yml b/modules/meeting/config/locales/crowdin/fil.yml index f8fdc0ad48a..68c9109d2b5 100644 --- a/modules/meeting/config/locales/crowdin/fil.yml +++ b/modules/meeting/config/locales/crowdin/fil.yml @@ -401,7 +401,7 @@ fil: label_meeting_state_in_progress: "Isinasagawa" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/fr.yml b/modules/meeting/config/locales/crowdin/fr.yml index baa54ceaa4a..87009e71192 100644 --- a/modules/meeting/config/locales/crowdin/fr.yml +++ b/modules/meeting/config/locales/crowdin/fr.yml @@ -401,7 +401,7 @@ fr: label_meeting_state_in_progress: "En cours" label_meeting_reopen_action: "Réouvrir la réunion" label_meeting_close_action: "Clôturer la réunion" - label_meeting_in_progress_action: "Marquer comme étant en cours" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Cette réunion est ouverte. Vous pouvez ajouter/supprimer des éléments de l'ordre du jour et les modifier comme vous le souhaitez. Une fois l'ordre du jour prêt, marquez-le comme étant en cours pour documenter les résultats." text_meeting_closed_description: "Cette réunion est clôturée. Vous ne pouvez plus ajouter/supprimer des points de l'ordre du jour." text_meeting_in_progress_description: "Cette réunion est en cours. Vous pouvez documenter les résultats pour chaque élément de l'ordre du jour, les réorganiser et même en ajouter de nouveaux. Une fois la réunion terminée, vous pouvez la marquer comme fermée pour la verrouiller." diff --git a/modules/meeting/config/locales/crowdin/he.yml b/modules/meeting/config/locales/crowdin/he.yml index 24fbc027b20..d9793a23a7b 100644 --- a/modules/meeting/config/locales/crowdin/he.yml +++ b/modules/meeting/config/locales/crowdin/he.yml @@ -409,7 +409,7 @@ he: label_meeting_state_in_progress: "בביצוע" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/hi.yml b/modules/meeting/config/locales/crowdin/hi.yml index 8bb10069ac3..e7d345b3c5d 100644 --- a/modules/meeting/config/locales/crowdin/hi.yml +++ b/modules/meeting/config/locales/crowdin/hi.yml @@ -401,7 +401,7 @@ hi: label_meeting_state_in_progress: "प्रगति में" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/hr.yml b/modules/meeting/config/locales/crowdin/hr.yml index 3c10de2e7f8..f2775a333c6 100644 --- a/modules/meeting/config/locales/crowdin/hr.yml +++ b/modules/meeting/config/locales/crowdin/hr.yml @@ -405,7 +405,7 @@ hr: label_meeting_state_in_progress: "U tijeku" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/hu.yml b/modules/meeting/config/locales/crowdin/hu.yml index 6da15106082..17ccd27f495 100644 --- a/modules/meeting/config/locales/crowdin/hu.yml +++ b/modules/meeting/config/locales/crowdin/hu.yml @@ -401,7 +401,7 @@ hu: label_meeting_state_in_progress: "Folyamatban" label_meeting_reopen_action: "A megbeszélés újranyitása" label_meeting_close_action: "Megbeszélés lezárása" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Ez a megbeszélés zárt. Többé nem tud napirendi pontokat hozzáadni/eltávolítani." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/id.yml b/modules/meeting/config/locales/crowdin/id.yml index 3167b2baa65..4d194fec13b 100644 --- a/modules/meeting/config/locales/crowdin/id.yml +++ b/modules/meeting/config/locales/crowdin/id.yml @@ -397,7 +397,7 @@ id: label_meeting_state_in_progress: "In Progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/it.yml b/modules/meeting/config/locales/crowdin/it.yml index d561f5f9341..8d782d6a484 100644 --- a/modules/meeting/config/locales/crowdin/it.yml +++ b/modules/meeting/config/locales/crowdin/it.yml @@ -401,7 +401,7 @@ it: label_meeting_state_in_progress: "In corso" label_meeting_reopen_action: "Riapri la riunione" label_meeting_close_action: "Chiudi riunione" - label_meeting_in_progress_action: "Segna come in corso" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Questa riunione è aperta. Puoi aggiungere/rimuovere i punti all'ordine del giorno e modificarli come vuoi. Una volta che l'ordine del giorno è pronto, contrassegna come in corso per documentare i risultati." text_meeting_closed_description: "Questa riunione è chiusa. Non puoi più aggiungere/rimuovere i punti all'ordine del giorno." text_meeting_in_progress_description: "Questa riunione è in corso. È possibile documentare i risultati per ogni punto all'ordine del giorno, riorganizzarli, e anche aggiungerne di nuovi. Una volta completata la riunione, è possibile contrassegnarla come chiusa per bloccarla." diff --git a/modules/meeting/config/locales/crowdin/ja.yml b/modules/meeting/config/locales/crowdin/ja.yml index 3ec9b66ad85..bf1abe7a617 100644 --- a/modules/meeting/config/locales/crowdin/ja.yml +++ b/modules/meeting/config/locales/crowdin/ja.yml @@ -397,7 +397,7 @@ ja: label_meeting_state_in_progress: "進行中" label_meeting_reopen_action: "会議を再開する" label_meeting_close_action: "会議を終了する" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "この会議は終了しています。これ以上、議題項目の追加/削除はできません。" text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ka.yml b/modules/meeting/config/locales/crowdin/ka.yml index 99784d723ae..f938682138f 100644 --- a/modules/meeting/config/locales/crowdin/ka.yml +++ b/modules/meeting/config/locales/crowdin/ka.yml @@ -401,7 +401,7 @@ ka: label_meeting_state_in_progress: "მიმდინარეობს" label_meeting_reopen_action: "შეხვედრის თავიდან გახსნა" label_meeting_close_action: "შეხვედრის დახურვა" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/kk.yml b/modules/meeting/config/locales/crowdin/kk.yml index a7b650c2251..ff5d461f5bb 100644 --- a/modules/meeting/config/locales/crowdin/kk.yml +++ b/modules/meeting/config/locales/crowdin/kk.yml @@ -401,7 +401,7 @@ kk: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ko.yml b/modules/meeting/config/locales/crowdin/ko.yml index 0ea0429266d..c0166f5388a 100644 --- a/modules/meeting/config/locales/crowdin/ko.yml +++ b/modules/meeting/config/locales/crowdin/ko.yml @@ -397,7 +397,7 @@ ko: label_meeting_state_in_progress: "진행 중" label_meeting_reopen_action: "미팅 다시 열기" label_meeting_close_action: "미팅 닫기" - label_meeting_in_progress_action: "진행 중으로 표시" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "이 미팅은 오픈 상태입니다. 의제 항목을 추가/제거하고 원하는 대로 편집할 수 있습니다. 의제가 준비되면 진행 중으로 표시하여 결과를 문서화하세요." text_meeting_closed_description: "이 미팅은 종료되었습니다. 더 이상 의제 항목을 추가/제거할 수 없습니다." text_meeting_in_progress_description: "이 미팅은 진행 중입니다. 각 의제 항목에 대한 결과를 문서화하고, 재정렬하고, 새로운 항목을 추가할 수도 있습니다. 미팅이 완료되면 닫힘으로 표시하여 잠글 수 있습니다." diff --git a/modules/meeting/config/locales/crowdin/lt.yml b/modules/meeting/config/locales/crowdin/lt.yml index 8de9eabd026..90254cc006b 100644 --- a/modules/meeting/config/locales/crowdin/lt.yml +++ b/modules/meeting/config/locales/crowdin/lt.yml @@ -409,7 +409,7 @@ lt: label_meeting_state_in_progress: "Vykdoma" label_meeting_reopen_action: "Iš naujo atidaryti susitikimą" label_meeting_close_action: "Uždaryti susitikimą" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Šis susitikimas yra uždarytas. Jūs daugiau nebegalite pridėti/išimti darbotvarkės elementų." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/lv.yml b/modules/meeting/config/locales/crowdin/lv.yml index 60d6c27e2a1..fc20b42eeed 100644 --- a/modules/meeting/config/locales/crowdin/lv.yml +++ b/modules/meeting/config/locales/crowdin/lv.yml @@ -405,7 +405,7 @@ lv: label_meeting_state_in_progress: "Izpildē" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/mn.yml b/modules/meeting/config/locales/crowdin/mn.yml index 3de70e39628..fc796972822 100644 --- a/modules/meeting/config/locales/crowdin/mn.yml +++ b/modules/meeting/config/locales/crowdin/mn.yml @@ -401,7 +401,7 @@ mn: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ms.yml b/modules/meeting/config/locales/crowdin/ms.yml index c94df9c6f7e..6c5e09c4080 100644 --- a/modules/meeting/config/locales/crowdin/ms.yml +++ b/modules/meeting/config/locales/crowdin/ms.yml @@ -397,7 +397,7 @@ ms: label_meeting_state_in_progress: "Dalam proses" label_meeting_reopen_action: "Buka semula mesyuarat" label_meeting_close_action: "Tutup mesyuarat" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Mesyuarat ini ditutup. Anda tidak boleh tambah/keluarkan item agenda lagi." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ne.yml b/modules/meeting/config/locales/crowdin/ne.yml index 2d187ca5673..50d8de3237e 100644 --- a/modules/meeting/config/locales/crowdin/ne.yml +++ b/modules/meeting/config/locales/crowdin/ne.yml @@ -401,7 +401,7 @@ ne: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/nl.yml b/modules/meeting/config/locales/crowdin/nl.yml index 54a01460aee..85a60c5eb22 100644 --- a/modules/meeting/config/locales/crowdin/nl.yml +++ b/modules/meeting/config/locales/crowdin/nl.yml @@ -401,7 +401,7 @@ nl: label_meeting_state_in_progress: "In behandeling" label_meeting_reopen_action: "Heropen vergadering" label_meeting_close_action: "Vergadering sluiten" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Deze vergadering is gesloten. U kunt geen agendapunten meer toevoegen/verwijderen." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/no.yml b/modules/meeting/config/locales/crowdin/no.yml index a59566dbe04..aacf8d76531 100644 --- a/modules/meeting/config/locales/crowdin/no.yml +++ b/modules/meeting/config/locales/crowdin/no.yml @@ -401,7 +401,7 @@ label_meeting_state_in_progress: "Under arbeid" label_meeting_reopen_action: "Gjenåpne møte" label_meeting_close_action: "Lukk møtet" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Dette møtet er lukket. Du kan ikke lenger legge til eller fjerne punkter på dagsorden." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/pl.yml b/modules/meeting/config/locales/crowdin/pl.yml index 8442eba6a88..2392b15ebb8 100644 --- a/modules/meeting/config/locales/crowdin/pl.yml +++ b/modules/meeting/config/locales/crowdin/pl.yml @@ -409,7 +409,7 @@ pl: label_meeting_state_in_progress: "W toku" label_meeting_reopen_action: "Otwórz ponownie spotkanie" label_meeting_close_action: "Zamknij spotkanie" - label_meeting_in_progress_action: "Oznacz jako „w toku”" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "To spotkanie jest otwarte. Możesz dodać/usunąć punkty planu spotkania i edytować je tak, jak chcesz. Gdy plan spotkania będzie gotowy, należy oznaczyć go jako „w toku” w celu dokumentowania wyników." text_meeting_closed_description: "To spotkanie jest zamknięte. Nie można już dodawać/usuwać elementów planu spotkania." text_meeting_in_progress_description: "To spotkanie jest w toku. Możesz udokumentować wyniki każdego punktu planu spotkania, zmienić ich kolejność, a nawet dodać nowe. Gdy spotkanie zostanie ukończone, możesz oznaczyć je jako zamknięte, aby je zablokować." diff --git a/modules/meeting/config/locales/crowdin/pt-BR.yml b/modules/meeting/config/locales/crowdin/pt-BR.yml index a57d3cd944f..d487a74b5e1 100644 --- a/modules/meeting/config/locales/crowdin/pt-BR.yml +++ b/modules/meeting/config/locales/crowdin/pt-BR.yml @@ -401,7 +401,7 @@ pt-BR: label_meeting_state_in_progress: "Em andamento" label_meeting_reopen_action: "Reabrir reunião" label_meeting_close_action: "Fechar reunião" - label_meeting_in_progress_action: "Marcar como \"Em andamento\"" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Esta reunião está aberta. Você pode adicionar, remover e editar itens da agenda como quiser. Assim que a agenda estiver pronta, marque-a como \"Em andamento\" para registrar os resultados." text_meeting_closed_description: "Esta reunião está fechada. Você não pode mais adicionar/remover itens da agenda." text_meeting_in_progress_description: "A reunião está em andamento. Você pode registrar os resultados de cada item da agenda, reorganizá-los e adicionar novos. Quando a reunião for concluída, marque-a como encerrada para bloqueá-la." diff --git a/modules/meeting/config/locales/crowdin/pt-PT.yml b/modules/meeting/config/locales/crowdin/pt-PT.yml index 8703cbd94c6..3a0758d8d14 100644 --- a/modules/meeting/config/locales/crowdin/pt-PT.yml +++ b/modules/meeting/config/locales/crowdin/pt-PT.yml @@ -338,7 +338,7 @@ pt-PT: permission_create_meeting_minutes: "Gerir minutos" permission_send_meeting_minutes_notification: "Enviar notificação de revisão por minutos" permission_meetings_send_invite: "Convidar utilizadores para reuniões" - permission_send_meeting_agendas_icalendar: "Enviar agenda de reunião como entrada na agenda" + permission_send_meeting_agendas_icalendar: "Enviar a ordem de trabalhos da reunião como entrada de calendário" project_module_meetings: "Reuniões" text_duration_in_hours: "Duração em horas" text_in_hours: "em horas" @@ -401,7 +401,7 @@ pt-PT: label_meeting_state_in_progress: "A decorrer" label_meeting_reopen_action: "Reabrir reunião" label_meeting_close_action: "Encerrar reunião" - label_meeting_in_progress_action: "Marcar como \"A decorrer\"" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Esta reunião está aberta. Pode adicionar/remover pontos da ordem de trabalhos e editá-los à vontade. Quando a ordem de trabalhos estiver pronta, marque-a como em curso para documentar os resultados." text_meeting_closed_description: "Esta reunião está encerrada. Você não pode mais adicionar/remover itens da agenda." text_meeting_in_progress_description: "Esta reunião está a decorrer. Pode documentar os resultados de cada ponto da ordem de trabalhos, reorganizá-los e até adicionar novos. Quando a reunião estiver concluída, pode marcá-la como encerrada para a bloquear." diff --git a/modules/meeting/config/locales/crowdin/ro.yml b/modules/meeting/config/locales/crowdin/ro.yml index 62833aa869d..7212855d5c7 100644 --- a/modules/meeting/config/locales/crowdin/ro.yml +++ b/modules/meeting/config/locales/crowdin/ro.yml @@ -405,7 +405,7 @@ ro: label_meeting_state_in_progress: "În lucru" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/ru.yml b/modules/meeting/config/locales/crowdin/ru.yml index 2e5c96f98d8..3f4c6f422fa 100644 --- a/modules/meeting/config/locales/crowdin/ru.yml +++ b/modules/meeting/config/locales/crowdin/ru.yml @@ -409,7 +409,7 @@ ru: label_meeting_state_in_progress: "В процессе" label_meeting_reopen_action: "Открыть совещание заново" label_meeting_close_action: "Закрыть совещание" - label_meeting_in_progress_action: "Отметить как в процессе" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Совещание открыто. Вы можете добавлять/удалять пункты повестки дня и редактировать их так, как захотите. Как только повестка дня будет готова, отметьте ее как \"в процессе\" для документирования результатов." text_meeting_closed_description: "Это совещание является закрытым. Вы не можете добавлять/удалять пункты повестки." text_meeting_in_progress_description: "Совещание в процессе. Вы можете документировать результаты для каждого пункта повестки дня, переупорядочить их и даже добавить новые. После завершения совещания вы можете пометить его как закрытое для блокировки." diff --git a/modules/meeting/config/locales/crowdin/rw.yml b/modules/meeting/config/locales/crowdin/rw.yml index 775fcf7aecb..b48a596a1ec 100644 --- a/modules/meeting/config/locales/crowdin/rw.yml +++ b/modules/meeting/config/locales/crowdin/rw.yml @@ -401,7 +401,7 @@ rw: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/si.yml b/modules/meeting/config/locales/crowdin/si.yml index b0f837af0a2..57d7cdefc27 100644 --- a/modules/meeting/config/locales/crowdin/si.yml +++ b/modules/meeting/config/locales/crowdin/si.yml @@ -401,7 +401,7 @@ si: label_meeting_state_in_progress: "ප්රගතියේ" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/sk.yml b/modules/meeting/config/locales/crowdin/sk.yml index b3bbd7a06f3..d5baf73e37b 100644 --- a/modules/meeting/config/locales/crowdin/sk.yml +++ b/modules/meeting/config/locales/crowdin/sk.yml @@ -409,7 +409,7 @@ sk: label_meeting_state_in_progress: "Prebieha" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/sl.yml b/modules/meeting/config/locales/crowdin/sl.yml index 2088889663e..f4dfb44f53a 100644 --- a/modules/meeting/config/locales/crowdin/sl.yml +++ b/modules/meeting/config/locales/crowdin/sl.yml @@ -409,7 +409,7 @@ sl: label_meeting_state_in_progress: "V teku" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/sr.yml b/modules/meeting/config/locales/crowdin/sr.yml index d4b259efddb..39293026411 100644 --- a/modules/meeting/config/locales/crowdin/sr.yml +++ b/modules/meeting/config/locales/crowdin/sr.yml @@ -405,7 +405,7 @@ sr: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/sv.yml b/modules/meeting/config/locales/crowdin/sv.yml index eee82711e7b..cd31d7d6bbc 100644 --- a/modules/meeting/config/locales/crowdin/sv.yml +++ b/modules/meeting/config/locales/crowdin/sv.yml @@ -401,7 +401,7 @@ sv: label_meeting_state_in_progress: "Pågående" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/th.yml b/modules/meeting/config/locales/crowdin/th.yml index e9b894f4a9a..f51657b68b0 100644 --- a/modules/meeting/config/locales/crowdin/th.yml +++ b/modules/meeting/config/locales/crowdin/th.yml @@ -397,7 +397,7 @@ th: label_meeting_state_in_progress: "อยู่ระหว่างดำเนินการ" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/tr.yml b/modules/meeting/config/locales/crowdin/tr.yml index 7afe405f391..9ba5582dbb5 100644 --- a/modules/meeting/config/locales/crowdin/tr.yml +++ b/modules/meeting/config/locales/crowdin/tr.yml @@ -401,7 +401,7 @@ tr: label_meeting_state_in_progress: "Devam etmekte" label_meeting_reopen_action: "Toplantıyı tekrar aç" label_meeting_close_action: "Toplantıyı kapat" - label_meeting_in_progress_action: "Devam etmekte olarak işaretle" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Bu toplantı açık. Gündem maddesi ekleyip kaldırabilirsiniz ve istediğiniz gibi düzenleyebilirsiniz. Gündem hazır olduğunda sonuçları belgelemek için devam etmekte olarak işaretleyin." text_meeting_closed_description: "Toplantı kapatılmış. Artık gündem maddesi ekleyip çıkartamazsınız." text_meeting_in_progress_description: "Bu toplantı devam etmekte. Her bir gündem maddesi için sonuçları belgeleyebilir, yerlerini düzenleyebilir ve hatta yenilerini ekleyebilirsiniz. Toplantı tamamlandığında bunları sabitlemek için kapalı olarak işaretleyin." diff --git a/modules/meeting/config/locales/crowdin/uk.yml b/modules/meeting/config/locales/crowdin/uk.yml index ba612a680e1..1eed9345574 100644 --- a/modules/meeting/config/locales/crowdin/uk.yml +++ b/modules/meeting/config/locales/crowdin/uk.yml @@ -409,7 +409,7 @@ uk: label_meeting_state_in_progress: "Поточна" label_meeting_reopen_action: "Відкрити зустріч знову" label_meeting_close_action: "Закрити зустріч" - label_meeting_in_progress_action: "Позначити як поточну" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "Це відкрита нарада. Ви можете додавати / вилучати пункти порядку денного й редагувати їх. Коли порядок денний буде готовий, позначте її як поточну в результатах документа." text_meeting_closed_description: "Це закрита нарада. Ви більше не можете додати або вилучати пункти порядку денного." text_meeting_in_progress_description: "Це поточна нарада. Ви можете документувати результати для кожного пункту порядку денного, перевпорядковувати їх і навіть додавати нові. Коли нараду буде завершено, позначте її як закриту, щоб заблокувати." diff --git a/modules/meeting/config/locales/crowdin/uz.yml b/modules/meeting/config/locales/crowdin/uz.yml index ee29a0420c1..f74bc7cc52c 100644 --- a/modules/meeting/config/locales/crowdin/uz.yml +++ b/modules/meeting/config/locales/crowdin/uz.yml @@ -401,7 +401,7 @@ uz: label_meeting_state_in_progress: "In progress" label_meeting_reopen_action: "Reopen meeting" label_meeting_close_action: "Close meeting" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "This meeting is closed. You cannot add/remove agenda items anymore." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/vi.yml b/modules/meeting/config/locales/crowdin/vi.yml index 880af64070e..f3f87869e15 100644 --- a/modules/meeting/config/locales/crowdin/vi.yml +++ b/modules/meeting/config/locales/crowdin/vi.yml @@ -397,7 +397,7 @@ vi: label_meeting_state_in_progress: "Đang xử lý" label_meeting_reopen_action: "Mở lại cuộc họp" label_meeting_close_action: "Đóng cuộc họp" - label_meeting_in_progress_action: "Mark as in progress" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "This meeting is open. You can add/remove agenda items and edit them as you please. Once the agenda is ready, mark it as in progress to document outcomes." text_meeting_closed_description: "Cuộc họp này đã đóng. Bạn không thể thêm/xóa các mục chương trình nghị sự nữa." text_meeting_in_progress_description: "This meeting is in progress. You can document outcomes for each agenda item, re-arrange them, and even add new ones. Once the meeting is complete, you can mark it as closed to lock it." diff --git a/modules/meeting/config/locales/crowdin/zh-CN.yml b/modules/meeting/config/locales/crowdin/zh-CN.yml index 3fd97d0e1a4..788c8f6fa40 100644 --- a/modules/meeting/config/locales/crowdin/zh-CN.yml +++ b/modules/meeting/config/locales/crowdin/zh-CN.yml @@ -213,8 +213,8 @@ zh-CN: new_date_time: "新日期/时间" label_mail_all_participants: "发送电子邮件给所有参与者" types: - classic: "Classic (unsupported)" - classic_text: "Note: Classic meetings will be removed in the next version of OpenProject." + classic: "经典(不支持)" + classic_text: "注意:经典会议将在下一版OpenProject中删除。" structured: "结构化" one_time: "动态" recurring: "定期" @@ -397,7 +397,7 @@ zh-CN: label_meeting_state_in_progress: "进行中" label_meeting_reopen_action: "重新开放会议" label_meeting_close_action: "关闭会议" - label_meeting_in_progress_action: "标记为进行中" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "本次会议已打开。您可以添加/删除议程项目并随时编辑。 一旦议程就绪,就将其记载为正在取得的成果。" text_meeting_closed_description: "此会议已关闭。您不能再添加/移除议程项目。" text_meeting_in_progress_description: "本次会议正在进行中。您可以记录每个议程项目的结果,重新排列,甚至添加新的项目。 一旦会议完成,您可以将其标记为关闭以便锁定。" diff --git a/modules/meeting/config/locales/crowdin/zh-TW.yml b/modules/meeting/config/locales/crowdin/zh-TW.yml index cdf0db78bf0..837f0ba44a2 100644 --- a/modules/meeting/config/locales/crowdin/zh-TW.yml +++ b/modules/meeting/config/locales/crowdin/zh-TW.yml @@ -397,7 +397,7 @@ zh-TW: label_meeting_state_in_progress: "進行中" label_meeting_reopen_action: "重新開啟會議" label_meeting_close_action: "關閉會議" - label_meeting_in_progress_action: "標記為進行中" + label_meeting_in_progress_action: "Start meeting" text_meeting_open_description: "此會議是開放的。您可以新增/移除議程項目,並隨意編輯。一旦議程準備就緒,請將其標示為進行中,以記錄結果。" text_meeting_closed_description: "此會議已關閉。您不能再新增/移除議程項目。" text_meeting_in_progress_description: "此會議正在進行中。您可以記錄每個議程項目的結果、重新排列它們,甚至新增新的項目。會議完成後,您可以將其標示為已結束,以鎖定它。" From c34077d1b65b3d24eb7fd5b825090edeb3eded66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 05:41:59 +0000 Subject: [PATCH 066/260] Bump eslint-plugin-react from 7.37.4 to 7.37.5 in /frontend Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.37.4 to 7.37.5. - [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases) - [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md) - [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.37.4...v7.37.5) --- updated-dependencies: - dependency-name: eslint-plugin-react dependency-version: 7.37.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 112 ++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 102bd156975..b536718b00e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8028,9 +8028,10 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -8040,12 +8041,13 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -9865,9 +9867,10 @@ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -10387,10 +10390,11 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -10402,7 +10406,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -11635,16 +11639,17 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -16289,14 +16294,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -27732,21 +27739,21 @@ } }, "call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "requires": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "callsites": { @@ -29106,9 +29113,9 @@ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "requires": { "es-errors": "^1.3.0" } @@ -29649,9 +29656,9 @@ } }, "eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "requires": { "array-includes": "^3.1.8", @@ -29664,7 +29671,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -30484,16 +30491,16 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "requires": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -33914,14 +33921,15 @@ } }, "object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" } }, "object.fromentries": { From 1d9fcdc17dff0af83533c458043078ac75d3d5e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 05:57:36 +0000 Subject: [PATCH 067/260] Bump rubocop from 1.75.1 to 1.75.2 Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.75.1 to 1.75.2. - [Release notes](https://github.com/rubocop/rubocop/releases) - [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop/compare/v1.75.1...v1.75.2) --- updated-dependencies: - dependency-name: rubocop dependency-version: 1.75.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a4f8f3fb748..38d401bacfb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1063,7 +1063,7 @@ GEM rspec-support (3.13.2) rspec-wait (1.0.1) rspec (>= 3.4) - rubocop (1.75.1) + rubocop (1.75.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -1071,10 +1071,10 @@ GEM parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.43.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.43.0) + rubocop-ast (1.44.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-capybara (2.22.1) @@ -1847,8 +1847,8 @@ CHECKSUMS rspec-retry (0.6.2) sha256=6101ba23a38809811ae3484acde4ab481c54d846ac66d5037ccb40131a60d858 rspec-support (3.13.2) sha256=cea3a2463fd9b84b9dcc9685efd80ea701aa8f7b3decb3b3ce795ed67737dbec rspec-wait (1.0.1) sha256=50ce9cc7cd20b8bb67b95a4ed56b59a16d4af7e86ae91b28dbf20eeaa2481d1f - rubocop (1.75.1) sha256=c12900c55b0b52e6ed1384f7f7575beb92047019ce37ca14b9572d80239adc29 - rubocop-ast (1.43.0) sha256=92cd649e336ce10212cb2f2b29028f487777ecc477f108f437a1dce1ee3db79a + rubocop (1.75.2) sha256=8efde647e278417e8074421b007e0d7d7c591482ef99d980528b18fea015a7c8 + rubocop-ast (1.44.0) sha256=77fdaf4aacf0c7d1ef887b075686124fb4ae5743d42ff7e73bb1c0d6b61b5d0a rubocop-capybara (2.22.1) sha256=ced88caef23efea53f46e098ff352f8fc1068c649606ca75cb74650970f51c0c rubocop-factory_bot (2.27.1) sha256=9d744b5916778c1848e5fe6777cc69855bd96548853554ec239ba9961b8573fe rubocop-openproject (0.2.0) sha256=2300ed6b638a34a9368b458dc5fb618ae396da6a27670b50519ad1e3cea65ccb From 602c44f917cb9892ce841c4ca37b641221b17c05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 05:58:15 +0000 Subject: [PATCH 068/260] Bump vernier from 1.6.0 to 1.7.0 Bumps [vernier](https://github.com/jhawthorn/vernier) from 1.6.0 to 1.7.0. - [Release notes](https://github.com/jhawthorn/vernier/releases) - [Commits](https://github.com/jhawthorn/vernier/compare/v1.6.0...v1.7.0) --- updated-dependencies: - dependency-name: vernier dependency-version: 1.7.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a4f8f3fb748..afd06a44d99 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1215,7 +1215,7 @@ GEM public_suffix vcr (6.3.1) base64 - vernier (1.6.0) + vernier (1.7.0) view_component (3.22.0) activesupport (>= 5.2.0, < 8.1) concurrent-ruby (= 1.3.4) @@ -1917,7 +1917,7 @@ CHECKSUMS validate_email (0.1.6) sha256=9dfe9016d527b17a8d3a6e95e4dc50a125400eef899d13d4cc2a254393f82ee4 validate_url (1.0.15) sha256=72fe164c0713d63a9970bd6700bea948babbfbdcec392f2342b6704042f57451 vcr (6.3.1) sha256=37b56e157e720446a3f4d2d39919cabef8cb7b6c45936acffd2ef8229fec03ed - vernier (1.6.0) sha256=dc9b489f720e25881dc5cd1e12ac237a980dc78919477aa8f1e02d8725987346 + vernier (1.7.0) sha256=b64c3e0cf1ddf1842e0afca8b09b1664d391b22f0ebfcc924cc2fbb2536231d9 view_component (3.22.0) sha256=70e350abeb77a8710d94b335e68f79bc51da5d1640bc486c5b9bb8b589f0f2c5 virtus (2.0.0) sha256=8841dae4eb7fcc097320ba5ea516bf1839e5d056c61ee27138aa4bddd6e3d1c2 warden (1.2.9) sha256=46684f885d35a69dbb883deabf85a222c8e427a957804719e143005df7a1efd0 From 31a9892fa2e74318b8fbd95c0797e09f10b5e18b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 06:00:26 +0000 Subject: [PATCH 069/260] Bump brakeman from 7.0.0 to 7.0.1 Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v7.0.0...v7.0.1) --- updated-dependencies: - dependency-name: brakeman dependency-version: 7.0.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a4f8f3fb748..9b450b2715e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -399,7 +399,7 @@ GEM bindata (2.5.0) bootsnap (1.18.4) msgpack (~> 1.2) - brakeman (7.0.0) + brakeman (7.0.1) racc browser (6.2.0) builder (3.3.0) @@ -1535,7 +1535,7 @@ CHECKSUMS bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc bindata (2.5.0) sha256=29dccb8ba1cc9de148f24bb88930840c62db56715f0f80eccadd624d9f3d2623 bootsnap (1.18.4) sha256=ac4c42af397f7ee15521820198daeff545e4c360d2772c601fbdc2c07d92af55 - brakeman (7.0.0) sha256=1a0122b0c70f17519a61548a53a332c0acc19e3aa10b445e15e025a4b13b8577 + brakeman (7.0.1) sha256=ec751d439820ed9d04d4ed00ff4fb21ac91689fcbb6cc564b786a4061c8f720d browser (6.2.0) sha256=281d5295788825c9396427c292c2d2be0a5c91875c93c390fde6e5d61a5ace2d budgets (1.0.0) builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f From bb7f75cb19c2c0989307c18835372cdda3428bc1 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Fri, 4 Apr 2025 08:22:44 +0200 Subject: [PATCH 070/260] Fix some links --- lookbook/docs/components/border-box.md.erb | 2 +- .../op_primer/border_box_table_component_preview.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lookbook/docs/components/border-box.md.erb b/lookbook/docs/components/border-box.md.erb index 176cae0e1ac..6cbd9852c16 100644 --- a/lookbook/docs/components/border-box.md.erb +++ b/lookbook/docs/components/border-box.md.erb @@ -35,7 +35,7 @@ Some places in which we already use the Border Box: - to display the a list of project attributes in Project settings - to display a list of configured OAuth applications -If the content needs to be more structured (with columns and column headers), please use the [Border Box Table](border-box-table) component instead. +If the content needs to be more structured (with columns and column headers), please use the [Border Box Table](./tables/border_box_table) component instead. ## Best practices diff --git a/lookbook/previews/op_primer/border_box_table_component_preview.rb b/lookbook/previews/op_primer/border_box_table_component_preview.rb index c9c4365cc78..02121b17095 100644 --- a/lookbook/previews/op_primer/border_box_table_component_preview.rb +++ b/lookbook/previews/op_primer/border_box_table_component_preview.rb @@ -4,22 +4,22 @@ module OpPrimer # @logical_path OpenProject/Primer # @display min_height 300px class BorderBoxTableComponentPreview < Lookbook::Preview - # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. + # See the [component documentation](/lookbook/pages/components/tables/border_box_table) for more details. def default render_with_template end - # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. + # See the [component documentation](/lookbook/pages/components/tables/border_box_table) for more details. def custom_column_widths render_with_template end - # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. + # See the [component documentation](/lookbook/pages/components/tables/border_box_table) for more details. def with_action_menu render_with_template end - # See the [component documentation](/lookbook/pages/components/border_box_table) for more details. + # See the [component documentation](/lookbook/pages/components/tables/border_box_table) for more details. def with_footer render_with_template end From f5890999f54b774405234ecd7ba53c5767d975c6 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Fri, 4 Apr 2025 08:40:21 +0200 Subject: [PATCH 071/260] Replace deprecated Primer::ButtonComponent with Primer::Beta::Button --- app/components/add_button_component.html.erb | 2 +- ...eld_projects_form_modal_component.html.erb | 4 +-- .../new_access_token_form_component.html.erb | 4 +-- .../configure_view_modal_component.html.erb | 4 +-- .../dialog_body_form_component.html.erb | 4 +-- ...rk_package_child_dialog_component.html.erb | 4 +-- ...package_relation_dialog_component.html.erb | 4 +-- .../date_picker/date_form_component.html.erb | 4 +-- .../dialog_content_component.html.erb | 4 +-- .../dialogs/create_dialog_component.html.erb | 30 +++++++++++-------- .../generate/modal_dialog_component.html.erb | 4 +-- .../exports/modal_dialog_component.html.erb | 4 +-- .../entry_dialog_component.html.erb | 6 ++-- .../meetings/index/dialog_component.html.erb | 4 +-- .../details_form_component.html.erb | 4 +-- .../side_panel/participants_dialog.html.erb | 4 +-- ...ckage_to_meeting_dialog_component.html.erb | 4 +-- .../sections/edit_dialog_component.html.erb | 4 +-- .../sections/edit_dialog_component.html.erb | 4 +-- ...ects_storage_form_modal_component.html.erb | 4 +-- ...n_project_storage_modal_component.html.erb | 2 +- 21 files changed, 56 insertions(+), 52 deletions(-) diff --git a/app/components/add_button_component.html.erb b/app/components/add_button_component.html.erb index 88aec27eada..b4903d3eb93 100644 --- a/app/components/add_button_component.html.erb +++ b/app/components/add_button_component.html.erb @@ -1,5 +1,5 @@ <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, aria: { label: aria_label }, title:, diff --git a/app/components/admin/custom_fields/custom_field_projects/new_custom_field_projects_form_modal_component.html.erb b/app/components/admin/custom_fields/custom_field_projects/new_custom_field_projects_form_modal_component.html.erb index f23190f45cd..2b78a95d1af 100644 --- a/app/components/admin/custom_fields/custom_field_projects/new_custom_field_projects_form_modal_component.html.erb +++ b/app/components/admin/custom_fields/custom_field_projects/new_custom_field_projects_form_modal_component.html.erb @@ -48,8 +48,8 @@ See COPYRIGHT and LICENSE files for more details. concat( render(Primer::Alpha::Dialog::Footer.new(show_divider: false)) do - concat(render(Primer::ButtonComponent.new(data: { "close-dialog-id": dialog_id })) { cancel_button_text }) - concat(render(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) { submit_button_text }) + concat(render(Primer::Beta::Button.new(data: { "close-dialog-id": dialog_id })) { cancel_button_text }) + concat(render(Primer::Beta::Button.new(scheme: :primary, type: :submit)) { submit_button_text }) end ) end diff --git a/app/components/my/access_token/new_access_token_form_component.html.erb b/app/components/my/access_token/new_access_token_form_component.html.erb index 2079647d98d..06ad515f16b 100644 --- a/app/components/my/access_token/new_access_token_form_component.html.erb +++ b/app/components/my/access_token/new_access_token_form_component.html.erb @@ -62,11 +62,11 @@ See COPYRIGHT and LICENSE files for more details. collection.with_component(Primer::Alpha::Dialog::Footer.new) do component_collection do |footer| - footer.with_component(Primer::ButtonComponent.new(data: { "close-dialog-id": "new-access-token-dialog" })) do + footer.with_component(Primer::Beta::Button.new(data: { "close-dialog-id": "new-access-token-dialog" })) do I18n.t("button_cancel") end - footer.with_component(Primer::ButtonComponent.new(scheme: :primary, type: :submit, test_selector: "create-api-token-button")) do + footer.with_component(Primer::Beta::Button.new(scheme: :primary, type: :submit, test_selector: "create-api-token-button")) do I18n.t("my.access_token.new_access_token_dialog_submit_button_text") end end diff --git a/app/components/projects/configure_view_modal_component.html.erb b/app/components/projects/configure_view_modal_component.html.erb index 05c7ac98765..7cb21a99360 100644 --- a/app/components/projects/configure_view_modal_component.html.erb +++ b/app/components/projects/configure_view_modal_component.html.erb @@ -50,9 +50,9 @@ <% end %> <% end %> <%= render(Primer::Alpha::Dialog::Footer.new) do %> - <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> + <%= render(Primer::Beta::Button.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, data: { "test-selector": "#{MODAL_ID}-submit" }, diff --git a/app/components/settings/project_custom_field_sections/dialog_body_form_component.html.erb b/app/components/settings/project_custom_field_sections/dialog_body_form_component.html.erb index 084fbf2ddff..6acb53d204a 100644 --- a/app/components/settings/project_custom_field_sections/dialog_body_form_component.html.erb +++ b/app/components/settings/project_custom_field_sections/dialog_body_form_component.html.erb @@ -12,11 +12,11 @@ collection.with_component(Primer::Alpha::Dialog::Footer.new) do component_collection do |modal_footer| - modal_footer.with_component(Primer::ButtonComponent.new(data: { "close-dialog-id": "project-custom-field-section-dialog#{@project_custom_field_section.id}" })) do + modal_footer.with_component(Primer::Beta::Button.new(data: { "close-dialog-id": "project-custom-field-section-dialog#{@project_custom_field_section.id}" })) do t("button_cancel") end - modal_footer.with_component(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) do + modal_footer.with_component(Primer::Beta::Button.new(scheme: :primary, type: :submit)) do t("button_save") end end diff --git a/app/components/work_package_relations_tab/add_work_package_child_dialog_component.html.erb b/app/components/work_package_relations_tab/add_work_package_child_dialog_component.html.erb index 4522ef9f5fc..50d11aaecdc 100644 --- a/app/components/work_package_relations_tab/add_work_package_child_dialog_component.html.erb +++ b/app/components/work_package_relations_tab/add_work_package_child_dialog_component.html.erb @@ -17,7 +17,7 @@ d.with_footer do component_collection do |buttons| buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": DIALOG_ID } @@ -26,7 +26,7 @@ t("button_cancel") end buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: FORM_ID, data: { turbo: true }, diff --git a/app/components/work_package_relations_tab/work_package_relation_dialog_component.html.erb b/app/components/work_package_relations_tab/work_package_relation_dialog_component.html.erb index 34b0f36f814..e36a5106b07 100644 --- a/app/components/work_package_relations_tab/work_package_relation_dialog_component.html.erb +++ b/app/components/work_package_relations_tab/work_package_relation_dialog_component.html.erb @@ -18,14 +18,14 @@ d.with_footer do component_collection do |buttons| buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": DIALOG_ID } ) ) do t(:button_cancel) end buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: FORM_ID, data: { turbo: true }, diff --git a/app/components/work_packages/date_picker/date_form_component.html.erb b/app/components/work_packages/date_picker/date_form_component.html.erb index 5eaa34764b2..e47c67aa808 100644 --- a/app/components/work_packages/date_picker/date_form_component.html.erb +++ b/app/components/work_packages/date_picker/date_form_component.html.erb @@ -4,7 +4,7 @@ flex_layout do |start_date| start_date.with_row(classes: container_classes(:start_date)) do render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( tag: :a, href: single_date_field_button_link("start_date"), data: { turbo_frame: "wp-datepicker-dialog--content", morph: true }, @@ -31,7 +31,7 @@ flex_layout do |due_date| due_date.with_row(classes: container_classes(:due_date), data: { skip_morphing: true }) do render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( tag: :a, href: single_date_field_button_link("due_date"), data: { turbo_frame: "wp-datepicker-dialog--content", morph: true }, diff --git a/app/components/work_packages/date_picker/dialog_content_component.html.erb b/app/components/work_packages/date_picker/dialog_content_component.html.erb index 52138d01df6..43bbbfb747d 100644 --- a/app/components/work_packages/date_picker/dialog_content_component.html.erb +++ b/app/components/work_packages/date_picker/dialog_content_component.html.erb @@ -76,7 +76,7 @@ collection.with_component(Primer::Alpha::Dialog::Footer.new) do component_collection do |footer| footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { action: "work-packages--date-picker--preview#cancel" }, test_selector: "op-datepicker-modal--action" ) @@ -85,7 +85,7 @@ end footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, form: DIALOG_FORM_ID, diff --git a/app/components/work_packages/dialogs/create_dialog_component.html.erb b/app/components/work_packages/dialogs/create_dialog_component.html.erb index b4643d2d510..d23259f7409 100644 --- a/app/components/work_packages/dialogs/create_dialog_component.html.erb +++ b/app/components/work_packages/dialogs/create_dialog_component.html.erb @@ -1,12 +1,14 @@ <%= - render(Primer::Alpha::Dialog.new( - id: "create-work-package-dialog", - title: I18n.t(:label_work_package_new), - size: :xlarge, - data: { - 'keep-open-on-submit': true, - } - )) do |dialog| + render( + Primer::Alpha::Dialog.new( + id: "create-work-package-dialog", + title: I18n.t(:label_work_package_new), + size: :xlarge, + data: { + "keep-open-on-submit": true + } + ) + ) do |dialog| dialog.with_header(variant: :large) dialog.with_body do render(WorkPackages::Dialogs::CreateFormComponent.new(work_package:, project:)) @@ -15,18 +17,20 @@ dialog.with_footer do component_collection do |modal_footer| modal_footer.with_component( - Primer::ButtonComponent.new( - data: { 'close-dialog-id': "create-work-package-dialog" } - )) do + Primer::Beta::Button.new( + data: { "close-dialog-id": "create-work-package-dialog" } + ) + ) do I18n.t(:button_cancel) end modal_footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: "create-work-package-form", type: :submit - )) do + ) + ) do if @work_package.persisted? I18n.t(:button_save) else diff --git a/app/components/work_packages/exports/generate/modal_dialog_component.html.erb b/app/components/work_packages/exports/generate/modal_dialog_component.html.erb index 746f9f13084..25757428b8a 100644 --- a/app/components/work_packages/exports/generate/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/generate/modal_dialog_component.html.erb @@ -130,9 +130,9 @@ end %> <% end %> <% dialog.with_footer do %> - <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> + <%= render(Primer::Beta::Button.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, form: GENERATE_PDF_FORM_ID, diff --git a/app/components/work_packages/exports/modal_dialog_component.html.erb b/app/components/work_packages/exports/modal_dialog_component.html.erb index e4ad7a825e1..6c95eec0deb 100644 --- a/app/components/work_packages/exports/modal_dialog_component.html.erb +++ b/app/components/work_packages/exports/modal_dialog_component.html.erb @@ -69,9 +69,9 @@ ) %> <% end %> <% end %> - <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> + <%= render(Primer::Beta::Button.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %> <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "work-packages--export--dialog-target": "submit" }, diff --git a/modules/costs/app/components/time_entries/entry_dialog_component.html.erb b/modules/costs/app/components/time_entries/entry_dialog_component.html.erb index 836bbdb7192..6dbcc8c26b9 100644 --- a/modules/costs/app/components/time_entries/entry_dialog_component.html.erb +++ b/modules/costs/app/components/time_entries/entry_dialog_component.html.erb @@ -15,7 +15,7 @@ <% if time_entry.persisted? %> <% flex.with_column do %> <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :danger, test_selector: "destroy-time-entry-button", data: { @@ -32,10 +32,10 @@ <% flex.with_column(classes: "time-entry-button-push") %> <% flex.with_column do %> <%= render( - Primer::ButtonComponent.new(data: { "close-dialog-id": "time-entry-dialog" }) + Primer::Beta::Button.new(data: { "close-dialog-id": "time-entry-dialog" }) ) { I18n.t("button_cancel") } %> <%= render( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, test_selector: "create-time-entry-button", diff --git a/modules/meeting/app/components/meetings/index/dialog_component.html.erb b/modules/meeting/app/components/meetings/index/dialog_component.html.erb index 6513667bd61..703820c53c2 100644 --- a/modules/meeting/app/components/meetings/index/dialog_component.html.erb +++ b/modules/meeting/app/components/meetings/index/dialog_component.html.erb @@ -21,7 +21,7 @@ dialog.with_footer do component_collection do |modal_footer| modal_footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": "new-meeting-dialog" } ) ) do @@ -29,7 +29,7 @@ end modal_footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: "meeting-form", type: :submit diff --git a/modules/meeting/app/components/meetings/side_panel/details_form_component.html.erb b/modules/meeting/app/components/meetings/side_panel/details_form_component.html.erb index 567773ead27..12cc5313487 100644 --- a/modules/meeting/app/components/meetings/side_panel/details_form_component.html.erb +++ b/modules/meeting/app/components/meetings/side_panel/details_form_component.html.erb @@ -33,11 +33,11 @@ collection.with_component(Primer::Alpha::Dialog::Footer.new) do component_collection do |modal_footer| - modal_footer.with_component(Primer::ButtonComponent.new(data: { "close-dialog-id": "edit-meeting-details-dialog" })) do + modal_footer.with_component(Primer::Beta::Button.new(data: { "close-dialog-id": "edit-meeting-details-dialog" })) do t("button_cancel") end - modal_footer.with_component(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) do + modal_footer.with_component(Primer::Beta::Button.new(scheme: :primary, type: :submit)) do t("button_save") end end diff --git a/modules/meeting/app/components/meetings/side_panel/participants_dialog.html.erb b/modules/meeting/app/components/meetings/side_panel/participants_dialog.html.erb index 18922ae2ba3..343d37ce3a7 100644 --- a/modules/meeting/app/components/meetings/side_panel/participants_dialog.html.erb +++ b/modules/meeting/app/components/meetings/side_panel/participants_dialog.html.erb @@ -135,11 +135,11 @@ if @meeting.editable? d.with_footer do component_collection do |footer| - footer.with_component(Primer::ButtonComponent.new(data: { "close-dialog-id": "edit-participants-dialog" })) do + footer.with_component(Primer::Beta::Button.new(data: { "close-dialog-id": "edit-participants-dialog" })) do t("button_cancel") end footer.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: "edit_participants_form", data: { turbo: true }, diff --git a/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_dialog_component.html.erb b/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_dialog_component.html.erb index c11239c337c..6b03a774dd9 100644 --- a/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_dialog_component.html.erb +++ b/modules/meeting/app/components/work_package_meetings_tab/add_work_package_to_meeting_dialog_component.html.erb @@ -18,7 +18,7 @@ d.with_footer do component_collection do |buttons| buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": "add-work-package-to-meeting-dialog" } @@ -27,7 +27,7 @@ t("button_cancel") end buttons.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, form: "add-work-package-to-meeting-form", data: { turbo: true }, diff --git a/modules/overviews/app/components/project_custom_fields/sections/edit_dialog_component.html.erb b/modules/overviews/app/components/project_custom_fields/sections/edit_dialog_component.html.erb index 1c4859b33cb..f91bbdc89b2 100644 --- a/modules/overviews/app/components/project_custom_fields/sections/edit_dialog_component.html.erb +++ b/modules/overviews/app/components/project_custom_fields/sections/edit_dialog_component.html.erb @@ -13,7 +13,7 @@ d.with_footer do component_collection do |footer_collection| footer_collection.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": "edit-project-custom-fields-dialog-#{@project_custom_field_section.id}" } @@ -22,7 +22,7 @@ t("button_cancel") end footer_collection.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, form: "project-section-edit-form", diff --git a/modules/overviews/app/components/project_life_cycles/sections/edit_dialog_component.html.erb b/modules/overviews/app/components/project_life_cycles/sections/edit_dialog_component.html.erb index 1a027271f46..ef4016a23f5 100644 --- a/modules/overviews/app/components/project_life_cycles/sections/edit_dialog_component.html.erb +++ b/modules/overviews/app/components/project_life_cycles/sections/edit_dialog_component.html.erb @@ -13,7 +13,7 @@ d.with_footer do component_collection do |footer_collection| footer_collection.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( data: { "close-dialog-id": DIALOG_ID } @@ -22,7 +22,7 @@ t("button_cancel") end footer_collection.with_component( - Primer::ButtonComponent.new( + Primer::Beta::Button.new( scheme: :primary, type: :submit, form: "project-life-cycles-edit-form", diff --git a/modules/storages/app/components/storages/admin/storages/projects_storage_form_modal_component.html.erb b/modules/storages/app/components/storages/admin/storages/projects_storage_form_modal_component.html.erb index fd3e5c3201e..5c14bfa3dde 100644 --- a/modules/storages/app/components/storages/admin/storages/projects_storage_form_modal_component.html.erb +++ b/modules/storages/app/components/storages/admin/storages/projects_storage_form_modal_component.html.erb @@ -85,8 +85,8 @@ See COPYRIGHT and LICENSE files for more details. concat( render(Primer::Alpha::Dialog::Footer.new(show_divider: false)) do - concat(render(Primer::ButtonComponent.new(data: { "close-dialog-id": dialog_id })) { cancel_button_text }) - concat(render(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) { submit_button_text }) + concat(render(Primer::Beta::Button.new(data: { "close-dialog-id": dialog_id })) { cancel_button_text }) + concat(render(Primer::Beta::Button.new(scheme: :primary, type: :submit)) { submit_button_text }) end ) end diff --git a/modules/storages/app/components/storages/open_project_storage_modal_component.html.erb b/modules/storages/app/components/storages/open_project_storage_modal_component.html.erb index 51001781bd3..6ca4884f067 100644 --- a/modules/storages/app/components/storages/open_project_storage_modal_component.html.erb +++ b/modules/storages/app/components/storages/open_project_storage_modal_component.html.erb @@ -10,6 +10,6 @@ <%= render(self.class::Body.new(@state)) %> <% end %> <% dialog.with_footer do %> - <%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": self.class.dialog_id })) { I18n.t("button_close") } %> + <%= render(Primer::Beta::Button.new(data: { "close-dialog-id": self.class.dialog_id })) { I18n.t("button_close") } %> <% end %> <% end %> From 7ad332d86cfda78ef72425c351bc522de244beb4 Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Fri, 4 Apr 2025 09:26:15 +0200 Subject: [PATCH 072/260] actually disable comments with restricted visibility with project setting is disabled --- .../activities_tab/journals/new_component.rb | 1 + app/models/work_package/journalized.rb | 1 + .../restricted_visibility_comments_spec.rb | 37 +++++++++++--- .../work_package_acts_as_journalized_spec.rb | 51 ++++++++++++++----- 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/app/components/work_packages/activities_tab/journals/new_component.rb b/app/components/work_packages/activities_tab/journals/new_component.rb index f84262eb508..4b691638f75 100644 --- a/app/components/work_packages/activities_tab/journals/new_component.rb +++ b/app/components/work_packages/activities_tab/journals/new_component.rb @@ -60,6 +60,7 @@ module WorkPackages def adding_restricted_comment_allowed? OpenProject::FeatureDecisions.comments_with_restricted_visibility_active? && + work_package.project.enabled_comments_with_restricted_visibility && User.current.allowed_in_project?(:add_comments_with_restricted_visibility, work_package.project) end diff --git a/app/models/work_package/journalized.rb b/app/models/work_package/journalized.rb index 0ff0d06be3f..2bfd855df77 100644 --- a/app/models/work_package/journalized.rb +++ b/app/models/work_package/journalized.rb @@ -33,6 +33,7 @@ module WorkPackage::Journalized acts_as_journalized journals_association_extension: proc { def restricted_visible if OpenProject::FeatureDecisions.comments_with_restricted_visibility_active? && + proxy_association.owner.project.enabled_comments_with_restricted_visibility && User.current.allowed_in_project?(:view_comments_with_restricted_visibility, proxy_association.owner.project) all else diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index 1b9fbecfc41..e23cf28c98b 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -52,17 +52,40 @@ RSpec.describe "Work package comments with restricted visibility", context "with an admin user" do current_user { admin } - before do - wp_page.visit! - wp_page.wait_for_activity_tab + context "when the feature is enabled for the project" do + before do + project.enabled_comments_with_restricted_visibility = true + project.save! + + wp_page.visit! + wp_page.wait_for_activity_tab + end + + it "allows adding a comment with restricted visibility" do + activity_tab.expect_input_field + + activity_tab.add_comment(text: "First (restricted) comment by admin", restricted: true) + + activity_tab.expect_journal_notes(text: "First (restricted) comment by admin") + end end - it "allows adding a comment with restricted visibility" do - activity_tab.expect_input_field + context "when the feature is not enabled for the project" do + before do + project.enabled_comments_with_restricted_visibility = false + project.save! - activity_tab.add_comment(text: "First (restricted) comment by admin", restricted: true) + wp_page.visit! + wp_page.wait_for_activity_tab + end - activity_tab.expect_journal_notes(text: "First (restricted) comment by admin") + it "allows adding a comment with restricted visibility" do + activity_tab.expect_input_field + + activity_tab.type_comment("This comment cannot be restricted") + + expect(page).not_to have_test_selector("op-work-package-journal-restricted-comment-checkbox") + end end end diff --git a/spec/models/work_package/work_package_acts_as_journalized_spec.rb b/spec/models/work_package/work_package_acts_as_journalized_spec.rb index 9a211518c20..1ba39f407cc 100644 --- a/spec/models/work_package/work_package_acts_as_journalized_spec.rb +++ b/spec/models/work_package/work_package_acts_as_journalized_spec.rb @@ -903,10 +903,45 @@ RSpec.describe WorkPackage do end context "when comments_with_restricted_visibility is enabled", with_flag: { comments_with_restricted_visibility: true } do - context "when the user cannot see restricted journals" do + context "and setting is enabled for the project" do before do + work_package.project.enabled_comments_with_restricted_visibility = true + work_package.project.save! + end + + context "when the user cannot see restricted journals" do + before do + mock_permissions_for(user) do |mock| + mock.allow_in_work_package :view_work_packages, work_package: + end + end + + it "does not return the restricted journal" do + expect(journals.map(&:id)).not_to include(restricted_note.id) + expect(journals.map(&:id)).to include(unrestricted_note.id) + end + end + + context "when the user can see restricted journals" do + before do + mock_permissions_for(user) do |mock| + mock.allow_in_project(:view_comments_with_restricted_visibility, project: work_package.project) + end + end + + it "returns all journals" do + expect(journals.map(&:id)).to include(restricted_note.id, unrestricted_note.id) + end + end + end + + context "and setting is disabled for the project" do + before do + work_package.project.enabled_comments_with_restricted_visibility = false + work_package.project.save! + mock_permissions_for(user) do |mock| - mock.allow_in_work_package :view_work_packages, work_package: + mock.allow_in_project(:view_comments_with_restricted_visibility, project: work_package.project) end end @@ -915,18 +950,6 @@ RSpec.describe WorkPackage do expect(journals.map(&:id)).to include(unrestricted_note.id) end end - - context "when the user can see restricted journals" do - before do - mock_permissions_for(user) do |mock| - mock.allow_in_project(:view_comments_with_restricted_visibility, project: work_package.project) - end - end - - it "returns all journals" do - expect(journals.map(&:id)).to include(restricted_note.id, unrestricted_note.id) - end - end end context "when comments_with_restricted_visibility is disabled", with_flag: { comments_with_restricted_visibility: false } do From c49cb779edd4175760848b85fcaf5cd29665908c Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Fri, 4 Apr 2025 09:56:14 +0200 Subject: [PATCH 073/260] adjust spec with project config --- spec/features/activities/work_package/activities_spec.rb | 2 +- .../work_package/restricted_visibility_comments_spec.rb | 5 +---- .../api/v3/activities_by_work_package_resource_spec.rb | 5 +++++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/features/activities/work_package/activities_spec.rb b/spec/features/activities/work_package/activities_spec.rb index 73ad5d2fd03..2aef16171dc 100644 --- a/spec/features/activities/work_package/activities_spec.rb +++ b/spec/features/activities/work_package/activities_spec.rb @@ -34,7 +34,7 @@ require "support/flash/expectations" RSpec.describe "Work package activity", :js, :with_cuprite do include Flash::Expectations - let(:project) { create(:project) } + let(:project) { create(:project, enabled_comments_with_restricted_visibility: true) } let(:admin) { create(:admin) } let(:member_role) do create(:project_role, diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index e23cf28c98b..4bde8840479 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -34,7 +34,7 @@ RSpec.describe "Work package comments with restricted visibility", :js, :with_cuprite, with_flag: { comments_with_restricted_visibility: true } do - let(:project) { create(:project) } + let(:project) { create(:project, enabled_comments_with_restricted_visibility: true) } let(:admin) { create(:admin) } let(:viewer) { create_user_with_restricted_comments_view_permissions } let(:viewer_with_commenting_permission) { create_user_with_restricted_comments_view_and_write_permissions } @@ -54,9 +54,6 @@ RSpec.describe "Work package comments with restricted visibility", context "when the feature is enabled for the project" do before do - project.enabled_comments_with_restricted_visibility = true - project.save! - wp_page.visit! wp_page.wait_for_activity_tab end diff --git a/spec/requests/api/v3/activities_by_work_package_resource_spec.rb b/spec/requests/api/v3/activities_by_work_package_resource_spec.rb index 3695d192104..d777e6f70c5 100644 --- a/spec/requests/api/v3/activities_by_work_package_resource_spec.rb +++ b/spec/requests/api/v3/activities_by_work_package_resource_spec.rb @@ -80,6 +80,11 @@ RSpec.describe API::V3::Activities::ActivitiesByWorkPackageAPI do # rubocop:disa version: 2) end + before do + project.enabled_comments_with_restricted_visibility = true + project.save! + end + context "and user has the permission to see it" do it "includes restricted activities" do get api_v3_paths.work_package_activities work_package.id From 6e809e169f0986b899361d1d5bf926268d99ea97 Mon Sep 17 00:00:00 2001 From: ulferts Date: Fri, 4 Apr 2025 13:24:12 +0200 Subject: [PATCH 074/260] update life cycle string --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 2b963fee3cf..ea03d5a5268 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3969,7 +3969,7 @@ en: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" From 39f102ab360770fee5f570e4f94e09bc2cfbaba6 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Fri, 4 Apr 2025 11:33:34 +0000 Subject: [PATCH 075/260] update locales from crowdin [ci skip] --- config/locales/crowdin/af.yml | 2 +- config/locales/crowdin/ar.yml | 2 +- config/locales/crowdin/az.yml | 2 +- config/locales/crowdin/be.yml | 2 +- config/locales/crowdin/bg.yml | 2 +- config/locales/crowdin/ca.yml | 2 +- config/locales/crowdin/ckb-IR.yml | 2 +- config/locales/crowdin/cs.yml | 54 +++---- config/locales/crowdin/da.yml | 2 +- config/locales/crowdin/de.seeders.yml | 20 +-- config/locales/crowdin/de.yml | 140 +++++++++--------- config/locales/crowdin/el.yml | 2 +- config/locales/crowdin/eo.yml | 2 +- config/locales/crowdin/es.yml | 4 +- config/locales/crowdin/et.yml | 2 +- config/locales/crowdin/eu.yml | 2 +- config/locales/crowdin/fa.yml | 2 +- config/locales/crowdin/fi.yml | 2 +- config/locales/crowdin/fil.yml | 2 +- config/locales/crowdin/fr.yml | 2 +- config/locales/crowdin/he.yml | 2 +- config/locales/crowdin/hi.yml | 2 +- config/locales/crowdin/hr.yml | 2 +- config/locales/crowdin/hu.yml | 2 +- config/locales/crowdin/id.yml | 4 +- config/locales/crowdin/it.yml | 16 +- config/locales/crowdin/ja.yml | 2 +- config/locales/crowdin/js-ca.yml | 2 +- config/locales/crowdin/js-da.yml | 2 +- config/locales/crowdin/js-id.yml | 2 +- config/locales/crowdin/js-no.yml | 2 +- config/locales/crowdin/js-ro.yml | 2 +- config/locales/crowdin/js-ru.yml | 2 +- config/locales/crowdin/js-vi.yml | 2 +- config/locales/crowdin/ka.yml | 2 +- config/locales/crowdin/kk.yml | 2 +- config/locales/crowdin/ko.yml | 2 +- config/locales/crowdin/lt.yml | 2 +- config/locales/crowdin/lv.yml | 2 +- config/locales/crowdin/mn.yml | 2 +- config/locales/crowdin/ms.yml | 2 +- config/locales/crowdin/ne.yml | 2 +- config/locales/crowdin/nl.yml | 2 +- config/locales/crowdin/no.yml | 2 +- config/locales/crowdin/pl.yml | 4 +- config/locales/crowdin/pt-BR.yml | 2 +- config/locales/crowdin/pt-PT.yml | 2 +- config/locales/crowdin/ro.yml | 6 +- config/locales/crowdin/ru.seeders.yml | 24 +-- config/locales/crowdin/ru.yml | 102 ++++++------- config/locales/crowdin/rw.yml | 2 +- config/locales/crowdin/si.yml | 2 +- config/locales/crowdin/sk.yml | 2 +- config/locales/crowdin/sl.yml | 6 +- config/locales/crowdin/sr.yml | 2 +- config/locales/crowdin/sv.yml | 2 +- config/locales/crowdin/th.yml | 2 +- config/locales/crowdin/tr.yml | 2 +- config/locales/crowdin/uk.yml | 4 +- config/locales/crowdin/uz.yml | 2 +- config/locales/crowdin/vi.yml | 4 +- config/locales/crowdin/zh-CN.seeders.yml | 4 +- config/locales/crowdin/zh-CN.yml | 16 +- config/locales/crowdin/zh-TW.yml | 10 +- .../backlogs/config/locales/crowdin/ro.yml | 2 +- .../backlogs/config/locales/crowdin/zh-TW.yml | 2 +- modules/bim/config/locales/crowdin/fr.yml | 2 +- modules/budgets/config/locales/crowdin/cs.yml | 2 +- modules/costs/config/locales/crowdin/de.yml | 8 +- .../costs/config/locales/crowdin/js-ca.yml | 2 +- .../costs/config/locales/crowdin/js-ro.yml | 2 +- .../config/locales/crowdin/zh-CN.yml | 2 +- .../config/locales/crowdin/zh-TW.yml | 2 +- modules/meeting/config/locales/crowdin/cs.yml | 2 +- modules/meeting/config/locales/crowdin/de.yml | 6 +- modules/meeting/config/locales/crowdin/ru.yml | 2 +- .../meeting/config/locales/crowdin/zh-CN.yml | 4 +- .../meeting/config/locales/crowdin/zh-TW.yml | 2 +- .../reporting/config/locales/crowdin/ro.yml | 2 +- .../config/locales/crowdin/zh-TW.yml | 4 +- .../storages/config/locales/crowdin/de.yml | 8 +- .../config/locales/crowdin/js-fr.yml | 2 +- .../config/locales/crowdin/ro.yml | 2 +- .../config/locales/crowdin/ru.yml | 2 +- .../config/locales/crowdin/uk.yml | 2 +- .../config/locales/crowdin/zh-CN.yml | 2 +- 86 files changed, 289 insertions(+), 289 deletions(-) diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml index 587e5c54b3d..d3f96ccb80f 100644 --- a/config/locales/crowdin/af.yml +++ b/config/locales/crowdin/af.yml @@ -3789,7 +3789,7 @@ af: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml index f4068a23f22..d0aede8f8db 100644 --- a/config/locales/crowdin/ar.yml +++ b/config/locales/crowdin/ar.yml @@ -3951,7 +3951,7 @@ ar: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml index 71255f8add7..5d8405843d4 100644 --- a/config/locales/crowdin/az.yml +++ b/config/locales/crowdin/az.yml @@ -3789,7 +3789,7 @@ az: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml index 2f925203d5e..d9e2fb12d61 100644 --- a/config/locales/crowdin/be.yml +++ b/config/locales/crowdin/be.yml @@ -3871,7 +3871,7 @@ be: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index ffd42318f81..706126c1e5a 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -3789,7 +3789,7 @@ bg: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index 28885759162..6c615bf7790 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -3780,7 +3780,7 @@ ca: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml index cbf56f9c6ba..cedf11f9baa 100644 --- a/config/locales/crowdin/ckb-IR.yml +++ b/config/locales/crowdin/ckb-IR.yml @@ -3789,7 +3789,7 @@ ckb-IR: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index 765dda18ba2..4e83763ae2d 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -559,7 +559,7 @@ cs: irreversible: "Tato akce je nevratná" confirmation: "Zadejte název zástupného uživatele %{name} pro potvrzení odstranění." upsale: - title: Placeholder uživatel + title: placeholder uživatel description: > Placeholder uživatelé jsou způsob, jak přiřadit pracovní balíčky uživatelům, kteří nejsou součástí vašeho projektu. Mohou být užiteční v řadě scénářů; například, pokud potřebujete sledovat úkoly u zdroje, který ještě nejsou pojmenovány nebo dostupné, nebo pokud nechcete této osobě umožnit přístup k OpenProject ale stále chcete sledovat úkoly, které jim byly přiděleny. prioritiies: @@ -947,7 +947,7 @@ cs: enabled_modules: "Povolené moduly" identifier: "Identifikátor" latest_activity_at: "Poslední aktivita" - parent: "Nadřazený projekt" + parent: "Podprojekt" public_value: title: "Viditelnost" true: "veřejný" @@ -1246,7 +1246,7 @@ cs: meeting: error_conflict: "Nelze uložit, protože schůzku mezitím aktualizoval někdo jiný. Znovu načtěte stránku." notifications: - at_least_one_channel: "Pro odesílání notifikací musí být specifikován alespoň jeden kanál" + at_least_one_channel: "Alespoň jeden kanál pro odesílání oznámení musí být specifikován." attributes: read_ian: read_on_creation: "nelze nastavit na pravdivé při vytváření oznámení " @@ -1520,11 +1520,11 @@ cs: member: "Člen" news: "Novinky" notification: - one: "Notifikace" - few: "Notifikací" - many: "Notifikací" - other: "Notifikace" - placeholder_user: "Placeholder uživatel" + one: "Oznámení" + few: "Oznámení" + many: "Oznámení" + other: "Oznámení" + placeholder_user: "placeholder uživatel" project: "Projekt" project_query: one: "Seznam projektů" @@ -2348,7 +2348,7 @@ cs: instructions_after_error: "Zkuste se znovu přihlásit kliknutím na %{signin}. Pokud chyba přetrvává, požádejte správce o pomoc." menus: admin: - mail_notification: "E-mailové notifikace" + mail_notification: "E-mailová upozornění" mails_and_notifications: "E-maily a oznámení" aggregation: "Agregace" api_and_webhooks: "API & Webhooky" @@ -2410,7 +2410,7 @@ cs: by_project: "Nepřečteno dle projektu" by_reason: "Důvod" inbox: "Doručená pošta" - send_notifications: "Pro tuto akci odeslat notifikaci" + send_notifications: "Odeslat oznámení pro tuto akci" work_packages: subject: created: "Pracovní balíček byl vytvořen." @@ -2824,9 +2824,9 @@ cs: label_permissions: "Práva" label_permissions_report: "Přehled oprávnění" label_personalize_page: "Přizpůsobit tuto stránku" - label_placeholder_user: "Placeholder uživatel" + label_placeholder_user: "placeholder uživatel" label_placeholder_user_new: "" - label_placeholder_user_plural: "Placeholder uživatelé" + label_placeholder_user_plural: "placeholder uživatelé" label_planning: "Plánování" label_please_login: "Přihlaste se prosím" label_plugins: "Pluginy" @@ -2849,7 +2849,7 @@ cs: label_project_attribute_plural: "Atributy projektu" label_project_attribute_manage_link: "Správa atributů produktu" label_project_count: "Celkový počet projektů" - label_project_copy_notifications: "Během kopírování projektu odeslat notifikace e-mailem" + label_project_copy_notifications: "Během kopie projektu odeslat oznámení e-mailem" label_project_latest: "Nejnovější projekty" label_project_default_type: "Povolit prázdný typ" label_project_hierarchy: "Hierarchie projektu" @@ -3005,7 +3005,7 @@ cs: label_version_new: "Nová verze" label_version_edit: "Upravit verzi" label_version_plural: "Verze" - label_version_sharing_descendants: "S podprojekty" + label_version_sharing_descendants: "S Podprojekty" label_version_sharing_hierarchy: "S hierarchií projektu" label_version_sharing_none: "Není sdíleno" label_version_sharing_system: "Se všemi projekty" @@ -3110,28 +3110,28 @@ cs: digests: including_mention_singular: "včetně zmínky" including_mention_plural: "včetně %{number_mentioned} zmínění" - unread_notification_singular: "1 nepřečtená notifikace" - unread_notification_plural: "%{number_unread} nepřečtených notifikací" + unread_notification_singular: "1 nepřečtené oznámení" + unread_notification_plural: "%{number_unread} nepřečtených oznámení" you_have: "Máte" logo_alt_text: "Logo" mention: subject: "%{user_name} vás zmínil v #%{id} - %{subject}" notification: - center: "Centrum notifikací" + center: "Centrum oznámení" see_in_center: "Zobrazit komentář v oznamovacím centru" settings: "Změnit nastavení e-mailu" salutation: "Ahoj %{user}!" salutation_full_name: "Jméno a příjmení" work_packages: created_at: "Vytvořeno v %{timestamp} uživatelem %{user} " - login_to_see_all: "Přihlaste se pro zobrazení všech notifikací." + login_to_see_all: "Přihlaste se pro zobrazení všech oznámení." mentioned: "Byli jste zmíněni v komentáři" mentioned_by: "%{user} vás zmínil v komentáři OpenProject" more_to_see: - one: "Existuje ještě 1 pracovní balíček s notifikací." - few: "Existuje ještě %{count} pracovních balíčků s notifikacema." - many: "Existuje ještě %{count} pracovních balíčků s notifikacema." - other: "Existuje ještě %{count} pracovních balíčků s notifikacema." + one: "Máte ještě 1 pracovní balíček s notifikací." + few: "Existuje ještě %{count} pracovních balíčků s oznámeními." + many: "Máte ještě %{count} pracovních balíčků s notifikacemi." + other: "Existuje ještě %{count} pracovních balíčků s oznámeními." open_in_browser: "Otevřít v prohlížeči" reason: watched: "Sledováno" @@ -3140,7 +3140,7 @@ cs: mentioned: "Zmíněné" shared: "Sdílené" subscribed: "vše" - prefix: "Obdrženo z důvodu nastavení notifikací: %{reason}" + prefix: "Obdrženo z důvodu nastavení oznámení: %{reason}" date_alert_start_date: "Upozornění na datum" date_alert_due_date: "Upozornění na datum" reminder: "Připomínka" @@ -3427,7 +3427,7 @@ cs: permission_move_work_packages: "Přesun pracovních balíčků" permission_protect_wiki_pages: "Ochrana stránky wiki" permission_rename_wiki_pages: "Přejmenovat stránky wiki" - permission_save_queries: "Uložit zobrazení" + permission_save_queries: "Uložit pohled" permission_search_project: "Hledat projekt" permission_select_custom_fields: "Vybrat vlastní pole" permission_select_project_custom_fields: "Vyberte atributy projektu" @@ -3848,7 +3848,7 @@ cs: enable_subscriptions_text_html: Umožňuje uživatelům s nezbytnými oprávněními přihlásit se do OpenProject kalendářů a získat přístup k informacím o pracovním balíčku prostřednictvím externího klienta kalendáře. Poznámka: Před povolením si prosím přečtěte podrobnosti o odběru. language_name_being_default: "%{language_name} (výchozí)" notifications: - events_explanation: "Určuje, pro kterou událost je odeslán e-mail. Pracovní balíčky jsou z tohoto seznamu vyloučeny, protože notifikace pro ně mohou být nastavena speciálně pro každého uživatele." + events_explanation: "Určuje, pro kterou událost je odeslán e-mail. Pracovní balíčky jsou z tohoto seznamu vyloučeny, protože oznámení pro ně mohou být nastavena speciálně pro každého uživatele." delay_minutes_explanation: "Odesílání e-mailu může být pozdrženo, aby bylo uživatelům s nakonfigurovaným v oznámení aplikace před odesláním pošty potvrzeno oznámení. Uživatelé, kteří si přečtou oznámení v aplikaci, nedostanou e-mail pro již přečtené oznámení." other: "Ostatní" passwords: "Hesla" @@ -3870,7 +3870,7 @@ cs: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" @@ -3957,7 +3957,7 @@ cs: text_destroy_with_associated: "Existují další objekty, které jsou přiřazeny k pracovním balíčkům a které mají být odstraněny. Tyto objekty jsou následující typy:" text_destroy_what_to_do: "Co chcete udělat?" text_diff_truncated: "... Toto rozlišení bylo zkráceno, protože přesahuje maximální velikost, kterou lze zobrazit." - text_email_delivery_not_configured: "Doručení e-mailu není nakonfigurováno a notifikace jsou zakázány.\nNakonfigurujte váš SMTP server pro jejich povolení." + text_email_delivery_not_configured: "Doručení e-mailu není nakonfigurováno a oznámení jsou zakázána.\nNakonfigurujte váš SMTP server pro jejich povolení." text_enumeration_category_reassign_to: "Přiřadit je k této hodnotě:" text_enumeration_destroy_question: "%{count} objektů je přiřazeno k této hodnotě." text_file_repository_writable: "Do adresáře příloh lze zapisovat" diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml index 32b6c0babbf..fc3ecd6c1b9 100644 --- a/config/locales/crowdin/da.yml +++ b/config/locales/crowdin/da.yml @@ -3785,7 +3785,7 @@ da: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/de.seeders.yml b/config/locales/crowdin/de.seeders.yml index dcebf7ba997..1f3ec5fa73c 100644 --- a/config/locales/crowdin/de.seeders.yml +++ b/config/locales/crowdin/de.seeders.yml @@ -38,11 +38,11 @@ de: item_0: name: PM2 Orange item_1: - name: PM2 Red + name: PM2 Rot item_2: name: PM2 Magenta item_3: - name: PM2 Green Yellow + name: PM2 Grüngelb document_categories: item_0: name: Dokumentation @@ -81,16 +81,16 @@ de: standard: project_phases: item_0: - name: Initiating + name: Initiierung item_1: - name: Planning - start_gate: Ready for Planning + name: Planung + start_gate: Bereit für Planung item_2: - name: Executing - start_gate: Ready for Executing + name: Durchführung + start_gate: Bereit für Durchführung item_3: - name: Closing - start_gate: Ready for Closing + name: Abschluss + start_gate: Bereit für Abschluss priorities: item_0: name: Niedrig @@ -485,7 +485,7 @@ de: item_1: name: Meilenstein item_2: - name: Summary task + name: Sammelvorgang item_3: name: Feature item_4: diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 0fcaea99c7f..28b23f8357e 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -64,7 +64,7 @@ de: main-menu-bg-hover-background: "Hintergrundfarbe des Hauptmenüs bei Hover" custom_colors: "Benutzerdefinierte Farben" customize: "Passen Sie Ihre OpenProject Installation mit Ihrem eigenen Logo und eigenen Farben an." - enterprise_notice: "Dieses kleine Add-on steht den Abonnenten der Enterprise-Edition ganz exklusiv als kleines Dankeschön für deren finanzielle Unterstützung zur Verfügung." + enterprise_notice: "Diese kleine Erweiterung steht den Abonnenten der Enterprise edition ganz exklusiv als kleines Dankeschön für deren finanzielle Unterstützung zur Verfügung." enterprise_more_info: "Hinweis: Das verwendete Logo wird öffentlich zugänglich sein." manage_colors: "Farbauswahloptionen bearbeiten" instructions: @@ -77,15 +77,15 @@ de: main-menu-bg-color: "Hintergrundfarbe des Menüs in der linken Seitenleiste." theme_warning: Das Ändern des Themes wird Ihr benutzerdefiniertes Design überschreiben. Alle Änderungen werden dann verloren gehen. Sind Sie sicher, dass Sie fortfahren möchten? enterprise: - upgrade_to_ee: "Auf Enterprise-Edition upgraden" - add_token: "Enterprise-Edition Support Token hochladen" + upgrade_to_ee: "Auf Enterprise edition upgraden" + add_token: "Enterprise edition Support Token hochladen" delete_token_modal: - text: "Sind Sie sicher, dass Sie das aktuelle Enterprise Edition-Token entfernen möchten?" + text: "Sind Sie sicher, dass Sie das aktuelle Enterprise edition token entfernen möchten?" title: "Token löschen" replace_token: "Aktuellen Enterprise edition Support Token ersetzen" order: "Enterprise on-premises bestellen" - paste: "Enterprise-Edition Support Token hier einfügen" - required_for_feature: "Dieses Add-on ist nur mit einem aktiven Enterprise-Edition Support-Token verfügbar." + paste: "Enterprise edition Support Token hier einfügen" + required_for_feature: "Dieses Add-on ist nur mit einem aktiven Enterprise edition Support-Token verfügbar." enterprise_link: "Klicken Sie hier für weitere Informationen." start_trial: "Kostenlose Testversion starten" book_now: "Jetzt buchen" @@ -366,14 +366,14 @@ de: no_results_title_text: Derzeit stehen keine benutzerdefinierten Felder zur Verfügung. life_cycle: header: - title: "Project life cycle" - description_html: "The active project phases define this project's life cycle and are defined in the administration settings. Enabled phases will be displayed in your project overview." - non_defined: "No phases are currently defined." - section_header: "Phases" + title: "Projekt-Lebenszyklus" + description_html: "Die aktiven Projektphasen definieren den Lebenszyklus dieses Projekts und sind in den Administrationseinstellungendefiniert. Aktivierte Phasen werden in Ihrer Projektübersicht angezeigt." + non_defined: "Derzeit sind keine Phasen definiert." + section_header: "Phasen" step: use_in_project: "%{step} in diesem Projekt verwenden" filter: - label: "Search project phase" + label: "Projektphase durchsuchen" project_custom_fields: header: title: "Projektattribute" @@ -400,8 +400,8 @@ de: new_label: "Neue Priorität" project_phase: working_days_count: - one: "Duration: %{count} working day" - other: "Duration: %{count} working days" + one: "Dauer: %{count} Arbeitstag" + other: "Dauer: %{count} Arbeitstage" lists: create: success: "Die geänderte Liste wurde als neue Liste gespeichert" @@ -608,13 +608,13 @@ de: subject_configuration: tab: "Titel konfigurieren" manually_editable_subjects: - label: "Manuell bearbeitbare Titel" - caption: "Benutzer können die Titel der Arbeitspakete ohne Einschränkungen manuell eingeben und bearbeiten." + label: "Manuell bearbeitbare Themen" + caption: "Benutzer können die Themen der Arbeitspakete ohne Einschränkungen manuell eingeben und bearbeiten." automatically_generated_subjects: - label: "Automatisch generierte Titel" - caption: "Definieren Sie ein Schema aus referenzierten Attributen und Freitext für die automatische Generierung von Arbeitspakettiteln. Nutzer können diese nicht manuell editieren." + label: "Automatisch generierte Themen" + caption: "Definieren Sie ein Schema aus referenzierten Attributen und Freitext für die automatische Generierung von Arbeitspaketthemen. Nutzer können diese nicht manuell editieren." pattern: - label: "Titel-Schema" + label: "Thema-Schema" caption: "Fügen Sie Text oder Typ / um nach einem Attribut zu suchen. Sie können Leerzeichen hinzufügen, um sie zu trennen." headings: work_package: "Arbeitspaket" @@ -948,15 +948,15 @@ de: is_required: "In allen Projekten erforderlich" custom_field_section: Abschnitt project/phase: - date_range: "Date range" + date_range: "Zeitraum" definition: "Definition" project/phase_definition: name: "Name" - color: "Color" - start_gate: "Start phase gate" - start_gate_name: "Start phase gate name" - finish_gate: "Finish phase gate" - finish_gate_name: "Finish phase gate name" + color: "Farbe" + start_gate: "Phasen-Gate zum Beginn" + start_gate_name: "Name des Phasen-Gates zum Beginn" + finish_gate: "Phasen-Gate zum Ende" + finish_gate_name: "Name des Phasen-Gates zum Ende" query: sums: "Summen" columns: "Spalten" @@ -1260,9 +1260,9 @@ de: project/phase: attributes: date_range: - start_date_must_be_before_finish_date: "start date must be before the finish date." - non_continuous_dates: "can't be earlier than the previous phase's end date." - incomplete: "is incomplete." + start_date_must_be_before_finish_date: "Startdatum muss vor dem Enddatum liegen." + non_continuous_dates: "kann nicht vor dem Enddatum der vorherigen Phase liegen." + incomplete: "ist unvollständig." query: attributes: project: @@ -1557,13 +1557,13 @@ de: wiki_edit: "Wiki" work_package: "Arbeitspakete" project_phase: - activated: "activated" - deactivated: "deactivated" - added_date: "set to %{date}" - changed_date: "changed from %{from} to %{to}" - removed_date: "date deleted %{date}" + activated: "aktiviert" + deactivated: "deaktiviert" + added_date: "auf %{date} setzen" + changed_date: "von %{from} zu %{to} geändert" + removed_date: "Datum gelöscht %{date}" phase_and_one_gate: "%{phase_message}. %{gate_message}" - phase_and_both_gates: "%{phase_message}. %{start_gate_message}, and %{finish_gate_message}" + phase_and_both_gates: "%{phase_message}. %{start_gate_message} und %{finish_gate_message}" #common attributes of all models attributes: active: "Aktiv" @@ -1963,7 +1963,7 @@ de: automatic_subject_generation: description: "Erstellen Sie automatisch generierte Betreffe mit referenzierten Attributen und Text." customize_life_cycle: - description: "Create and organize different project phases than the ones provided by PM2 project cycle planning." + description: "Erstellen und organisieren Sie von PM2 abweichende Projektlebenszyklen." form_configuration: description: "Anpassen der Form-Konfiguration mit diesen zusätzlichen Add-ons:" add_groups: "Neue Attributgruppen hinzufügen" @@ -1993,7 +1993,7 @@ de: error_cookie_missing: "Das OpenProject Cookie fehlt. Bitte stellen Sie sicher, dass Cookies aktiviert sind, da diese Applikation ohne aktivierte Cookies nicht korrekt funktioniert." error_custom_option_not_found: "Option ist nicht vorhanden." error_enterprise_activation_user_limit: "Ihr Konto konnte nicht aktiviert werden (Nutzerlimit erreicht). Bitte kontaktieren Sie Ihren Administrator um Zugriff zu erhalten." - error_enterprise_token_invalid_domain: "Die Enterprise-Edition ist nicht aktiv. Die aktuelle Domain (%{actual}) entspricht nicht dem erwarteten Hostnamen (%{expected})." + error_enterprise_token_invalid_domain: "Die Enterprise edition ist nicht aktiv. Die aktuelle Domain (%{actual}) entspricht nicht dem erwarteten Hostnamen (%{expected})." error_failed_to_delete_entry: "Fehler beim Löschen dieses Eintrags." error_in_dependent: "Fehler beim Versuch, abhängiges Objekt zu ändern: %{dependent_class} #%{related_id} - %{related_subject}: %{error}" error_in_new_dependent: "Fehler beim Versuch, abhängiges Objekt zu erstellen: %{dependent_class} - %{related_subject}: %{error}" @@ -2050,7 +2050,7 @@ de: title: "Exportieren" submit: "Exportieren" save_export_settings: - label: "Save settings" + label: "Einstellungen speichern" format: label: "Dateiformat" options: @@ -2195,10 +2195,10 @@ de: blocks: community: "OpenProject Community" upsale: - title: "Auf Enterprise-Edition upgraden" + title: "Auf Enterprise edition upgraden" more_info: "Weitere Informationen" links: - upgrade_enterprise_edition: "Auf Enterprise-Edition upgraden" + upgrade_enterprise_edition: "Auf Enterprise edition upgraden" postgres_migration: "Migration Ihrer Installation zu PostgreSQL" user_guides: "Benutzerhandbuch" faq: "Häufig gestellte Fragen" @@ -2236,7 +2236,7 @@ de: dates: working: "%{date} ist jetzt ein Arbeitstag" non_working: "%{date} ist jetzt ein arbeitsfreier Tag" - progress_mode_changed_to_status_based: Fortschrittberechnung wurde auf Status-bezogen gesetzt + progress_mode_changed_to_status_based: Fortschrittberechnung wurde auf Status-basiert gesetzt status_excluded_from_totals_set_to_false_message: jetzt in den Gesamtwerten der Hierarchie enthalten status_excluded_from_totals_set_to_true_message: jetzt von den Hierarchie-Gesamtwerten ausgeschlossen status_percent_complete_changed: "% abgeschlossen von %{old_value}% auf %{new_value} % geändert" @@ -2523,7 +2523,7 @@ de: label_enumerations: "Aufzählungen" label_enterprise: "Enterprise" label_enterprise_active_users: "%{current}/%{limit} gebuchte aktive Nutzer" - label_enterprise_edition: "Enterprise Edition" + label_enterprise_edition: "Enterprise edition" label_enterprise_support: "Enterprise Support" label_environment: "Umgebung" label_estimates_and_progress: "Schätzungen und Fortschritt" @@ -2710,7 +2710,7 @@ de: label_none_parentheses: "(keiner)" label_not_contains: "enthält nicht" label_not_equals: "ist nicht" - label_life_cycle_step_plural: "Project life cycle" + label_life_cycle_step_plural: "Projekt-Lebenszyklus" label_on: "am" label_operator_all: "ist nicht leer" label_operator_none: "ist leer" @@ -2772,7 +2772,7 @@ de: label_project_new: "Neues Projekt" label_project_plural: "Projekte" label_project_list_plural: "Projektlisten" - label_project_life_cycle: "Project life cycle" + label_project_life_cycle: "Projekt-Lebenszyklus" label_project_attributes_plural: "Projektattribute" label_project_custom_field_plural: "Projektattribute" label_project_settings: "Projektkonfiguration" @@ -3313,7 +3313,7 @@ de: permission_edit_others_comments_with_restricted_visibility_explanation: "Caution: Users with this permission are able to edit other users' comments with restricted visibility." permission_edit_project: "Projekt bearbeiten" permission_edit_project_attributes: "Projektattribute bearbeiten" - permission_edit_project_phases: "Edit project phases" + permission_edit_project_phases: "Projektphasen bearbeiten" permission_edit_reportings: "Statusberichte bearbeiten" permission_edit_time_entries: "Zeitaufwand für andere Benutzer bearbeiten" permission_edit_timelines: "Zeitplan-Reporte bearbeiten" @@ -3343,8 +3343,8 @@ de: permission_search_project: "Projekt suchen" permission_select_custom_fields: "Benutzerdefinierte Felder verwalten" permission_select_project_custom_fields: "Projektattribute auswählen" - permission_select_project_phases: "Select project phases" - permission_select_project_phases_explanation: "Activate/Deactivate the phases in a project. Enables the user to select the life cycle appropriate for the project as inactive phases will not be visible in the project overview page nor the project list." + permission_select_project_phases: "Projektphase auswählen" + permission_select_project_phases_explanation: "(De-)Aktivieren der Projektphasen. Erlaubt dem Nutzer die Auswahl des passenden Lebenszyklus-Modells da definierte, aber inaktive Phasen weder auf der Projekt-Übersichtsseite noch in der Projektliste sichtbar sind." permission_select_project_modules: "Projektmodule auswählen" permission_share_work_packages: "Arbeitspakete teilen" permission_manage_types: "Typen auswählen" @@ -3370,7 +3370,7 @@ de: permission_work_package_assigned_explanation: "Arbeitspakete können Benutzern und Gruppen im Besitz dieser Rolle in dem jeweiligen Projekt zugeordnet werden" permission_view_project_activity: "Projektaktivität anzeigen" permission_view_project_attributes: "Projektattribute ansehen" - permission_view_project_phases: "View project phases" + permission_view_project_phases: "Projektphasen sehen" permission_save_bcf_queries: "BCF-Abfragen speichern" permission_manage_public_bcf_queries: "Öffentliche BCF-Abfragen verwalten" permission_edit_attribute_help_texts: "Attribut-Hilfetxt bearbeiten" @@ -3396,9 +3396,9 @@ de: subprojects_confirmation: "Sein(e) Unterprojekt(e): %{value} werden ebenfalls gelöscht." title: "Projekt %{name} löschen" filters: - project_phase: "Project phase: %{phase}" - project_phase_any: "Project phase: Any" - project_phase_gate: "Project phase gate: %{gate}" + project_phase: "Projektphase: %{phase}" + project_phase_any: "Projektphase: Alle" + project_phase_gate: "Projektphasen-Gate: %{gate}" identifier: warning_one: Projektmitglieder müssen die Projektarchive des Projekts umziehen. warning_two: Bestehende Projekt-Links werden nicht mehr funktionieren. @@ -3518,8 +3518,8 @@ de: update_timeout: "Speichere die Informationen bzgl. des genutzten Festplattenspeichers eines Projektarchivs für N Minuten.\nErhöhen Sie diesen Wert zur Verbesserung der Performance, da die Erfassung des genutzten Festplattenspeichers Ressourcen-intensiv ist." oauth_application_details: "Der Client Geheimcode wird nach dem Schließen dieses Fensters nicht mehr zugänglich sein. Bitte kopieren Sie diese Werte in die Nextcloud OpenProject Integrationseinstellungen:" oauth_application_details_link_text: "Zu den Einstellungen gehen" - setup_documentation_details: "Wenn Sie Hilfe bei der Konfiguration eines neuen Dateispeichers benötigen, konsultieren Sie bitte die Dokumentation: " - setup_documentation_details_link_text: "Dateispeicher einrichten" + setup_documentation_details: "Wenn Sie Hilfe bei der Konfiguration eines neuen Datei-Speichers benötigen, konsultieren Sie bitte die Dokumentation: " + setup_documentation_details_link_text: "Datei-Speicher einrichten" show_warning_details: "Um diesen Dateispeicher nutzen zu können, müssen Sie das Modul und den spezifischen Speicher in den Projekteinstellungen jedes gewünschten Projekts aktivieren." subversion: existing_title: "Vorhandenes Subversion Projektarchiv" @@ -3779,26 +3779,26 @@ de: heading: "Neues Attribut" description: "Änderungen an diesem Projektattribut werden in allen Projekten übernommen, in denen es aktiviert ist. Erforderliche Attribute können nicht projektweise deaktiviert werden." project_phase_definitions: - heading: "Project life cycle" - heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." - label_add: "Add" - label_add_description: "Add life cycle definition" + heading: "Projekt-Lebenszyklus" + heading_description: "Der Projekt-Lebenszyklus definiert die Projektphasen, die für Ihre Projektplanung verwendet werden können und auf der Übersichtsseite jedes Projekts erscheinen. Diese Attribute können aktiviert oder deaktiviert werden, aber nicht auf Projektebene neu geordnet werden." + label_add: "Hinzufügen" + label_add_description: "Add project phase definition" filter: - label: "Search project phase" - section_header: "Phases" - non_defined: "No phases are currently defined." - phase_gates: "Phase gates" + label: "Projektphase suchen" + section_header: "Phasen" + non_defined: "Derzeit sind keine Phasen definiert." + phase_gates: "Phasen Gates" new: - description: "Changes to this project phase will be reflected in all projects where it is enabled." - heading: "New Phase" + description: "Änderungen an dieser Projekt-Phase werden in allen sie verwendenden Projekten sichtbar." + heading: "Neue Phase" edit: - heading: "Edit Phase" - both_gate: "Start and finish gate" - no_gate: "No gate" - start_gate: "Start gate" - start_gate_caption: "Add a gate with the start date of the phase" - finish_gate: "Finish gate" - finish_gate_caption: "Add a gate with the end date of the phase" + heading: "Phase bearbeiten" + both_gate: "Gate zum Beginn und zum Ende" + no_gate: "Kein Gate" + start_gate: "Gate zum Beginn" + start_gate_caption: "Fügen Sie ein Gate zum Beginn der Phase hinzu" + finish_gate: "Gate zum Ende" + finish_gate_caption: "Fügen Sie ein Gate zum Ende der Phase hinzu" projects: missing_dependencies: "Projektmodul %{module} wurde aktiviert, hängt aber ab von %{dependencies}. Sie müssen diese Module ebenfalls aktivieren." section_new_projects: "Einstellungen für neue Projekte" @@ -3834,7 +3834,7 @@ de: text_are_you_sure_continue: "Sind Sie sicher, dass Sie fortfahren möchten?" text_are_you_sure_with_children: "Lösche Aufgabe und alle Unteraufgaben?" text_are_you_sure_with_project_custom_fields: "Wenn Sie dieses Attribut löschen, werden auch dessen Werte in allen Projekten gelöscht. Sind Sie sicher, dass Sie dies tun möchten?" - text_are_you_sure_with_project_life_cycle_step: "Deleting this phase will also delete its usages in all projects. Are you sure you want to do this?" + text_are_you_sure_with_project_life_cycle_step: "Das Entfernen dieser Projektphase entfernt sie auch aus allen Projekten, in denen sie bisher Verwendung fand. Sind Sie sicher, dass sie dies möchten?" text_assign_to_project: "Dem Projekt zuweisen" text_form_configuration: > Sie können anpassen, welche Felder in den Arbeitspaket-Formularen angezeigt werden. Sie können die Felder entsprechend Ihren Bedürfnissen frei gruppieren. @@ -4036,7 +4036,7 @@ de: warning_user_limit_reached_admin: > Das Hinzufügen zusätzlicher Benutzer überschreitet das aktuelle Benutzerlimit. Bitte aktualisieren Sie Ihr Abonnement um sicherzustellen, dass externe Benutzer auf diese Instanz zugreifen können. warning_user_limit_reached_instructions: > - Du hast dein Nutzerlimit erreicht (%{current}/%{max} active users). Bitte kontaktiere sales@openproject.com um deinen Enterprise Edition Plan upzugraden und weitere Nutzer hinzuzufügen. + Du hast dein Nutzerlimit erreicht (%{current}/%{max} active users). Bitte kontaktiere sales@openproject.com um deinen Enterprise edition Plan upzugraden und weitere Nutzer hinzuzufügen. warning_protocol_mismatch_html: > warning_bar: diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml index a10c1aeb70f..bb71c00fe36 100644 --- a/config/locales/crowdin/el.yml +++ b/config/locales/crowdin/el.yml @@ -3784,7 +3784,7 @@ el: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml index 893df3ab326..8433cb2b4e9 100644 --- a/config/locales/crowdin/eo.yml +++ b/config/locales/crowdin/eo.yml @@ -3789,7 +3789,7 @@ eo: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml index ca57e179aa4..b1a11248a4a 100644 --- a/config/locales/crowdin/es.yml +++ b/config/locales/crowdin/es.yml @@ -662,7 +662,7 @@ es: automatic_with_children: "Fechas determinadas por paquetes de trabajo secundarios." automatic_with_predecessor: "La fecha de inicio la fija un predecesor." manual_mobile: "Programado manualmente." - manually_scheduled: "Programado manualmente. No afectadas por relaciones." + manually_scheduled: "Programado manualmente. Fechas no afectadas por relaciones." blankslate: title: "Sin predecesores" description: "Para activar la programación automática, este paquete de trabajo debe tener al menos un predecesor. Entonces se programará automáticamente para que comience después del predecesor más cercano." @@ -3786,7 +3786,7 @@ es: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml index 58238b01efc..f699b9b12d7 100644 --- a/config/locales/crowdin/et.yml +++ b/config/locales/crowdin/et.yml @@ -3789,7 +3789,7 @@ et: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml index 1a8c1729e3a..b7440976292 100644 --- a/config/locales/crowdin/eu.yml +++ b/config/locales/crowdin/eu.yml @@ -3789,7 +3789,7 @@ eu: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml index d18f0bc1744..74217bc2beb 100644 --- a/config/locales/crowdin/fa.yml +++ b/config/locales/crowdin/fa.yml @@ -3789,7 +3789,7 @@ fa: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml index cdde77eeefe..cacd5d32292 100644 --- a/config/locales/crowdin/fi.yml +++ b/config/locales/crowdin/fi.yml @@ -3789,7 +3789,7 @@ fi: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml index 649eeb4e7f6..5007da51c7c 100644 --- a/config/locales/crowdin/fil.yml +++ b/config/locales/crowdin/fil.yml @@ -3787,7 +3787,7 @@ fil: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index b1da7802691..86fb2db02db 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -3787,7 +3787,7 @@ fr: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml index 3c8ab22fae1..eabfedb50b6 100644 --- a/config/locales/crowdin/he.yml +++ b/config/locales/crowdin/he.yml @@ -3871,7 +3871,7 @@ he: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml index 4b9ffa1b34e..0881476e8ae 100644 --- a/config/locales/crowdin/hi.yml +++ b/config/locales/crowdin/hi.yml @@ -3787,7 +3787,7 @@ hi: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml index b152521aed2..52541a65262 100644 --- a/config/locales/crowdin/hr.yml +++ b/config/locales/crowdin/hr.yml @@ -3830,7 +3830,7 @@ hr: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml index ccae94aa121..3e62fcd4e73 100644 --- a/config/locales/crowdin/hu.yml +++ b/config/locales/crowdin/hu.yml @@ -3787,7 +3787,7 @@ hu: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml index 1f8cdd3262e..1058dc2ec05 100644 --- a/config/locales/crowdin/id.yml +++ b/config/locales/crowdin/id.yml @@ -2515,7 +2515,7 @@ id: label_filter_add: "Tambah Filter" label_filter_by: "Filter by" label_filter_any_name_attribute: "Name attributes" - label_filter_plural: "Penyaring" + label_filter_plural: "Filter" label_filters_toggle: "Tampilkan/Sembunyikan penyaringan" label_float: "Float" label_folder: "Folder" @@ -3741,7 +3741,7 @@ id: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml index bbd5f8b2b2d..8fa7dc26856 100644 --- a/config/locales/crowdin/it.yml +++ b/config/locales/crowdin/it.yml @@ -80,11 +80,11 @@ it: upgrade_to_ee: "Aggiorna a Enterprise edition" add_token: "Carica un token di assistenza per Enterprise edition" delete_token_modal: - text: "Vuoi davvero rimuovere il token Enterprise Edition attualmente utilizzato?" + text: "Vuoi davvero rimuovere il token Enterprise edition attualmente utilizzato?" title: "Elimina token" replace_token: "Sostituisci il token di assistenza attuale" order: "Ordina l'edizione Enterprise on-premises" - paste: "Incolla il tuo token di assistenza per Enterprise Edition" + paste: "Incolla il tuo token di assistenza per Enterprise edition" required_for_feature: "Questa aggiunta è disponibile solo con un token di assistenza Enterprise Edition attivo." enterprise_link: "Per ulteriori informazioni, clicca qui." start_trial: "Inizia la prova gratuita" @@ -1116,7 +1116,7 @@ it: confirmation: "non coincide con %{attribute}." could_not_be_copied: "%{dependency} non può essere (completamente) copiato." does_not_exist: "non esiste." - error_enterprise_only: "%{action} è disponibile solo in OpenProject Enterprise Edition" + error_enterprise_only: "%{action} è disponibile solo in OpenProject Enterprise edition" error_unauthorized: "potrebbe non essere accessibile." error_readonly: "è in sola lettura, pertanto non è stato possibile modificarlo." error_conflict: "L'informazione è stata aggiornata da almeno un altro utente nel frattempo." @@ -1997,7 +1997,7 @@ it: error_cookie_missing: "Il cookie di OpenProject è mancante. Prego, verifica che i cookie siano attivati, questa applicazione non funziona correttamente senza." error_custom_option_not_found: "L'opzione non esiste." error_enterprise_activation_user_limit: "Il tuo account potrebbe non essere attivo (raggiunto il limite utente). Si prega di contattare l'amministratore per ottenere l'accesso." - error_enterprise_token_invalid_domain: "L'Enterprise Edition non è attiva. Il dominio del token Enterprise (%{actual}) non corrisponde al nome host del sistema (%{expected})." + error_enterprise_token_invalid_domain: "L'Enterprise edition non è attiva. Il dominio del token Enterprise (%{actual}) non corrisponde al nome host del sistema (%{expected})." error_failed_to_delete_entry: "Cancellazione voce non riuscita." error_in_dependent: "Errore nel tentativo di modificare l'oggetto dipendente: %{dependent_class} #%{related_id} - %{related_subject}: %{error}" error_in_new_dependent: "Errore nel tentativo di creare un oggetto dipendente: %{dependent_class} - %{related_subject}: %{error}" @@ -2199,10 +2199,10 @@ it: blocks: community: "Comunità di OpenProject" upsale: - title: "Aggiorna ad Enterprise Edition" + title: "Aggiorna ad Enterprise edition" more_info: "Altre informazioni" links: - upgrade_enterprise_edition: "Aggiorna ad Enterprise Edition" + upgrade_enterprise_edition: "Aggiorna ad Enterprise edition" postgres_migration: "Migrazione dell'installazione su PostgreSQL" user_guides: "Guide utente" faq: "FAQ" @@ -2527,7 +2527,7 @@ it: label_enumerations: "Enumerazioni" label_enterprise: "Enterprise" label_enterprise_active_users: "%{current}/%{limit} utenti attivi riservati" - label_enterprise_edition: "Enterprise Edition" + label_enterprise_edition: "Enterprise edition" label_enterprise_support: "Supporto per Imprese" label_environment: "Ambiente" label_estimates_and_progress: "Stime e progressi" @@ -3786,7 +3786,7 @@ it: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml index 890e1816a1e..2fbb629a025 100644 --- a/config/locales/crowdin/ja.yml +++ b/config/locales/crowdin/ja.yml @@ -3746,7 +3746,7 @@ ja: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/js-ca.yml b/config/locales/crowdin/js-ca.yml index 8037825c911..a198ed78cdd 100644 --- a/config/locales/crowdin/js-ca.yml +++ b/config/locales/crowdin/js-ca.yml @@ -102,7 +102,7 @@ ca: button_save: "Desa" button_settings: "Configuració" button_uncheck_all: "Desmarca-ho tot" - button_update: "Actualitzar" + button_update: "Actualitza" button_export-atom: "Descarregar Atom" button_generate_pdf: "Generate PDF" button_create: "Crear" diff --git a/config/locales/crowdin/js-da.yml b/config/locales/crowdin/js-da.yml index ab72d5740ca..a8ab63ed07e 100644 --- a/config/locales/crowdin/js-da.yml +++ b/config/locales/crowdin/js-da.yml @@ -102,7 +102,7 @@ da: button_save: "Gem" button_settings: "Indstillinger" button_uncheck_all: "Fjern alle markeringer" - button_update: "Opdatér" + button_update: "Opdater" button_export-atom: "Download Atom" button_generate_pdf: "Generate PDF" button_create: "Opret" diff --git a/config/locales/crowdin/js-id.yml b/config/locales/crowdin/js-id.yml index 91413036632..65230465d89 100644 --- a/config/locales/crowdin/js-id.yml +++ b/config/locales/crowdin/js-id.yml @@ -102,7 +102,7 @@ id: button_save: "Simpan" button_settings: "Pengaturan" button_uncheck_all: "Uncek semua" - button_update: "Perbarui" + button_update: "Update" button_export-atom: "Download Atom" button_generate_pdf: "Generate PDF" button_create: "Buat baru" diff --git a/config/locales/crowdin/js-no.yml b/config/locales/crowdin/js-no.yml index ac04f7261b5..63c1d17a8a7 100644 --- a/config/locales/crowdin/js-no.yml +++ b/config/locales/crowdin/js-no.yml @@ -102,7 +102,7 @@ button_save: "Lagre" button_settings: "Innstillinger" button_uncheck_all: "Avmerk alle" - button_update: "Oppdater" + button_update: "Oppdatèr" button_export-atom: "Last ned Atom" button_generate_pdf: "Generate PDF" button_create: "Opprett" diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index 360b464166d..d1ec0f0ab44 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -102,7 +102,7 @@ ro: button_save: "Salvează" button_settings: "Setări" button_uncheck_all: "Deselectează tot" - button_update: "Actualizează" + button_update: "Actualizare" button_export-atom: "Descarcă Atom" button_generate_pdf: "Generate PDF" button_create: "Creează" diff --git a/config/locales/crowdin/js-ru.yml b/config/locales/crowdin/js-ru.yml index d5a605f3ccd..01b4600d3ed 100644 --- a/config/locales/crowdin/js-ru.yml +++ b/config/locales/crowdin/js-ru.yml @@ -102,7 +102,7 @@ ru: button_save: "Сохранить" button_settings: "Настройки" button_uncheck_all: "Снять все отметки" - button_update: "Обновить" + button_update: "Обновление" button_export-atom: "Скачать Atom" button_generate_pdf: "Создать PDF" button_create: "Создать" diff --git a/config/locales/crowdin/js-vi.yml b/config/locales/crowdin/js-vi.yml index 13165d4c27d..0e5f4973e54 100644 --- a/config/locales/crowdin/js-vi.yml +++ b/config/locales/crowdin/js-vi.yml @@ -102,7 +102,7 @@ vi: button_save: "Lưu" button_settings: "Cài đặt" button_uncheck_all: "Bỏ chọn tất cả" - button_update: "Cập nhật" + button_update: "Cập Nhật" button_export-atom: "Tải xuống Atom" button_generate_pdf: "Generate PDF" button_create: "Tạo" diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml index 82cb17d882d..c0161b10314 100644 --- a/config/locales/crowdin/ka.yml +++ b/config/locales/crowdin/ka.yml @@ -3789,7 +3789,7 @@ ka: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml index f942b2517d3..ebbc5f6354f 100644 --- a/config/locales/crowdin/kk.yml +++ b/config/locales/crowdin/kk.yml @@ -3789,7 +3789,7 @@ kk: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml index a0da7ebd9a1..688e34e9416 100644 --- a/config/locales/crowdin/ko.yml +++ b/config/locales/crowdin/ko.yml @@ -3745,7 +3745,7 @@ ko: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 095e5946052..45cb7c665f4 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -3865,7 +3865,7 @@ lt: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml index 29e7015dd77..b447cbf3b30 100644 --- a/config/locales/crowdin/lv.yml +++ b/config/locales/crowdin/lv.yml @@ -3830,7 +3830,7 @@ lv: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml index 76752b320b6..dfc19a66f42 100644 --- a/config/locales/crowdin/mn.yml +++ b/config/locales/crowdin/mn.yml @@ -3789,7 +3789,7 @@ mn: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml index 16fb93e51ea..8a540266f86 100644 --- a/config/locales/crowdin/ms.yml +++ b/config/locales/crowdin/ms.yml @@ -3745,7 +3745,7 @@ ms: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml index 1fcebbd4021..15a130930bd 100644 --- a/config/locales/crowdin/ne.yml +++ b/config/locales/crowdin/ne.yml @@ -3789,7 +3789,7 @@ ne: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 875d50d255b..132dd8d09a1 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -3784,7 +3784,7 @@ nl: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml index 9ca3c2f2b1b..571c887179b 100644 --- a/config/locales/crowdin/no.yml +++ b/config/locales/crowdin/no.yml @@ -3788,7 +3788,7 @@ heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml index 8eb4f386eec..339f8af3ed2 100644 --- a/config/locales/crowdin/pl.yml +++ b/config/locales/crowdin/pl.yml @@ -1134,7 +1134,7 @@ pl: confirmation: "nie pasuje do %{attribute}." could_not_be_copied: "Nie można było (w pełni) skopiować %{dependency}." does_not_exist: "nie istnieje." - error_enterprise_only: "%{action} jest dostępna tylko w OpenProject Enterprise Edition" + error_enterprise_only: "%{action} jest dostępna tylko w OpenProject Enterprise edition" error_unauthorized: "— nie można uzyskac dostępu." error_readonly: "— podjęto próbę zapisu, ale nie jest zapisywalny." error_conflict: "Information has been updated by at least one other user in the meantime." @@ -3865,7 +3865,7 @@ pl: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml index c144e76b587..4baff7e4a88 100644 --- a/config/locales/crowdin/pt-BR.yml +++ b/config/locales/crowdin/pt-BR.yml @@ -3785,7 +3785,7 @@ pt-BR: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml index 9319c670a65..ab9ef885b10 100644 --- a/config/locales/crowdin/pt-PT.yml +++ b/config/locales/crowdin/pt-PT.yml @@ -3783,7 +3783,7 @@ pt-PT: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index 930bd377474..b3e091fea35 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -2556,7 +2556,7 @@ ro: label_duplicated_by: "dublat de" label_duplicate: "duplicat" label_duplicates: "dublează" - label_edit: "Editează" + label_edit: "Editare" label_edit_x: "Editare: %{x}" label_enable_multi_select: "Comutare selecție multiplă" label_enabled_project_custom_fields: "Câmpuri personalizate activate" @@ -2610,7 +2610,7 @@ ro: label_generate_key: "Generare cheie" label_git_path: "Calea catre directorul .git" label_greater_or_equal: ">=" - label_group_by: "Grupează după" + label_group_by: "Grupare după" label_group_new: "Grupare nouă" label_group: "Grup" label_group_named: "Grup %{name}" @@ -3829,7 +3829,7 @@ ro: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/ru.seeders.yml b/config/locales/crowdin/ru.seeders.yml index 70a39971ff5..986eb6c5cc7 100644 --- a/config/locales/crowdin/ru.seeders.yml +++ b/config/locales/crowdin/ru.seeders.yml @@ -36,13 +36,13 @@ ru: name: Чёрный project_phase_colors: item_0: - name: PM2 Orange + name: PM2 Оранжевый item_1: - name: PM2 Red + name: PM2 Красный item_2: - name: PM2 Magenta + name: PM2 Пурпурный item_3: - name: PM2 Green Yellow + name: PM2 Зелено-жёлтый document_categories: item_0: name: Документация @@ -81,16 +81,16 @@ ru: standard: project_phases: item_0: - name: Initiating + name: Запуск item_1: - name: Planning - start_gate: Ready for Planning + name: Планирование + start_gate: Готово к планированию item_2: - name: Executing - start_gate: Ready for Executing + name: Выполнение + start_gate: Готово к выполнению item_3: - name: Closing - start_gate: Ready for Closing + name: Завершение + start_gate: Готово к завершению priorities: item_0: name: Низкий @@ -485,7 +485,7 @@ ru: item_1: name: Веха item_2: - name: Summary task + name: Сводка задачи item_3: name: Функция item_4: diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml index 6d39556681a..2281be3922d 100644 --- a/config/locales/crowdin/ru.yml +++ b/config/locales/crowdin/ru.yml @@ -368,14 +368,14 @@ ru: no_results_title_text: Нет доступных настраиваемых полей. life_cycle: header: - title: "Project life cycle" + title: "Жизненный цикл проекта" description_html: "The active project phases define this project's life cycle and are defined in the administration settings. Enabled phases will be displayed in your project overview." - non_defined: "No phases are currently defined." - section_header: "Phases" + non_defined: "В настоящее время этапы не определены." + section_header: "Этапы" step: use_in_project: "Использовано %{step} в этом проекте" filter: - label: "Search project phase" + label: "Поиск этапа проекта" project_custom_fields: header: title: "Атрибуты проекта" @@ -402,10 +402,10 @@ ru: new_label: "Новый приоритет" project_phase: working_days_count: - one: "Duration: %{count} working day" + one: "Продолжительность: %{count} рабочий день" few: "Duration: %{count} working days" many: "Duration: %{count} working days" - other: "Duration: %{count} working days" + other: "Продолжительность: %{count} рабочих дней" lists: create: success: "Измененный список был сохранен как новый" @@ -971,15 +971,15 @@ ru: is_required: "Требуется для всех проектов" custom_field_section: Раздел project/phase: - date_range: "Date range" - definition: "Definition" + date_range: "Диапазон дат" + definition: "Описание" project/phase_definition: - name: "Name" - color: "Color" - start_gate: "Start phase gate" - start_gate_name: "Start phase gate name" - finish_gate: "Finish phase gate" - finish_gate_name: "Finish phase gate name" + name: "Имя" + color: "Цвет" + start_gate: "Начальная стадия этапа" + start_gate_name: "Имя начальной стадии этапа" + finish_gate: "Конечная стадия этапа" + finish_gate_name: "Имя конечной стадии этапа" query: sums: "Сумма" columns: "Столбцы" @@ -1283,9 +1283,9 @@ ru: project/phase: attributes: date_range: - start_date_must_be_before_finish_date: "start date must be before the finish date." - non_continuous_dates: "can't be earlier than the previous phase's end date." - incomplete: "is incomplete." + start_date_must_be_before_finish_date: "дата начала должна быть раньше даты окончания." + non_continuous_dates: "не может быть раньше, чем дата окончания предыдущего этапа." + incomplete: "неполный." query: attributes: project: @@ -1602,13 +1602,13 @@ ru: wiki_edit: "Wiki" work_package: "Пакеты работ" project_phase: - activated: "activated" - deactivated: "deactivated" - added_date: "set to %{date}" - changed_date: "changed from %{from} to %{to}" - removed_date: "date deleted %{date}" + activated: "активирован" + deactivated: "деактивирован" + added_date: "установлено на %{date}" + changed_date: "изменено с %{from} на %{to}" + removed_date: "дата удаления %{date}" phase_and_one_gate: "%{phase_message}. %{gate_message}" - phase_and_both_gates: "%{phase_message}. %{start_gate_message}, and %{finish_gate_message}" + phase_and_both_gates: "%{phase_message}. %{start_gate_message} и %{finish_gate_message}" #common attributes of all models attributes: active: "Активно" @@ -2046,7 +2046,7 @@ ru: automatic_subject_generation: description: "Создать автоматически генерируемые темы, используя атрибуты и текст." customize_life_cycle: - description: "Create and organize different project phases than the ones provided by PM2 project cycle planning." + description: "Создание и организация этапов и стадий проекта, отличных от тех, что предусмотрены планированием цикла проекта PM2." form_configuration: description: "Настройте конфигурацию формы с помощью этих дополнительных дополнений:" add_groups: "Добавить новую группу атрибутов" @@ -2133,7 +2133,7 @@ ru: title: "Экспорт" submit: "Экспорт" save_export_settings: - label: "Save settings" + label: "Сохранить настройки" format: label: "Формат файла" options: @@ -2793,7 +2793,7 @@ ru: label_none_parentheses: "(нет)" label_not_contains: "не содержит" label_not_equals: "не" - label_life_cycle_step_plural: "Project life cycle" + label_life_cycle_step_plural: "Жизненный цикл проекта" label_on: "на" label_operator_all: "не пусто" label_operator_none: "пусто" @@ -2855,7 +2855,7 @@ ru: label_project_new: "Новый проект" label_project_plural: "Проекты" label_project_list_plural: "Списки проектов" - label_project_life_cycle: "Project life cycle" + label_project_life_cycle: "Жизненный цикл проекта" label_project_attributes_plural: "Атрибуты проекта" label_project_custom_field_plural: "Атрибуты проекта" label_project_settings: "Настройки проекта" @@ -3399,7 +3399,7 @@ ru: permission_edit_others_comments_with_restricted_visibility_explanation: "Внимание: пользователи с этим правом могут редактировать комментарии других пользователей с ограниченной видимостью." permission_edit_project: "Редактировать проект" permission_edit_project_attributes: "Редактирование атрибутов проекта" - permission_edit_project_phases: "Edit project phases" + permission_edit_project_phases: "Редактировать этапы проекта" permission_edit_reportings: "Редактировать отчеты" permission_edit_time_entries: "Править трудозатраты других пользователей" permission_edit_timelines: "Редактировать графики" @@ -3429,8 +3429,8 @@ ru: permission_search_project: "Поиск проекта" permission_select_custom_fields: "Выберите настраиваемые поля" permission_select_project_custom_fields: "Выберите атрибуты проекта" - permission_select_project_phases: "Select project phases" - permission_select_project_phases_explanation: "Activate/Deactivate the phases in a project. Enables the user to select the life cycle appropriate for the project as inactive phases will not be visible in the project overview page nor the project list." + permission_select_project_phases: "Выбрать этапы проекта" + permission_select_project_phases_explanation: "Включить/отключить этапы проекта. Позволяет пользователю выбрать жизненный цикл, подходящий для проекта, поскольку неактивные этапы не будут видны ни на странице обзора проекта, ни в списке проектов." permission_select_project_modules: "Выбор модулей проекта" permission_share_work_packages: "Поделиться пакетами работ" permission_manage_types: "Выберите типы" @@ -3456,7 +3456,7 @@ ru: permission_work_package_assigned_explanation: "Пакеты работ могут быть привязаны к пользователям и группам в зависимости от этой роли в рамках соответствующего проекта" permission_view_project_activity: "Просмотр деятельности по проекту" permission_view_project_attributes: "Просмотр атрибутов проекта" - permission_view_project_phases: "View project phases" + permission_view_project_phases: "Просмотр этапов проекта" permission_save_bcf_queries: "Сохранить запросы BCF" permission_manage_public_bcf_queries: "Управление публичными BCF запросами" permission_edit_attribute_help_texts: "Редактировать атрибут справки" @@ -3482,9 +3482,9 @@ ru: subprojects_confirmation: "Его подпроекты: %{value} также будут удалены." title: "Удаление проекта %{name}" filters: - project_phase: "Project phase: %{phase}" - project_phase_any: "Project phase: Any" - project_phase_gate: "Project phase gate: %{gate}" + project_phase: "Этап проекта: %{phase}" + project_phase_any: "Этап проекта: Любой" + project_phase_gate: "Стадия этапа проекта: %{gate}" identifier: warning_one: Участникам проекта нужно будет переместить репозитории проекта. warning_two: Существующие ссылки на проект больше работать не будут. @@ -3863,26 +3863,26 @@ ru: heading: "Новый атрибут" description: "Изменения этого атрибута проекта будут отражены во всех проектах, где он включен. Обязательные атрибуты не могут быть отключены для каждого проекта." project_phase_definitions: - heading: "Project life cycle" + heading: "Жизненный цикл проекта" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." - label_add: "Add" - label_add_description: "Add life cycle definition" + label_add: "Добавить" + label_add_description: "Add project phase definition" filter: - label: "Search project phase" - section_header: "Phases" - non_defined: "No phases are currently defined." - phase_gates: "Phase gates" + label: "Поиск этапа проекта" + section_header: "Этапы" + non_defined: "В настоящее время этапы не определены." + phase_gates: "Стадии этапа" new: - description: "Changes to this project phase will be reflected in all projects where it is enabled." - heading: "New Phase" + description: "Изменения на этом этапе проекта будут отражены во всех проектах, где он включен." + heading: "Новый этап" edit: - heading: "Edit Phase" - both_gate: "Start and finish gate" - no_gate: "No gate" - start_gate: "Start gate" - start_gate_caption: "Add a gate with the start date of the phase" - finish_gate: "Finish gate" - finish_gate_caption: "Add a gate with the end date of the phase" + heading: "Изменить этап" + both_gate: "Начать и завершить стадию" + no_gate: "Нет стадии" + start_gate: "Начать стадию" + start_gate_caption: "Добавить стадию с датой начала этапа" + finish_gate: "Завершить стадию" + finish_gate_caption: "Добавить стадию с датой окончания этапа" projects: missing_dependencies: "Был проверен модуль проекта %{module}, который зависит от %{dependencies}. Вам также необходимо проверить эти зависимости." section_new_projects: "Настройки для новых проектов" @@ -3918,7 +3918,7 @@ ru: text_are_you_sure_continue: "Вы уверены, что хотите продолжить?" text_are_you_sure_with_children: "Удалить пакет работ и все дочерние пакеты работ?" text_are_you_sure_with_project_custom_fields: "Удаление этого атрибута также приведет к удалению его значений во всех проектах. Вы уверены, что хотите это сделать?" - text_are_you_sure_with_project_life_cycle_step: "Deleting this phase will also delete its usages in all projects. Are you sure you want to do this?" + text_are_you_sure_with_project_life_cycle_step: "Удаление этого этапа также приведет к его удалению во всех используемых проектах. Вы уверены, что хотите это сделать?" text_assign_to_project: "Назначить на проект" text_form_configuration: > Вы можете настроить, какие поля будут показываться в формах пакетов работ. Вы можете свободно сгруппировать поля с учетом потребностей вашего домена. diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml index 5474bf78409..17aae515f1b 100644 --- a/config/locales/crowdin/rw.yml +++ b/config/locales/crowdin/rw.yml @@ -3789,7 +3789,7 @@ rw: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml index 9a8d5bef692..323212bd246 100644 --- a/config/locales/crowdin/si.yml +++ b/config/locales/crowdin/si.yml @@ -3789,7 +3789,7 @@ si: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml index 32ec85e87ce..39c65bc0931 100644 --- a/config/locales/crowdin/sk.yml +++ b/config/locales/crowdin/sk.yml @@ -3870,7 +3870,7 @@ sk: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml index 4e4b587bedd..efb59786a4e 100644 --- a/config/locales/crowdin/sl.yml +++ b/config/locales/crowdin/sl.yml @@ -1904,8 +1904,8 @@ sl: - "avgust" - "september" - "oktober" - - "november" - - "december" + - "November" + - "December" order: - :leto - :mesec @@ -3869,7 +3869,7 @@ sl: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml index 6e8c9e97455..4a4884186b1 100644 --- a/config/locales/crowdin/sr.yml +++ b/config/locales/crowdin/sr.yml @@ -3830,7 +3830,7 @@ sr: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml index 986784f24da..3b12f191ea9 100644 --- a/config/locales/crowdin/sv.yml +++ b/config/locales/crowdin/sv.yml @@ -3787,7 +3787,7 @@ sv: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml index b25c09881b5..27ba1c2f2ea 100644 --- a/config/locales/crowdin/th.yml +++ b/config/locales/crowdin/th.yml @@ -3748,7 +3748,7 @@ th: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml index 0fb956f1532..6124297eb54 100644 --- a/config/locales/crowdin/tr.yml +++ b/config/locales/crowdin/tr.yml @@ -3786,7 +3786,7 @@ tr: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml index 32d0464501d..e863e4d1cc7 100644 --- a/config/locales/crowdin/uk.yml +++ b/config/locales/crowdin/uk.yml @@ -2670,7 +2670,7 @@ uk: label_index_by_title: "Індекс за назвою" label_information: "Інформація" label_information_plural: "Інформація" - label_installation_guides: "Інструкції із встановлення" + label_installation_guides: "Інструкції зі встановлення" label_integer: "Ціле число" label_internal: "Власне" label_introduction_video: "Введення відео" @@ -3863,7 +3863,7 @@ uk: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml index a448d0d310d..548f1607304 100644 --- a/config/locales/crowdin/uz.yml +++ b/config/locales/crowdin/uz.yml @@ -3789,7 +3789,7 @@ uz: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml index c63307e583e..aabaebee712 100644 --- a/config/locales/crowdin/vi.yml +++ b/config/locales/crowdin/vi.yml @@ -2519,7 +2519,7 @@ vi: label_filter_add: "Thêm bộ lọc" label_filter_by: "Filter by" label_filter_any_name_attribute: "Name attributes" - label_filter_plural: "Các bộ lọc" + label_filter_plural: "Bộ lọc" label_filters_toggle: "Hiển thị/ẩn bộ lọc" label_float: "Số thực" label_folder: "Thư mục" @@ -3748,7 +3748,7 @@ vi: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/config/locales/crowdin/zh-CN.seeders.yml b/config/locales/crowdin/zh-CN.seeders.yml index f70e2f9ab52..c36cab226be 100644 --- a/config/locales/crowdin/zh-CN.seeders.yml +++ b/config/locales/crowdin/zh-CN.seeders.yml @@ -104,7 +104,7 @@ zh-CN: demo-project: name: 演示项目 status_explanation: 所有任务都按计划进行。相关人员均知晓各自任务。系统已完全建立。 - description: 这是对此演示 Scrum 项目目标的简短摘要。 + description: 这是对此演示项目目标的简短摘要。 news: item_0: title: 欢迎来到您的演示项目 @@ -222,7 +222,7 @@ zh-CN: scrum-project: name: Scrum 项目 status_explanation: 所有任务都按计划进行。相关人员均知晓各自任务。系统已完全建立。 - description: 这是对此演示 Scrum 项目目标的简短摘要。 + description: 这是对此演示Scrum项目目标的简短摘要。 news: item_0: title: 欢迎来到您的 Scrum 演示项目 diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml index 163c64c7d24..29e1b2af78e 100644 --- a/config/locales/crowdin/zh-CN.yml +++ b/config/locales/crowdin/zh-CN.yml @@ -83,7 +83,7 @@ zh-CN: text: "您确定要删除当前使用的企业版令牌吗?" title: "删除令牌" replace_token: "替换您当前的支持令牌" - order: "订购本地部署版的 Enterprise edition" + order: "订购本地部署的 Enterprise edition" paste: "粘贴您企业版的支持令牌" required_for_feature: "此功能仅限具激活的企业版支持令牌的订阅者使用。" enterprise_link: "如需了解详细信息,请单击此处。" @@ -367,7 +367,7 @@ zh-CN: life_cycle: header: title: "项目生命周期" - description_html: "活动项目阶段定义此项目的生命周期,并在管理设置。已启用的阶段将显示在您的 项目概述中。" + description_html: "活动项目阶段定义此项目的生命周期,并在管理设置。已启用的阶段将显示在您的 项目概述中。" non_defined: "当前没有定义阶段。" section_header: "阶段" step: @@ -2014,7 +2014,7 @@ zh-CN: title: "导出" submit: "导出" save_export_settings: - label: "Save settings" + label: "保存设置" format: label: "文件格式" options: @@ -2788,7 +2788,7 @@ zh-CN: label_revision_id: "修订版本 %{value}" label_revision_plural: "修订" label_roadmap: "路线图" - label_roadmap_edit: "编辑路线图%{name}" + label_roadmap_edit: "编辑路线图 %{name}" label_roadmap_due_in: "%{value} 到期" label_roadmap_no_work_packages: "该版本没有工作包。" label_roadmap_overdue: "%{value} 超时" @@ -3472,7 +3472,7 @@ zh-CN: managed: "在 OpenProject 中创建新的存储库" storage: not_available: "磁盘存储开销不可用于此存储库。" - update_timeout: "在 N 分钟内保留存储库最后所需的磁盘空间信息。由于计算存储库所需的磁盘空间可能增加系统开销,增加该值可以减少性能影响。" + update_timeout: "在 N 分钟内保留存储库最后所需磁盘空间的信息。由于计算存储库所需的磁盘空间可能增加系统开销,增加该值可以减少性能影响。" oauth_application_details: "关闭此窗口后,将无法再次访问客户端密钥值。请将这些值复制到 Nextcloud OpenProject 集成设置中:" oauth_application_details_link_text: "转到设置页面" setup_documentation_details: "如果您在配置新文件存储方面需要帮助,请查看文档:" @@ -3643,7 +3643,7 @@ zh-CN: setting_session_ttl_hint: "当设置的值低于5时,其作用类似于禁用。" setting_session_ttl_enabled: "会话过期" setting_start_of_week: "一周起始日" - setting_sys_api_enabled: "启用存储库管理网页服务" + setting_sys_api_enabled: "启用版本库管理 web 服务" setting_sys_api_description: "存储库管理网页服务提供了集成的,用户授权的存储库访问。" setting_time_format: "时间" setting_total_percent_complete_mode: "计算 完成% 层次结构总数" @@ -3739,7 +3739,7 @@ zh-CN: heading: "项目生命周期" heading_description: "项目生命周期定义了可以用于您的项目规划并将出现在每个项目的概览页面中的项目阶段。 这些属性可以启用或禁用,但不能在项目一级重新排序。" label_add: "添加" - label_add_description: "添加生命周期定义" + label_add_description: "Add project phase definition" filter: label: "搜索项目阶段" section_header: "阶段" @@ -3992,7 +3992,7 @@ zh-CN: warning_user_limit_reached_admin: > 添加额外的用户将超出当前限制。请升级您的计划,以确保外部用户能够访问此实例。 warning_user_limit_reached_instructions: > - 您已达到用户限制(%{current}/%{max} 活跃用户)。请联系 sales@openproject.com 升级您的企业版计划以添加额外用户。 + 您达到了用户限制(%{current}/%{max}活跃用户)。 请联系sales@openproject.com以升级您的Enterprise edition计划并添加其他用户。 warning_protocol_mismatch_html: > warning_bar: diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 6d9697c3787..56bc44992ce 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -2517,7 +2517,7 @@ zh-TW: label_filter_add: "新增條件" label_filter_by: "篩選條件:" label_filter_any_name_attribute: "名稱屬性" - label_filter_plural: "篩選條件" + label_filter_plural: "篩選器" label_filters_toggle: "顯示/隱藏篩選條件" label_float: "浮點數" label_folder: "資料夾" @@ -2530,7 +2530,7 @@ zh-TW: label_generate_key: "產生一個金鑰" label_git_path: ".git 目錄的路徑" label_greater_or_equal: ">=" - label_group_by: "分類" + label_group_by: "分組依據" label_group_new: "新增群組" label_group: "群組" label_group_named: "群組名稱 %{name}" @@ -2542,7 +2542,7 @@ zh-TW: label_hierarchy: "階層" label_hierarchy_leaf: "頁面結構頁" label_home: "Home" - label_subject_or_id: "名稱或 id" + label_subject_or_id: "主旨或 id" label_calendar_subscriptions: "訂閱行事曆" label_identifier: "識別碼" label_in: "在" @@ -2588,7 +2588,7 @@ zh-TW: label_latest_revision_plural: "最新版本" label_ldap_authentication: "LDAP 認證" label_learn_more: "了解更多" - label_less_or_equal: "之後" + label_less_or_equal: "<=" label_less_than_ago: "幾天內" label_link_url: "連結(URL)" label_list: "清單" @@ -3744,7 +3744,7 @@ zh-TW: heading: "Project life cycle" heading_description: "Project life cycle define the project phases that can be used for your project planning and will appear in the overview page of each project. These attributes can be enabled or disabled but not re-ordered at a project level." label_add: "Add" - label_add_description: "Add life cycle definition" + label_add_description: "Add project phase definition" filter: label: "Search project phase" section_header: "Phases" diff --git a/modules/backlogs/config/locales/crowdin/ro.yml b/modules/backlogs/config/locales/crowdin/ro.yml index 2380b3d27be..b9c6fef0dde 100644 --- a/modules/backlogs/config/locales/crowdin/ro.yml +++ b/modules/backlogs/config/locales/crowdin/ro.yml @@ -28,7 +28,7 @@ ro: work_package: position: "Poziție" story_points: "Puncte" - backlogs_work_package_type: "Tipul de restante" + backlogs_work_package_type: "Tip restanță" errors: models: work_package: diff --git a/modules/backlogs/config/locales/crowdin/zh-TW.yml b/modules/backlogs/config/locales/crowdin/zh-TW.yml index 85de4c2f83a..bd8e8101dfc 100644 --- a/modules/backlogs/config/locales/crowdin/zh-TW.yml +++ b/modules/backlogs/config/locales/crowdin/zh-TW.yml @@ -21,7 +21,7 @@ #++ zh-TW: plugin_openproject_backlogs: - name: "OpenProject待辦事項" + name: "OpenProject代辦事項" description: "此模組新增了讓敏捷團隊能夠在 Scrum 專案中使用 OpenProject 的功能。" activerecord: attributes: diff --git a/modules/bim/config/locales/crowdin/fr.yml b/modules/bim/config/locales/crowdin/fr.yml index 717608ff597..288904f98e5 100644 --- a/modules/bim/config/locales/crowdin/fr.yml +++ b/modules/bim/config/locales/crowdin/fr.yml @@ -59,7 +59,7 @@ fr: perform_description: "Voulez-vous importer ou mettre à jour les problèmes repris ci-dessus ?" replace_with_system_user: 'Les remplacer par l''utilisateur "Système"' import_as_system_user: 'Les importer comme utilisateur "Système".' - what_to_do: "Que voulez-vous faire ?" + what_to_do: "Que voulez-vous faire?" work_package_has_newer_changes: "Obsolète ! Ce sujet n'a pas été mis à jour, car les derniers changements sur le serveur étaient plus récents que la \"ModifiedDate\" du sujet importé. Toutefois, les commentaires sur le sujet ont été importés." bcf_file_not_found: "Impossible de localiser le fichier BCF. Veuillez recommencer le processus de téléversement." export: diff --git a/modules/budgets/config/locales/crowdin/cs.yml b/modules/budgets/config/locales/crowdin/cs.yml index 72dd2ee8925..231267126ec 100644 --- a/modules/budgets/config/locales/crowdin/cs.yml +++ b/modules/budgets/config/locales/crowdin/cs.yml @@ -27,7 +27,7 @@ cs: budget: author: "Autor" available: "Dostupné" - budget: "Plánované" + budget: "Rozpočet" budget_ratio: "Stráveno (poměr)" description: "Popis" spent: "Strávený čas" diff --git a/modules/costs/config/locales/crowdin/de.yml b/modules/costs/config/locales/crowdin/de.yml index 14cdec675b5..b650cac3201 100644 --- a/modules/costs/config/locales/crowdin/de.yml +++ b/modules/costs/config/locales/crowdin/de.yml @@ -58,11 +58,11 @@ de: end_time: Endzeit models: time_entry: - one: "Time entry" - other: "Time entries" + one: "Zeitbuchung" + other: "Zeiterfassungen" cost_entry: - one: "Cost entry" - other: "Cost entries" + one: "Kosteneintrag" + other: "Kosteneinträge" cost_type: one: "Kostentyp" other: "Kostentypen" diff --git a/modules/costs/config/locales/crowdin/js-ca.yml b/modules/costs/config/locales/crowdin/js-ca.yml index 41d5db88189..32dfbc5b149 100644 --- a/modules/costs/config/locales/crowdin/js-ca.yml +++ b/modules/costs/config/locales/crowdin/js-ca.yml @@ -21,7 +21,7 @@ #++ ca: js: - text_are_you_sure: "N'esteu segur?" + text_are_you_sure: "N'estas segur?" work_packages: property_groups: costs: "Costs" diff --git a/modules/costs/config/locales/crowdin/js-ro.yml b/modules/costs/config/locales/crowdin/js-ro.yml index 69e4a265a58..64a94d4263c 100644 --- a/modules/costs/config/locales/crowdin/js-ro.yml +++ b/modules/costs/config/locales/crowdin/js-ro.yml @@ -21,7 +21,7 @@ #++ ro: js: - text_are_you_sure: "Sunteți sigur?" + text_are_you_sure: "Ești sigur?" work_packages: property_groups: costs: "Costuri" diff --git a/modules/ldap_groups/config/locales/crowdin/zh-CN.yml b/modules/ldap_groups/config/locales/crowdin/zh-CN.yml index 865f6146895..120e78daadc 100644 --- a/modules/ldap_groups/config/locales/crowdin/zh-CN.yml +++ b/modules/ldap_groups/config/locales/crowdin/zh-CN.yml @@ -1,7 +1,7 @@ zh-CN: plugin_openproject_ldap_groups: name: "OpenProject LDAP 组" - description: "LDAP组成员同步。" + description: "LDAP 组成员同步。" activerecord: attributes: ldap_groups/synchronized_group: diff --git a/modules/ldap_groups/config/locales/crowdin/zh-TW.yml b/modules/ldap_groups/config/locales/crowdin/zh-TW.yml index 2b0eaacb1a5..72f3eab1d51 100644 --- a/modules/ldap_groups/config/locales/crowdin/zh-TW.yml +++ b/modules/ldap_groups/config/locales/crowdin/zh-TW.yml @@ -10,7 +10,7 @@ zh-TW: ldap_auth_source: 'LDAP 連線' sync_users: '同步使用者' ldap_groups/synchronized_filter: - filter_string: 'LDAP篩選條件' + filter_string: '簡約登入目錄制約(LDAP)篩選' auth_source: '驗證來源' ldap_auth_source: 'LDAP 連線' group_name_attribute: "群組名字屬性" diff --git a/modules/meeting/config/locales/crowdin/cs.yml b/modules/meeting/config/locales/crowdin/cs.yml index 637e35bb206..482ccfee765 100644 --- a/modules/meeting/config/locales/crowdin/cs.yml +++ b/modules/meeting/config/locales/crowdin/cs.yml @@ -335,7 +335,7 @@ cs: notice_meeting_updated: "Tato stránka byla aktualizována někým jiným. Pro zobrazení změn znovu načtena." permission_create_meetings: "Vytvořit schůzku\n" permission_edit_meetings: "Upravit schůzku" - permission_delete_meetings: "Odstranit schůzky" + permission_delete_meetings: "Smazat schůzku" permission_view_meetings: "Zobrazit schůzky" permission_create_meeting_agendas: "Vytvořit agendy schůzek" permission_create_meeting_agendas_explanation: "Umožňuje upravovat obsah programu klasické schůzky." diff --git a/modules/meeting/config/locales/crowdin/de.yml b/modules/meeting/config/locales/crowdin/de.yml index 615eed6c56e..8fa8e091091 100644 --- a/modules/meeting/config/locales/crowdin/de.yml +++ b/modules/meeting/config/locales/crowdin/de.yml @@ -215,8 +215,8 @@ de: new_date_time: "Neue(s) Datum/Zeit" label_mail_all_participants: "E-Mail an alle Teilnehmer senden" types: - classic: "Classic (unsupported)" - classic_text: "Note: Classic meetings will be removed in the next version of OpenProject." + classic: "Klassisch (nicht unterstützt)" + classic_text: "Hinweis: Klassische Meetings werden in der nächsten Version von OpenProject entfernt." structured: "Dynamisch" one_time: "Einmalig" recurring: "Terminserie" @@ -401,7 +401,7 @@ de: label_meeting_state_in_progress: "In Durchführung" label_meeting_reopen_action: "Besprechung wiedereröffnen" label_meeting_close_action: "Besprechung schließen" - label_meeting_in_progress_action: "Start meeting" + label_meeting_in_progress_action: "Besprechung starten" text_meeting_open_description: "Diese Besprechung ist offen. Sie können Tagesordnungspunkte hinzufügen oder entfernen und bearbeiten. Sobald die Tagesordnung fertig ist, wechseln Sie auf In Durchführung, um Ergebnisse zu dokumentieren." text_meeting_closed_description: "Diese Besprechung ist abgeschlossen. Sie können keine Tagesordnungspunkte mehr hinzufügen/entfernen." text_meeting_in_progress_description: "Diese Besprechung befindet sich in Durchführung. Sie können die Ergebnisse für jeden Tagesordnungspunkt dokumentieren, neu anordnen und neue Punkte hinzufügen. Sobald die Besprechung abgeschlossen ist, können Sie es als geschlossen markieren, um es zu sperren." diff --git a/modules/meeting/config/locales/crowdin/ru.yml b/modules/meeting/config/locales/crowdin/ru.yml index 3f4c6f422fa..24a320050d2 100644 --- a/modules/meeting/config/locales/crowdin/ru.yml +++ b/modules/meeting/config/locales/crowdin/ru.yml @@ -409,7 +409,7 @@ ru: label_meeting_state_in_progress: "В процессе" label_meeting_reopen_action: "Открыть совещание заново" label_meeting_close_action: "Закрыть совещание" - label_meeting_in_progress_action: "Start meeting" + label_meeting_in_progress_action: "Начать совещание" text_meeting_open_description: "Совещание открыто. Вы можете добавлять/удалять пункты повестки дня и редактировать их так, как захотите. Как только повестка дня будет готова, отметьте ее как \"в процессе\" для документирования результатов." text_meeting_closed_description: "Это совещание является закрытым. Вы не можете добавлять/удалять пункты повестки." text_meeting_in_progress_description: "Совещание в процессе. Вы можете документировать результаты для каждого пункта повестки дня, переупорядочить их и даже добавить новые. После завершения совещания вы можете пометить его как закрытое для блокировки." diff --git a/modules/meeting/config/locales/crowdin/zh-CN.yml b/modules/meeting/config/locales/crowdin/zh-CN.yml index 788c8f6fa40..0137abdb0ed 100644 --- a/modules/meeting/config/locales/crowdin/zh-CN.yml +++ b/modules/meeting/config/locales/crowdin/zh-CN.yml @@ -214,7 +214,7 @@ zh-CN: label_mail_all_participants: "发送电子邮件给所有参与者" types: classic: "经典(不支持)" - classic_text: "注意:经典会议将在下一版OpenProject中删除。" + classic_text: "注意:经典会议将在下一版 OpenProject 中删除。" structured: "结构化" one_time: "动态" recurring: "定期" @@ -397,7 +397,7 @@ zh-CN: label_meeting_state_in_progress: "进行中" label_meeting_reopen_action: "重新开放会议" label_meeting_close_action: "关闭会议" - label_meeting_in_progress_action: "Start meeting" + label_meeting_in_progress_action: "开始会议" text_meeting_open_description: "本次会议已打开。您可以添加/删除议程项目并随时编辑。 一旦议程就绪,就将其记载为正在取得的成果。" text_meeting_closed_description: "此会议已关闭。您不能再添加/移除议程项目。" text_meeting_in_progress_description: "本次会议正在进行中。您可以记录每个议程项目的结果,重新排列,甚至添加新的项目。 一旦会议完成,您可以将其标记为关闭以便锁定。" diff --git a/modules/meeting/config/locales/crowdin/zh-TW.yml b/modules/meeting/config/locales/crowdin/zh-TW.yml index 8da4bb20034..837f0ba44a2 100644 --- a/modules/meeting/config/locales/crowdin/zh-TW.yml +++ b/modules/meeting/config/locales/crowdin/zh-TW.yml @@ -329,7 +329,7 @@ zh-TW: permission_create_meeting_agendas_explanation: "允許編輯傳統會議的議程。" permission_manage_agendas: "管理議程" permission_manage_agendas_explanation: "允許編輯動態會議的議程項目。" - permission_close_meeting_agendas: "結束會議大綱" + permission_close_meeting_agendas: "定案會議大綱" permission_send_meeting_agendas_notification: "傳送會議大綱審閱通知" permission_create_meeting_minutes: "管理會議記錄" permission_send_meeting_minutes_notification: "傳送會議記錄審閱通知" diff --git a/modules/reporting/config/locales/crowdin/ro.yml b/modules/reporting/config/locales/crowdin/ro.yml index a6c8c711a62..6b730320b60 100644 --- a/modules/reporting/config/locales/crowdin/ro.yml +++ b/modules/reporting/config/locales/crowdin/ro.yml @@ -70,7 +70,7 @@ ro: label_filter: "Filtrează" label_filter_add: "Adaugă filtru" label_filter_plural: "Filtre" - label_group_by: "Grupează după" + label_group_by: "Grupare după" label_group_by_add: "Adaugă atributul Grupează-după" label_inactive: "Inactiv" label_no: "Nu" diff --git a/modules/reporting/config/locales/crowdin/zh-TW.yml b/modules/reporting/config/locales/crowdin/zh-TW.yml index 160d6764df0..5885d7e25a2 100644 --- a/modules/reporting/config/locales/crowdin/zh-TW.yml +++ b/modules/reporting/config/locales/crowdin/zh-TW.yml @@ -53,7 +53,7 @@ zh-TW: label_money: "現金價值" label_month_reporting: "月" label_new_report: "新建成本報表" - label_open: "開啟" + label_open: "開啟中" label_operator: "操作員" label_private_report_plural: "私密成本報告" label_progress_bar_explanation: "產生報告中..." @@ -70,7 +70,7 @@ zh-TW: label_filter: "篩選條件" label_filter_add: "新增篩選條件" label_filter_plural: "篩選條件" - label_group_by: "分類" + label_group_by: "分組依據" label_group_by_add: "新增分組依據屬性" label_inactive: "«不活動»" label_no: "否" diff --git a/modules/storages/config/locales/crowdin/de.yml b/modules/storages/config/locales/crowdin/de.yml index 47a52078e74..361c127a604 100644 --- a/modules/storages/config/locales/crowdin/de.yml +++ b/modules/storages/config/locales/crowdin/de.yml @@ -173,7 +173,7 @@ de: storages: buttons: complete_without_setup: Ohne fortfahren - done_complete_setup: Fertig, Einrichtung abschließen + done_complete_setup: Fertig, Einrichtung abgeschlossen done_continue: Fertig, Fortfahren open_storage: Dateispeicher öffnen replace_oauth_application: OpenProject OAuth ersetzen @@ -242,9 +242,9 @@ de: host_not_found: Kein Nextcloud-Server unter der konfigurierten Host-URL gefunden. Bitte überprüfen Sie die Konfiguration. missing_dependencies: 'Eine erforderliche Abhängigkeit fehlt auf dem Datei-Speicher. Bitte fügen Sie die folgende Abhängigkeit hinzu: %{dependency}.' not_configured: Die Verbindung konnte nicht validiert werden. Bitte schließen Sie zuerst die Konfiguration ab. - oauth_request_not_found: OpenProject couldn't find the root folder of Nextcloud using the current logged-in user. Please check the server logs for further information. - oauth_request_unauthorized: The current user isn't authorized to see the main folder of Nextcloud or we couldn't acquire a token. Please check the server logs for further information. - oauth_token_missing: OpenProject cannot test the user level communication with Nextcloud as there's no token for the current user. + oauth_request_not_found: OpenProject konnte den Hauptordner von Nextcloud mit dem aktuellen eingeloggten Benutzer nicht finden. Bitte überprüfen Sie die Server-Logs für weitere Informationen. + oauth_request_unauthorized: Der aktuelle Benutzer ist nicht berechtigt, den Hauptordner von Nextcloud zu sehen, oder wir konnten keinen Token hierfür erhalten. Bitte überprüfen Sie die Serverprotokolle für weitere Informationen. + oauth_token_missing: OpenProject kann die Kommunikation auf Benutzerebene mit Nextcloud nicht testen, da kein Token für den aktuellen Benutzer vorhanden ist. oidc_cant_acquire_token: Dein OpenID Connect Setup bietet weder die nötige Audience noch bietet es Tokenaustausch Möglichkeiten. Bitte lies unsere Dokumentation für weitere Informationen. oidc_cant_exchange_token: Es scheint ein Problem mit dem Token Exchange Setup auf Ihrem OpenID Connect Provider zu geben. Bitte überprüfen Sie die Konfiguration und versuchen Sie es erneut. oidc_cant_refresh_token: Beim Versuch, Ihren Zugriff auf den Speicher zu überprüfen, ist ein Fehler aufgetreten. Bitte überprüfen Sie die Server-Protokolle auf weitere Informationen. diff --git a/modules/team_planner/config/locales/crowdin/js-fr.yml b/modules/team_planner/config/locales/crowdin/js-fr.yml index 695779007b4..b0450fae0c8 100644 --- a/modules/team_planner/config/locales/crowdin/js-fr.yml +++ b/modules/team_planner/config/locales/crowdin/js-fr.yml @@ -18,7 +18,7 @@ fr: today: 'Aujourd''hui' drag_here_to_remove: 'Faites glisser ici pour supprimer le responsable et les dates de début et de fin.' cannot_drag_here: 'Impossible de supprimer le lot de travaux en raison des autorisations ou des restrictions d''édition.' - cannot_drag_to_non_working_day: 'Ce lot de travaux ne peut pas démarrer/terminer sur un jour non ouvré.' + cannot_drag_to_non_working_day: 'Ce lot de travail ne peut pas démarrer/terminer sur un jour non ouvré.' quick_add: empty_state: 'Utilisez le champ de recherche pour trouver des lots de travaux et faites-les glisser vers le planificateur pour l''assigner à quelqu''un et définir des dates de début et de fin.' search_placeholder: 'Rechercher...' diff --git a/modules/two_factor_authentication/config/locales/crowdin/ro.yml b/modules/two_factor_authentication/config/locales/crowdin/ro.yml index 06a4a7bded1..ff3049144f8 100644 --- a/modules/two_factor_authentication/config/locales/crowdin/ro.yml +++ b/modules/two_factor_authentication/config/locales/crowdin/ro.yml @@ -178,7 +178,7 @@ ro: label_expiration_hint: "%{date} sau la deconectare" label_actions: "Acțiuni" label_confirmed: "Confirmat" - button_continue: "Continuă" + button_continue: "Continuaţi" button_make_default: "Marcați ca implicit" label_unverified_phone: "Telefonul mobil nu a fost încă verificat" notice_phone_number_format: "Te rog să introduci numărul în următorul format: +XX XXXXXXXX." diff --git a/modules/two_factor_authentication/config/locales/crowdin/ru.yml b/modules/two_factor_authentication/config/locales/crowdin/ru.yml index a1bbf15b728..b03e8cd0695 100644 --- a/modules/two_factor_authentication/config/locales/crowdin/ru.yml +++ b/modules/two_factor_authentication/config/locales/crowdin/ru.yml @@ -178,7 +178,7 @@ ru: label_expiration_hint: "%{date} или при выходе из системы" label_actions: "Действия" label_confirmed: "Подтвержден" - button_continue: "Продолжить" + button_continue: "Далее" button_make_default: "Задать по умолчанию" label_unverified_phone: "Сотовый телефон еще не подтвержден" notice_phone_number_format: "Введите номер в следующем формате: +XX XXXXXXXX." diff --git a/modules/two_factor_authentication/config/locales/crowdin/uk.yml b/modules/two_factor_authentication/config/locales/crowdin/uk.yml index 0c70cad71e7..3430ee3cac3 100644 --- a/modules/two_factor_authentication/config/locales/crowdin/uk.yml +++ b/modules/two_factor_authentication/config/locales/crowdin/uk.yml @@ -119,7 +119,7 @@ uk: failed_to_delete: "Не вдалося видалити пристрій 2FA." is_default_cannot_delete: "Пристрій позначено як типовий і його не можна видалити через активну політику безпеки. Перед видаленням позначте інший пристрій як стандартний." not_existing: "Для вашого облікового запису не зареєстровано жодного пристрою 2FA." - 2fa_from_input: Введіть код, отриманий на пристрій %{device_name}, щоб підтвердити свою особу. + 2fa_from_input: Введіть код, що надійшов на пристрій %{device_name}, щоб підтвердити свою особу. 2fa_from_webauthn: Укажіть пристрій WebAuthn %{device_name}. Якщо це USB-пристрій, переконайтеся, що його підключено, і торкніться його. Потім натисніть кнопку входу. webauthn: title: "WebAuthn" diff --git a/modules/xls_export/config/locales/crowdin/zh-CN.yml b/modules/xls_export/config/locales/crowdin/zh-CN.yml index 59230e603ec..31c8d3cdd71 100644 --- a/modules/xls_export/config/locales/crowdin/zh-CN.yml +++ b/modules/xls_export/config/locales/crowdin/zh-CN.yml @@ -13,4 +13,4 @@ zh-CN: xls_with_relations: "带关系的 XLS" xls_export: child_of: 此项的子项 - parent_of: 此项的父级 + parent_of: 此项的父项 From 7dc59c60ebed65d57f76f563f4bca1e925f2a911 Mon Sep 17 00:00:00 2001 From: Bruno Pagno Date: Fri, 4 Apr 2025 13:48:21 +0200 Subject: [PATCH 076/260] update copy for enterprise banner --- config/locales/en.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 407017f09d2..817aeae8856 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2056,7 +2056,8 @@ en: add_groups: "Add new attribute groups" rename_groups: "Rename attributes groups" comments_with_restricted_visibility: - description: "To be defined" + title: "For your eyes only" + description: "Restricted-visibilty comments allow an internal team to communicate amongst themselves privately. These are only visible to certain project roles and will never be visible publicly. Available only through the enterprise professional plan." enumeration_activities: "Time tracking activities" enumeration_work_package_priorities: "Work package priorities" From 448696490f39cff9a05429b1bebe9e5e21424514 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Fri, 4 Apr 2025 13:50:17 +0200 Subject: [PATCH 077/260] Add code example for SidePanel component --- lookbook/docs/components/side-panel.md.erb | 28 +++++++++++-------- lookbook/docs/patterns/01-layout.md.erb | 4 +-- .../patterns/layout_preview/default.html.erb | 3 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/lookbook/docs/components/side-panel.md.erb b/lookbook/docs/components/side-panel.md.erb index 8e160374c60..d136fc088ba 100644 --- a/lookbook/docs/components/side-panel.md.erb +++ b/lookbook/docs/components/side-panel.md.erb @@ -1,10 +1,12 @@ -The Side panel is right-side pane that is used to show information relevant to the current page. This information normally concerns the contents of the entire page and can generally directly be modified or adjusted via the side panel. +The SidePanel is right-side pane that is used to show information relevant to the current page. This information normally concerns the contents of the entire page and can generally directly be modified or adjusted via the SidePanel. -A good example is a meeting occurrence; the side panel is used to show key meeting details (time, location, duration...), status, a list of participants and attachments. +A good example is a meeting occurrence; the SidePanel is used to show key meeting details (time, location, duration...), status, a list of participants and attachments. + +<%= embed Patterns::LayoutPreview, :default %> ## Anatomy -The side panel consists of a series of sections (or just one section). Each section has a fixed format and contains: +The SidePanel consists of a series of sections (or just one section). Each section has a fixed format and contains: - A section header - with counter (optional) @@ -17,14 +19,14 @@ These sections are stacked vertically. The content slot can take a number of different types of content and is relatively free. However, the content has to make sense in visual and semantic hierarchy. It's also best to make sure all objects are aligned to the left edge of the panel. -The content of the side panel should always be secondary to the main content area. +The content of the SidePanel should always be secondary to the main content area. ## Best practices **Do** -- Do use the side panel for contextual information on the page -- Ensure that elements on a side panel respect the hierarchy of the page and elements in other side panels (the content in each side panel should roughly be at the same hierarchical and visual level) +- Do use the SidePanel for contextual information on the page +- Ensure that elements on a SidePanel respect the hierarchy of the page and elements in other SidePanels (the content in each SidePanel should roughly be at the same hierarchical and visual level) - Use `color-fg-subtle` if the text is meant to be helpful guideline text or a caption; use `color-fg-default` for key information. **Don't** @@ -34,22 +36,26 @@ The content of the side panel should always be secondary to the main content are ## Used in -Some pages where the side panel is used: +Some pages where the SidePanel is used: -- Meeting occurence (displays meeting details, meeting status, participants and attachments) +- Meeting occurrence (displays meeting details, meeting status, participants and attachments) - Project overview (displays project attributes) - Project list - Some admin index pages (eg. SAML or OpenID provider details page; file storage details page) ## Mobile considerations -By default, side panel move to the bottom of the main content area on mobile. However, there are other considerations to keep in mind: +By default, SidePanel move to the bottom of the main content area on mobile. However, there are other considerations to keep in mind: -- Some sections have to manually be moved to the top if they contain critical information (eg. the meeting details for a meeting occurence go to the top, but the participant list goes to the bottom) +- Some sections have to be moved to the top if they contain critical information (eg. the meeting details for a meeting occurence go to the top). This can be done via tha surrounding Layout component - Sections can be simplified (certain actions hidden) or indeed completely left out on mobile if they are judged to be not critical on smaller screens - ## Technical notes +To achieve that the SidePanel moves to the right side, you have to wrap it into the `with_sidebar` slot of the `Primer::Alpha::Layout` component. + +<%= embed Patterns::LayoutPreview, :default, panels: %i[source] %> + ## Examples +For detailed examples have a look at the other [preview examples](/lookbook/inspect/primer/open_project/side_panel/default) of the component. diff --git a/lookbook/docs/patterns/01-layout.md.erb b/lookbook/docs/patterns/01-layout.md.erb index d173d816f9b..1f9a83360a5 100644 --- a/lookbook/docs/patterns/01-layout.md.erb +++ b/lookbook/docs/patterns/01-layout.md.erb @@ -9,8 +9,8 @@ you a layout with a side panel and a main content area, stacking behavior for mo These are the involved primer components: -- `Primer::Beta::Layout` - The main layout component. For more information, see https://primer.style/components/layout/rails/alpha and [the preview for the component](/lookbook/inspect/primer/alpha/layout/playground) -- `Primer::OpenProject::SidePanel` - Side panel component for one or multiple sections +- `Primer::Beta::Layout` - The main layout component. For more information, see the [Primer docs](https://primer.style/product/getting-started/rails/components/layout/) and [the preview for the component](/lookbook/inspect/primer/alpha/layout/playground) +- `Primer::OpenProject::SidePanel` - SidePanel component for one or multiple sections. Please have a look at the docs for the [SidePanel component](./../components/side_panel). Here is an example on how this would be used: diff --git a/lookbook/previews/patterns/layout_preview/default.html.erb b/lookbook/previews/patterns/layout_preview/default.html.erb index aee423aa4c3..3886f16fb00 100644 --- a/lookbook/previews/patterns/layout_preview/default.html.erb +++ b/lookbook/previews/patterns/layout_preview/default.html.erb @@ -1,6 +1,7 @@ <%= render(Primer::Alpha::Layout.new) do |component| - component.with_main do + # The border is only for visualization in the preview + component.with_main(border: true, p: 6) do "Main content" end component.with_sidebar(row_placement: :start, col_placement: :end) do From 31bf231a0cddf03bb4aa2d175d58aa41ffc60264 Mon Sep 17 00:00:00 2001 From: Parimal Satyal <88370597+psatyal@users.noreply.github.com> Date: Fri, 4 Apr 2025 15:22:04 +0200 Subject: [PATCH 078/260] Minor --- lookbook/docs/components/side-panel.md.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lookbook/docs/components/side-panel.md.erb b/lookbook/docs/components/side-panel.md.erb index d136fc088ba..0ff6c1b69ce 100644 --- a/lookbook/docs/components/side-panel.md.erb +++ b/lookbook/docs/components/side-panel.md.erb @@ -52,7 +52,7 @@ By default, SidePanel move to the bottom of the main content area on mobile. How ## Technical notes -To achieve that the SidePanel moves to the right side, you have to wrap it into the `with_sidebar` slot of the `Primer::Alpha::Layout` component. +To move the SidePanel the right side from its default left position, you have to wrap it into the `with_sidebar` slot of the `Primer::Alpha::Layout` component. <%= embed Patterns::LayoutPreview, :default, panels: %i[source] %> From b4dff826b1669c1ae481a5d7e07d8df79bcf1bf1 Mon Sep 17 00:00:00 2001 From: Dombi Attila <83396+dombesz@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:59:11 +0200 Subject: [PATCH 079/260] Unify the Version.visible scope to contain Version.systemwide too --- app/models/custom_field.rb | 2 +- app/models/queries/work_packages/filter/version_filter.rb | 2 +- app/models/version.rb | 1 + lib/api/v3/versions/versions_api.rb | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb index b74af8119e0..3fcab7a3a61 100644 --- a/app/models/custom_field.rb +++ b/app/models/custom_field.rb @@ -373,7 +373,7 @@ class CustomField < ApplicationRecord if project&.persisted? project.shared_versions elsif options[:scope] == :visible - Version.visible.or(Version.systemwide) + Version.visible else Version.systemwide end diff --git a/app/models/queries/work_packages/filter/version_filter.rb b/app/models/queries/work_packages/filter/version_filter.rb index 620781a822e..a746b74f24a 100644 --- a/app/models/queries/work_packages/filter/version_filter.rb +++ b/app/models/queries/work_packages/filter/version_filter.rb @@ -62,7 +62,7 @@ class Queries::WorkPackages::Filter::VersionFilter < if project project.shared_versions else - Version.visible.or(Version.systemwide) + Version.visible end end end diff --git a/app/models/version.rb b/app/models/version.rb index 002869967a9..e72133043dd 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -53,6 +53,7 @@ class Version < ApplicationRecord scope :visible, ->(*args) { joins(:project) .merge(Project.allowed_to(args.first || User.current, :view_work_packages)) + .or(Version.systemwide) } scope :systemwide, -> { where(sharing: "system") } diff --git a/lib/api/v3/versions/versions_api.rb b/lib/api/v3/versions/versions_api.rb index 7561c9adc4b..07228488955 100644 --- a/lib/api/v3/versions/versions_api.rb +++ b/lib/api/v3/versions/versions_api.rb @@ -36,7 +36,7 @@ module API # the distinct(false) is added in order to allow ORDER BY LOWER(name) # which would otherwise be invalid in postgresql # SELECT DISTINCT, ORDER BY expressions must appear in select list - Version.visible(current_user).or(Version.systemwide).distinct(false) + Version.visible(current_user).distinct(false) }) .mount From 22cc675c2491e9699fe416dc40429c33f277b3f9 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Fri, 4 Apr 2025 16:50:31 +0300 Subject: [PATCH 080/260] Handle internal server error on mention sanitization request --- .../work_packages/activities_tab_controller.rb | 5 ++++- .../restricted_mentions_sanitizer.rb | 4 ++++ .../restricted-comment.controller.ts | 13 ++++++++++--- .../restricted_visibility_comments_spec.rb | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/app/controllers/work_packages/activities_tab_controller.rb b/app/controllers/work_packages/activities_tab_controller.rb index c8978df026b..ce975eb36b8 100644 --- a/app/controllers/work_packages/activities_tab_controller.rb +++ b/app/controllers/work_packages/activities_tab_controller.rb @@ -141,6 +141,9 @@ class WorkPackages::ActivitiesTabController < ApplicationController def sanitize_restricted_mentions render plain: sanitized_journal_notes + rescue StandardError => e + handle_internal_server_error(e) + respond_with_turbo_streams end def toggle_reaction # rubocop:disable Metrics/AbcSize @@ -226,7 +229,7 @@ class WorkPackages::ActivitiesTabController < ApplicationController end def sanitized_journal_notes - WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer.new(@work_package, journal_params[:notes]).call + WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer.sanitize(@work_package, journal_params[:notes]) end def journal_params diff --git a/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb index 5dee938a469..7e02e3dab6a 100644 --- a/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb +++ b/app/services/work_packages/activities_tab/restricted_mentions_sanitizer.rb @@ -29,6 +29,10 @@ #++ class WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer + def self.sanitize(work_package, notes) + new(work_package, notes).call + end + def initialize(work_package, notes) @work_package = work_package @notes = notes diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts index b11b91f03b0..e52a34b903a 100644 --- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/restricted-comment.controller.ts @@ -29,6 +29,7 @@ */ import { Controller } from '@hotwired/stimulus'; +import { renderStreamMessage } from '@hotwired/turbo'; import type IndexController from './index.controller'; export default class RestrictedCommentController extends Controller { @@ -89,10 +90,16 @@ export default class RestrictedCommentController extends Controller { }, }); - const sanitizedNotes = await response.text(); - this.ckEditorInstance.setData(sanitizedNotes); + const sanitizedNotesResponse = await response.text(); + + if (response.ok) { + this.ckEditorInstance.setData(sanitizedNotesResponse); + } else { + renderStreamMessage(sanitizedNotesResponse); + throw new Error(`Failed to sanitize restricted mentions. Response status: ${response.status}`); + } } catch (error) { - console.error(`Failed to sanitize restricted mentions: ${error}`); + console.error(error); } } } diff --git a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb index 2f52ff9030b..2fc80533844 100644 --- a/spec/features/activities/work_package/restricted_visibility_comments_spec.rb +++ b/spec/features/activities/work_package/restricted_visibility_comments_spec.rb @@ -248,5 +248,23 @@ RSpec.describe "Work package comments with restricted visibility", .to contain_exactly("Project Admin", "Restricted Viewer", "Restricted ViewerCommenter") end end + + context "with a server error" do + before do + allow(WorkPackages::ActivitiesTab::RestrictedMentionsSanitizer).to receive(:sanitize) + .and_raise(RuntimeError, "Something went wrong!!!") + end + + it "shows an error message" do + activity_tab.type_comment("@Restricted") + page.first(".mention-list-item", text: "Restricted Viewer").click + + activity_tab.check_restricted_visibility_comment_checkbox + + page.within_test_selector("op-primer-flash-message") do + expect(page).to have_text("Something went wrong!!!") + end + end + end end end From 5e62896aa52ad77194fbb636f73e94498b93d2fb Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Fri, 4 Apr 2025 16:58:17 +0300 Subject: [PATCH 081/260] Encapsulate restricted mentionable predicate fn --- .../src/app/core/path-helper/apiv3-paths.ts | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/core/path-helper/apiv3-paths.ts b/frontend/src/app/core/path-helper/apiv3-paths.ts index 2c21c1ac787..4a656267cae 100644 --- a/frontend/src/app/core/path-helper/apiv3-paths.ts +++ b/frontend/src/app/core/path-helper/apiv3-paths.ts @@ -46,16 +46,12 @@ export class ApiV3Paths { // that are members of that project: filters.add('member', '=', [(workPackage.project as HalResource).id as string]); } else { - const isRestrictedAttributeValue = 'data-work-packages--activities-tab--restricted-comment-is-restricted-value'; - const addingCommentIsRestricted = document.getElementById('work-packages-activities-tab-add-comment-component')?.getAttribute(isRestrictedAttributeValue) === 'true'; - const editingCommentIsRestricted = document.querySelector('.work-packages-activities-tab-journals-item-component-edit')?.getAttribute(isRestrictedAttributeValue) === 'true'; - // that are mentionable on the work package - if (addingCommentIsRestricted || editingCommentIsRestricted) { - filters.add('restricted_mentionable_on_work_package', '=', [workPackage.id.toString()]); - } else { - filters.add('mentionable_on_work_package', '=', [workPackage.id.toString()]); - } + filters.add( + (this.isRestrictedMentionable() ? 'restricted_mentionable_on_work_package' : 'mentionable_on_work_package'), + '=', + [workPackage.id.toString()], + ); } // That are users: filters.add('type', '=', ['User', 'Group']); @@ -67,4 +63,18 @@ export class ApiV3Paths { return `${this.apiV3Base}/principals?${filters.toParams({ sortBy: '[["name","asc"]]', offset: '1', pageSize: '10' })}`; } + + /** + * Check if either adding or editing a comment is restricted, and thus + * the mentionable principals are to be restricted + * + * @returns {boolean} + */ + private isRestrictedMentionable():boolean { + const isRestrictedAttributeValue = 'data-work-packages--activities-tab--restricted-comment-is-restricted-value'; + const addingCommentIsRestricted = document.getElementById('work-packages-activities-tab-add-comment-component')?.getAttribute(isRestrictedAttributeValue) === 'true'; + const editingCommentIsRestricted = document.querySelector('.work-packages-activities-tab-journals-item-component-edit')?.getAttribute(isRestrictedAttributeValue) === 'true'; + + return addingCommentIsRestricted || editingCommentIsRestricted; + } } From c11195bf6b7378d9b36f04fa26793dfcdda82a7e Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Sat, 5 Apr 2025 03:16:48 +0000 Subject: [PATCH 082/260] update locales from crowdin [ci skip] --- config/locales/crowdin/af.yml | 4 ++++ config/locales/crowdin/ar.yml | 4 ++++ config/locales/crowdin/az.yml | 4 ++++ config/locales/crowdin/be.yml | 4 ++++ config/locales/crowdin/bg.yml | 4 ++++ config/locales/crowdin/ca.yml | 4 ++++ config/locales/crowdin/ckb-IR.yml | 4 ++++ config/locales/crowdin/cs.yml | 4 ++++ config/locales/crowdin/da.yml | 4 ++++ config/locales/crowdin/de.yml | 38 +++++++++++++++++-------------- config/locales/crowdin/el.yml | 4 ++++ config/locales/crowdin/eo.yml | 4 ++++ config/locales/crowdin/es.yml | 4 ++++ config/locales/crowdin/et.yml | 4 ++++ config/locales/crowdin/eu.yml | 4 ++++ config/locales/crowdin/fa.yml | 4 ++++ config/locales/crowdin/fi.yml | 4 ++++ config/locales/crowdin/fil.yml | 4 ++++ config/locales/crowdin/fr.yml | 4 ++++ config/locales/crowdin/he.yml | 4 ++++ config/locales/crowdin/hi.yml | 4 ++++ config/locales/crowdin/hr.yml | 4 ++++ config/locales/crowdin/hu.yml | 4 ++++ config/locales/crowdin/id.yml | 4 ++++ config/locales/crowdin/it.yml | 4 ++++ config/locales/crowdin/ja.yml | 4 ++++ config/locales/crowdin/js-de.yml | 4 ++-- config/locales/crowdin/ka.yml | 4 ++++ config/locales/crowdin/kk.yml | 4 ++++ config/locales/crowdin/ko.yml | 4 ++++ config/locales/crowdin/lt.yml | 4 ++++ config/locales/crowdin/lv.yml | 4 ++++ config/locales/crowdin/mn.yml | 4 ++++ config/locales/crowdin/ms.yml | 4 ++++ config/locales/crowdin/ne.yml | 4 ++++ config/locales/crowdin/nl.yml | 4 ++++ config/locales/crowdin/no.yml | 4 ++++ config/locales/crowdin/pl.yml | 4 ++++ config/locales/crowdin/pt-BR.yml | 4 ++++ config/locales/crowdin/pt-PT.yml | 4 ++++ config/locales/crowdin/ro.yml | 4 ++++ config/locales/crowdin/ru.yml | 4 ++++ config/locales/crowdin/rw.yml | 4 ++++ config/locales/crowdin/si.yml | 4 ++++ config/locales/crowdin/sk.yml | 4 ++++ config/locales/crowdin/sl.yml | 4 ++++ config/locales/crowdin/sr.yml | 4 ++++ config/locales/crowdin/sv.yml | 4 ++++ config/locales/crowdin/th.yml | 4 ++++ config/locales/crowdin/tr.yml | 4 ++++ config/locales/crowdin/uk.yml | 4 ++++ config/locales/crowdin/uz.yml | 4 ++++ config/locales/crowdin/vi.yml | 4 ++++ config/locales/crowdin/zh-CN.yml | 4 ++++ config/locales/crowdin/zh-TW.yml | 4 ++++ 55 files changed, 235 insertions(+), 19 deletions(-) diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml index d3f96ccb80f..c8d16aab466 100644 --- a/config/locales/crowdin/af.yml +++ b/config/locales/crowdin/af.yml @@ -1304,6 +1304,10 @@ af: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml index d0aede8f8db..c9aa94817e9 100644 --- a/config/locales/crowdin/ar.yml +++ b/config/locales/crowdin/ar.yml @@ -1340,6 +1340,10 @@ ar: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml index 5d8405843d4..22614af04bd 100644 --- a/config/locales/crowdin/az.yml +++ b/config/locales/crowdin/az.yml @@ -1304,6 +1304,10 @@ az: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml index d9e2fb12d61..560ca2988ad 100644 --- a/config/locales/crowdin/be.yml +++ b/config/locales/crowdin/be.yml @@ -1322,6 +1322,10 @@ be: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index 706126c1e5a..571456b37f7 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -1304,6 +1304,10 @@ bg: values: inclusion: "филтърът има невалидни стойности." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index 6c615bf7790..81e8786eae1 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -1301,6 +1301,10 @@ ca: values: inclusion: "el filtre té valors invàlids." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "La relació crea un cercle de relacions." diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml index cedf11f9baa..8d5e0a9008d 100644 --- a/config/locales/crowdin/ckb-IR.yml +++ b/config/locales/crowdin/ckb-IR.yml @@ -1304,6 +1304,10 @@ ckb-IR: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index 4e83763ae2d..a7977042111 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -1322,6 +1322,10 @@ cs: values: inclusion: "filtr má neplatné hodnoty." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Vztah vytvoří cyklický vztah." diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml index fc3ecd6c1b9..4ac6ab82eda 100644 --- a/config/locales/crowdin/da.yml +++ b/config/locales/crowdin/da.yml @@ -1302,6 +1302,10 @@ da: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 28b23f8357e..d715075970c 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -42,8 +42,8 @@ de: created: "erstellt" commented: "kommentiert" restrict_visibility: Sichtbarkeit einschränken - restricted_journal: Restricted comments are visible to a limited group of members. - unsaved_changes_confirmation_message: You have unsaved changes. Are you sure you want to close the editor? + restricted_journal: Kommentare mit eingeschränkter Sichtbarkeit sind nur mit entsprechender Berechtigung sichtbar. + unsaved_changes_confirmation_message: Sie haben ungespeicherte Änderungen. Sind Sie sicher, dass Sie den Editor schließen möchten? admin: plugins: no_results_title_text: Es sind derzeit keine Plugins installiert. @@ -618,7 +618,7 @@ de: caption: "Fügen Sie Text oder Typ / um nach einem Attribut zu suchen. Sie können Leerzeichen hinzufügen, um sie zu trennen." headings: work_package: "Arbeitspaket" - parent: "Parent" + parent: "Eltern-Arbeitspaket" project: "Projekt" insert_as_text: "Keine Attribute gefunden. Als Text hinzufügen: \"%{word}\"" export_configuration: @@ -753,9 +753,9 @@ de: follows_description: "Das verknüpfte Arbeitspaket muss beendet sein bevor dieses Arbeitspaket starten kann" label_child_singular: "Untergeordnetes Arbeitspaket" label_child_plural: "Untergeordnete Arbeitspakete" - new_child: "Create new child" + new_child: "Neues Unter-Arbeitspaket" new_child_text: "Erstellt ein zugehöriges Arbeitspaket als Unterelement des aktuellen (übergeordneten) Arbeitspakets" - child: "Child" + child: "Unteraufgabe" child_description: "Macht das zugehörige Arbeitspaket zu einem Unterelement des aktuellen (übergeordneten) Arbeitspakets" label_closest: "Am nächsten" label_blocks_singular: "Blockiert" @@ -963,7 +963,7 @@ de: column_names: "Spalten" relations_to_type_column: "Beziehungen zu %{type}" relations_of_type_column: "Beziehungen der Art: %{type}" - child_work_packages: "Child work packages" + child_work_packages: "Unter-Arbeitspakete" group_by: "Gruppiere Ergebnisse nach" sort_by: "Ergebnisse sortieren nach" filters: "Filter" @@ -1076,7 +1076,7 @@ de: title: "Werktage" false: "Nur Werktage" true: "Mit Wochenenden" - journal_restricted: Restricted Journal + journal_restricted: Journal mit eingeschränkter Sichtbarkeit notify: "Benachrichtigung" #used in custom actions parent: "Übergeordnetes Arbeitspaket" parent_issue: "Übergeordnetes Arbeitspaket" @@ -1297,6 +1297,10 @@ de: values: inclusion: "Filter enthält ungültige Werte." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Die Beziehung erzeugt eine zirkuläre Abhängigkeit." @@ -2115,7 +2119,7 @@ de: succeeded: "Export abgeschlossen" failed: "Beim Versuch, die Arbeitspakete zu exportieren, ist ein Fehler aufgetreten: %{message}" errors: - embedded_table_with_too_many_columns: "This embedded work package table could not fit on the page, please reduce the number of columns." + embedded_table_with_too_many_columns: "Diese eingebettete Arbeitspakettabelle passte nicht auf die Seite. Bitte reduzieren Sie die Anzahl der Spalten." format: atom: "Atom" csv: "CSV" @@ -2162,7 +2166,7 @@ de: label: Sprache und Silbentrennung page_orientation: label: Seitenausrichtung - caption: Select the orientation of the pages in the PDF document. + caption: Wählen Sie die Ausrichtung der Seiten im PDF-Dokument. options: portrait: Hochformat landscape: Querformat @@ -3276,7 +3280,7 @@ de: permission_add_project: "Projekte erstellen" permission_add_work_package_attachments: "Anhänge hinzufügen" permission_add_work_package_attachments_explanation: "Erlaubt das Hinzufügen von Anhängen ohne die Berechtigung, das Arbeitspaket selbst zu bearbeiten" - permission_add_comments_with_restricted_visibility: "Write comments with restricted visibility" + permission_add_comments_with_restricted_visibility: "Kommentare mit eingeschränkter Sichtbarkeit schreiben" permission_archive_project: "Projekt archivieren" permission_create_user: "Benutzer erstellen" permission_manage_user: "Benutzer bearbeiten" @@ -3305,12 +3309,12 @@ de: permission_edit_work_package_notes_explanation: "Achtung: Benutzer mit dieser Berechtigung können den Kommentar eines anderen Benutzers bearbeiten." permission_edit_work_packages: "Arbeitspakete bearbeiten" permission_edit_messages: "Forenbeiträge bearbeiten" - permission_edit_own_comments_with_restricted_visibility: "Edit own comments with restricted visibility" + permission_edit_own_comments_with_restricted_visibility: "Eigene Kommentare mit eingeschränkter Sichtbarkeit bearbeiten" permission_edit_own_work_package_notes: "Eigene Kommentare bearbeiten" permission_edit_own_messages: "Eigene Forenbeiträge bearbeiten" permission_edit_own_time_entries: "Selbstgebuchte Aufwände bearbeiten" - permission_edit_others_comments_with_restricted_visibility: "Moderate comments with restricted visibility" - permission_edit_others_comments_with_restricted_visibility_explanation: "Caution: Users with this permission are able to edit other users' comments with restricted visibility." + permission_edit_others_comments_with_restricted_visibility: "Kommentare mit eingeschränkter Sichtbarkeit moderieren" + permission_edit_others_comments_with_restricted_visibility_explanation: "Achtung: Benutzer mit dieser Berechtigung können Kommentare anderer Benutzer mit eingeschränkter Sichtbarkeit bearbeiten." permission_edit_project: "Projekt bearbeiten" permission_edit_project_attributes: "Projektattribute bearbeiten" permission_edit_project_phases: "Projektphasen bearbeiten" @@ -3351,7 +3355,7 @@ de: permission_manage_own_reminders: "Eigene Erinnerungen erstellen" permission_view_project: "Projekt anzeigen" permission_view_changesets: "Revisionen des Projektarchivs in OpenProject ansehen" - permission_view_comments_with_restricted_visibility: "View comments with restricted visibility" + permission_view_comments_with_restricted_visibility: "Kommentare mit eingeschränkter Sichtbarkeit sehen" permission_view_commit_author_statistics: "Commit Autor Statistiken ansehen" permission_view_dashboards: "Dashboard anzeigen" permission_view_work_package_watchers: "Liste der Beobachter ansehen" @@ -3543,9 +3547,9 @@ de: manual: "auf Manuell setzen" automatic: "auf Automatisch setzen" search_input_placeholder: "Suchen ..." - setting_allowed_link_protocols: "Allowed link protocols" + setting_allowed_link_protocols: "Erlaubte Link-Protokolle" setting_allowed_link_protocols_text_html: >- - Allow these protocols to be rendered as links in work package descriptions, long text fields and comments. For example, %{tel_code} or %{element_code}. Enter one protocol per line.
Protocols %{http_code}, %{https_code}, and %{mailto_code} are always allowed. + Erlauben Sie es, diese Protokolle als Links in Arbeitspaket-Beschreibungen, langen Textfeldern und Kommentaren darzustellen. Zum Beispiel %{tel_code} oder %{element_code}. Geben Sie ein Protokoll pro Zeile ein.
Protokolle %{http_code}, %{https_code} und %{mailto_code} sind immer erlaubt. setting_after_first_login_redirect_url: "Weiterleitung nach erster Anmeldung" setting_after_first_login_redirect_url_text_html: > Legen Sie einen Pfad fest, an den Nutzer:innen nach der ersten Anmeldung weitergeleitet werden. Wenn leer, führt er auf die Startseite des Onboarding-Tours.
Beispiel: /meine/seite @@ -3782,7 +3786,7 @@ de: heading: "Projekt-Lebenszyklus" heading_description: "Der Projekt-Lebenszyklus definiert die Projektphasen, die für Ihre Projektplanung verwendet werden können und auf der Übersichtsseite jedes Projekts erscheinen. Diese Attribute können aktiviert oder deaktiviert werden, aber nicht auf Projektebene neu geordnet werden." label_add: "Hinzufügen" - label_add_description: "Add project phase definition" + label_add_description: "Neue Projektphase definieren" filter: label: "Projektphase suchen" section_header: "Phasen" diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml index bb71c00fe36..6a4eca950d3 100644 --- a/config/locales/crowdin/el.yml +++ b/config/locales/crowdin/el.yml @@ -1300,6 +1300,10 @@ el: values: inclusion: "το φίλτρο έχει μη έγκυρες τιμές." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Η σχέση αυτή δημιουργεί έναν κύκλο σχέσεων." diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml index 8433cb2b4e9..40d0b576064 100644 --- a/config/locales/crowdin/eo.yml +++ b/config/locales/crowdin/eo.yml @@ -1304,6 +1304,10 @@ eo: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml index b1a11248a4a..a20164aeb51 100644 --- a/config/locales/crowdin/es.yml +++ b/config/locales/crowdin/es.yml @@ -1302,6 +1302,10 @@ es: values: inclusion: "El filtro tiene valores inválidos." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "La relación crea un bucle de relaciones." diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml index f699b9b12d7..df5d6f751eb 100644 --- a/config/locales/crowdin/et.yml +++ b/config/locales/crowdin/et.yml @@ -1304,6 +1304,10 @@ et: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml index b7440976292..0e8096408ff 100644 --- a/config/locales/crowdin/eu.yml +++ b/config/locales/crowdin/eu.yml @@ -1304,6 +1304,10 @@ eu: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml index 74217bc2beb..d3138a4d2f1 100644 --- a/config/locales/crowdin/fa.yml +++ b/config/locales/crowdin/fa.yml @@ -1304,6 +1304,10 @@ fa: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "رابطه دایره روابط ایجاد می کند." diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml index cacd5d32292..6ef78ccf6b3 100644 --- a/config/locales/crowdin/fi.yml +++ b/config/locales/crowdin/fi.yml @@ -1304,6 +1304,10 @@ fi: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml index 5007da51c7c..4ad08b372f8 100644 --- a/config/locales/crowdin/fil.yml +++ b/config/locales/crowdin/fil.yml @@ -1304,6 +1304,10 @@ fil: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Ang relasyon ay lumilikha ng mga bilog na relasyon." diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index 86fb2db02db..cea5b3b7edf 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -1302,6 +1302,10 @@ fr: values: inclusion: "Les valeurs du filtre sont invalides." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "La relation créée un cercle de relations." diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml index eabfedb50b6..4bc92fa29ea 100644 --- a/config/locales/crowdin/he.yml +++ b/config/locales/crowdin/he.yml @@ -1322,6 +1322,10 @@ he: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml index 0881476e8ae..3d1d6639d96 100644 --- a/config/locales/crowdin/hi.yml +++ b/config/locales/crowdin/hi.yml @@ -1302,6 +1302,10 @@ hi: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml index 52541a65262..17a7199863a 100644 --- a/config/locales/crowdin/hr.yml +++ b/config/locales/crowdin/hr.yml @@ -1313,6 +1313,10 @@ hr: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Odnos stvara krug odnosa." diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml index 3e62fcd4e73..753e93b2f47 100644 --- a/config/locales/crowdin/hu.yml +++ b/config/locales/crowdin/hu.yml @@ -1303,6 +1303,10 @@ hu: values: inclusion: "A szűrő érvénytelen értékeket tartalmaz" format: "%{message}\n" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "A kapcsolat körkörös függőséget hoz létre." diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml index 1058dc2ec05..053498976f5 100644 --- a/config/locales/crowdin/id.yml +++ b/config/locales/crowdin/id.yml @@ -1291,6 +1291,10 @@ id: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Relasi menciptakan lingkaran relasi-relasi." diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml index 8fa7dc26856..519daa8bad6 100644 --- a/config/locales/crowdin/it.yml +++ b/config/locales/crowdin/it.yml @@ -1301,6 +1301,10 @@ it: values: inclusion: "il filtro ha valori non validi." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "La relazione crea un riferimento circolare." diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml index 2fbb629a025..7bede16d88d 100644 --- a/config/locales/crowdin/ja.yml +++ b/config/locales/crowdin/ja.yml @@ -1293,6 +1293,10 @@ ja: values: inclusion: "フィルタの値が無効です" format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "関係が、関係のループを作ります。" diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml index f72fb0670b0..d81b5a55735 100644 --- a/config/locales/crowdin/js-de.yml +++ b/config/locales/crowdin/js-de.yml @@ -798,7 +798,7 @@ de: typeahead_placeholder: Nach möglichen Beobachtern suchen relation_labels: parent: "Übergeordnetes Arbeitspaket" - child: "Child" + child: "Kind" children: "Untergeordnete Arbeitspakete" relates: "Verwandt mit" duplicates: "Dupliziert" @@ -828,7 +828,7 @@ de: add_new_child: "Neue Unteraufgabe" create_new: "Neu erstellen" add_existing: "Bestehende hinzufügen" - add_existing_child: "Add child" + add_existing_child: "Kind hinzufügen" remove_child: "Unteraufgabe entfernen" add_new_relation: "Neue Beziehung erstellen" add_existing_relation: "Bestehende Beziehung hinzufügen" diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml index c0161b10314..16de6a241c7 100644 --- a/config/locales/crowdin/ka.yml +++ b/config/locales/crowdin/ka.yml @@ -1304,6 +1304,10 @@ ka: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml index ebbc5f6354f..c3e87262086 100644 --- a/config/locales/crowdin/kk.yml +++ b/config/locales/crowdin/kk.yml @@ -1304,6 +1304,10 @@ kk: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml index 688e34e9416..4ff3f56424c 100644 --- a/config/locales/crowdin/ko.yml +++ b/config/locales/crowdin/ko.yml @@ -1295,6 +1295,10 @@ ko: values: inclusion: "필터에 잘못된 값이 있습니다." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "이 관계는 관계의 원을 만듭니다." diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 45cb7c665f4..0e1435a5426 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -1319,6 +1319,10 @@ lt: values: inclusion: "filtras turi neteisingas reikšmes." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Ryšys sukuria ryšių ciklą." diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml index b447cbf3b30..1b11c56692b 100644 --- a/config/locales/crowdin/lv.yml +++ b/config/locales/crowdin/lv.yml @@ -1313,6 +1313,10 @@ lv: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml index dfc19a66f42..4561b946946 100644 --- a/config/locales/crowdin/mn.yml +++ b/config/locales/crowdin/mn.yml @@ -1304,6 +1304,10 @@ mn: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml index 8a540266f86..b98975c098f 100644 --- a/config/locales/crowdin/ms.yml +++ b/config/locales/crowdin/ms.yml @@ -1293,6 +1293,10 @@ ms: values: inclusion: "penyaring mempunyai nilai yang tidak sah." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Hubungan ini mencipta sebuah lingkaran hubungan." diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml index 15a130930bd..75a975cd51c 100644 --- a/config/locales/crowdin/ne.yml +++ b/config/locales/crowdin/ne.yml @@ -1304,6 +1304,10 @@ ne: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 132dd8d09a1..07dd1f2bc5f 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -1300,6 +1300,10 @@ nl: values: inclusion: "filter heeft ongeldige waarden." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "De relatie wordt gemaakt van een kring van relaties." diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml index 571c887179b..44eac806295 100644 --- a/config/locales/crowdin/no.yml +++ b/config/locales/crowdin/no.yml @@ -1303,6 +1303,10 @@ values: inclusion: "filteret har ugyldige verdier." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Forholdet skaper en sirkel av forhold." diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml index 339f8af3ed2..6e500046b4b 100644 --- a/config/locales/crowdin/pl.yml +++ b/config/locales/crowdin/pl.yml @@ -1319,6 +1319,10 @@ pl: values: inclusion: "filtr ma nieważne wartości." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Relacja tworzy krąg relacji." diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml index 4baff7e4a88..31f885d8241 100644 --- a/config/locales/crowdin/pt-BR.yml +++ b/config/locales/crowdin/pt-BR.yml @@ -1301,6 +1301,10 @@ pt-BR: values: inclusion: "o filtro tem valores inválidos." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "O relacionamento cria um círculo de relacionamentos." diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml index ab9ef885b10..066cc751214 100644 --- a/config/locales/crowdin/pt-PT.yml +++ b/config/locales/crowdin/pt-PT.yml @@ -1301,6 +1301,10 @@ pt-PT: values: inclusion: "o filtro tem valores inválidos." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "A relação cria um círculo de relações." diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index b3e091fea35..631587880cf 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -1313,6 +1313,10 @@ ro: values: inclusion: "are valori invalide." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Relația creează un cerc închis." diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml index 2281be3922d..90faa306cbb 100644 --- a/config/locales/crowdin/ru.yml +++ b/config/locales/crowdin/ru.yml @@ -1320,6 +1320,10 @@ ru: values: inclusion: "у фильтра недопустимые значения." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Зацикливание зависимостей." diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml index 17aae515f1b..5dae32fffdd 100644 --- a/config/locales/crowdin/rw.yml +++ b/config/locales/crowdin/rw.yml @@ -1304,6 +1304,10 @@ rw: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml index 323212bd246..3aab687c1dd 100644 --- a/config/locales/crowdin/si.yml +++ b/config/locales/crowdin/si.yml @@ -1304,6 +1304,10 @@ si: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "සම්බන්ධතාවය සබඳතා කවයක් නිර්මාණය කරයි." diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml index 39c65bc0931..a3e0585a203 100644 --- a/config/locales/crowdin/sk.yml +++ b/config/locales/crowdin/sk.yml @@ -1322,6 +1322,10 @@ sk: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Vzťah vytvorí kruh vzťahov." diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml index efb59786a4e..2c9b4eb43af 100644 --- a/config/locales/crowdin/sl.yml +++ b/config/locales/crowdin/sl.yml @@ -1321,6 +1321,10 @@ sl: values: inclusion: "filter ima neveljavne vrednosti." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Odnos ustvarja krog odnosov." diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml index 4a4884186b1..077ff576827 100644 --- a/config/locales/crowdin/sr.yml +++ b/config/locales/crowdin/sr.yml @@ -1313,6 +1313,10 @@ sr: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml index 3b12f191ea9..d6554eaa94e 100644 --- a/config/locales/crowdin/sv.yml +++ b/config/locales/crowdin/sv.yml @@ -1304,6 +1304,10 @@ sv: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Förhållandet skapar en cirkel av relationer." diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml index 27ba1c2f2ea..5e1820f2854 100644 --- a/config/locales/crowdin/th.yml +++ b/config/locales/crowdin/th.yml @@ -1295,6 +1295,10 @@ th: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml index 6124297eb54..9a7eea959ea 100644 --- a/config/locales/crowdin/tr.yml +++ b/config/locales/crowdin/tr.yml @@ -1303,6 +1303,10 @@ tr: values: inclusion: "filtrede geçersiz değerler var." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "İlişki, bir ilişki çemberi oluşturur." diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml index e863e4d1cc7..0d2a2242399 100644 --- a/config/locales/crowdin/uk.yml +++ b/config/locales/crowdin/uk.yml @@ -1316,6 +1316,10 @@ uk: values: inclusion: "фільтр має неприпустимі значення." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Відносини створюють коло відносин." diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml index 548f1607304..a19e39e2d8f 100644 --- a/config/locales/crowdin/uz.yml +++ b/config/locales/crowdin/uz.yml @@ -1304,6 +1304,10 @@ uz: values: inclusion: "filter has invalid values." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "The relationship creates a circle of relationships." diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml index aabaebee712..4d4e4048ca5 100644 --- a/config/locales/crowdin/vi.yml +++ b/config/locales/crowdin/vi.yml @@ -1295,6 +1295,10 @@ vi: values: inclusion: "bộ lọc có các giá trị không hợp lệ." format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "Mối quan hệ tạo ra một vòng tròn các mối quan hệ." diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml index 29e1b2af78e..639d4911cdb 100644 --- a/config/locales/crowdin/zh-CN.yml +++ b/config/locales/crowdin/zh-CN.yml @@ -1291,6 +1291,10 @@ zh-CN: values: inclusion: "过滤器有无效值。" format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "关系会创建关系的循环。" diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 56bc44992ce..caa3da2f964 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -1293,6 +1293,10 @@ zh-TW: values: inclusion: "過濾條件錯誤" format: "%{message}" + queries/principals/filters/restricted_mentionable_on_work_package_filter: + attributes: + values: + single_value_requirement: "must be a single work package" relation: typed_dag: circular_dependency: "無限迴圈的關聯。" From 680d54c367fca549f2dd4650ffe5e7a7baf82016 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Sun, 6 Apr 2025 03:19:07 +0000 Subject: [PATCH 083/260] update locales from crowdin [ci skip] --- config/locales/crowdin/de.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index d715075970c..f23ff05ecec 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -1300,7 +1300,7 @@ de: queries/principals/filters/restricted_mentionable_on_work_package_filter: attributes: values: - single_value_requirement: "must be a single work package" + single_value_requirement: "muss ein einzelnes Arbeitspaket sein" relation: typed_dag: circular_dependency: "Die Beziehung erzeugt eine zirkuläre Abhängigkeit." From e3423125985b30fcce188562400d7ad3c0b03c78 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Mon, 7 Apr 2025 03:20:02 +0000 Subject: [PATCH 084/260] update locales from crowdin [ci skip] --- config/locales/crowdin/js-ro.yml | 16 +-- config/locales/crowdin/ro.yml | 134 +++++++++--------- .../calendar/config/locales/crowdin/js-ro.yml | 2 +- .../calendar/config/locales/crowdin/ro.yml | 4 +- .../costs/config/locales/crowdin/js-ro.yml | 4 +- modules/costs/config/locales/crowdin/ro.yml | 2 +- .../documents/config/locales/crowdin/ro.yml | 2 +- .../grids/config/locales/crowdin/js-ro.yml | 2 +- .../job_status/config/locales/crowdin/ro.yml | 4 +- .../reporting/config/locales/crowdin/ro.yml | 4 +- .../config/locales/crowdin/ro.yml | 2 +- .../webhooks/config/locales/crowdin/ro.yml | 4 +- 12 files changed, 90 insertions(+), 90 deletions(-) diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index d1ec0f0ab44..b8725df58be 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -360,7 +360,7 @@ ro: "15_4": standard: new_features_html: > - The release brings various features and improvements for you, e.g.
  • Enable automatic scheduling mode.
  • Set agenda item outcomes for meetings.
  • Generate PDF documents from a work package description.
  • Better manage a large number of projects with an enhanced project lists view.
  • Use @-mention of user when quote replying to a comment.
+ Versiunea aduce diverse caracteristici și îmbunătățiri pentru tine, de ex.
  • Activează modul de programare automată.
  • Stabilește rezultatele de pe ordinea de zi pentru ședințe.
  • Generează documentele PDF dintr-o descriere a pachetului de lucru.
  • O mai bună gestionare a unui număr mare de proiecte cu o vizualizare îmbunătățită a listelor de proiecte.
  • Utilizează @-mențiunea utilizatorului atunci când citezi un comentariu.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." @@ -625,11 +625,11 @@ ro: date_alerts: milestone_date: "Dată etapă" overdue: "Restanțe" - overdue_since: "since %{difference_in_days}." - property_today: "is today." - property_is: "is in %{difference_in_days}." - property_was: "was %{difference_in_days} ago." - property_is_deleted: "is deleted." + overdue_since: "de %{difference_in_days}" + property_today: "este azi." + property_is: "este în %{difference_in_days}" + property_was: "a fost acum %{difference_in_days}" + property_is_deleted: "este ștearsă." upsale: title: "Alerte date" description: "Cu alertele de date, veți fi notificat cu privire la următoarele date de început sau de sfârșit, astfel încât să nu ratați sau să uitați niciodată un termen limită important." @@ -1046,7 +1046,7 @@ ro: is_switched_from_manual_to_automatic: "Este posibil ca datele acestui pachet de lucru să trebuiască să fie recalculate după trecerea de la programarea manuală la cea automată din cauza relațiilor cu alte pachete de lucru." sharing: title: "Share work package" - show_all_users: "Show all users with whom the work package has been shared with" + show_all_users: "Arată toți utilizatorilor cu care pachetul de lucru a fost partajat" upsale: description: "Share work packages with users who are not members of the project." table: @@ -1343,7 +1343,7 @@ ro: close: "Close modal" open_project_storage_modal: waiting_title: - timeout: "Timeout" + timeout: "Expirat" waiting_subtitle: network_off: "There is a network problem." network_on: "Network is back. We are trying." diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index 631587880cf..011221d1057 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -78,13 +78,13 @@ ro: theme_warning: Schimbarea temei va suprascrie stilul personalizat. În acest caz, designul va fi pierdut. Sunteți sigur că doriți să continuați? enterprise: upgrade_to_ee: "Actualizare la ediția Enterprise" - add_token: "Încărcați un token de suport pentru ediția Enterprise" + add_token: "Încărcacă un token de suport pentru ediția Enterprise" delete_token_modal: - text: "Sunteți sigur că doriți să eliminați actualul token Enterprise edition utilizat?" + text: "Ești sigur că vrei să elimini actualul token Enterprise edition utilizat?" title: "Ștergeți tokenul" replace_token: "Înlocuiți tokenul de suport actual" - order: "Comandați ediția Enterprise on-premise" - paste: "Lipiți token-ul de suport pentru ediția Enterprise" + order: "Comandă ediția Enterprise on-premise" + paste: "Lipește token-ul de suport pentru ediția Enterprise" required_for_feature: "Acest add-on este disponibil numai cu un token de asistență pentru ediția Enterprise activ." enterprise_link: "Pentru mai multe informații, clic aici." start_trial: "Începeți o încercare gratuită" @@ -161,7 +161,7 @@ ro: atunci când aceștia se autentifică pentru prima dată cu OpenProject. Lăsați această casetă debifată pentru a permite doar conturilor existente în OpenProject să se autentifice prin LDAP! connection_encryption: "Criptarea conexiunii" - encryption_details: "LDAPS / STARTTLS opțiuni" + encryption_details: "Opțiuni LDAPS / STARTTLS" system_account: "Contul de sistem" system_account_legend: | OpenProject necesită acces doar pentru citire printr-un cont de sistem pentru a căuta utilizatori și grupuri în arborele LDAP. @@ -181,7 +181,7 @@ ro: section_more_info_link_html: > Această secțiune se referă la securitatea conexiunii acestei surse de autentificare LDAP. Pentru mai multe informații, consultați documentația Net::LDAP. tls_options: - verify_peer: "Verificarea certificatului SSL" + verify_peer: "Verifică certificatul SSL" verify_peer_description_html: > Enables strict SSL verification of the certificate trusted chain.
Warning: Unchecking this option disables SSL verification of the LDAP server certificate. This exposes your connection to Man in the Middle attacks. tls_certificate_description: "Dacă certificatul serverului LDAP nu se află în sursele de încredere ale acestui sistem, îl poți adăuga manual aici. Introdu un șir de certificate PEM X509." @@ -259,16 +259,16 @@ ro: reorder_confirmation: "Avertisment: Ordinea curentă a valorilor disponibile se va pierde. Continuați?" placeholder_version_select: "Work package or project selection is required first" instructions: - is_required: "Mark the custom field as required. This will make it mandatory to fill in the field when creating new or updating existing resources." + is_required: "Marchează câmpul personalizat ca obligatoriu. Acest lucru va face obligatorie completarea câmpului atunci când se creează resurse noi sau se actualizează resursele existente." is_required_for_project: "Bifează pentru a activa acest atribut și a-l face obligatoriu în toate proiectele. Nu poate fi dezactivat pentru proiecte individuale." - is_for_all: "Mark the custom field as available in all existing and new projects." + is_for_all: "Marcați câmpul personalizat ca disponibil în toate proiectele existente și noi." multi_select: "Permite utilizatorului să atribuie valori multiple acestui câmp personalizat." searchable: "Include valorile câmpului atunci când utilizezi funcționalitatea globală de căutare." searchable_for_project: "Bifează pentru a face acest atribut disponibil sub formă de filtru în listele de proiecte." - editable: "Allow the field to be editable by users themselves." + editable: "Permite câmpului să fie editat de către utilizatorii înșiși." admin_only: "Bifează pentru a face acest atribut vizibil doar administratorilor. Utilizatorii fără drepturi de administrator nu vor putea vedea sau edita acest atribut" is_filter: > - Allow the custom field to be used in a filter in work package views. Note that only with 'For all projects' selected, the custom field will show up in global views. + Permite ca, câmpul personalizat să fie utilizat într-un filtru în vizualizările pachetului de lucru. Ține cont că numai cu 'Pentru toate proiectele' selectate, câmpul personalizat va apărea în vizualizări globale. tab: no_results_title_text: În acest moment nu există câmpuri personalizate. no_results_content_text: Creează câmp personalizat nou @@ -331,7 +331,7 @@ ro: failed_text: "Solicitarea de ștergere a proiectului %{name} a eșuat. Proiectul a rămas arhivat." completed: "Ștergerea proiectului %{name} finalizată" completed_text: "Cererea de ștergere a proiectului \"%{name}\" a fost finalizată." - completed_text_children: "Additionally, the following subprojects have been deleted:" + completed_text_children: "În plus, următoarele subproiecte au fost eliminate:" index: open_as_gantt: "Deschide ca vizualizare Gantt" no_results_title_text: În acest moment nu există proiecte @@ -490,8 +490,8 @@ ro: access_token: create_dialog: title: Token generated - header: The %{type} token has been generated - warning: Note that this is the only time you will see this token, make sure to copy it now. + header: Token-ul %{type} a fost generat + warning: Țineți cont că aceasta este singura dată când vei vedea acest token, asigură-te că îl copiezi acum. errors: token_name_blank: "Please provide an API token name" token_name_in_use: "This API token name is already in use, please select a different one" @@ -508,7 +508,7 @@ ro: notice_reset_token: "S-a generat un token nou %{type} . Token-ul de acces este:" token_value_warning: "Notă: este singura dată când veți vedea acest token, asigurați-vă că îl copiați acum." no_results_title_text: În acest moment nu există tichete de acces disponibile. - notice_api_token_revoked: "The API token has been deleted. To create a new token please use the button in the API section." + notice_api_token_revoked: "Token-ul API a fost șters. Pentru a crea un nou token, foloște butonul din secțiunea API." notice_rss_token_revoked: "The RSS token has been deleted. To create a new token please use the link in the RSS section." notice_ical_token_revoked: 'iCalendar token "%{token_name}" for calendar "%{calendar_name}" of project "%{project_name}" has been revoked. The iCalendar URL with this token is now invalid.' news: @@ -720,9 +720,9 @@ ro: The current types of the work packages aren't enabled in the target project. Please enable the types in the target project if you'd like them to remain unchanged. Otherwise, select an available type in the target project from the list. sharing: missing_workflow_warning: - title: "Workflow missing for work package sharing" - message: "No workflow is configured for the 'Work package editor' role. Without a workflow, the shared with user cannot alter the status of the work package. Workflows can be copied. Select a source type (e.g. 'Task') and source role (e.g. 'Member'). Then select the target types. To start with, you could select all the types as targets. Finally, select the 'Work package editor' role as the target and press 'Copy'. After having thus created the defaults, fine tune the workflows as you do for every other role." - link_message: "Configure the workflows in the administration." + title: "Lipsește fluxul pentru partajarea pachetului de lucru" + message: "Niciun flux de lucru nu este configurat pentru rolul 'Editor pachete de lucru'. Fără un flux de lucru, utilizatorul nu poate modifica statusul pachetului de lucru. Fluxurile de lucru pot fi copiate. Selectează un tip sursă (de ex. 'Task') şi rolul sursă (de ex. 'Membru'). Apoi selectează tipurile țintă. Pentru a începe, ai putea selecta toate tipurile ca ținte. După aceea, selectează rolul de „editor pachete de lucru” ca țintă și apăsă „Copiază”. După ce ai creat cele implicite, reglează fluxurile de lucru așa cum faci pentru orice alt rol." + link_message: "Configurează fluxurile de lucru din administrare." templated_subject_hint: Automatically generated through type %{type} summary: reports: @@ -752,7 +752,7 @@ ro: label_add_description: "Adaugă descriere" lag: subject: "Întârziere" - caption: "The minimum number of working days to keep in between the two work packages." + caption: "Numărul minim de zile lucrătoare care trebuie păstrate între cele două pachete de lucru." relations: label_new_child_created: "Pachet de lucru nou creat și adăugat ca și copil" label_relates_singular: "asociat cu" @@ -1042,7 +1042,7 @@ ro: user: "Utilizator" user: admin: "Administrator" - auth_source: "Authentication source" + auth_source: "Sursa de autentificare" ldap_auth_source: "Conexiune LDAP" identity_url: "Identity URL" current_password: "Parola curentă" @@ -1081,8 +1081,8 @@ ro: begin_deletion: "Început de ștergere" children: "Subelemente" derived_done_ratio: "Total % finalizat" - derived_remaining_hours: "Total remaining work" - derived_remaining_time: "Total remaining work" + derived_remaining_hours: "Total muncă rămasă" + derived_remaining_time: "Total muncă rămasă" done_ratio: "% finalizat" duration: "Durată" end_insertion: "Sfârșitul inserării" @@ -1178,7 +1178,7 @@ ro: unknown_property_nested: "are calea necunoscută '%{path}'." unremovable: "nu poate fi îndepărtată." url_not_secure_context: > - nu oferă un "Context securizat". Folosiţi fie HTTPS sau o adresă de tip buclă, cum ar fi localhost. + nu oferă un "Context securizat". Folosește fie HTTPS sau o adresă de tip buclă, cum ar fi localhost. wrong_length: "nu are lungimea corectă (ar trebui să fie de %{count} characters)." models: ldap_auth_source: @@ -1219,7 +1219,7 @@ ro: fragment_present: "nu poate conține un fragment." invalid_uri: "trebuie să fie un URI valid." relative_uri: "trebuie să fie un URI absolut." - secured_uri: 'nu oferă un "Context securizat". Folosiţi fie HTTPS sau o adresă de tip buclă, cum ar fi localhost.' + secured_uri: 'nu oferă un "Context securizat". Folosește fie HTTPS sau o adresă de tip buclă, cum ar fi localhost.' forbidden_uri: "este interzisă de către server." scopes: not_match_configured: "nu se potrivește cu domeniile de aplicare disponibile." @@ -1322,15 +1322,15 @@ ro: circular_dependency: "Relația creează un cerc închis." attributes: to_id: - error_not_found: "not found or not visible." - error_readonly: "cannot be changed for existing relations." + error_not_found: "negăsit sau invizibil." + error_readonly: "nu poate fi schimbat pentru relaţiile existente." from_id: - error_not_found: "not found or not visible." - error_readonly: "cannot be changed for existing relations." + error_not_found: "negăsit sau invizibil." + error_readonly: "nu poate fi schimbat pentru relaţiile existente." lag: greater_than_or_equal_to: - zero: "cannot be negative." - less_than_or_equal_to: "is too high." + zero: "nu poate fi negativ." + less_than_or_equal_to: "este prea mare." repository: not_available: "Nu este disponibil furnizorul de SCM" not_whitelisted: "nu este permisă de configurație." @@ -1384,8 +1384,8 @@ ro: attributes: id: format: "%{message}" - cannot_add_child_because_of_lack_of_permission: "Cannot add child because you don't have permissions to edit the selected work package." - blank: "ID can't be blank." + cannot_add_child_because_of_lack_of_permission: "Nu poți adăuga un copil deoarece nu ai permisiunea de a edita pachetul de lucru selectat." + blank: "ID nu poate fi gol." assigned_to: format: "%{message}" done_ratio: @@ -1422,11 +1422,11 @@ ro: only_same_project_categories_allowed: "Categoria unui pachet de lucru trebuie să fie în cadrul aceluiaşi proiect ca pachetul de lucru." does_not_exist: "Categoria specificată nu există." estimated_hours: - not_a_number: "is not a valid duration." + not_a_number: "nu este o durată validă." cant_be_inferior_to_remaining_work: "cannot be lower than Remaining work." must_be_set_when_remaining_work_and_percent_complete_are_set: "required when Remaining work and % Complete are set." remaining_hours: - not_a_number: "is not a valid duration." + not_a_number: "nu este o durată validă." cant_exceed_work: "cannot be higher than Work." must_be_set_when_work_is_set: "required when Work is set." must_be_set_when_work_and_percent_complete_are_set: "required when Work and % Complete are set." @@ -1503,7 +1503,7 @@ ro: custom_field: "Câmp personalizat" "doorkeeper/application": "Aplicație OAuth" forum: "Forum" - global_role: "Global role" + global_role: "Rol Global" group: "Grup" issue_priority: one: "Prioritate" @@ -1518,9 +1518,9 @@ ro: placeholder_user: "Utilizator Placeholder" project: "Proiect" project_query: - one: "Project list" + one: "Listă proiecte" few: "Listă proiecte" - other: "Listă proiecte" + other: "Listă de proiecte" query: "Interogare personalizată" reminder: "Reminder" role: @@ -1529,7 +1529,7 @@ ro: other: "Roluri" status: "Stare pachet de lucru" token/api: - one: Tichet de acces + one: Token acces few: Token-uri de acces other: Token-uri de acces type: "Tip" @@ -1623,7 +1623,7 @@ ro: default_columns: "Coloane implicite" description: "Descriere" derived_due_date: "Dată finală derivată" - derived_estimated_hours: "Total work" + derived_estimated_hours: "Total muncă" derived_start_date: "Dată început derivată" direction: "Direction" display_sums: "Afişare totaluri" @@ -2015,7 +2015,7 @@ ro: customize_life_cycle: description: "Create and organize different project phases than the ones provided by PM2 project cycle planning." form_configuration: - description: "Personalizați configurația formularului cu aceste add-on-uri suplimentare:" + description: "Personalizează configurația formularului cu aceste add-on-uri suplimentare:" add_groups: "Adaugă noi grupuri de atribut" rename_groups: "Redenumește atribute grupuri" enumeration_activities: "Activități de urmărire timp activate" @@ -2245,10 +2245,10 @@ ro: blocks: community: "Comunitatea OpenProject" upsale: - title: "Actualizați la ediția Enterprise" + title: "Actualizează la ediția Enterprise" more_info: "Mai multe informatii" links: - upgrade_enterprise_edition: "Actualizați la ediția Enterprise" + upgrade_enterprise_edition: "Actualizează la ediția Enterprise" postgres_migration: "Migrarea instalației dvs. către PostgreSQL" user_guides: "Ghiduri utilizator" faq: "Întrebări Frecvente" @@ -3046,8 +3046,8 @@ ro: label_yesterday: "ieri" label_zen_mode: "Zen mode" label_role_type: "Tip" - label_member_role: "Project role" - label_global_role: "Global role" + label_member_role: "Rol proiect" + label_global_role: "Rol Global" label_not_changeable: "(nu se poate modifica)" label_global: "Global" label_seeded_from_env_warning: This record has been created through a setting environment variable. It is not editable through UI. @@ -3096,7 +3096,7 @@ ro: one: "Mai există un pachet de lucru cu notificări." few: "Există %{count} pachete de lucru cu notificări." other: "Există %{count} de pachete de lucru cu notificări." - open_in_browser: "Open in browser" + open_in_browser: "Deschide în browser" reason: watched: "Urmărit" assigned: "Alocat" @@ -3167,9 +3167,9 @@ ro: mail_body_incoming_email_error_logs: "Jurnale" mail_body_lost_password: "Pentru a vă modifica parola, dați click pe următorul link:" mail_password_change_not_possible: - title: "Password change not possible" - body: "Your account at %{app_title} is connected to an external authentication provider (%{name})." - subtext: "Passwords for external account cannot be changed in the application. Please use the lost password functionality of your authentication provider." + title: "Modificarea parolei nu este posibilă" + body: "Contul tău %{app_title} este conectat la un furnizor extern de autentificare (%{name})." + subtext: "Parolele pentru contul extern nu pot fi schimbate în aplicație. Utilizează funcția de parolă pierdută a furnizorului tău de autentificare." mail_body_register: "Bine ai venit la %{app_title}. Te rog să activezi contul făcând clic pe acest link:" mail_body_register_header_title: "E-mail de invitație pentru membrii proiectului" mail_body_register_user: "Dragă %{name}," @@ -3260,9 +3260,9 @@ ro: notice_locking_conflict: "Informaţia a fost actualizată de cel puţin un alt utilizator între timp." notice_locking_conflict_additional_information: "Modificările au fost făcute de %{users}." notice_locking_conflict_reload_page: "Te rog să reîncarci pagina, examinează modificările și reaplică actualizările." - notice_locking_conflict_warning: "This page has been updated by someone else. To not lose your edits, copy them locally and reload to view the updated version." - notice_locking_conflict_danger: "Could not save your changes because of conflicting modifications. To not lose your edits, copy them locally and reload to view the updated version." - notice_locking_conflict_action_button: "Discard changes and reload" + notice_locking_conflict_warning: "Această pagină a fost actualizată de altcineva. Pentru a nu pierde editările, copiază-le local și reîncarcă pentru a vizualiza versiunea actualizată." + notice_locking_conflict_danger: "Modificările nu au putut fi salvate din cauza modificărilor contradictorii. Pentru a nu pierde editările, copiază-le local și reîncarcă pentru a vizualiza versiunea actualizată." + notice_locking_conflict_action_button: "Renunță la modificări și reîncărcă" notice_member_added: '%{name} a fost adăugat în proiect.' notice_members_added: A adăugat %{number} utilizatori la proiect. notice_member_removed: "%{user} a fost eliminat din proiect." @@ -3366,7 +3366,7 @@ ro: permission_edit_project_attributes: "Edit project attributes" permission_edit_project_phases: "Edit project phases" permission_edit_reportings: "Editare raportări" - permission_edit_time_entries: "Editați jurnalele de timp pentru alți utilizatori" + permission_edit_time_entries: "Editează jurnalele de timp pentru alți utilizatori" permission_edit_timelines: "Editare linii de timp" permission_edit_wiki_pages: "Editare pagini wiki" permission_export_work_packages: "Export pachete de lucru" @@ -3571,7 +3571,7 @@ ro: oauth_application_details_link_text: "Mergi la pagina setări" setup_documentation_details: "Dacă aveți nevoie de ajutor pentru configurarea unui nou depozit de fișiere, consultați documentația: " setup_documentation_details_link_text: "Configurarea fișierelor de stocare" - show_warning_details: "Pentru a utiliza acest spațiu de stocare a fișierelor, nu uitați să activați modulul și spațiul de stocare specific în setările de proiect ale fiecărui proiect dorit." + show_warning_details: "Pentru a utiliza acest spațiu de stocare a fișierelor, nu uita să activezi modulul și spațiul de stocare specific în setările de proiect ale fiecărui proiect dorit." subversion: existing_title: "Repo Subversion existent" existing_introduction: "Dacă aveţi deja un repo de Subversion, puteți să-l conectați cu OpenProject pentru a-l accesa din aplicație." @@ -3591,8 +3591,8 @@ ro: warnings: cannot_annotate: "Acest fișier nu poate fi adnotat." scheduling: - manual: "set to Manual" - automatic: "set to Automatic" + manual: "setează la Manual" + automatic: "setează la Automat" search_input_placeholder: "Caută ..." setting_allowed_link_protocols: "Allowed link protocols" setting_allowed_link_protocols_text_html: >- @@ -3808,7 +3808,7 @@ ro: type: "Întregul rând pe tipuri" priority: "Întregul rând în funcție de Prioritate" icalendar: - enable_subscriptions_text_html: Allows users with the necessary permissions to subscribe to OpenProject calendars and access work package information via an external calendar client. Note: Please read about iCalendar subscriptions to understand potential security risks before enabling this. + enable_subscriptions_text_html: Permite utilizatorilor cu permisiunile necesare să se aboneze la calendarele OpenProject şi să acceseze informaţiile pachetului de lucru prin intermediul unui client extern al calendarului. Notă: Te rog să citești despre abonamentele iCalendar pentru a înţelege potenţialele riscuri de securitate înainte de a activa acest lucru. language_name_being_default: "%{language_name} (default)" notifications: events_explanation: "Stabilește pentru ce eveniment se trimite un e-mail. Pachetele de lucru sunt excluse din această listă, deoarece notificările pentru acestea pot fi configurate în mod specific pentru fiecare utilizator." @@ -3900,9 +3900,9 @@ ro: text_custom_field_hint_activate_per_project_and_type: > Câmpurile personalizate trebuie să fie activate pentru fiecare pachet de lucru și pentru fiecare proiect. text_wp_status_read_only_html: > - Ediția Enterprise va adăuga aceste add-on-uri suplimentare pentru câmpurile de statusuri ale pachetelor de lucru:
  • Permiteți să marcați pachetele de lucru ca fiind numai pentru citire pentru anumite stări
+ Ediția Enterprise va adăuga aceste add-on-uri suplimentare pentru câmpurile de statusuri ale pachetelor de lucru:
  • Permite să marchezi pachetele de lucru ca fiind numai pentru citire pentru anumite stări
text_project_custom_field_html: > - Ediția Enterprise va adăuga aceste add-on-uri suplimentare pentru câmpurile personalizate ale proiectelor:
  • Adăugați câmpuri personalizate pentru proiecte la lista de proiecte pentru a crea o vizualizare a portofoliului de proiecte
+ Ediția Enterprise va adăuga aceste add-on-uri suplimentare pentru câmpurile personalizate ale proiectelor:
  • Adăugă câmpuri personalizate pentru proiecte la lista de proiecte pentru a crea o vizualizare a portofoliului de proiecte
text_custom_logo_instructions: > Este recomandată utilizarea unui logo cu fundal transparent. Pentru a obține rezultate satisfăcătoare pe afișajele convenționale dar și pe cele de tipe retina, asigurați-vă că dimensiunea imaginii este de 460px pe 110px. text_custom_export_logo_instructions: > @@ -4089,12 +4089,12 @@ ro: warning_user_limit_reached_admin: > Adding additional users will exceed the current limit. Please upgrade your plan to be able to ensure external users are able to access this instance. warning_user_limit_reached_instructions: > - Ați atins limita de utilizatori (%{current}/%{max} utilizatori activi). Vă rugăm să contactați sales@openproject.com pentru a vă actualiza planul ediției Enterprise și a adăuga utilizatori suplimentari. + Ai atins limita de utilizatori (%{current}/%{max} utilizatori activi). Te rog să contactezi sales@openproject.com pentru a vă actualiza planul ediției Enterprise și a adăuga utilizatori suplimentari. warning_protocol_mismatch_html: > warning_bar: https_mismatch: - title: "Nepotrivire de configurare a modului HTTPS" + title: "Configurare greșită a modului HTTPS" text_html: > Aplicația ta rulează cu modul HTTPS setat la %{set_protocol}, dar solicitarea este o cerere %{actual_protocol} . Acest lucru va duce la erori! Va trebui să setezi următoarea valoare de configurare: %{setting_value}. Vezi documentația de instalare despre cum să setezi această configurație. hostname_mismatch: @@ -4194,12 +4194,12 @@ ro: additional_privileges_group: "Might have additional privileges (as group member)" additional_privileges_project_or_group: "Might have additional privileges (as project or group member)" project_queries: - publishing_denied: "You do not have permission to make project lists public." + publishing_denied: "Nu ai permisiunea pentru a publica listele de proiecte." access_warning: "Users will only see the projects they have access to. Sharing project lists does not impact individual project permissions." user_details: - owner: "List owner" - can_view_because_public: "Can already view because list is shared with everyone" - can_manage_public_lists: "Can edit due to global permissions" + owner: "Listează proprietar" + can_view_because_public: "Poate deja vizualiza deoarece lista este partajată cu toată lumea" + can_manage_public_lists: "Poate edita datorită permisiunilor globale" public_flag: label: "Share with everyone at %{instance_name}" caption: "Everyone can view this project list. Those with global edit permissions can modify it." @@ -4216,7 +4216,7 @@ ro: edit: "Editează" edit_description: "Can view, share and edit this project list." upsale: - message: "Sharing project lists with individual users is an enterprise add-on." + message: "Partajarea listelor de proiecte cu utilizatorii individuali este un add-on Enterprise." working_days: info: > Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level. @@ -4247,7 +4247,7 @@ ro: code_429: "Prea multe solicitări. Vă rugăm încercați mai târziu." code_500: "A apărut o eroare internă." code_500_outbound_request_failure: "An outbound request to another resource has failed with status code %{status_code}." - code_500_missing_enterprise_token: "The request can not be handled due to invalid or missing Enterprise token." + code_500_missing_enterprise_token: "Cererea nu poate fi gestionată din cauza token-ului Enterprise invalid sau lipsă." not_found: work_package: "Pachetul de lucru pe care îl căutați nu poate fi găsit sau a fost șters." expected: @@ -4440,11 +4440,11 @@ ro: you: tu link: link plugin_openproject_auth_plugins: - name: "OpenProject Auth Plugins" + name: "Plugin-urile OpenProject Auth" description: "Integration of OmniAuth strategy providers for authentication in OpenProject." plugin_openproject_auth_saml: name: "OmniAuth SAML / Single-Sign On" - description: "Adds the OmniAuth SAML provider to OpenProject" + description: "Adaugă furnizorul SAML OmniAuth la OpenProject" enterprise_plans: legacy_enterprise: "Enterprise Plan" enterprise_features: diff --git a/modules/calendar/config/locales/crowdin/js-ro.yml b/modules/calendar/config/locales/crowdin/js-ro.yml index c970dc3245a..0ef5f37b02d 100644 --- a/modules/calendar/config/locales/crowdin/js-ro.yml +++ b/modules/calendar/config/locales/crowdin/js-ro.yml @@ -4,5 +4,5 @@ ro: calendar: create_new: 'Creează un calendar nou' title: 'Calendar' - too_many: 'Există %{count} pachete de lucru în total, dar numai %{max} poate fi afișat.' + too_many: 'Există %{count} pachete de lucru în total, dar numai %{max} pot fi afișate.' unsaved_title: 'Calendar fără nume' diff --git a/modules/calendar/config/locales/crowdin/ro.yml b/modules/calendar/config/locales/crowdin/ro.yml index bb084898069..4dc7b8d757f 100644 --- a/modules/calendar/config/locales/crowdin/ro.yml +++ b/modules/calendar/config/locales/crowdin/ro.yml @@ -1,8 +1,8 @@ #English strings go here ro: plugin_openproject_calendar: - name: "OpenProject Calendar" - description: "Provides calendar views." + name: "Calendar OpenProject" + description: "Oferă vizualizări calendar." label_calendar: "Calendar" label_calendar_plural: "Calendare" label_new_calendar: "New calendar" diff --git a/modules/costs/config/locales/crowdin/js-ro.yml b/modules/costs/config/locales/crowdin/js-ro.yml index 64a94d4263c..3f90960013b 100644 --- a/modules/costs/config/locales/crowdin/js-ro.yml +++ b/modules/costs/config/locales/crowdin/js-ro.yml @@ -21,13 +21,13 @@ #++ ro: js: - text_are_you_sure: "Ești sigur?" + text_are_you_sure: "Sunteți sigur?" work_packages: property_groups: costs: "Costuri" properties: overallCosts: "Costuri totale" - spentUnits: "Unități consumate" + spentUnits: "Unități cheltuite" button_log_costs: "Înregistrare costuri unitare" label_hour: "oră" label_hours: "ore" diff --git a/modules/costs/config/locales/crowdin/ro.yml b/modules/costs/config/locales/crowdin/ro.yml index 57502d9ac62..2c5127bdd2d 100644 --- a/modules/costs/config/locales/crowdin/ro.yml +++ b/modules/costs/config/locales/crowdin/ro.yml @@ -106,7 +106,7 @@ ro: caption_save_rate: "Salvează tarif" caption_set_rate: "Setează tarif curent" caption_show_locked: "Afișați tipurile blocate" - caption_log_time_dialog: "Consum timp" + caption_log_time_dialog: "Registru timp" description_date_for_new_rate: "Dată pentru noul tarif" description_costs_settings: "Define the desired format for the costs in all projects." description_time_settings: "Define which fields are mandatory to fill when logging time in all projects." diff --git a/modules/documents/config/locales/crowdin/ro.yml b/modules/documents/config/locales/crowdin/ro.yml index 83a5761b1f6..9d98a684691 100644 --- a/modules/documents/config/locales/crowdin/ro.yml +++ b/modules/documents/config/locales/crowdin/ro.yml @@ -34,7 +34,7 @@ ro: enumeration_doc_categories: "Document nou" documents: label_attachment_author: "Autorul anexei" - label_categories: "Categories" + label_categories: "Categorii" new_category: "Categorie nouă" label_document_added: "Document adăugat" label_document_new: "Document nou" diff --git a/modules/grids/config/locales/crowdin/js-ro.yml b/modules/grids/config/locales/crowdin/js-ro.yml index 31b00139e8c..93c6f2f41da 100644 --- a/modules/grids/config/locales/crowdin/js-ro.yml +++ b/modules/grids/config/locales/crowdin/js-ro.yml @@ -5,7 +5,7 @@ ro: remove: 'Eliminați widget-ul' configure: 'Configurați widget-ul' upsale: - text: "Unele widgeturi, cum ar fi widgetul grafic al pachetului de lucru, sunt disponibile numai în ediția Enterprise." + text: "Unele widget-uri, cum ar fi widget-ul grafic pachet de lucru, sunt disponibile doar în Enterprise Edition." link: 'Ediția Enterprise.' widgets: missing_permission: "Nu ai drepturile necesare pentru a vizualiza acest widget." diff --git a/modules/job_status/config/locales/crowdin/ro.yml b/modules/job_status/config/locales/crowdin/ro.yml index 7e78ab566bb..f119720347e 100644 --- a/modules/job_status/config/locales/crowdin/ro.yml +++ b/modules/job_status/config/locales/crowdin/ro.yml @@ -1,8 +1,8 @@ ro: label_job_status_plural: "Job statuses" plugin_openproject_job_status: - name: "OpenProject Job status" - description: "Listing and status of background jobs." + name: "Stare lucrări OpenProject" + description: "Listare și stare lucrări de fundal." job_status_dialog: download_starts: 'Descărcarea ar trebui să înceapă automat.' link_to_download: 'Or, %{link} to download.' diff --git a/modules/reporting/config/locales/crowdin/ro.yml b/modules/reporting/config/locales/crowdin/ro.yml index 6b730320b60..459bfcc7f5a 100644 --- a/modules/reporting/config/locales/crowdin/ro.yml +++ b/modules/reporting/config/locales/crowdin/ro.yml @@ -21,8 +21,8 @@ #++ ro: plugin_openproject_reporting: - name: "OpenProject Reporting" - description: "This plugin allows creating custom cost reports with filtering and grouping created by the OpenProject Time and costs plugin." + name: "Raport OpenProject" + description: "Acest plugin permite crearea de rapoarte de costuri personalizate cu filtrare şi grupare create de OpenProject Time şi de plugin-ul costuri." button_save_report_as: "Salvează raportul ca..." comments: "Comentariu" cost_reports_title: "Timp și costuri" diff --git a/modules/team_planner/config/locales/crowdin/ro.yml b/modules/team_planner/config/locales/crowdin/ro.yml index 1b3c3660aa0..4fe36642f3f 100644 --- a/modules/team_planner/config/locales/crowdin/ro.yml +++ b/modules/team_planner/config/locales/crowdin/ro.yml @@ -2,7 +2,7 @@ ro: plugin_openproject_team_planner: name: "Planificare echipă OpenProject" - description: "Provides team planner views." + description: "Oferă vederi planificator echipă." permission_view_team_planner: "Vezi planificatorul echipei" permission_manage_team_planner: "Gestionează planificatorul de echipe" project_module_team_planner_view: "Planificare echipă" diff --git a/modules/webhooks/config/locales/crowdin/ro.yml b/modules/webhooks/config/locales/crowdin/ro.yml index e3a83d82ca4..e6ea40a75ce 100644 --- a/modules/webhooks/config/locales/crowdin/ro.yml +++ b/modules/webhooks/config/locales/crowdin/ro.yml @@ -1,7 +1,7 @@ ro: plugin_openproject_webhooks: - name: "OpenProject Webhooks" - description: "Provides a plug-in API to support OpenProject webhooks for better 3rd party integration." + name: "Webhook-uri OpenProject" + description: "Oferă un plug-in API pentru a sprijini OpenProject webhooks pentru o mai bună integrare a terților." activerecord: attributes: webhooks/webhook: From e0c1ab80d36e4650a5050a80bb14dfc7c8027619 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 05:53:43 +0000 Subject: [PATCH 085/260] Bump selenium-devtools from 0.134.0 to 0.135.0 Bumps [selenium-devtools](https://github.com/SeleniumHQ/selenium) from 0.134.0 to 0.135.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES) - [Commits](https://github.com/SeleniumHQ/selenium/commits) --- updated-dependencies: - dependency-name: selenium-devtools dependency-version: 0.135.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index de889207a07..277fb5fbbf5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1124,7 +1124,7 @@ GEM nokogiri (>= 1.16.8) secure_headers (7.1.0) securerandom (0.4.1) - selenium-devtools (0.134.0) + selenium-devtools (0.135.0) selenium-webdriver (~> 4.2) selenium-webdriver (4.30.1) base64 (~> 0.2) @@ -1869,7 +1869,7 @@ CHECKSUMS sanitize (7.0.0) sha256=269d1b9d7326e69307723af5643ec032ff86ad616e72a3b36d301ac75a273984 secure_headers (7.1.0) sha256=6b1f9d5f9507af2948f4636452c41c09371927836396c2185438ffdf0a731124 securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 - selenium-devtools (0.134.0) sha256=ad53fc638dc72be8d5606c479de65744b5eaefdd83206edd3ddafc88ef1bc029 + selenium-devtools (0.135.0) sha256=3862ec1f3e940a030f492b3691d11af35544789f961fcd0633cb89e4ea4251ec selenium-webdriver (4.30.1) sha256=c498fef823a44bf2b110b46edaee3e86aeeb21f8b4e7e12088b4995af4a216f7 semantic (1.6.1) sha256=3cdbb48f59198ebb782a3fdfb87b559e0822a311610db153bae22777a7d0c163 shoulda-context (2.0.0) sha256=7adf45342cd800f507d2a053658cb1cce2884b616b26004d39684b912ea32c34 From ee1a98d5fc25192605f585e66520f2b3440882b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 7 Apr 2025 08:51:54 +0200 Subject: [PATCH 086/260] Update publiccode.yml --- publiccode.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/publiccode.yml b/publiccode.yml index 9309e869648..ff20ddae339 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -184,7 +184,7 @@ description: Zusätzlich bietet der Hersteller in ihrer [Enterprise Cloud](https://www.openproject.org/de/enterprise-edition) ein Hosting in einem Rechenzentrum innerhalb der Europäischen Union an, das gemäß der Datenschutz-Grundverordnung (DS-GVO) erfolgt. OpenProject entspricht den Anforderungen des [BSI - IT-Grundschutzes](https://www.bsi.bund.de/DE/Themen/ITGrundschutz/itgrundschutz_node.html) + IT-Grundschutzes](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html) und wird kontinuierlich auf Basis der WCAG 2.1-Richtlinien getestet, wie im [Prüfbericht](https://gitlab.opencode.de/bmi/opendesk/info/-/blob/main/24.03/Barrierefreiheit/Barrierefreiheitsbericht%20-%20Komponente%20Projekte.pdf) From 695c6e1ab9337bede8a3fd32fc4fa4c3c670f036 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 06:00:48 +0000 Subject: [PATCH 087/260] Bump brakeman from 7.0.1 to 7.0.2 Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v7.0.1...v7.0.2) --- updated-dependencies: - dependency-name: brakeman dependency-version: 7.0.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index de889207a07..013937dd304 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -399,7 +399,7 @@ GEM bindata (2.5.0) bootsnap (1.18.4) msgpack (~> 1.2) - brakeman (7.0.1) + brakeman (7.0.2) racc browser (6.2.0) builder (3.3.0) @@ -1535,7 +1535,7 @@ CHECKSUMS bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc bindata (2.5.0) sha256=29dccb8ba1cc9de148f24bb88930840c62db56715f0f80eccadd624d9f3d2623 bootsnap (1.18.4) sha256=ac4c42af397f7ee15521820198daeff545e4c360d2772c601fbdc2c07d92af55 - brakeman (7.0.1) sha256=ec751d439820ed9d04d4ed00ff4fb21ac91689fcbb6cc564b786a4061c8f720d + brakeman (7.0.2) sha256=b602d91bcec6c5ce4d4bc9e081e01f621c304b7a69f227d1e58784135f333786 browser (6.2.0) sha256=281d5295788825c9396427c292c2d2be0a5c91875c93c390fde6e5d61a5ace2d budgets (1.0.0) builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f From 69da8e524130475f7203ecb75cb11a46e91ce8b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 05:56:33 +0000 Subject: [PATCH 088/260] Bump doorkeeper from 5.8.1 to 5.8.2 Bumps [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) from 5.8.1 to 5.8.2. - [Release notes](https://github.com/doorkeeper-gem/doorkeeper/releases) - [Changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/main/CHANGELOG.md) - [Commits](https://github.com/doorkeeper-gem/doorkeeper/compare/v5.8.1...v5.8.2) --- updated-dependencies: - dependency-name: doorkeeper dependency-version: 5.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 013937dd304..8c9956c772b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -478,7 +478,7 @@ GEM disposable (0.6.3) declarative (>= 0.0.9, < 1.0.0) representable (>= 3.1.1, < 4) - doorkeeper (5.8.1) + doorkeeper (5.8.2) railties (>= 5) dotenv (3.1.7) dotenv-rails (3.1.7) @@ -701,7 +701,7 @@ GEM ice_nine (0.11.2) interception (0.5) io-console (0.8.0) - irb (1.15.1) + irb (1.15.2) pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) @@ -1020,7 +1020,7 @@ GEM redis-client (0.24.0) connection_pool regexp_parser (2.10.0) - reline (0.6.0) + reline (0.6.1) io-console (~> 0.5) representable (3.2.0) declarative (< 0.1.0) @@ -1582,7 +1582,7 @@ CHECKSUMS descendants_tracker (0.0.4) sha256=e9c41dd4cfbb85829a9301ea7e7c48c2a03b26f09319db230e6479ccdc780897 diff-lcs (1.6.1) sha256=12a5a83f3e37a8e2f4427268e305914d5f1879f22b4e73bb1a09f76a3dd86cd4 disposable (0.6.3) sha256=7f2a3fb251bff6cd83f25b164043d4ec3531209b51b066ed476a9df9c2d384cc - doorkeeper (5.8.1) sha256=6d54f3c36755d8cfcb7e4f04fbcf1ff3492c816090ad78126ec8a722c292d26c + doorkeeper (5.8.2) sha256=a73d07aeaf590b1e7e2a35390446f23131c9f37bc0561653e514d3973f4d50d3 dotenv (3.1.7) sha256=c670df478675d23889e657beaca6fb423228f75ce9f052a0690c0d0daa333cf3 dotenv-rails (3.1.7) sha256=02c07b9601ad64046e196f48f6280c2cc660b073e08b30ad5c2f78b4872e9189 drb (2.2.1) sha256=e9d472bf785f558b96b25358bae115646da0dbfd45107ad858b0bc0d935cb340 @@ -1673,7 +1673,7 @@ CHECKSUMS ice_nine (0.11.2) sha256=5d506a7d2723d5592dc121b9928e4931742730131f22a1a37649df1c1e2e63db interception (0.5) sha256=a53818d636752a8df90d8c1bb2f7b6e13a7b828543cb02b50fbde98b849d7907 io-console (0.8.0) sha256=cd6a9facbc69871d69b2cb8b926fc6ea7ef06f06e505e81a64f14a470fddefa2 - irb (1.15.1) sha256=d9bca745ac4207a8b728a52b98b766ca909b86ff1a504bcde3d6f8c84faae890 + irb (1.15.2) sha256=222f32952e278da34b58ffe45e8634bf4afc2dc7aa9da23fed67e581aa50fdba iso8601 (0.13.0) sha256=298c2b15b7be5fa95a1372813d36a2257656cd8e906dfbc1f5cb409851425aa2 jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1 json (2.10.2) sha256=34e0eada93022b2a0a3345bb0b5efddb6e9ff5be7c48e409cfb54ff8a36a8b06 @@ -1829,7 +1829,7 @@ CHECKSUMS redis (5.4.0) sha256=798900d869418a9fc3977f916578375b45c38247a556b61d58cba6bb02f7d06b redis-client (0.24.0) sha256=ee65ee39cb2c38608b734566167fd912384f3c1241f59075e22858f23a085dbb regexp_parser (2.10.0) sha256=cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61 - reline (0.6.0) sha256=57620375dcbe56ec09bac7192bfb7460c716bbf0054dc94345ecaa5438e539d2 + reline (0.6.1) sha256=1afcc9d7cb1029cdbe780d72f2f09251ce46d3780050f3ec39c3ccc6b60675fb representable (3.2.0) sha256=cc29bf7eebc31653586849371a43ffe36c60b54b0a6365b5f7d95ec34d1ebace request_store (1.7.0) sha256=e1b75d5346a315f452242a68c937ef8e48b215b9453a77a6c0acdca2934c88cb responders (3.1.1) sha256=92f2a87e09028347368639cfb468f5fefa745cb0dc2377ef060db1cdd79a341a From 114f27d91c32620c6634110fca72dc0a2dc3f27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 24 Mar 2025 19:55:34 +0100 Subject: [PATCH 089/260] Primerize banners --- app/views/common/upsale.html.erb | 56 +++++++++++-------- .../free-trial-button.component.html | 2 +- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/app/views/common/upsale.html.erb b/app/views/common/upsale.html.erb index 0ec58904a67..2484930d72d 100644 --- a/app/views/common/upsale.html.erb +++ b/app/views/common/upsale.html.erb @@ -9,7 +9,7 @@ <% end %>
-

<%= feature_title %>

+ <%= render(Primer::Beta::Heading.new(tag: :h2)) { feature_title } %> <% if feature_description.empty? %>

<%= t("js.admin.enterprise.upsale.benefits.description") %> @@ -19,9 +19,7 @@ <%= t("js.admin.enterprise.upsale.benefits.professional_support_text") %>

<% else %> -

- <%= feature_description %> -

+ <%= render(Primer::Beta::Text.new) { feature_description } %> <% end %>

@@ -40,25 +38,37 @@
<%= t("admin.enterprise.upgrade_info") %>

- <%= link_to( - OpenProject::Static::Links.links[:contact_us][:href], - { class: "button", - aria: { label: t("admin.enterprise.buttons.contact") }, - target: "_blank", - title: t("admin.enterprise.buttons.contact") } - ) do %> - <%= t("admin.enterprise.buttons.contact") %> - <% end %> - <%= link_to( - OpenProject::Static::Links.links[:pricing][:href], - { class: "button -primary", - aria: { label: t("admin.enterprise.buttons.upgrade") }, + <%= + render(Primer::OpenProject::FlexLayout.new(align_items: :center, style: "justify-self: center")) do |flex| + flex.with_column do + render(Primer::Beta::Button.new( + tag: :a, + scheme: :secondary, + href: OpenProject::Static::Links.links[:contact_us][:href], target: "_blank", - title: t("admin.enterprise.buttons.upgrade") } - ) do %> - <%= spot_icon("enterprise-addons") %> - <%= t("admin.enterprise.buttons.upgrade") %> - <% end %> - + title: t("admin.enterprise.buttons.contact"), + aria_label: t("admin.enterprise.buttons.contact"), + )) { t("admin.enterprise.buttons.contact") } + end + + flex.with_column(ml: 1) do + render(Primer::Beta::Button.new( + tag: :a, + scheme: :primary, + href: OpenProject::Static::Links.links[:pricing][:href], + target: "_blank", + title: t("admin.enterprise.buttons.upgrade"), + aria_label: t("admin.enterprise.buttons.upgrade"), + )) do |link| + link.with_leading_visual_icon(icon: :"op-enterprise-addons") + t("admin.enterprise.buttons.upgrade") + end + end + + flex.with_column(ml: 1) do + angular_component_tag("opce-free-trial-button") + end + end + %>
diff --git a/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html b/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html index c42e0558a60..d6679b3cf5b 100644 --- a/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html +++ b/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html @@ -4,7 +4,7 @@ - -
- - - - - {{text.you_contribute}} - - - - - - diff --git a/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.sass b/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.sass deleted file mode 100644 index 52a027076d2..00000000000 --- a/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.sass +++ /dev/null @@ -1,52 +0,0 @@ -@import '../../app/spot/styles/sass/variables' - -.op-enterprise-banner - - &--header - font-size: 20px - line-height: 24px - display: grid - grid-template-columns: auto auto 1fr - align-items: center - - &--title - margin-left: $spot-spacing-0_5 - - &--description - display: block - @include spot-body-small - margin-bottom: $spot-spacing-0_75 - - &--image - width: 115px - height: 75px - padding-right: 20px - margin: auto - - &--buttons - display: flex - justify-content: flex-end - align-items: center - - a.button - text-decoration: none - - &--info-button - padding-top: $spot-spacing-1 - padding-right: $spot-spacing-1_5 - display: flex - justify-content: center - align-items: center - text-decoration: none - - .spot-icon:before - padding-right: 0.875rem - - &--collapsible-button - background: transparent - color: $spot-color-main - border: 0 - padding: $spot-spacing-0_5 $spot-spacing-0_5 - cursor: pointer - display: flex - justify-content: flex-end diff --git a/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.ts b/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.ts deleted file mode 100644 index fc6af3c8022..00000000000 --- a/frontend/src/app/shared/components/enterprise-banner/enterprise-banner.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ChangeDetectionStrategy, Component, ElementRef, Injector, Input, OnInit } from '@angular/core'; -import { BannersService } from 'core-app/core/enterprise/banners.service'; -import { I18nService } from 'core-app/core/i18n/i18n.service'; -import { imagePath } from 'core-app/shared/helpers/images/path-helper'; -import { OpModalService } from '../modal/modal.service'; -import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; -import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs'; -import { pricingUrl } from 'core-app/core/setup/globals/constants.const'; - -@Component({ - selector: 'op-enterprise-banner', - changeDetection: ChangeDetectionStrategy.OnPush, - styleUrls: ['./enterprise-banner.component.sass'], - templateUrl: './enterprise-banner.component.html', -}) -export class EnterpriseBannerComponent implements OnInit { - @Input() public leftMargin = false; - - @Input() public topMargin = false; - - @Input() public textMessage:string; - - @Input() public linkMessage:string; - - @Input() public opReferrer:string; - - @Input() public moreInfoLink:string; - - @Input() public collapsible:boolean; - - public collapsed = false; - - link:string; - - pricingUrl = pricingUrl; - - text = { - enterpriseFeature: this.I18n.t('js.upsale.ee_only'), - become_hero: this.I18n.t('js.admin.enterprise.upsale.become_hero'), - you_contribute: this.I18n.t('js.admin.enterprise.upsale.you_contribute'), - button_trial: this.I18n.t('js.admin.enterprise.upsale.button_start_trial'), - upgrade: this.I18n.t('js.admin.enterprise.upsale.button_upgrade'), - more_info_link: `${this.pathHelper.appBasePath}/admin/enterprise`, - more_info_text: this.I18n.t('js.admin.enterprise.upsale.more_info'), - }; - - image = { - enterprise_edition: imagePath('enterprise-add-on.svg'), - }; - - constructor( - readonly elementRef:ElementRef, - protected I18n:I18nService, - protected bannersService:BannersService, - protected opModalService:OpModalService, - readonly injector:Injector, - readonly pathHelper:PathHelperService, - ) { - populateInputsFromDataset(this); - } - - ngOnInit():void { - this.link = this.bannersService.getEnterPriseEditionUrl({ referrer: this.opReferrer }); - this.collapsed = this.collapsible; - } - - toggleCollapse():void { - this.collapsed = !this.collapsed; - } -} diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index b42cc06d905..07cbb80f2cc 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -57,7 +57,6 @@ import { import { OPContextMenuComponent } from 'core-app/shared/components/op-context-menu/op-context-menu.component'; import { OpenprojectPrincipalRenderingModule } from 'core-app/shared/components/principal/principal-rendering.module'; import { FocusModule } from 'core-app/shared/directives/focus/focus.module'; -import { EnterpriseBannerComponent } from 'core-app/shared/components/enterprise-banner/enterprise-banner.component'; import { EnterprisePageComponent } from 'core-app/shared/components/enterprise-page/enterprise-page.component'; import { FreeTrialButtonComponent } from 'core-app/features/enterprise/free-trial-button/free-trial-button.component'; import { HomescreenNewFeaturesBlockComponent } from 'core-app/features/homescreen/blocks/new-features.component'; @@ -176,7 +175,6 @@ export function bootstrapModule(injector:Injector):void { EditableToolbarTitleComponent, // Enterprise Edition - EnterpriseBannerComponent, EnterprisePageComponent, FreeTrialButtonComponent, @@ -223,7 +221,6 @@ export function bootstrapModule(injector:Injector):void { RemoteFieldUpdaterComponent, // Enterprise Edition - EnterpriseBannerComponent, EnterprisePageComponent, FreeTrialButtonComponent, From 98313d1a210c7b2355f3198727156cc125350a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 25 Mar 2025 19:56:56 +0100 Subject: [PATCH 099/260] Replace notifications upsale pages --- .../enterprise}/date-alert-notifications.mp4 | Bin .../videos/enterprise}/share-work-package.mp4 | Bin app/views/notifications/date_alerts.html.erb | 8 +++++- app/views/notifications/share_upsale.html.erb | 8 +++++- config/locales/en.yml | 24 +++++++++++------- config/locales/js-en.yml | 5 ---- frontend/src/app/app.module.ts | 6 ----- .../share-upsale/share-upsale.component.html | 6 ----- .../share-upsale/share-upsale.component.ts | 21 --------------- .../ian-date-alerts-upsale.component.html | 6 ----- .../ian-date-alerts-upsale.component.ts | 21 --------------- .../in-app-notifications.module.ts | 4 --- .../routing/work-packages-routes.ts | 6 ----- frontend/src/app/shared/shared.module.ts | 3 --- .../global_styles/content/_enterprise.sass | 4 +++ 15 files changed, 33 insertions(+), 89 deletions(-) rename {frontend/src/assets/videos/notification-center => app/assets/videos/enterprise}/date-alert-notifications.mp4 (100%) rename {frontend/src/assets/videos/sharing => app/assets/videos/enterprise}/share-work-package.mp4 (100%) delete mode 100644 frontend/src/app/features/enterprise/share-upsale/share-upsale.component.html delete mode 100644 frontend/src/app/features/enterprise/share-upsale/share-upsale.component.ts delete mode 100644 frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.html delete mode 100644 frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.ts diff --git a/frontend/src/assets/videos/notification-center/date-alert-notifications.mp4 b/app/assets/videos/enterprise/date-alert-notifications.mp4 similarity index 100% rename from frontend/src/assets/videos/notification-center/date-alert-notifications.mp4 rename to app/assets/videos/enterprise/date-alert-notifications.mp4 diff --git a/frontend/src/assets/videos/sharing/share-work-package.mp4 b/app/assets/videos/enterprise/share-work-package.mp4 similarity index 100% rename from frontend/src/assets/videos/sharing/share-work-package.mp4 rename to app/assets/videos/enterprise/share-work-package.mp4 diff --git a/app/views/notifications/date_alerts.html.erb b/app/views/notifications/date_alerts.html.erb index 7bd17ca6e45..a9c14fed3bd 100644 --- a/app/views/notifications/date_alerts.html.erb +++ b/app/views/notifications/date_alerts.html.erb @@ -1,5 +1,11 @@ <% html_title t("js.notifications.title") %> <% content_for :content_body do %> - <%= angular_component_tag "opce-ian-date-alerts-upsale" %> + <%= render template: "common/upsale", + locals: { + feature_title: t("enterprise_features.date_alerts"), + feature_description: t("ee.upsale.date_alerts.description"), + feature_reference: "enterprise-date-alerts", + feature_video: "enterprise/date-alert-notifications.mp4" + } %> <% end %> diff --git a/app/views/notifications/share_upsale.html.erb b/app/views/notifications/share_upsale.html.erb index 6b72a636ae6..151e3b1d4ad 100644 --- a/app/views/notifications/share_upsale.html.erb +++ b/app/views/notifications/share_upsale.html.erb @@ -1,5 +1,11 @@ <% html_title t("js.notifications.title") %> <% content_for :content_body do %> - <%= angular_component_tag "opce-share-upsale" %> + <%= render template: "common/upsale", + locals: { + feature_title: t("enterprise_features.work_package_sharing"), + feature_description: t("ee.upsale.work_package_sharing.description"), + feature_reference: "enterprise-work-package-sharing", + feature_video: "enterprise/share-work-package.mp4" + } %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 1cde08cab2e..8a9ae21477d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2058,6 +2058,12 @@ en: description: "Mark work packages as read-only for specific statuses." custom_field_hierarchies: description: "Hierarchy custom fields allow organizing hierarchical structures in work packages by making use of multi-level select lists." + date_alerts: + description: "With date alerts, you will be notified of upcoming start or finish dates so that you never miss or forget an important deadline." + work_package_sharing: + description: "Share work packages with users who are not members of the project." + + enumeration_activities: "Time tracking activities" enumeration_work_package_priorities: "Work package priorities" @@ -4671,26 +4677,26 @@ en: legacy_enterprise: "Enterprise Plan" enterprise_features: - baseline_comparison: Baseline Comparison - board_view: Board View + baseline_comparison: Baseline Comparisons + board_view: Advanced Boards conditional_highlighting: Conditional Highlighting custom_actions: Custom Actions - custom_field_hierarchies: Custom Field Hierarchies + custom_field_hierarchies: Custom fields of type hierarchy customize_life_cycle: Customize Life Cycle date_alerts: Date Alerts - define_custom_style: Define Custom Style + define_custom_style: Custom theme and logo edit_attribute_groups: Edit Attribute Groups gantt_pdf_export: Gantt PDF Export grid_widget_wp_graph: Grid Widget Work Package Graph - ldap_groups: LDAP Groups + ldap_groups: LDAP users and group sync one_drive_sharepoint_file_storage: OneDrive/SharePoint File Storage placeholder_users: Placeholder Users project_list_sharing: Project List Sharing readonly_work_packages: Readonly Work Packages - sso_auth_providers: SSO Auth Providers + sso_auth_providers: Single sign-on team_planner_view: Team Planner View - two_factor_authentication: Two-Factor Authentication - virus_scanning: Attachment Virus Scanning + two_factor_authentication: 2FA Authentication + virus_scanning: Antivirus scanning work_package_query_relation_columns: Work Package Query Relation Columns - work_package_sharing: Work Package Sharing + work_package_sharing: Share work packages with external users work_package_subject_generation: Work Package Subject Generation diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml index a388e002b9c..a94ad708f9c 100644 --- a/config/locales/js-en.yml +++ b/config/locales/js-en.yml @@ -685,9 +685,6 @@ en: property_is: "is in %{difference_in_days}." property_was: "was %{difference_in_days} ago." property_is_deleted: "is deleted." - upsale: - title: "Date alerts" - description: "With date alerts, you will be notified of upcoming start or finish dates so that you never miss or forget an important deadline." center: label_actor_and: "and" and_more_users: @@ -1127,8 +1124,6 @@ en: sharing: title: "Share work package" show_all_users: "Show all users with whom the work package has been shared with" - upsale: - description: "Share work packages with users who are not members of the project." table: configure_button: "Configure work package table" summary: "Table with rows of work package and columns of work package attributes." diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index edb81718b0f..78386494d49 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -160,10 +160,6 @@ import { import { WorkPackageSplitViewEntryComponent, } from 'core-app/features/work-packages/routing/wp-split-view/wp-split-view-entry.component'; -import { - InAppNotificationsDateAlertsUpsaleComponent, -} from 'core-app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component'; -import { ShareUpsaleComponent } from 'core-app/features/enterprise/share-upsale/share-upsale.component'; import { StorageLoginButtonComponent, } from 'core-app/shared/components/storages/storage-login-button/storage-login-button.component'; @@ -443,8 +439,6 @@ export class OpenProjectModule implements DoBootstrap { registerCustomElement('opce-notification-settings', NotificationsSettingsPageComponent, { injector }); registerCustomElement('opce-reminder-settings', ReminderSettingsPageComponent, { injector }); registerCustomElement('opce-notification-center', InAppNotificationCenterComponent, { injector }); - registerCustomElement('opce-ian-date-alerts-upsale', InAppNotificationsDateAlertsUpsaleComponent, { injector }); - registerCustomElement('opce-share-upsale', ShareUpsaleComponent, { injector }); registerCustomElement('opce-wp-split-view', WorkPackageSplitViewEntryComponent, { injector }); registerCustomElement('opce-timer-account-menu', TimerAccountMenuComponent, { injector }); registerCustomElement('opce-remote-field-updater', RemoteFieldUpdaterComponent, { injector }); diff --git a/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.html b/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.html deleted file mode 100644 index 34043d6e6f1..00000000000 --- a/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.html +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.ts b/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.ts deleted file mode 100644 index f850e6bbc13..00000000000 --- a/frontend/src/app/features/enterprise/share-upsale/share-upsale.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { I18nService } from 'core-app/core/i18n/i18n.service'; -import { videoPath } from 'core-app/shared/helpers/videos/path-helper'; - -@Component({ - selector: 'op-share-upsale', - templateUrl: './share-upsale.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ShareUpsaleComponent { - video = videoPath('sharing/share-work-package.mp4'); - - text = { - title: this.I18n.t('js.work_packages.sharing.title'), - description: this.I18n.t('js.work_packages.sharing.upsale.description'), - }; - - constructor( - readonly I18n:I18nService, - ) { } -} diff --git a/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.html b/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.html deleted file mode 100644 index 34043d6e6f1..00000000000 --- a/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.html +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.ts b/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.ts deleted file mode 100644 index 0275a1c03c5..00000000000 --- a/frontend/src/app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { I18nService } from 'core-app/core/i18n/i18n.service'; -import { videoPath } from 'core-app/shared/helpers/videos/path-helper'; - -@Component({ - selector: 'op-ian-date-alerts-upsale', - templateUrl: './ian-date-alerts-upsale.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class InAppNotificationsDateAlertsUpsaleComponent { - video = videoPath('notification-center/date-alert-notifications.mp4'); - - text = { - title: this.I18n.t('js.notifications.date_alerts.upsale.title'), - description: this.I18n.t('js.notifications.date_alerts.upsale.description'), - }; - - constructor( - readonly I18n:I18nService, - ) { } -} diff --git a/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts b/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts index d921e8f48c7..a37afc37245 100644 --- a/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts +++ b/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts @@ -9,9 +9,6 @@ import { InAppNotificationCenterComponent, } from 'core-app/features/in-app-notifications/center/in-app-notification-center.component'; import { IanCenterService } from 'core-app/features/in-app-notifications/center/state/ian-center.service'; -import { - InAppNotificationsDateAlertsUpsaleComponent, -} from 'core-app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component'; import { InAppNotificationEntryComponent, } from 'core-app/features/in-app-notifications/entry/in-app-notification-entry.component'; @@ -37,7 +34,6 @@ import { InAppNotificationStatusComponent } from './entry/status/in-app-notifica InAppNotificationStatusComponent, InAppNotificationActorsLineComponent, InAppNotificationDateAlertComponent, - InAppNotificationsDateAlertsUpsaleComponent, InAppNotificationRelativeTimeComponent, InAppNotificationReminderAlertComponent, ], diff --git a/frontend/src/app/features/work-packages/routing/work-packages-routes.ts b/frontend/src/app/features/work-packages/routing/work-packages-routes.ts index 1d32cd86c83..0b94fc7f0b5 100644 --- a/frontend/src/app/features/work-packages/routing/work-packages-routes.ts +++ b/frontend/src/app/features/work-packages/routing/work-packages-routes.ts @@ -37,7 +37,6 @@ import { WorkPackageViewPageComponent } from 'core-app/features/work-packages/ro import { makeSplitViewRoutes } from 'core-app/features/work-packages/routing/split-view-routes.template'; import { WorkPackageCopyFullViewComponent } from 'core-app/features/work-packages/components/wp-copy/wp-copy-full-view.component'; import { KeepTabService } from 'core-app/features/work-packages/components/wp-single-view-tabs/keep-tab/keep-tab.service'; -import { ShareUpsaleComponent } from 'core-app/features/enterprise/share-upsale/share-upsale.component'; export const menuItemClass = 'work-packages-menu-item'; export const sidemenuId = 'work_packages_sidemenu'; @@ -162,11 +161,6 @@ export const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [ menuItemClass, WorkPackageSplitViewComponent, ), - { - url: '/share_upsale', - name: 'work-packages.share_upsale', - component: ShareUpsaleComponent, - }, // Avoid lazy-loading the routes for now // { // name: 'work-packages.calendar.**', diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 07cbb80f2cc..08e6ec760ae 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -88,7 +88,6 @@ import { import { OpenprojectModalModule } from 'core-app/shared/components/modal/modal.module'; import { FullCalendarModule } from '@fullcalendar/angular'; import { OpDatePickerModule } from 'core-app/shared/components/datepicker/datepicker.module'; -import { ShareUpsaleComponent } from 'core-app/features/enterprise/share-upsale/share-upsale.component'; export function bootstrapModule(injector:Injector):void { // Ensure error reporter is run @@ -232,8 +231,6 @@ export function bootstrapModule(injector:Injector):void { OpLoadingProjectListComponent, OpNonWorkingDaysListComponent, - - ShareUpsaleComponent, ], }) export class OpSharedModule { diff --git a/frontend/src/global_styles/content/_enterprise.sass b/frontend/src/global_styles/content/_enterprise.sass index 04e10759e46..fb456195d23 100644 --- a/frontend/src/global_styles/content/_enterprise.sass +++ b/frontend/src/global_styles/content/_enterprise.sass @@ -55,6 +55,10 @@ .upsale-colored color: $spot-color-feedback-warning-dark +.upsale-colored-background + background: $spot-color-feedback-warning-dark !important + color: white !important + .upsale-border-colored border-color: $spot-color-feedback-warning-dark From 60dc69696592b5d1a8db32ce157c1a11f6150441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 25 Mar 2025 19:57:29 +0100 Subject: [PATCH 100/260] Remove enterprise page no longer in use --- .../enterprise-page.component.html | 51 ----------------- .../enterprise-page.component.ts | 55 ------------------- frontend/src/app/shared/shared.module.ts | 3 - 3 files changed, 109 deletions(-) delete mode 100644 frontend/src/app/shared/components/enterprise-page/enterprise-page.component.html delete mode 100644 frontend/src/app/shared/components/enterprise-page/enterprise-page.component.ts diff --git a/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.html b/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.html deleted file mode 100644 index 37870323435..00000000000 --- a/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.html +++ /dev/null @@ -1,51 +0,0 @@ -
-

-

{{feature_description}}

-

- {{text.benefits_description}} -
- {{text.premium_features_text}} -
- {{text.professional_support_text}} -

- -

- - - - - - -

-

{{text.upgrade_info}}

- - - {{ text.button_contact_us }} - - - - - {{ text.upgrade }} - - -
diff --git a/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.ts b/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.ts deleted file mode 100644 index d2313ffa800..00000000000 --- a/frontend/src/app/shared/components/enterprise-page/enterprise-page.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { ChangeDetectionStrategy, Component, ElementRef, Input } from '@angular/core'; -import { I18nService } from 'core-app/core/i18n/i18n.service'; -import { imagePath } from 'core-app/shared/helpers/images/path-helper'; -import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; -import { contactUrl, pricingUrl } from 'core-app/core/setup/globals/constants.const'; - - -@Component({ - selector: 'op-enterprise-page', - changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './enterprise-page.component.html', -}) -export class EnterprisePageComponent { - @Input() public feature_more_info:string; - - @Input() public feature_video:string; - - @Input() public feature_image:string; - - @Input() public feature_title:string; - - @Input() public feature_description:string; - - @Input() public more_info:string; - - @Input() public hide_breadcrumb = false; - - text = { - button_contact_us: this.I18n.t('js.admin.enterprise.upsale.button_contact_us'), - upgrade: this.I18n.t('js.admin.enterprise.upsale.button_upgrade'), - upgrade_link: pricingUrl, - contact_link: contactUrl.en, - benefits_description: this.I18n.t('js.admin.enterprise.upsale.benefits.description'), - premium_features_text: this.I18n.t('js.admin.enterprise.upsale.benefits.premium_features_text'), - professional_support_text: this.I18n.t('js.admin.enterprise.upsale.benefits.professional_support_text'), - enterprise_info_html: (feature_title:string):string => this.I18n.t('js.admin.enterprise.upsale.enterprise_info_html', { - feature_title, - }), - upgrade_info: this.I18n.t('js.admin.enterprise.upsale.upgrade_info'), - button_contact: this.I18n.t('js.admin.enterprise.upsale.buttons.contact'), - button_upgrade: this.I18n.t('js.admin.enterprise.upsale.buttons.upgrade'), - }; - - image = { - enterprise_edition: imagePath('enterprise-add-on.svg'), - }; - - constructor( - readonly elementRef:ElementRef, - protected I18n:I18nService, - readonly pathHelper:PathHelperService, - ) { - - } -} diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 08e6ec760ae..b4664769fa7 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -57,7 +57,6 @@ import { import { OPContextMenuComponent } from 'core-app/shared/components/op-context-menu/op-context-menu.component'; import { OpenprojectPrincipalRenderingModule } from 'core-app/shared/components/principal/principal-rendering.module'; import { FocusModule } from 'core-app/shared/directives/focus/focus.module'; -import { EnterprisePageComponent } from 'core-app/shared/components/enterprise-page/enterprise-page.component'; import { FreeTrialButtonComponent } from 'core-app/features/enterprise/free-trial-button/free-trial-button.component'; import { HomescreenNewFeaturesBlockComponent } from 'core-app/features/homescreen/blocks/new-features.component'; import { TablePaginationComponent } from 'core-app/shared/components/table-pagination/table-pagination.component'; @@ -174,7 +173,6 @@ export function bootstrapModule(injector:Injector):void { EditableToolbarTitleComponent, // Enterprise Edition - EnterprisePageComponent, FreeTrialButtonComponent, DynamicModule, @@ -220,7 +218,6 @@ export function bootstrapModule(injector:Injector):void { RemoteFieldUpdaterComponent, // Enterprise Edition - EnterprisePageComponent, FreeTrialButtonComponent, HomescreenNewFeaturesBlockComponent, From 549df0ad14bbacae9969b3088e361013125c1cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 26 Mar 2025 15:21:29 +0100 Subject: [PATCH 101/260] Use standard banner with custom colors --- .../banner_component.html.erb | 62 ++++++++++++------- .../enterprise_edition/banner_component.sass | 40 ++---------- .../free-trial-button.component.html | 2 +- .../global_styles/content/_enterprise.sass | 6 +- .../openproject/_variable_defaults.scss | 1 + 5 files changed, 49 insertions(+), 62 deletions(-) diff --git a/app/components/enterprise_edition/banner_component.html.erb b/app/components/enterprise_edition/banner_component.html.erb index 5123bca9211..7bc4c1f1399 100644 --- a/app/components/enterprise_edition/banner_component.html.erb +++ b/app/components/enterprise_edition/banner_component.html.erb @@ -1,29 +1,47 @@ <%= - grid_layout("op-ee-banner", **@system_arguments) do |grid| - grid.with_area(:"icon-container") do - content_tag :div, class: "op-ee-banner--shield" do - render( - Primer::Beta::Octicon.new( - icon: "op-enterprise-addons", - size: :medium, - classes: "op-ee-banner--icon" - ) - ) + render(Primer::Alpha::Banner.new( + classes: "op-enterprise-banner", + full: false, + icon: :"op-enterprise-addons", + mb: 2 + )) do + flex_layout do |flex| + flex.with_row do + render(Primer::Beta::Text.new(font_weight: :bold)) { title } end - end - grid.with_area(:"title-container") { render(Primer::Beta::Text.new) { title } } - grid.with_area(:"description-container") do - if features.present? - concat render(Primer::Beta::Text.new) { description } - concat content_tag(:ul) { safe_join features.map { |text| render(Primer::Beta::Text.new(tag: :li)) { text } } } - else + + flex.with_row(mt: 1) do render(Primer::Beta::Text.new) { description } end - end - grid.with_area(:"link-container") do - render(Primer::Beta::Link.new(href: href)) do |link| - link.with_trailing_visual_icon(icon: "link-external") - link_title + + if features.present? + flex.with_row do + content_tag(:ul) { safe_join features.map { |text| render(Primer::Beta::Text.new(tag: :li)) { text } } } + end + end + + flex.with_row(mt: 2, flex_layout: true, align_items: :center) do |buttons| + buttons.with_column do + helpers.angular_component_tag("opce-free-trial-button") + end + + buttons.with_column(ml: 1) do + render(Primer::Beta::Button.new( + tag: :a, + href: OpenProject::Static::Links.links[:pricing][:href], + target: "_blank", + classes: "upsale-colored-background", + title: t("admin.enterprise.buttons.upgrade"), + aria_label: t("admin.enterprise.buttons.upgrade"), + )) { t("admin.enterprise.buttons.upgrade") } + end + + buttons.with_column(ml: 1) do + render(Primer::Beta::Link.new(href:)) do |link| + link.with_trailing_visual_icon(icon: "link-external") + link_title + end + end end end end diff --git a/app/components/enterprise_edition/banner_component.sass b/app/components/enterprise_edition/banner_component.sass index 2d69234897d..c4ba4d8b311 100644 --- a/app/components/enterprise_edition/banner_component.sass +++ b/app/components/enterprise_edition/banner_component.sass @@ -28,41 +28,9 @@ / ++ / -$op-ee-banner--shield-width: 32px +.op-enterprise-banner + border-color: var(--borderColor-severe-muted) + background: white -// This is not named op-enterprise-banner because as of now, there is still a legacy angular component that uses that block name. -.op-ee-banner - display: grid - grid-template-columns: $op-ee-banner--shield-width auto auto - grid-template-areas: "icon-container title-container" "icon-container description-container" "icon-container link-container" - grid-column-gap: 0.5rem - justify-content: left - @media screen and (min-width: $breakpoint-md) - grid-template-areas: "icon-container title-container title-container" "icon-container description-container link-container" - - &--icon-container + .Banner-visual .octicon @extend .upsale-colored - align-self: start - justify-self: center - - &--shield - @extend .upsale-border-colored - width: $op-ee-banner--shield-width - height: 42px - border-width: 10px 5px 10px 5px - border-radius: 0 0 10px 10px - border-style: solid - display: flex - align-items: center - justify-content: center - - &--icon - width: $op-ee-banner--shield-width - height: $op-ee-banner--shield-width - - &--title-container - @extend .upsale-colored - font-weight: bold - - &--link-container - align-self: start diff --git a/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html b/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html index d6679b3cf5b..5342ba5ee8c 100644 --- a/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html +++ b/frontend/src/app/features/enterprise/free-trial-button/free-trial-button.component.html @@ -4,7 +4,7 @@