Merge remote-tracking branch 'upstream/dev' into storybook-updates-ux

pull/11399/head
Parimal Satyal 2 years ago
commit ec12261bad
  1. 13
      .github/CODEOWNERS
  2. 10
      Gemfile
  3. 58
      Gemfile.lock
  4. 4
      app/controllers/workflows_controller.rb
  5. 6
      app/models/notification_setting.rb
  6. 11
      app/models/project.rb
  7. 34
      app/models/user.rb
  8. 2
      app/seeders/admin_user_seeder.rb
  9. 7
      app/seeders/development_data/projects_seeder.rb
  10. 2
      app/seeders/development_data/users_seeder.rb
  11. 57
      app/seeders/random_data/forum_seeder.rb
  12. 56
      app/seeders/random_data/news_seeder.rb
  13. 61
      app/seeders/random_data/wiki_seeder.rb
  14. 188
      app/seeders/random_data/work_package_seeder.rb
  15. 55
      app/seeders/random_data_seeder.rb
  16. 5
      app/seeders/root_seeder.rb
  17. 47
      app/services/base_services/copy.rb
  18. 7
      app/services/copy/dependency.rb
  19. 10
      app/services/grids/copy_service.rb
  20. 4
      app/services/notifications/create_from_model_service.rb
  21. 57
      app/services/projects/copy/attachment_copier.rb
  22. 2
      app/services/projects/copy/categories_dependent_service.rb
  23. 2
      app/services/projects/copy/dependency.rb
  24. 2
      app/services/projects/copy/members_dependent_service.rb
  25. 42
      app/services/projects/copy/no_copier.rb
  26. 2
      app/services/projects/copy/overview_dependent_service.rb
  27. 2
      app/services/projects/copy/queries_dependent_service.rb
  28. 7
      app/services/projects/copy/wiki_dependent_service.rb
  29. 15
      app/services/projects/copy/wiki_page_attachments_dependent_service.rb
  30. 19
      app/services/projects/copy/work_package_attachments_dependent_service.rb
  31. 47
      app/services/projects/copy/work_packages_dependent_service.rb
  32. 112
      app/services/projects/copy_service.rb
  33. 11
      app/services/queries/copy_service.rb
  34. 3
      app/services/user_preferences/update_service.rb
  35. 2
      app/services/users/set_attributes_service.rb
  36. 14
      app/services/wiki_pages/copy_service.rb
  37. 31
      app/services/work_packages/copy_service.rb
  38. 28
      app/services/work_packages/schedule_dependency.rb
  39. 1
      app/views/onboarding/_onboarding_video_modal.html.erb
  40. 9
      app/views/projects/_project_export_modal.html.erb
  41. 15
      app/workers/backup_job.rb
  42. 10
      config/locales/crowdin/af.yml
  43. 10
      config/locales/crowdin/ar.yml
  44. 10
      config/locales/crowdin/az.yml
  45. 10
      config/locales/crowdin/bg.yml
  46. 10
      config/locales/crowdin/ca.yml
  47. 10
      config/locales/crowdin/ckb-IR.yml
  48. 10
      config/locales/crowdin/cs.yml
  49. 10
      config/locales/crowdin/da.yml
  50. 12
      config/locales/crowdin/de.yml
  51. 10
      config/locales/crowdin/el.yml
  52. 10
      config/locales/crowdin/eo.yml
  53. 10
      config/locales/crowdin/es.yml
  54. 10
      config/locales/crowdin/et.yml
  55. 10
      config/locales/crowdin/fa.yml
  56. 10
      config/locales/crowdin/fi.yml
  57. 10
      config/locales/crowdin/fil.yml
  58. 14
      config/locales/crowdin/fr.yml
  59. 10
      config/locales/crowdin/he.yml
  60. 10
      config/locales/crowdin/hi.yml
  61. 10
      config/locales/crowdin/hr.yml
  62. 10
      config/locales/crowdin/hu.yml
  63. 10
      config/locales/crowdin/id.yml
  64. 10
      config/locales/crowdin/it.yml
  65. 10
      config/locales/crowdin/ja.yml
  66. 6
      config/locales/crowdin/js-af.yml
  67. 6
      config/locales/crowdin/js-ar.yml
  68. 6
      config/locales/crowdin/js-az.yml
  69. 6
      config/locales/crowdin/js-bg.yml
  70. 6
      config/locales/crowdin/js-ca.yml
  71. 6
      config/locales/crowdin/js-ckb-IR.yml
  72. 6
      config/locales/crowdin/js-cs.yml
  73. 6
      config/locales/crowdin/js-da.yml
  74. 6
      config/locales/crowdin/js-de.yml
  75. 6
      config/locales/crowdin/js-el.yml
  76. 6
      config/locales/crowdin/js-eo.yml
  77. 6
      config/locales/crowdin/js-es.yml
  78. 6
      config/locales/crowdin/js-et.yml
  79. 6
      config/locales/crowdin/js-fa.yml
  80. 6
      config/locales/crowdin/js-fi.yml
  81. 6
      config/locales/crowdin/js-fil.yml
  82. 6
      config/locales/crowdin/js-fr.yml
  83. 6
      config/locales/crowdin/js-he.yml
  84. 6
      config/locales/crowdin/js-hi.yml
  85. 6
      config/locales/crowdin/js-hr.yml
  86. 6
      config/locales/crowdin/js-hu.yml
  87. 6
      config/locales/crowdin/js-id.yml
  88. 6
      config/locales/crowdin/js-it.yml
  89. 6
      config/locales/crowdin/js-ja.yml
  90. 6
      config/locales/crowdin/js-ko.yml
  91. 6
      config/locales/crowdin/js-lol.yml
  92. 6
      config/locales/crowdin/js-lt.yml
  93. 6
      config/locales/crowdin/js-lv.yml
  94. 6
      config/locales/crowdin/js-ne.yml
  95. 44
      config/locales/crowdin/js-nl.yml
  96. 6
      config/locales/crowdin/js-no.yml
  97. 6
      config/locales/crowdin/js-pl.yml
  98. 6
      config/locales/crowdin/js-pt.yml
  99. 6
      config/locales/crowdin/js-ro.yml
  100. 8
      config/locales/crowdin/js-ru.yml
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,14 +1,3 @@
# Frontend rules
*.js @opf/frontend
*.ts @opf/frontend
# Backend rules
/app/ @opf/backend
/config/ @opf/backend
/lib/ @opf/backend
/lib_static/ @opf/backend
/modules/ @opf/backend
# docs rules
/docs/ @opf/doc-writers
@ -16,4 +5,4 @@
/docs/development @opf/tech-writers
/docs/installation-and-operations @opf/tech-writers
/docs/system-admin-guide @opf/tech-writers
/docs/api @opf/tech-writers @opf/backend
/docs/api @opf/tech-writers

@ -88,7 +88,7 @@ gem 'deckar01-task_list', '~> 2.3.1'
# Requires escape-utils for faster escaping
gem 'escape_utils', '~> 1.3'
# Syntax highlighting used in html-pipeline with rouge
gem 'rouge', '~> 3.30.0'
gem 'rouge', '~> 4.0.0'
# HTML sanitization used for html-pipeline
gem 'sanitize', '~> 6.0.0'
# HTML autolinking for mails and urls (replaces autolink)
@ -120,7 +120,7 @@ gem 'daemons'
gem 'delayed_cron_job', '~> 0.9.0'
gem 'delayed_job_active_record', '~> 4.1.5'
gem 'rack-protection', '~> 2.2.0'
gem 'rack-protection', '~> 3.0.0'
# Rack::Attack is a rack middleware to protect your web app from bad clients.
# It allows whitelisting, blacklisting, throttling, and tracking based
@ -157,7 +157,7 @@ gem 'matrix', '~> 0.4.2'
gem 'cells-erb', '~> 0.1.0'
gem 'cells-rails', '~> 0.1.4'
gem 'meta-tags', '~> 2.17.0'
gem 'meta-tags', '~> 2.18.0'
gem "paper_trail", "~> 12.3"
@ -216,7 +216,7 @@ group :test do
# and other niceties
gem 'test-prof', '~> 1.0.0'
gem 'database_cleaner', '~> 2.0'
gem 'database_cleaner', '~> 2.0' # only useful for legacy_spec
gem 'rack_session_access'
gem 'rspec', '~> 3.11.0'
# also add to development group, so "spec" rake task gets loaded
@ -235,7 +235,7 @@ group :test do
gem 'capybara', '~> 3.37.0'
gem 'capybara-screenshot', '~> 1.0.17'
gem 'selenium-webdriver', '~> 4.0'
gem 'webdrivers', '~> 5.0.0'
gem 'webdrivers', '~> 5.2.0'
gem 'fuubar', '~> 2.5.0'
gem 'timecop', '~> 0.9.0'

