diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 07c1674cb336..de098ef7b263 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -315,7 +315,7 @@ jobs:
needs: [setup, build, merge]
permissions:
contents: none
- if: ${{ github.repository == 'opf/openproject' && inputs.tag != '' }}
+ if: ${{ github.repository == 'opf/openproject' }}
runs-on: ubuntu-latest
steps:
- name: Trigger Helm charts release
diff --git a/.github/workflows/email-notification.yml b/.github/workflows/email-notification.yml
index 9e9799ad1ff6..10f8a3cf0222 100644
--- a/.github/workflows/email-notification.yml
+++ b/.github/workflows/email-notification.yml
@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send mail
- uses: dawidd6/action-send-mail@v3
+ uses: dawidd6/action-send-mail@v4
with:
subject: ${{ inputs.subject }}
body: ${{ inputs.body }}
diff --git a/Gemfile b/Gemfile
index 5a32c7f481bd..bc673e74dcf9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,7 +36,7 @@ ruby File.read(File.expand_path(".ruby-version", __dir__)).strip
gem "actionpack-xml_parser", "~> 2.0.0"
gem "activemodel-serializers-xml", "~> 1.0.1"
-gem "activerecord-import", "~> 1.7.0"
+gem "activerecord-import", "~> 1.8.0"
gem "activerecord-session_store", "~> 2.1.0"
gem "ox"
gem "rails", "~> 7.1.3"
@@ -46,7 +46,7 @@ gem "ffi", "~> 1.15"
gem "rdoc", ">= 2.4.2"
-gem "doorkeeper", "~> 5.7.0"
+gem "doorkeeper", "~> 5.8.0"
# Maintain our own omniauth due to relative URL root issues
# see upstream PR: https://github.com/omniauth/omniauth/pull/903
gem "omniauth", git: "https://github.com/opf/omniauth", ref: "fe862f986b2e846e291784d2caa3d90a658c67f0"
@@ -93,7 +93,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", "~> 4.4.0"
+gem "rouge", "~> 4.5.1"
# HTML sanitization used for html-pipeline
gem "sanitize", "~> 6.1.0"
# HTML autolinking for mails and urls (replaces autolink)
@@ -184,7 +184,7 @@ gem "rails-i18n", "~> 7.0.0"
gem "sprockets", "~> 3.7.2" # lock sprockets below 4.0
gem "sprockets-rails", "~> 3.5.1"
-gem "puma", "~> 6.4"
+gem "puma", "~> 6.5"
gem "puma-plugin-statsd", "~> 2.0"
gem "rack-timeout", "~> 0.7.0", require: "rack/timeout/base"
@@ -218,7 +218,7 @@ gem "dry-validation"
gem "store_attribute", "~> 1.0"
# Appsignal integration
-gem "appsignal", "~> 3.10.0", require: false
+gem "appsignal", "~> 4.2", require: false
gem "view_component"
# Lookbook
@@ -247,7 +247,7 @@ group :test do
gem "rack_session_access"
gem "rspec", "~> 3.13.0"
# also add to development group, so 'spec' rake task gets loaded
- gem "rspec-rails", "~> 7.0.0", group: :development
+ gem "rspec-rails", "~> 7.1.0", group: :development
# Retry failures within the same environment
gem "retriable", "~> 3.1.1"
diff --git a/Gemfile.lock b/Gemfile.lock
index 7c59e1fb9b0a..45bcbbd02770 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -206,7 +206,7 @@ PATH
remote: modules/two_factor_authentication
specs:
openproject-two_factor_authentication (1.0.0)
- aws-sdk-sns (~> 1.88.0)
+ aws-sdk-sns (~> 1.90.0)
messagebird-rest (~> 1.4.2)
rotp (~> 6.1)
webauthn (~> 3.0)
@@ -225,36 +225,36 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- Ascii85 (1.1.1)
- actioncable (7.1.4.1)
- actionpack (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ Ascii85 (2.0.1)
+ actioncable (7.1.5)
+ actionpack (= 7.1.5)
+ activesupport (= 7.1.5)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (7.1.4.1)
- actionpack (= 7.1.4.1)
- activejob (= 7.1.4.1)
- activerecord (= 7.1.4.1)
- activestorage (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ actionmailbox (7.1.5)
+ actionpack (= 7.1.5)
+ activejob (= 7.1.5)
+ activerecord (= 7.1.5)
+ activestorage (= 7.1.5)
+ activesupport (= 7.1.5)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
- actionmailer (7.1.4.1)
- actionpack (= 7.1.4.1)
- actionview (= 7.1.4.1)
- activejob (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ actionmailer (7.1.5)
+ actionpack (= 7.1.5)
+ actionview (= 7.1.5)
+ activejob (= 7.1.5)
+ activesupport (= 7.1.5)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2)
- actionpack (7.1.4.1)
- actionview (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ actionpack (7.1.5)
+ actionview (= 7.1.5)
+ activesupport (= 7.1.5)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
@@ -265,33 +265,33 @@ GEM
actionpack-xml_parser (2.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
- actiontext (7.1.4.1)
- actionpack (= 7.1.4.1)
- activerecord (= 7.1.4.1)
- activestorage (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ actiontext (7.1.5)
+ actionpack (= 7.1.5)
+ activerecord (= 7.1.5)
+ activestorage (= 7.1.5)
+ activesupport (= 7.1.5)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (7.1.4.1)
- activesupport (= 7.1.4.1)
+ actionview (7.1.5)
+ activesupport (= 7.1.5)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- activejob (7.1.4.1)
- activesupport (= 7.1.4.1)
+ activejob (7.1.5)
+ activesupport (= 7.1.5)
globalid (>= 0.3.6)
- activemodel (7.1.4.1)
- activesupport (= 7.1.4.1)
+ activemodel (7.1.5)
+ activesupport (= 7.1.5)
activemodel-serializers-xml (1.0.3)
activemodel (>= 5.0.0.a)
activesupport (>= 5.0.0.a)
builder (~> 3.1)
- activerecord (7.1.4.1)
- activemodel (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ activerecord (7.1.5)
+ activemodel (= 7.1.5)
+ activesupport (= 7.1.5)
timeout (>= 0.4.0)
- activerecord-import (1.7.0)
+ activerecord-import (1.8.1)
activerecord (>= 4.2)
activerecord-nulldb-adapter (1.0.1)
activerecord (>= 5.2.0, < 7.2)
@@ -302,23 +302,26 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 4)
railties (>= 6.1)
- activestorage (7.1.4.1)
- actionpack (= 7.1.4.1)
- activejob (= 7.1.4.1)
- activerecord (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ activestorage (7.1.5)
+ actionpack (= 7.1.5)
+ activejob (= 7.1.5)
+ activerecord (= 7.1.5)
+ activesupport (= 7.1.5)
marcel (~> 1.0)
- activesupport (7.1.4.1)
+ activesupport (7.1.5)
base64
+ benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
+ logger (>= 1.4.2)
minitest (>= 5.1)
mutex_m
+ securerandom (>= 0.3)
tzinfo (~> 2.0)
- acts_as_list (1.2.3)
+ acts_as_list (1.2.4)
activerecord (>= 6.1)
activesupport (>= 6.1)
acts_as_tree (2.9.1)
@@ -332,7 +335,8 @@ GEM
airbrake-ruby (6.2.2)
rbtree3 (~> 0.6)
android_key_attestation (0.3.0)
- appsignal (3.10.0)
+ appsignal (4.2.0)
+ logger
rack
ast (2.4.2)
attr_required (1.0.2)
@@ -341,30 +345,30 @@ GEM
awesome_nested_set (3.7.0)
activerecord (>= 4.0.0, < 8.0)
aws-eventstream (1.3.0)
- aws-partitions (1.1001.0)
- aws-sdk-core (3.211.0)
+ aws-partitions (1.1012.0)
+ aws-sdk-core (3.212.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
- aws-sdk-kms (1.95.0)
+ aws-sdk-kms (1.96.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.170.0)
+ aws-sdk-s3 (1.173.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
- aws-sdk-sns (1.88.0)
- aws-sdk-core (~> 3, >= 3.207.0)
+ aws-sdk-sns (1.90.0)
+ aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.10.1)
aws-eventstream (~> 1, >= 1.0.2)
- axe-core-api (4.10.1)
+ axe-core-api (4.10.2)
dumb_delegator
ostruct
virtus
- axe-core-rspec (4.10.1)
- axe-core-api (= 4.10.1)
+ axe-core-rspec (4.10.2)
+ axe-core-api (= 4.10.2)
dumb_delegator
ostruct
virtus
@@ -374,6 +378,7 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.2.0)
bcrypt (3.1.20)
+ benchmark (0.4.0)
better_html (2.1.1)
actionview (>= 6.0)
activesupport (>= 6.0)
@@ -445,7 +450,7 @@ GEM
ferrum (~> 0.15.0)
daemons (1.4.1)
dalli (3.2.8)
- date (3.3.4)
+ date (3.4.0)
date_validator (0.12.0)
activemodel (>= 3)
activesupport (>= 3)
@@ -461,7 +466,7 @@ GEM
disposable (0.6.3)
declarative (>= 0.0.9, < 1.0.0)
representable (>= 3.1.1, < 4)
- doorkeeper (5.7.1)
+ doorkeeper (5.8.0)
railties (>= 5)
dotenv (3.1.4)
dotenv-rails (3.1.4)
@@ -476,8 +481,9 @@ GEM
zeitwerk (~> 2.6)
dry-container (0.11.0)
concurrent-ruby (~> 1.0)
- dry-core (1.0.1)
+ dry-core (1.0.2)
concurrent-ruby (~> 1.0)
+ logger
zeitwerk (~> 2.6)
dry-inflector (1.1.0)
dry-initializer (3.1.1)
@@ -540,7 +546,7 @@ GEM
tzinfo
eventmachine (1.2.7)
eventmachine_httpserver (0.2.1)
- excon (1.0.0)
+ excon (1.2.0)
factory_bot (6.5.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.4)
@@ -633,7 +639,7 @@ GEM
rack
gravatar_image_tag (1.2.0)
hana (1.3.7)
- hashdiff (1.1.1)
+ hashdiff (1.1.2)
hashery (2.1.2)
hashie (3.6.0)
highline (3.1.1)
@@ -644,10 +650,10 @@ GEM
htmlbeautifier (1.4.3)
htmldiff (0.0.1)
htmlentities (4.3.4)
- http-2 (1.0.1)
+ http-2 (1.0.2)
http_parser.rb (0.6.0)
httpclient (2.8.3)
- httpx (1.3.1)
+ httpx (1.3.3)
http-2 (>= 1.0.0)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
@@ -676,7 +682,7 @@ GEM
reline (>= 0.4.2)
iso8601 (0.13.0)
jmespath (1.6.2)
- json (2.7.4)
+ json (2.8.2)
json-jwt (1.16.7)
activesupport (>= 4.2)
aes_key_wrap
@@ -702,7 +708,7 @@ GEM
launchy (3.0.1)
addressable (~> 2.8)
childprocess (~> 5.0)
- lefthook (1.8.2)
+ lefthook (1.8.4)
letter_opener (1.10.0)
launchy (>= 2.2, < 4)
letter_opener_web (3.0.0)
@@ -723,7 +729,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.22.0)
+ loofah (2.23.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
lookbook (2.3.4)
@@ -753,21 +759,21 @@ GEM
mime-types (3.6.0)
logger
mime-types-data (~> 3.2015)
- mime-types-data (3.2024.1001)
+ mime-types-data (3.2024.1105)
mini_magick (5.0.1)
mini_mime (1.1.5)
- mini_portile2 (2.8.7)
+ mini_portile2 (2.8.8)
minitest (5.25.1)
- msgpack (1.7.3)
+ msgpack (1.7.5)
multi_json (1.15.0)
mustermann (3.0.3)
ruby2_keywords (~> 0.0.1)
mustermann-grape (1.1.0)
mustermann (>= 1.0.0)
- mutex_m (0.2.0)
+ mutex_m (0.3.0)
net-http (0.4.1)
uri
- net-imap (0.4.17)
+ net-imap (0.5.1)
date
net-protocol
net-ldap (0.19.0)
@@ -777,11 +783,11 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
- nio4r (2.7.3)
+ nio4r (2.7.4)
nokogiri (1.16.7)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- oj (3.16.6)
+ oj (3.16.7)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
okcomputer (1.18.5)
@@ -817,9 +823,9 @@ GEM
openssl (3.2.0)
openssl-signature_algorithm (1.3.0)
openssl (> 2.0)
- optimist (3.1.0)
+ optimist (3.2.0)
os (1.1.4)
- ostruct (0.6.0)
+ ostruct (0.6.1)
ox (2.14.18)
paper_trail (15.2.0)
activerecord (>= 6.1)
@@ -827,14 +833,14 @@ GEM
parallel (1.26.3)
parallel_tests (4.7.2)
parallel
- parser (3.3.5.0)
+ parser (3.3.6.0)
ast (~> 2.4.1)
racc
pdf-core (0.9.0)
pdf-inspector (1.3.0)
pdf-reader (>= 1.0, < 3.0.a)
- pdf-reader (2.12.0)
- Ascii85 (~> 1.0)
+ pdf-reader (2.13.0)
+ Ascii85 (>= 1.0, < 3.0, != 2.0.0)
afm (~> 0.2.1)
hashery (~> 2.0)
ruby-rc4
@@ -863,7 +869,7 @@ GEM
pry-rescue (1.6.0)
interception (>= 0.5)
pry (>= 0.12.0)
- psych (5.1.2)
+ psych (5.2.0)
stringio
public_suffix (6.0.1)
puffing-billy (4.0.0)
@@ -874,7 +880,7 @@ GEM
eventmachine_httpserver
http_parser.rb (~> 0.6.0)
multi_json
- puma (6.4.3)
+ puma (6.5.0)
nio4r (~> 2.0)
puma-plugin-statsd (2.6.0)
puma (>= 5.0, < 7)
@@ -905,23 +911,23 @@ GEM
rack_session_access (0.2.0)
builder (>= 2.0.0)
rack (>= 1.0.0)
- rackup (1.0.0)
+ rackup (1.0.1)
rack (< 3)
webrick
- rails (7.1.4.1)
- actioncable (= 7.1.4.1)
- actionmailbox (= 7.1.4.1)
- actionmailer (= 7.1.4.1)
- actionpack (= 7.1.4.1)
- actiontext (= 7.1.4.1)
- actionview (= 7.1.4.1)
- activejob (= 7.1.4.1)
- activemodel (= 7.1.4.1)
- activerecord (= 7.1.4.1)
- activestorage (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ rails (7.1.5)
+ actioncable (= 7.1.5)
+ actionmailbox (= 7.1.5)
+ actionmailer (= 7.1.5)
+ actionpack (= 7.1.5)
+ actiontext (= 7.1.5)
+ actionview (= 7.1.5)
+ activejob (= 7.1.5)
+ activemodel (= 7.1.5)
+ activerecord (= 7.1.5)
+ activestorage (= 7.1.5)
+ activesupport (= 7.1.5)
bundler (>= 1.15.0)
- railties (= 7.1.4.1)
+ railties (= 7.1.5)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@@ -933,12 +939,12 @@ GEM
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
- rails-i18n (7.0.9)
+ rails-i18n (7.0.10)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
- railties (7.1.4.1)
- actionpack (= 7.1.4.1)
- activesupport (= 7.1.4.1)
+ railties (7.1.5)
+ actionpack (= 7.1.5)
+ activesupport (= 7.1.5)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
@@ -955,7 +961,7 @@ GEM
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
rbtree3 (0.7.1)
- rdoc (6.7.0)
+ rdoc (6.8.1)
psych (>= 4.0.0)
recaptcha (5.17.0)
redcarpet (3.6.0)
@@ -964,7 +970,7 @@ GEM
redis-client (0.22.2)
connection_pool
regexp_parser (2.9.2)
- reline (0.5.10)
+ reline (0.5.11)
io-console (~> 0.5)
representable (3.2.0)
declarative (< 0.1.0)
@@ -981,7 +987,7 @@ GEM
roar (1.2.0)
representable (~> 3.1)
rotp (6.3.0)
- rouge (4.4.0)
+ rouge (4.5.1)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
@@ -994,7 +1000,7 @@ GEM
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
- rspec-rails (7.0.1)
+ rspec-rails (7.1.0)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
@@ -1007,7 +1013,7 @@ GEM
rspec-support (3.13.1)
rspec-wait (1.0.1)
rspec (>= 3.4)
- rubocop (1.67.0)
+ rubocop (1.68.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
@@ -1017,7 +1023,7 @@ GEM
rubocop-ast (>= 1.32.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
- rubocop-ast (1.32.3)
+ rubocop-ast (1.36.1)
parser (>= 3.3.1.0)
rubocop-capybara (2.21.0)
rubocop (~> 1.41)
@@ -1025,7 +1031,7 @@ GEM
rubocop (~> 1.61)
rubocop-openproject (0.2.0)
rubocop
- rubocop-performance (1.22.1)
+ rubocop-performance (1.23.0)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rails (2.27.0)
@@ -1059,7 +1065,8 @@ GEM
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
secure_headers (7.0.0)
- selenium-devtools (0.129.0)
+ securerandom (0.3.2)
+ selenium-devtools (0.130.0)
selenium-webdriver (~> 4.2)
selenium-webdriver (4.26.0)
base64 (~> 0.2)
@@ -1078,7 +1085,7 @@ GEM
multi_json (~> 1.10)
simpleidn (0.2.3)
smart_properties (1.17.0)
- spreadsheet (1.3.1)
+ spreadsheet (1.3.3)
bigdecimal
ruby-ole
spring (4.2.1)
@@ -1099,7 +1106,7 @@ GEM
store_attribute (1.3.1)
activerecord (>= 6.1)
stringex (2.8.6)
- stringio (3.1.1)
+ stringio (3.1.2)
structured_warnings (0.4.0)
svg-graph (2.2.2)
swd (2.0.3)
@@ -1117,7 +1124,7 @@ GEM
thor (1.3.2)
thread_safe (0.3.6)
timecop (0.9.10)
- timeout (0.4.1)
+ timeout (0.4.2)
tpm-key_attestation (0.12.1)
bindata (~> 2.4)
openssl (> 2.0)
@@ -1175,7 +1182,7 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
- webrick (1.8.2)
+ webrick (1.9.0)
websocket (1.2.11)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
@@ -1187,7 +1194,7 @@ GEM
xpath (3.2.0)
nokogiri (~> 1.8)
yard (0.9.37)
- zeitwerk (2.7.0)
+ zeitwerk (2.7.1)
PLATFORMS
ruby
@@ -1195,14 +1202,14 @@ PLATFORMS
DEPENDENCIES
actionpack-xml_parser (~> 2.0.0)
activemodel-serializers-xml (~> 1.0.1)
- activerecord-import (~> 1.7.0)
+ activerecord-import (~> 1.8.0)
activerecord-nulldb-adapter (~> 1.0.0)
activerecord-session_store (~> 2.1.0)
acts_as_list (~> 1.2.0)
acts_as_tree (~> 2.9.0)
addressable (~> 2.8.0)
airbrake (~> 13.0.0)
- appsignal (~> 3.10.0)
+ appsignal (~> 4.2)
auto_strip_attributes (~> 2.5)
awesome_nested_set (~> 3.7.0)
aws-sdk-core (~> 3.107)
@@ -1233,7 +1240,7 @@ DEPENDENCIES
debug
deckar01-task_list (~> 2.3.1)
disposable (~> 0.6.2)
- doorkeeper (~> 5.7.0)
+ doorkeeper (~> 5.8.0)
dotenv-rails
dry-auto_inject
dry-container
@@ -1328,7 +1335,7 @@ DEPENDENCIES
pry-rails (~> 0.3.6)
pry-rescue (~> 1.6.0)
puffing-billy (~> 4.0.0)
- puma (~> 6.4)
+ puma (~> 6.5)
puma-plugin-statsd (~> 2.0)
rack-attack (~> 6.7.0)
rack-cors (~> 2.0.2)
@@ -1348,9 +1355,9 @@ DEPENDENCIES
retriable (~> 3.1.1)
rinku (~> 2.0.4)
roar (~> 1.2.0)
- rouge (~> 4.4.0)
+ rouge (~> 4.5.1)
rspec (~> 3.13.0)
- rspec-rails (~> 7.0.0)
+ rspec-rails (~> 7.1.0)
rspec-retry (~> 0.6.1)
rspec-wait
rubocop
diff --git a/app/components/work_packages/activities_tab/index_component.html.erb b/app/components/work_packages/activities_tab/index_component.html.erb
index 6ff2baeee91c..6b4492a05afe 100644
--- a/app/components/work_packages/activities_tab/index_component.html.erb
+++ b/app/components/work_packages/activities_tab/index_component.html.erb
@@ -1,53 +1,59 @@
<%=
- content_tag("turbo-frame", id: "work-package-activities-tab-content") do
- flex_layout(classes: "work-packages-activities-tab-index-component", mb: [5, 5, 5, 5, 0]) do |activties_tab_wrapper_container|
- activties_tab_wrapper_container.with_row(classes: "work-packages-activities-tab-index-component--errors") do
- render(
- WorkPackages::ActivitiesTab::ErrorStreamComponent.new
- )
- end
- activties_tab_wrapper_container.with_row do
- component_wrapper(data: wrapper_data_attributes) do
- flex_layout do |activties_tab_container|
- activties_tab_container.with_row(mb: 2) do
- render(
- WorkPackages::ActivitiesTab::Journals::FilterAndSortingComponent.new(
- work_package:,
- filter:
- )
- )
- end
- activties_tab_container.with_row(flex_layout: true, mt: 3) do |journals_wrapper_container|
- journals_wrapper_container.with_row(
- classes: "work-packages-activities-tab-index-component--journals-container work-packages-activities-tab-index-component--journals-container_with-initial-input-compensation",
- data: { "work-packages--activities-tab--index-target": "journalsContainer" }
- ) do
+ unless deferred
+ content_tag("turbo-frame", id: "work-package-activities-tab-content") do
+ flex_layout(classes: "work-packages-activities-tab-index-component", mb: [5, 5, 5, 5, 0]) do |activties_tab_wrapper_container|
+ activties_tab_wrapper_container.with_row(classes: "work-packages-activities-tab-index-component--errors") do
+ render(
+ WorkPackages::ActivitiesTab::ErrorStreamComponent.new
+ )
+ end
+ activties_tab_wrapper_container.with_row do
+ component_wrapper(data: wrapper_data_attributes) do
+ flex_layout do |activties_tab_container|
+ activties_tab_container.with_row(mb: 2) do
render(
- WorkPackages::ActivitiesTab::Journals::IndexComponent.new(work_package:, filter:)
+ WorkPackages::ActivitiesTab::Journals::FilterAndSortingComponent.new(
+ work_package:,
+ filter:
+ )
)
end
- if adding_comment_allowed?
+ activties_tab_container.with_row(flex_layout: true, mt: 3) do |journals_wrapper_container|
journals_wrapper_container.with_row(
- classes: "work-packages-activities-tab-index-component--input-container work-packages-activities-tab-index-component--input-container_sort-#{journal_sorting}",
- mt: 3,
- mb: [3, nil, nil, nil, 0],
- pt: 2,
- pb: 2,
- pl: 3,
- pr: [3, nil, nil, nil, 2],
- border: [nil, nil, nil, nil, :top],
- border_radius: [2, nil, nil, nil, 0],
- bg: :subtle
+ classes: "work-packages-activities-tab-index-component--journals-container work-packages-activities-tab-index-component--journals-container_with-initial-input-compensation",
+ data: { "work-packages--activities-tab--index-target": "journalsContainer" }
) do
render(
- WorkPackages::ActivitiesTab::Journals::NewComponent.new(work_package:)
+ WorkPackages::ActivitiesTab::Journals::IndexComponent.new(work_package:, filter:)
)
end
+ if adding_comment_allowed?
+ journals_wrapper_container.with_row(
+ classes: "work-packages-activities-tab-index-component--input-container work-packages-activities-tab-index-component--input-container_sort-#{journal_sorting}",
+ mt: 3,
+ mb: [3, nil, nil, nil, 0],
+ pt: 2,
+ pb: 2,
+ pl: 3,
+ pr: [3, nil, nil, nil, 2],
+ border: [nil, nil, nil, nil, :top],
+ border_radius: [2, nil, nil, nil, 0],
+ bg: :subtle
+ ) do
+ render(
+ WorkPackages::ActivitiesTab::Journals::NewComponent.new(work_package:)
+ )
+ end
+ end
end
end
end
end
end
end
+ else
+ render(
+ WorkPackages::ActivitiesTab::Journals::IndexComponent.new(work_package:, filter:, deferred:)
+ )
end
%>
diff --git a/app/components/work_packages/activities_tab/index_component.rb b/app/components/work_packages/activities_tab/index_component.rb
index 65ed1463d37c..4b80371b21f3 100644
--- a/app/components/work_packages/activities_tab/index_component.rb
+++ b/app/components/work_packages/activities_tab/index_component.rb
@@ -36,17 +36,18 @@ class IndexComponent < ApplicationComponent
include OpTurbo::Streamable
include WorkPackages::ActivitiesTab::SharedHelpers
- def initialize(work_package:, last_server_timestamp:, filter: :all)
+ def initialize(work_package:, last_server_timestamp:, filter: :all, deferred: false)
super
@work_package = work_package
@filter = filter
@last_server_timestamp = last_server_timestamp
+ @deferred = deferred
end
private
- attr_reader :work_package, :filter, :last_server_timestamp
+ attr_reader :work_package, :filter, :last_server_timestamp, :deferred
def wrapper_data_attributes
stimulus_controller = "work-packages--activities-tab--index"
diff --git a/app/components/work_packages/activities_tab/journals/index_component.html.erb b/app/components/work_packages/activities_tab/journals/index_component.html.erb
index aa761592d114..c541372a20a6 100644
--- a/app/components/work_packages/activities_tab/journals/index_component.html.erb
+++ b/app/components/work_packages/activities_tab/journals/index_component.html.erb
@@ -1,34 +1,61 @@
<%=
- component_wrapper(class: "work-packages-activities-tab-journals-index-component") do
- flex_layout(data: { test_selector: "op-wp-journals-#{filter}-#{journal_sorting}" }) do |journals_index_wrapper_container|
- journals_index_wrapper_container.with_row(
- classes: "work-packages-activities-tab-journals-index-component--journals-inner-container",
- mb: inner_container_margin_bottom
- ) do
- flex_layout(id: insert_target_modifier_id,
- data: { test_selector: "op-wp-journals-container" }) do |journals_index_container|
- if empty_state?
- journals_index_container.with_row(mt: 2, mb: 3) do
- render(
- WorkPackages::ActivitiesTab::Journals::EmptyComponent.new
- )
+ unless deferred
+ component_wrapper(class: "work-packages-activities-tab-journals-index-component") do
+ flex_layout(data: { test_selector: "op-wp-journals-#{filter}-#{journal_sorting}" }) do |journals_index_wrapper_container|
+ journals_index_wrapper_container.with_row(
+ classes: "work-packages-activities-tab-journals-index-component--journals-inner-container",
+ mb: inner_container_margin_bottom
+ ) do
+ flex_layout(id: insert_target_modifier_id,
+ data: { test_selector: "op-wp-journals-container" }) do |journals_index_container|
+ if empty_state?
+ journals_index_container.with_row(mt: 2, mb: 3) do
+ render(
+ WorkPackages::ActivitiesTab::Journals::EmptyComponent.new
+ )
+ end
+ end
+
+ if !journal_sorting_desc? && journals.count > MAX_RECENT_JOURNALS
+ journals_index_container.with_row do
+ helpers.turbo_frame_tag("work-package-activities-tab-content-older-journals", src: work_package_activities_path(work_package, filter:, deferred: true))
+ end
end
- end
- journals.each do |journal|
- journals_index_container.with_row do
- render(WorkPackages::ActivitiesTab::Journals::ItemComponent.new(
- journal:, filter:,
- grouped_emoji_reactions: wp_journals_grouped_emoji_reactions[journal.id]
- ))
+ recent_journals.each do |journal|
+ journals_index_container.with_row do
+ render(WorkPackages::ActivitiesTab::Journals::ItemComponent.new(
+ journal:, filter:,
+ grouped_emoji_reactions: wp_journals_grouped_emoji_reactions[journal.id]
+ ))
+ end
+ end
+
+ if journal_sorting_desc? && journals.count > MAX_RECENT_JOURNALS
+ journals_index_container.with_row do
+ helpers.turbo_frame_tag("work-package-activities-tab-content-older-journals", src: work_package_activities_path(work_package, filter:, deferred: true))
+ end
end
end
end
- end
- unless empty_state? || journal_sorting_desc?
- journals_index_wrapper_container
- .with_row(classes: "work-packages-activities-tab-journals-index-component--stem-connection")
+ unless empty_state? || journal_sorting_desc?
+ journals_index_wrapper_container
+ .with_row(classes: "work-packages-activities-tab-journals-index-component--stem-connection")
+ end
+ end
+ end
+ else
+ helpers.turbo_frame_tag("work-package-activities-tab-content-older-journals") do
+ flex_layout do |older_journals_container|
+ older_journals.each do |journal|
+ older_journals_container.with_row do
+ render(WorkPackages::ActivitiesTab::Journals::ItemComponent.new(
+ journal:, filter:,
+ grouped_emoji_reactions: wp_journals_grouped_emoji_reactions[journal.id]
+ ))
+ end
+ end
end
end
end
diff --git a/app/components/work_packages/activities_tab/journals/index_component.rb b/app/components/work_packages/activities_tab/journals/index_component.rb
index a2120884a006..469f0e3d4e11 100644
--- a/app/components/work_packages/activities_tab/journals/index_component.rb
+++ b/app/components/work_packages/activities_tab/journals/index_component.rb
@@ -32,21 +32,24 @@ module WorkPackages
module ActivitiesTab
module Journals
class IndexComponent < ApplicationComponent
+ MAX_RECENT_JOURNALS = 30
+
include ApplicationHelper
include OpPrimer::ComponentHelpers
include OpTurbo::Streamable
include WorkPackages::ActivitiesTab::SharedHelpers
- def initialize(work_package:, filter: :all)
+ def initialize(work_package:, filter: :all, deferred: false)
super
@work_package = work_package
@filter = filter
+ @deferred = deferred
end
private
- attr_reader :work_package, :filter
+ attr_reader :work_package, :filter, :deferred
def insert_target_modified?
true
@@ -60,16 +63,48 @@ def journal_sorting_desc?
journal_sorting == "desc"
end
- def journals
+ def base_journals
work_package
.journals
- .includes(:user, :notifications)
+ .includes(
+ :user,
+ :customizable_journals,
+ :attachable_journals,
+ :storable_journals,
+ :notifications
+ )
.reorder(version: journal_sorting)
.with_sequence_version
end
+ def journals
+ API::V3::Activities::ActivityEagerLoadingWrapper.wrap(base_journals)
+ end
+
+ def recent_journals
+ recent_ones = if journal_sorting_desc?
+ base_journals.first(MAX_RECENT_JOURNALS)
+ else
+ base_journals.last(MAX_RECENT_JOURNALS)
+ end
+
+ API::V3::Activities::ActivityEagerLoadingWrapper.wrap(recent_ones)
+ end
+
+ def older_journals
+ older_ones = if journal_sorting_desc?
+ base_journals.offset(MAX_RECENT_JOURNALS)
+ else
+ total = base_journals.count
+ limit = [total - MAX_RECENT_JOURNALS, 0].max
+ base_journals.limit(limit)
+ end
+
+ API::V3::Activities::ActivityEagerLoadingWrapper.wrap(older_ones)
+ end
+
def journal_with_notes
- journals.where.not(notes: "")
+ base_journals.where.not(notes: "")
end
def wp_journals_grouped_emoji_reactions
diff --git a/app/components/work_packages/activities_tab/journals/item_component.html.erb b/app/components/work_packages/activities_tab/journals/item_component.html.erb
index 46e88201e3c8..7ea180f1a7ae 100644
--- a/app/components/work_packages/activities_tab/journals/item_component.html.erb
+++ b/app/components/work_packages/activities_tab/journals/item_component.html.erb
@@ -30,6 +30,16 @@
classes: "work-packages-activities-tab-journals-item-component--user-name ellipsis hidden-for-mobile") do
truncated_user_name(journal.user)
end
+ if journal.initial?
+ header_start_container.with_column(
+ mr: 1,
+ classes: "work-packages-activities-tab-journals-item-component-details--journal-type hidden-for-mobile"
+ ) do
+ render(Primer::Beta::Text.new(font_size: :small, color: :subtle, mt: 1)) do
+ I18n.t("activities.work_packages.activity_tab.created_on")
+ end
+ end
+ end
header_start_container.with_column(mr: 1, classes: "hidden-for-mobile") do
render(Primer::Beta::Text.new(font_size: :small, color: :subtle, mt: 1)) { format_time(journal.updated_at) }
end
diff --git a/app/components/work_packages/activities_tab/journals/item_component.rb b/app/components/work_packages/activities_tab/journals/item_component.rb
index 0030013b1fdd..af733a7474c4 100644
--- a/app/components/work_packages/activities_tab/journals/item_component.rb
+++ b/app/components/work_packages/activities_tab/journals/item_component.rb
@@ -75,7 +75,7 @@ def updated?
end
def has_unread_notifications?
- journal.notifications.where(read_ian: false, recipient_id: User.current.id).any?
+ journal.has_unread_notifications_for_user?(User.current)
end
def notification_on_details?
diff --git a/app/components/work_packages/activities_tab/journals/item_component/details.html.erb b/app/components/work_packages/activities_tab/journals/item_component/details.html.erb
index 1398253b079c..e2ca551782ed 100644
--- a/app/components/work_packages/activities_tab/journals/item_component/details.html.erb
+++ b/app/components/work_packages/activities_tab/journals/item_component/details.html.erb
@@ -14,23 +14,20 @@
when :only_comments
render_empty_line(details_container) unless journal.notes.blank? && !journal.noop?
when :only_changes
- if journal.details.any?
+ if has_details?
render_details_header(details_container)
render_details(details_container)
end
else
- if journal.details.any?
+ if has_details?
if journal.notes.present?
render_details(details_container)
else
render_details_header(details_container)
render_details(details_container)
end
- elsif journal.notes.present?
- render_details(details_container)
else
- # empty row to render the flex layout with its minimal height
- render_empty_line(details_container)
+ render_details(details_container)
end
end
end
diff --git a/app/components/work_packages/activities_tab/journals/item_component/details.rb b/app/components/work_packages/activities_tab/journals/item_component/details.rb
index 59f0c5ed4fbf..529fbcd6ab95 100644
--- a/app/components/work_packages/activities_tab/journals/item_component/details.rb
+++ b/app/components/work_packages/activities_tab/journals/item_component/details.rb
@@ -53,6 +53,14 @@ def wrapper_uniq_by
journal.id
end
+ def journal_details
+ @journal_details ||= journal.details
+ end
+
+ def has_details?
+ @has_details ||= journal_details.any?
+ end
+
def render_details_header(details_container)
details_container.with_row(
flex_layout: true,
@@ -223,7 +231,7 @@ def skip_rendering_details?
end
def render_journal_details(details_container_inner)
- journal.details.each do |detail|
+ journal_details.each do |detail|
rendered_detail = journal.render_detail(detail)
render_single_detail(details_container_inner, rendered_detail) if rendered_detail.present?
end
diff --git a/app/components/work_packages/exports/generate/modal_dialog_component.html.erb b/app/components/work_packages/exports/generate/modal_dialog_component.html.erb
new file mode 100644
index 000000000000..2ca7ef37b7e4
--- /dev/null
+++ b/app/components/work_packages/exports/generate/modal_dialog_component.html.erb
@@ -0,0 +1,57 @@
+<%= render(Primer::Alpha::Dialog.new(
+ title: I18n.t("pdf_generator.dialog.title"),
+ id: MODAL_ID,
+ size: :large
+)) do |dialog|
+ dialog.with_header(variant: :large)
+ dialog.with_body do
+ primer_form_with(
+ url: generate_pdf_work_package_path(work_package),
+ data: { turbo: false },
+ id: GENERATE_PDF_FORM_ID
+ ) do |form|
+ flex_layout do |modal_body|
+ generate_selects.each_with_index do |entry, index|
+ modal_body.with_row(mt: index == 0 ? 0 : 3) do
+ render(Primer::Alpha::Select.new(
+ name: entry[:name],
+ label: entry[:label],
+ caption: entry[:caption],
+ size: :medium,
+ input_width: :small,
+ value: entry[:options].find { |e| e[:default] }[:value])
+ ) do |component|
+ entry[:options].each do |entry|
+ component.option(label: entry[:label], value: entry[:value])
+ end
+ end
+ end
+ end
+ modal_body.with_row(mt: 3) do
+ render Primer::Alpha::TextField.new(
+ name: :header_text_right,
+ label: I18n.t("pdf_generator.dialog.header_right.label"),
+ caption: I18n.t("pdf_generator.dialog.header_right.caption"),
+ visually_hide_label: false,
+ value: default_header_text_right
+ )
+ end
+ modal_body.with_row(mt: 3) do
+ render Primer::Alpha::TextField.new(
+ name: :footer_text_center,
+ label: I18n.t("pdf_generator.dialog.footer_center.label"),
+ caption: I18n.t("pdf_generator.dialog.footer_center.caption"),
+ visually_hide_label: false,
+ value: default_footer_text_center
+ )
+ end
+ end
+ end
+ end
+ dialog.with_footer do
+ render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) }
+ render(Primer::ButtonComponent.new(
+ scheme: :primary, type: :submit, form: GENERATE_PDF_FORM_ID,
+ data: { "close-dialog-id": MODAL_ID })) { I18n.t("pdf_generator.dialog.submit") }
+ end
+end %>
diff --git a/app/components/work_packages/exports/generate/modal_dialog_component.rb b/app/components/work_packages/exports/generate/modal_dialog_component.rb
new file mode 100644
index 000000000000..bf64944cabb6
--- /dev/null
+++ b/app/components/work_packages/exports/generate/modal_dialog_component.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+require "text/hyphen"
+
+module WorkPackages
+ module Exports
+ module Generate
+ class ModalDialogComponent < ApplicationComponent
+ MODAL_ID = "op-work-package-generate-pdf-dialog"
+ GENERATE_PDF_FORM_ID = "op-work-packages-generate-pdf-dialog-form"
+ include OpTurbo::Streamable
+ include OpPrimer::ComponentHelpers
+
+ attr_reader :work_package, :params
+
+ def initialize(work_package:, params:)
+ super
+
+ @work_package = work_package
+ @params = params
+ end
+
+ def default_header_text_right
+ "#{work_package.type} ##{work_package.id}"
+ end
+
+ def default_footer_text_center
+ work_package.subject
+ end
+
+ def generate_selects
+ [
+ {
+ name: "hyphenation",
+ label: I18n.t("pdf_generator.dialog.hyphenation.label"),
+ caption: I18n.t("pdf_generator.dialog.hyphenation.caption"),
+ options: hyphenation_options
+ },
+ {
+ name: "paper_size",
+ label: I18n.t("pdf_generator.dialog.paper_size.label"),
+ caption: I18n.t("pdf_generator.dialog.paper_size.caption"),
+ options: paper_size_options
+ }
+ ]
+ end
+
+ def hyphenation_options
+ # This is a list of languages that are supported by the hyphenation library
+ # https://rubygems.org/gems/text-hyphen
+ # The labels are the language names in the language itself (NOT to be put I18n)
+ supported_languages = [
+ { label: "Català", value: "ca" },
+ { label: "Dansk", value: "da" },
+ { label: "Deutsch", value: "de" },
+ { label: "Eesti", value: "et" },
+ { label: "English (UK)", value: "en_uk" },
+ { label: "English (USA)", value: "en_us" },
+ { label: "Español", value: "es" },
+ { label: "Euskara", value: "eu" },
+ { label: "Français", value: "fr" },
+ { label: "Gaeilge", value: "ga" },
+ { label: "Hrvatski", value: "hr" },
+ { label: "Indonesia", value: "id" },
+ { label: "Interlingua", value: "ia" },
+ { label: "Italiano", value: "it" },
+ { label: "Magyar", value: "hu" },
+ { label: "Melayu", value: "ms" },
+ { label: "Nederlands", value: "nl" },
+ { label: "Norsk", value: "no" },
+ { label: "Polski", value: "pl" },
+ { label: "Português", value: "pt" },
+ { label: "Slovenčina", value: "sk" },
+ { label: "Suomi", value: "fi" },
+ { label: "Svenska", value: "sv" },
+ { label: "Ísland", value: "is" },
+ { label: "Čeština", value: "cs" },
+ { label: "Монгол", value: "mn" },
+ { label: "Русский", value: "ru" }
+ ]
+
+ [{ value: "", label: "Off", default: true }].concat(supported_languages)
+ end
+
+ def paper_size_options
+ [
+ { label: "A4", value: "A4", default: true },
+ { label: "A3", value: "A3" },
+ { label: "A2", value: "A2" },
+ { label: "A1", value: "A1" },
+ { label: "A0", value: "A0" },
+ { label: "Executive", value: "EXECUTIVE" },
+ { label: "Folio", value: "FOLIO" },
+ { label: "Letter", value: "LETTER" },
+ { label: "Tabloid", value: "TABLOID" }
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/app/controllers/work_packages/activities_tab_controller.rb b/app/controllers/work_packages/activities_tab_controller.rb
index 93ac7ba6cde9..2b824dc6b5e6 100644
--- a/app/controllers/work_packages/activities_tab_controller.rb
+++ b/app/controllers/work_packages/activities_tab_controller.rb
@@ -43,7 +43,8 @@ def index
WorkPackages::ActivitiesTab::IndexComponent.new(
work_package: @work_package,
filter: @filter,
- last_server_timestamp: get_current_server_timestamp
+ last_server_timestamp: get_current_server_timestamp,
+ deferred: ActiveRecord::Type::Boolean.new.cast(params[:deferred])
),
layout: false
)
@@ -374,6 +375,7 @@ def rerender_journals_with_updated_notification(journals, last_update_timestamp,
# alternative approach in order to bypass the notification join issue in relation with the sequence_version query
Notification
.where(journal_id: journals.pluck(:id))
+ .where(recipient_id: User.current.id)
.where("notifications.updated_at > ?", last_update_timestamp)
.find_each do |notification|
update_item_show_component(
diff --git a/app/controllers/work_packages_controller.rb b/app/controllers/work_packages_controller.rb
index c17fec995245..81e3613a662e 100644
--- a/app/controllers/work_packages_controller.rb
+++ b/app/controllers/work_packages_controller.rb
@@ -37,13 +37,13 @@ class WorkPackagesController < ApplicationController
accept_key_auth :index, :show
before_action :authorize_on_work_package,
- :project, only: :show
+ :project, only: %i[show generate_pdf_dialog generate_pdf]
before_action :load_and_authorize_in_optional_project,
:check_allowed_export,
:protect_from_unauthorized_export, only: %i[index export_dialog]
before_action :authorize, only: :show_conflict_flash_message
- authorization_checked! :index, :show, :export_dialog
+ authorization_checked! :index, :show, :export_dialog, :generate_pdf_dialog, :generate_pdf
before_action :load_and_validate_query, only: :index, unless: -> { request.format.html? }
before_action :load_work_packages, only: :index, if: -> { request.format.atom? }
@@ -93,6 +93,19 @@ def export_dialog
respond_with_dialog WorkPackages::Exports::ModalDialogComponent.new(query: @query, project: @project, title: params[:title])
end
+ def generate_pdf_dialog
+ respond_with_dialog WorkPackages::Exports::Generate::ModalDialogComponent.new(work_package: work_package, params: params)
+ end
+
+ def generate_pdf
+ exporter = WorkPackage::PDFExport::DocumentGenerator.new(work_package, params)
+ export = exporter.export!
+ send_data(export.content, type: export.mime_type, filename: export.title)
+ rescue ::Exports::ExportError => e
+ flash[:error] = e.message
+ redirect_back(fallback_location: work_package_path(work_package))
+ end
+
def show_conflict_flash_message
scheme = params[:scheme]&.to_sym || :danger
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index b1d7ae1942c3..f1eb8ad9cae3 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -163,8 +163,12 @@ def is_pdf?
content_type == "application/pdf"
end
+ def is_html?
+ content_type == "text/html"
+ end
+
def is_text?
- content_type.match?(/\Atext\/.+/)
+ content_type.match?(/\Atext\/.+/) && !is_html?
end
def is_diff?
diff --git a/app/models/journal.rb b/app/models/journal.rb
index 04f66834916a..95da1c3ed52a 100644
--- a/app/models/journal.rb
+++ b/app/models/journal.rb
@@ -177,6 +177,16 @@ def has_cause?
cause_type.present?
end
+ def has_unread_notifications_for_user?(user)
+ # we optionally set the instance variable @unread_notifications in the ActivityEagerLoadingWrapper
+ # in order to avoid N+1 queries
+ if instance_variable_defined?(:@unread_notifications)
+ @unread_notifications&.any? { |notification| notification.recipient_id == user.id }
+ else
+ notifications.where(read_ian: false, recipient_id: user.id).any?
+ end
+ end
+
private
def has_file_links?
diff --git a/app/models/journal/base_journal.rb b/app/models/journal/base_journal.rb
index ea9cd0fa0941..826b7c627671 100644
--- a/app/models/journal/base_journal.rb
+++ b/app/models/journal/base_journal.rb
@@ -37,7 +37,7 @@ def journaled_attributes
end
def self.journaled_attributes
- @journaled_attributes ||= column_names.map(&:to_sym) - excluded_attributes
+ @journaled_attributes ||= columns.reject(&:virtual?).map { |col| col.name.to_sym } - excluded_attributes
end
def self.excluded_attributes
diff --git a/app/models/project.rb b/app/models/project.rb
index cb377c6b5ad2..89191c1eba8b 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -86,6 +86,7 @@ class Project < ApplicationRecord
has_many :notification_settings, dependent: :destroy
has_many :project_storages, dependent: :destroy, class_name: "Storages::ProjectStorage"
has_many :storages, through: :project_storages
+ has_many :life_cycle_steps, class_name: "Project::LifeCycleStep", dependent: :destroy
store_attribute :settings, :deactivate_work_package_attachments, :boolean
@@ -174,7 +175,7 @@ class Project < ApplicationRecord
scopes :activated_time_activity,
:visible_with_activated_time_activity
- enum status_code: {
+ enum :status_code, {
on_track: 0,
at_risk: 1,
off_track: 2,
diff --git a/app/models/project/gate.rb b/app/models/project/gate.rb
new file mode 100644
index 000000000000..46ee6fffdb74
--- /dev/null
+++ b/app/models/project/gate.rb
@@ -0,0 +1,42 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::Gate < Project::LifeCycleStep
+ alias_attribute :date, :start_date
+
+ # This ensures the type cannot be changed after initialising the class.
+ validates :type, inclusion: { in: %w[Project::Gate], message: :must_be_a_gate }
+ validates :date, presence: true
+ validate :end_date_not_allowed
+
+ def end_date_not_allowed
+ if end_date.present?
+ errors.add(:base, :end_date_not_allowed)
+ end
+ end
+end
diff --git a/app/models/project/gate_definition.rb b/app/models/project/gate_definition.rb
new file mode 100644
index 000000000000..a51561075728
--- /dev/null
+++ b/app/models/project/gate_definition.rb
@@ -0,0 +1,35 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::GateDefinition < Project::LifeCycleStepDefinition
+ has_many :gates, # Alias for life_cycle_steps
+ class_name: "Project::Gate",
+ foreign_key: :definition_id,
+ inverse_of: :definition,
+ dependent: :destroy
+end
diff --git a/app/models/project/life_cycle_step.rb b/app/models/project/life_cycle_step.rb
new file mode 100644
index 000000000000..dfa4b11efda9
--- /dev/null
+++ b/app/models/project/life_cycle_step.rb
@@ -0,0 +1,49 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::LifeCycleStep < ApplicationRecord
+ belongs_to :project, optional: false
+ belongs_to :definition,
+ optional: false,
+ class_name: "Project::LifeCycleStepDefinition"
+ has_many :work_packages, inverse_of: :project_life_cycle_step, dependent: :nullify
+
+ attr_readonly :definition_id, :type
+
+ validates :type, inclusion: { in: %w[Project::Stage Project::Gate], message: :must_be_a_stage_or_gate }
+
+ def initialize(*args)
+ if instance_of? Project::LifeCycleStep
+ # Do not allow directly instantiating this class
+ raise NotImplementedError, "Cannot instantiate the base Project::LifeCycleStep class directly. " \
+ "Use Project::Stage or Project::Gate instead."
+ end
+
+ super
+ end
+end
diff --git a/app/models/project/life_cycle_step_definition.rb b/app/models/project/life_cycle_step_definition.rb
new file mode 100644
index 000000000000..d511cc284cc4
--- /dev/null
+++ b/app/models/project/life_cycle_step_definition.rb
@@ -0,0 +1,54 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::LifeCycleStepDefinition < ApplicationRecord
+ has_many :life_cycle_steps,
+ class_name: "Project::LifeCycleStep",
+ foreign_key: :definition_id,
+ inverse_of: :definition,
+ dependent: :destroy
+ has_many :projects, through: :life_cycle_steps
+ belongs_to :color, optional: false
+
+ validates :name, presence: true
+ validates :type, inclusion: { in: %w[Project::StageDefinition Project::GateDefinition], message: :must_be_a_stage_or_gate }
+
+ attr_readonly :type
+
+ acts_as_list
+
+ def initialize(*args)
+ if instance_of? Project::LifeCycleStepDefinition
+ # Do not allow directly instantiating this class
+ raise NotImplementedError, "Cannot instantiate the base Project::LifeCycleStepDefinition class directly. " \
+ "Use Project::StageDefinition or Project::GateDefinition instead."
+ end
+
+ super
+ end
+end
diff --git a/app/models/project/stage.rb b/app/models/project/stage.rb
new file mode 100644
index 000000000000..b49ca7787b71
--- /dev/null
+++ b/app/models/project/stage.rb
@@ -0,0 +1,33 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::Stage < Project::LifeCycleStep
+ # This ensures the type cannot be changed after initialising the class.
+ validates :type, inclusion: { in: %w[Project::Stage], message: :must_be_a_stage }
+ validates :start_date, :end_date, presence: true
+end
diff --git a/app/models/project/stage_definition.rb b/app/models/project/stage_definition.rb
new file mode 100644
index 000000000000..91ae98584def
--- /dev/null
+++ b/app/models/project/stage_definition.rb
@@ -0,0 +1,35 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class Project::StageDefinition < Project::LifeCycleStepDefinition
+ has_many :stages, # Alias for life_cycle_steps
+ class_name: "Project::Stage",
+ foreign_key: :definition_id,
+ inverse_of: :definition,
+ dependent: :destroy
+end
diff --git a/app/models/projects.rb b/app/models/projects.rb
new file mode 100644
index 000000000000..27b2504bd994
--- /dev/null
+++ b/app/models/projects.rb
@@ -0,0 +1,5 @@
+module Projects
+ def self.table_name_prefix
+ "projects_"
+ end
+end
diff --git a/app/models/work_package.rb b/app/models/work_package.rb
index 270106799161..a16611e48b03 100644
--- a/app/models/work_package.rb
+++ b/app/models/work_package.rb
@@ -55,6 +55,7 @@ class WorkPackage < ApplicationRecord
belongs_to :assigned_to, class_name: "Principal", optional: true
belongs_to :responsible, class_name: "Principal", optional: true
belongs_to :version, optional: true
+ belongs_to :project_life_cycle_step, class_name: "Project::LifeCycleStep", optional: true
belongs_to :priority, class_name: "IssuePriority"
belongs_to :category, class_name: "Category", optional: true
@@ -303,7 +304,7 @@ def included_in_totals_calculation?
end
def done_ratio
- if WorkPackage.status_based_mode? && status && status.default_done_ratio
+ if WorkPackage.status_based_mode? && status&.default_done_ratio
status.default_done_ratio
else
read_attribute(:done_ratio)
@@ -378,7 +379,7 @@ def attributes=(new_attributes)
# Set the done_ratio using the status if that setting is set. This will keep the done_ratios
# even if the user turns off the setting later
def update_done_ratio_from_status
- if WorkPackage.status_based_mode? && status && status.default_done_ratio
+ if WorkPackage.status_based_mode? && status&.default_done_ratio
self.done_ratio = status.default_done_ratio
end
end
@@ -632,7 +633,7 @@ def self.update_versions(conditions = nil)
# Default assignment based on category
def default_assign
- if assigned_to.nil? && category && category.assigned_to
+ if assigned_to.nil? && category&.assigned_to
self.assigned_to = category.assigned_to
end
end
diff --git a/app/models/work_package/exports/formatters/costs.rb b/app/models/work_package/exports/formatters/costs.rb
index 9133f3cfe02e..310f864aff4b 100644
--- a/app/models/work_package/exports/formatters/costs.rb
+++ b/app/models/work_package/exports/formatters/costs.rb
@@ -38,8 +38,8 @@ def format_options
def number_format_string
# [$CUR] makes sure we have an actually working currency format with arbitrary currencies
- curr = "[$CUR]".gsub "CUR", ERB::Util.h(Setting.plugin_costs["costs_currency"])
- format = ERB::Util.h Setting.plugin_costs["costs_currency_format"]
+ curr = "[$CUR]".gsub "CUR", ERB::Util.h(Setting.costs_currency)
+ format = ERB::Util.h Setting.costs_currency_format
number = "#,##0.00"
format.gsub("%n", number).gsub("%u", curr)
diff --git a/app/models/work_package/pdf_export/common/attachments.rb b/app/models/work_package/pdf_export/common/attachments.rb
new file mode 100644
index 000000000000..2a1574f8618d
--- /dev/null
+++ b/app/models/work_package/pdf_export/common/attachments.rb
@@ -0,0 +1,77 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "mini_magick"
+
+module WorkPackage::PDFExport::Common::Attachments
+ def resize_image(file_path)
+ tmp_file = Tempfile.new(["temp_image", File.extname(file_path)])
+ @resized_images = [] if @resized_images.nil?
+
+ @resized_images << tmp_file
+ resized_file_path = tmp_file.path
+
+ image = MiniMagick::Image.open(file_path)
+ image.resize("x800>")
+ image.write(resized_file_path)
+
+ resized_file_path
+ end
+
+ def pdf_embeddable?(content_type)
+ %w[image/jpeg image/png].include?(content_type)
+ end
+
+ def delete_all_resized_images
+ @resized_images&.each(&:close!)
+ @resized_images = []
+ end
+
+ def attachment_image_local_file(attachment)
+ attachment.file.local_file
+ rescue StandardError => e
+ Rails.logger.error "Failed to access attachment #{attachment.id} file: #{e}"
+ nil # return nil as if the id was wrong and the attachment obj has not been found
+ end
+
+ def attachment_image_filepath(work_package, src)
+ # images are embedded into markup with the api-path as img.src
+ attachment = attachment_by_api_content_src(work_package, src)
+ return nil if attachment.nil? || !pdf_embeddable?(attachment.content_type)
+
+ local_file = attachment_image_local_file(attachment)
+ return nil if local_file.nil?
+
+ resize_image(local_file.path)
+ end
+
+ def attachment_by_api_content_src(work_package, src)
+ # find attachment by api-path
+ work_package.attachments.find { |a| api_url_helpers.attachment_content(a.id) == src }
+ end
+end
diff --git a/app/models/work_package/pdf_export/common.rb b/app/models/work_package/pdf_export/common/common.rb
similarity index 89%
rename from app/models/work_package/pdf_export/common.rb
rename to app/models/work_package/pdf_export/common/common.rb
index e9ccb01a6a1c..c91d44836ab5 100644
--- a/app/models/work_package/pdf_export/common.rb
+++ b/app/models/work_package/pdf_export/common/common.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Common
+module WorkPackage::PDFExport::Common::Common
include Redmine::I18n
include ActionView::Helpers::TextHelper
include ActionView::Helpers::NumberHelper
@@ -36,7 +36,7 @@ module WorkPackage::PDFExport::Common
private
def get_pdf(_language)
- ::WorkPackage::PDFExport::View.new(current_language)
+ ::WorkPackage::PDFExport::Common::View.new(current_language)
end
def field_value(work_package, attribute)
@@ -76,26 +76,11 @@ def with_vertical_margin(opts)
pdf.move_down(opts[:bottom_margin]) if opts.key?(:bottom_margin)
end
- def write_optional_page_break
- space_from_bottom = pdf.y - pdf.bounds.bottom
- if space_from_bottom < styles.page_break_threshold
- pdf.start_new_page
- end
- end
-
def get_column_value(work_package, column_name)
formatter = formatter_for(column_name, :pdf)
formatter.format(work_package)
end
- def get_column_value_cell(work_package, column_name)
- value = get_column_value(work_package, column_name)
- return get_id_column_cell(work_package, value) if column_name == :id
- return get_subject_column_cell(work_package, value) if wants_report? && column_name == :subject
-
- escape_tags(value)
- end
-
def get_formatted_value(value, column_name)
return "" if value.nil?
@@ -108,19 +93,6 @@ def escape_tags(value)
value.to_s.gsub("<", "<").gsub(">", ">")
end
- def get_id_column_cell(work_package, value)
- href = url_helpers.work_package_url(work_package)
- make_link_href_cell(href, value)
- end
-
- def get_subject_column_cell(work_package, value)
- make_link_anchor(work_package.id, escape_tags(value))
- end
-
- def make_link_href_cell(href, caption)
- "#{caption}"
- end
-
def make_link_anchor(anchor, caption)
"#{caption}"
end
@@ -306,6 +278,10 @@ def title_datetime
DateTime.now.strftime("%Y-%m-%d_%H-%M")
end
+ def footer_date
+ format_time(Time.zone.now)
+ end
+
def current_page_nr
pdf.page_number + @page_count - (with_cover? ? 1 : 0)
end
diff --git a/app/models/work_package/pdf_export/common/logo.rb b/app/models/work_package/pdf_export/common/logo.rb
new file mode 100644
index 000000000000..fe4cc81b6f28
--- /dev/null
+++ b/app/models/work_package/pdf_export/common/logo.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module WorkPackage::PDFExport::Common::Logo
+ def logo_image
+ image_obj, image_info = pdf.build_image_object(logo_image_filename)
+ [image_obj, image_info]
+ end
+
+ def logo_image_filename
+ custom_logo_image_filename || Rails.root.join("app/assets/images/logo_openproject.png")
+ end
+
+ def custom_logo_image_filename
+ return unless CustomStyle.current.present? &&
+ CustomStyle.current.export_logo.present? && CustomStyle.current.export_logo.local_file.present?
+
+ image_file = CustomStyle.current.export_logo.local_file.path
+ content_type = OpenProject::ContentTypeDetector.new(image_file).detect
+ return unless pdf_embeddable?(content_type)
+
+ image_file
+ end
+end
diff --git a/app/models/work_package/pdf_export/markdown_field.rb b/app/models/work_package/pdf_export/common/macro.rb
similarity index 84%
rename from app/models/work_package/pdf_export/markdown_field.rb
rename to app/models/work_package/pdf_export/common/macro.rb
index 53ccd93dc8b6..bb2a73b914db 100644
--- a/app/models/work_package/pdf_export/markdown_field.rb
+++ b/app/models/work_package/pdf_export/common/macro.rb
@@ -26,28 +26,15 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::MarkdownField
- include WorkPackage::PDFExport::Markdown
+module WorkPackage::PDFExport::Common::Macro
PREFORMATTED_BLOCKS = %w(pre code).freeze
- def write_markdown_field!(work_package, markdown, label)
- return if markdown.blank?
-
- write_optional_page_break
- with_margin(styles.wp_markdown_label_margins) do
- pdf.formatted_text([styles.wp_markdown_label.merge({ text: label })])
- end
- with_margin(styles.wp_markdown_margins) do
- write_markdown! work_package, apply_markdown_field_macros(markdown, work_package)
- end
- end
-
- private
-
def apply_markdown_field_macros(markdown, work_package)
apply_macros(markdown, work_package, WorkPackage::Exports::Macros::Attributes)
end
+ private
+
def apply_macros(markdown, work_package, formatter)
return markdown unless formatter.applicable?(markdown)
diff --git a/app/models/work_package/pdf_export/view.rb b/app/models/work_package/pdf_export/common/view.rb
similarity index 98%
rename from app/models/work_package/pdf_export/view.rb
rename to app/models/work_package/pdf_export/common/view.rb
index 86f9c4418c61..8adc723fc043 100644
--- a/app/models/work_package/pdf_export/view.rb
+++ b/app/models/work_package/pdf_export/common/view.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-class WorkPackage::PDFExport::View
+class WorkPackage::PDFExport::Common::View
include Prawn::View
include Redmine::I18n
diff --git a/app/models/work_package/pdf_export/document_generator.rb b/app/models/work_package/pdf_export/document_generator.rb
new file mode 100644
index 000000000000..37b69c6b4ea0
--- /dev/null
+++ b/app/models/work_package/pdf_export/document_generator.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class WorkPackage::PDFExport::DocumentGenerator < Exports::Exporter
+ include WorkPackage::PDFExport::Common::Common
+ include WorkPackage::PDFExport::Common::Attachments
+ include WorkPackage::PDFExport::Common::Logo
+ include WorkPackage::PDFExport::Common::Macro
+ include WorkPackage::PDFExport::Generator::Generator
+
+ attr_accessor :pdf
+
+ self.model = WorkPackage
+
+ alias :work_package :object
+
+ def self.key
+ :generate_pdf
+ end
+
+ def initialize(work_package, _options = {})
+ super
+
+ setup_page!
+ end
+
+ def setup_page!
+ self.pdf = get_pdf(current_language)
+ end
+
+ def export!
+ render_doc
+ success(pdf.render)
+ rescue StandardError => e
+ Rails.logger.error { "Failed to generate PDF: #{e} #{e.message}}." }
+ error(I18n.t(:error_pdf_failed_to_export, error: e.message))
+ end
+
+ def render_doc
+ generate_doc!(
+ apply_markdown_field_macros(work_package.description || "", work_package),
+ "contracts.yml"
+ )
+ end
+
+ def hyphenation_language
+ options[:hyphenation]
+ end
+
+ def heading
+ options[:header_text_right]
+ end
+
+ def footer_title
+ options[:footer_text_center]
+ end
+
+ def title
+ # ____.pdf
+ build_pdf_filename([work_package.project, work_package.type,
+ "##{work_package.id}", work_package.subject].join("_"))
+ end
+
+ def with_images?
+ true
+ end
+end
diff --git a/app/models/work_package/pdf_export/cover.rb b/app/models/work_package/pdf_export/export/cover.rb
similarity index 98%
rename from app/models/work_package/pdf_export/cover.rb
rename to app/models/work_package/pdf_export/export/cover.rb
index ebac1df6b501..e50d0c101c30 100644
--- a/app/models/work_package/pdf_export/cover.rb
+++ b/app/models/work_package/pdf_export/export/cover.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Cover
+module WorkPackage::PDFExport::Export::Cover
def write_cover_page!
write_cover_logo
write_cover_hr
diff --git a/app/models/work_package/pdf_export/export/export_common.rb b/app/models/work_package/pdf_export/export/export_common.rb
new file mode 100644
index 000000000000..ace15b8f08c7
--- /dev/null
+++ b/app/models/work_package/pdf_export/export/export_common.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module WorkPackage::PDFExport::Export::ExportCommon
+ def write_optional_page_break
+ space_from_bottom = pdf.y - pdf.bounds.bottom
+ if space_from_bottom < styles.page_break_threshold
+ pdf.start_new_page
+ end
+ end
+
+ def make_link_href_cell(href, caption)
+ "#{caption}"
+ end
+
+ def get_column_value_cell(work_package, column_name)
+ value = get_column_value(work_package, column_name)
+ return get_id_column_cell(work_package, value) if column_name == :id
+ return get_subject_column_cell(work_package, value) if wants_report? && column_name == :subject
+
+ escape_tags(value)
+ end
+
+ def get_id_column_cell(work_package, value)
+ href = url_helpers.work_package_url(work_package)
+ make_link_href_cell(href, value)
+ end
+
+ def get_subject_column_cell(work_package, value)
+ make_link_anchor(work_package.id, escape_tags(value))
+ end
+end
diff --git a/app/models/work_package/pdf_export/gantt.rb b/app/models/work_package/pdf_export/export/gantt.rb
similarity index 98%
rename from app/models/work_package/pdf_export/gantt.rb
rename to app/models/work_package/pdf_export/export/gantt.rb
index 778f286168f6..a395b4ce0710 100644
--- a/app/models/work_package/pdf_export/gantt.rb
+++ b/app/models/work_package/pdf_export/export/gantt.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -43,7 +45,7 @@
# 1. Build the data classes, do the layout, measuring, etc.
# 2. Paint the Gantt chart into the PDF
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
GANTT_DAY_COLUMN_WIDTHS = [64, 32, 24, 18].freeze
GANTT_COLUMN_WIDTHS = [128, 64, 32, 24].freeze
GANTT_COLUMN_WIDTHS_NAMES = %w[very_wide wide medium narrow].freeze
diff --git a/app/models/work_package/pdf_export/gantt/gantt_builder.rb b/app/models/work_package/pdf_export/export/gantt/gantt_builder.rb
similarity index 99%
rename from app/models/work_package/pdf_export/gantt/gantt_builder.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_builder.rb
index 334697cfbe75..1af1b7ee16a5 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_builder.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_builder.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttBuilder
include Redmine::I18n
BAR_CELL_PADDING = 5.to_f
diff --git a/app/models/work_package/pdf_export/gantt/gantt_builder_days.rb b/app/models/work_package/pdf_export/export/gantt/gantt_builder_days.rb
similarity index 97%
rename from app/models/work_package/pdf_export/gantt/gantt_builder_days.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_builder_days.rb
index 829e2f8bb41f..465a4f9515bc 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_builder_days.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_builder_days.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttBuilderDays < GanttBuilder
def build_column_dates_range(range)
range.to_a
diff --git a/app/models/work_package/pdf_export/gantt/gantt_builder_months.rb b/app/models/work_package/pdf_export/export/gantt/gantt_builder_months.rb
similarity index 98%
rename from app/models/work_package/pdf_export/gantt/gantt_builder_months.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_builder_months.rb
index 2505a1d2de52..fe8b8f252d8a 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_builder_months.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_builder_months.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttBuilderMonths < GanttBuilder
def build_column_dates_range(range)
range
diff --git a/app/models/work_package/pdf_export/gantt/gantt_builder_quarters.rb b/app/models/work_package/pdf_export/export/gantt/gantt_builder_quarters.rb
similarity index 98%
rename from app/models/work_package/pdf_export/gantt/gantt_builder_quarters.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_builder_quarters.rb
index c6767403b3fe..664f02d2048d 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_builder_quarters.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_builder_quarters.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttBuilderQuarters < GanttBuilder
def build_column_dates_range(range)
range
diff --git a/app/models/work_package/pdf_export/gantt/gantt_builder_weeks.rb b/app/models/work_package/pdf_export/export/gantt/gantt_builder_weeks.rb
similarity index 98%
rename from app/models/work_package/pdf_export/gantt/gantt_builder_weeks.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_builder_weeks.rb
index f0cc8750a423..337f04977d61 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_builder_weeks.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_builder_weeks.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttBuilderWeeks < GanttBuilder
def build_column_dates_range(range)
range
diff --git a/app/models/work_package/pdf_export/gantt/gantt_painter.rb b/app/models/work_package/pdf_export/export/gantt/gantt_painter.rb
similarity index 99%
rename from app/models/work_package/pdf_export/gantt/gantt_painter.rb
rename to app/models/work_package/pdf_export/export/gantt/gantt_painter.rb
index 952b08b505b8..4247900974b1 100644
--- a/app/models/work_package/pdf_export/gantt/gantt_painter.rb
+++ b/app/models/work_package/pdf_export/export/gantt/gantt_painter.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Gantt
+module WorkPackage::PDFExport::Export::Gantt
class GanttPainter
GANTT_GRID_COLOR = "9b9ea3".freeze
GANTT_LINE_COLOR = "2b8bd5".freeze
diff --git a/app/models/work_package/pdf_export/markdown.rb b/app/models/work_package/pdf_export/export/markdown.rb
similarity index 77%
rename from app/models/work_package/pdf_export/markdown.rb
rename to app/models/work_package/pdf_export/export/markdown.rb
index a875f800bf89..eab8c54370a9 100644
--- a/app/models/work_package/pdf_export/markdown.rb
+++ b/app/models/work_package/pdf_export/export/markdown.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -28,8 +30,8 @@
require "md_to_pdf/core"
-module WorkPackage::PDFExport::Markdown
- class MD2PDF
+module WorkPackage::PDFExport::Export::Markdown
+ class MD2PDFExport
include MarkdownToPDF::Core
include MarkdownToPDF::Parser
@@ -96,35 +98,10 @@ def warn(text, element, node)
end
end
- def write_markdown!(work_package, markdown)
- md2pdf = MD2PDF.new(styles.wp_markdown_styling_yml, pdf)
+ def write_markdown!(work_package, markdown, styling_yml)
+ md2pdf = MD2PDFExport.new(styling_yml, pdf)
md2pdf.draw_markdown(markdown, pdf, ->(src) {
with_images? ? attachment_image_filepath(work_package, src) : nil
})
end
-
- private
-
- def attachment_image_local_file(attachment)
- attachment.file.local_file
- rescue StandardError => e
- Rails.logger.error "Failed to access attachment #{attachment.id} file: #{e}"
- nil # return nil as if the id was wrong and the attachment obj has not been found
- end
-
- def attachment_image_filepath(work_package, src)
- # images are embedded into markup with the api-path as img.src
- attachment = attachment_by_api_content_src(work_package, src)
- return nil if attachment.nil? || !pdf_embeddable?(attachment.content_type)
-
- local_file = attachment_image_local_file(attachment)
- return nil if local_file.nil?
-
- resize_image(local_file.path)
- end
-
- def attachment_by_api_content_src(work_package, src)
- # find attachment by api-path
- work_package.attachments.detect { |a| api_url_helpers.attachment_content(a.id) == src }
- end
end
diff --git a/app/models/work_package/pdf_export/export/markdown_field.rb b/app/models/work_package/pdf_export/export/markdown_field.rb
new file mode 100644
index 000000000000..02c097089ac1
--- /dev/null
+++ b/app/models/work_package/pdf_export/export/markdown_field.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module WorkPackage::PDFExport::Export::MarkdownField
+ include WorkPackage::PDFExport::Export::Markdown
+ include WorkPackage::PDFExport::Common::Macro
+
+ def write_markdown_field!(work_package, markdown, label)
+ return if markdown.blank?
+
+ write_optional_page_break
+ write_markdown_field_label(label)
+ write_markdown_field_value(work_package, markdown)
+ end
+
+ private
+
+ def write_markdown_field_label(label)
+ with_margin(styles.wp_markdown_label_margins) do
+ pdf.formatted_text([styles.wp_markdown_label.merge({ text: label })])
+ end
+ end
+
+ def write_markdown_field_value(work_package, markdown)
+ with_margin(styles.wp_markdown_margins) do
+ write_markdown!(
+ work_package,
+ apply_markdown_field_macros(markdown, work_package),
+ styles.wp_markdown_styling_yml
+ )
+ end
+ end
+end
diff --git a/app/models/work_package/pdf_export/overview_table.rb b/app/models/work_package/pdf_export/export/overview_table.rb
similarity index 98%
rename from app/models/work_package/pdf_export/overview_table.rb
rename to app/models/work_package/pdf_export/export/overview_table.rb
index c44684665114..10405fb87c6b 100644
--- a/app/models/work_package/pdf_export/overview_table.rb
+++ b/app/models/work_package/pdf_export/export/overview_table.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::OverviewTable
+module WorkPackage::PDFExport::Export::OverviewTable
def write_work_packages_overview!(work_packages)
if query.grouped?
write_grouped!(work_packages)
diff --git a/app/models/work_package/pdf_export/page.rb b/app/models/work_package/pdf_export/export/page.rb
similarity index 83%
rename from app/models/work_package/pdf_export/page.rb
rename to app/models/work_package/pdf_export/export/page.rb
index 571efcfaf76f..c63001e5060f 100644
--- a/app/models/work_package/pdf_export/page.rb
+++ b/app/models/work_package/pdf_export/export/page.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Page
+module WorkPackage::PDFExport::Export::Page
MAX_NR_OF_PDF_FOOTER_LINES = 3
def configure_page_size!(layout)
@@ -68,24 +70,6 @@ def logo_pdf_image
[image_obj, image_info, scale]
end
- def logo_image
- image_file = custom_logo_image
- image_file = Rails.root.join("app/assets/images/logo_openproject.png") if image_file.nil?
- image_obj, image_info = pdf.build_image_object(image_file)
- [image_obj, image_info]
- end
-
- def custom_logo_image
- return unless CustomStyle.current.present? &&
- CustomStyle.current.export_logo.present? && CustomStyle.current.export_logo.local_file.present?
-
- image_file = CustomStyle.current.export_logo.local_file.path
- content_type = OpenProject::ContentTypeDetector.new(image_file).detect
- return unless pdf_embeddable?(content_type)
-
- image_file
- end
-
def write_title!
pdf.title = heading
with_margin(styles.page_heading_margins) do
@@ -126,10 +110,6 @@ def footer_page_nr
current_page_nr.to_s + total_page_nr_text
end
- def footer_date
- format_time(Time.zone.now)
- end
-
def total_page_nr_text
if @total_page_nr
"/#{@total_page_nr - (with_cover? ? 1 : 0)}"
diff --git a/app/models/work_package/pdf_export/schema.json b/app/models/work_package/pdf_export/export/schema.json
similarity index 100%
rename from app/models/work_package/pdf_export/schema.json
rename to app/models/work_package/pdf_export/export/schema.json
diff --git a/app/models/work_package/pdf_export/standard.yml b/app/models/work_package/pdf_export/export/standard.yml
similarity index 100%
rename from app/models/work_package/pdf_export/standard.yml
rename to app/models/work_package/pdf_export/export/standard.yml
diff --git a/app/models/work_package/pdf_export/style.rb b/app/models/work_package/pdf_export/export/style.rb
similarity index 98%
rename from app/models/work_package/pdf_export/style.rb
rename to app/models/work_package/pdf_export/export/style.rb
index 349bc977d67f..4a1a152adf1f 100644
--- a/app/models/work_package/pdf_export/style.rb
+++ b/app/models/work_package/pdf_export/export/style.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::Style
+module WorkPackage::PDFExport::Export::Style
include MarkdownToPDF::StyleValidation
class PDFStyles
@@ -308,7 +310,6 @@ def load_style
end
def styles_asset_path
- # TODO: where to put & load yml & json file
File.dirname(File.expand_path(__FILE__))
end
end
diff --git a/app/models/work_package/pdf_export/sums_table.rb b/app/models/work_package/pdf_export/export/sums_table.rb
similarity index 97%
rename from app/models/work_package/pdf_export/sums_table.rb
rename to app/models/work_package/pdf_export/export/sums_table.rb
index c34c08ad4eb0..59c22e467c9e 100644
--- a/app/models/work_package/pdf_export/sums_table.rb
+++ b/app/models/work_package/pdf_export/export/sums_table.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::SumsTable
+module WorkPackage::PDFExport::Export::SumsTable
def write_work_packages_sums!(_work_packages)
return unless has_summable_column?
diff --git a/app/models/work_package/pdf_export/table_of_contents.rb b/app/models/work_package/pdf_export/export/table_of_contents.rb
similarity index 98%
rename from app/models/work_package/pdf_export/table_of_contents.rb
rename to app/models/work_package/pdf_export/export/table_of_contents.rb
index 8d763bb21d09..2e6094626a4f 100644
--- a/app/models/work_package/pdf_export/table_of_contents.rb
+++ b/app/models/work_package/pdf_export/export/table_of_contents.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,7 +28,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::TableOfContents
+module WorkPackage::PDFExport::Export::TableOfContents
def write_work_packages_toc!(work_packages, id_wp_meta_map)
toc_list = build_toc_data_list work_packages, id_wp_meta_map
with_margin(styles.toc_margins) do
diff --git a/app/models/work_package/pdf_export/work_package_detail.rb b/app/models/work_package/pdf_export/export/work_package_detail.rb
similarity index 98%
rename from app/models/work_package/pdf_export/work_package_detail.rb
rename to app/models/work_package/pdf_export/export/work_package_detail.rb
index 24ad8fa359b7..f54b179a08c3 100644
--- a/app/models/work_package/pdf_export/work_package_detail.rb
+++ b/app/models/work_package/pdf_export/export/work_package_detail.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -26,8 +28,8 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module WorkPackage::PDFExport::WorkPackageDetail
- include WorkPackage::PDFExport::MarkdownField
+module WorkPackage::PDFExport::Export::WorkPackageDetail
+ include WorkPackage::PDFExport::Export::MarkdownField
def write_work_packages_details!(work_packages, id_wp_meta_map)
work_packages.each do |work_package|
diff --git a/app/models/work_package/pdf_export/generator/contracts.yml b/app/models/work_package/pdf_export/generator/contracts.yml
new file mode 100644
index 000000000000..97930db5db6b
--- /dev/null
+++ b/app/models/work_package/pdf_export/generator/contracts.yml
@@ -0,0 +1,244 @@
+page:
+ font: 'NotoSans'
+ size: 11
+ character-spacing: 0
+ styles: []
+ color: '000000'
+ page-size: 'A4'
+ page-layout: 'portrait'
+ margin-left: 20mm
+ margin-right: 20mm
+ margin-top: 40mm
+ margin-bottom: 35mm
+ leading: 6
+
+page-footer:
+ filter-pages: [ ]
+ align: "left"
+ offset: -51
+ size: 8
+
+page-footer-2:
+ filter-pages: [ ]
+ align: "center"
+ offset: -51
+ size: 8
+
+page-footer-3:
+ filter-pages: [ ]
+ align: "right"
+ offset: -51
+ size: 8
+
+page-header:
+ filter-pages: [ ]
+ align: "right"
+ size: 8
+ leading: 4
+ offset: -61
+
+page-logo:
+ filter-pages: [ ]
+ align: "left"
+ max-width: 40mm
+ offset: -70
+
+paragraph:
+ align: 'justify'
+ padding-bottom: 3mm
+
+link:
+ color: '1b69b6'
+
+unordered-list:
+ spacing: 3mm
+ padding-bottom: 3mm
+
+unordered-list-point:
+ sign: "•"
+ spacing: 0.75mm
+
+ordered-list:
+ spacing: 3mm
+ padding-bottom: 3mm
+
+ordered-list-point:
+ spanning: true
+
+ordered-list-point-1:
+ template: '()'
+
+ordered-list-point-2:
+ template: ')'
+ alphabetical: true
+
+hrule:
+ margin-top: 2mm
+ margin-bottom: 4mm
+ line-width: 1
+
+header:
+ styles: [ 'bold' ]
+ padding-top: 2mm
+ padding-bottom: 2mm
+
+header-1:
+ size: 18
+ padding-top: 6mm
+header-2:
+ size: 14
+ padding-top: 5mm
+header-3:
+ size: 12
+ padding-top: 4mm
+header-4:
+ size: 11
+ padding-top: 3mm
+header-5:
+ size: 10
+header-6:
+ size: 10
+header-7:
+ size: 10
+header-8:
+ size: 10
+
+table:
+ margin-top: 2mm
+ margin-bottom: 4mm
+ header:
+ styles: [ 'bold' ]
+ background-color: 'F0F0F0'
+ size: 10
+ cell:
+ no-border: true
+ padding: 1mm
+ size: 9
+
+headless-table:
+ margin-top: 2mm
+ margin-bottom: 4mm
+ cell:
+ no-border: true
+ padding: 1mm
+ size: 9
+
+blockquote:
+ background-color: 'f4f9ff'
+ size: 11
+ styles: [ 'italic' ]
+ color: '0f3b66'
+ border-color: 'b8d6f4'
+ border-width: 1
+ no-border-right: true
+ no-border-left: false
+ no-border-bottom: true
+ no-border-top: true
+ padding: 8mm
+ padding-left: 4mm
+ padding-right: 4mm
+ margin-top: 2mm
+ margin-bottom: 2mm
+
+alerts:
+ NOTE:
+ border_color: '0969da'
+ alert_color: '0969da'
+ padding: '4mm'
+ size: 10
+ styles: []
+ border_width: 2
+ no_border_right: true
+ no_border_left: false
+ no_border_bottom: true
+ no_border_top: true
+ TIP:
+ border_color: '1a7f37'
+ alert_color: '1a7f37'
+ padding: '4mm'
+ size: 10
+ styles: [ ]
+ border_width: 2
+ no_border_right: true
+ no_border_left: false
+ no_border_bottom: true
+ no_border_top: true
+ IMPORTANT:
+ border_color: '8250df'
+ alert_color: '8250df'
+ padding: '4mm'
+ size: 10
+ styles: [ ]
+ border_width: 2
+ no_border_right: true
+ no_border_left: false
+ no_border_bottom: true
+ no_border_top: true
+ WARNING:
+ border_color: 'bf8700'
+ alert_color: 'bf8700'
+ padding: '4mm'
+ size: 10
+ styles: [ ]
+ border_width: 2
+ no_border_right: true
+ no_border_left: false
+ no_border_bottom: true
+ no_border_top: true
+ CAUTION:
+ border_color: 'd1242f'
+ alert_color: 'd1242f'
+ size: 10
+ styles: [ ]
+ padding: '4mm'
+ border_width: 2
+ no_border_right: true
+ no_border_left: false
+ no_border_bottom: true
+ no_border_top: true
+
+code:
+ font: 'SpaceMono'
+ color: '880000'
+
+codeblock:
+ background-color: 'F5F5F5'
+ font: 'SpaceMono'
+ size: 8
+ color: '880000'
+ padding: 3mm
+ margin-top: 2mm
+ margin-bottom: 2mm
+
+image:
+ max-width: 50mm
+ margin: 2mm
+ margin-bottom: 3mm
+ align: "center"
+
+image-classes:
+ small:
+ max-width: 10mm
+ left:
+ margin: 0
+ align: "left"
+ center:
+ margin: 0
+ align: "center"
+ right:
+ margin: 0
+ align: "right"
+
+footnote-definition:
+ point:
+ size: 13
+ styles: [ 'superscript' ]
+ color: '000000'
+
+footnote-reference:
+ size: 13
+ styles: [ 'superscript' ]
+ color: '000088'
+
+fields-default:
+ pdf_hyphenation: true
diff --git a/app/models/work_package/pdf_export/generator/generator.rb b/app/models/work_package/pdf_export/generator/generator.rb
new file mode 100644
index 000000000000..2e152e561526
--- /dev/null
+++ b/app/models/work_package/pdf_export/generator/generator.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "md_to_pdf/core"
+
+module WorkPackage::PDFExport::Generator::Generator
+ class MD2PDFGenerator
+ include MarkdownToPDF::Core
+ include MarkdownToPDF::Parser
+ include MarkdownToPDF::StyleSchema
+
+ def initialize(styling_yml)
+ symbol_yml = symbolize(styling_yml)
+ validate_schema!(symbol_yml, styles_schema)
+ @styles = MarkdownToPDF::Styles.new(symbol_yml)
+ init_options({ auto_generate_header_ids: false })
+ end
+
+ def init_pdf(pdf)
+ @pdf = pdf
+ init_pdf_page_styles(pdf)
+ pdf_init_md2pdf_fonts(pdf)
+ end
+
+ def init_pdf_page_styles(pdf)
+ page_style = @styles.page
+ page_margins = opts_margin(page_style)
+ pdf.options[:page_layout] = (page_style[:page_layout] || "portrait").to_sym
+ pdf.options[:page_size] = page_style[:page_size]
+ %i[top_margin left_margin bottom_margin right_margin].each do |margin|
+ pdf.options[margin] = page_margins[margin]
+ end
+ end
+
+ def generate!(markdown, options, image_loader)
+ @image_loader = image_loader
+ fields = {}
+ .merge(@styles.default_fields)
+ .merge(options)
+ doc = parse_frontmatter_markdown(markdown, fields)
+ @hyphens = Text::Hyphen.new(language: options[:language], left: 2, right: 2) if options[:language].present?
+ render_doc(doc)
+ end
+
+ def render_doc(doc)
+ style = @styles.page
+ opts = pdf_root_options(style)
+ root = doc[:root]
+ draw_node(root, opts, true)
+ draw_footnotes(opts)
+ repeating_page_footer(doc, opts)
+ repeating_page_header(doc, opts)
+ repeating_page_logo(doc[:logo], root, opts)
+ end
+
+ def image_url_to_local_file(url, _node = nil)
+ return nil if url.blank? || @image_loader.nil?
+
+ @image_loader.call(url)
+ end
+
+ def hyphenate(text)
+ return text if @hyphens.nil?
+
+ @hyphens.visualize(text, Prawn::Text::SHY)
+ end
+
+ def handle_mention_html_tag(tag, node, opts)
+ if tag.text.blank?
+ #
+ #
+ text = tag.attr("data-text")
+ if text.present? && !node.next.respond_to?(:string_content) && node.next.string_content != text
+ return [text_hash(text, opts)]
+ end
+ end
+ # @Some User
+ []
+ end
+
+ def handle_unknown_inline_html_tag(tag, node, opts)
+ result = if tag.name == "mention"
+ handle_mention_html_tag(tag, node, opts)
+ else
+ # unknown/unsupported html tags eg. hi are ignored
+ # but scanned for supported or text children
+ data_inlinehtml_tag(tag, node, opts)
+ end
+ [result, opts]
+ end
+
+ def handle_unknown_html_tag(_tag, _node, opts)
+ # unknown/unsupported html tags eg. hi are ignored
+ # but scanned for supported or text children [true, ...]
+ [true, opts]
+ end
+
+ def warn(text, element, node)
+ Rails.logger.warn "PDF-Export: #{text}\nGot #{element} at #{node.source_position.inspect}\n\n"
+ end
+ end
+
+ def generate_doc!(markdown, styling_file)
+ md2pdf = MD2PDFGenerator.new(md_to_pdf_styling(styling_file))
+ md2pdf.init_pdf(pdf)
+ md2pdf.generate!(markdown, md_to_pdf_options, ->(src) {
+ if src == logo_image_filename
+ logo_image_filename
+ else
+ attachment_image_filepath(work_package, src)
+ end
+ })
+ end
+
+ private
+
+ def md_to_pdf_styling(styling_file)
+ styling = YAML::load_file(File.join(styling_asset_path, styling_file))
+ # overwrite the paper size if it is set in the options
+ styling["page"]["page-size"] = options[:paper_size] if options[:paper_size].present?
+ styling
+ end
+
+ def md_to_pdf_options
+ # rubocop:disable Naming/VariableNumber
+ {
+ language: hyphenation_language,
+ pdf_footer: footer_date,
+ pdf_footer_2: footer_title,
+ pdf_footer_3: I18n.t("pdf_generator.page_nr_footer", page: "", total: ""),
+ pdf_header_logo: logo_image_filename,
+ pdf_header: heading
+ }
+ # rubocop:enable Naming/VariableNumber
+ end
+
+ def styling_asset_path
+ File.dirname(File.expand_path(__FILE__))
+ end
+end
diff --git a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
index cf346d0f91c7..9a1ca49c949e 100644
--- a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
+++ b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -40,16 +42,20 @@
require "open3"
class WorkPackage::PDFExport::WorkPackageListToPdf < WorkPackage::Exports::QueryExporter
- include WorkPackage::PDFExport::Common
- include WorkPackage::PDFExport::Attachments
- include WorkPackage::PDFExport::OverviewTable
- include WorkPackage::PDFExport::SumsTable
- include WorkPackage::PDFExport::WorkPackageDetail
- include WorkPackage::PDFExport::TableOfContents
- include WorkPackage::PDFExport::Page
- include WorkPackage::PDFExport::Gantt
- include WorkPackage::PDFExport::Style
- include WorkPackage::PDFExport::Cover
+ include WorkPackage::PDFExport::Common::Common
+ include WorkPackage::PDFExport::Common::Logo
+ include WorkPackage::PDFExport::Common::Attachments
+ include WorkPackage::PDFExport::Export::ExportCommon
+ include WorkPackage::PDFExport::Export::WorkPackageDetail
+ include WorkPackage::PDFExport::Export::Page
+ include WorkPackage::PDFExport::Export::Style
+ include WorkPackage::PDFExport::Export::OverviewTable
+ include WorkPackage::PDFExport::Export::SumsTable
+ include WorkPackage::PDFExport::Export::WorkPackageDetail
+ include WorkPackage::PDFExport::Export::TableOfContents
+ include WorkPackage::PDFExport::Export::Style
+ include WorkPackage::PDFExport::Export::Cover
+ include WorkPackage::PDFExport::Export::Gantt
attr_accessor :pdf,
:options
diff --git a/app/models/work_package/pdf_export/work_package_to_pdf.rb b/app/models/work_package/pdf_export/work_package_to_pdf.rb
index 9f85c9d9572b..5dcfa09dd8c8 100644
--- a/app/models/work_package/pdf_export/work_package_to_pdf.rb
+++ b/app/models/work_package/pdf_export/work_package_to_pdf.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -27,11 +29,13 @@
#++
class WorkPackage::PDFExport::WorkPackageToPdf < Exports::Exporter
- include WorkPackage::PDFExport::Common
- include WorkPackage::PDFExport::Attachments
- include WorkPackage::PDFExport::WorkPackageDetail
- include WorkPackage::PDFExport::Page
- include WorkPackage::PDFExport::Style
+ include WorkPackage::PDFExport::Common::Common
+ include WorkPackage::PDFExport::Common::Logo
+ include WorkPackage::PDFExport::Common::Attachments
+ include WorkPackage::PDFExport::Export::ExportCommon
+ include WorkPackage::PDFExport::Export::WorkPackageDetail
+ include WorkPackage::PDFExport::Export::Page
+ include WorkPackage::PDFExport::Export::Style
attr_accessor :pdf, :columns
@@ -54,7 +58,7 @@ def export!
render_work_package
success(pdf.render)
rescue StandardError => e
- Rails.logger.error { "Failed to generated PDF export: #{e} #{e.message}}." }
+ Rails.logger.error { "Failed to generate PDF export: #{e} #{e.message}}." }
error(I18n.t(:error_pdf_failed_to_export, error: e.message))
end
diff --git a/app/seeders/basic_data/color_seeder.rb b/app/seeders/basic_data/color_seeder.rb
index 225c372b704d..760ec3ed6cf5 100644
--- a/app/seeders/basic_data/color_seeder.rb
+++ b/app/seeders/basic_data/color_seeder.rb
@@ -29,6 +29,7 @@ module BasicData
class ColorSeeder < ModelSeeder
self.model_class = Color
self.seed_data_model_key = "colors"
+ self.attribute_names_for_lookups = %i[name]
def model_attributes(color_data)
{
diff --git a/app/seeders/basic_data/life_cycle_color_seeder.rb b/app/seeders/basic_data/life_cycle_color_seeder.rb
new file mode 100644
index 000000000000..835dd00cb2d8
--- /dev/null
+++ b/app/seeders/basic_data/life_cycle_color_seeder.rb
@@ -0,0 +1,44 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module BasicData
+ class LifeCycleColorSeeder < ColorSeeder
+ self.seed_data_model_key = "life_cycle_colors"
+
+ def applicable?
+ missing_color_names.any?
+ end
+
+ private
+
+ def missing_color_names
+ color_names = models_data.pluck("name")
+ color_names - Color.where(name: color_names).pluck(:name)
+ end
+ end
+end
diff --git a/app/seeders/basic_data/life_cycle_step_definition_seeder.rb b/app/seeders/basic_data/life_cycle_step_definition_seeder.rb
new file mode 100644
index 000000000000..54166f731019
--- /dev/null
+++ b/app/seeders/basic_data/life_cycle_step_definition_seeder.rb
@@ -0,0 +1,46 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+module BasicData
+ class LifeCycleStepDefinitionSeeder < ModelSeeder
+ self.model_class = Project::LifeCycleStepDefinition
+ self.seed_data_model_key = "life_cycles"
+ self.needs = [
+ BasicData::LifeCycleColorSeeder
+ ]
+
+ self.attribute_names_for_lookups = %i[name type]
+
+ def model_attributes(life_cyle_data)
+ {
+ name: life_cyle_data["name"],
+ type: life_cyle_data["type"],
+ color_id: color_id(life_cyle_data["color_name"])
+ }
+ end
+ end
+end
diff --git a/app/seeders/common.yml b/app/seeders/common.yml
index bd7e4a71f8b0..ee89fb7b1376 100644
--- a/app/seeders/common.yml
+++ b/app/seeders/common.yml
@@ -70,6 +70,23 @@ colors:
t_name: Black
hexcode: "#000000"
+life_cycle_colors:
+ - reference: :default_color_pm2_orange
+ t_name: PM2 Orange
+ hexcode: "#F7983A"
+ - reference: :default_color_pm2_purple
+ t_name: PM2 Purple
+ hexcode: "#682D91"
+ - reference: :default_color_pm2_red
+ t_name: PM2 Red
+ hexcode: "#F05823"
+ - reference: :default_color_pm2_magenta
+ t_name: PM2 Magenta
+ hexcode: "#EC038A"
+ - reference: :default_color_pm2_green_yellow
+ t_name: PM2 Green Yellow
+ hexcode: "#B1D13A"
+
document_categories:
- t_name: Documentation
position: 1
diff --git a/app/seeders/source/seed_data.rb b/app/seeders/source/seed_data.rb
index f3813a98e8c2..13f9726bfe39 100644
--- a/app/seeders/source/seed_data.rb
+++ b/app/seeders/source/seed_data.rb
@@ -60,7 +60,10 @@ def find_reference(reference, *fallbacks, default: :__unset__)
default
else
references = [reference, *fallbacks].map(&:inspect)
- message = "Nothing registered with #{'reference'.pluralize(references.count)} #{references.to_sentence(locale: false)}"
+ message = <<~STRING
+ Nothing registered with #{'reference'.pluralize(references.count)} #{references.to_sentence(locale: false)}
+ Perhaps you forgot to add the `attribute_names_for_lookups` for your seeder?
+ STRING
raise ArgumentError, message
end
end
diff --git a/app/seeders/standard.yml b/app/seeders/standard.yml
index a177de929704..0e00dea26de8 100644
--- a/app/seeders/standard.yml
+++ b/app/seeders/standard.yml
@@ -26,6 +26,36 @@
# See COPYRIGHT and LICENSE files for more details.
#++
+life_cycles:
+ - reference: :default_life_cycle_initiating
+ t_name: Initiating
+ type: Project::StageDefinition
+ color_name: :default_color_pm2_orange
+ - reference: :default_life_cycle_ready_for_planning
+ t_name: Ready for Planning
+ type: Project::GateDefinition
+ color_name: :default_color_pm2_purple
+ - reference: :default_life_cycle_planning
+ t_name: Planning
+ type: Project::StageDefinition
+ color_name: :default_color_pm2_red
+ - reference: :default_life_cycle_ready_for_executing
+ t_name: Ready for Executing
+ type: Project::GateDefinition
+ color_name: :default_color_pm2_purple
+ - reference: :default_life_cycle_executing
+ t_name: Executing
+ type: Project::StageDefinition
+ color_name: :default_color_pm2_magenta
+ - reference: :default_life_cycle_ready_for_closing
+ t_name: Ready for Closing
+ type: Project::GateDefinition
+ color_name: :default_color_pm2_purple
+ - reference: :default_life_cycle_closing
+ t_name: Closing
+ type: Project::StageDefinition
+ color_name: :default_color_pm2_green_yellow
+
priorities:
- reference: :default_priority_low
t_name: Low
diff --git a/app/seeders/standard/basic_data_seeder.rb b/app/seeders/standard/basic_data_seeder.rb
index 5c6c06c8ee29..d77525b74a16 100644
--- a/app/seeders/standard/basic_data_seeder.rb
+++ b/app/seeders/standard/basic_data_seeder.rb
@@ -37,6 +37,8 @@ def data_seeder_classes
::BasicData::TimeEntryActivitySeeder,
::BasicData::ColorSeeder,
::BasicData::ColorSchemeSeeder,
+ ::BasicData::LifeCycleColorSeeder,
+ ::BasicData::LifeCycleStepDefinitionSeeder,
::BasicData::WorkflowSeeder,
::BasicData::PrioritySeeder,
::BasicData::SettingSeeder,
diff --git a/app/views/custom_fields/_form.html.erb b/app/views/custom_fields/_form.html.erb
index f9e75001b658..c8328bf81d6c 100644
--- a/app/views/custom_fields/_form.html.erb
+++ b/app/views/custom_fields/_form.html.erb
@@ -64,7 +64,7 @@ See COPYRIGHT and LICENSE files for more details.
collapsible: true,
topMargin: true,
opReferrer: "custom-field-hierarchy",
- textMessage: "PLACEHOLDER - upgrade to Starkiller Base",
+ textMessage: I18n.t("custom_fields.upsale.custom_field_format_hierarchy"),
moreInfoLink: OpenProject::Static::Links.links[:enterprise_docs][:boards][:href]
}
%>
diff --git a/config/application.rb b/config/application.rb
index 31298b2ed02c..0b5c8cff7a79 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -75,6 +75,18 @@ class Application < Rails::Application
# set to true.
config.active_record.belongs_to_required_by_default = false
+ ###
+ # Enable raising on assignment to attr_readonly attributes. The previous
+ # behavior would allow assignment but silently not persist changes to the
+ # database.
+ # This is a rails 7.1 behaviour.
+ # Ideally this should be defined in the `config/initializers/new_framework_defaults_7_1.rb`
+ # file, but since there is a bug, that file is not loaded correctly in the production environment.
+ # Once [the issue](https://community.openproject.org/wp/59474) is solved, this configuration can
+ # be moved to the `config/initializers/new_framework_defaults_7_1.rb`.
+ #++
+ config.active_record.raise_on_assign_to_attr_readonly = true
+
# Sets up logging for STDOUT and configures the default logger formatter
# so that all environments receive level and timestamp information
#
diff --git a/config/environments/test.rb b/config/environments/test.rb
index f5826c7c4b1b..2ac8d639f9a1 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-require 'active_support/core_ext/integer/time'
+require "active_support/core_ext/integer/time"
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
@@ -52,7 +52,7 @@
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
- config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
+ config.public_file_server.headers = { "Cache-Control" => "public, max-age=3600" }
# Show full error reports and disable caching.
config.consider_all_requests_local = true
@@ -75,11 +75,11 @@
config.action_mailer.delivery_method = :test
# Silence deprecations early on for testing on CI
- deprecators.silenced = ENV['CI'].present?
+ deprecators.silenced = ENV["CI"].present?
# Print deprecation notices to the stderr.
config.active_support.deprecation =
- if ENV['CI']
+ if ENV["CI"]
:silence
else
:stderr
@@ -114,7 +114,7 @@
# Use in-memory store for testing
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
- if ENV['TEST_ENV_NUMBER']
+ if ENV["TEST_ENV_NUMBER"]
assets_cache_path = Rails.root.join("tmp/cache/assets/paralleltests#{ENV['TEST_ENV_NUMBER']}")
config.assets.cache = Sprockets::Cache::FileStore.new(assets_cache_path)
end
diff --git a/config/initializers/appsignal.rb b/config/initializers/appsignal.rb
index 7a7c9fee84ee..4159de1e877f 100644
--- a/config/initializers/appsignal.rb
+++ b/config/initializers/appsignal.rb
@@ -3,56 +3,53 @@
if OpenProject::Appsignal.enabled?
require "appsignal"
- Rails.application.configure do |app|
- config = {
- active: true,
- name: ENV.fetch("APPSIGNAL_NAME"),
- push_api_key: ENV.fetch("APPSIGNAL_KEY"),
- revision: OpenProject::VERSION.to_s,
- ignore_actions: [
- "OkComputer::OkComputerController#show",
- "OkComputer::OkComputerController#index",
- "GET::API::V3::Notifications::NotificationsAPI",
- "GET::API::V3::Notifications::NotificationsAPI#/notifications/"
- ],
- ignore_errors: [
- "Grape::Exceptions::MethodNotAllowed",
- "ActionController::UnknownFormat",
- "ActiveJob::DeserializationError",
- "Net::SMTPServerBusy"
- ],
- ignore_logs: [
- "GET /health_check"
- ]
- }
-
- if ENV["APPSIGNAL_DEBUG"] == "true"
- config[:log] = "stdout"
- config[:debug] = true
- config[:log_level] = "debug"
- end
-
- Appsignal.config = Appsignal::Config.new(
- Rails.root,
- Rails.env,
- config
- )
+ Rails.application.configure do |app|
app.middleware.insert_after(
ActionDispatch::DebugExceptions,
Appsignal::Rack::RailsInstrumentation
)
+ end
- # Extend the core log delegator
- handler = OpenProject::Appsignal.method(:exception_handler)
- OpenProject::Logging::LogDelegator.register(:appsignal, handler)
+ Appsignal.configure do |config|
+ config.active = true
+ config.name = ENV.fetch("APPSIGNAL_NAME")
+ config.push_api_key = ENV.fetch("APPSIGNAL_KEY")
+ config.revision = OpenProject::VERSION.to_s
- # Send our logs to appsignal
- if OpenProject::Appsignal.logging_enabled?
- appsignal_logger = Appsignal::Logger.new("rails")
- Rails.logger.broadcast_to(appsignal_logger)
+ if ENV["APPSIGNAL_DEBUG"] == "true"
+ config.log = "stdout"
+ config.log_level = "debug"
end
- Appsignal.start
+ config.ignore_actions = [
+ "OkComputer::OkComputerController#show",
+ "OkComputer::OkComputerController#index",
+ "GET::API::V3::Notifications::NotificationsAPI",
+ "GET::API::V3::Notifications::NotificationsAPI#/notifications/"
+ ]
+
+ config.ignore_errors = [
+ "Grape::Exceptions::MethodNotAllowed",
+ "ActionController::UnknownFormat",
+ "ActiveJob::DeserializationError",
+ "Net::SMTPServerBusy"
+ ]
+
+ config.ignore_logs = [
+ "GET /health_check"
+ ]
end
+
+ # Extend the core log delegator
+ handler = OpenProject::Appsignal.method(:exception_handler)
+ OpenProject::Logging::LogDelegator.register(:appsignal, handler)
+
+ # Send our logs to appsignal
+ if OpenProject::Appsignal.logging_enabled?
+ appsignal_logger = Appsignal::Logger.new("rails")
+ Rails.logger.broadcast_to(appsignal_logger)
+ end
+
+ Appsignal.start
end
diff --git a/config/initializers/feature_decisions.rb b/config/initializers/feature_decisions.rb
index 371c20ae6d57..1af9d4f3b80d 100644
--- a/config/initializers/feature_decisions.rb
+++ b/config/initializers/feature_decisions.rb
@@ -43,6 +43,10 @@
OpenProject::FeatureDecisions.add :built_in_oauth_applications,
description: "Allows the display and use of built-in OAuth applications."
+OpenProject::FeatureDecisions.add :generate_pdf_from_work_package,
+ description: "Allows to generate a PDF document from a work package description. " \
+ "See #45896 for details."
+
OpenProject::FeatureDecisions.add :custom_field_of_type_hierarchy,
description: "Allows the use of the custom field type 'Hierarchy'."
@@ -52,3 +56,6 @@
(Setting.exists?("feature_primerized_work_package_activities_active") &&
Setting.send(:feature_primerized_work_package_activities_active?))
end
+
+OpenProject::FeatureDecisions.add :stages_and_gates,
+ description: "Enables the under construction feature of stages and gates."
diff --git a/config/initializers/menus.rb b/config/initializers/menus.rb
index e52606a27690..33bdb9cd0d25 100644
--- a/config/initializers/menus.rb
+++ b/config/initializers/menus.rb
@@ -546,18 +546,6 @@
icon: "op-enterprise-addons",
if: proc { User.current.admin? && OpenProject::Configuration.ee_manager_visible? }
- menu.push :admin_costs,
- { controller: "/admin/settings", action: "show_plugin", id: :costs },
- if: Proc.new { User.current.admin? },
- caption: :project_module_costs,
- icon: "op-cost-reports"
-
- menu.push :costs_setting,
- { controller: "/admin/settings", action: "show_plugin", id: :costs },
- if: Proc.new { User.current.admin? },
- caption: :label_setting_plural,
- parent: :admin_costs
-
menu.push :admin_backlogs,
{ controller: "/backlogs_settings", action: :show },
if: Proc.new { User.current.admin? },
diff --git a/config/initializers/new_framework_defaults_7_1.rb b/config/initializers/new_framework_defaults_7_1.rb
index e39bd17a2107..cda7419b65dc 100644
--- a/config/initializers/new_framework_defaults_7_1.rb
+++ b/config/initializers/new_framework_defaults_7_1.rb
@@ -167,7 +167,7 @@
# behavior would allow assignment but silently not persist changes to the
# database.
#++
-# Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true
+Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true
###
# Enable validating only parent-related columns for presence when the parent is mandatory.
diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml
index cbd3a9711990..b3ff4842ba77 100644
--- a/config/locales/crowdin/af.yml
+++ b/config/locales/crowdin/af.yml
@@ -33,7 +33,7 @@ af:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ af:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ af:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml
index 21b5ef2bce8f..d91b44ba5771 100644
--- a/config/locales/crowdin/ar.yml
+++ b/config/locales/crowdin/ar.yml
@@ -33,7 +33,7 @@ ar:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ ar:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1967,6 +1969,23 @@ ar:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml
index 1b31db3c833b..5b2c8018906f 100644
--- a/config/locales/crowdin/az.yml
+++ b/config/locales/crowdin/az.yml
@@ -33,7 +33,7 @@ az:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ az:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ az:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml
index 1eaca71a9130..34ac060c7c4a 100644
--- a/config/locales/crowdin/be.yml
+++ b/config/locales/crowdin/be.yml
@@ -33,7 +33,7 @@ be:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ be:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1895,6 +1897,23 @@ be:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml
index 55b199fad409..f4b7afbf1476 100644
--- a/config/locales/crowdin/bg.yml
+++ b/config/locales/crowdin/bg.yml
@@ -33,7 +33,7 @@ bg:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ bg:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
За да добавите нови потребителски полета към даден проект, първо трябва да ги създадете, преди да можете да ги добавите към този проект.
is_enabled_globally: "Активирано е глобално"
@@ -1823,6 +1825,23 @@ bg:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml
index 8d72e94eede8..d6e45914d010 100644
--- a/config/locales/crowdin/ca.yml
+++ b/config/locales/crowdin/ca.yml
@@ -33,7 +33,7 @@ ca:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -236,6 +236,8 @@ ca:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Per afegir nous camps personalitzats a un projecte primer has de crear-los abans de poder-los afegir a aquest projecte.
is_enabled_globally: "És habilitat globalment"
@@ -1819,6 +1821,23 @@ ca:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponible (opcional)"
diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml
index 028b6469080d..1ad979811d31 100644
--- a/config/locales/crowdin/ckb-IR.yml
+++ b/config/locales/crowdin/ckb-IR.yml
@@ -33,7 +33,7 @@ ckb-IR:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ ckb-IR:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ ckb-IR:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml
index fed896cdd76e..94848e14cd15 100644
--- a/config/locales/crowdin/cs.yml
+++ b/config/locales/crowdin/cs.yml
@@ -33,10 +33,10 @@ cs:
label_activity_show_only_changes: "Zobrazit pouze změny"
label_sort_asc: "Nejnovější v dolní části"
label_sort_desc: "Nejnovější nahoře"
- label_type_to_comment: "Pro komentování pište zde"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Odeslat komentář"
changed_on: "změněno dne"
- created_on: "created this on"
+ created_on: "toto vytvořil/a dne"
changed: "změněno"
created: "vytvořeno"
commented: "komentováno"
@@ -224,7 +224,7 @@ cs:
actions: "Akce položky"
blankslate:
root:
- title: "Your list of items is empty"
+ title: "Váš seznam položek je prázdný"
description: "Start by adding items to the custom field of type hierarchy. Each item can be used to create a hierarchy bellow it. To navigate and create sub-items inside a hierarchy click on the created item."
item:
title: This item doesn't have any hierarchy level below
@@ -239,6 +239,8 @@ cs:
zero: žádné dílčí položky
one: 1 dílčí položka
other: "%{count} dílčí položky"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Chcete-li přidat nová vlastní pole do projektu, musíte je nejprve vytvořit, než je budete moci přidat do tohoto projektu.
is_enabled_globally: "Globálně povoleno"
@@ -265,8 +267,8 @@ cs:
single: "nebo"
dry_validation:
errors:
- int?: "must be an integer."
- filled?: "must be filled."
+ int?: "musí být celé číslo"
+ filled?: "musí být vyplněno"
greater_or_equal_zero: "must be greater or equal to 0."
not_found: "not found."
rules:
@@ -280,11 +282,11 @@ cs:
parent:
not_descendant: "must be a descendant of the hierarchy root."
rules:
- depth: "Depth"
- item: "Item"
- label: "Label"
- short: "Short name"
- parent: "Parent"
+ depth: "Hloubka"
+ item: "Položka"
+ label: "Popisek"
+ short: "Krátký název"
+ parent: "Nadřazený"
global_search:
placeholder: "Hledat v %{app_title}"
overwritten_tabs:
@@ -1895,6 +1897,23 @@ cs:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext k dispozici (volitelné)"
diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml
index 78f988454587..d167edaa388f 100644
--- a/config/locales/crowdin/da.yml
+++ b/config/locales/crowdin/da.yml
@@ -33,7 +33,7 @@ da:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -237,6 +237,8 @@ da:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
For at tilføje nye brugerdefinerede felter til et projekt, skal du først oprette dem, før du kan føje dem til dette projekt.
is_enabled_globally: "Er aktiveret globalt"
@@ -1821,6 +1823,23 @@ da:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml
index a8bd62e2ed5d..7d9038377e8b 100644
--- a/config/locales/crowdin/de.yml
+++ b/config/locales/crowdin/de.yml
@@ -33,7 +33,7 @@ de:
label_activity_show_only_changes: "Nur Änderungen anzeigen"
label_sort_asc: "Neueste unten"
label_sort_desc: "Neueste oben"
- label_type_to_comment: "Tippen Sie hier, um zu kommentieren"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Kommentar absenden"
changed_on: "geändert am"
created_on: "erstellte dies am"
@@ -236,6 +236,8 @@ de:
zero: keine Unterelemente
one: 1 Unterelement
other: "%{count} Unterelemente"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Um neue benutzerdefinierte Felder einem Projekt zuzuweisen, müssen Sie diese erst global erstellen, um Sie dann an dieser Stelle aktivieren zu können.
is_enabled_globally: "Für alle Projekte aktiviert"
@@ -1816,6 +1818,23 @@ de:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Seite %{page} von %{total}"
+ dialog:
+ title: PDF generieren
+ submit: Generieren
+ header_right:
+ label: Kopfzeile rechts
+ caption: Text, der rechts neben der Kopfzeile angezeigt werden soll
+ footer_center:
+ label: Fußzeile mittig
+ caption: Text, der in der Mitte der Fußzeile angezeigt werden soll
+ hyphenation:
+ label: Silbentrennung
+ caption: Wörter zwischen den Zeilen umbrechen, um die Textausrichtung und die Lesbarkeit zu verbessern.
+ paper_size:
+ label: Papierformat
+ caption: Die Größe des Papiers, das für das PDF verwendet werden soll.
extraction:
available:
pdftotext: "Pdftotext verfügbar (optional)"
diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml
index 229478e6400f..80dcdd44cd28 100644
--- a/config/locales/crowdin/el.yml
+++ b/config/locales/crowdin/el.yml
@@ -33,7 +33,7 @@ el:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -235,6 +235,8 @@ el:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Για να προσθέσετε νέα προσαρμοσμένα πεδία σε ένα έργο, πρέπει πρώτα να τα δημιουργήσετε για να τα προσθέσετε σε αυτό το έργο.
is_enabled_globally: "Είναι ενεργοποιημένο σε όλο το σύστημα"
@@ -1819,6 +1821,23 @@ el:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Το Pdftotext είναι διαθέσιμο (προαιρετικό)"
diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml
index f6c7f70d9bc0..97a5b9ec195c 100644
--- a/config/locales/crowdin/eo.yml
+++ b/config/locales/crowdin/eo.yml
@@ -33,7 +33,7 @@ eo:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ eo:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Ĉie ŝaltita"
@@ -1823,6 +1825,23 @@ eo:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdfaltekto disponebla (nedeviga)"
diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml
index 039964c82da4..4bc5056d936b 100644
--- a/config/locales/crowdin/es.yml
+++ b/config/locales/crowdin/es.yml
@@ -33,7 +33,7 @@ es:
label_activity_show_only_changes: "Mostrar solo los cambios"
label_sort_asc: "Lo más reciente en la parte inferior"
label_sort_desc: "Lo más reciente en la parte superior"
- label_type_to_comment: "Escriba aquí para comentar"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Enviar comentario"
changed_on: "cambiado el"
created_on: "creó esto el"
@@ -236,6 +236,8 @@ es:
zero: ningún subelemento
one: 1 subelemento
other: "%{count} subelementos"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Para agregar nuevos campos personalizados a un proyecto, primero debe crearlos, y luego añadirlos a este proyecto.
is_enabled_globally: "Está activado a nivel global"
@@ -1820,6 +1822,23 @@ es:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponible (opcional)"
diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml
index 33dd16c34851..5a48f35ad649 100644
--- a/config/locales/crowdin/et.yml
+++ b/config/locales/crowdin/et.yml
@@ -33,7 +33,7 @@ et:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ et:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ et:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml
index 9313c5e6ae5c..7360cb892957 100644
--- a/config/locales/crowdin/eu.yml
+++ b/config/locales/crowdin/eu.yml
@@ -33,7 +33,7 @@ eu:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ eu:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ eu:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml
index 8182d2bfc15a..4ea03aaeceba 100644
--- a/config/locales/crowdin/fa.yml
+++ b/config/locales/crowdin/fa.yml
@@ -33,7 +33,7 @@ fa:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ fa:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ fa:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml
index 5f5629a27201..44bf0b674b9c 100644
--- a/config/locales/crowdin/fi.yml
+++ b/config/locales/crowdin/fi.yml
@@ -33,7 +33,7 @@ fi:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ fi:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Jotta voit lisätä tälle projektille uusia muokattavia kenttiä, tulee sinun ensin luoda ne.
is_enabled_globally: "On käytössä kaikkialla"
@@ -1823,6 +1825,23 @@ fi:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml
index a91bc658e157..e217cba1c317 100644
--- a/config/locales/crowdin/fil.yml
+++ b/config/locales/crowdin/fil.yml
@@ -33,7 +33,7 @@ fil:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ fil:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Upang magdagdag ng mga kustom na patlang sa isang proyekto kinakailangan mo muna likhain bago ka muna sila idagdag sa proyektong ito.
is_enabled_globally: "Ay pinagana pandaigdigan"
@@ -1823,6 +1825,23 @@ fil:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext ay magagamit (opsyonal)"
diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml
index 7bda2a621e5b..58a44d36656d 100644
--- a/config/locales/crowdin/fr.yml
+++ b/config/locales/crowdin/fr.yml
@@ -33,7 +33,7 @@ fr:
label_activity_show_only_changes: "Afficher uniquement les modifications"
label_sort_asc: "Les plus récents en bas"
label_sort_desc: "Les plus récents en haut"
- label_type_to_comment: "Saisissez ici votre commentaire"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Envoyer le commentaire"
changed_on: "modifié le"
created_on: "a créé ce lot de travaux le"
@@ -239,6 +239,8 @@ fr:
zero: aucun sous-élément
one: 1 sous-élément
other: "%{count} sous-éléments"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Pour ajouter de nouveaux champs personnalisés à un projet, vous devez d’abord les créer avant de pouvoir les ajouter à ce projet.
is_enabled_globally: "Est activé globalement"
@@ -1821,6 +1823,23 @@ fr:
units:
hours: h
days: j
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponible (optionnel)"
diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml
index 1e1a885bbf0f..f87b540178f7 100644
--- a/config/locales/crowdin/he.yml
+++ b/config/locales/crowdin/he.yml
@@ -33,7 +33,7 @@ he:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ he:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1895,6 +1897,23 @@ he:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml
index 8f424cfe8293..08b64fa3d64a 100644
--- a/config/locales/crowdin/hi.yml
+++ b/config/locales/crowdin/hi.yml
@@ -33,7 +33,7 @@ hi:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ hi:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
परियोजना में नई custom fields जोडनें हेतु, पहले आपको उनका सृजन करना पडेगा, तत्पष्चात ही आप उन्हें परियोजना में जोड सकेंगे.
is_enabled_globally: "Is enabled globally"
@@ -1821,6 +1823,23 @@ hi:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext उपलब्ध (वैकल्पिक)"
diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml
index ed9e698a5113..25320ebb1d3d 100644
--- a/config/locales/crowdin/hr.yml
+++ b/config/locales/crowdin/hr.yml
@@ -33,7 +33,7 @@ hr:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ hr:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1859,6 +1861,23 @@ hr:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml
index 893f3f49172f..4870e190b85e 100644
--- a/config/locales/crowdin/hu.yml
+++ b/config/locales/crowdin/hu.yml
@@ -33,7 +33,7 @@ hu:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -238,6 +238,8 @@ hu:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Új egyéni mezők hozzáadásához először létre kell hozni őket, még mielőtt felvenné azokat a projekthez.
is_enabled_globally: "Globálisan engedélyezve van"
@@ -1820,6 +1822,23 @@ hu:
units:
hours: óra
days: nap
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext elérhető (opcionális)"
diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml
index c8b49456ed4e..4307df515f47 100644
--- a/config/locales/crowdin/id.yml
+++ b/config/locales/crowdin/id.yml
@@ -33,7 +33,7 @@ id:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -233,6 +233,8 @@ id:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Untuk menambahkan kolom kustom baru untuk sebuah proyek, pertama-tama Anda harus membuatnya, sebelum Anda dapat menambahkannya ke proyek ini.
is_enabled_globally: "Diaktifkan secara global"
@@ -1780,6 +1782,23 @@ id:
units:
hours: j
days: h
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdf2teks tersedia (opsional)"
diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml
index 4019ae02a53c..403b877a7fae 100644
--- a/config/locales/crowdin/it.yml
+++ b/config/locales/crowdin/it.yml
@@ -33,7 +33,7 @@ it:
label_activity_show_only_changes: "Mostra solo le modifiche"
label_sort_asc: "Più recenti in fondo"
label_sort_desc: "Più recenti in cima"
- label_type_to_comment: "Digita qui per commentare"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Invia commento"
changed_on: "ha modificato il"
created_on: "l'ha creata il"
@@ -236,6 +236,8 @@ it:
zero: nessun sottoelemento
one: 1 sottoelemento
other: "%{count} sottoelementi"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Per aggiungere nuovi campi personalizzati a un progetto, è necessario prima crearli.
is_enabled_globally: "Abilitato a livello globale"
@@ -1819,6 +1821,23 @@ it:
units:
hours: o
days: g
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdfatesto disponibile (opzionale)"
diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml
index 34feb775318d..e5f84c566931 100644
--- a/config/locales/crowdin/ja.yml
+++ b/config/locales/crowdin/ja.yml
@@ -33,7 +33,7 @@ ja:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -237,6 +237,8 @@ ja:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
新しいカスタムフィールドをプロジェクトに追加するには、それをこのプロジェクトに追加する前に、まず作成する必要があります。
is_enabled_globally: "グローバルで有効"
@@ -1783,6 +1785,23 @@ ja:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotextが利用可能 (オプション)"
diff --git a/config/locales/crowdin/js-af.yml b/config/locales/crowdin/js-af.yml
index 2e85ba0c0360..26d718f80818 100644
--- a/config/locales/crowdin/js-af.yml
+++ b/config/locales/crowdin/js-af.yml
@@ -105,6 +105,7 @@ af:
button_update: "Opdateer"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Skep"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ af:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-ar.yml b/config/locales/crowdin/js-ar.yml
index 2ed8f35668fb..0c7a0daa857d 100644
--- a/config/locales/crowdin/js-ar.yml
+++ b/config/locales/crowdin/js-ar.yml
@@ -105,6 +105,7 @@ ar:
button_update: "التحديث"
button_export-pdf: "تنزيل PDF"
button_export-atom: "تحميل Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "إنشاء"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ ar:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-az.yml b/config/locales/crowdin/js-az.yml
index a1e627b6cf03..46d54a4b7858 100644
--- a/config/locales/crowdin/js-az.yml
+++ b/config/locales/crowdin/js-az.yml
@@ -105,6 +105,7 @@ az:
button_update: "Yeniləmə"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ az:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-be.yml b/config/locales/crowdin/js-be.yml
index 34f8c231e8ff..7ff86dc719c8 100644
--- a/config/locales/crowdin/js-be.yml
+++ b/config/locales/crowdin/js-be.yml
@@ -105,6 +105,7 @@ be:
button_update: "Абнавіць"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ be:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-bg.yml b/config/locales/crowdin/js-bg.yml
index fd684a72a226..449c04569386 100644
--- a/config/locales/crowdin/js-bg.yml
+++ b/config/locales/crowdin/js-bg.yml
@@ -105,6 +105,7 @@ bg:
button_update: "Обнови"
button_export-pdf: "Свали PDF"
button_export-atom: "Свали Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Създаване"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ bg:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-ca.yml b/config/locales/crowdin/js-ca.yml
index 71ff3534c146..eedba654c29c 100644
--- a/config/locales/crowdin/js-ca.yml
+++ b/config/locales/crowdin/js-ca.yml
@@ -105,6 +105,7 @@ ca:
button_update: "Actualitza"
button_export-pdf: "Descarregar PDF"
button_export-atom: "Descarregar Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Crear"
card:
add_new: "Afegir nova targeta"
@@ -575,7 +576,7 @@ ca:
members: "Convida nous membres a afegir-se al teu projecte."
quick_add_button: "Fes clic a la icona de més (+) en la navegació superior per crear un nou projecte o convidar companys de feina."
sidebar_arrow: "Utilitza la fletxa de retorn a la cantonada esquerra per tornar al menú principal del projecte."
- welcome: "Segueix la introducció de tres minuts per aprendre les funcions més importants. Recomanem completar les passes fins al final. Podràs tornar a començar aquesta introducció en qualsevol moment."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Dintre de la wiki pots documentar i compartir el coneixement conjuntament amb el teu equip."
backlogs:
overview: "Administra la teva feina en vistes de treballs pendents."
diff --git a/config/locales/crowdin/js-ckb-IR.yml b/config/locales/crowdin/js-ckb-IR.yml
index 25322f5c6e10..7792e89f7283 100644
--- a/config/locales/crowdin/js-ckb-IR.yml
+++ b/config/locales/crowdin/js-ckb-IR.yml
@@ -105,6 +105,7 @@ ckb-IR:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ ckb-IR:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-cs.yml b/config/locales/crowdin/js-cs.yml
index 537e4567c8d1..392e45599ab5 100644
--- a/config/locales/crowdin/js-cs.yml
+++ b/config/locales/crowdin/js-cs.yml
@@ -105,6 +105,7 @@ cs:
button_update: "Aktualizovat"
button_export-pdf: "Stáhnout PDF"
button_export-atom: "Stáhnout Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Vytvořit"
card:
add_new: "Přidat novou kartu"
@@ -574,7 +575,7 @@ cs:
members: "Pozvěte nové členy , aby se připojili k vašemu projektu."
quick_add_button: "Klikněte na ikonu plus (+) v záhlaví pro vytvoření nového projektu nebo pro pozvání spolupracovníků."
sidebar_arrow: "Pomocí šipky zpět v levém horním rohu se vrátíte do hlavního menu projektu."
- welcome: "Naučte se během tří minut důležité funkce. Doporučujeme dokončit prohlídku až do konce. Prohlídku můžete kdykoliv restartovat."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "V rámci Wiki můžete dokumentovat a sdílet znalosti společně se svým týmem."
backlogs:
overview: "Spravujte svou práci v backlogs zobrazení."
diff --git a/config/locales/crowdin/js-da.yml b/config/locales/crowdin/js-da.yml
index 1f7260e04fb0..4b4690d6a21c 100644
--- a/config/locales/crowdin/js-da.yml
+++ b/config/locales/crowdin/js-da.yml
@@ -105,6 +105,7 @@ da:
button_update: "Opdater"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Opret"
card:
add_new: "Add new card"
@@ -574,7 +575,7 @@ da:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Tag en tre minutters introduktionsturné for at lære de mest vigtige funktioner . Vi anbefaler at du gennemfører trinende til slutningen. Du kan når som helst genstarte turen."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml
index bf7dc90d3d9e..80dbc44574c5 100644
--- a/config/locales/crowdin/js-de.yml
+++ b/config/locales/crowdin/js-de.yml
@@ -105,6 +105,7 @@ de:
button_update: "Aktualisieren"
button_export-pdf: "PDF-Download"
button_export-atom: "Atom-Download"
+ button_generate_pdf: "PDF generieren"
button_create: "Anlegen"
card:
add_new: "Neue Karte hinzufügen"
@@ -574,7 +575,7 @@ de:
members: "Sie können hier neue Mitglieder zu Ihrem Projekt hinzufügen."
quick_add_button: "Klicken Sie auf das Plus (+) Symbol in der Navigationsleiste um neue Projekte zu erzeugen oder MitarbeiterInnen einzuladen."
sidebar_arrow: "Benutzen Sie den Pfeil in der oberen linken Ecke um zum Hauptmenü des Projekts zurückzukehren."
- welcome: "Lernen Sie in drei Minuten die wichtigen Funktionen kennen. Wir empfehlen Ihnen, die Tour vollständig abzuschließen. Sie können diese jederzeit wieder neu starten."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Im Wiki können Sie gemeinsam mit dem Team Informationen dokumentieren und eine Wissensdatenbank aufbauen."
backlogs:
overview: "Verwalten Sie Ihre Arbeit in der -Backlogs Ansicht."
diff --git a/config/locales/crowdin/js-el.yml b/config/locales/crowdin/js-el.yml
index b843a70eec32..b07327f7f325 100644
--- a/config/locales/crowdin/js-el.yml
+++ b/config/locales/crowdin/js-el.yml
@@ -105,6 +105,7 @@ el:
button_update: "Ενημέρωση"
button_export-pdf: "Λήψη PDF"
button_export-atom: "Κατεβάστε το Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Δημιουργία"
card:
add_new: "Προσθέστε νέα κάρτα"
@@ -574,7 +575,7 @@ el:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Κάντε μια τρίλεπτη εισαγωγική περιήγηση για να μάθετε τα πιο σημαντικά χαρακτηριστικά. Προτείνουμε να ολοκληρώσετε τα βήματα μέχρι το τέλος. Μπορείτε να επανεκκινήσετε την περιήγηση ανά πάσα στιγμή."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-eo.yml b/config/locales/crowdin/js-eo.yml
index fab34948e671..511e38d6f0dc 100644
--- a/config/locales/crowdin/js-eo.yml
+++ b/config/locales/crowdin/js-eo.yml
@@ -105,6 +105,7 @@ eo:
button_update: "Ĝisdatigi"
button_export-pdf: "Elŝuti PDF"
button_export-atom: "Elŝuti Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Krei"
card:
add_new: "Aldoni novan karton"
@@ -575,7 +576,7 @@ eo:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-es.yml b/config/locales/crowdin/js-es.yml
index e1f4184ebf47..7e09b9c4a021 100644
--- a/config/locales/crowdin/js-es.yml
+++ b/config/locales/crowdin/js-es.yml
@@ -105,6 +105,7 @@ es:
button_update: "Actualizar"
button_export-pdf: "Descargar PDF"
button_export-atom: "Descargar Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Crear"
card:
add_new: "Añadir nueva tarjeta"
@@ -575,7 +576,7 @@ es:
members: "Invitar a nuevos miembros a unirse a tu proyecto."
quick_add_button: "Haga clic en el icono del signo más (+) en el menú de navegación del encabezado para crear un proyecto o invitar a compañeros."
sidebar_arrow: "Usa la flecha de retorno en la esquina superior izquierda para regresar al menú principal del proyecto."
- welcome: "Realice un paseo de introducción de tres minutos para conocer las funciones más importantes. Le recomendamos que complete todos los pasos. Puede volver a iniciar el paseo en cualquier momento."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "En la wiki, puede elaborar documentos y compartir conocimientos con su equipo."
backlogs:
overview: "Administre su trabajo en la vista de trabajos pendientes."
diff --git a/config/locales/crowdin/js-et.yml b/config/locales/crowdin/js-et.yml
index eda78d83c57f..de1c13f8ffde 100644
--- a/config/locales/crowdin/js-et.yml
+++ b/config/locales/crowdin/js-et.yml
@@ -105,6 +105,7 @@ et:
button_update: "Uuenda"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Loo uus"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ et:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-eu.yml b/config/locales/crowdin/js-eu.yml
index e4277f4a90d4..5ae9e1fd7e37 100644
--- a/config/locales/crowdin/js-eu.yml
+++ b/config/locales/crowdin/js-eu.yml
@@ -105,6 +105,7 @@ eu:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ eu:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-fa.yml b/config/locales/crowdin/js-fa.yml
index 1bd6049c6dd2..5ef1dc12dbe9 100644
--- a/config/locales/crowdin/js-fa.yml
+++ b/config/locales/crowdin/js-fa.yml
@@ -105,6 +105,7 @@ fa:
button_update: "به روز رسانی"
button_export-pdf: "دانلود PDF"
button_export-atom: "دریافت Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "ایجاد"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ fa:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "یک تور معرفی سه دقیقهای را برای یادگیری مهمترین ویژگی ها در پیش گیرید. وصیه میکنیم مراحل را تا پایان کامل کنید. شما می توانید تور را در هر زمان دیگری هم دوباره راه اندازی کنید."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "کار خود را در نمای backlogs مدیریت کنید."
diff --git a/config/locales/crowdin/js-fi.yml b/config/locales/crowdin/js-fi.yml
index e7af4d41e6e1..14a86b98a4dd 100644
--- a/config/locales/crowdin/js-fi.yml
+++ b/config/locales/crowdin/js-fi.yml
@@ -105,6 +105,7 @@ fi:
button_update: "Päivitä"
button_export-pdf: "Lataa PDF"
button_export-atom: "Lataa Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Uusi"
card:
add_new: "Uusi kortti"
@@ -575,7 +576,7 @@ fi:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-fil.yml b/config/locales/crowdin/js-fil.yml
index ec72e1f98195..f8246d62f2eb 100644
--- a/config/locales/crowdin/js-fil.yml
+++ b/config/locales/crowdin/js-fil.yml
@@ -105,6 +105,7 @@ fil:
button_update: "I-update"
button_export-pdf: "I-download ang PDF"
button_export-atom: "I-download ang atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Lumikha"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ fil:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-fr.yml b/config/locales/crowdin/js-fr.yml
index cd5ced7a11ae..62ac3265f18d 100644
--- a/config/locales/crowdin/js-fr.yml
+++ b/config/locales/crowdin/js-fr.yml
@@ -105,6 +105,7 @@ fr:
button_update: "Mettre à jour"
button_export-pdf: "Télécharger le PDF"
button_export-atom: "Télécharger Atom"
+ button_generate_pdf: "Générer un fichier PDF"
button_create: "Créer"
card:
add_new: "Ajouter une nouvelle carte"
@@ -188,8 +189,8 @@ fr:
without_type: "Créer un lot de travaux"
with_type: "Créer un lot de travaux (Type : %{typename})"
embedded_table:
- button: "Tableau intégré de lots de travaux"
- text: "[Placeholder] Tableau intégré de lots de travaux"
+ button: "Intégrer le lot de travaux"
+ text: "[Placeholder] Tableau du lot de travaux intégré"
embedded_calendar:
text: "[Placeholder] Calendrier embarqué"
admin:
@@ -575,7 +576,7 @@ fr:
members: "Invitez de nouveaux membres à rejoindre votre projet."
quick_add_button: "Cliquez sur l'icône plus (+) dans l'en-tête de navigation pour créer un nouveau projet ou inviter des collègues."
sidebar_arrow: "Utilisez la flèche de retour dans le coin supérieur gauche pour retourner au menu principal du projet."
- welcome: "Faites une visite d’introduction de trois minutes d’apprendre le plus de caractéristiques importantes de . il est recommandé d’avoir effectué les étapes jusqu'à la fin. Vous pouvez redémarrer la tournée à tout moment."
+ welcome: "Faites une visite d’introduction de trois minutes pour apprendre les fonctionnalités les plus importantes. Il est recommandé d’effectuer les étapes jusqu'à la fin. Vous pouvez redémarrer cette visite à tout moment."
wiki: "Dans le wiki vous pouvez documenter et partager vos connaissances avec votre équipe."
backlogs:
overview: "Gérez votre travail dans la vue backlogs."
diff --git a/config/locales/crowdin/js-he.yml b/config/locales/crowdin/js-he.yml
index 5a8d338ccb36..024e8857ca3e 100644
--- a/config/locales/crowdin/js-he.yml
+++ b/config/locales/crowdin/js-he.yml
@@ -105,6 +105,7 @@ he:
button_update: "עדכון"
button_export-pdf: "הורד קובץ PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "צור"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ he:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-hi.yml b/config/locales/crowdin/js-hi.yml
index 329cb1f25b1c..b52d35648ba9 100644
--- a/config/locales/crowdin/js-hi.yml
+++ b/config/locales/crowdin/js-hi.yml
@@ -105,6 +105,7 @@ hi:
button_update: "अद्यतन करें"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "रचना करें"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ hi:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-hr.yml b/config/locales/crowdin/js-hr.yml
index 258e305c1892..3222581a2c60 100644
--- a/config/locales/crowdin/js-hr.yml
+++ b/config/locales/crowdin/js-hr.yml
@@ -105,6 +105,7 @@ hr:
button_update: "Ažuriraj"
button_export-pdf: "Preuzmi PDF"
button_export-atom: "Preuzmite Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Stvori"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ hr:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-hu.yml b/config/locales/crowdin/js-hu.yml
index 3a3b31374ebf..613dac3c2f74 100644
--- a/config/locales/crowdin/js-hu.yml
+++ b/config/locales/crowdin/js-hu.yml
@@ -105,6 +105,7 @@ hu:
button_update: "Frissítés"
button_export-pdf: "PDF-fájl letöltése"
button_export-atom: "Atom letöltés"
+ button_generate_pdf: "Generate PDF"
button_create: "Létrehoz"
card:
add_new: "Új kártya hozzáadása"
@@ -575,7 +576,7 @@ hu:
members: "Új tagok meghívása, hogy a projekthez csatlakozzanak."
quick_add_button: "Kattintson a fejlécben található (+) ikonra hogy create a new project vagy invite coworkers."
sidebar_arrow: "Használja a vissza nyilat bal felül hogy visszatérjen a projektekhez main menu.."
- welcome: "Áldozzon három percet erre a bemutatóra, hogy megismerje a legfontosabb szolgáltatásokat Javasoljuk, hogy végezze el a lépéseket egészen a végéig. A túra bármikor újraindítható."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "A Wiki modulban tudását dokumentálhatja és megoszthatja a csapatával."
backlogs:
overview: "Munka kezelése a backlogs nézetben"
diff --git a/config/locales/crowdin/js-id.yml b/config/locales/crowdin/js-id.yml
index 4c8e30546296..4c08a0446287 100644
--- a/config/locales/crowdin/js-id.yml
+++ b/config/locales/crowdin/js-id.yml
@@ -105,6 +105,7 @@ id:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Buat baru"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ id:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-it.yml b/config/locales/crowdin/js-it.yml
index 649e90143f8f..1bea09cdd4d1 100644
--- a/config/locales/crowdin/js-it.yml
+++ b/config/locales/crowdin/js-it.yml
@@ -105,6 +105,7 @@ it:
button_update: "Aggiorna"
button_export-pdf: "Scarica PDF"
button_export-atom: "Scarica Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Crea"
card:
add_new: "Aggiungi una nuova carta"
@@ -575,7 +576,7 @@ it:
members: "Invita nuovi membri per entrare al tuo progetto."
quick_add_button: "Clicca sull'icona più (+) nella navigazione dell'intestazione per creare un nuovo progetto o per invitare colleghi."
sidebar_arrow: "Utilizza la freccia di ritorno nell'angolo in alto a sinistra per tornare al menu principale del progetto."
- welcome: "Fai un tour introduttivo di tre minuti per apprendere le funzioni importanti. Consigliamo di completare i passaggi fino alla fine. Puoi riavviare il tour in qualsiasi momento."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Nella wiki puoi documentare e condividere la conoscenza con il tuo team."
backlogs:
overview: "Gestisci il tuo lavoro nella vista backlog."
diff --git a/config/locales/crowdin/js-ja.yml b/config/locales/crowdin/js-ja.yml
index 3ee15dedf82a..3572da0769a2 100644
--- a/config/locales/crowdin/js-ja.yml
+++ b/config/locales/crowdin/js-ja.yml
@@ -106,6 +106,7 @@ ja:
button_update: "更新"
button_export-pdf: "PDFファイルをダウンロード"
button_export-atom: "Atomをダウンロード"
+ button_generate_pdf: "Generate PDF"
button_create: "作成"
card:
add_new: "新規カード追加"
@@ -576,7 +577,7 @@ ja:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "3分間の導入ツアーで、最も重要な機能を確認します。 最後まで手順を完了することをお勧めします。 ツアーはいつでも再開できます。"
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-ka.yml b/config/locales/crowdin/js-ka.yml
index de78ca5aa76c..0b038cd3d253 100644
--- a/config/locales/crowdin/js-ka.yml
+++ b/config/locales/crowdin/js-ka.yml
@@ -105,6 +105,7 @@ ka:
button_update: "განახლება"
button_export-pdf: "გადმოწერე PDF"
button_export-atom: "Atom-ის გადმოწერა"
+ button_generate_pdf: "Generate PDF"
button_create: "შექმნა"
card:
add_new: "ახალი ბარათის დამატება"
@@ -575,7 +576,7 @@ ka:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-kk.yml b/config/locales/crowdin/js-kk.yml
index ef989f591977..5840074ea858 100644
--- a/config/locales/crowdin/js-kk.yml
+++ b/config/locales/crowdin/js-kk.yml
@@ -105,6 +105,7 @@ kk:
button_update: "Жаңарту"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ kk:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-ko.yml b/config/locales/crowdin/js-ko.yml
index ebedc5034d53..692695e968fd 100644
--- a/config/locales/crowdin/js-ko.yml
+++ b/config/locales/crowdin/js-ko.yml
@@ -105,6 +105,7 @@ ko:
button_update: "업데이트"
button_export-pdf: "PDF 다운로드"
button_export-atom: "Atom 다운로드"
+ button_generate_pdf: "Generate PDF"
button_create: "만들기"
card:
add_new: "새로운 카드를 추가하다"
@@ -575,7 +576,7 @@ ko:
members: "프로젝트에 참여할 새로운 멤버를 초대하세요."
quick_add_button: "헤더 탐색에서 더하기(+) 아이콘을 클릭하여 새 프로젝트를 생성하거나 동료를 초대하세요."
sidebar_arrow: "프로젝트의 기본 메뉴로 돌아가려면 왼쪽 상단의 뒤로 화살표를 사용하세요."
- welcome: "3분 소개 투어를 보고 가장 중요한 기능에 대해 알아보세요. 끝까지 단계를 완료하는 것이 좋습니다. 언제든지 투어를 다시 시작할 수 있습니다."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Wiki에서 문서화하고 팀과 함께 지식을 공유할 수 있습니다."
backlogs:
overview: "백로그 보기에서 작업을 관리하세요."
diff --git a/config/locales/crowdin/js-lt.yml b/config/locales/crowdin/js-lt.yml
index 8dff71eb4d77..3204ee92ba07 100644
--- a/config/locales/crowdin/js-lt.yml
+++ b/config/locales/crowdin/js-lt.yml
@@ -105,6 +105,7 @@ lt:
button_update: "Atnaujinti"
button_export-pdf: "Atsisiųsti PDF"
button_export-atom: "Atsisiųsti Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Kurti"
card:
add_new: "Pridėti naują kortelę"
@@ -575,7 +576,7 @@ lt:
members: "Pakvieskite naujus narius prisijungti prie projekto."
quick_add_button: "Paspauskite pliuso (+) ženklą navigacijos antraštėje ir sukursite naują projektą arba pakviesite bendradarbius."
sidebar_arrow: "Pasinaudokite grįžimo rodykle viršutiniame kairiajame kampe grįžimui į projekto pagrindinį meniu."
- welcome: "Paskirkite tris minutes įvadinei kelionei ir išmokite daugumą svarbių sistemos galimybių. Rekomenduojame atlikti visus veiksmus iki pabaigos. Ekskursiją galite paleisti iš naujo bet kuriuo metu."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Wiki'yje galite dokumentuoti ir dalintis žiniomis su savo komandos nariais."
backlogs:
overview: "Valdykite savo darbus Darbų sąrašo vaizde."
diff --git a/config/locales/crowdin/js-lv.yml b/config/locales/crowdin/js-lv.yml
index 123b62fb6bb4..76fc5f1ec0e6 100644
--- a/config/locales/crowdin/js-lv.yml
+++ b/config/locales/crowdin/js-lv.yml
@@ -105,6 +105,7 @@ lv:
button_update: "Atjaunot"
button_export-pdf: "Lejupielādēt PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Izveidot"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ lv:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-mn.yml b/config/locales/crowdin/js-mn.yml
index 07730680615c..6998fea95619 100644
--- a/config/locales/crowdin/js-mn.yml
+++ b/config/locales/crowdin/js-mn.yml
@@ -105,6 +105,7 @@ mn:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ mn:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-ms.yml b/config/locales/crowdin/js-ms.yml
index e4691fd83b1b..8973fb8f64a5 100644
--- a/config/locales/crowdin/js-ms.yml
+++ b/config/locales/crowdin/js-ms.yml
@@ -105,6 +105,7 @@ ms:
button_update: "Kemas kini"
button_export-pdf: "Muat turun PDF"
button_export-atom: "Muat Turun Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Cipta"
card:
add_new: "Tambah kad baharu"
@@ -575,7 +576,7 @@ ms:
members: "Jemput ahli baharu untuk sertai projek anda."
quick_add_button: "Klik ikon tambah (+) dalam navigasi pengepala untuk cipta projek baharu atau untuk jemput rakan sekerja."
sidebar_arrow: "Guna anak panah kembali di sudut kiri atas untuk kembali ke menu utama projek."
- welcome: "Ambil lawatan pengenalan 3 minit untuk belajar fitur-fitur penting dengan banyak. Kami sarankan melengkapi langkah-langkah tersebut sehingga ke akhirnya. Anda boleh mula semula lawatan bila-bila masa."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Dalam wiki anda boleh mendokumentasikan dan kongsi pengetahuan bersama pasukan anda."
backlogs:
overview: "Kendalikan kerja anda dalam paparan tunggakan."
diff --git a/config/locales/crowdin/js-ne.yml b/config/locales/crowdin/js-ne.yml
index a87b44f29ec6..8dad01d65f2a 100644
--- a/config/locales/crowdin/js-ne.yml
+++ b/config/locales/crowdin/js-ne.yml
@@ -105,6 +105,7 @@ ne:
button_update: "Update"
button_export-pdf: "PDF डाउनलोड गर्नुहोस्"
button_export-atom: "एटम डाउनलोड गर्नुहोस्"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "नयाँ कार्ड थप्नुहोस्"
@@ -575,7 +576,7 @@ ne:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-nl.yml b/config/locales/crowdin/js-nl.yml
index 7a2030cfe250..15fe33cbeb87 100644
--- a/config/locales/crowdin/js-nl.yml
+++ b/config/locales/crowdin/js-nl.yml
@@ -105,6 +105,7 @@ nl:
button_update: "Bijwerken"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Maken"
card:
add_new: "Nieuwe kaart toevoegen"
@@ -575,7 +576,7 @@ nl:
members: "Nodig nieuwe leden uit om deel te nemen aan uw project."
quick_add_button: "Klik op het plus (+) pictogram in de koptekst navigatie om een nieuw project te maken of collega's uit te nodigen."
sidebar_arrow: "Gebruik de terug pijl in de linkerbovenhoek om terug te keren naar het project hoofdmenu."
- welcome: "Neem drie minuten introductie rondleiding om de meeste belangrijke kenmerken te leren. het is raadzaam de stappen uit te voeren tot het einde. U kunt de tour ieder moment opnieuw doen."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Binnen de wiki kunt u kennis delen en documenteren met uw team."
backlogs:
overview: "Beheer uw werk in de backlogs weergave."
diff --git a/config/locales/crowdin/js-no.yml b/config/locales/crowdin/js-no.yml
index 883d329932df..26e7df81cc47 100644
--- a/config/locales/crowdin/js-no.yml
+++ b/config/locales/crowdin/js-no.yml
@@ -105,6 +105,7 @@
button_update: "Oppdatèr"
button_export-pdf: "Last ned PDF"
button_export-atom: "Last ned Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Opprett"
card:
add_new: "Legg til nytt kort"
@@ -575,7 +576,7 @@
members: "Inviter nye medlemmer til å bli med i prosjektet ditt."
quick_add_button: "Klikk på plussikonet (+) i toppnavigasjonen til opprette et nytt prosjekt eller for å inviterer kolleger."
sidebar_arrow: "Bruk returpilen i øvre venstre hjørne for å gå tilbake til prosjektets hovedmeny."
- welcome: "Ta en tre minutters introduksjon for å lære de viktigste mulighetene. Vi anbefaler å fullføre alle trinnene. Du kan når som helst starte på nytt."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "I wiki kan du dokumentere og dele kunnskap sammen med teamet."
backlogs:
overview: "Administrer arbeidet ditt i - backlogs -visningen."
diff --git a/config/locales/crowdin/js-pl.yml b/config/locales/crowdin/js-pl.yml
index d6287a1855fa..522d0d058cc4 100644
--- a/config/locales/crowdin/js-pl.yml
+++ b/config/locales/crowdin/js-pl.yml
@@ -105,6 +105,7 @@ pl:
button_update: "Aktualizacja"
button_export-pdf: "Pobierz plik PDF"
button_export-atom: "Pobierz Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Utwórz"
card:
add_new: "Dodaj nową kartę"
@@ -575,7 +576,7 @@ pl:
members: "Zaproś nowych członków do swojego projektu."
quick_add_button: "Kliknij ikonę plus (+) w nawigacji nagłówka, aby utworzyć nowy projekt lub zaprosić współpracowników."
sidebar_arrow: "Użyj strzałki powrotu w lewym górnym rogu, aby wrócić do menu głównego projektu."
- welcome: "Poświęć trzy minuty na zapoznanie się z najważniejszymi funkcjami. \n Zalecamy wykonanie tych kroków do końca. Zwiedzanie można w każdej chwili zacząć od nowa."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "W wiki możesz dokumentować wiedzę i dzielić się nią z zespołem."
backlogs:
overview: "Zarządzaj swoją pracą w widoku backlogs."
diff --git a/config/locales/crowdin/js-pt-BR.yml b/config/locales/crowdin/js-pt-BR.yml
index 1c0098f23b32..3858224a93b0 100644
--- a/config/locales/crowdin/js-pt-BR.yml
+++ b/config/locales/crowdin/js-pt-BR.yml
@@ -105,6 +105,7 @@ pt-BR:
button_update: "Atualizar"
button_export-pdf: "Baixar PDF"
button_export-atom: "Baixar Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Criar"
card:
add_new: "Adicionar novo cartão"
@@ -574,7 +575,7 @@ pt-BR:
members: "Convide novos membros para participar de seu projeto."
quick_add_button: "Clique no ícone mais (+) no menu de navegação para criar um novo projeto ou para convidar colegas de trabalho."
sidebar_arrow: "Use a seta de retorno no canto superior esquerdo para retornar ao menu principal do projeto."
- welcome: "Acompanhe um tour de apresentação de 3 minutos para descobrir mais recursos importantes. Recomendamos que você conclua as etapas até o final. Você pode reiniciar o tour a qualquer momento."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Na wiki, você pode documentar e compartilhar conhecimento junto com sua equipe. "
backlogs:
overview: "Gerencie seu trabalho na visão de backlogs."
diff --git a/config/locales/crowdin/js-pt-PT.yml b/config/locales/crowdin/js-pt-PT.yml
index 12f36114d7f0..e7815ce30a05 100644
--- a/config/locales/crowdin/js-pt-PT.yml
+++ b/config/locales/crowdin/js-pt-PT.yml
@@ -105,6 +105,7 @@ pt-PT:
button_update: "Atualizar"
button_export-pdf: "Transferir PDF"
button_export-atom: "Transferir Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Criar"
card:
add_new: "Adicionar novo cartão"
@@ -575,7 +576,7 @@ pt-PT:
members: "Convide novos membros para participarem no seu projeto."
quick_add_button: "Clique no ícone mais (+) no menu de navegação para criar um novo projeto ou convidar colegas."
sidebar_arrow: "Use a seta de retorno no canto superior esquerdo para voltar ao menu principal do projeto."
- welcome: "Acompanhe um tour de apresentação de 3 minutos para descobrir mais recursos importantes. Recomendamos que conclua as etapas até ao final. Pode reiniciar o tour a qualquer momento."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Na wiki pode documentar e partilhar conhecimento com a sua equipa."
backlogs:
overview: "Faça a gestão do seu trabalho na vista de backlogs."
diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml
index b1f99b406c50..ab986e120b1b 100644
--- a/config/locales/crowdin/js-ro.yml
+++ b/config/locales/crowdin/js-ro.yml
@@ -105,6 +105,7 @@ ro:
button_update: "Actualizare"
button_export-pdf: "Descarcă PDF"
button_export-atom: "Descarcă Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Creează"
card:
add_new: "Adaugă card nou"
@@ -574,7 +575,7 @@ ro:
members: "Invitați noi membri să se alăture proiectului dumneavoastră."
quick_add_button: "Dă click pe pictograma plus (+) din antetul navigării pentru a crea un nou proiect sau invita colaboratori."
sidebar_arrow: "Folosește săgeata de întoarcere din colțul din stânga sus pentru a te întoarce în meniul al proiectului."
- welcome: "Faceți un tur introductiv de trei minute pentru a afla cele mai importante caracteristici. Vă recomandăm să parcurgeți pașii până la sfârșit. Puteți relua turul în orice moment. "
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "În cadrul Wiki puteți documenta și împărtăși cunoștințe împreună cu echipa dumneavoastră."
backlogs:
overview: "Gestionează-ți munca în vizualizarea backlogs."
diff --git a/config/locales/crowdin/js-ru.yml b/config/locales/crowdin/js-ru.yml
index a8e1013e4436..51678a9b9afc 100644
--- a/config/locales/crowdin/js-ru.yml
+++ b/config/locales/crowdin/js-ru.yml
@@ -105,6 +105,7 @@ ru:
button_update: "Обновление"
button_export-pdf: "Скачать PDF"
button_export-atom: "Скачать Atom"
+ button_generate_pdf: "Создать PDF"
button_create: "Создать"
card:
add_new: "Добавить новую карту"
diff --git a/config/locales/crowdin/js-rw.yml b/config/locales/crowdin/js-rw.yml
index 7bba3fd311a5..262eecb8f9fd 100644
--- a/config/locales/crowdin/js-rw.yml
+++ b/config/locales/crowdin/js-rw.yml
@@ -105,6 +105,7 @@ rw:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ rw:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-si.yml b/config/locales/crowdin/js-si.yml
index e2c0f71de022..7007a80fd54a 100644
--- a/config/locales/crowdin/js-si.yml
+++ b/config/locales/crowdin/js-si.yml
@@ -105,6 +105,7 @@ si:
button_update: "යාවත්කාලීන"
button_export-pdf: "PDF බාගන්න"
button_export-atom: "බාගත කරන්න පරමාණුව"
+ button_generate_pdf: "Generate PDF"
button_create: "සාදන්න"
card:
add_new: "නව කාඩ් එකතු කරන්න"
@@ -575,7 +576,7 @@ si:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "වඩාත්ම ඉගෙන ගැනීමට විනාඩි තුනක් හඳුන්වාදීමේ චාරිකාවක් ගන්න වැදගත් ලක්ෂණ. අවසානය දක්වා පියවර සම්පූර්ණ කිරීම අපි නිර්දේශ කරමු. ඔබට ඕනෑම වේලාවක සංචාරය නැවත ආරම්භ කළ හැකිය."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-sk.yml b/config/locales/crowdin/js-sk.yml
index 3618d2d0405d..02b3bf092d4b 100644
--- a/config/locales/crowdin/js-sk.yml
+++ b/config/locales/crowdin/js-sk.yml
@@ -105,6 +105,7 @@ sk:
button_update: "Aktualizovať"
button_export-pdf: "Stiahnuť PDF"
button_export-atom: "Stiahnuť Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Vytvoriť"
card:
add_new: "Pridať novú kartu"
@@ -575,7 +576,7 @@ sk:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Urobte si tri minúty čas na úvodnú prehliadku, aby ste sa naučili čo najviac dôležité funkcie. Doporučujeme dokončiť prehliadku až do konca. Prehliadku môžete kedykoľvek reštartovať."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-sl.yml b/config/locales/crowdin/js-sl.yml
index a5169c3cf2a4..6f5442e3f9c3 100644
--- a/config/locales/crowdin/js-sl.yml
+++ b/config/locales/crowdin/js-sl.yml
@@ -105,6 +105,7 @@ sl:
button_update: "Posodobi"
button_export-pdf: "Prenesi PDF"
button_export-atom: "Prenesi Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Ustvari"
card:
add_new: "Dodaj nov card"
@@ -574,7 +575,7 @@ sl:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Poglejte si tri minutni ogled, da se naučite čim več pomembne lastnosti. Priporočamo, da ogled dokončat. Ogled lahko ponovno začnete kadar koli. "
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-sr.yml b/config/locales/crowdin/js-sr.yml
index d769518db554..f5c569974268 100644
--- a/config/locales/crowdin/js-sr.yml
+++ b/config/locales/crowdin/js-sr.yml
@@ -105,6 +105,7 @@ sr:
button_update: "Ažuriraj"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ sr:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-sv.yml b/config/locales/crowdin/js-sv.yml
index 5cbb7a54465f..30796ce19fa1 100644
--- a/config/locales/crowdin/js-sv.yml
+++ b/config/locales/crowdin/js-sv.yml
@@ -105,6 +105,7 @@ sv:
button_update: "Uppdatera"
button_export-pdf: "Ladda ner PDF"
button_export-atom: "Ladda ner Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Skapa"
card:
add_new: "Lägg till kort"
@@ -574,7 +575,7 @@ sv:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Ta en tre minuters introduktionstur för att lära dig de viktigaste funktionerna. Vi rekommenderar att du slutför stegen till slutet. Du kan starta om turen när som helst."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-th.yml b/config/locales/crowdin/js-th.yml
index feec1d35ecfd..b31d7e82cc67 100644
--- a/config/locales/crowdin/js-th.yml
+++ b/config/locales/crowdin/js-th.yml
@@ -105,6 +105,7 @@ th:
button_update: "ปรับปรุง"
button_export-pdf: "ดาวน์โหลดไฟล์ PDF"
button_export-atom: "ดาวน์โหลดไฟล์ Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "สร้าง"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ th:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-tr.yml b/config/locales/crowdin/js-tr.yml
index a906f935490a..c72f093f5fd7 100644
--- a/config/locales/crowdin/js-tr.yml
+++ b/config/locales/crowdin/js-tr.yml
@@ -105,6 +105,7 @@ tr:
button_update: "Güncelleştirme"
button_export-pdf: "PDF indir"
button_export-atom: "Atom İndir"
+ button_generate_pdf: "Generate PDF"
button_create: "Oluştur"
card:
add_new: "Yeni kart ekleyin"
@@ -574,7 +575,7 @@ tr:
members: "Projenize katılmak için yeni üyeler davet edin."
quick_add_button: "Yeni bir proje oluşturmak veya iş arkadaşlarınızı davet etmek için başlık bölümündeki artı (+) simgesini tıklayın."
sidebar_arrow: "Projenin ana menüsüne dönmek için sol üst köşedeki dönüş okunu kullanın."
- welcome: "En önemli özellikleri öğrenmek için üç dakikalık bir tanıtım gezintisine çıkın. Tüm adımları tamamlamanızı öneririz. Turu istediğiniz zaman yeniden başlatabilirsiniz."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "wiki içinde belgeleyebilir ve ekibinizle birlikte bilgi paylaşabilirsiniz."
backlogs:
overview: "İşinizi birikimler görünümünde yönetin."
diff --git a/config/locales/crowdin/js-uk.yml b/config/locales/crowdin/js-uk.yml
index 6d0041718cef..131403902b4a 100644
--- a/config/locales/crowdin/js-uk.yml
+++ b/config/locales/crowdin/js-uk.yml
@@ -105,6 +105,7 @@ uk:
button_update: "Оновити"
button_export-pdf: "Завантажити PDF"
button_export-atom: "Завантажити Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Створити"
card:
add_new: "Додати нову картку"
@@ -575,7 +576,7 @@ uk:
members: "Запросіть нових учасників до свого проєкту."
quick_add_button: "Натисніть на значок плюса (+) на панелі заголовків, щоб створити новий проєкт або запросити колег."
sidebar_arrow: "Використовуйте стрілку повернення у верхньому лівому куті, щоб повернутися в головне меню проєкту."
- welcome: "Здійсніть трихвилинний ознайомчий огляд для вивчення найважливішого функціоналу. Ми рекомендуємо пройти всі кроки до завершення огляду. Ви можете повернутися до цього огляду повторно в будь-який час."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "У межах Wiki ви можете документувати знання та обмінюватися ними зі своєю командою."
backlogs:
overview: "Керуйте своєю роботою в поданні Backlogs."
diff --git a/config/locales/crowdin/js-uz.yml b/config/locales/crowdin/js-uz.yml
index 1a005a46e472..fb018f798a9e 100644
--- a/config/locales/crowdin/js-uz.yml
+++ b/config/locales/crowdin/js-uz.yml
@@ -105,6 +105,7 @@ uz:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
add_new: "Add new card"
@@ -575,7 +576,7 @@ uz:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/locales/crowdin/js-vi.yml b/config/locales/crowdin/js-vi.yml
index 3d2b36b9122d..c4417652bdc8 100644
--- a/config/locales/crowdin/js-vi.yml
+++ b/config/locales/crowdin/js-vi.yml
@@ -105,6 +105,7 @@ vi:
button_update: "Cập Nhật"
button_export-pdf: "Tải xuống PDF"
button_export-atom: "Tải xuống Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Tạo"
card:
add_new: "Thêm thẻ mới"
@@ -575,7 +576,7 @@ vi:
members: "Mời thành viên mới tham gia dự án của bạn."
quick_add_button: "Nhấp vào biểu tượng cộng (+) trong thanh điều hướng tiêu đề để tạo một dự án mới hoặc mời đồng nghiệp."
sidebar_arrow: "Sử dụng mũi tên trở lại ở góc trên bên trái để quay lại menu chính của dự án."
- welcome: "Tham gia tour giới thiệu ba phút để tìm hiểu những tính năng quan trọng nhất. Chúng tôi khuyến nghị bạn hoàn thành các bước cho đến cuối. Bạn có thể khởi động lại tour bất kỳ lúc nào."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Trong wiki, bạn có thể tài liệu hóa và chia sẻ kiến thức cùng với nhóm của bạn."
backlogs:
overview: "Quản lý công việc của bạn trong chế độ xem backlogs."
diff --git a/config/locales/crowdin/js-zh-CN.yml b/config/locales/crowdin/js-zh-CN.yml
index 4ca865a5ecb0..6207d3ac209c 100644
--- a/config/locales/crowdin/js-zh-CN.yml
+++ b/config/locales/crowdin/js-zh-CN.yml
@@ -105,6 +105,7 @@ zh-CN:
button_update: "更新"
button_export-pdf: "下载 PDF"
button_export-atom: "下载 Atom"
+ button_generate_pdf: "生成 PDF"
button_create: "创建"
card:
add_new: "添加新卡"
diff --git a/config/locales/crowdin/js-zh-TW.yml b/config/locales/crowdin/js-zh-TW.yml
index 2c7b05c2ec32..cc41b13c3a17 100644
--- a/config/locales/crowdin/js-zh-TW.yml
+++ b/config/locales/crowdin/js-zh-TW.yml
@@ -105,6 +105,7 @@ zh-TW:
button_update: "更新"
button_export-pdf: "下載 PDF"
button_export-atom: "下載 Atom"
+ button_generate_pdf: "產生PDF檔案"
button_create: "建立"
card:
add_new: "新增卡片"
diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml
index cf398007c0b2..8e09c64b61b9 100644
--- a/config/locales/crowdin/ka.yml
+++ b/config/locales/crowdin/ka.yml
@@ -33,7 +33,7 @@ ka:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ ka:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ ka:
units:
hours: სთ
days: დ
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml
index 94f43a19c492..2c000fbdc3ad 100644
--- a/config/locales/crowdin/kk.yml
+++ b/config/locales/crowdin/kk.yml
@@ -33,7 +33,7 @@ kk:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ kk:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ kk:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml
index fb67e2a2bdd3..10a883dd64ab 100644
--- a/config/locales/crowdin/ko.yml
+++ b/config/locales/crowdin/ko.yml
@@ -33,7 +33,7 @@ ko:
label_activity_show_only_changes: "변경 사항만 표시"
label_sort_asc: "오래된 순"
label_sort_desc: "최신 순"
- label_type_to_comment: "코멘트를 작성하려면 여기에 입력하세요"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "코멘트 제출"
changed_on: "- 변경함:"
created_on: "- 이 패키지를 생성함:"
@@ -239,6 +239,8 @@ ko:
zero: 하위 항목 없음
one: 하위 항목 1개
other: "하위 항목 %{count}개"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
프로젝트에 새 사용자 지정 필드를 추가하려면 먼저 해당 필드를 만들어야 합니다. 그래야 이 프로젝트에 해당 필드를 추가할 수 있습니다.
is_enabled_globally: "는 세계적으로 사용 가능합니다."
@@ -1786,6 +1788,23 @@ ko:
units:
hours: 시간
days: 일
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext 사용 가능(선택적)"
diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml
index 7e80f5254721..1c5aec89a3b0 100644
--- a/config/locales/crowdin/lt.yml
+++ b/config/locales/crowdin/lt.yml
@@ -33,7 +33,7 @@ lt:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -236,6 +236,8 @@ lt:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Norėdami pridėti naujus pritaikytus laukelius prie projekto, pirmiausia reikia juos sukurti. Tik tada yra galimybė juos pridėti prie šio projekto.
is_enabled_globally: "Yra įgalintas globaliai"
@@ -1892,6 +1894,23 @@ lt:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdf-į-tekstą pasiekiamas (pasirinktinai)"
diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml
index 0bc5b3edf07e..85d6fcaada94 100644
--- a/config/locales/crowdin/lv.yml
+++ b/config/locales/crowdin/lv.yml
@@ -33,7 +33,7 @@ lv:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ lv:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1859,6 +1861,23 @@ lv:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml
index 8965166ae81e..ddcf46c5c9b9 100644
--- a/config/locales/crowdin/mn.yml
+++ b/config/locales/crowdin/mn.yml
@@ -33,7 +33,7 @@ mn:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ mn:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ mn:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml
index 7d6c2d729c54..54d6b67d1164 100644
--- a/config/locales/crowdin/ms.yml
+++ b/config/locales/crowdin/ms.yml
@@ -33,7 +33,7 @@ ms:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -238,6 +238,8 @@ ms:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Untuk menambah ruang tersuai ke projek, anda perlu menciptanya terlebih dahulu sebelum anda boleh menambahnya ke projek ini.
is_enabled_globally: "Adalah diaktifkan secara global"
@@ -1785,6 +1787,23 @@ ms:
units:
hours: j
days: h
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "PdfkeTeks tersedia (pilihan)"
diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml
index cfb672e263be..c44d3a19b656 100644
--- a/config/locales/crowdin/ne.yml
+++ b/config/locales/crowdin/ne.yml
@@ -33,7 +33,7 @@ ne:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ ne:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ ne:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml
index f02d80730ae5..5c1cb975757b 100644
--- a/config/locales/crowdin/nl.yml
+++ b/config/locales/crowdin/nl.yml
@@ -33,7 +33,7 @@ nl:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -236,6 +236,8 @@ nl:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Om de nieuwe aangepaste velden toevoegen aan een project moet u deze eerst maken voordat u ze aan dit project toevoegen kunt.
is_enabled_globally: "Is ingeschakeld Op het hoofdniveau"
@@ -1820,6 +1822,23 @@ nl:
units:
hours: u
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext beschikbaar (optioneel)"
diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml
index 14713791f319..3db5e64463dc 100644
--- a/config/locales/crowdin/no.yml
+++ b/config/locales/crowdin/no.yml
@@ -33,7 +33,7 @@
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
For å legge til nye egendefinerte felt i et prosjekt må du først opprette dem før du kan legge dem til i dette prosjektet.
is_enabled_globally: "Er aktivert globalt"
@@ -1822,6 +1824,23 @@
units:
hours: t
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext tilgjengelig (valgfritt)"
diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml
index 75c43784ba2c..b84da75ed434 100644
--- a/config/locales/crowdin/pl.yml
+++ b/config/locales/crowdin/pl.yml
@@ -33,7 +33,7 @@ pl:
label_activity_show_only_changes: "Pokaż tylko zmiany"
label_sort_asc: "Najnowsze na końcu"
label_sort_desc: "Najnowsze na początku"
- label_type_to_comment: "Wpisz tutaj, aby skomentować"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Prześlij komentarz"
changed_on: "zmieniono"
created_on: "utworzono to"
@@ -236,6 +236,8 @@ pl:
zero: brak podelementów
one: 1 podelement
other: "Liczba podelementów: %{count}"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Aby dodać do projektu nowe pola niestandardowe, najpierw należy je utworzyć.
is_enabled_globally: "Jest włączony globalnie"
@@ -1892,6 +1894,23 @@ pl:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Dostępny konwerter Pdftotext (opcjonalny)"
diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml
index 312b2e053f54..a4798463a2c9 100644
--- a/config/locales/crowdin/pt-BR.yml
+++ b/config/locales/crowdin/pt-BR.yml
@@ -33,7 +33,7 @@ pt-BR:
label_activity_show_only_changes: "Exibir apenas alterações"
label_sort_asc: "Mais recentes embaixo"
label_sort_desc: "Mais recentes em cima"
- label_type_to_comment: "Digite aqui para comentar"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Enviar comentário"
changed_on: "alterado em"
created_on: "criou em"
@@ -238,6 +238,8 @@ pt-BR:
zero: sem subitens
one: 1 subitem
other: "%{count} subitens"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Para adicionar campos personalizados a um projeto é necessário criá-los primeiro para depois adicioná-los a este projeto.
is_enabled_globally: "Está habilitado globalmente"
@@ -1820,6 +1822,23 @@ pt-BR:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponível (opcional)"
diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml
index aadf8c2c69fa..5165b460dec2 100644
--- a/config/locales/crowdin/pt-PT.yml
+++ b/config/locales/crowdin/pt-PT.yml
@@ -33,7 +33,7 @@ pt-PT:
label_activity_show_only_changes: "Mostrar apenas alterações"
label_sort_asc: "Mais recente em baixo"
label_sort_desc: "Mais recente no topo"
- label_type_to_comment: "Escreva aqui para comentar"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submeter comentário"
changed_on: "alterou a"
created_on: "criou isto a"
@@ -237,6 +237,8 @@ pt-PT:
zero: sem sub-itens
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Para adicionar novos campos personalizados a um projeto, primeiro precisa de criá-los para depois adicioná-los a este projeto.
is_enabled_globally: "Ativado a nível global"
@@ -1820,6 +1822,23 @@ pt-PT:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponível (opcional)"
diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml
index 61a23a0f8bd7..b3e5c6d42f9d 100644
--- a/config/locales/crowdin/ro.yml
+++ b/config/locales/crowdin/ro.yml
@@ -33,7 +33,7 @@ ro:
label_activity_show_only_changes: "Arată doar modificările"
label_sort_asc: "Cele mai noi jos"
label_sort_desc: "Cele mai noi sus"
- label_type_to_comment: "Tastează aici pentru a comenta"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "a creat-o pe"
@@ -239,6 +239,8 @@ ro:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Dacă vrei să adaugi noi câmpuri personalizate în cadrul unui proiect va trebui, mai întâi, să le creezi.
is_enabled_globally: "Este activat/ă la nivel global"
@@ -1859,6 +1861,23 @@ ro:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext disponibil (opțional)"
diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml
index e5e92c59516a..6051b268f000 100644
--- a/config/locales/crowdin/ru.yml
+++ b/config/locales/crowdin/ru.yml
@@ -33,7 +33,7 @@ ru:
label_activity_show_only_changes: "Показать только изменения"
label_sort_asc: "Новые внизу"
label_sort_desc: "Новые вверху"
- label_type_to_comment: "Введите комментарий"
+ label_type_to_comment: "Добавить комментарий. Введите @ для уведомления пользователей."
label_submit_comment: "Отправить комментарий"
changed_on: "изменено"
created_on: "создано в"
@@ -224,10 +224,10 @@ ru:
blankslate:
root:
title: "Ваш список пунктов пуст"
- description: "Start by adding items to the custom field of type hierarchy. Each item can be used to create a hierarchy bellow it. To navigate and create sub-items inside a hierarchy click on the created item."
+ description: "Начните с добавления элементов в иерархическое настраиваемое поле. Каждый элемент может быть использован для создания иерархии ниже его. Чтобы переместить и создать подпункты внутри иерархии, нажмите на созданный элемент."
item:
- title: This item doesn't have any hierarchy level below
- description: Add items to this list to create sub-items inside another one
+ title: Этот элемент не имеет уровня иерархии ниже
+ description: Добавьте элементы в этот список, чтобы создать подпункты внутри другого списка
placeholder:
label: "Название элемента"
short: "Краткое имя"
@@ -238,6 +238,8 @@ ru:
zero: нет подпунктов
one: 1 подпункт
other: "%{count} подпунктов"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Прежде чем добавлять настраиваемые поля в проект, нужно создать их.
is_enabled_globally: "Разрешено в глобальном масштабе"
@@ -264,20 +266,20 @@ ru:
single: "или"
dry_validation:
errors:
- int?: "must be an integer."
- filled?: "must be filled."
- greater_or_equal_zero: "must be greater or equal to 0."
- not_found: "not found."
+ int?: "должно быть целым числом."
+ filled?: "должно быть заполнено."
+ greater_or_equal_zero: "должно быть больше или равно 0."
+ not_found: "не найдено."
rules:
item:
- root_item: "cannot be a root item."
- not_persisted: "must be an already existing item."
+ root_item: "не может быть корневым элементом."
+ not_persisted: "должно быть уже существующим элементом."
label:
- not_unique: "must be unique within the same hierarchy level."
+ not_unique: "должно быть уникальным в пределах одного уровня иерархии."
short:
- not_unique: "must be unique within the same hierarchy level."
+ not_unique: "должно быть уникальным в пределах одного уровня иерархии."
parent:
- not_descendant: "must be a descendant of the hierarchy root."
+ not_descendant: "должно быть потомком корневого уровня иерархии."
rules:
depth: "Глубина"
item: "Элемент"
@@ -1210,7 +1212,7 @@ ru:
special: "спецсимволы (например, \"%\")"
reused:
one: "уже использовался ранее. Пожалуйста, укажите другое значение."
- few: "уже использовалось ранее. Пожалуйста, укажите другое значение."
+ few: "уже использовался ранее. Пожалуйста, укажите отличающийся пароль от %{count} использованных ранее."
many: "уже использовались ранее. Пожалуйста, укажите значения отличающиеся от %{count}."
other: "уже использовалось ранее. Пожалуйста, укажите значения отличающиеся от ваших последних %{count}."
match:
@@ -1894,6 +1896,23 @@ ru:
units:
hours: ч
days: д
+ pdf_generator:
+ page_nr_footer: "Страница %{page} из %{total}"
+ dialog:
+ title: Создать PDF
+ submit: Создать
+ header_right:
+ label: Заголовок справа
+ caption: Текст, отображаемый справа от заголовка
+ footer_center:
+ label: Нижний колонтитул по центру
+ caption: Текст, отображаемый в центре нижнего колонтитула
+ hyphenation:
+ label: Расстановка переносов
+ caption: Разрыв слов между строками для улучшения выравнивания и читаемости текста.
+ paper_size:
+ label: Размер бумаги
+ caption: Размер бумаги, используемый в PDF.
extraction:
available:
pdftotext: "Pdftotext доступно (опционально)"
diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml
index 1c520ed90639..49a2b7002a2b 100644
--- a/config/locales/crowdin/rw.yml
+++ b/config/locales/crowdin/rw.yml
@@ -33,7 +33,7 @@ rw:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ rw:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ rw:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml
index 9fec0325f02e..8a00b95cb815 100644
--- a/config/locales/crowdin/si.yml
+++ b/config/locales/crowdin/si.yml
@@ -33,7 +33,7 @@ si:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ si:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
ව්යාපෘතියකට නව අභිරුචි ක්ෂේත්ර එකතු කිරීම සඳහා ඔබ මුලින්ම මෙම ව්යාපෘතියට එකතු කිරීමට පෙර ඒවා නිර්මාණය කළ යුතුය.
is_enabled_globally: "ගෝලීයව සබල කර ඇත"
@@ -1823,6 +1825,23 @@ si:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "ලබා ගත හැකි PDftotext (විකල්ප)"
diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml
index 1c4126177a0e..cd676744bcb0 100644
--- a/config/locales/crowdin/sk.yml
+++ b/config/locales/crowdin/sk.yml
@@ -33,7 +33,7 @@ sk:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ sk:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Ak chcete priradiť nové vlastné pole do projektu, je potrebné ich vytvoriť ako prvé. Následne je ich možné pridať v tomto projekte.
is_enabled_globally: "Je povolené globálne"
@@ -1895,6 +1897,23 @@ sk:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext k dispozícii (voliteľné)"
diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml
index ce5d592147dc..9ad1b106213a 100644
--- a/config/locales/crowdin/sl.yml
+++ b/config/locales/crowdin/sl.yml
@@ -33,7 +33,7 @@ sl:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -238,6 +238,8 @@ sl:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Če želite projektu dodati nova polja po meri, jih morate najprej ustvariti, preden jih lahko dodate v ta projekt.
is_enabled_globally: "Omogočeno po vsem svetu"
@@ -1892,6 +1894,23 @@ sl:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Na voljo je pdftotekst (neobvezno)"
diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml
index 1ce4b58fb1df..7d2b40625ba5 100644
--- a/config/locales/crowdin/sr.yml
+++ b/config/locales/crowdin/sr.yml
@@ -33,7 +33,7 @@ sr:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ sr:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1859,6 +1861,23 @@ sr:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml
index 187536e63337..7d6d682e29f6 100644
--- a/config/locales/crowdin/sv.yml
+++ b/config/locales/crowdin/sv.yml
@@ -33,7 +33,7 @@ sv:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ sv:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Innan du kan lägga till nya anpassade fält till ett projekt måste du skapa dessa.
is_enabled_globally: "Är aktiverad globalt"
@@ -1822,6 +1824,23 @@ sv:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext tillgängligt (tillval)"
diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml
index 9bb075afdc2c..4a523946e493 100644
--- a/config/locales/crowdin/th.yml
+++ b/config/locales/crowdin/th.yml
@@ -33,7 +33,7 @@ th:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ th:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1787,6 +1789,23 @@ th:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml
index cc9d2d3b556b..0f894243c997 100644
--- a/config/locales/crowdin/tr.yml
+++ b/config/locales/crowdin/tr.yml
@@ -33,7 +33,7 @@ tr:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ tr:
zero: alt öğe yok
one: 1 alt öğe
other: "%{count} alt öğe"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Bir projeye yeni özel alanlar eklemeden önce onları oluşturmalısınız.
is_enabled_globally: "Genel için etkinleştirildi"
@@ -1821,6 +1823,23 @@ tr:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext kullanılabilir (isteğe bağlı)"
diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml
index 9f4a86469321..afd223ef21df 100644
--- a/config/locales/crowdin/uk.yml
+++ b/config/locales/crowdin/uk.yml
@@ -33,7 +33,7 @@ uk:
label_activity_show_only_changes: "Показувати лише зміни"
label_sort_asc: "Найновіші внизу"
label_sort_desc: "Найновіші вгорі"
- label_type_to_comment: "Місце для коментаря"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Надіслати коментар"
changed_on: "змінено"
created_on: "створив(-ла)"
@@ -234,6 +234,8 @@ uk:
zero: немає піделементів
one: 1 піделемент
other: "Піделементів: %{count}"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Щоб додати нові користувальницькі поля до проекту, спочатку потрібно створити їх, перш ніж ви зможете додати їх до цього проекту.
is_enabled_globally: "Увімкнено у всьому світі"
@@ -1888,6 +1890,23 @@ uk:
units:
hours: г
days: д
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Доступний текст PDF (необов'язково)"
diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml
index 15cd95a8b310..feeab6600274 100644
--- a/config/locales/crowdin/uz.yml
+++ b/config/locales/crowdin/uz.yml
@@ -33,7 +33,7 @@ uz:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -239,6 +239,8 @@ uz:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before you can add them to this project.
is_enabled_globally: "Is enabled globally"
@@ -1823,6 +1825,23 @@ uz:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext available (optional)"
diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml
index 09d268e92148..cf7ab2e72f0e 100644
--- a/config/locales/crowdin/vi.yml
+++ b/config/locales/crowdin/vi.yml
@@ -33,7 +33,7 @@ vi:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -241,6 +241,8 @@ vi:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
Để thêm các trường tùy chỉnh mới vào một dự án, trước tiên bạn cần tạo chúng trước khi có thể thêm vào dự án này.
is_enabled_globally: "Được bật toàn cầu"
@@ -1789,6 +1791,23 @@ vi:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
pdftotext: "Pdftotext có sẵn (không bắt buộc)"
diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml
index a1813130674e..5e72b94c9818 100644
--- a/config/locales/crowdin/zh-CN.yml
+++ b/config/locales/crowdin/zh-CN.yml
@@ -33,7 +33,7 @@ zh-CN:
label_activity_show_only_changes: "仅显示更改"
label_sort_asc: "时间升序"
label_sort_desc: "时间降序"
- label_type_to_comment: "在此输入评论"
+ label_type_to_comment: "添加评论。输入 @ 以通知他人。"
label_submit_comment: "提交评论"
changed_on: "更改于"
created_on: "创建于"
@@ -236,6 +236,8 @@ zh-CN:
zero: 无子项目
one: 1个子项目
other: "%{count} 个子项目"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
要向项目添加新的自定义字段,您需要先创建字段,然后才能将其添加到此项目中。
is_enabled_globally: "已全局启用"
@@ -1782,6 +1784,23 @@ zh-CN:
units:
hours: 时
days: 天
+ pdf_generator:
+ page_nr_footer: "第 %{page} 页,共%{total} 页"
+ dialog:
+ title: 生成 PDF
+ submit: 生成
+ header_right:
+ label: 页眉右侧
+ caption: 标题右侧显示的文本
+ footer_center:
+ label: 页脚中心
+ caption: 在页脚中心显示的文本
+ hyphenation:
+ label: 断字
+ caption: 在行之间打断单词,以改进文本解释和可读性。
+ paper_size:
+ label: 纸张大小
+ caption: 用于PDF的纸张大小。
extraction:
available:
pdftotext: "Pdftotext 可用 (可选)"
diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml
index 4f191bb1869c..c6317f76735e 100644
--- a/config/locales/crowdin/zh-TW.yml
+++ b/config/locales/crowdin/zh-TW.yml
@@ -33,7 +33,7 @@ zh-TW:
label_activity_show_only_changes: "僅顯示差異"
label_sort_asc: "最新的在最下面"
label_sort_desc: "最新的在最上面"
- label_type_to_comment: "在此留言"
+ label_type_to_comment: "留言。輸入 @ 來通知他人。"
label_submit_comment: "留言"
changed_on: "異動於"
created_on: "新增於"
@@ -238,6 +238,8 @@ zh-TW:
zero: 無子項目
one: 1 個子項目
other: "%{count} 子項目"
+ upsale:
+ custom_field_format_hierarchy: "工作項目的自訂欄位需要分層嗎?"
text_add_new_custom_field: >
要加入客製欄位至一個專案,您必須先建立欄位才能將它們加入至此專案。
is_enabled_globally: "已全域啟用"
@@ -1784,6 +1786,23 @@ zh-TW:
units:
hours: 小時
days: 日
+ pdf_generator:
+ page_nr_footer: "頁面 %{page} of %{total}"
+ dialog:
+ title: 產生PDF檔案
+ submit: 產生
+ header_right:
+ label: 標題右側
+ caption: 要顯示在標頭右側的文字
+ footer_center:
+ label: 頁尾中心
+ caption: 要顯示在頁尾中央的文字
+ hyphenation:
+ label: 連字符
+ caption: 在行與行之間分隔字詞,以改善文字的正確性和可讀性。
+ paper_size:
+ label: 紙張大小
+ caption: PDF 要使用的紙張尺寸。
extraction:
available:
pdftotext: "Pdftotext 可用 (非必要)"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 81e66307eb52..203fec0fad30 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -41,7 +41,7 @@ en:
label_activity_show_only_changes: "Show changes only"
label_sort_asc: "Newest at the bottom"
label_sort_desc: "Newest on top"
- label_type_to_comment: "Type here to comment"
+ label_type_to_comment: "Add a comment. Type @ to notify people."
label_submit_comment: "Submit comment"
changed_on: "changed on"
created_on: "created this on"
@@ -263,6 +263,8 @@ en:
zero: no sub-items
one: 1 sub-item
other: "%{count} sub-items"
+ upsale:
+ custom_field_format_hierarchy: "Need a hierarchy in your custom fields for work packages?"
text_add_new_custom_field: >
To add new custom fields to a project you first need to create them before
@@ -1109,6 +1111,20 @@ en:
attributes:
project_ids:
blank: "Please select a project."
+ project/life_cycle_step_definition:
+ attributes:
+ type:
+ must_be_a_stage_or_gate: "must be either Project::StageDefinition or Project::GateDefinition"
+ project/life_cycle_step:
+ attributes:
+ type:
+ must_be_a_stage_or_gate: "must be either Project::Stage or Project::Gate"
+ must_be_a_stage: "must be a Project::Stage"
+ must_be_a_gate: "must be a Project::Gate"
+ project/gate:
+ attributes:
+ base:
+ end_date_not_allowed: "Cannot assign `end_date` to a Project::Gate"
query:
attributes:
project:
@@ -1606,7 +1622,7 @@ en:
create_new_page: "Wiki page"
date:
- abbr_day_names: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]
+ abbr_day_names: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
abbr_month_names:
[
~,
@@ -1932,6 +1948,23 @@ en:
units:
hours: h
days: d
+ pdf_generator:
+ page_nr_footer: "Page %{page} of %{total}"
+ dialog:
+ title: Generate PDF
+ submit: Generate
+ header_right:
+ label: Header right
+ caption: Text to be displayed in the right of the header
+ footer_center:
+ label: Footer center
+ caption: Text to be displayed in the center of the footer
+ hyphenation:
+ label: Hyphenation
+ caption: Break words between lines to improve text justification and readability.
+ paper_size:
+ label: Paper size
+ caption: The size of the paper to use for the PDF.
extraction:
available:
diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml
index 44daa9c4dd6d..fdae57b86244 100644
--- a/config/locales/js-en.yml
+++ b/config/locales/js-en.yml
@@ -122,6 +122,7 @@ en:
button_update: "Update"
button_export-pdf: "Download PDF"
button_export-atom: "Download Atom"
+ button_generate_pdf: "Generate PDF"
button_create: "Create"
card:
@@ -631,7 +632,7 @@ en:
members: "Invite new members to join your project."
quick_add_button: "Click on the plus (+) icon in the header navigation to create a new project or to invite coworkers."
sidebar_arrow: "Use the return arrow in the top left corner to return to the project’s main menu."
- welcome: "Take a three minutes introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
+ welcome: "Take a three-minute introduction tour to learn the most important features. We recommend completing the steps until the end. You can restart the tour any time."
wiki: "Within the wiki you can document and share knowledge together with your team."
backlogs:
overview: "Manage your work in the backlogs view."
diff --git a/config/routes.rb b/config/routes.rb
index 02699c025748..a8df9e2e0a3e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -574,6 +574,9 @@
get "hover_card" => "work_packages/hover_card#show", on: :member
+ get "generate_pdf_dialog" => "work_packages#generate_pdf_dialog", on: :member
+ post "generate_pdf" => "work_packages#generate_pdf", on: :member
+
# move bulk of wps
get "move/new" => "work_packages/moves#new", on: :collection, as: "new_move"
post "move" => "work_packages/moves#create", on: :collection, as: "move"
diff --git a/db/migrate/20241030154245_create_project_life_cycles.rb b/db/migrate/20241030154245_create_project_life_cycles.rb
new file mode 100644
index 000000000000..e3c28014eb1a
--- /dev/null
+++ b/db/migrate/20241030154245_create_project_life_cycles.rb
@@ -0,0 +1,53 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class CreateProjectLifeCycles < ActiveRecord::Migration[7.1]
+ def change
+ create_table :project_life_cycle_step_definitions do |t|
+ t.string :type
+ t.string :name
+ t.integer :position, null: true
+ t.references :color, foreign_key: true
+
+ t.timestamps
+ end
+
+ create_table :project_life_cycle_steps do |t|
+ t.string :type
+ t.date :start_date
+ t.date :end_date
+ t.boolean :active, default: false, null: false
+ t.references :project, foreign_key: true
+ t.references :definition, foreign_key: { to_table: :project_life_cycle_step_definitions }
+
+ t.timestamps
+ end
+
+ add_reference :work_packages, :project_life_cycle_step, null: true
+ end
+end
diff --git a/db/migrate/20241120103858_add_start_end_times_to_time_entries.rb b/db/migrate/20241120103858_add_start_end_times_to_time_entries.rb
new file mode 100644
index 000000000000..4d30710e517e
--- /dev/null
+++ b/db/migrate/20241120103858_add_start_end_times_to_time_entries.rb
@@ -0,0 +1,13 @@
+class AddStartEndTimesToTimeEntries < ActiveRecord::Migration[7.1]
+ def change
+ change_table :time_entries, bulk: true do |t|
+ t.integer :start_time, null: true
+ t.integer :end_time, null: true
+ end
+
+ change_table :time_entry_journals, bulk: true do |t|
+ t.integer :start_time, null: true
+ t.integer :end_time, null: true
+ end
+ end
+end
diff --git a/db/migrate/20241121094113_migrate_cost_settings_to_regular_settings.rb b/db/migrate/20241121094113_migrate_cost_settings_to_regular_settings.rb
new file mode 100644
index 000000000000..7d1c1a4b8710
--- /dev/null
+++ b/db/migrate/20241121094113_migrate_cost_settings_to_regular_settings.rb
@@ -0,0 +1,24 @@
+class MigrateCostSettingsToRegularSettings < ActiveRecord::Migration[7.1]
+ def up
+ costs_settings = Setting.plugin_costs || {}
+ if costs_settings["costs_currency"]
+ Setting.create(name: "costs_currency", value: costs_settings["costs_currency"])
+ end
+
+ if costs_settings["costs_currency_format"]
+ Setting.create(name: "costs_currency_format", value: costs_settings["costs_currency_format"])
+ end
+
+ Setting.where(name: "plugin_costs").destroy_all
+ end
+
+ def down
+ costs_settings = {
+ "costs_currency" => Setting.costs_currency,
+ "costs_currency_format" => Setting.costs_currency_format
+ }
+
+ Setting.create(name: "plugin_costs", value: costs_settings)
+ Setting.where(name: ["costs_currency", "costs_currency_format"]).destroy_all
+ end
+end
diff --git a/docker/dev/backend/scripts/setup-bim b/docker/dev/backend/scripts/setup-bim
index 4ec396b503a2..bb59a141878b 100755
--- a/docker/dev/backend/scripts/setup-bim
+++ b/docker/dev/backend/scripts/setup-bim
@@ -29,8 +29,8 @@ unzip -q COLLADA2GLTF-v2.1.5-linux.zip
mv COLLADA2GLTF-bin "/usr/local/bin/COLLADA2GLTF"
# IFCconvert
-wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.6.0-517b819-linux64.zip
-unzip -q IfcConvert-v0.6.0-517b819-linux64.zip
+wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.7.11-fea8e3a-linux64.zip
+unzip -q IfcConvert-v0.7.11-fea8e3a-linux64.zip
mv IfcConvert "/usr/local/bin/IfcConvert"
wget --quiet https://github.com/bimspot/xeokit-metadata/releases/download/1.0.1/xeokit-metadata-linux-x64.tar.gz
diff --git a/docker/prod/setup/preinstall-common.sh b/docker/prod/setup/preinstall-common.sh
index 976cc5d2b5b5..8ba635d252c1 100755
--- a/docker/prod/setup/preinstall-common.sh
+++ b/docker/prod/setup/preinstall-common.sh
@@ -77,8 +77,8 @@ if [ ! "$BIM_SUPPORT" = "false" ]; then
mv COLLADA2GLTF-bin "/usr/local/bin/COLLADA2GLTF"
# IFCconvert
- wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.6.0-517b819-linux64.zip
- unzip -q IfcConvert-v0.6.0-517b819-linux64.zip
+ wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.7.11-fea8e3a-linux64.zip
+ unzip -q IfcConvert-v0.7.11-fea8e3a-linux64.zip
mv IfcConvert "/usr/local/bin/IfcConvert"
wget --quiet https://github.com/bimspot/xeokit-metadata/releases/download/1.0.1/xeokit-metadata-linux-x64.tar.gz
diff --git a/docs/api/apiv3/components/schemas/file_link_collection_read_model.yml b/docs/api/apiv3/components/schemas/file_link_collection_read_model.yml
index 6d59d1137244..4d0693eea18e 100644
--- a/docs/api/apiv3/components/schemas/file_link_collection_read_model.yml
+++ b/docs/api/apiv3/components/schemas/file_link_collection_read_model.yml
@@ -1,28 +1,21 @@
# Schema: FileLinkCollectionReadModel
---
allOf:
- - $ref: './collection_model.yml'
+ - $ref: './paginated_collection_model.yml'
- type: object
- required:
- - _links
- - _embedded
properties:
_links:
type: object
- required:
- - self
properties:
self:
allOf:
- - $ref: "./link.yml"
+ - $ref: './link.yml'
- description: |-
This file links collection
**Resource**: FileLinkCollectionReadModel
_embedded:
type: object
- required:
- - elements
properties:
elements:
type: array
@@ -33,9 +26,17 @@ example:
_type: Collection
total: 2
count: 2
+ pageSize: 30
+ offset: 1
_links:
self:
href: '/api/v3/work_packages/42/file_links'
+ jumpTo:
+ href: '/api/v3/work_packages/42/file_links?offset=%7Boffset%7D&pageSize=30'
+ templated: true
+ changeSize:
+ href: '/api/v3/work_packages/42/file_links?offset=1&pageSize=%7Bsize%7D'
+ templated: true
_embedded:
elements:
- id: 1337
diff --git a/docs/api/apiv3/components/schemas/file_link_read_model.yml b/docs/api/apiv3/components/schemas/file_link_read_model.yml
index bcf766608739..8c912c5a4441 100644
--- a/docs/api/apiv3/components/schemas/file_link_read_model.yml
+++ b/docs/api/apiv3/components/schemas/file_link_read_model.yml
@@ -1,11 +1,6 @@
# Schema: FileLinkReadModel
---
type: object
-required:
- - id
- - _type
- - originData
- - _links
properties:
id:
type: integer
@@ -36,17 +31,6 @@ properties:
$ref: './work_package_model.yml'
_links:
type: object
- required:
- - self
- - storage
- - container
- - creator
- - permission
- - originOpen
- - staticOriginOpen
- - originOpenLocation
- - staticOriginOpenLocation
- - staticOriginDownload
properties:
self:
allOf:
@@ -166,24 +150,8 @@ example:
container:
_hint: Work package resource shortened for brevity
_type: WorkPackage
- _links:
- self:
- href: "/api/v3/work_packages/1528"
- title: Develop API
- schema:
- href: "/api/v3/work_packages/schemas/11-2"
id: 1528
subject: Develop API
- description:
- format: markdown
- raw: Develop super cool OpenProject API.
- html: "
Develop super cool OpenProject API.
"
- scheduleManually: false
- readonly: false
- startDate:
- dueDate:
- createdAt: '2014-08-29T12:40:53.860Z'
- updatedAt: '2014-08-29T12:44:41.036Z'
_links:
self:
href: /api/v3/work_package/17/file_links/1337
@@ -199,8 +167,8 @@ example:
delete:
href: /api/v3/work_package/17/file_links/1337
status:
- href: urn:openproject-org:api:v3:file-links:permission:View
- title: View
+ href: urn:openproject-org:api:v3:file-links:permission:ViewAllowed
+ title: View allowed
originOpen:
href: https://nextcloud.deathstar.rocks/index.php/f/5503?openfile=1
staticOriginOpen:
diff --git a/docs/installation-and-operations/configuration/outbound-emails/README.md b/docs/installation-and-operations/configuration/outbound-emails/README.md
index dfff551b9bac..15ca4b7005eb 100644
--- a/docs/installation-and-operations/configuration/outbound-emails/README.md
+++ b/docs/installation-and-operations/configuration/outbound-emails/README.md
@@ -47,6 +47,7 @@ These are the options that are available. Please see the [Configuration guide](.
| SMTP password | smtp_password | `OPENPROJECT_SMTP__PASSWORD` | Password for authentication against the SMTP server (when authentication is required) |
| Automatically use STARTTLS | smtp_enable_starttls_auto | `OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO` | You can enable or disable STARTTLS here in case it doesn't work. Make sure you don't login to a SMTP server over a public network when using this. Recommended to leave this on if your server supports it. Possible values: true / false |
| OpenSSL verify mode | smtp_openssl_verify_mode | `OPENPROJECT_SMTP__OPENSSL__VERIFY__MODE` | Define how the SMTP server certificate is validated. Make sure you don't just disable verification here unless both, OpenProject and SMTP servers are on a private network. Possible values: `none`, `peer`, `client_once` or `fail_if_no_peer_cert`. Note: This setting can only be set through ENV/settings |
+| SMTP Timeout | smtp_timeout | `OPENPROJECT_SMTP__TIMEOUT` | This optional setting allows you to specify the number of seconds to wait for SMTP connections to be opened and read. If the value is set too low, a `Net::OpenTimeout` or `Net::ReadTimeout` might be raised. |
## Package-based installation (DEB/RPM)
@@ -59,7 +60,7 @@ openproject config:set OPENPROJECT_SMTP__PORT=587
openproject config:set OPENPROJECT_SMTP__DOMAIN=my.domain.com
openproject config:set OPENPROJECT_SMTP__AUTHENTICATION=login
openproject config:set OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO=true
-openproject config:set OPENPROJECT_SMTP__USER_NAME="apikey"
+openproject config:set OPENPROJECT_SMTP__USER__NAME="apikey"
openproject config:set OPENPROJECT_SMTP__PASSWORD="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"
```
@@ -76,7 +77,7 @@ docker run -d \
-e OPENPROJECT_SMTP__DOMAIN=my.domain.com \
-e OPENPROJECT_SMTP__AUTHENTICATION=login \
-e OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO=true \
- -e OPENPROJECT_SMTP__USER_NAME="apikey" \
+ -e OPENPROJECT_SMTP__USER__NAME="apikey" \
-e OPENPROJECT_SMTP__PASSWORD="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" \
...
```
diff --git a/docs/release-notes/15-0-2/README.md b/docs/release-notes/15-0-2/README.md
new file mode 100644
index 000000000000..87f50df7b795
--- /dev/null
+++ b/docs/release-notes/15-0-2/README.md
@@ -0,0 +1,36 @@
+---
+title: OpenProject 15.0.2
+sidebar_navigation:
+ title: 15.0.2
+release_version: 15.0.2
+release_date: 2024-11-20
+---
+
+# OpenProject 15.0.2
+
+Release date: 2024-11-20
+
+We released OpenProject [OpenProject 15.0.2](https://community.openproject.org/versions/2158).
+The release contains several bug fixes and we recommend updating to the newest version.
+In these Release Notes, we will give an overview of important feature changes.
+At the end, you will find a complete list of all changes and bug fixes.
+
+
+
+## Bug fixes and changes
+
+
+
+
+- Bugfix: Work package creation event not displayed if aggregation includes a comment \[[#58738](https://community.openproject.org/wp/58738)\]
+- Bugfix: Error toast giving a 500 error without relevant details \[[#59065](https://community.openproject.org/wp/59065)\]
+- Bugfix: The comment box remains open and does not blur on submitting comment \[[#59279](https://community.openproject.org/wp/59279)\]
+- Bugfix: Split screen activity tab does not scroll to the right position from list view \[[#59281](https://community.openproject.org/wp/59281)\]
+- Bugfix: Storage in copied project does not have the correct Project Folder setting \[[#59344](https://community.openproject.org/wp/59344)\]
+- Bugfix: Cannot change limit\_self\_registration for SAML auth providers \[[#59370](https://community.openproject.org/wp/59370)\]
+- Bugfix: Option to limit\_self\_registration in SAML provider not respected \[[#59375](https://community.openproject.org/wp/59375)\]
+- Bugfix: Migration of SAML auth providers doesn't retain limit\_self\_registration \[[#59403](https://community.openproject.org/wp/59403)\]
+- Bugfix: OpenID connect does not allow setting custom scopes \[[#59430](https://community.openproject.org/wp/59430)\]
+
+
+
diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md
index 495306a14982..0aa676ccdc3e 100644
--- a/docs/release-notes/README.md
+++ b/docs/release-notes/README.md
@@ -13,6 +13,13 @@ Stay up to date and get an overview of the new features included in the releases
+## 15.0.2
+
+Release date: 2024-11-20
+
+[Release Notes](15-0-2/)
+
+
## 15.0.1
Release date: 2024-11-13
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index eca0153a8903..717841455470 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -4086,9 +4086,9 @@
}
},
"node_modules/@ngx-formly/core": {
- "version": "6.3.10",
- "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.10.tgz",
- "integrity": "sha512-YWS+0ts3aeyX7iQQop3exffmKsub5ZD18EnZPuoHSCCglLRS0tB8ra3kFTaYT0dyc8mXRQyES9TulbX9+ZdRFg==",
+ "version": "6.3.11",
+ "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.11.tgz",
+ "integrity": "sha512-C/k1bbBjIKM5SnpGl9eHe0EcTlXlxYBg9u5JCWuh8GgR2BPXAaBcXfTcsrp4SRDLSXre/GyxWt4iCLjPWCZ/ug==",
"dependencies": {
"tslib": "^2.0.0"
},
@@ -5544,9 +5544,9 @@
"dev": true
},
"node_modules/@types/hotwired__turbo": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/@types/hotwired__turbo/-/hotwired__turbo-8.0.1.tgz",
- "integrity": "sha512-EloDlDDxlicl22+gFc77f7j16b8nCUvy6iyCtpICTlofAJfMCfnXNC8nYXCnVApes3BtWklAc2f3RKQgpaaFRQ=="
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@types/hotwired__turbo/-/hotwired__turbo-8.0.2.tgz",
+ "integrity": "sha512-fFWI/JNSTVKTPliSOV4fdeC3Kt3FUTbRYkvtF7QPCkqR51+AJWIiX0T5sJXwUnjL9j43tzfBXPZ2jEsBqw8/Bg=="
},
"node_modules/@types/http-errors": {
"version": "2.0.1",
@@ -8941,9 +8941,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -24780,9 +24780,9 @@
"integrity": "sha512-SfTCbplt4y6ak5cf2IfqdoVOsnoNdh/j6Vu+wb8WWABKwZ5yfr2S/Gk6ithSKcdIZhAF8DNBOoyk1EJuf8Xkfg=="
},
"@ngx-formly/core": {
- "version": "6.3.10",
- "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.10.tgz",
- "integrity": "sha512-YWS+0ts3aeyX7iQQop3exffmKsub5ZD18EnZPuoHSCCglLRS0tB8ra3kFTaYT0dyc8mXRQyES9TulbX9+ZdRFg==",
+ "version": "6.3.11",
+ "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.11.tgz",
+ "integrity": "sha512-C/k1bbBjIKM5SnpGl9eHe0EcTlXlxYBg9u5JCWuh8GgR2BPXAaBcXfTcsrp4SRDLSXre/GyxWt4iCLjPWCZ/ug==",
"requires": {
"tslib": "^2.0.0"
}
@@ -25805,9 +25805,9 @@
"dev": true
},
"@types/hotwired__turbo": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/@types/hotwired__turbo/-/hotwired__turbo-8.0.1.tgz",
- "integrity": "sha512-EloDlDDxlicl22+gFc77f7j16b8nCUvy6iyCtpICTlofAJfMCfnXNC8nYXCnVApes3BtWklAc2f3RKQgpaaFRQ=="
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@types/hotwired__turbo/-/hotwired__turbo-8.0.2.tgz",
+ "integrity": "sha512-fFWI/JNSTVKTPliSOV4fdeC3Kt3FUTbRYkvtF7QPCkqR51+AJWIiX0T5sJXwUnjL9j43tzfBXPZ2jEsBqw8/Bg=="
},
"@types/http-errors": {
"version": "2.0.1",
@@ -28303,9 +28303,9 @@
}
},
"cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
diff --git a/frontend/src/app/core/state/file-links/file-links.service.ts b/frontend/src/app/core/state/file-links/file-links.service.ts
index 67735b9b7ed7..c2626f87c193 100644
--- a/frontend/src/app/core/state/file-links/file-links.service.ts
+++ b/frontend/src/app/core/state/file-links/file-links.service.ts
@@ -88,7 +88,7 @@ export class FileLinksResourceService extends ResourceStoreService {
}),
tap((fileLinkCollections) => {
const storageId = idFromLink(fileLinkCollections.storage);
- const collectionKey = `${fileLinksSelfLink}?filters=[{"storage":{"operator":"=","values":["${storageId}"]}}]`;
+ const collectionKey = `${fileLinksSelfLink}?pageSize=-1&filters=[{"storage":{"operator":"=","values":["${storageId}"]}}]`;
const collection = { _embedded: { elements: fileLinkCollections.fileLinks } } as IHALCollection;
insertCollectionIntoState(this.store, collection, collectionKey);
}),
diff --git a/frontend/src/app/features/work-packages/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts b/frontend/src/app/features/work-packages/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts
index 05d78208de17..5233ec01d478 100644
--- a/frontend/src/app/features/work-packages/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts
+++ b/frontend/src/app/features/work-packages/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts
@@ -91,7 +91,7 @@ export class WorkPackageContextMenuHelperService {
// remove some actions on Gantt
if (this.wpViewTimeline.isVisible) {
allowedActions = allowedActions.filter((el) => {
- const ganttNotAllowedActions = ['log_time', 'copy', 'copy_to_other_project', 'export-pdf', 'export-atom', 'log_costs'];
+ const ganttNotAllowedActions = ['log_time', 'copy', 'copy_to_other_project', 'export-pdf', 'generate_pdf', 'export-atom', 'log_costs'];
return !(ganttNotAllowedActions.includes(el.key));
});
}
diff --git a/frontend/src/app/features/work-packages/components/wp-tabs/services/wp-tabs/wp-files-count.function.ts b/frontend/src/app/features/work-packages/components/wp-tabs/services/wp-tabs/wp-files-count.function.ts
index 36f6bed47e36..dfc00da48d04 100644
--- a/frontend/src/app/features/work-packages/components/wp-tabs/services/wp-tabs/wp-files-count.function.ts
+++ b/frontend/src/app/features/work-packages/components/wp-tabs/services/wp-tabs/wp-files-count.function.ts
@@ -27,26 +27,38 @@
//++
import { Injector } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
import { combineLatest, Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
-import { FileLinksResourceService } from 'core-app/core/state/file-links/file-links.service';
import { AttachmentsResourceService } from 'core-app/core/state/attachments/attachments.service';
+import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
+import { IFileLink } from 'core-app/core/state/file-links/file-link.model';
export function workPackageFilesCount(
workPackage:WorkPackageResource,
injector:Injector,
):Observable {
const attachmentService = injector.get(AttachmentsResourceService);
- const fileLinkService = injector.get(FileLinksResourceService);
+ const http = injector.get(HttpClient);
const attachmentsCollection = workPackage.$links.attachments
? attachmentService.collection(workPackage.$links.attachments.href || '')
: of([]);
- const fileLinksCollection = fileLinkService.collection(workPackage.$links.fileLinks?.href || '');
+ const totalFileLinks = workPackage.$links.fileLinks
+ ? http.get>(href(workPackage))
+ : of({ total: 0 });
return combineLatest([
attachmentsCollection,
- fileLinksCollection,
- ]).pipe(map(([a, f]) => a.length + f.length));
+ totalFileLinks,
+ ]).pipe(map(([a, f]) => a.length + f.total));
+}
+
+function href(workPackage:WorkPackageResource):string {
+ if (!workPackage.$links.fileLinks) {
+ return '';
+ }
+
+ return `${workPackage.$links.fileLinks.href}?pageSize=0`;
}
diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts
index 2dfd8da37984..89a8259fc5f0 100644
--- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts
+++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts
@@ -19,6 +19,7 @@ import { TimeEntryCreateService } from 'core-app/shared/components/time_entries/
import { WpDestroyModalComponent } from 'core-app/shared/components/modals/wp-destroy-modal/wp-destroy.modal';
import { WorkPackageAuthorization } from 'core-app/features/work-packages/services/work-package-authorization.service';
import * as moment from 'moment-timezone';
+import { TurboRequestsService } from 'core-app/core/turbo/turbo-requests.service';
@Directive({
selector: '[wpSingleContextMenu]',
@@ -34,6 +35,7 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger
readonly PathHelper:PathHelperService,
readonly elementRef:ElementRef,
readonly opModalService:OpModalService,
+ readonly turboRequests:TurboRequestsService,
readonly opContextMenuService:OPContextMenuService,
readonly authorisationService:AuthorisationService,
protected copyToClipboardService:CopyToClipboardService,
@@ -74,6 +76,9 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger
// do nothing, the user closed without changes
});
break;
+ case 'generate_pdf':
+ void this.turboRequests.requestStream(link as string);
+ break;
case 'copy_link_to_clipboard': {
const url = new URL(String(link), window.location.origin);
this.copyToClipboardService.copy(url.toString());
diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts
index cd1ae3a3eed3..4a2e0d82f146 100644
--- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts
+++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts
@@ -35,6 +35,11 @@ export const PERMITTED_CONTEXT_MENU_ACTIONS:WorkPackageAction[] = [
key: 'export-pdf',
link: 'pdf',
},
+ {
+ key: 'generate_pdf',
+ link: 'generate_pdf',
+ icon: 'icon-export-pdf-with-descriptions',
+ },
{
key: 'export-atom',
link: 'atom',
diff --git a/frontend/src/app/shared/components/storages/storage/storage.component.ts b/frontend/src/app/shared/components/storages/storage/storage.component.ts
index dd967426192e..9877227ab475 100644
--- a/frontend/src/app/shared/components/storages/storage/storage.component.ts
+++ b/frontend/src/app/shared/components/storages/storage/storage.component.ts
@@ -84,6 +84,7 @@ import { IUploadLink } from 'core-app/core/state/storage-files/upload-link.model
import { IStorageFile } from 'core-app/core/state/storage-files/storage-file.model';
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
+import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import {
UploadConflictModalComponent,
} from 'core-app/shared/components/storages/upload-conflict-modal/upload-conflict-modal.component';
@@ -546,8 +547,8 @@ export class StorageComponent extends UntilDestroyedMixin implements OnInit, OnD
}
private fileLinkSelfLink(storage:IStorage):string {
- const fileLinks = this.resource.fileLinks as { href:string };
- return `${fileLinks.href}?filters=[{"storage":{"operator":"=","values":["${storage.id}"]}}]`;
+ const fileLinks = (this.resource as WorkPackageResource).$links.fileLinks;
+ return `${fileLinks?.href}?pageSize=-1&filters=[{"storage":{"operator":"=","values":["${storage.id}"]}}]`;
}
public onDropFiles(event:DragEvent):void {
diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/index.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/index.controller.ts
index ef02a67e404a..9df5c036f223 100644
--- a/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/index.controller.ts
+++ b/frontend/src/stimulus/controllers/dynamic/work-packages/activities-tab/index.controller.ts
@@ -355,15 +355,22 @@ export default class IndexController extends Controller {
}
}
- private scrollToActivity(activityId:string) {
+ private tryScroll(activityId:string, attempts:number, maxAttempts:number) {
const scrollableContainer = this.getScrollableContainer();
const activityElement = document.getElementById(`activity-anchor-${activityId}`);
if (activityElement && scrollableContainer) {
- scrollableContainer.scrollTop = activityElement.offsetTop-70;
+ scrollableContainer.scrollTop = activityElement.offsetTop - 70;
+ } else if (attempts < maxAttempts) {
+ setTimeout(() => this.tryScroll(activityId, attempts + 1, maxAttempts), 1000);
}
}
+ private scrollToActivity(activityId:string) {
+ const maxAttempts = 20; // wait max 20 seconds for the activity to be rendered
+ this.tryScroll(activityId, 0, maxAttempts);
+ }
+
private scrollToBottom() {
const scrollableContainer = this.getScrollableContainer();
if (scrollableContainer) {
diff --git a/lib/api/v3/activities/activity_eager_loading_wrapper.rb b/lib/api/v3/activities/activity_eager_loading_wrapper.rb
index b21a7abc355a..8b7f20a61238 100644
--- a/lib/api/v3/activities/activity_eager_loading_wrapper.rb
+++ b/lib/api/v3/activities/activity_eager_loading_wrapper.rb
@@ -36,6 +36,7 @@ def wrap(journals)
set_journable(journals)
set_predecessor(journals)
set_data(journals)
+ set_notifications(journals)
end
super
@@ -72,6 +73,20 @@ def set_data(journals)
end
end
+ def set_notifications(journals)
+ notifications = Notification
+ .where(journal_id: journals.map(&:id))
+ .where(read_ian: false)
+ .group_by(&:journal_id)
+
+ journals.each do |journal|
+ journal.instance_variable_set(
+ :@unread_notifications,
+ notifications[journal.id]
+ )
+ end
+ end
+
def journable_by_type_and_id(journals)
journals
.group_by(&:journable_type)
diff --git a/lib/api/v3/custom_fields/hierarchy/hierarchy_item_representer.rb b/lib/api/v3/custom_fields/hierarchy/hierarchy_item_representer.rb
index c978dd7993c4..fc527c011e99 100644
--- a/lib/api/v3/custom_fields/hierarchy/hierarchy_item_representer.rb
+++ b/lib/api/v3/custom_fields/hierarchy/hierarchy_item_representer.rb
@@ -36,7 +36,13 @@ def _type
end
self_link path: :custom_field_item,
- title_getter: ->(*) { represented.label }
+ title_getter: ->(*) do
+ if represented.short.nil?
+ represented.label
+ else
+ "#{represented.label} (#{represented.short})"
+ end
+ end
property :id
diff --git a/lib/api/v3/work_packages/work_package_representer.rb b/lib/api/v3/work_packages/work_package_representer.rb
index 46c02c3deb4c..20ea4a61abe7 100644
--- a/lib/api/v3/work_packages/work_package_representer.rb
+++ b/lib/api/v3/work_packages/work_package_representer.rb
@@ -133,6 +133,19 @@ def self_v3_path(*)
}
end
+ link :generate_pdf,
+ cache_if: -> { export_work_packages_allowed? } do
+ next if represented.new_record?
+
+ next unless OpenProject::FeatureDecisions.generate_pdf_from_work_package_active?
+
+ {
+ href: generate_pdf_dialog_work_package_path(id: represented.id),
+ type: "application/pdf",
+ title: "Generate PDF"
+ }
+ end
+
link :atom,
cache_if: -> { export_work_packages_allowed? } do
next if represented.new_record? || !Setting.feeds_enabled?
diff --git a/lib/open_project/patches/mailer_controller_preview.rb b/lib/open_project/patches/mailer_controller_preview.rb
index 8f516840e246..04090d2d853f 100644
--- a/lib/open_project/patches/mailer_controller_preview.rb
+++ b/lib/open_project/patches/mailer_controller_preview.rb
@@ -41,6 +41,6 @@ def extend_content_security_policy
end
end
-OpenProject::Patches.patch_gem_version "rails", "7.1.4.1" do
+OpenProject::Patches.patch_gem_version "rails", "7.1.5" do
Rails::MailersController.include OpenProject::Patches::MailerControllerCsp
end
diff --git a/modules/auth_saml/app/models/saml/provider.rb b/modules/auth_saml/app/models/saml/provider.rb
index 515c3a42d67c..341bc594342c 100644
--- a/modules/auth_saml/app/models/saml/provider.rb
+++ b/modules/auth_saml/app/models/saml/provider.rb
@@ -97,7 +97,7 @@ def loaded_idp_certificates
end
def idp_certificate_configured?
- idp_cert.present?
+ idp_cert.present? || idp_cert_fingerprint.present?
end
def idp_certificate_valid?
diff --git a/modules/bim/app/seeders/bim/basic_data_seeder.rb b/modules/bim/app/seeders/bim/basic_data_seeder.rb
index fd404d89db3b..d153b2e42273 100644
--- a/modules/bim/app/seeders/bim/basic_data_seeder.rb
+++ b/modules/bim/app/seeders/bim/basic_data_seeder.rb
@@ -37,6 +37,8 @@ def data_seeder_classes
::BasicData::TimeEntryActivitySeeder,
::BasicData::ColorSeeder,
::BasicData::ColorSchemeSeeder,
+ ::BasicData::LifeCycleColorSeeder,
+ ::BasicData::LifeCycleStepDefinitionSeeder,
::BasicData::WorkflowSeeder,
::BasicData::PrioritySeeder,
::Bim::BasicData::SettingSeeder,
diff --git a/modules/bim/bin/setup_dev.sh b/modules/bim/bin/setup_dev.sh
index 25104c5e7006..b4484b55f872 100755
--- a/modules/bim/bin/setup_dev.sh
+++ b/modules/bim/bin/setup_dev.sh
@@ -25,8 +25,8 @@ unzip -q COLLADA2GLTF-v2.1.5-linux.zip
mv COLLADA2GLTF-bin "/usr/local/bin/COLLADA2GLTF"
# IFCconvert
-wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.6.0-517b819-linux64.zip
-unzip -q IfcConvert-v0.6.0-517b819-linux64.zip
+wget --quiet https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.7.11-fea8e3a-linux64.zip
+unzip -q IfcConvert-v0.7.11-fea8e3a-linux64.zip
mv IfcConvert "/usr/local/bin/IfcConvert"
wget --quiet https://github.com/bimspot/xeokit-metadata/releases/download/1.0.1/xeokit-metadata-linux-x64.tar.gz
diff --git a/modules/bim/config/locales/crowdin/js-fa.yml b/modules/bim/config/locales/crowdin/js-fa.yml
index c8c3844fdff0..9adfc6ead415 100644
--- a/modules/bim/config/locales/crowdin/js-fa.yml
+++ b/modules/bim/config/locales/crowdin/js-fa.yml
@@ -12,8 +12,8 @@ fa:
show_viewpoint: 'Show viewpoint'
delete_viewpoint: 'Delete viewpoint'
management: 'BCF management'
- refresh: 'Refresh'
- refresh_work_package: 'Refresh work package'
+ refresh: 'بازنشانی'
+ refresh_work_package: 'بازنشانی بسته کار'
ifc_models:
empty_warning: "This project does not yet have any IFC models."
use_this_link_to_manage: "Use this link to upload and manage your IFC models"
diff --git a/modules/bim/config/locales/crowdin/ru.seeders.yml b/modules/bim/config/locales/crowdin/ru.seeders.yml
index d709222a3d9a..46fe7461889d 100644
--- a/modules/bim/config/locales/crowdin/ru.seeders.yml
+++ b/modules/bim/config/locales/crowdin/ru.seeders.yml
@@ -75,16 +75,16 @@ ru:
text: |
Ознакомьтесь с демонстрационными проектами, чтобы начать работу с некоторыми примерами.
- * [(Демонстрационный) Проект разработки]({{Настройка:base_url}}/projects/demo-construction-project): Планирование, BIM-процесс, управление BCF и создание - все с первого взгляда.
- * [(Демо) Планирование и разработка]({{{{opSetting:base_url}}Настройка параметров:base_url}}/projects/demo-planning-constructing-project): Классическое планирование и управление разработкой.
- * [(Демо) Bim-проект]({{opSetting:base_url}}/projects/demo-bim-project): BIM-процесс и координация.
- * [(Демо) Управление BCF]({{opSetting:base_url}}/projects/demo-bcf-management-project): управление BCF.
+ * [(Demo) Проект постройки]({{opSetting:base_url}}/projects/demo-construction-project): Планирование, BIM процессы, BCF управление и стройка, всё в одном месте.
+ * [(Demo) Планирование и стройка]({{opSetting:base_url}}/projects/demo-planning-constructing-project): Классическое планирование и управление стройкой.
+ * [(Demo) BIM проект]({{opSetting:base_url}}/projects/demo-bim-project): BIM процесс и координация.
+ * [(Demo) BCF управление]({{opSetting:base_url}}/projects/demo-bcf-management-project): BCF управление.
- Также вы можете создать пустой [новый проект]({{opSetting:base_url}}/projects/new).
+ Также, вы можете создать пустой [новый проект]({{opSetting:base_url}}/projects/new).
- Никогда не прекращайте сотрудничество. С открытым исходным кодом и непредвзятым мышлением.
+ Неикогда не прекращайте сотрудничество. С открытым исходным кодом и непредвзятым мышлением.
- Вы можете изменить этот текст приветствия [здесь]({{opSetting:base_url}}/admin/settings/general).
+ Вы можете именить этот текст приветствия [здесь]({{opSetting:base_url}}/admin/settings/general).
projects:
demo-construction-project:
name: "(Демо) Конструкторский проект"
@@ -120,7 +120,25 @@ ru:
options:
name: Приступая к работе
text: |
- shared with me
+ Мы рады, что Вы присоединились! Предлагаем Вам попробовать несколько функций для начала работы в OpenProject.
+
+ Но прежде чем приступить к работе, Вам следует знать, что этот демонстрационный проект разделён на два разных проекта:
+
+ 1. [Проект постройки]({{opSetting:base_url}}/projects/demo-planning-constructing-project): Здесь вы найдёте классические роли, некоторые рабочие потоки и пакеты работ вашего проекта стройки.
+ 2. [Создание BIM модели]({{opSetting:base_url}}/projects/demo-bim-project): Этот проект так же предлагает к ознакомлению роли, рабочие потоки и пакеты работ, но в контексте BIM
+
+ _Попробуйте выполнить следующие шаги:_
+
+ 1. _Пригласите новых участников в Ваш проект_: → Перейдите [Участники]({{opSetting:base_url}}/projects/demo-construction-project/members) в меню навигации по проекту.
+ 2. _Посмотрите работы в Вашем проекте_: → Перейдите [Пакеты работ]({{opSetting:base_url}}/projects/demo-construction-project/work_packages?query_props=%7B%22c%22%3A%5B%22type%22%2C%22id%22%2C%22subject%22%2C%22status%22%2C%22assignee%22%2C%22priority%22%5D%2C%22hl%22%3A%22priority%22%2C%22hi%22%3Atrue%2C%22g%22%3A%22%22%2C%22t%22%3A%22startDate%3Aasc%22%2C%22f%22%3A%5B%7B%22n%22%3A%22bcfIssueAssociated%22%2C%22o%22%3A%22%3D%22%2C%22v%22%3A%5B%22f%22%5D%7D%5D%2C%22pa%22%3A1%2C%22pp%22%3A100%2C%22dr%22%3A%22list%22%7D) в меню навигации по проекту.
+ 3. _Создайте новый пакет работ_: → Перейдите в [Пакет работ → Создать]({{opSetting:base_url}}/projects/demo-construction-project/work_packages/new?query_props=%7B%22c%22%3A%5B%22type%22%2C%22id%22%2C%22subject%22%2C%22status%22%2C%22assignee%22%2C%22priority%22%5D%2C%22hl%22%3A%22priority%22%2C%22hi%22%3Atrue%2C%22g%22%3A%22%22%2C%22t%22%3A%22startDate%3Aasc%22%2C%22f%22%3A%5B%7B%22n%22%3A%22bcfIssueAssociated%22%2C%22o%22%3A%22%3D%22%2C%22v%22%3A%5B%22f%22%5D%7D%5D%2C%22pa%22%3A1%2C%22pp%22%3A100%2C%22dr%22%3A%22list%22%7D&type=11).
+ 4. _Создайте и обновите диаграмму Гантта_: → Перейдите в [Диаграмма Гантта]({{opSetting:base_url}}/projects/demo-construction-project/work_packages?query_props=%7B%22c%22%3A%5B%22type%22%2C%22id%22%2C%22subject%22%2C%22assignee%22%2C%22responsible%22%5D%2C%22tv%22%3Atrue%2C%22tzl%22%3A%22weeks%22%2C%22hl%22%3A%22priority%22%2C%22hi%22%3Atrue%2C%22g%22%3A%22%22%2C%22t%22%3A%22startDate%3Aasc%22%2C%22f%22%3A%5B%5D%2C%22pa%22%3A1%2C%22pp%22%3A100%2C%22dr%22%3A%22list%22%7D) в меню навигации по проекту.
+ 5. _Активируйте дополнительные модули_: → Перейдите в [Настройки проекта → Модули]({{opSetting:base_url}}/projects/demo-construction-project/settings/modules).
+ 6. _Проверьте плиточный вид, чтобы получить общее представление о проблемах вашего BCF:_ → Перейдите в [Пакеты работ]({{opSetting:base_url}}/projects/demo-construction-project/work_packages?query_props=%7B%22c%22%3A%5B%22type%22%2C%22id%22%2C%22subject%22%2C%22status%22%2C%22assignee%22%2C%22priority%22%5D%2C%22hl%22%3A%22priority%22%2C%22hi%22%3Atrue%2C%22g%22%3A%22%22%2C%22t%22%3A%22id%3Aasc%22%2C%22f%22%3A%5B%5D%2C%22pa%22%3A1%2C%22pp%22%3A100%2C%22dr%22%3A%22card%22%7D)
+ 7. _Используете Agile? Посмотрите функционал наших новых досок:_ → Перейдите в [Доски]({{opSetting:base_url}}/projects/demo-construction-project/boards)
+
+ Здесь вы найдёте наши [Инструкции пользователя](https://www.openproject.org/docs/user-guide/).
+ Пожалуйста, дайте нам знать, если у Вас возникнут вопросы или необходима техническая поддержка. Свяжитесь с нами: [support\[at\]openproject.com](mailto:support@openproject.com).
item_4:
options:
name: Участники
diff --git a/modules/bim/spec/seeders/root_seeder_bim_edition_spec.rb b/modules/bim/spec/seeders/root_seeder_bim_edition_spec.rb
index ab647887a86c..1e4870b4a904 100644
--- a/modules/bim/spec/seeders/root_seeder_bim_edition_spec.rb
+++ b/modules/bim/spec/seeders/root_seeder_bim_edition_spec.rb
@@ -98,7 +98,7 @@ def group_name(reference)
)
end
- include_examples "it creates records", model: Color, expected_count: 144
+ include_examples "it creates records", model: Color, expected_count: 149
include_examples "it creates records", model: DocumentCategory, expected_count: 3
include_examples "it creates records", model: IssuePriority, expected_count: 4
include_examples "it creates records", model: Status, expected_count: 4
diff --git a/modules/budgets/app/controllers/budgets_controller.rb b/modules/budgets/app/controllers/budgets_controller.rb
index 7f01d8adf16a..f820b9b9fd80 100644
--- a/modules/budgets/app/controllers/budgets_controller.rb
+++ b/modules/budgets/app/controllers/budgets_controller.rb
@@ -229,7 +229,7 @@ def find_optional_project
def render_item_as_json(element_id, costs, unit, project, permission)
response = {
"#{element_id}_unit_name" => ActionController::Base.helpers.sanitize(unit),
- "#{element_id}_currency" => Setting.plugin_costs["costs_currency"]
+ "#{element_id}_currency" => Setting.costs_currency
}
if current_user.allowed_in_project?(permission, project)
diff --git a/modules/budgets/app/views/budgets/items/_budget_override_cost_form.html.erb b/modules/budgets/app/views/budgets/items/_budget_override_cost_form.html.erb
index b58df02221d3..101ee5b6e8a0 100644
--- a/modules/budgets/app/views/budgets/items/_budget_override_cost_form.html.erb
+++ b/modules/budgets/app/views/budgets/items/_budget_override_cost_form.html.erb
@@ -12,7 +12,7 @@
) %>
diff --git a/modules/budgets/spec/features/budgets/update_budget_spec.rb b/modules/budgets/spec/features/budgets/update_budget_spec.rb
index 8958488a8d43..5da73d7fae42 100644
--- a/modules/budgets/spec/features/budgets/update_budget_spec.rb
+++ b/modules/budgets/spec/features/budgets/update_budget_spec.rb
@@ -205,13 +205,7 @@
expect(material_budget_item_2.costs).to eq(543.0)
end
- context "with a reversed currency format" do
- before do
- allow(Setting)
- .to receive(:plugin_costs)
- .and_return({ costs_currency_format: "%u %n", costs_currency: "USD" }.with_indifferent_access)
- end
-
+ context "with a reversed currency format", with_settings: { costs_currency_format: "%u %n", costs_currency: "USD" } do
it "can still update budgets (Regression test #32664)" do
budget_page.visit!
click_on "Update"
@@ -282,13 +276,7 @@
expect(labor_budget_item_2.costs).to eq(987.0)
end
- context "with a reversed currency format" do
- before do
- allow(Setting)
- .to receive(:plugin_costs)
- .and_return({ costs_currency_format: "%u %n", costs_currency: "USD" }.with_indifferent_access)
- end
-
+ context "with a reversed currency format", with_settings: { costs_currency_format: "%u %n", costs_currency: "USD" } do
it "can still update budgets (Regression test #32664)" do
budget_page.visit!
click_on "Update"
diff --git a/modules/costs/app/controllers/costs_settings_controller.rb b/modules/costs/app/controllers/costs_settings_controller.rb
new file mode 100644
index 000000000000..737541a38b4f
--- /dev/null
+++ b/modules/costs/app/controllers/costs_settings_controller.rb
@@ -0,0 +1,31 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class CostsSettingsController < Admin::SettingsController
+ menu_item :admin_costs
+end
diff --git a/modules/costs/app/models/time_entry.rb b/modules/costs/app/models/time_entry.rb
index 1388a2379932..962f12750a5f 100644
--- a/modules/costs/app/models/time_entry.rb
+++ b/modules/costs/app/models/time_entry.rb
@@ -36,6 +36,9 @@ class TimeEntry < ApplicationRecord
belongs_to :rate, -> { where(type: %w[HourlyRate DefaultHourlyRate]) }, class_name: "Rate"
belongs_to :logged_by, class_name: "User"
+ MIN_TIME = 0 # => 00:00
+ MAX_TIME = (60 * 24) - 1 # => 23:59
+
acts_as_customizable
acts_as_journalized
@@ -44,6 +47,23 @@ class TimeEntry < ApplicationRecord
validates_presence_of :hours, if: -> { !ongoing? }
validates_numericality_of :hours, allow_nil: true, message: :invalid
+ validates :start_time, :end_time,
+ presence: true,
+ if: -> { TimeEntry.must_track_start_and_end_time? }
+
+ validates :start_time,
+ numericality: { only_integer: true, greater_than_or_equal_to: MIN_TIME, less_than_or_equal_to: MAX_TIME },
+ allow_blank: true
+
+ validates :end_time,
+ numericality: {
+ only_integer: true,
+ greater_than: ->(te) { te.start_time.to_i },
+ less_than_or_equal_to: MAX_TIME
+ # TODO: nice error message
+ },
+ allow_blank: true
+
scope :on_work_packages, ->(work_packages) { where(work_package_id: work_packages) }
extend ::TimeEntries::TimeEntryScopes
@@ -101,6 +121,19 @@ def costs_visible_by?(usr)
(user_id == usr.id && usr.allowed_in_project?(:view_own_hourly_rate, project))
end
+ class << self
+ def can_track_start_and_end_time?(_project: nil)
+ OpenProject::FeatureDecisions.track_start_and_end_times_for_time_entries_active? &&
+ Setting.allow_tracking_start_and_end_times?
+ # TODO: Add project check when we have decided if we also want a project specific flag
+ end
+
+ def must_track_start_and_end_time?(_project: nil)
+ can_track_start_and_end_time? && Setting.enforce_tracking_start_and_end_times?
+ # TODO: Add project check when we have decided if we also want a project specific flag
+ end
+ end
+
private
def cost_attribute
diff --git a/modules/costs/app/views/cost_types/_list.html.erb b/modules/costs/app/views/cost_types/_list.html.erb
index 0e721aa73901..f5c50f77d51c 100644
--- a/modules/costs/app/views/cost_types/_list.html.erb
+++ b/modules/costs/app/views/cost_types/_list.html.erb
@@ -98,7 +98,7 @@ See COPYRIGHT and LICENSE files for more details.
placeholder: t(:label_example_placeholder, decimal: unitless_currency_number(1000.50)),
id: "rate_field_#{cost_type.id}" %>
- <%= Setting.plugin_costs['costs_currency'] %>
+ <%= Setting.costs_currency %>