diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7ffa1dd391b..76c655fb3b4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -107,6 +107,11 @@ jobs: - name: Prepare docker files run: | cp ./docker/prod/Dockerfile ./Dockerfile + + # Add build information + echo "${{ steps.extract_version.outputs.checkout_ref }}" > PRODUCT_VERSION + echo "https://github.com/opf/openproject/commits/${{ steps.extract_version.outputs.checkout_ref }}" > PRODUCT_URL + date -u +"%Y-%m-%dT%H:%M:%SZ" > RELEASE_DATE - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx diff --git a/app/components/projects/configure_view_modal_component.html.erb b/app/components/projects/configure_view_modal_component.html.erb index 0e0bcb4f2d5..f91e00c9e8b 100644 --- a/app/components/projects/configure_view_modal_component.html.erb +++ b/app/components/projects/configure_view_modal_component.html.erb @@ -7,7 +7,7 @@ style: "min-height: 430px")) do |d| %> <% d.with_header(variant: :large, mb: 3) %> - <%= render(Primer::Alpha::Dialog::Body.new) do %> + <%= render(Primer::Alpha::Dialog::Body.new(id: "op-draggable-autocomplete-container")) do %> <%= primer_form_with( url: projects_path, id: COLUMN_FORM_ID, diff --git a/app/models/queries/work_packages/selects/property_select.rb b/app/models/queries/work_packages/selects/property_select.rb index 9b716ef8fd8..4a4ccead99d 100644 --- a/app/models/queries/work_packages/selects/property_select.rb +++ b/app/models/queries/work_packages/selects/property_select.rb @@ -123,8 +123,7 @@ class Queries::WorkPackages::Selects::PropertySelect < Queries::WorkPackages::Se }, done_ratio: { sortable: "#{WorkPackage.table_name}.done_ratio", - groupable: true, - if: ->(*) { !WorkPackage.done_ratio_disabled? } + groupable: true }, created_at: { sortable: "#{WorkPackage.table_name}.created_at", diff --git a/app/models/work_package.rb b/app/models/work_package.rb index d873070c3e9..6b6450db188 100644 --- a/app/models/work_package.rb +++ b/app/models/work_package.rb @@ -206,10 +206,6 @@ class WorkPackage < ApplicationRecord include WorkPackage::Journalized prepend Journable::Timestamps - def self.done_ratio_disabled? - Setting.work_package_done_ratio == "disabled" - end - def self.use_status_for_done_ratio? Setting.work_package_done_ratio == "status" end @@ -310,6 +306,11 @@ class WorkPackage < ApplicationRecord write_attribute :estimated_hours, !!converted_hours ? converted_hours : hours end + def remaining_hours=(hours) + converted_hours = (hours.is_a?(String) ? hours.to_hours : hours) + write_attribute :remaining_hours, !!converted_hours ? converted_hours : hours + end + def duration_in_hours duration ? duration * 24 : nil end diff --git a/app/services/work_packages/update_ancestors_service.rb b/app/services/work_packages/update_ancestors_service.rb index 7dd7a27bb05..0e058e285e5 100644 --- a/app/services/work_packages/update_ancestors_service.rb +++ b/app/services/work_packages/update_ancestors_service.rb @@ -116,17 +116,15 @@ class WorkPackages::UpdateAncestorsService end def derive_done_ratio(ancestor, loader) - return if WorkPackage.done_ratio_disabled? - ancestor.derived_done_ratio = compute_derived_done_ratio(ancestor, loader) end - def compute_derived_done_ratio(work_package, loader) + def compute_derived_done_ratio(work_package, _loader) return if work_package.derived_estimated_hours.nil? || work_package.derived_remaining_hours.nil? - leaves = loader.leaves_of(work_package) - - if leaves.size.positive? + if work_package.derived_estimated_hours.zero? + nil + else work_done = (work_package.derived_estimated_hours - work_package.derived_remaining_hours) progress = (work_done.to_f / work_package.derived_estimated_hours) * 100 progress.round @@ -153,22 +151,20 @@ class WorkPackages::UpdateAncestorsService def derive_total_estimated_and_remaining_hours(work_package, loader) descendants = loader.descendants_of(work_package) - work_package.derived_estimated_hours = not_zero(all_estimated_hours([work_package] + descendants).sum.to_f) - work_package.derived_remaining_hours = not_zero(all_remaining_hours([work_package] + descendants).sum.to_f) + work_package.derived_estimated_hours = total(all_estimated_hours([work_package] + descendants)) + work_package.derived_remaining_hours = total(all_remaining_hours([work_package] + descendants)) end - def not_zero(value) - value unless value.zero? + def total(hours) + hours.empty? ? nil : hours.sum.to_f end def all_estimated_hours(work_packages) - work_packages - .map(&:estimated_hours) - .reject { |hours| hours.to_f.zero? } + work_packages.filter_map(&:estimated_hours) end def all_remaining_hours(work_packages) - work_packages.map(&:remaining_hours).reject { |hours| hours.to_f.zero? } + work_packages.filter_map(&:remaining_hours) end def modified_attributes_justify_derivation?(attributes) diff --git a/app/views/work_package_mailer/_work_package_details.html.erb b/app/views/work_package_mailer/_work_package_details.html.erb index 213a6fa6b89..692e2f39bd3 100644 --- a/app/views/work_package_mailer/_work_package_details.html.erb +++ b/app/views/work_package_mailer/_work_package_details.html.erb @@ -40,10 +40,7 @@ See COPYRIGHT and LICENSE files for more details.
  • <%= WorkPackage.human_attribute_name(:start_date) %>: <%= work_package.start_date %>
  • <%= WorkPackage.human_attribute_name(:due_date) %>: <%= work_package.due_date %>
  • <%= WorkPackage.human_attribute_name(:estimated_hours)%>: <%= work_package.estimated_hours %>
  • - - <% if Setting.work_package_done_ratio != 'disabled' %> -
  • <%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %>
  • - <% end %> +
  • <%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %>
  • <% work_package.custom_field_values.each do |value| %>
  • <%= value.custom_field.name %>: <%= show_value(value) %>
  • diff --git a/app/views/work_package_mailer/_work_package_details.text.erb b/app/views/work_package_mailer/_work_package_details.text.erb index dea72fc98ff..2a64e9387d6 100644 --- a/app/views/work_package_mailer/_work_package_details.text.erb +++ b/app/views/work_package_mailer/_work_package_details.text.erb @@ -40,9 +40,7 @@ See COPYRIGHT and LICENSE files for more details. <%= WorkPackage.human_attribute_name(:start_date) %>: <%= work_package.start_date %> <%= WorkPackage.human_attribute_name(:due_date) %>: <%= work_package.due_date %> <%= WorkPackage.human_attribute_name(:estimated_hours)%>: <%= work_package.estimated_hours %> -<% if Setting.work_package_done_ratio != 'disabled' %> -<%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %> -<% end %> +<%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %> <% work_package.custom_field_values.each do |value| %> <%= value.custom_field.name %>: <%= show_value(value) %> <% end %> diff --git a/app/workers/work_packages/update_progress_job.rb b/app/workers/work_packages/update_progress_job.rb index 9aa0e1142ba..8565723c0c8 100644 --- a/app/workers/work_packages/update_progress_job.rb +++ b/app/workers/work_packages/update_progress_job.rb @@ -53,6 +53,8 @@ class WorkPackages::UpdateProgressJob < ApplicationJob update_totals + unset_total_p_complete + copy_progress_values_to_work_packages_and_update_journals end end @@ -211,6 +213,33 @@ class WorkPackages::UpdateProgressJob < ApplicationJob SQL end + # The value for derived_done_ratio had been calculated wrong in the past. So prior to executing the job + # values in the work_packages and work_package_journals table sometimes contained wrong data. + # The whole job/migration is now treating the derived_done_ratio as a value newly introduced even if it, under + # the hood has existed before. But it was not shown in the activites before so the user would not have seen it. + # + # Because of this, all values, in the work_packages and work_package_journals table, for derived_done_ratio are + # reset to null. + # + # This results in two cases: + # * The value before has been something (most of the time 0) and is now null. This will hopefully be the + # majority of the cases as it would save a lot of journal creation, the slowest part of the job. + # For that case, the derived_done_ratio will be treated as not having changed by the job since with the rewrite + # the value looks to have been null before and is now null again. + # * The value before has been something and is now something. It could have been the same value as before. But + # since the job resets the value to null, it will in every case be treated as having changed (set for the first time) + def unset_total_p_complete + execute(<<~SQL) + UPDATE work_packages + SET derived_done_ratio = NULL + SQL + + execute(<<~SQL) + UPDATE work_package_journals + SET derived_done_ratio = NULL + SQL + end + def copy_progress_values_to_work_packages_and_update_journals updated_work_package_ids = copy_progress_values_to_work_packages create_journals_for_updated_work_packages(updated_work_package_ids) diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml index 3e304467bd6..f3e5bea25e2 100644 --- a/config/locales/crowdin/af.yml +++ b/config/locales/crowdin/af.yml @@ -3411,9 +3411,7 @@ af: unsupported_context: "Die bron gegee word nie as konteks ondersteun nie." context_object_not_found: "Kan nie die hulpbron gegee as die konteks vind nie." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Die gekose gebruiker is nie toegelaat om '%{property}' vir hierdie werkspakket te wees nie." start_date: "Begindatum kan nie gestel word op ouerwerkspakkette nie." eprops: diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml index a52155aee67..53708c2bb47 100644 --- a/config/locales/crowdin/ar.yml +++ b/config/locales/crowdin/ar.yml @@ -3553,9 +3553,7 @@ ar: unsupported_context: "غير معتمد المورد نظراً للسياق." context_object_not_found: "تعذر العثور على المورد نظراً للسياق." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "غير مسموح للمستخدم الذي تم اختياره أن يكون '%{property}' لمجموعة العمل هذه." start_date: "الوقت لإتمام المشروع لا يمكن تعيينه في حزم العمل الحالية." eprops: diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml index 91443096035..b710e6b9cd1 100644 --- a/config/locales/crowdin/az.yml +++ b/config/locales/crowdin/az.yml @@ -3411,9 +3411,7 @@ az: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml index 6493a40bc62..e282853909c 100644 --- a/config/locales/crowdin/be.yml +++ b/config/locales/crowdin/be.yml @@ -3483,9 +3483,7 @@ be: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index f4645cd10c1..9dbc449e126 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -3411,9 +3411,7 @@ bg: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index 3ed05c7721f..250350271c9 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -3400,9 +3400,7 @@ ca: unsupported_context: "El recurs proporcionat no s'admet com a context." context_object_not_found: "No puc trobar el recurs proporionat com al context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "La data de finalització no es pot establir als paquets de treball pare." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "L'usuari escollit no pot ser \"%{property}\" per a aquest paquet de treball." start_date: "La data d'inici no es pot definir per paquets de treball del pare." eprops: diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml index bc3310d597b..3d76e48a343 100644 --- a/config/locales/crowdin/ckb-IR.yml +++ b/config/locales/crowdin/ckb-IR.yml @@ -3411,9 +3411,7 @@ ckb-IR: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index 8b16f7e43de..9aa4d7a25dc 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -3481,9 +3481,7 @@ cs: unsupported_context: "Zadaný dokument není podporován jako kontext." context_object_not_found: "Zdroj nelze najít jako kontext." validation: - done_ratio: "% Průběh nelze nastavit na nadřazených pracovních balíčcích, je odvozen ze stavu podřazených nebo pokud je zakázán." due_date: "Datum ukončení nemůže být nastaveno na nadřazených pracovních balíčcích." - estimated_hours: "Práci nelze nastavit na nadřazených pracovních balíčcích." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Zvolený uživatel nesmí být '%{property}' pro tento pracovní balíček." start_date: "Počáteční datum nelze nastavit na nadřazených pracovních balíčcích." eprops: diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml index d1137089cc5..5d924b70b00 100644 --- a/config/locales/crowdin/da.yml +++ b/config/locales/crowdin/da.yml @@ -3407,9 +3407,7 @@ da: unsupported_context: "Den givne ressource understøttes ikke som korrekt sammenhæng." context_object_not_found: "Kan ikke finde ressourcen, der ar angivet som sammenhæng." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Den valgte bruger er ikke tilladt at være '%{property}' for denne arbejdspakke." start_date: "Startdato kan ikke angives for overordnede arbejdspakker." eprops: diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index b24cc6015f5..91038711050 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -3405,9 +3405,7 @@ de: unsupported_context: "Die übergebene Ressource wird nicht als Kontext unterstützt." context_object_not_found: "Die als Kontext übergebene Ressource konnte nicht gefunden werden." validation: - done_ratio: "Der Fortschritt kann nicht gesetzt werden falls es sich um ein Eltern-Arbeitspaket handelt, er durch den Status definiert wird oder wenn er komplett deaktiviert wurde." due_date: "Der Endtermin kann für Eltern-Arbeitspakete nicht gesetzt werden." - estimated_hours: "Aufwand kann nicht für übergeordnete Arbeitspakete gesetzt werden." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Der gewählte Nutzer darf dem Arbeitspaket nicht als '%{property}' zugewiesen werden." start_date: "Das Startdatum kann für Eltern-Arbeitspakete nicht gesetzt werden." eprops: diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml index bc296a17fb9..a1b3b7b7c22 100644 --- a/config/locales/crowdin/el.yml +++ b/config/locales/crowdin/el.yml @@ -3405,9 +3405,7 @@ el: unsupported_context: "Ο πόρος που δόθηκε δεν υποστηρίζεται ως πλαίσιο αναφοράς." context_object_not_found: "Δεν ήταν δυνατή η εύρεση του πόρου που δόθηκε ως πλαίσιο αναφοράς." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Η ημερομηνία λήξης δεν μπορεί να οριστεί σε πακέτα εργασίας-γονείς." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Ο επιλεγμένος χρήστης δεν επιτρέπεται να είναι '%{property}' για αυτό το πακέτο εργασίας." start_date: "Η ημερομηνία έναρξης δεν μπορεί να οριστεί σε πακέτα εργασίας-γονείς." eprops: diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml index 1733cd743dc..bb3c4934e4b 100644 --- a/config/locales/crowdin/eo.yml +++ b/config/locales/crowdin/eo.yml @@ -3411,9 +3411,7 @@ eo: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml index 30794ea6b1a..99486363acf 100644 --- a/config/locales/crowdin/es.yml +++ b/config/locales/crowdin/es.yml @@ -3406,9 +3406,7 @@ es: unsupported_context: "El recurso dado no es soportado como contexto." context_object_not_found: "No se ha podido encontrar el recurso dado como el contexto." validation: - done_ratio: "% Completado no puede establecerse en paquetes de trabajo padres, cuando es influenciado por estado o cuando está desactivado." due_date: "La fecha de finalización no se puede establecer en los paquetes de trabajo principales." - estimated_hours: "El trabajo no puede establecerse en paquetes de trabajo padres." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "El usuario elegido no tiene permiso para ser '%{property}' para este paquete de trabajo." start_date: "La fecha de inicio no puede ser establecida en paquetes de trabajo padres." eprops: diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml index 0ca6c2e9164..29e9ddd8d3b 100644 --- a/config/locales/crowdin/et.yml +++ b/config/locales/crowdin/et.yml @@ -3411,9 +3411,7 @@ et: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml index d899db6d59a..b5ce6fd5346 100644 --- a/config/locales/crowdin/eu.yml +++ b/config/locales/crowdin/eu.yml @@ -3411,9 +3411,7 @@ eu: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml index a5ff10fcbcf..1e19188eb9d 100644 --- a/config/locales/crowdin/fa.yml +++ b/config/locales/crowdin/fa.yml @@ -3411,9 +3411,7 @@ fa: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml index 82c9b592272..d817fa6e58d 100644 --- a/config/locales/crowdin/fi.yml +++ b/config/locales/crowdin/fi.yml @@ -3411,9 +3411,7 @@ fi: unsupported_context: "Resurssi koska ei ole tuettu yhteydessä." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Päättymispäivää ei voida asettaa ylätason tehtäville." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Aloituspäivää ei voi asettaa ylätehtäville." eprops: diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml index 2b78dafbc50..e441e05ecf5 100644 --- a/config/locales/crowdin/fil.yml +++ b/config/locales/crowdin/fil.yml @@ -3409,9 +3409,7 @@ fil: unsupported_context: "Ang ibinigay na mapagkukunan ay hindi suportado bilang isang konteksto." context_object_not_found: "Hindi mahanap ang ibinigay na mapagkukunan bilang konteksto." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Ang piniling gumagamit ay hindi pinahihintulan sa '%{property}' na para sa package ng gawain ng magulang." start_date: "Sinimulang petsa ay hindi mai-set sa mga pakete ng gawain ng magulang." eprops: diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index 9439286828b..aeec3dae070 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -3410,9 +3410,7 @@ fr: unsupported_context: "La ressource donnée n'est pas prise en charge comme contexte." context_object_not_found: "Impossible de trouver la ressource donnée comme contexte." validation: - done_ratio: "Le % réalisé ne peut pas être défini sur les lots de travaux parents, lorsqu'il est déduit par le statut ou lorsqu'il est désactivé." due_date: "La date de fin ne peut pas être définie dans les lots de travaux parents." - estimated_hours: "La valeur \"travail\" ne peut pas être définie pour les paquets de travail parents." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "L’utilisateur choisi n'est pas autorisé à être « %{property} » pour ce lot de travaux." start_date: "La date de début ne peut pas être définie dans les lots de travaux parents." eprops: diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml index 1ca05ae4cd0..417a6dc37ec 100644 --- a/config/locales/crowdin/he.yml +++ b/config/locales/crowdin/he.yml @@ -3483,9 +3483,7 @@ he: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "לא ניתן לבחור '%{property}' עבור המשתמש בחבילת עבודה זו." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml index cac1b7f5c88..c07e634c276 100644 --- a/config/locales/crowdin/hi.yml +++ b/config/locales/crowdin/hi.yml @@ -3409,9 +3409,7 @@ hi: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml index 934ffb1f1cd..26c2c648936 100644 --- a/config/locales/crowdin/hr.yml +++ b/config/locales/crowdin/hr.yml @@ -3447,9 +3447,7 @@ hr: unsupported_context: "Dani resurs nije podržan u obliku konteksta." context_object_not_found: "Ne mogu pronaći resurs zadan kao kontekst." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Izabranom korisniku nije dopušteno da bude '%{property}' za ovaj radni paket." start_date: "Datum početka ne može biti postavljen na nadređenim radnim paketima." eprops: diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml index 477fd181afd..ce3b38d7d10 100644 --- a/config/locales/crowdin/hu.yml +++ b/config/locales/crowdin/hu.yml @@ -3407,9 +3407,7 @@ hu: unsupported_context: "A megadott erőforrás nem támogatott kontextus." context_object_not_found: "Nem található a kontextusként megadott erőforrás." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Befejezési dátumot nem lehet beállítani a szülő feladatcsoportnak." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "A kiválasztott felhasználó '%{property}'-ként való beállítása nem engedélyezett ehhez a feladatcsoporthoz." start_date: "Kezdés dátuma nem állítható a szülő feladatcsoportokon." eprops: diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml index a50786d650d..554fa1b9f16 100644 --- a/config/locales/crowdin/id.yml +++ b/config/locales/crowdin/id.yml @@ -3364,9 +3364,7 @@ id: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Tanggal selesai tidak dapat diatur pada paket pekerjaan induk." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Pilihan pengguna tidak diperbolehkan untuk menjadi '%{property}' untuk paket pekerjaan ini." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml index 893cd68e87b..224b58cee89 100644 --- a/config/locales/crowdin/it.yml +++ b/config/locales/crowdin/it.yml @@ -3408,9 +3408,7 @@ it: unsupported_context: "La risorsa non è supportata come contesto." context_object_not_found: "Impossibile trovare la risorsa indicata come contesto." validation: - done_ratio: "La % completamento non può essere impostata sulla macro-attività principale, quando viene dedotta dallo stato o quando è disabilitata." due_date: "La data di fine non può essere impostata sulla macro-attività principale." - estimated_hours: "Il lavoro non può essere impostato sulla macro-attività principale." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "All'utente scelto non è consentito di essere '%{property}' per questa macro-attività." start_date: "La data di inizio non può essere impostata sulla macro-attività principale." eprops: diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml index 5dc551b6464..6a5119c9424 100644 --- a/config/locales/crowdin/ja.yml +++ b/config/locales/crowdin/ja.yml @@ -3370,9 +3370,7 @@ ja: unsupported_context: "指定されたリソースは、コンテキストとしてはサポートされません。" context_object_not_found: "コンテキストで指定されたリソースが見つかりません。" validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "終了日は親作業項目には設定できません。" - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "選択されたユーザーは、この作業項目の'%{property}' にすることはできません。" start_date: "開始日は、親ワークパッケージに設定できません。" eprops: diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml index 669ac06e2a8..fa9eeafba0d 100644 --- a/config/locales/crowdin/ka.yml +++ b/config/locales/crowdin/ka.yml @@ -3411,9 +3411,7 @@ ka: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml index 96772d227e6..90c03a0518e 100644 --- a/config/locales/crowdin/kk.yml +++ b/config/locales/crowdin/kk.yml @@ -3411,9 +3411,7 @@ kk: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml index 5cb23dd2032..25fe2d5a29a 100644 --- a/config/locales/crowdin/ko.yml +++ b/config/locales/crowdin/ko.yml @@ -3371,9 +3371,7 @@ ko: unsupported_context: "지정된 리소스는 컨텍스트로 지원되지 않습니다." context_object_not_found: "컨텍스트로 지정된 리소스를 찾을 수 없습니다." validation: - done_ratio: "완료 %는 상태에 의해 유추되는 경우 또는 비활성화된 경우 부모 작업 패키지에서 설정할 수 없습니다." due_date: "완료 날짜는 부모 작업 패키지에서 설정할 수 없습니다." - estimated_hours: "작업은 부모 작업 패키지에서 설정할 수 없습니다." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "선택한 사용자는 이 작업 패키지에 대해 '%{property}' 허가되지 않았습니다." start_date: "시작 날짜는 부모 작업 패키지에서 설정할 수 없습니다." eprops: diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 6afd758cbaa..e3ed074f7ea 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -3475,9 +3475,7 @@ lt: unsupported_context: "Duotas resursas nėra palaikomas kaip kontekstas." context_object_not_found: "Nepavyko rasti resurso, duoto kaip kontekstas." validation: - done_ratio: "% baigta negali būti nurodytas tėviniams darbų paketams, kai paketas apibrėžtas pagal būseną arba kai jis deaktyvuotas." due_date: "Tėviniams darbo paketams negalima nurodyti pabaigos datos." - estimated_hours: "Darbo negalima nustatyti tėviniams darbo paketams." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Pasirinktas vartotojas negali būti '%{property}' šiam darbų paketui." start_date: "Pradžios data negali būti nustatyta tėviniams darbų paketams." eprops: diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml index dc090798e74..3233b1192c6 100644 --- a/config/locales/crowdin/lv.yml +++ b/config/locales/crowdin/lv.yml @@ -3447,9 +3447,7 @@ lv: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml index 1e55c03d3bd..5708087a3c0 100644 --- a/config/locales/crowdin/mn.yml +++ b/config/locales/crowdin/mn.yml @@ -3411,9 +3411,7 @@ mn: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml index 013a45b4313..3b193b7b9b1 100644 --- a/config/locales/crowdin/ms.yml +++ b/config/locales/crowdin/ms.yml @@ -3374,9 +3374,7 @@ ms: unsupported_context: "Sumber yang diberi tidak disokong sebagai konteks." context_object_not_found: "Tidak dapat mencari sumber yang diberikan sebagai konteks." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Tarikh tamat tidak boleh ditetapkan pada pakej kerja induk." - estimated_hours: "Kerja tidak boleh ditetapkan pada pakej kerja induk." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Pengguna yang dipilih tidak dibenarkan untuk menjadi '%{property}' untuk pakej kerja ini." start_date: "Tarikh mula tidak boleh ditetapkan pada pakej kerja induk." eprops: diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml index f08451552fa..06c6f63cc38 100644 --- a/config/locales/crowdin/ne.yml +++ b/config/locales/crowdin/ne.yml @@ -3411,9 +3411,7 @@ ne: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 75d24afe426..68fdf26366f 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -3406,9 +3406,7 @@ nl: unsupported_context: "De gegeven bron wordt niet ondersteund als context." context_object_not_found: "Kan de bron niet vind als gegeven context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Einddatum kan niet worden ingesteld op bovenliggende werkpakketten." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "De gekozen gebruiker kan geen '%{property}' zijn voor dit werkpakket." start_date: "De startdatum kan niet worden ingesteld op bovenliggende werkpakketten." eprops: diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml index 0b828e9021a..9f7fa66ef02 100644 --- a/config/locales/crowdin/no.yml +++ b/config/locales/crowdin/no.yml @@ -3411,9 +3411,7 @@ unsupported_context: "Ressursen som er gitt støttes ikke som kontekst." context_object_not_found: "Kan ikke finne ressursen som er angitt som kontekst." validation: - done_ratio: "% ferdig kan ikke angis på overordnede arbeidspakker, de har feil status eller er avslått." due_date: "Sluttdato kan ikke settes på overordnede arbeidspakker." - estimated_hours: "Arbeidet kan ikke angis med overordnede arbeidspakker." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Valgt bruker har ikke de nødvendige rettighetene til å være '%{property}' for denne arbeidspakken." start_date: "Startdato kan ikke angis på overordnede arbeidspakker." eprops: diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml index 4be28561bb8..d9b5f06ae00 100644 --- a/config/locales/crowdin/pl.yml +++ b/config/locales/crowdin/pl.yml @@ -3477,9 +3477,7 @@ pl: unsupported_context: "Podany zasób nie jest obsługiwany jako kontekst." context_object_not_found: "Nie można odnaleźć zasobu z podanym kontekstem." validation: - done_ratio: "% ukończenia nie może być ustawiony na nadrzędnych pakietach roboczych, jeśli został wyprowadzony ze statusu lub wyłączony." due_date: "Nie można ustawić daty zakończenia w nadrzędnych pakietach roboczych." - estimated_hours: "Pracy nie można ustawić na nadrzędnych pakietach roboczych." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Wybrany użytkownik nie może być „%{property}” dla tego pakietu roboczego." start_date: "Daty rozpoczęcia nie można ustawić na nadrzędnych pakietach roboczych." eprops: diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml index c8ea1ff28f3..6d5fa92ae01 100644 --- a/config/locales/crowdin/pt-BR.yml +++ b/config/locales/crowdin/pt-BR.yml @@ -3407,9 +3407,7 @@ pt-BR: unsupported_context: "O recurso dado não está suportado como contexto." context_object_not_found: "Não é possível encontrar o recurso dado como contexto." validation: - done_ratio: "A % de conclusão não pode ser definida em pacotes de trabalho pais quando é inferida pelo estado ou quando está desabilitada." due_date: "Data de conclusão não pode ser definida em pacote de trabalho pai." - estimated_hours: "O trabalho não pode ser definido em pacotes de trabalho pais." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "O usuário selecionado não tem permissão de '%{property}' neste pacote de trabalho." start_date: "Data de início não pode ser definida no pacote de trabalho pai." eprops: diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml index 9ae0984ad71..ba2a89cd9cc 100644 --- a/config/locales/crowdin/pt-PT.yml +++ b/config/locales/crowdin/pt-PT.yml @@ -3406,9 +3406,7 @@ pt-PT: unsupported_context: "Não há suporte para o recurso dado como contexto." context_object_not_found: "Não é possível encontrar o recurso dado como contexto." validation: - done_ratio: "A % de conclusão não pode ser definida em pacotes de trabalho parentes quando é inferida pelo estado ou quando está desativada." due_date: "Data de término não pode ser definida em pacotes de trabalho pai." - estimated_hours: "O trabalho não pode ser definido em tarefas principais." #feel like this one should be removed eventually 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." eprops: diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index d6a394072ed..dec3e123476 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -3446,9 +3446,7 @@ ro: unsupported_context: "Resursa furnizată nu este suportată ca și context." context_object_not_found: "Resursa furnizată ca și contet nu poate fi identificată." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Data de finalizare nu poate fi stabilită pentru pachetele de lucru părinte." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Utilizatorul selectat nu poate fi '%{property}' pentru acest pachet de lucru." start_date: "Nu se poate seta data start pe pachetele de lucru părinte." eprops: diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml index 40c80b331c5..0b622471cf4 100644 --- a/config/locales/crowdin/ru.yml +++ b/config/locales/crowdin/ru.yml @@ -3478,9 +3478,7 @@ ru: unsupported_context: "Ресурс не поддерживается как контекст." context_object_not_found: "Не удается найти ресурс заданный как контекст." validation: - done_ratio: "% законченный не может быть установлен в родительских пакетах работ, когда он устанавливается по статусу или когда он отключен." due_date: "Дату окончания нельзя задать на родительских пакетах работ." - estimated_hours: "Предполагаемое количество часов не может быть задано для родительских пакетов." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Выбранный пользователь не может быть «%{property}» для этого пакета работ." start_date: "Дата начала не может быть задана на родительских пакетах работ." eprops: diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml index 2b06d5ff32b..9b3fa691969 100644 --- a/config/locales/crowdin/rw.yml +++ b/config/locales/crowdin/rw.yml @@ -3411,9 +3411,7 @@ rw: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml index ae1775a5f2e..1dae7a3f6d1 100644 --- a/config/locales/crowdin/si.yml +++ b/config/locales/crowdin/si.yml @@ -3411,9 +3411,7 @@ si: unsupported_context: "ලබා දී ඇති සම්පත සන්දර්භය ලෙස සහාය නොදක්වයි." context_object_not_found: "සන්දර්භය ලෙස ලබා දී ඇති සම්පත සොයාගත නොහැක." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "අවසන් දිනය මව් වැඩ පැකේජ මත සැකසිය නොහැක." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "තෝරාගත් පරිශීලකයාට මෙම වැඩ පැකේජය සඳහා '%{property}' වීමට අවසර නැත." start_date: "ආරම්භක දිනය මව් වැඩ පැකේජ මත සැකසිය නොහැක." eprops: diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml index c141893801c..2c636165d5b 100644 --- a/config/locales/crowdin/sk.yml +++ b/config/locales/crowdin/sk.yml @@ -3482,9 +3482,7 @@ sk: unsupported_context: "Zadaný prostriedok nie je podporovaný ako kontext." context_object_not_found: "Pre vložené vstupné podmienky neboli nájdené žiadne prostriedky." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Dátum ukončenia nie je možné nastaviť na rodičovské pracovné balíčky." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Zvolený používateľ nemôže byť \"%{property}\" v prípade tohto pracovného balíčka." start_date: "Dátum \"Od\" nie je možné nastaviť na pracovnom balíčku obsahujúcom podriadené pracovné balíčky." eprops: diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml index f9f6c4dafef..891378dd41d 100644 --- a/config/locales/crowdin/sl.yml +++ b/config/locales/crowdin/sl.yml @@ -3479,9 +3479,7 @@ sl: unsupported_context: "Navedeni vir ni podprt kot kontekst." context_object_not_found: "Ni mogoče najti vira kot konteksta." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Končnega datuma ni mogoče določiti za nadrejene delovne pakete." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Izbrani uporabnik ne sme biti '%{property}' za ta delovni paket." start_date: "Na nadrejenih delovnih paketih začetnega datuma ni mogoče nastaviti." eprops: diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml index 8ad02b27c10..4be7d572218 100644 --- a/config/locales/crowdin/sr.yml +++ b/config/locales/crowdin/sr.yml @@ -3447,9 +3447,7 @@ sr: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml index 312fcf1bb03..b42f558f15e 100644 --- a/config/locales/crowdin/sv.yml +++ b/config/locales/crowdin/sv.yml @@ -3407,9 +3407,7 @@ sv: unsupported_context: "Resursen som angavs stöds inte som kontext." context_object_not_found: "Kan inte hitta den angivna resursen som kontext." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Slutdatum kan inte anges på överordnade arbetspaket." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Den valda användaren tillåts inte att vara \"%{property}\" för detta arbetspaket." start_date: "Startdatum kan inte anges för överordnade arbetspaket." eprops: diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml index 2a8231f0848..84e74d513d5 100644 --- a/config/locales/crowdin/th.yml +++ b/config/locales/crowdin/th.yml @@ -3375,9 +3375,7 @@ th: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml index 0649a3a7028..8c0177633c4 100644 --- a/config/locales/crowdin/tr.yml +++ b/config/locales/crowdin/tr.yml @@ -3406,9 +3406,7 @@ tr: unsupported_context: "Verilen kaynak bağlam olarak desteklenmiyor." context_object_not_found: "Bağlam olarak verilen kaynağı bulamıyor." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Bitiş ​​tarihi, üst çalışma paketlerinde ayarlanamaz." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Seçilen kullanıcının bu çalışma paketi için ' %{property} ' olması için izin verilmiyor." start_date: "Başlangıç ​​tarihi, üst çalışma paketlerinde ayarlanamaz." eprops: diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml index bc49f7c5316..024d6813a3c 100644 --- a/config/locales/crowdin/uk.yml +++ b/config/locales/crowdin/uk.yml @@ -3474,9 +3474,7 @@ uk: unsupported_context: "Даний ресурс не підтримується як контекст." context_object_not_found: "Не можу знайти ресурс з урахуванням контексту." validation: - done_ratio: "Значення «% завершення» не можна встановити для батьківських пакетів робіт, коли воно успадковується за статусом або коли його вимкнено." due_date: "Дата закінчення не може бути встановлена на початкових робочих пакетах." - estimated_hours: "Значення «Робота» не можна встановити для батьківських пакетів робіт." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "Вибраному користувачеві не дозволяється %{property} для цього робочого пакету." start_date: "Дата початку не може бути встановлена на базових робочих пакетах." eprops: diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml index 0d5d2653583..a8ce16d05f7 100644 --- a/config/locales/crowdin/uz.yml +++ b/config/locales/crowdin/uz.yml @@ -3411,9 +3411,7 @@ uz: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml index 3afe6ea0352..08973e96c97 100644 --- a/config/locales/crowdin/vi.yml +++ b/config/locales/crowdin/vi.yml @@ -3376,9 +3376,7 @@ vi: unsupported_context: "The resource given is not supported as context." context_object_not_found: "Cannot find the resource given as the context." validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "Finish date cannot be set on parent work packages." - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "The chosen user is not allowed to be '%{property}' for this work package." start_date: "Start date cannot be set on parent work packages." eprops: diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml index 0dd1cba8a38..1a7ad4408e4 100644 --- a/config/locales/crowdin/zh-CN.yml +++ b/config/locales/crowdin/zh-CN.yml @@ -3364,9 +3364,7 @@ zh-CN: unsupported_context: "所提供的资源不被上下文环境所支持。" context_object_not_found: "找不到可作为上下文环境的资源。" validation: - done_ratio: "无法在父级工作包上设置 % 已完成,当其由状态推导或被禁用时。" due_date: "不能在父工作包中设置完成日期。" - estimated_hours: "不能在父工作包中设置工作。" #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "所选的用户不允许为此工作包的 '%{property}'。" start_date: "不能在父工作包中设置开始日期。" eprops: diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 4c8f2048c82..f9dd359e031 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -3373,9 +3373,7 @@ zh-TW: unsupported_context: "所提供的資源不受相對應支援。" context_object_not_found: "Cannot find the resource given with the context.\n無法找到本文對應的資源。" validation: - done_ratio: "% Complete cannot be set on parent work packages, when it is inferred by status or when it is disabled." due_date: "無法在主工作項目上設置結束日期。" - estimated_hours: "Work cannot be set on parent work packages." #feel like this one should be removed eventually invalid_user_assigned_to_work_package: "所指定的使用者不允許成為工作項目的 '%{property}' 。" start_date: "無法在主工作項目設置開始日期。" eprops: diff --git a/config/locales/en.yml b/config/locales/en.yml index 92b0e652cd6..b7997a6506e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3668,9 +3668,7 @@ Project attributes and sections are defined in the } */ public async create( - wrapper:HTMLElement, context:ICKEditorContext, + wrapper:HTMLElement, + context:ICKEditorContext, initialData:string|null = null, ):Promise { // Load the bundle and the matching locale, if found. @@ -62,6 +64,7 @@ export class CKEditorSetupService { const config = { openProject: this.createConfig(context), + removePlugins: context.removePlugins, initialData, language: { ui: uiLocale, @@ -144,4 +147,31 @@ export class CKEditorSetupService { pluginContext: window.OpenProject.pluginContext.value, }; } + + private watchTopLayer() { + const targetClassNames = ['ck-body-wrapper', 'ck-inspector-']; + + const observer = new MutationObserver((mutations) => { + const dialog = document.querySelector('dialog[open]'); + if (!dialog) { + return; + } + + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (!(node instanceof HTMLElement)) { + return; + } + + if (targetClassNames.some((className) => node.classList.contains(className))) { + dialog.append(node); + } + }); + }); + }); + + observer.observe(document.body, { + childList: true, + }); + } } diff --git a/frontend/src/app/shared/components/op-context-menu/op-context-menu.service.ts b/frontend/src/app/shared/components/op-context-menu/op-context-menu.service.ts index 2ed8f9ab325..068dbe75f97 100644 --- a/frontend/src/app/shared/components/op-context-menu/op-context-menu.service.ts +++ b/frontend/src/app/shared/components/op-context-menu/op-context-menu.service.ts @@ -71,7 +71,7 @@ export class OPContextMenuService { if (that.active && !that.portalHostElement.contains(evt.target as Element)) { that.close(); } - }, true); + }); // Listen if it scrolles then close the active context menu wrapper.addEventListener('scroll', (evt:Event) => { if (that.active && !that.portalHostElement.contains(evt.target as Element)) { diff --git a/lib/api/v3/work_packages/schema/work_package_schema_representer.rb b/lib/api/v3/work_packages/schema/work_package_schema_representer.rb index 45b87641ed7..67f7202d26f 100644 --- a/lib/api/v3/work_packages/schema/work_package_schema_representer.rb +++ b/lib/api/v3/work_packages/schema/work_package_schema_representer.rb @@ -188,13 +188,11 @@ module API schema :percentage_done, type: "Integer", name_source: :done_ratio, - show_if: ->(*) { Setting.work_package_done_ratio != "disabled" }, required: false schema :derived_percentage_done, type: "Integer", name_source: :derived_done_ratio, - show_if: ->(*) { Setting.work_package_done_ratio != "disabled" }, required: false schema :readonly, diff --git a/lib/api/v3/work_packages/work_package_representer.rb b/lib/api/v3/work_packages/work_package_representer.rb index 3f2adbd163a..eaffde1acf8 100644 --- a/lib/api/v3/work_packages/work_package_representer.rb +++ b/lib/api/v3/work_packages/work_package_representer.rb @@ -444,13 +444,11 @@ module API property :done_ratio, as: :percentageDone, - render_nil: true, - if: ->(*) { Setting.work_package_done_ratio != "disabled" } + render_nil: true property :derived_done_ratio, as: :derivedPercentageDone, - render_nil: true, - if: ->(*) { Setting.work_package_done_ratio != "disabled" } + render_nil: true date_time_property :created_at diff --git a/lib/open_project/text_formatting/filters/link_attribute_filter.rb b/lib/open_project/text_formatting/filters/link_attribute_filter.rb index 451a51446ae..e8e9a5a2139 100644 --- a/lib/open_project/text_formatting/filters/link_attribute_filter.rb +++ b/lib/open_project/text_formatting/filters/link_attribute_filter.rb @@ -31,6 +31,8 @@ module OpenProject::TextFormatting class LinkAttributeFilter < HTML::Pipeline::Filter def call links.each do |node| + next if node["target"] || node["href"]&.start_with?("#") + node["target"] = context.fetch(:target, "_top") end @@ -38,7 +40,7 @@ module OpenProject::TextFormatting end def links - doc.css('a[href^="/"]') + doc.css("a") end end end diff --git a/lib/primer/open_project/forms/rich_text_area.html.erb b/lib/primer/open_project/forms/rich_text_area.html.erb index a7b9357ff79..92851cac8a8 100644 --- a/lib/primer/open_project/forms/rich_text_area.html.erb +++ b/lib/primer/open_project/forms/rich_text_area.html.erb @@ -6,7 +6,8 @@ inputs: @rich_text_options.reverse_merge( { textareaSelector: "##{builder.field_id(@input.name)}", - macros: 'resource', + removePlugins: ["CodeBlock"], + macros: false, turboMode: true } ) diff --git a/modules/costs/lib/api/v3/time_entries/time_entries_activity_representer.rb b/modules/costs/lib/api/v3/time_entries/time_entries_activity_representer.rb index 9a90c9aaf47..07f7df63f36 100644 --- a/modules/costs/lib/api/v3/time_entries/time_entries_activity_representer.rb +++ b/modules/costs/lib/api/v3/time_entries/time_entries_activity_representer.rb @@ -53,6 +53,8 @@ module API end }, getter: ->(*) { + next unless embed_links + active_projects.map do |project| Projects::ProjectRepresenter.create(project, current_user:) end diff --git a/modules/dashboards/spec/features/project_details_spec.rb b/modules/dashboards/spec/features/project_details_spec.rb index 19bfa250675..ea283e9a9d6 100644 --- a/modules/dashboards/spec/features/project_details_spec.rb +++ b/modules/dashboards/spec/features/project_details_spec.rb @@ -141,8 +141,6 @@ RSpec.describe "Project details widget on dashboard", :js do it 'has a "Project activity" entry in More menu linking to the project activity page' do details_widget = Components::Grids::GridArea.new(".grid--area.-widgeted:nth-of-type(1)") - details_widget.expect_menu_item("Project details activity") - details_widget.click_menu_item("Project details activity") expect(page).to have_current_path(project_activity_index_path(project), ignore_query: true) expect(page).to have_checked_field(id: "event_types_project_attributes") diff --git a/modules/meeting/spec/features/structured_meetings/turbo_links_spec.rb b/modules/meeting/spec/features/structured_meetings/turbo_links_spec.rb new file mode 100644 index 00000000000..f5a3bfe7217 --- /dev/null +++ b/modules/meeting/spec/features/structured_meetings/turbo_links_spec.rb @@ -0,0 +1,71 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +require_relative "../../support/pages/meetings/new" +require_relative "../../support/pages/structured_meeting/show" + +RSpec.describe "Structured meetings links caught by turbo", + :js, + :with_cuprite do + include Rails.application.routes.url_helpers + + shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) } + shared_let(:user) do + create(:user, + lastname: "First", + member_with_permissions: { project => %i[view_meetings create_meetings edit_meetings delete_meetings manage_agendas + view_work_packages] }).tap do |u| + u.pref[:time_zone] = "utc" + + u.save! + end + end + shared_let(:meeting1) { create(:structured_meeting, title: "First meeting", project:) } + shared_let(:meeting2) { create(:structured_meeting, title: "Other meeting", project:) } + + let(:notes) do + <<~NOTES + [Meeting link](#{meeting_url(meeting2)}) + NOTES + end + let!(:agenda_item) { create(:meeting_agenda_item, meeting: meeting1, notes:) } + let(:show_page) { Pages::StructuredMeeting::Show.new(meeting1) } + + before do + login_as user + show_page.visit! + end + + it "can link to the other meeting" do + click_link_or_button "Meeting link" + expect(page).to have_current_path meeting_path(meeting2) + expect(page).to have_css("#content", text: "Other meeting", visible: :visible) + end +end diff --git a/spec/contracts/work_packages/base_contract_spec.rb b/spec/contracts/work_packages/base_contract_spec.rb index a24c86069d2..54eab898ca4 100644 --- a/spec/contracts/work_packages/base_contract_spec.rb +++ b/spec/contracts/work_packages/base_contract_spec.rb @@ -725,13 +725,6 @@ RSpec.describe WorkPackages::BaseContract do with_settings: { work_package_done_ratio: "status" } do it_behaves_like "invalid if changed", :done_ratio end - - context "when % Complete disabled", - with_settings: { work_package_done_ratio: "disabled" } do - let(:changed_values) { [:done_ratio] } - - it_behaves_like "invalid if changed", :done_ratio - end end describe "version" do diff --git a/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb b/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb index 20bd139e836..d7edef04246 100644 --- a/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb +++ b/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb @@ -674,16 +674,6 @@ RSpec.describe API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do let(:required) { false } let(:writable) { false } end - - context "as disabled" do - before do - allow(Setting).to receive(:work_package_done_ratio).and_return("disabled") - end - - it "is hidden" do - expect(subject).not_to have_json_path("percentageDone") - end - end end describe "derivedPercentageDone" do @@ -694,16 +684,6 @@ RSpec.describe API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do let(:required) { false } let(:writable) { false } end - - context "as disabled" do - before do - allow(Setting).to receive(:work_package_done_ratio).and_return("disabled") - end - - it "is hidden" do - expect(subject).not_to have_json_path("derivedPercentageDone") - end - end end describe "readonly" do diff --git a/spec/lib/api/v3/work_packages/work_package_representer_spec.rb b/spec/lib/api/v3/work_packages/work_package_representer_spec.rb index 89b590260ab..a511900c879 100644 --- a/spec/lib/api/v3/work_packages/work_package_representer_spec.rb +++ b/spec/lib/api/v3/work_packages/work_package_representer_spec.rb @@ -401,16 +401,6 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter do context "when setting enabled" do it { expect(parse_json(subject)["percentageDone"]).to eq(50) } end - - context "when setting disabled" do - before do - allow(Setting) - .to receive(:work_package_done_ratio) - .and_return("disabled") - end - - it { is_expected.not_to have_json_path("percentageDone") } - end end end diff --git a/spec/lib/open_project/text_formatting/markdown/lists_spec.rb b/spec/lib/open_project/text_formatting/markdown/lists_spec.rb index 880cd90fa94..3724b3302b5 100644 --- a/spec/lib/open_project/text_formatting/markdown/lists_spec.rb +++ b/spec/lib/open_project/text_formatting/markdown/lists_spec.rb @@ -285,7 +285,7 @@ RSpec.describe OpenProject::TextFormatting, asdfasdfasdf - + @@ -316,7 +316,7 @@ RSpec.describe OpenProject::TextFormatting,
  • asdfasdfasdf - + foobar
  • diff --git a/spec/lib/open_project/text_formatting/markdown/mentions_spec.rb b/spec/lib/open_project/text_formatting/markdown/mentions_spec.rb index 39f75ae8b3f..64104d1ec4b 100644 --- a/spec/lib/open_project/text_formatting/markdown/mentions_spec.rb +++ b/spec/lib/open_project/text_formatting/markdown/mentions_spec.rb @@ -313,7 +313,7 @@ RSpec.describe OpenProject::TextFormatting, let(:expected) do <<~EXPECTED

    - Link to Foo Barrit + Link to Foo Barrit

    EXPECTED end diff --git a/spec/lib/open_project/text_formatting/markdown/setting_variable_spec.rb b/spec/lib/open_project/text_formatting/markdown/setting_variable_spec.rb index 3ce2081762d..1e014970436 100644 --- a/spec/lib/open_project/text_formatting/markdown/setting_variable_spec.rb +++ b/spec/lib/open_project/text_formatting/markdown/setting_variable_spec.rb @@ -60,11 +60,11 @@ RSpec.describe OpenProject::TextFormatting, Inline reference to base_url variable: #{Rails.application.root_url}

    - Link with setting

    - Saved and transformed link with setting

    diff --git a/spec/lib/open_project/text_formatting/markdown/user_provided_links_spec.rb b/spec/lib/open_project/text_formatting/markdown/user_provided_links_spec.rb index 4b50c7bad7a..b3aa10aa4e6 100644 --- a/spec/lib/open_project/text_formatting/markdown/user_provided_links_spec.rb +++ b/spec/lib/open_project/text_formatting/markdown/user_provided_links_spec.rb @@ -121,7 +121,7 @@ RSpec.describe OpenProject::TextFormatting, let(:expected) do <<~EXPECTED

    - Link to relative path + Link to relative path

    EXPECTED end diff --git a/spec/migrations/update_progress_calculation_spec.rb b/spec/migrations/update_progress_calculation_spec.rb index 1895179a257..8ce33af5d5b 100644 --- a/spec/migrations/update_progress_calculation_spec.rb +++ b/spec/migrations/update_progress_calculation_spec.rb @@ -78,10 +78,18 @@ RSpec.describe UpdateProgressCalculation, type: :model do run_migration end - it "does not create a journal entry" do - table_work_packages.each do |wp| - expect(wp.journals.count).to eq(1) - end + it "does create a journal entry only for the work package with a total % complete" do + expect(wp_all_unset.journals.count).to eq(1) + expect(wp_only_pc_set.journals.count).to eq(1) + + # This one will receive a journal entry since we treat the total % complete field + # as if it was introduced by the migration (OP 14.0) even though the field existed before. + # But the calculation was off and we did not present the activity on the field anyway. + expect(wp_all_set_consistent.journals.count).to eq(2) + + expect(wp_all_set_consistent.last_journal.get_changes) + .to include("derived_done_ratio" => [nil, 60], + "cause" => [nil, { "feature" => "progress_calculation_changed", "type" => "system_update" }]) end end @@ -635,6 +643,26 @@ RSpec.describe UpdateProgressCalculation, type: :model do ) end end + + context "when parent is open without any work or remaining work set, " \ + "and children have a 100% complete status" do + it "sets parent total % complete to 100%" do + expect_migrates( + from: <<~TABLE, + hierarchy | status | work | remaining work | % complete + parent | To do (0%) | | | 0% + child1 | Done (100%) | 10h | 0h | 100% + child2 | Done (100%) | 10h | 0h | 100% + TABLE + to: <<~TABLE + hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete + parent | To do (0%) | | | 0% | 20h | 0h | 100% + child1 | Done (100%) | 10h | 0h | 100% | 10h | 0h | 100% + child2 | Done (100%) | 10h | 0h | 100% | 10h | 0h | 100% + TABLE + ) + end + end end describe "totals computation" do @@ -689,6 +717,148 @@ RSpec.describe UpdateProgressCalculation, type: :model do ) end end + + context "when parent does not have any work or remaining work set, " \ + "and children have a 100% complete status" do + it "sets parent total % complete to 100%" do + expect_migrates( + from: <<~TABLE, + hierarchy | work | remaining work | % complete + parent | | | + child1 | 10h | 0h | 100% + child2 | 10h | 0h | 100% + TABLE + to: <<~TABLE + hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete + parent | | | | 20h | 0h | 100% + child1 | 10h | 0h | 100% | 10h | 0h | 100% + child2 | 10h | 0h | 100% | 10h | 0h | 100% + TABLE + ) + end + end + + context "when work and remaining work are unset" do + it "does not set total work, total remaining work, and total % complete" do + expect_migrates( + from: <<~TABLE, + subject | work | remaining work | % complete + wp all unset | | | + wp 0% | | | 0% + wp 30% | | | 30% + wp 100% | | | 100% + TABLE + to: <<~TABLE + subject | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete + wp all unset | | | | | | + wp 0% | | | 0% | | | + wp 30% | | | 30% | | | + wp 100% | | | 100% | | | + TABLE + ) + end + end + + context "when work is set to 0h and remaining work is unset" do + it "sets remaining work, total work, and total remaining work to 0h, unsets % complete, and keeps total % complete unset" do + expect_migrates( + from: <<~TABLE, + subject | work | remaining work | % complete + wp all unset | 0h | | + wp 0% | 0h | | 0% + wp 30% | 0h | | 30% + wp 100% | 0h | | 100% + TABLE + to: <<~TABLE + subject | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete + wp all unset | 0h | 0h | | 0h | 0h | + wp 0% | 0h | 0h | | 0h | 0h | + wp 30% | 0h | 0h | | 0h | 0h | + wp 100% | 0h | 0h | | 0h | 0h | + TABLE + ) + end + end + + context "when work and remaining work are set and not 0h" do + it "sets total work, total remaining work, and total % complete accordingly same as work, remaining work and % complete" do + expect_migrates( + from: <<~TABLE, + subject | work | remaining work | + wp w set | 10h | | + wp rw set | | 5h | + wp w rw set | 10h | 5h | + TABLE + to: <<~TABLE + subject | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete + wp w set | 10h | 10h | 0% | 10h | 10h | 0% + wp rw set | 5h | 5h | 0% | 5h | 5h | 0% + wp w rw set | 10h | 5h | 50% | 10h | 5h | 50% + TABLE + ) + end + end + + context "when ∑ % complete has had some values (including wrong ones)" do + let_work_packages(<<~TABLE) + hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete | + wp zero | | | 0 | | | 0 | + wp correct | 100h | 50h | 50 | 100h | 50h | 50 | + wp wrong | | | 90 | 100h | 50h | 90 | + wp wrong child | 100h | 50h | 20 | 10h | 10h | 20 | + TABLE + + before do + run_migration + end + + it "fixes the total values and sets ∑ % complete to nil (not 0) but keeps % complete (unless wrong)" do + expect_work_packages(WorkPackage.all, <<~TABLE) + subject | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete | + wp zero | | | 0 | | | | + wp correct | 100h | 50h | 50 | 100h | 50h | 50 | + wp wrong | | | 90 | 100h | 50h | 50 | + wp wrong child | 100h | 50h | 50 | 100h | 50h | 50 | + TABLE + end + + it "creates no journal for the work package transitioning from 0 to nil and reworks the pre migration journals" do + expect(wp_zero.journals.count).to eq(1) + + expect(wp_zero.journals.first.get_changes.keys) + .not_to include("derived_done_ratio") + end + + it "creates a journal for the correct work package as the old ∑ % complete value has been set to null during the job" do + expect(wp_correct.journals.count).to eq(2) + + expect(wp_correct.journals.first.get_changes.keys) + .not_to include("derived_done_ratio") + + expect(wp_correct.journals.last.get_changes["derived_done_ratio"]) + .to eql [nil, 50] + end + + it "creates a journal for the work package transitioning from 90 to 50 and reworks the pre migration journals" do + expect(wp_wrong.journals.count).to eq(2) + + expect(wp_wrong.journals.first.get_changes.keys) + .not_to include("derived_done_ratio") + + expect(wp_wrong.journals.last.get_changes["derived_done_ratio"]) + .to eql [nil, 50] + end + + it "creates a journal for the work package transitioning from 20 to 50 and reworks the pre migration journals" do + expect(wp_wrong_child.journals.count).to eq(2) + + expect(wp_wrong_child.journals.first.get_changes.keys) + .not_to include("derived_done_ratio") + + expect(wp_wrong_child.journals.last.get_changes["derived_done_ratio"]) + .to eql [nil, 50] + end + end end describe "error during job execution" do diff --git a/spec/models/custom_actions/actions/done_ratio_spec.rb b/spec/models/custom_actions/actions/done_ratio_spec.rb index 320ac891804..4c8a1efe79f 100644 --- a/spec/models/custom_actions/actions/done_ratio_spec.rb +++ b/spec/models/custom_actions/actions/done_ratio_spec.rb @@ -88,14 +88,7 @@ RSpec.describe CustomActions::Actions::DoneRatio do end describe ".all" do - context "with field disabled", with_settings: { work_package_done_ratio: "disabled" } do - it "is empty" do - expect(described_class.all) - .to be_empty - end - end - - context "with field derived", with_settings: { work_package_done_ratio: "status" } do + context "in status-based progress calculation mode", with_settings: { work_package_done_ratio: "status" } do it "is empty" do expect(described_class.all) .to be_empty diff --git a/spec/models/queries/work_packages/selects/property_select_spec.rb b/spec/models/queries/work_packages/selects/property_select_spec.rb index e7b0f40e582..ad7868b4673 100644 --- a/spec/models/queries/work_packages/selects/property_select_spec.rb +++ b/spec/models/queries/work_packages/selects/property_select_spec.rb @@ -35,24 +35,8 @@ RSpec.describe Queries::WorkPackages::Selects::PropertySelect do it_behaves_like "query column" describe "instances" do - context "when done_ratio disabled" do - it "the done ratio column does not exist" do - allow(WorkPackage) - .to receive(:done_ratio_disabled?) - .and_return(true) - - expect(described_class.instances.map(&:name)).not_to include :done_ratio - end - end - - context "when done_ratio enabled" do - it "the done ratio column exists" do - allow(WorkPackage) - .to receive(:done_ratio_disabled?) - .and_return(false) - - expect(described_class.instances.map(&:name)).to include :done_ratio - end + it "the done_ratio column exists" do + expect(described_class.instances.map(&:name)).to include :done_ratio end context "when duration feature flag enabled" do diff --git a/spec/models/query_spec.rb b/spec/models/query_spec.rb index f1e7855090a..3dae47bb06f 100644 --- a/spec/models/query_spec.rb +++ b/spec/models/query_spec.rb @@ -319,20 +319,8 @@ RSpec.describe Query, end describe "#available_columns" do - context "with work_package_done_ratio NOT disabled" do - it "includes the done_ratio column" do - expect(query.displayable_columns.map(&:name)).to include :done_ratio - end - end - - context "with work_package_done_ratio disabled" do - before do - allow(WorkPackage).to receive(:done_ratio_disabled?).and_return(true) - end - - it "does not include the done_ratio column" do - expect(query.displayable_columns.map(&:name)).not_to include :done_ratio - end + it "includes the done_ratio column" do + expect(query.displayable_columns.map(&:name)).to include :done_ratio end context "results caching" do diff --git a/spec/requests/api/v3/render_resource_spec.rb b/spec/requests/api/v3/render_resource_spec.rb index 25eba4518ae..9de125e4384 100644 --- a/spec/requests/api/v3/render_resource_spec.rb +++ b/spec/requests/api/v3/render_resource_spec.rb @@ -73,6 +73,7 @@ RSpec.describe "API v3 Render resource" do

    Hello World! This is markdown with a link and ümläutß.

    diff --git a/spec/services/work_packages/update_ancestors_service_spec.rb b/spec/services/work_packages/update_ancestors_service_spec.rb index 05c495d178f..ce44ef03c83 100644 --- a/spec/services/work_packages/update_ancestors_service_spec.rb +++ b/spec/services/work_packages/update_ancestors_service_spec.rb @@ -32,8 +32,8 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do shared_association_default(:author, factory_name: :user) { create(:user) } shared_association_default(:project_with_types) { create(:project_with_types) } shared_association_default(:priority) { create(:priority) } - shared_association_default(:open_status, factory_name: :status) { create(:status) } - shared_let(:closed_status) { create(:closed_status) } + shared_association_default(:open_status, factory_name: :status) { create(:status, name: "Open", default_done_ratio: 0) } + shared_let(:closed_status) { create(:closed_status, name: "Closed", default_done_ratio: 100) } shared_let(:user) { create(:user) } let(:estimated_hours) { [nil, nil, nil] } @@ -56,11 +56,14 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do describe "done_ratio/estimated_hours/remaining_hours propagation" do context "when setting the status of a work package" do - shared_let(:open_status) { create(:status, name: "open", default_done_ratio: 0) } - shared_let(:complete_status_with_100p_done_ratio) { create(:status, name: "complete", default_done_ratio: 100) } - context 'when using the "status-based" % complete mode', with_settings: { work_package_done_ratio: "status" } do + def call_update_ancestors_service(work_package) + changed_attributes = work_package.changes.keys.map(&:to_sym) + described_class.new(user:, work_package:) + .call(changed_attributes) + end + context "with both parent and children having estimated hours set" do shared_let(:parent) do create(:work_package, @@ -80,19 +83,14 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do status: open_status) end - def call_update_ancestors_service(work_package) - changed_attributes = work_package.changes.keys.map(&:to_sym) - described_class.new(user:, work_package:) - .call(changed_attributes) - end context "when changing child status to a status with a default done ratio" do %i[status status_id].each do |field| context "with the #{field} field" do it "recomputes child remaining work and update ancestors total % complete accordingly" do value = case field - when :status then complete_status_with_100p_done_ratio - when :status_id then complete_status_with_100p_done_ratio.id + when :status then closed_status + when :status_id then closed_status.id end set_attributes_on(child, field => value) call_update_ancestors_service(child) @@ -100,13 +98,40 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do expect_work_packages([parent, child], <<~TABLE) | subject | work | total work | remaining work | total remaining work | % complete | total % complete | | parent | 10h | 15h | 10h | 10h | 0% | 33% | - | child | 5h | 5h | 0h | | 100% | | + | child | 5h | 5h | 0h | 0h | 100% | 100% | TABLE end end end end end + + context "with parent having nothing set, and 2 children having values set (bug #54179)" do + let_work_packages(<<~TABLE) + hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete + parent | Open | | 15h | | 10h | 0% | 33% + child1 | Open | 10h | | 10h | | 0% | + child2 | Closed | 5h | | 0h | | 100% | + TABLE + + context "when changing children to all have 100% complete" do + before do + set_attributes_on(child1, status: closed_status) + call_update_ancestors_service(child1) + end + + it "sets parent total % complete to 100% and its total remaining work to 0h, " \ + "and computes totals for the updated children too" do + table_work_packages.map(&:reload) + expect_work_packages(table_work_packages, <<~TABLE) + hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete + parent | Open | | 15h | | 0h | 0% | 100% + child1 | Closed | 10h | 10h | 0h | 0h | 100% | 100% + child2 | Closed | 5h | | 0h | | 100% | + TABLE + end + end + end end end @@ -224,7 +249,7 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do end end - context "with all tasks having estimated hours and no tasks having any progress done yet" do + context "with all tasks having estimated hours and no tasks having any remaining hours" do it_behaves_like "attributes of parent having children" do let(:estimated_hours) do [10.0, 2.0, 3.0] @@ -237,10 +262,10 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do 15.0 end let(:aggregate_remaining_hours) do - nil # zero-values aren't accounted for + 0.0 end let(:aggregate_done_ratio) do - nil + 100 end end end @@ -431,7 +456,7 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do end end - context "with all tasks having estimated hours and no tasks having any progress done yet" do + context "with all tasks having estimated hours and no tasks having remaining hours" do it_behaves_like "attributes of parent having children" do let(:estimated_hours) do [10.0, 2.0, 3.0] @@ -444,10 +469,10 @@ RSpec.describe WorkPackages::UpdateAncestorsService, type: :model do 15.0 end let(:aggregate_remaining_hours) do - nil # zero-values aren't accounted for + 0.0 end let(:aggregate_done_ratio) do - nil + 100 end end end