@ -291,8 +291,8 @@ GEM
awesome_nested_set (3.5.0)
activerecord (>= 4.0.0, < 7.1)
aws-eventstream (1.2.0)
aws-partitions (1.640.0)
aws-sdk-core (3.158.0)
aws-partitions (1.644.0)
aws-sdk-core (3.159.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
@ -310,7 +310,7 @@ GEM
aws-sigv4 (1.5.2)
aws-eventstream (~> 1, >= 1.0.2)
bcrypt (3.1.18)
bindata (2.4.10)
bindata (2.4.12)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootsnap (1.13.0)
@ -409,13 +409,12 @@ GEM
declarative-option (0.1.0)
delayed_cron_job (0.9.0)
fugit (>= 1.5)
delayed_job (4.1.10)
delayed_job (4.1.11)
activesupport (>= 3.0, < 8.0)
delayed_job_active_record (4.1.7)
activerecord (>= 3.0, < 8.0)
delayed_job (>= 3.0, < 5)
diff-lcs (1.5.0)
digest (3.1.0)
disposable (0.6.3)
declarative (>= 0.0.9, < 1.0.0)
representable (>= 3.1.1, < 4)
@ -427,7 +426,7 @@ GEM
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
dry-container (0.10.1)
dry-container (0.11.0)
concurrent-ruby (~> 1.0)
dry-core (0.8.1)
concurrent-ruby (~> 1.0)
@ -465,7 +464,7 @@ GEM
tzinfo
eventmachine (1.2.7)
eventmachine_httpserver (0.2.1)
excon (0.92.4)
excon (0.93.0)
factory_bot (6.2.1)
activesupport (>= 5.0.0)
factory_bot_rails (6.2.0)
@ -519,7 +518,7 @@ GEM
formatador (1.1.0)
friendly_id (5.4.2)
activerecord (>= 4.0.0)
fugit (1.6.0)
fugit (1.7.1)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
fuubar (2.5.1)
@ -591,7 +590,7 @@ GEM
open4 (~> 1.0)
launchy (2.5.0)
addressable (~> 2.7)
lefthook (1.1.1)
lefthook (1.1.2)
letter_opener (1.8.1)
launchy (>= 2.2, < 3)
listen (3.7.1)
@ -612,7 +611,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.18.0)
loofah (2.19.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@ -620,7 +619,7 @@ GEM
marcel (1.0.2)
matrix (0.4.2)
messagebird-rest (1.4.2)
meta-tags (2.17.0)
meta-tags (2.18.0)
actionpack (>= 3.2.0, < 7.1)
method_source (1.0.0)
mime-types (3.4.1)
@ -631,7 +630,7 @@ GEM
mini_portile2 (2.8.0)
minisyntax (0.2.5)
minitest (5.16.3)
msgpack (1.5.6)
msgpack (1.6.0)
multi_json (1.15.0)
multipart-post (2.2.3)
mustermann (3.0.0)
@ -639,28 +638,22 @@ GEM
mustermann-grape (1.0.2)
mustermann (>= 1.0.0)
nap (1.1.0)
net-imap (0.2.3)
digest
net-imap (0.3.1)
net-protocol
strscan
net-ldap (0.17.1)
net-pop (0.1.1)
digest
net-pop (0.1.2)
net-protocol
timeout
net-protocol (0.1.3)
timeout
net-smtp (0.3.1)
digest
net-smtp (0.3.2)
net-protocol
timeout
netrc (0.11.0)
nio4r (2.5.8)
no_proxy_fix (0.1.2)
nokogiri (1.13.8)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (5.5.0)
octokit (5.6.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
oj (3.13.21)
@ -698,7 +691,7 @@ GEM
hashery (~> 2.0)
ruby-rc4
ttfunk
pg (1.4.3)
pg (1.4.4)
plaintext (0.3.4)
activesupport (> 2.2.1)
nokogiri (~> 1.10, >= 1.10.4)
@ -759,7 +752,7 @@ GEM
httpclient
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (2.2.2)
rack-protection (3.0.2)
rack
rack-test (2.0.2)
rack (>= 1.3)
@ -812,7 +805,7 @@ GEM
recaptcha (5.12.3)
json
redcarpet (3.5.1)
regexp_parser (2.5.0)
regexp_parser (2.6.0)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
@ -833,7 +826,7 @@ GEM
roar (1.1.1)
representable (~> 3.0)
rotp (6.2.0)
rouge (3.30.0)
rouge (4.0.0)
rspec (3.11.0)
rspec-core (~> 3.11.0)
rspec-expectations (~> 3.11.0)
@ -938,7 +931,6 @@ GEM
stackprof (0.2.21)
stringex (2.8.5)
stringio (3.0.2)
strscan (3.0.4)
structured_warnings (0.4.0)
svg-graph (2.2.1)
swd (1.3.0)
@ -980,7 +972,7 @@ GEM
rack (>= 2.0.9)
warden-basic_auth (0.2.1)
warden (~> 1.2)
webdrivers (5.0.0)
webdrivers (5.2.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0)
@ -1000,7 +992,7 @@ GEM
activerecord (>= 4.2)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.0)
zeitwerk (2.6.1)
PLATFORMS
ruby
@ -1075,7 +1067,7 @@ DEPENDENCIES
livingstyleguide (~> 2.1.0)
lograge (~> 0.12.0)
matrix (~> 0.4.2)
meta-tags (~> 2.17.0)
meta-tags (~> 2.18.0)
mini_magick (~> 4.11.0)
multi_json (~> 1.15.0)
my_page!
@ -1127,7 +1119,7 @@ DEPENDENCIES
rack-attack (~> 6.6.0)
rack-cors (~> 1.1.1)
rack-mini-profiler
rack-protection (~> 2.2.0)
rack-protection (~> 3.0.0)
rack-test (~> 2.0.0)
rack-timeout (~> 0.6.3)
rack_session_access
@ -1141,7 +1133,7 @@ DEPENDENCIES
retriable (~> 3.1.1)
rinku (~> 2.0.4)
roar (~> 1.1.0)
rouge (~> 3.30.0)
rouge (~> 4.0.0)
rspec (~> 3.11.0)
rspec-rails (= 6.0.0.rc1)
rspec-retry (~> 0.6.1)
@ -1179,7 +1171,7 @@ DEPENDENCIES
validate_url
warden (~> 1.2)
warden-basic_auth (~> 0.2.1)
webdrivers (~> 5.0.0)
webdrivers (~> 5.2.0)
webmock (~> 3.12)
will_paginate (~> 3.3.0)
with_advisory_lock (~> 4.6.0)

@ -69,12 +69,12 @@ class WorkflowsController < ApplicationController
@source_type = if params[:source_type_id].blank? || params[:source_type_id] == 'any'
nil
else
::Type.find_by(id: params[:source_type_id].to_i)
::Type.find(params[:source_type_id])
end
@source_role = if params[:source_role_id].blank? || params[:source_role_id] == 'any'
nil
else
Role.find_by(id: params[:source_role_id].to_i)
Role.find(params[:source_role_id])
end
@target_types = params[:target_type_ids].blank? ? nil : ::Type.where(id: params[:target_type_ids])

@ -1,6 +1,7 @@
class NotificationSetting < ApplicationRecord
WATCHED = :watched
INVOLVED = :involved
ASSIGNEE = :assignee
RESPONSIBLE = :responsible
MENTIONED = :mentioned
WORK_PACKAGE_CREATED = :work_package_created
WORK_PACKAGE_COMMENTED = :work_package_commented
@ -19,7 +20,8 @@ class NotificationSetting < ApplicationRecord
def self.all_settings
[
WATCHED,
INVOLVED,
ASSIGNEE,
RESPONSIBLE,
MENTIONED,
WORK_PACKAGE_CREATED,
WORK_PACKAGE_COMMENTED,

@ -258,17 +258,6 @@ class Project < ApplicationRecord
@assignable_versions ||= shared_versions.references(:project).with_status_open.order_by_semver_name.to_a
end
# Returns a hash of project users grouped by role
def users_by_role
members.includes(:principal, :roles).inject({}) do |h, m|
m.roles.each do |r|
h[r] ||= []
h[r] << m.principal
end
h
end
end
# Returns an AR scope of all custom fields enabled for project's work packages
# (explicitly associated custom fields and custom fields enabled for all projects)
def all_work_package_custom_fields

@ -164,7 +164,6 @@ class User < Principal
def reload(*args)
@name = nil
@projects_by_role = nil
@user_allowed_service = nil
@project_role_cache = nil
@ -480,37 +479,6 @@ class User < Principal
roles_for_project(project).any?(&:member?)
end
# Returns a hash of user's projects grouped by roles
def projects_by_role
return @projects_by_role if @projects_by_role
@projects_by_role = Hash.new { |h, k| h[k] = [] }
memberships.each do |membership|
membership.roles.each do |role|
@projects_by_role[role] << membership.project if membership.project
end
end
@projects_by_role.each do |_role, projects|
projects.uniq!
end
@projects_by_role
end
# Returns true if user is arg or belongs to arg
# rubocop:disable Naming/PredicateName
def is_or_belongs_to?(arg)
case arg
when User
self == arg
when Group
arg.users.include?(self)
else
false
end
end
# rubocop:enable Naming/PredicateName
def self.allowed(action, project)
Authorization.users(action, project)
end
@ -638,7 +606,7 @@ class User < Principal
separators = Regexp.escape(Setting.mail_suffix_separators)
recipient, domain = mail.split('@').map { |part| Regexp.escape(part) }
skip_suffix_check = recipient.nil? || Setting.mail_suffix_separators.empty? || recipient.match?(/.+[#{separators}].+/)
regexp = "#{recipient}([#{separators}][^@]+)*@#{domain}"
regexp = "^#{recipient}([#{separators}][^@]+)*@#{domain}$"
[skip_suffix_check, regexp]
end

@ -55,7 +55,7 @@ class AdminUserSeeder < Seeder
user.language = I18n.locale.to_s
user.status = User.statuses[:active]
user.force_password_change = force_password_change?
user.notification_settings.build(involved: true, mentioned: true, watched: true)
user.notification_settings.build(assignee: true, responsible: true, mentioned: true, watched: true)
end
end

@ -97,13 +97,18 @@ module DevelopmentData
def project_data(identifier)
{
name: identifier.humanize,
name: project_name(identifier),
identifier:,
enabled_module_names: project_modules,
types: Type.all
}
end
def project_name(identifier)
_dev, *parts = identifier.split('-')
"[dev] #{parts.join(' ').capitalize}"
end
def project_modules
Setting.default_projects_modules - %w(news wiki meetings calendar)
end

@ -103,7 +103,7 @@ module DevelopmentData
user.status = User.statuses[:active]
user.language = I18n.locale
user.force_password_change = false
user.notification_settings.build(involved: true, mentioned: true, watched: true)
user.notification_settings.build(assignee: true, responsible: true, mentioned: true, watched: true)
end
end

@ -1,57 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module RandomData
class ForumSeeder
def self.seed!(project)
user = User.admin.first
puts ''
print_status ' ↳ Creating forum with posts'
forum = Forum.create! project: project,
name: I18n.t("seeders.#{OpenProject::Configuration['edition']}.demo_data.board.name"),
description: I18n.t("seeders.#{OpenProject::Configuration['edition']}.demo_data.board.description")
rand(30).times do
print_status '.'
message = Message.create forum: forum,
author: user,
subject: Faker::Lorem.words(5).join(' '),
content: Faker::Lorem.paragraph(5, true, 3)
rand(5).times do
print_status '.'
Message.create forum:,
author: user,
subject: message.subject,
content: Faker::Lorem.paragraph(5, true, 3),
parent: message
end
end
end
end
end

@ -1,56 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module RandomData
class NewsSeeder
def self.seed!(project)
user = User.admin.first
puts ''
print_status ' ↳ Creating news'
rand(30).times do
print_status '.'
news = News.create project: project,
author: user,
title: Faker::Lorem.characters(60),
summary: Faker::Lorem.paragraph(1, true, 3),
description: Faker::Lorem.paragraph(5, true, 3)
## create some journal entries
rand(5).times do
news.reload
news.title = Faker::Lorem.words(5).join(' ').slice(0, 60) if rand(99).even?
news.summary = Faker::Lorem.paragraph(1, true, 3) if rand(99).even?
news.description = Faker::Lorem.paragraph(5, true, 3) if rand(99).even?
news.save!
end
end
end
end
end

@ -1,61 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module RandomData
class WikiSeeder
def self.seed!(project)
user = User.admin.first
puts ''
print_status ' ↳ Creating wikis'
rand(5).times do
print_status '.'
wiki_page = WikiPage.create(
wiki: project.wiki,
title: Faker::Lorem.words(5).join(' ')
)
## create some wiki contents
rand(5).times do
print_status '.'
wiki_content = WikiContent.create(
page: wiki_page,
author: user,
text: Faker::Lorem.paragraph(5, true, 3)
)
## create some journal entries
rand(5).times do
wiki_content.reload
wiki_content.text = Faker::Lorem.paragraph(5, true, 3) if rand(99).even?
wiki_content.save!
end
end
end
end
end
end

@ -1,188 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module RandomData
class WorkPackageSeeder
attr_accessor :project, :user, :statuses, :repository, :types
def initialize(project)
self.project = project
self.user = User.admin.first
self.statuses = Status.all
self.repository = Repository.first
self.types = project.types.all.reject(&:is_milestone?)
end
def seed!(random: true)
puts ''
print_status ' ↳ Creating work_packages'
seed_random_work_packages
end
private
def seed_random_work_packages
rand(50).times do
print_status '.'
work_package = WorkPackage.create!(
project:,
author: user,
subject: Faker::Lorem.words(8).join(' '),
status: statuses.sample,
type: types.sample,
start_date: s = Date.today - rand(-24..25).days,
due_date: s + rand(1..120).days
)
work_package.priority = IssuePriority.all.sample
work_package.description = Faker::Lorem.paragraph(5, true, 3)
work_package.save!
end
work_package = WorkPackage.first
if repository
add_changeset(work_package)
end
add_time_entries(work_package)
add_attachments(work_package)
add_custom_values(work_package)
make_changes(work_package)
end
def add_changeset(work_package)
2.times do |changeset_count|
print_status '.'
changeset = Changeset.create(
repository:,
user:,
revision: (work_package.id * 10) + changeset_count,
scmid: (work_package.id * 10) + changeset_count,
work_packages: [work_package],
committer: Faker::Name.name,
committed_on: Date.today,
comments: Faker::Lorem.words(8).join(' ')
)
5.times do
print_status '.'
change = Change.create(
action: Faker::Lorem.characters(1),
path: Faker::Internet.url
)
changeset.file_changes << change
end
repository.changesets << changeset
changeset.save!
rand(5).times do
print_status '.'
changeset.reload
changeset.committer = Faker::Name.name if rand(99).even?
changeset.committed_on = Date.today + rand(999) if rand(99).even?
changeset.comments = Faker::Lorem.words(8).join(' ') if rand(99).even?
changeset.save!
end
end
end
def add_time_entries(work_package)
5.times do |time_entry_count|
time_entry = TimeEntry.create(
project:,
user:,
work_package:,
spent_on: Date.today + time_entry_count,
activity: time_entry_activities.sample,
hours: time_entry_count
)
work_package.time_entries << time_entry
end
end
def add_attachments(work_package)
3.times do |_attachment_count|
file = OpenProject::Files.create_uploaded_file(name: Faker::Lorem.words(8).join(' '))
attachment = Attachment.new(
container: work_package,
author: user,
file:
)
attachment.save!
work_package.attachments << attachment
end
end
def add_custom_values(work_package)
project.work_package_custom_fields.each do |custom_field|
work_package.type.custom_fields << custom_field if !work_package.type.custom_fields.include?(custom_field)
work_package.custom_values << CustomValue.new(custom_field:,
value: Faker::Lorem.words(8).join(' '))
end
work_package.type.save!
work_package.save!
end
def make_changes(work_package)
20.times do
print_status '.'
work_package.reload
work_package.status = statuses.sample if rand(99).even?
work_package.subject = Faker::Lorem.words(8).join(' ') if rand(99).even?
work_package.description = Faker::Lorem.paragraph(5, true, 3) if rand(99).even?
work_package.type = types.sample if rand(99).even?
work_package.time_entries.each do |t|
t.spent_on = Date.today + rand(100) if rand(99).even?
t.activity = time_entry_activities.sample if rand(99).even?
t.hours = rand(10) if rand(99).even?
end
work_package.reload
attachments = work_package.attachments.select { |_a| rand(999) < 10 }
work_package.attachments = work_package.attachments - attachments
work_package.reload
work_package.custom_values.each do |cv|
cv.value = Faker::Code.isbn if rand(99).even?
end
work_package.save!
end
end
end
end

@ -1,55 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
class RandomDataSeeder
def self.seed!
puts ' ########################################################'
puts ' # WARNING: THIS DELETES ANY DEMO DATA THAT WAS SEEDED #'
puts ' ########################################################'
project = DemoData::ProjectSeeder.seed!
DemoData::CustomFieldSeeder.seed!(project)
RandomData::ForumSeeder.seed!(project)
RandomData::NewsSeeder.seed!(project)
RandomData::WikiSeeder.seed!(project)
RandomData::WorkPackageSeeder.new(project).seed!
puts "\n\n"
puts ' ################################'
puts ' # Random seeding....done #'
puts ' ################################'
puts " # %02d %-23s #" % [WorkPackage.where(project_id: project.id).count, 'issues created.']
puts " # %02d %-23s #" % [Message.joins(:board).where(boards: { project_id: project.id }).count, 'messages created.']
puts " # %02d %-23s #" % [News.where(project_id: project.id).count, 'news created.']
puts " # %02d %-23s #" % [WikiContent.joins(page: [:wiki]).where('wikis.project_id = ?', project.id).count,
'wiki contents created.']
puts " # %02d %-23s #" % [TimeEntry.where(project_id: project.id).count, 'time entries created.']
puts " # %02d %-23s #" % [Changeset.joins(:repository).where(repositories: { project_id: project.id }).count,
'changesets created.']
puts " ################################\n\n"
end
end

@ -88,7 +88,10 @@ class RootSeeder < Seeder
##
# Clears some schema caches and column information.
def reset_active_record!
ActiveRecord::Base.descendants.each do |klass|
ActiveRecord::Base
.descendants
.reject(&:abstract_class?)
.each do |klass|
klass.connection.schema_cache.clear!
klass.reset_column_information
end

@ -27,7 +27,7 @@
#++
module BaseServices
class Copy < ::BaseServices::BaseContracted
class Copy < ::BaseServices::Write
alias_attribute(:source, :model)
##
@ -39,7 +39,9 @@ module BaseServices
##
# collect copyable associated modules
def self.copyable_dependencies
copy_dependencies.map do |service_cls|
copy_dependencies
.flat_map { |dependency| [dependency] + dependency.copy_dependencies }
.map do |service_cls|
{
identifier: service_cls.identifier,
name_source: -> { service_cls.human_name },
@ -61,33 +63,30 @@ module BaseServices
end
def call(params)
User.execute_as(user) do
prepare(params)
perform(params)
end
end
prepare_state(params)
def after_validate(params, _call)
# Initialize the target resource to copy into
call = initialize_copy(source, params)
super
end
def persist(call)
# Return only the unsaved copy
return call if params[:attributes_only]
# Try to save the result or return its errors
copy_instance = call.result
unless copy_instance.save
return ServiceResult.failure(result: copy_instance, errors: copy_instance.errors)
end
self.class.copy_dependencies.each do |service_cls|
next if skip_dependency?(params, service_cls)
super.tap do |super_call|
copy_instance = super_call.result
self.class.copy_dependencies.each do |service_cls|
next if skip_dependency?(params, service_cls)
call.merge! call_dependent_service(service_cls, target: copy_instance, params:),
without_success: true
super_call.merge! call_dependent_service(service_cls, target: copy_instance, params:),
without_success: true
end
end
end
def after_perform(call)
return call if params[:attributes_only]
call
super
end
protected
@ -110,7 +109,7 @@ module BaseServices
#
# Note that for dependent copy services to be called
# this will already be present.
def prepare(_params)
def prepare_state(_params)
# Retain the source project itself
state.source = source
end
@ -124,8 +123,8 @@ module BaseServices
.call(params:)
end
def initialize_copy(source, params)
raise NotImplementedError
def instance(_params)
source.class.new
end
def default_contract_class

@ -47,6 +47,13 @@ module Copy
identifier.capitalize
end
##
# Dependencies the current dependency itself supports.
# The most common case for this are attachment services.
def self.copy_dependencies
[]
end
def initialize(source:, target:, user:)
@source = source
@target = target

@ -51,14 +51,8 @@ module Grids
protected
def initialize_copy(source, params)
grid = source.dup
initialize_new_grid! grid, source, params
ServiceResult.new success: grid.save, result: grid
def set_attributes_params(_params)
source.dup.attributes
end
def initialize_new_grid!(_new_grid, _original_grid, _params); end
end
end

@ -141,13 +141,13 @@ class Notifications::CreateFromModelService
def settings_of_assigned
project_applicable_settings(User.where(id: group_or_user_ids(journal.data.assigned_to)),
project,
NotificationSetting::INVOLVED)
NotificationSetting::ASSIGNEE)
end
def settings_of_responsible
project_applicable_settings(User.where(id: group_or_user_ids(journal.data.responsible)),
project,
NotificationSetting::INVOLVED)
NotificationSetting::RESPONSIBLE)
end
def settings_of_subscribed

@ -0,0 +1,57 @@
# OpenProject is an open source project management software.
# Copyright (C) 2010-2022 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module Projects::Copy
# Can be included in case the dependent service needs to be listed in the copy_dependency section for:
# * Being an option in the UI
# * Calculating the count
# but does not really need to do anything beyond that.
#
# This is currently employed to turn the attachment dependent services into NoCreate services as attachment
# handling has been moved into the create services e.g. of WorkPackage and WikiPage.
module AttachmentCopier
extend ActiveSupport::Concern
class_methods do
def attachment_dependent_service(service_const = nil)
@attachment_dependent_service = service_const if service_const
@attachment_dependent_service
end
def copy_dependencies
super + [attachment_dependent_service]
end
end
protected
def copy_attachments?
(params.dig(:params, :only) || [])
.any? { |k| k.to_s == self.class.attachment_dependent_service.identifier }
end
end
end

@ -29,7 +29,7 @@
module Projects::Copy
class CategoriesDependentService < Dependency
def self.human_name
I18n.t(:label_work_package_category_plural)
I18n.t(:'projects.copy.work_package_categories')
end
def source_count

@ -41,7 +41,7 @@ module Projects::Copy
# Check whether this dependency should be copied
# as it was selected
def self.should_copy?(params, check)
return true unless params[:only].present?
return true if params[:only].blank?
params[:only].any? { |key| key.to_sym == check }
end

@ -29,7 +29,7 @@
module Projects::Copy
class MembersDependentService < Dependency
def self.human_name
I18n.t(:label_member_plural)
I18n.t(:'projects.copy.members')
end
def source_count

@ -0,0 +1,42 @@
# OpenProject is an open source project management software.
# Copyright (C) 2010-2022 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
module Projects::Copy
# Can be included in case the dependent service needs to be listed in the copy_dependency section for:
# * Being an option in the UI
# * Calculating the count
# but does not really need to do anything beyond that.
#
# This is currently employed to turn the attachment dependent services into NoCreate services as attachment
# handling has been moved into the create services e.g. of WorkPackage and WikiPage.
module NoCopier
protected
def copy_dependency(params:)
# Not actually doing any copying.
end
end
end

@ -29,7 +29,7 @@
module Projects::Copy
class OverviewDependentService < Dependency
def self.human_name
I18n.t(:'overviews.label')
I18n.t(:'projects.copy.overviews')
end
protected

@ -29,7 +29,7 @@
module Projects::Copy
class QueriesDependentService < Dependency
def self.human_name
I18n.t(:label_query_plural)
I18n.t(:'projects.copy.queries')
end
def source_count

@ -28,6 +28,10 @@
module Projects::Copy
class WikiDependentService < Dependency
include AttachmentCopier
attachment_dependent_service ::Projects::Copy::WikiPageAttachmentsDependentService
def self.human_name
I18n.t(:label_wiki_page_plural)
end
@ -74,7 +78,8 @@ module Projects::Copy
.new(user:, model: source_page, contract_class: WikiPages::CopyContract)
.call(wiki: target.wiki,
parent_id: new_parent_id,
send_notifications: ActionMailer::Base.perform_deliveries)
send_notifications: ActionMailer::Base.perform_deliveries,
copy_attachments: copy_attachments?)
if service_call.success?
service_call.result

@ -28,25 +28,14 @@
module Projects::Copy
class WikiPageAttachmentsDependentService < Dependency
include ::Copy::Concerns::CopyAttachments
include ::Projects::Copy::NoCopier
def self.human_name
I18n.t(:label_wiki_page_attachments)
I18n.t(:'projects.copy.wiki_page_attachments')
end
def source_count
source.wiki && source.wiki.pages.joins(:attachments).count('attachments.id')
end
protected
def copy_dependency(params:)
# If no wiki pages copied, we cannot copy their attachments
return unless state.wiki_page_id_lookup
state.wiki_page_id_lookup.each do |old_id, new_id|
copy_attachments('WikiPage', from_id: old_id, to_id: new_id)
end
end
end
end

@ -1,6 +1,6 @@
#-- copyright
#--copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
# Copyright (C) 2010-2022 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.
@ -28,25 +28,14 @@
module Projects::Copy
class WorkPackageAttachmentsDependentService < Dependency
include ::Copy::Concerns::CopyAttachments
include ::Projects::Copy::NoCopier
def self.human_name
I18n.t(:label_work_package_attachments)
I18n.t(:'projects.copy.work_package_attachments')
end
def source_count
source.work_packages.joins(:attachments).count('attachments.id')
end
protected
def copy_dependency(params:)
# If no work packages were copied, we cannot copy their attachments
return unless state.work_package_id_lookup
state.work_package_id_lookup.each do |old_wp_id, new_wp_id|
copy_attachments('WorkPackage', from_id: old_wp_id, to_id: new_wp_id)
end
end
end
end

@ -28,6 +28,10 @@
module Projects::Copy
class WorkPackagesDependentService < Dependency
include AttachmentCopier
attachment_dependent_service ::Projects::Copy::WorkPackageAttachmentsDependentService
def self.human_name
I18n.t(:label_work_package_plural)
end
@ -39,37 +43,39 @@ module Projects::Copy
protected
def copy_dependency(params:)
to_copy = source_work_packages
# Stores the source work_package id as a key and the copied work package ID as the
# value. Used to map the two together for work_package relations.
work_packages_map = {}
# value. Used to map the two together for work_package relations.
work_packages_map = copy_work_packages(to_copy)
# Relations after in case copied work_packages are related to each other.
copy_work_packages_relations(to_copy, work_packages_map)
state.work_package_id_lookup = work_packages_map
end
# Get work_packages sorted by their depth in the hierarchy tree
# so that parents get copied before their children.
to_copy = source
# Get work_packages sorted by their depth in the hierarchy tree
# so that parents get copied before their children.
def source_work_packages
source
.work_packages
.includes(:custom_values, :version, :assigned_to, :responsible)
.order_by_ancestors('asc')
.order('id ASC')
end
def copy_work_packages(to_copy)
user_cf_ids = WorkPackageCustomField.where(field_format: 'user').pluck(:id)
to_copy.each do |wp|
to_copy.inject({}) do |work_packages_map, wp|
parent_id = work_packages_map[wp.parent_id] || wp.parent_id
new_wp = copy_work_package(wp, parent_id, user_cf_ids)
work_packages_map[wp.id] = new_wp.id if new_wp
end
# Relations and attachments after in case work_packages related each other
to_copy.each do |wp|
new_wp_id = work_packages_map[wp.id]
next unless new_wp_id
copy_relations(wp, new_wp_id, work_packages_map)
work_packages_map
end
state.work_package_id_lookup = work_packages_map
end
def copy_work_package(source_work_package, parent_id, user_cf_ids)
@ -79,7 +85,7 @@ module Projects::Copy
.new(user:,
work_package: source_work_package,
contract_class: WorkPackages::CopyProjectContract)
.call(**overrides)
.call(copy_attachments: copy_attachments?, **overrides)
if service_call.success?
service_call.result
@ -94,6 +100,15 @@ module Projects::Copy
end
end
def copy_work_packages_relations(to_copy, work_packages_map)
to_copy.each do |wp|
new_wp_id = work_packages_map[wp.id]
next unless new_wp_id
copy_relations(wp, new_wp_id, work_packages_map)
end
end
def copy_relations(source_wp, new_wp_id, work_packages_map)
Relation.of_work_package(source_wp).each do |source_relation|
from_id, to_id = relations_from_to(source_relation, source_wp, new_wp_id, work_packages_map)

@ -36,9 +36,7 @@ module Projects
::Projects::Copy::VersionsDependentService,
::Projects::Copy::CategoriesDependentService,
::Projects::Copy::WorkPackagesDependentService,
::Projects::Copy::WorkPackageAttachmentsDependentService,
::Projects::Copy::WikiDependentService,
::Projects::Copy::WikiPageAttachmentsDependentService,
::Projects::Copy::ForumsDependentService,
::Projects::Copy::QueriesDependentService,
::Projects::Copy::BoardsDependentService,
@ -57,70 +55,86 @@ module Projects
!Copy::Dependency.should_copy?(params, dependency_cls.identifier.to_sym)
end
def initialize_copy(source, params)
target = Project.new
def set_attributes_params(_params)
attributes = source_attributes.merge(
# Clear enabled modules
enabled_module_names: source_enabled_modules,
types: source_types,
work_package_custom_fields: source_custom_fields,
target.attributes = source.attributes.dup.except(*skipped_attributes)
# Clear enabled modules
target.enabled_modules = []
target.enabled_module_names = source.enabled_module_names - %w[repository]
target.types = source.types
target.work_package_custom_fields = source.work_package_custom_fields
# Copy status object
target.status = source.status&.dup
# Take over the CF values for attributes
target.custom_field_values = source.custom_value_attributes
# Additional input target params
target_project_params = params[:target_project_params].with_indifferent_access
cleanup_target_project_params(source, target, target_project_params)
cleanup_target_project_attributes(source, target, target_project_params)
# Copy status object
status: source_status
)
# Assign additional params from user
call = Projects::SetAttributesService
.new(user:,
model: target,
contract_class: Projects::CopyContract,
contract_options: { copy_source: source, validate_model: true })
.with_state(state)
.call(target_project_params)
only_allowed_parent_id(attributes)
.merge(source_custom_field_attributes)
.merge(target_project_params)
end
# Retain values after the set attributes service
retain_attributes(source, target, target_project_params)
def before_perform(params, service_call)
super.tap do |super_call|
# Retain values after the set attributes service
retain_attributes(source, super_call.result)
# Retain the project in the state for other dependent
# copy services to use
state.project = target
# Retain the project in the state for other dependent
# copy services to use
state.project = super_call.result
end
end
call
def contract_options
{ copy_source: source, validate_model: true }
end
def retain_attributes(source, target, target_project_params)
def retain_attributes(source, target)
# Ensure we keep the public value of the source project
# which might get overridden by the SetAttributesService
# unless the user provided a different value
target.public = source.public unless target_project_params.key?(:public)
end
def cleanup_target_project_params(_source, _target, target_project_params)
if (parent_id = target_project_params[:parent_id]) && (parent = Project.find_by(id: parent_id)) && !user.allowed_to?(
:add_subprojects, parent
)
target_project_params.delete(:parent_id)
end
def skipped_attributes
%w[id created_at updated_at name identifier active templated lft rgt]
end
def cleanup_target_project_attributes(_source, target, _target_project_params)
if target.parent && !user.allowed_to?(:add_subprojects, target.parent)
target.parent = nil
end
def source_attributes
source.attributes.dup.except(*skipped_attributes).with_indifferent_access
end
def skipped_attributes
%w[id created_at updated_at name identifier active templated lft rgt]
def source_enabled_modules
source.enabled_module_names - %w[repository]
end
def source_status
source.status&.attributes
end
def source_types
source.types
end
def source_custom_fields
source.work_package_custom_fields
end
def source_custom_field_attributes
source
.custom_value_attributes
.transform_keys { |key| "custom_field_#{key}" }
end
# Additional input target params
def target_project_params
params[:target_project_params].with_indifferent_access
end
def only_allowed_parent_id(attributes)
if (parent_id = attributes[:parent_id]) && (parent = Project.find_by(id: parent_id)) &&
!user.allowed_to?(:add_subprojects, parent)
attributes.except(:parent_id)
else
attributes
end
end
end
end

@ -37,16 +37,19 @@ module Queries
protected
def initialize_copy(source, _params)
new_query = ::Query.new source.attributes.dup.except(*skipped_attributes)
def set_attributes(_params)
new_query = copied_query
new_query.sort_criteria = source.sort_criteria if source.sort_criteria
new_query.project = state.project || source.project
::Queries::Copy::FiltersMapper
.new(state, new_query.filters)
.map_filters!
ServiceResult.new(success: new_query.save, result: new_query)
ServiceResult.new(success: new_query.valid?, result: new_query)
end
def copied_query
::Query.new source.attributes.dup.except(*skipped_attributes).merge(project: state.project || source.project)
end
def skipped_attributes

@ -90,7 +90,8 @@ module UserPreferences
conflict_target:,
index_predicate:,
columns: %i[watched
involved
assignee
responsible
mentioned
work_package_commented
work_package_created

@ -62,7 +62,7 @@ module Users
end
def initialize_notification_settings
model.notification_settings.build(involved: true, mentioned: true, watched: true)
model.notification_settings.build(assignee: true, responsible: true, mentioned: true, watched: true)
end
# rubocop:disable Metrics/AbcSize

@ -29,6 +29,7 @@
class WikiPages::CopyService
include ::Shared::ServiceContext
include Contracted
include ::Copy::Concerns::CopyAttachments
attr_accessor :user,
:model,
@ -40,18 +41,21 @@ class WikiPages::CopyService
self.contract_class = contract_class
end
def call(send_notifications: true, **attributes)
def call(send_notifications: true, copy_attachments: true, **attributes)
in_context(model, send_notifications) do
copy(attributes)
copy(attributes, copy_attachments)
end
end
protected
def copy(attribute_override)
def copy(attribute_override, copy_attachments)
attributes = copied_attributes(attribute_override)
create(attributes)
.on_success do |call|
copy_wiki_page_attachments(call.result) if copy_attachments
end
end
def create(attributes)
@ -74,4 +78,8 @@ class WikiPages::CopyService
instantiate_contract(model, user)
.writable_attributes
end
def copy_wiki_page_attachments(copy)
copy_attachments('WikiPage', from_id: model.id, to_id: copy.id)
end
end

@ -29,6 +29,7 @@
class WorkPackages::CopyService
include ::Shared::ServiceContext
include Contracted
include ::Copy::Concerns::CopyAttachments
attr_accessor :user,
:work_package,
@ -40,34 +41,34 @@ class WorkPackages::CopyService
self.contract_class = contract_class
end
def call(send_notifications: true, **attributes)
def call(send_notifications: true, copy_attachments: true, **attributes)
in_context(work_package, send_notifications) do
copy(attributes, send_notifications)
copy(attributes, copy_attachments, send_notifications)
end
end
protected
def copy(attribute_override, send_notifications)
attributes = copied_attributes(work_package, attribute_override)
copied = create(attributes, send_notifications)
if copied.success?
remove_author_watcher(copied.result)
copy_watchers(copied.result)
end
def copy(attribute_override, copy_attachments, send_notifications)
copied = create(work_package,
attribute_override,
send_notifications)
.on_success do |copy_call|
remove_author_watcher(copy_call.result)
copy_watchers(copy_call.result)
copy_work_package_attachments(copy_call.result) if copy_attachments
end
copied.state.copied_from_work_package_id = work_package&.id
copied
end
def create(attributes, send_notifications)
def create(work_package, attribute_overrides, send_notifications)
WorkPackages::CreateService
.new(user:,
contract_class:)
.call(**attributes.merge(send_notifications:).symbolize_keys)
.call(**copied_attributes(work_package, attribute_overrides).merge(send_notifications:).symbolize_keys)
end
def copied_attributes(work_package, override)
@ -102,4 +103,8 @@ class WorkPackages::CopyService
copied.add_watcher(user) if user.active?
end
end
def copy_work_package_attachments(copy)
copy_attachments('WorkPackage', from_id: work_package.id, to_id: copy.id)
end
end

@ -93,6 +93,8 @@ class WorkPackages::ScheduleDependency
end
def descendants(work_package)
# Avoid using WorkPackage.with_ancestors to save database requests.
# All needed data is already loaded.
@descendants ||= {}
@descendants[work_package] ||= begin
children = children_by_parent_id(work_package.id)
@ -101,15 +103,14 @@ class WorkPackages::ScheduleDependency
end
end
# Get relations of type follows for which the given work package is a direct
# follower, or an indirect follower (through parent and/or children).
#
# Used by +Dependency#dependent_ids+ to get work packages that must be
# scheduled prior to the given work package.
def follows_relations(work_package)
@follows_relations ||= {}
@follows_relations[work_package] ||= begin
line = [work_package] + ancestors(work_package) + descendants(work_package)
@follows_relations_by_from_id ||= known_follows_relations.group_by(&:from_id)
@follows_relations_by_from_id
.fetch_values(*line.map(&:id)) { [] }
.flatten
end
@follows_relations[work_package] ||= all_direct_and_indirect_follows_relations_for(work_package)
end
private
@ -117,6 +118,18 @@ class WorkPackages::ScheduleDependency
attr_accessor :known_follows_relations,
:moved_work_packages
def all_direct_and_indirect_follows_relations_for(work_package)
family = ancestors(work_package) + [work_package] + descendants(work_package)
follows_relations_by_follower_id
.fetch_values(*family.pluck(:id)) { [] }
.flatten
.uniq
end
def follows_relations_by_follower_id
@follows_relations_by_follower_id ||= known_follows_relations.group_by(&:from_id)
end
def create_dependencies
moving_work_packages.index_with { |work_package| Dependency.new(work_package, self) }
end
@ -168,6 +181,7 @@ class WorkPackages::ScheduleDependency
WorkPackage
.with_ancestor(known_work_packages)
.where.not(id: known_work_packages.map(&:id))
.distinct
end
# Load all the predecessors of follows relations that are not already loaded.

@ -34,7 +34,6 @@ See COPYRIGHT and LICENSE files for more details.
</div>
<div class="spot-divider"></div>
<div class="onboarding--main spot-modal--body spot-container">
<h2><%= I18n.t('onboarding.heading_getting_started') %></h2>
<div class="onboarding--video-block">
<div class="onboarding--video-text">
<span><%= I18n.t('onboarding.text_getting_started_description') %></span>

@ -46,4 +46,13 @@ See COPYRIGHT and LICENSE files for more details.
<% end %>
</ul>
</div>
<div class="spot-action-bar hidden-for-mobile">
<div class="spot-action-bar--right">
<button
class="button button_no-margin spot-modal--cancel-button spot-action-bar--action"
dynamic-content-modal-close-button
title=<%= t(:button_cancel) %>
><%= t(:button_cancel) %></button>
</div>
</div>
</div>

@ -249,23 +249,30 @@ class BackupJob < ::ApplicationJob
end
def pg_env
config = ActiveRecord::Base.connection_db_config.configuration_hash
entries = pg_env_to_connection_config.map do |key, config_key|
value = config[config_key].to_s
possible_keys = Array(config_key)
value = possible_keys
.lazy
.filter_map { |key| database_config[key] }
.first
[key.to_s, value] if value.present?
[key.to_s, value.to_s] if value.present?
end
entries.compact.to_h
end
def database_config
@database_config ||= ActiveRecord::Base.connection_db_config.configuration_hash
end
##
# Maps the PG env variable name to the key in the AR connection config.
def pg_env_to_connection_config
{
PGHOST: :host,
PGPORT: :port,
PGUSER: :username,
PGUSER: %i[username user],
PGPASSWORD: :password,
PGDATABASE: :database
}

@ -210,6 +210,15 @@ af:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ af:
label_wiki_start: "Begin bladsy"
label_work_package: "Werkspakket"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Nuwe kategorie"
label_work_package_category_plural: "Werkspakket kategorieë"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ ar:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1986,7 +1995,6 @@ ar:
label_wiki_start: "صفحة البداية"
label_work_package: "مجموعة العمل"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "فئة جديدة"
label_work_package_category_plural: "فئات مجموعة العمل"
label_work_package_hierarchy: "التسلسل الهرمي لمجموعة العمل"

@ -210,6 +210,15 @@ az:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ az:
label_wiki_start: "Start page"
label_work_package: "Work package"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ bg:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Изтриването е планирано и се извършва във фонов режим. Ще бъдете уведомени за резултата."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ bg:
label_wiki_start: "Начална страница"
label_work_package: "Работен пакет"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Нова категория"
label_work_package_category_plural: "Категории работни пакети"
label_work_package_hierarchy: "Work package hierarchy"

@ -207,6 +207,15 @@ ca:
ignore_filenames: >
Especifica una llista de noms per a ignorar quan es processin adjuncions per a correus electrònics entrants (p.e. signatures o icones). Introduïu un nom de fitxer per línia.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Membres del projecte'
overviews: 'Visió general del projecte'
queries: 'Paquets de treball: vistes guardades'
wiki_page_attachments: 'Pàgines wiki: fitxers adjunts'
work_package_attachments: 'Paquets de treball: fitxers adjunts'
work_package_categories: 'Paquets de treball: categories'
work_package_file_links: 'Paquets de treball: enllaços de fitxers'
delete:
scheduled: "L'eliminació s'ha planificat i s'efectuarà de fons. Sereu notificats del resultat."
schedule_failed: "El projecte no es pot eliminar: %{errors}"
@ -1915,7 +1924,6 @@ ca:
label_wiki_start: "Pàgina d'inici"
label_work_package: "Paquet de treball"
label_work_package_attachments: "Fitxers adjunts del paquet de treball"
label_work_package_file_link_plural: "Enllaços de fitxer del paquet de treball"
label_work_package_category_new: "Nova categoria"
label_work_package_category_plural: "Categories de paquet de treball"
label_work_package_hierarchy: "Jerarquia del paquet de treball"

@ -210,6 +210,15 @@ ckb-IR:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ ckb-IR:
label_wiki_start: "Start page"
label_work_package: "Work package"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ cs:
ignore_filenames: >
Zadejte seznam názvů, které budou ignorovány při zpracování příloh pro příchozí poštu (např. podpisy nebo ikony). Zadejte jeden název souboru na řádek.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Odstranění bylo naplánováno a je dokončeno na pozadí. Výsledek vám bude oznámen."
schedule_failed: "Projekt nelze odstranit: %{errors}"
@ -1953,7 +1962,6 @@ cs:
label_wiki_start: "Úvodní stránka"
label_work_package: "Pracovní balíček"
label_work_package_attachments: "Přílohy pracovních balíčků"
label_work_package_file_link_plural: "Odkazy na souborů pracovních balíčků"
label_work_package_category_new: "Nová kategorie"
label_work_package_category_plural: "Kategorie pracovních balíčků"
label_work_package_hierarchy: "Hierarchie pracovních balíčků"

@ -208,6 +208,15 @@ da:
ignore_filenames: >
Angiv en liste over navne der skal ignoreres ved behandling af vedhæftede filer for indgående breve (f.eks. signaturer eller ikoner). Indtast et filnavn pr. linje.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Sletning er skemalagt og udføres i baggrunden. Du får besked om resultatet."
schedule_failed: "Projektet kan ikke slettes: %{errors}"
@ -1917,7 +1926,6 @@ da:
label_wiki_start: "Startside"
label_work_package: "Arbejdspakke"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Ny kategori"
label_work_package_category_plural: "Kategorier for arbejdspakker"
label_work_package_hierarchy: "Work package hierarchy"

@ -207,6 +207,15 @@ de:
ignore_filenames: >
Geben Sie eine Liste von Dateinamen an, die beim Verarbeiten von Anhängen für eingehende Mails (z.B. Signaturen oder Symbole) ignoriert werden sollen. Geben Sie einen Dateinamen pro Zeile ein.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Die Löschung wurde geplant und wird im Hintergrund durchgeführt. Sie werden über das Ergebnis informiert."
schedule_failed: "Projekt kann nicht gelöscht werden: %{errors}"
@ -1914,7 +1923,6 @@ de:
label_wiki_start: "Hauptseite"
label_work_package: "Arbeitspaket"
label_work_package_attachments: "Anhänge des Arbeitspakets"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Neue Kategorie"
label_work_package_category_plural: "Arbeitspaket-Kategorien"
label_work_package_hierarchy: "Arbeitspakethierarchie"
@ -1930,7 +1938,7 @@ de:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Zusammenfassung"
label_working_days: "Working days"
label_working_days: "Werktage"
label_x_closed_work_packages_abbr:
one: "1 geschlossen"
other: "%{count} geschlossen"

@ -206,6 +206,15 @@ el:
ignore_filenames: >
Καθορίστε μια λίστα με τα ονόματα που πρέπει να αγνοήσετε όταν επεξεργάζεστε συνημμένα για εισερχόμενα email (π.χ. υπογραφές ή εικονίδια). Εισάγετε ένα όνομα αρχείου ανά γραμμή.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Η διαγραφή έχει προγραμματιστεί και εκτελείται στο παρασκήνιο. Θα ειδοποιηθείτε για το αποτέλεσμα."
schedule_failed: "Το έργο δεν μπορεί να διαγραφεί: %{errors}"
@ -1915,7 +1924,6 @@ el:
label_wiki_start: "Σελίδα έναρξης"
label_work_package: "Εργασία"
label_work_package_attachments: "Συνημμένα πακέτου εργασίας"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Νέα κατηγορία"
label_work_package_category_plural: "Κατηγορίες πακέτου εργασίας"
label_work_package_hierarchy: "Ιεραρχία πακέτου εργασίας"

@ -210,6 +210,15 @@ eo:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "La projekto ne povas esti forigita: %{errors}"
@ -1919,7 +1928,6 @@ eo:
label_wiki_start: "Start page"
label_work_package: "Laborpakaĵo"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"

@ -207,6 +207,15 @@ es:
ignore_filenames: >
Especifica una lista de nombres a ignorar al procesar archivos adjuntos de emails entrantes (por ejemplo, firmas o iconos). Introduce un nombre de archivo por línea.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Miembros del proyecto'
overviews: 'Visión general del proyecto'
queries: 'Paquetes de trabajo: vistas guardadas'
wiki_page_attachments: 'Páginas wiki: archivos adjuntos'
work_package_attachments: 'Paquetes de trabajo: archivos adjuntos'
work_package_categories: 'Paquetes de trabajo: categorías'
work_package_file_links: 'Paquetes de trabajo: enlaces de archivos'
delete:
scheduled: "Se ha programado la eliminación y se ejecutará en segundo plano. Recibirá una notificación con el resultado."
schedule_failed: "El proyecto no puede ser eliminado: %{errors}"
@ -1916,7 +1925,6 @@ es:
label_wiki_start: "Página de inicio"
label_work_package: "Paquete de trabajo"
label_work_package_attachments: "Datos adjuntos de paquete de trabajo"
label_work_package_file_link_plural: "Enlaces de archivo de paquete de trabajo"
label_work_package_category_new: "Nueva categoría"
label_work_package_category_plural: "Categorías de paquete de trabajo"
label_work_package_hierarchy: "Jerarquía del paquete de trabajo"

@ -210,6 +210,15 @@ et:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ et:
label_wiki_start: "Esileht"
label_work_package: "Teema"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Uus kategooria"
label_work_package_category_plural: "Teema kategooriad"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ fa:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ fa:
label_wiki_start: "صفحهی شروع"
label_work_package: "Work package"
label_work_package_attachments: "پیوست بسته کاری"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ fi:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ fi:
label_wiki_start: "Aloitussivu"
label_work_package: "Työpaketti"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Uusi luokka"
label_work_package_category_plural: "Kategoriat"
label_work_package_hierarchy: "Tehtävähierarkia"

@ -210,6 +210,15 @@ fil:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1919,7 +1928,6 @@ fil:
label_wiki_start: "Simulan ang pahina"
label_work_package: "Work package"
label_work_package_attachments: "Nakakalakip na pahinag trabaho"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Bagong kategorya"
label_work_package_category_plural: "Ang mga katergorya ng work package"
label_work_package_hierarchy: "Hierarchy ng work package"

@ -210,6 +210,15 @@ fr:
ignore_filenames: >
Spécifiez une liste de noms à ignorer lors du traitement des pièces jointes aux messages entrants (par exemple, signatures ou icônes). Entrez un nom de fichier par ligne.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "La suppression a été planifiée et est effectuée en arrière-plan. Vous serez notifié du résultat."
schedule_failed: "Le projet ne peut pas être supprimé : %{errors}"
@ -532,9 +541,9 @@ fr:
end_deletion: "Fin de la suppression"
ignore_non_working_days: "Ignorer les jours non ouvrables"
include_non_working_days:
title: 'Journées de travail'
title: 'Jours ouvrés'
false: 'jours ouvrés seulement'
true: 'Inclure les jours non travaillés'
true: 'Inclure les jours non ouvrés'
parent: "Parent"
parent_issue: "Parent"
parent_work_package: "Parent"
@ -1919,7 +1928,6 @@ fr:
label_wiki_start: "Page d'accueil"
label_work_package: "Lot de travaux"
label_work_package_attachments: "Pièces jointes du lot de travaux"
label_work_package_file_link_plural: "Liens des fichiers du lot de travaux"
label_work_package_category_new: "Nouvelle catégorie"
label_work_package_category_plural: "Catégories de Lots de Travaux"
label_work_package_hierarchy: "Hiérarchie du lot de travaux"

@ -210,6 +210,15 @@ he:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1953,7 +1962,6 @@ he:
label_wiki_start: "דף פתיחה"
label_work_package: "חבילת עבודה"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "קטגוריה חדשה"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ hi:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1917,7 +1926,6 @@ hi:
label_wiki_start: "पभ पठ"
label_work_package: "कय पज"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "नई श"
label_work_package_category_plural: "कय पज शि"
label_work_package_hierarchy: "Work package hierarchy"

@ -210,6 +210,15 @@ hr:
ignore_filenames: >
Specify a list of names to ignore when processing attachments for incoming mails (e.g., signatures or icons). Enter one filename per line.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Project cannot be deleted: %{errors}"
@ -1936,7 +1945,6 @@ hr:
label_wiki_start: "Početna stranica"
label_work_package: "Radni paket"
label_work_package_attachments: "Work package attachments"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Nova kategorija"
label_work_package_category_plural: "Kategorije radnih paketa"
label_work_package_hierarchy: "Hijerarhija radnih paketa"

@ -209,6 +209,15 @@ hu:
ignore_filenames: >
Adja meg azoknak a neveknek a listáját, amelyeket figyelmen kívül kell hagyni a bejövő levelek mellékleteinek feldolgozásakor (pl. Aláírások vagy ikonok). Írjon be egy fájlnevet soronként.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "A törlés ütemezésre került, és a háttérben történik. Értesítést kap az eredményről.\n"
schedule_failed: "A projektet nem lehet törölni: %{errors}"
@ -1916,7 +1925,6 @@ hu:
label_wiki_start: "Kezdő oldal"
label_work_package: "Feladatcsoport"
label_work_package_attachments: "Munkacsomag mellékletek"
label_work_package_file_link_plural: "Munkacsomag fájlhivatkozások"
label_work_package_category_new: "Új kategória"
label_work_package_category_plural: "Munkacsomag kategóriák"
label_work_package_hierarchy: "Feladatcsoport hierarchia"

@ -207,6 +207,15 @@ id:
ignore_filenames: >
Tentukan daftar nama yang harus diabaikan ketika memproses lampiran untuk surat masuk (mis., Tanda tangan atau ikon). Masukkan satu nama file per baris.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "Deletion has been scheduled and is performed in the background. You will be notified of the result."
schedule_failed: "Proyek tidak dapat dihapus: %{errors}"
@ -1899,7 +1908,6 @@ id:
label_wiki_start: "Homepage"
label_work_package: "Paket-Penugasan"
label_work_package_attachments: "Lampiran paket kerja"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "Kategori Baru"
label_work_package_category_plural: "Kategori Paket-Penugasan"
label_work_package_hierarchy: "Work package hierarchy"

@ -207,6 +207,15 @@ it:
ignore_filenames: >
Specifica un elenco di nomi da ignorare durante l'elaborazione di allegati per posta in arrivo (ad esempio firme o icone). Immettere un nome file per riga.
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "L'eliminazione è stata programmata e verrà eseguita in background. Verrai avvisato del risultato."
schedule_failed: "Il progetto non può essere eliminato: %{errors}"
@ -1916,7 +1925,6 @@ it:
label_wiki_start: "Pagina iniziale"
label_work_package: "Macro-attività"
label_work_package_attachments: "Allegati macro-attività"
label_work_package_file_link_plural: "Collegamenti file macro-attività"
label_work_package_category_new: "Nuova categoria"
label_work_package_category_plural: "Categorie della macro-attività"
label_work_package_hierarchy: "Gerarchia Macro-attività"

@ -208,6 +208,15 @@ ja:
ignore_filenames: >
受信メールの添付ファイルを処理するとき、無視する名前の一覧を指定します (例えば、署名またはアイコン)。1 行につき 1 つのファイル名を入力してください。
projects:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Project members'
overviews: 'Project overview'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
work_package_file_links: 'Work packages: file links'
delete:
scheduled: "削除がスケジュールされ、バックグラウンドで実行されます。結果は通知されます。"
schedule_failed: "プロジェクトを削除できません: %{errors}"
@ -1898,7 +1907,6 @@ ja:
label_wiki_start: "開始ページ"
label_work_package: "ワーク パッケージ"
label_work_package_attachments: "ワークパッケージの添付ファイル"
label_work_package_file_link_plural: "Work package file links"
label_work_package_category_new: "新規カテゴリ"
label_work_package_category_plural: "ワークパッケージのカテゴリ"
label_work_package_hierarchy: "ワークパッケージの階層"

@ -551,6 +551,7 @@ af:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ af:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ ar:
all: 'الجميع'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
zero: 'and %{count} others'
one: 'and 1 other'
@ -588,9 +589,8 @@ ar:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ az:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ az:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ bg:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ bg:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ ca:
all: 'Totes'
all_title: 'Mostrar tots'
center:
label_actor_and: 'and'
and_more_users:
one: ' i 1 altre'
other: ' i %{count} altres'
@ -584,9 +585,8 @@ ca:
mentioned:
title: 'He estat @mencionat'
description: 'Rep una notificació cada vegada que algú em menciona a qualsevol lloc'
involved:
title: 'Assignat a mi o responsable'
description: 'Rep notificacions per a totes les activitats en paquets de treball pels quals soc assignat o responsable.'
assignee: 'Assignat a'
responsible: 'Responsable'
watched: 'Actualitzacions en elements observats'
work_package_commented: 'Tots els nous comentaris'
work_package_created: 'Paquets de treball nou'

@ -551,6 +551,7 @@ ckb-IR:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ ckb-IR:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ cs:
all: 'Vše'
all_title: 'Zobrazit vše'
center:
label_actor_and: 'and'
and_more_users:
one: 'a 1 další'
few: 'a %{count} dalšich'
@ -586,9 +587,8 @@ cs:
mentioned:
title: 'Jsem @zmíněn'
description: 'Dostat upozornění, kdykoli mě někdo kdekoli zmíní'
involved:
title: 'Přiřazeno mně nebo jsem Odpovědný'
description: 'Přijímat oznámení pro všechny aktivity v pracovních balíčcích, pro které jsem ŘeŠitel nebo Zodpovědný'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Aktualizace u sledovaných položek'
work_package_commented: 'Všechny nové komentáře'
work_package_created: 'Nový pracovní balíček'

@ -550,6 +550,7 @@ da:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -583,9 +584,8 @@ da:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -550,6 +550,7 @@ de:
all: 'Alle'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'und ein weiterer'
other: 'und %{count} weitere'
@ -583,9 +584,8 @@ de:
mentioned:
title: 'Wenn ich @erwähnt werde'
description: 'Jedes Mal eine Benachrichtigung erhalten, wenn ich irgendwo erwähnt werde'
involved:
title: 'Mir zugewiesen oder verantwortlich'
description: 'Benachrichtigungen für Aktivitäten auf Arbeitspaketen erhalten, wenn ich zugewiesen oder verantwortlich bin'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Aktualisierungen auf beobachteten Objekten'
work_package_commented: 'Alle neuen Kommentare'
work_package_created: 'Neue Arbeitspakete'

@ -550,6 +550,7 @@ el:
all: 'Όλα'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -583,9 +584,8 @@ el:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ eo:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ eo:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ es:
all: 'Todos'
all_title: 'Mostrar todos'
center:
label_actor_and: 'and'
and_more_users:
one: 'y 1 más'
other: 'y %{count} más'
@ -584,9 +585,8 @@ es:
mentioned:
title: 'Estoy @mencionado'
description: 'Recibir una notificación cada vez que un usuario me mencione'
involved:
title: 'Asignado a mi usuario o responsable'
description: 'Recibe notificaciones para todas las actividades relacionadas con paquetes de trabajo en los cuales mi rol es asignado/a o responsable'
assignee: 'Asignado a'
responsible: 'Responsable'
watched: 'Actualizaciones en elementos observados'
work_package_commented: 'Todos los nuevos comentarios'
work_package_created: 'Nuevos paquetes de trabajo'

@ -551,6 +551,7 @@ et:
all: 'Kõik'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ et:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ fa:
all: 'همه'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ fa:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ fi:
all: 'Kaikki'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ fi:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ fil:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ fil:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ fr:
all: 'Toutes'
all_title: 'Afficher tout'
center:
label_actor_and: 'and'
and_more_users:
one: 'et 1 autre'
other: 'et %{count} autres'
@ -584,9 +585,8 @@ fr:
mentioned:
title: 'Je suis @mentionné'
description: 'Recevoir une notification chaque fois que quelqu''un me mentionne n''importe où'
involved:
title: 'Assigné à moi ou responsable'
description: 'Recevez des notifications pour toutes les activités sur les lots de travaux qui vous ont été assignés'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Mises à jour sur les éléments surveillés'
work_package_commented: 'Tous les nouveaux commentaires'
work_package_created: 'Nouveaux lots de travaux'

@ -551,6 +551,7 @@ he:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
two: 'and %{count} others'
@ -586,9 +587,8 @@ he:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ hi:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ hi:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ hr:
all: 'Svi'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
few: 'and %{count} others'
@ -585,9 +586,8 @@ hr:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ hu:
all: 'Mind'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: "és 1 másik\n"
other: 'és %{count} egyéb'
@ -584,9 +585,8 @@ hu:
mentioned:
title: 'Megemlítettek'
description: 'Értesítés fogadása minden alkalommal, amikor bárki bárhol megemlít'
involved:
title: 'Hozzám vagy a felelőshöz rendelve'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'Új megjegyzések'
work_package_created: 'Új munkacsomagok'

@ -551,6 +551,7 @@ id:
all: 'Semua'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
other: 'and %{count} others'
no_results:
@ -583,9 +584,8 @@ id:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ it:
all: 'Tutti'
all_title: 'Mostra tutto'
center:
label_actor_and: 'and'
and_more_users:
one: 'e 1 altro'
other: 'e altri %{count}'
@ -584,9 +585,8 @@ it:
mentioned:
title: 'Ricevo una @menzione'
description: 'Ricevi una notifica ogni volta che qualcuno ti menziona ovunque'
involved:
title: 'Assegnato a me o responsabile'
description: 'Ricevi notifiche per tutte le attività sui pacchetti di lavoro di cui sei assegnatario o responsabile.'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Aggiornamenti sugli elementi osservati'
work_package_commented: 'Tutti i nuovi commenti'
work_package_created: 'Nuove macro-attività'

@ -552,6 +552,7 @@ ja:
all: '全て'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
other: 'and %{count} others'
no_results:
@ -584,9 +585,8 @@ ja:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ ko:
all: '모두'
all_title: '모두 표시'
center:
label_actor_and: 'and'
and_more_users:
other: '외 %{count}건'
no_results:
@ -583,9 +584,8 @@ ko:
mentioned:
title: '내가 @멘션되었습니다'
description: '어디에서든 누군가가 나를 멘션할 때마다 알림 받기'
involved:
title: '내게 할당되거나 내가 담당함'
description: '내게 할당되거나 내가 담당하는 작업 패키지의 모든 활동에 대한 알림을 받습니다.'
assignee: 'Assignee'
responsible: 'Accountable'
watched: '지켜보는 항목에 대한 업데이트'
work_package_commented: '모든 새로운 코멘트'
work_package_created: '새 작업 패키지'

@ -550,6 +550,7 @@ lol:
all: 'crwdns787696:0crwdne787696:0'
all_title: 'crwdns833312:0crwdne833312:0'
center:
label_actor_and: 'crwdns835484:0crwdne835484:0'
and_more_users:
one: 'crwdns787698:1crwdne787698:1'
other: 'crwdns787698:5%{count}crwdne787698:5'
@ -583,9 +584,8 @@ lol:
mentioned:
title: 'crwdns787742:0crwdne787742:0'
description: 'crwdns787744:0crwdne787744:0'
involved:
title: 'crwdns787746:0crwdne787746:0'
description: 'crwdns787748:0crwdne787748:0'
assignee: 'crwdns834614:0crwdne834614:0'
responsible: 'crwdns834616:0crwdne834616:0'
watched: 'crwdns787750:0crwdne787750:0'
work_package_commented: 'crwdns787752:0crwdne787752:0'
work_package_created: 'crwdns787754:0crwdne787754:0'

@ -551,6 +551,7 @@ lt:
all: 'Visi'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'ir dar 1'
few: 'ir dar %{count}'
@ -586,9 +587,8 @@ lt:
mentioned:
title: 'Aš @paminėtas'
description: 'Gauti pranešimą kiekvieną kartą, kai kas nors mane bet kur pamini'
involved:
title: 'Priskirta man arba atsakingas'
description: 'Gauti pranešimus apie visus veiksmus su darbų paketais, kuriuose aš arba paskirtasis, arba atsakingas'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Stebimų elementų pakeitimai'
work_package_commented: 'Visi nauji komentarai'
work_package_created: 'Nauji darbų paketai'

@ -551,6 +551,7 @@ lv:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
zero: 'and %{count} others'
one: 'and 1 other'
@ -585,9 +586,8 @@ lv:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ ne:
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@ ne:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -26,9 +26,9 @@ nl:
loading: "Laden…"
updating: "Bijwerken…"
attachments:
delete: "Delete attachment"
delete: "Bijlage verwijderen"
delete_confirmation: |
Are you sure you want to delete this file? This action is not reversible.
Weet je zeker dat je dit bestand wilt verwijderen? Deze actie is niet omkeerbaar.
draggable_hint: |
Sleep op het invoerveld naar in line afbeelding of verwijzing bijlage. Gesloten invoervelden wordt geopend terwijl u blijft slepen.
autocomplete_select:
@ -85,10 +85,10 @@ nl:
button_open_fullscreen: "Open volledig scherm"
button_show_cards: "Toon kaartweergave"
button_show_list: "Toon lijstweergave"
button_show_table: "Show table view"
button_show_gantt: "Show Gantt view"
button_show_fullscreen: "Show fullscreen view"
button_more_actions: "More actions"
button_show_table: "Tabel weergave tonen"
button_show_gantt: "Toon Gantt-weergave"
button_show_fullscreen: "Volledig scherm weergeven"
button_more_actions: "Meer acties"
button_quote: "Citeer"
button_save: "Opslaan"
button_settings: "Instellingen"
@ -301,11 +301,11 @@ nl:
standard:
learn_about_link: https://www.openproject.org/blog/openproject-12-3-release
new_features_html: >
The release contains various new features and improvements: <br> <ul class="%{list_styling_class}"> <li>Define your global work week (weekends and non-working days of the week).</li> <li>Calculate duration based on start and finish dates and the possibility to consider non-working days (weekends) in scheduling.</li> <li>Add meaningful tooltips to the most essential actions.</li> <li>Copying a project will also copy file links attached to all work packages.</li> </ul>
De release bevat verschillende nieuwe functies en verbeteringen: <br> <ul class="%{list_styling_class}"> <li>Definieer je globale werkweek (weekends en niet-werkdagen van de week).</li> <li>Bereken de duur op basis van begin- en einddatums en de mogelijkheid om niet-werkdagen (weekend) in de planning te overwegen.</li> <li>Voeg zinvolle tooltips toe aan de meest essentiële acties.</li> <li>Het kopiëren van een project zal ook bestandslinks kopiëren die zijn gekoppeld aan alle werkpakketten.</li> </ul>
bim:
learn_about_link: https://www.openproject.org/blog/openproject-12-3-release
new_features_html: >
The release contains various new features and improvements: <br> <ul class="%{list_styling_class}"> <li>Define your global work week (weekends and non-working days of the week).</li> <li>Calculate duration based on start and finish dates and the possibility to consider non-working days (weekends) in scheduling.</li> <li>Add meaningful tooltips to the most essential actions.</li> <li>Copying a project will also copy file links attached to all work packages.</li> </ul>
De release bevat verschillende nieuwe functies en verbeteringen: <br> <ul class="%{list_styling_class}"> <li>Definieer je globale werkweek (weekends en niet-werkdagen van de week).</li> <li>Bereken de duur op basis van begin- en einddatums en de mogelijkheid om niet-werkdagen (weekend) in de planning te overwegen.</li> <li>Voeg zinvolle tooltips toe aan de meest essentiële acties.</li> <li>Het kopiëren van een project zal ook bestandslinks kopiëren die zijn gekoppeld aan alle werkpakketten.</li> </ul>
label_activate: "Activeren"
label_assignee: 'Toegewezene'
label_add_column_after: "Kolom toevoegen"
@ -547,46 +547,46 @@ nl:
prioritized: 'prioriteren'
facets:
unread: 'Ongelezen'
unread_title: 'Show unread'
unread_title: 'Toon ongelezen'
all: 'Alle'
all_title: 'Show all'
all_title: 'Alles weergeven'
center:
label_actor_and: 'and'
and_more_users:
one: 'en 1 ander'
other: 'en %{count} anderen'
no_results:
at_all: 'New notifications will appear here when there is activity that concerns you, in the mean time you can also view and modify your notification settings to configure when to be notified.'
with_current_filter: 'There are no notifications in this view at the moment'
at_all: 'Nieuwe meldingen verschijnen hier wanneer er activiteit is die je aangaat, in de tussentijd kunt u ook uw meldingsinstellingen bekijken en wijzigen zodat u kunt configureren wanneer u een melding moet ontvangen.'
with_current_filter: 'Er zijn geen meldingen in deze weergave op dit moment'
mark_all_read: 'Alles als gelezen markeren'
mark_as_read: 'Als gelezen markeren'
text_update_date: "%{date} door"
total_count_warning: "De %{newest_count} meest recente meldingen weergeven. %{more_count} meer worden niet weergegeven."
empty_state:
no_notification: "Het lijkt erop dat u helemaal bij bent."
no_notification_with_current_project_filter: "Looks like you're all caught up with the selected project."
no_notification_with_current_filter: "Looks like you're all caught up for %{filter} filter."
no_notification_with_current_project_filter: "Het lijkt erop dat je allemaal bij bent met het geselecteerde project."
no_notification_with_current_filter: "Het lijkt erop dat je allemaal bij bent met %{filter} filter."
no_selection: "Klik op een melding om alle activiteit details te bekijken."
new_notifications:
message: 'There are new notifications.'
link_text: 'Click here to load them'
message: 'Er zijn nieuwe meldingen.'
link_text: 'Klik hier om ze te laden'
menu:
accountable: 'Verantwoording afleggen'
by_project: 'Unread by project'
by_reason: 'Involvement'
by_project: 'Ongelezen per project'
by_reason: 'Betrokkenheid'
inbox: 'Inkomend'
mentioned: '@vermeld'
watching: 'Bekijken'
settings:
change_notification_settings: 'To view and change your notification settings, <a target="_blank" href="%{url}">click here</a>'
change_notification_settings: 'Om je meldingen instellingen te bekijken en te wijzigen, <a target="_blank" href="%{url}">klik hier</a>'
title: "Instellingen voor meldingen"
notify_me: "Waarschuw mij"
reasons:
mentioned:
title: 'Ik ben @vermeld'
description: 'Ontvang een melding elke keer dat iemand mij ergens noemt'
involved:
title: 'Toegewezen aan mij of verantwoordelijk'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Toegewezene'
responsible: 'Accountable'
watched: 'Updates van bekeken artikelen'
work_package_commented: 'Alle nieuwe reacties'
work_package_created: 'Nieuwe werkpakketten'

@ -551,6 +551,7 @@
all: 'All'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'and 1 other'
other: 'and %{count} others'
@ -584,9 +585,8 @@
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -551,6 +551,7 @@ pl:
all: 'Wszystko'
all_title: 'Pokaż wszystkie'
center:
label_actor_and: 'and'
and_more_users:
one: 'i 1 inny'
few: 'i %{count} inne'
@ -586,9 +587,8 @@ pl:
mentioned:
title: '@wzmianka o mnie'
description: 'Otrzymuj powiadomienie za każdym razem, gdy pojawi się o tobie wzmianka gdziekolwiek'
involved:
title: 'Przypisane do mnie lub moja odpowiedzialność'
description: 'Otrzymuj powiadomienia o wszystkich czynnościach w pakietach roboczych, do których jesteś przypisany lub za które ponosisz odpowiedzialność'
assignee: 'Przypisana osoba'
responsible: 'Osoba odpowiedzialna'
watched: 'Aktualizacje obserwowanych pozycji'
work_package_commented: 'Wszystkie nowe komentarze'
work_package_created: 'Nowe pakiety robocze'

@ -550,6 +550,7 @@ pt:
all: 'Todos'
all_title: 'Mostrar todas'
center:
label_actor_and: 'and'
and_more_users:
one: 'e 1 outro'
other: 'e %{count} outros'
@ -583,9 +584,8 @@ pt:
mentioned:
title: 'Eu sou @mencionado'
description: 'Receber uma notificação sempre que alguém me mencionar'
involved:
title: 'Atribuído a mim ou responsável'
description: 'Receba notificações para todas as atividades nos pacotes de trabalho atribuídos a mim ou de minha responsabilidade'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Atualizações em itens observados'
work_package_commented: 'Todos os novos comentários'
work_package_created: 'Novos pacotes de trabalho'

@ -550,6 +550,7 @@ ro:
all: 'Toate'
all_title: 'Show all'
center:
label_actor_and: 'and'
and_more_users:
one: 'și încă unul'
few: 'și %{count} alții'
@ -584,9 +585,8 @@ ro:
mentioned:
title: 'I am @mentioned'
description: 'Receive a notification every time someone mentions me anywhere'
involved:
title: 'Assigned to me or accountable'
description: 'Receive notifications for all activities on work packages for which I am assignee or accountable'
assignee: 'Assignee'
responsible: 'Accountable'
watched: 'Updates on watched items'
work_package_commented: 'All new comments'
work_package_created: 'New work packages'

@ -550,6 +550,7 @@ ru:
all: 'Bсе'
all_title: 'Показать все'
center:
label_actor_and: 'and'
and_more_users:
one: 'и еще 1'
few: 'и %{count} других'
@ -585,9 +586,8 @@ ru:
mentioned:
title: 'Я @mentioned'
description: 'Получать уведомления каждый раз, когда кто-то упоминает меня в любом месте'
involved:
title: 'Назначен мне или подотчетен'
description: 'Получать уведомления о всех видах деятельности в пакетах работ, к которым я причастен.'
assignee: 'Назначенный'
responsible: 'Подотчетный'
watched: 'Обновления просмотренных элементов'
work_package_commented: 'Все новые комментарии'
work_package_created: 'Новые пакеты работ'
@ -1187,7 +1187,7 @@ ru:
next_button: 'Следующие'
message:
label: 'Сообщение о приглашении'
description: 'We will send an email to the user, to which you can add a personal message here. An explanation for the invitation could be useful, or prehaps a bit of information regarding the project to help them get started.'
description: 'Мы отправим пользователю электронное письмо, к которому вы можете что-нибудь добавить. Приглашение облегчит им начало работы, если у них будет немного информации о проекте.'
next_button: 'Далее'
summary:
next_button: 'Отправить приглашение'

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save