mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Merge pull request #15283 from opf/merge-release/14.0-20240417033437
Merge release/14.0 into dev
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -40,10 +40,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<li><%= WorkPackage.human_attribute_name(:start_date) %>: <%= work_package.start_date %></li>
|
||||
<li><%= WorkPackage.human_attribute_name(:due_date) %>: <%= work_package.due_date %></li>
|
||||
<li><%= WorkPackage.human_attribute_name(:estimated_hours)%>: <%= work_package.estimated_hours %></li>
|
||||
|
||||
<% if Setting.work_package_done_ratio != 'disabled' %>
|
||||
<li><%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %></li>
|
||||
<% end %>
|
||||
<li><%= WorkPackage.human_attribute_name(:done_ratio) %>: <%= work_package.done_ratio %></li>
|
||||
|
||||
<% work_package.custom_field_values.each do |value| %>
|
||||
<li><%= value.custom_field.name %>: <%= show_value(value) %></li>
|
||||
|
||||
@@ -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 %>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -3668,9 +3668,7 @@ Project attributes and sections are defined in the <a href=%{admin_settings_url}
|
||||
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:
|
||||
|
||||
-1
@@ -13,7 +13,6 @@
|
||||
bindLabel="name"
|
||||
[multiple]="false"
|
||||
[virtualScroll]="true"
|
||||
appendTo="body"
|
||||
[placeholder]="inputPlaceholder"
|
||||
[clearSearchOnAdd]="true"
|
||||
[closeOnSelect]="true"
|
||||
|
||||
+9
-3
@@ -2,19 +2,22 @@ import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild,
|
||||
ElementRef } from '@angular/core';
|
||||
} from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { NgSelectComponent } from '@ng-select/ng-select';
|
||||
import { DragulaService, Group } from 'ng2-dragula';
|
||||
import { DomAutoscrollService } from 'core-app/shared/helpers/drag-and-drop/dom-autoscroll.service';
|
||||
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
|
||||
import { setBodyCursor } from 'core-app/shared/helpers/dom/set-window-cursor.helper';
|
||||
import { repositionDropdownBugfix } from 'core-app/shared/components/autocompleter/op-autocompleter/autocompleter.helper';
|
||||
import {
|
||||
repositionDropdownBugfix,
|
||||
} from 'core-app/shared/components/autocompleter/op-autocompleter/autocompleter.helper';
|
||||
import { QueryFilterResource } from 'core-app/features/hal/resources/query-filter-resource';
|
||||
import { AlternativeSearchService } from 'core-app/shared/components/work-packages/alternative-search.service';
|
||||
import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs';
|
||||
@@ -92,7 +95,10 @@ export class DraggableAutocompleteComponent extends UntilDestroyedMixin implemen
|
||||
this.updateAvailableOptions();
|
||||
|
||||
// Setup groups
|
||||
this.columnsGroup = this.dragula.createGroup('columns', {});
|
||||
this.columnsGroup = this.dragula.createGroup(
|
||||
'columns',
|
||||
{ mirrorContainer: this.appendToComponent ? document.getElementById('op-draggable-autocomplete-container')! : document.body },
|
||||
);
|
||||
|
||||
// Set cursor when dragging
|
||||
this.dragula.drag('columns')
|
||||
|
||||
+3
@@ -64,6 +64,8 @@ export class CkeditorAugmentedTextareaComponent extends UntilDestroyedMixin impl
|
||||
|
||||
@Input() public macros:ICKEditorMacroType;
|
||||
|
||||
@Input() public removePlugins:string[] = [];
|
||||
|
||||
@Input() public resource?:object;
|
||||
|
||||
@Input() public turboMode = false;
|
||||
@@ -130,6 +132,7 @@ export class CkeditorAugmentedTextareaComponent extends UntilDestroyedMixin impl
|
||||
type: this.editorType,
|
||||
resource: this.halResource,
|
||||
previewContext: this.previewContext,
|
||||
removePlugins: this.removePlugins,
|
||||
};
|
||||
if (this.readOnly) {
|
||||
this.context.macros = 'none';
|
||||
|
||||
+31
-1
@@ -31,6 +31,7 @@ export class CKEditorSetupService {
|
||||
|
||||
public initialize() {
|
||||
this.prefetch = this.load();
|
||||
this.watchTopLayer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,8 @@ export class CKEditorSetupService {
|
||||
* @returns {Promise<ICKEditorWatchdog>}
|
||||
*/
|
||||
public async create(
|
||||
wrapper:HTMLElement, context:ICKEditorContext,
|
||||
wrapper:HTMLElement,
|
||||
context:ICKEditorContext,
|
||||
initialData:string|null = null,
|
||||
):Promise<ICKEditorWatchdog> {
|
||||
// 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
inputs: @rich_text_options.reverse_merge(
|
||||
{
|
||||
textareaSelector: "##{builder.field_id(@input.name)}",
|
||||
macros: 'resource',
|
||||
removePlugins: ["CodeBlock"],
|
||||
macros: false,
|
||||
turboMode: true
|
||||
}
|
||||
)
|
||||
|
||||
@@ -53,6 +53,8 @@ module API
|
||||
end
|
||||
},
|
||||
getter: ->(*) {
|
||||
next unless embed_links
|
||||
|
||||
active_projects.map do |project|
|
||||
Projects::ProjectRepresenter.create(project, current_user:)
|
||||
end
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ RSpec.describe OpenProject::TextFormatting,
|
||||
<input type="checkbox" disabled="disabled">
|
||||
<span class="op-uc-list__label__description">asdfasdfasdf </span>
|
||||
</label>
|
||||
<a class="op-uc-link" href="https://example.com/">
|
||||
<a class="op-uc-link" target="_top" href="https://example.com/">
|
||||
<label class="op-uc-list__label">
|
||||
<span class="op-uc-list__label__description">foobar</span>
|
||||
</label>
|
||||
@@ -316,7 +316,7 @@ RSpec.describe OpenProject::TextFormatting,
|
||||
<li class="op-uc-list--item">
|
||||
<input type="checkbox" class="op-uc-list--task-checkbox" disabled>
|
||||
<span>asdfasdfasdf </span>
|
||||
<a class="op-uc-link" href="https://example.com/" rel="noopener noreferrer">
|
||||
<a class="op-uc-link" href="https://example.com/" target="_top" rel="noopener noreferrer">
|
||||
<span>foobar</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -313,7 +313,7 @@ RSpec.describe OpenProject::TextFormatting,
|
||||
let(:expected) do
|
||||
<<~EXPECTED
|
||||
<p class="op-uc-p">
|
||||
Link to <a class="user-mention op-uc-link" href="http://openproject.org/users/#{user.id}" title="User Foo Barrit">Foo Barrit</a>
|
||||
Link to <a class="user-mention op-uc-link" target="_top" href="http://openproject.org/users/#{user.id}" title="User Foo Barrit">Foo Barrit</a>
|
||||
</p>
|
||||
EXPECTED
|
||||
end
|
||||
|
||||
@@ -60,11 +60,11 @@ RSpec.describe OpenProject::TextFormatting,
|
||||
Inline reference to base_url variable: #{Rails.application.root_url}
|
||||
</p>
|
||||
<p class="op-uc-p">
|
||||
<a href="#{Rails.application.root_url}/foo/bar" rel="noopener noreferrer"
|
||||
<a href="#{Rails.application.root_url}/foo/bar" target="_top" rel="noopener noreferrer"
|
||||
class="op-uc-link">Link with setting</a>
|
||||
</p>
|
||||
<p class="op-uc-p">
|
||||
<a href="#{Rails.application.root_url}/foo/bar" rel="noopener noreferrer"
|
||||
<a href="#{Rails.application.root_url}/foo/bar" target="_top" rel="noopener noreferrer"
|
||||
class="op-uc-link">Saved and transformed link with setting</a>
|
||||
</p>
|
||||
<p class="op-uc-p">
|
||||
|
||||
@@ -121,7 +121,7 @@ RSpec.describe OpenProject::TextFormatting,
|
||||
let(:expected) do
|
||||
<<~EXPECTED
|
||||
<p class="op-uc-p">
|
||||
Link to <a href="http://openproject.org/foo/bar" class="op-uc-link" rel="noopener noreferrer">relative path</a>
|
||||
Link to <a href="http://openproject.org/foo/bar" target="_top" class="op-uc-link" rel="noopener noreferrer">relative path</a>
|
||||
</p>
|
||||
EXPECTED
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -73,6 +73,7 @@ RSpec.describe "API v3 Render resource" do
|
||||
<p class="op-uc-p">
|
||||
Hello World! This <em>is</em> markdown with a
|
||||
<a href="http://community.openproject.org"
|
||||
target="_top"
|
||||
rel="noopener noreferrer"
|
||||
class="op-uc-link">link</a>
|
||||
and ümläutß.</p>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user