diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2d8f5e78c27..00000000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000000..599a9e8e8a4 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,24 @@ +name: Docker +on: + # Scheduled workflows run on the latest commit on the default or base branch + schedule: + - cron: '20 2 * * *' # Daily at 02:20 + + push: + tags: + - v* +jobs: + publish: + # restrict this job to base repo for now + if: github.repository == 'opf/openproject' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Publish to registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openproject/community-test + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + tag_semver: true + cache: ${{ github.event_name != 'schedule' }} diff --git a/.gitignore b/.gitignore index 1d4edfc5a2b..d21efa3c01c 100644 --- a/.gitignore +++ b/.gitignore @@ -51,9 +51,9 @@ npm-debug.log* /backup /.project /.loadpath -/app/assets/javascripts/bundles/*.* /app/assets/javascripts/editor/* /app/assets/javascripts/locales/*.* +/frontend/src/locales/*.js /config/additional_environment.rb /config/configuration.yml /config/database.yml diff --git a/.jshintignore b/.jshintignore index 34fea6388e2..3054c805e2d 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,5 +1,2 @@ -app/assets/javascripts/date-de-DE.js -app/assets/javascripts/date-en-US.js -app/assets/javascripts/jquery_noconflict.js app/assets/javascripts/project/**/* app/assets/javascripts/lib/**/* diff --git a/.pkgr.yml b/.pkgr.yml index 107a798a8f6..cc1695d79f3 100644 --- a/.pkgr.yml +++ b/.pkgr.yml @@ -11,12 +11,12 @@ targets: - catdoc debian-10: <<: *debian9 - ubuntu-14.04: - <<: *debian9 ubuntu-16.04: <<: *debian9 ubuntu-18.04: <<: *debian9 + ubuntu-20.04: + <<: *debian9 centos-8: dependencies: - epel-release diff --git a/.travis.yml b/.travis.yml index cc417538c7d..c70cc270f81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,8 +38,7 @@ cache: bundler: true directories: - public/assets - - app/assets/javascripts/bundles - - app/assets/javascripts/locales + - frontend/src/locales branches: only: @@ -91,68 +90,67 @@ jobs: - bash script/ci/runner.sh npm - stage: test - name: 'spec_legacy (1/1)' + name: 'legacy specs + cukes (1/1)' script: - bash script/ci/setup.sh spec_legacy - bash script/ci/runner.sh spec_legacy 1 1 - - stage: test - name: 'units (1/4)' - script: - - bash script/ci/setup.sh units - - bash script/ci/runner.sh units 4 1 - - stage: test - name: 'units (2/4)' - script: - - bash script/ci/setup.sh units - - bash script/ci/runner.sh units 4 2 - - stage: test - name: 'units (3/4)' - script: - - bash script/ci/setup.sh units - - bash script/ci/runner.sh units 4 3 - - stage: test - name: 'units (4/4)' - script: - - bash script/ci/setup.sh units - - bash script/ci/runner.sh units 4 4 - - stage: test - name: 'features (1/4)' - script: - - bash script/ci/setup.sh features - - bash script/ci/runner.sh features 4 1 - - stage: test - name: 'features (2/4)' - script: - - bash script/ci/setup.sh features - - bash script/ci/runner.sh features 4 2 - - stage: test - name: 'features (3/4)' - script: - - bash script/ci/setup.sh features - - bash script/ci/runner.sh features 4 3 - - stage: test - name: 'features (4/4)' - script: - - bash script/ci/setup.sh features - - bash script/ci/runner.sh features 4 4 - - stage: test - name: 'plugins:units (1/1)' - script: - - bash script/ci/setup.sh plugins:units - - bash script/ci/runner.sh plugins:units 1 1 - if: head_branch !~ /^core\// - - stage: test - name: 'plugins:features (1/1)' - script: - - bash script/ci/setup.sh plugins:features - - bash script/ci/runner.sh plugins:features 1 1 - if: head_branch !~ /^core\// - - stage: test - name: 'plugins:cucumber (1/1)' - script: - - bash script/ci/setup.sh plugins:cucumber - bash script/ci/runner.sh plugins:cucumber 1 1 - if: head_branch !~ /^core\// + - stage: test + name: 'units (1/5)' + script: + - bash script/ci/setup.sh units + - bash script/ci/runner.sh units 5 1 + - stage: test + name: 'units (2/5)' + script: + - bash script/ci/setup.sh units + - bash script/ci/runner.sh units 5 2 + - stage: test + name: 'units (3/5)' + script: + - bash script/ci/setup.sh units + - bash script/ci/runner.sh units 5 3 + - stage: test + name: 'units (4/5)' + script: + - bash script/ci/setup.sh units + - bash script/ci/runner.sh units 5 4 + - stage: test + name: 'units (5/5)' + script: + - bash script/ci/setup.sh units + - bash script/ci/runner.sh units 5 5 + - stage: test + name: 'features (1/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 1 + - stage: test + name: 'features (2/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 2 + - stage: test + name: 'features (3/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 3 + - stage: test + name: 'features (4/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 4 + - stage: test + name: 'features (5/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 5 + - stage: test + name: 'features (6/6)' + script: + - bash script/ci/setup.sh features + - bash script/ci/runner.sh features 6 6 + addons: chrome: stable diff --git a/Gemfile b/Gemfile index 83ec0a67ddc..4fa6d8d1630 100644 --- a/Gemfile +++ b/Gemfile @@ -34,7 +34,7 @@ gem 'actionpack-xml_parser', '~> 2.0.0' gem 'activemodel-serializers-xml', '~> 1.0.1' gem 'activerecord-import', '~> 1.0.2' gem 'activerecord-session_store', '~> 1.1.0' -gem 'rails', '~> 6.0.3' +gem 'rails', '~> 6.0.3.2' gem 'responders', '~> 3.0' gem 'rdoc', '>= 2.4.2' @@ -85,7 +85,7 @@ gem 'escape_utils', '~> 1.0' # Syntax highlighting used in html-pipeline with rouge gem 'rouge', '~> 3.17.0' # HTML sanitization used for html-pipeline -gem 'sanitize', '~> 5.1.0' +gem 'sanitize', '~> 5.2.1' # HTML autolinking for mails and urls (replaces autolink) gem 'rinku', '~> 2.0.4' # Version parsing with semver @@ -156,29 +156,27 @@ group :production do gem 'unicorn-worker-killer', require: false end -gem 'autoprefixer-rails', '~> 9.7.4' -gem 'bourbon', '~> 6.0.0' gem 'i18n-js', '~> 3.6.0' gem 'rails-i18n', '~> 6.0.0' -gem 'sassc-rails', '~> 2.1.0' gem 'sprockets', '~> 3.7.0' # required by Procfile, for deployment on heroku or packaging with packager.io. # also, better than thin since we can control worker concurrency. gem 'unicorn' -gem 'puma', '~> 4.3.1' # used for development and optionally for production +gem 'puma', '~> 4.3.5' # used for development and optionally for production gem 'nokogiri', '~> 1.10.8' gem 'carrierwave', '~> 1.3.1' +gem 'carrierwave_direct', '~> 2.1.0' gem 'fog-aws' gem 'aws-sdk-core', '~> 3.91.0' # File upload via fog + screenshots on travis gem 'aws-sdk-s3', '~> 1.61.0' -gem 'openproject-token', '~> 1.0.2' +gem 'openproject-token', '~> 2.1.1' gem 'plaintext', '~> 0.3.2' @@ -245,12 +243,15 @@ group :development do gem 'faker' gem 'letter_opener' - gem 'livingstyleguide', '~> 2.1.0' gem 'spring' gem 'spring-commands-rspec' gem 'rubocop' + + # Gems for living styleguide + gem 'sassc-rails' + gem 'livingstyleguide', '~> 2.1.0' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 1b307731fdc..74601dd6890 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -114,6 +114,11 @@ PATH specs: grids (1.0.0) +PATH + remote: modules/job_status + specs: + openproject-job_status (1.0.0) + PATH remote: modules/ldap_groups specs: @@ -168,7 +173,6 @@ PATH remote: modules/reporting specs: openproject-reporting (1.0.0) - jquery-tablesorter (~> 1.27.0) openproject-costs reporting_engine @@ -195,26 +199,26 @@ GEM remote: https://rubygems.org/ specs: Ascii85 (1.0.3) - actioncable (6.0.3) - actionpack (= 6.0.3) + actioncable (6.0.3.2) + actionpack (= 6.0.3.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3) - actionpack (= 6.0.3) - activejob (= 6.0.3) - activerecord (= 6.0.3) - activestorage (= 6.0.3) - activesupport (= 6.0.3) + actionmailbox (6.0.3.2) + actionpack (= 6.0.3.2) + activejob (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) mail (>= 2.7.1) - actionmailer (6.0.3) - actionpack (= 6.0.3) - actionview (= 6.0.3) - activejob (= 6.0.3) + actionmailer (6.0.3.2) + actionpack (= 6.0.3.2) + actionview (= 6.0.3.2) + activejob (= 6.0.3.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3) - actionview (= 6.0.3) - activesupport (= 6.0.3) + actionpack (6.0.3.2) + actionview (= 6.0.3.2) + activesupport (= 6.0.3.2) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) @@ -222,30 +226,30 @@ GEM actionpack-xml_parser (2.0.1) actionpack (>= 5.0) railties (>= 5.0) - actiontext (6.0.3) - actionpack (= 6.0.3) - activerecord (= 6.0.3) - activestorage (= 6.0.3) - activesupport (= 6.0.3) + actiontext (6.0.3.2) + actionpack (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) nokogiri (>= 1.8.5) - actionview (6.0.3) - activesupport (= 6.0.3) + actionview (6.0.3.2) + activesupport (= 6.0.3.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3) - activesupport (= 6.0.3) + activejob (6.0.3.2) + activesupport (= 6.0.3.2) globalid (>= 0.3.6) - activemodel (6.0.3) - activesupport (= 6.0.3) + activemodel (6.0.3.2) + activesupport (= 6.0.3.2) activemodel-serializers-xml (1.0.2) activemodel (> 5.x) activesupport (> 5.x) builder (~> 3.1) - activerecord (6.0.3) - activemodel (= 6.0.3) - activesupport (= 6.0.3) + activerecord (6.0.3.2) + activemodel (= 6.0.3.2) + activesupport (= 6.0.3.2) activerecord-import (1.0.4) activerecord (>= 3.2) activerecord-nulldb-adapter (0.4.0) @@ -256,12 +260,12 @@ GEM multi_json (~> 1.11, >= 1.11.2) rack (>= 1.5.2, < 3) railties (>= 4.0) - activestorage (6.0.3) - actionpack (= 6.0.3) - activejob (= 6.0.3) - activerecord (= 6.0.3) + activestorage (6.0.3.2) + actionpack (= 6.0.3.2) + activejob (= 6.0.3.2) + activerecord (= 6.0.3.2) marcel (~> 0.3.1) - activesupport (6.0.3) + activesupport (6.0.3.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -283,8 +287,6 @@ GEM attr_required (1.0.1) auto_strip_attributes (2.5.0) activerecord (>= 4.0) - autoprefixer-rails (9.7.4) - execjs awesome_nested_set (3.2.0) activerecord (>= 4.0.0, < 7.0) aws-eventstream (1.0.3) @@ -313,8 +315,6 @@ GEM debug_inspector (>= 0.0.1) bootsnap (1.4.6) msgpack (~> 1.0) - bourbon (6.0.0) - thor (~> 0.19) brakeman (4.8.0) browser (2.6.1) builder (3.2.4) @@ -334,6 +334,9 @@ GEM activemodel (>= 4.0.0) activesupport (>= 4.0.0) mime-types (>= 1.16) + carrierwave_direct (2.1.0) + carrierwave (>= 1.0.0) + fog-aws cells (4.1.7) declarative-builder (< 0.2.0) declarative-option (< 0.2.0) @@ -357,7 +360,7 @@ GEM ruby-enum (~> 0.5) compare-xml (0.66) nokogiri (~> 1.8) - concurrent-ruby (1.1.6) + concurrent-ruby (1.1.7) cookiejar (0.3.3) cork (0.3.0) colored2 (~> 3.1) @@ -478,7 +481,6 @@ GEM eventmachine (1.2.7) eventmachine_httpserver (0.2.1) excon (0.72.0) - execjs (2.7.0) factory_bot (5.1.1) activesupport (>= 4.2.0) factory_bot_rails (5.1.1) @@ -547,7 +549,7 @@ GEM domain_name (~> 0.5) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.8.2) + i18n (1.8.5) concurrent-ruby (~> 1.0) i18n-js (3.6.0) i18n (>= 0.6.6) @@ -559,8 +561,6 @@ GEM iso8601 (0.12.1) jaro_winkler (1.5.4) jmespath (1.4.0) - jquery-tablesorter (1.27.1) - railties (>= 3.2) json (2.3.0) json-jwt (1.11.0) activesupport (>= 4.2) @@ -597,7 +597,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.5.0) + loofah (2.6.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -615,7 +615,7 @@ GEM mini_mime (1.0.2) mini_portile2 (2.4.0) minisyntax (0.2.5) - minitest (5.14.0) + minitest (5.14.1) mixlib-shellout (2.1.0) msgpack (1.3.3) multi_json (1.14.1) @@ -631,7 +631,7 @@ GEM newrelic_rpm (6.9.0.363) nio4r (2.5.2) no_proxy_fix (0.1.2) - nokogiri (1.10.9) + nokogiri (1.10.10) mini_portile2 (~> 2.4.0) nokogumbo (2.0.2) nokogiri (~> 1.8, >= 1.8.4) @@ -654,7 +654,8 @@ GEM validate_email validate_url webfinger (>= 1.0.1) - openproject-token (1.0.2) + openproject-token (2.1.3) + activemodel parallel (1.19.1) parallel_tests (2.32.0) parallel @@ -710,9 +711,9 @@ GEM eventmachine_httpserver http_parser.rb (~> 0.6.0) multi_json - puma (4.3.3) + puma (4.3.5) nio4r (~> 2.0) - rack (2.2.2) + rack (2.2.3) rack-accept (0.4.5) rack (>= 0.4) rack-attack (6.2.2) @@ -732,20 +733,20 @@ GEM rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (6.0.3) - actioncable (= 6.0.3) - actionmailbox (= 6.0.3) - actionmailer (= 6.0.3) - actionpack (= 6.0.3) - actiontext (= 6.0.3) - actionview (= 6.0.3) - activejob (= 6.0.3) - activemodel (= 6.0.3) - activerecord (= 6.0.3) - activestorage (= 6.0.3) - activesupport (= 6.0.3) + rails (6.0.3.2) + actioncable (= 6.0.3.2) + actionmailbox (= 6.0.3.2) + actionmailer (= 6.0.3.2) + actionpack (= 6.0.3.2) + actiontext (= 6.0.3.2) + actionview (= 6.0.3.2) + activejob (= 6.0.3.2) + activemodel (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) bundler (>= 1.3.0) - railties (= 6.0.3) + railties (= 6.0.3.2) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) @@ -764,9 +765,9 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (6.0.3) - actionpack (= 6.0.3) - activesupport (= 6.0.3) + railties (6.0.3.2) + actionpack (= 6.0.3.2) + activesupport (= 6.0.3.2) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -860,7 +861,7 @@ GEM structured_warnings (~> 0.3) rubyzip (1.3.0) safe_yaml (1.0.5) - sanitize (5.1.0) + sanitize (5.2.1) crass (~> 1.0.2) nokogiri (>= 1.8.0) nokogumbo (~> 2.0) @@ -915,7 +916,7 @@ GEM daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) rack (>= 1, < 3) - thor (0.20.3) + thor (1.0.1) thread_safe (0.3.6) tilt (2.0.10) timecop (0.9.1) @@ -958,15 +959,15 @@ GEM addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - websocket-driver (0.7.1) + websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.4) + websocket-extensions (0.1.5) will_paginate (3.3.0) with_advisory_lock (4.6.0) activerecord (>= 4.2) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.3.0) + zeitwerk (2.4.0) PLATFORMS ruby @@ -982,18 +983,17 @@ DEPENDENCIES addressable (~> 2.7.0) airbrake (~> 9.4.3) auto_strip_attributes (~> 2.5) - autoprefixer-rails (~> 9.7.4) awesome_nested_set (~> 3.2.0) aws-sdk-core (~> 3.91.0) aws-sdk-s3 (~> 1.61.0) bcrypt (~> 3.1.6) bootsnap (~> 1.4.5) - bourbon (~> 6.0.0) brakeman (~> 4.8.0) browser (~> 2.6.1) capybara (~> 3.32.0) capybara-screenshot (~> 1.0.17) carrierwave (~> 1.3.1) + carrierwave_direct (~> 2.1.0) cells-erb (~> 0.1.0) cells-rails (~> 0.0.9) commonmarker (~> 0.21.0) @@ -1055,13 +1055,14 @@ DEPENDENCIES openproject-documents! openproject-github_integration! openproject-global_roles! + openproject-job_status! openproject-ldap_groups! openproject-meeting! openproject-openid_connect! openproject-pdf_export! openproject-recaptcha! openproject-reporting! - openproject-token (~> 1.0.2) + openproject-token (~> 2.1.1) openproject-translations! openproject-two_factor_authentication! openproject-webhooks! @@ -1079,13 +1080,13 @@ DEPENDENCIES pry-rescue (~> 1.5.0) pry-stack_explorer (~> 0.4.9.2) puffing-billy (~> 2.3.1) - puma (~> 4.3.1) + puma (~> 4.3.5) rack-attack (~> 6.2.2) rack-mini-profiler rack-protection (~> 2.0.8) rack-test (~> 1.1.0) rack_session_access - rails (~> 6.0.3) + rails (~> 6.0.3.2) rails-controller-testing (~> 1.0.2) rails-i18n (~> 6.0.0) rails_12factor @@ -1109,8 +1110,8 @@ DEPENDENCIES ruby-prof ruby-progressbar (~> 1.10.0) rubytree (~> 1.0.0) - sanitize (~> 5.1.0) - sassc-rails (~> 2.1.0) + sanitize (~> 5.2.1) + sassc-rails secure_headers (~> 6.3.0) selenium-webdriver (~> 3.14) semantic (~> 1.6.1) diff --git a/Gemfile.modules b/Gemfile.modules index abe5a637249..d53c504912e 100644 --- a/Gemfile.modules +++ b/Gemfile.modules @@ -38,6 +38,7 @@ group :opf_plugins do gem 'openproject-github_integration', path: 'modules/github_integration' gem 'openproject-ldap_groups', path: 'modules/ldap_groups' gem 'openproject-recaptcha', path: 'modules/recaptcha' + gem 'openproject-job_status', path: 'modules/job_status' gem 'grids', path: 'modules/grids' gem 'my_page', path: 'modules/my_page' diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..2297dae099a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security Policy + + +At its core, OpenProject is an open-source software that is [developed and published on GitHub](https://github.com/opf/openproject). Every change to the OpenProject code base ends up in an open repository accessible to everyone. This results in a transparent software where every commit can be traced back to the contributor. + +Automated tests and manual code reviews ensure that these contributions are safe for the entire community of OpenProject. These tests encompass the correctness of security and access control features. We have ongoing collaborations with security professionals from to test the OpenProject code base for security exploits. + + + +### Security announcements mailing list + +We provide a mailing list for security advisories on OpenProject at . Please register there to get immediate notifications as we publish them. + +Any security related information will also be published on our blog and website at https://www.openproject.com + + + +### Reporting a vulnerability + +We take all facets of security seriously at OpenProject. If you want to report a security concerns, have remarks, or contributions regarding security at OpenProject, please reach out to us at [security@openproject.com](mailto:security@openproject.com). + +If you can, please send us a PGP-encrypted email using the following key: + +- Key ID: [0x7D669C6D47533958](https://pgp.mit.edu/pks/lookup?op=get&search=0x7D669C6D47533958) , +- Fingerprint BDCF E01E DE84 EA19 9AE1 72CE 7D66 9C6D 4753 3958 +- You may also find the key [attached in our OpenProject repository.](https://github.com/opf/openproject/blob/dev/docs/development/security/security-at-openproject.com.asc) + +Please include a description on how to reproduce the issue if possible. Our security team will get your email and will attempt to reproduce and fix the issue as soon as possible. diff --git a/app/assets/images/files/image.png b/app/assets/images/files/image.png deleted file mode 100644 index 8954d2a55fb..00000000000 Binary files a/app/assets/images/files/image.png and /dev/null differ diff --git a/app/assets/images/jquery-ui/ui-icons_222222_256x240.png b/app/assets/images/jquery-ui/ui-icons_222222_256x240.png deleted file mode 100644 index ee039dc096a..00000000000 Binary files a/app/assets/images/jquery-ui/ui-icons_222222_256x240.png and /dev/null differ diff --git a/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png b/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png deleted file mode 100644 index 45e8928e528..00000000000 Binary files a/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/app/assets/images/jquery-ui/ui-icons_454545_256x240.png b/app/assets/images/jquery-ui/ui-icons_454545_256x240.png deleted file mode 100644 index 7ec70d11bfb..00000000000 Binary files a/app/assets/images/jquery-ui/ui-icons_454545_256x240.png and /dev/null differ diff --git a/app/assets/images/jquery-ui/ui-icons_888888_256x240.png b/app/assets/images/jquery-ui/ui-icons_888888_256x240.png deleted file mode 100644 index 5ba708c3917..00000000000 Binary files a/app/assets/images/jquery-ui/ui-icons_888888_256x240.png and /dev/null differ diff --git a/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png b/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png deleted file mode 100644 index 7930a558099..00000000000 Binary files a/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png and /dev/null differ diff --git a/app/assets/images/new_feature_teaser.jpg b/app/assets/images/new_feature_teaser.jpg index 4f794976cd5..7dcef6104f1 100644 Binary files a/app/assets/images/new_feature_teaser.jpg and b/app/assets/images/new_feature_teaser.jpg differ diff --git a/app/assets/javascripts/action_menu.js b/app/assets/javascripts/action_menu.js deleted file mode 100644 index 8b692974b24..00000000000 --- a/app/assets/javascripts/action_menu.js +++ /dev/null @@ -1,100 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 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 docs/COPYRIGHT.rdoc for more details. -//++ - -/* - The action menu is a menu that usually belongs to an OpenProject entity (like an Issue, WikiPage, Meeting, ..). - Most likely it looks like this: - - The following code is responsible to open and close the "more functions" submenu. -*/ - -jQuery(function ($) { - var animationSpeed = 100; // ms - - function menu_top_position(menu) { - // if an h2 tag follows the submenu should unfold out at the border - var menu_start_position; - if (menu.next().get(0) != undefined && (menu.next().get(0).tagName == 'H2')) { - menu_start_position = menu.next().innerHeight() + menu.next().position().top; - } - else if (menu.next().hasClass("wiki-content") && menu.next().children().next().first().get(0) != undefined && menu.next().children().next().first().get(0).tagName == 'H1') { - var wiki_heading = menu.next().children().next().first(); - menu_start_position = wiki_heading.innerHeight() + wiki_heading.position().top; - } - return menu_start_position; - } - - function close_menu(event) { - var menu = $(event.data.menu); - // do not close the menu, if the user accidentally clicked next to a menu item (but still within the menu) - if (event.target !== menu.find(" > li.drop-down.open > ul").get(0)) { - menu.find(" > li.drop-down.open").removeClass("open").find("> ul").slideUp(animationSpeed); - // no need to watch for clicks, when the menu is already closed - $('html').off('click', close_menu); - } - } - - function open_menu(menu) { - var drop_down = menu.find(" > li.drop-down"); - // do not open a menu, which is already open - if (!drop_down.hasClass('open')) { - drop_down.find('> ul').slideDown(animationSpeed, function () { - drop_down.find('li > a:first').focus(); - // when clicking on something, which is not the menu, close the menu - $('html').on('click', {menu: menu.get(0)}, close_menu); - }); - drop_down.addClass('open'); - } - } - - // open the given submenu when clicking on it - function install_menu_logic(menu) { - menu.find(" > li.drop-down").click(function (event) { - open_menu(menu); - // and prevent default action (href) for that element - // but not for the menu items. - var target = $(event.target); - if (target.is('.drop-down') || target.closest('li, ul').is('.drop-down')) { - event.preventDefault(); - } - }); - } - - $('.project-actions, .toolbar-items').each(function (idx, menu) { - install_menu_logic($(menu)); - }); -}); diff --git a/app/assets/javascripts/application.js.erb b/app/assets/javascripts/application.js.erb deleted file mode 100644 index 34806b7e975..00000000000 --- a/app/assets/javascripts/application.js.erb +++ /dev/null @@ -1,398 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2013 Jean-Philippe Lang -// Copyright (C) 2010-2013 the ChiliProject Team -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// See docs/COPYRIGHT.rdoc for more details. -//++ - -//= require lib/jquery.colorcontrast -//= require lib/jquery.trap -//= require lib/jquery.is_visible_within - -//= require top_menu -//= require action_menu -//= require breadcrumb -//= require findDomElement -//= require settings -//= require openproject_plugins -//= require versions -//= require forums -//= require_tree ./specific - -//= require custom-fields -//= require date-range -//= require search -//= require colors -//= require tooltips -//= require danger_zone_validation -//= require flash_messages - -//= require_tree ./onboarding - - -function checkAll(selector, checked) { - jQuery('#' + selector + ' input:checkbox').not(':disabled').each(function() { - this.checked = checked; - }); -} - -function toggleCheckboxesBySelector(selector) { - boxes = jQuery(selector); - var all_checked = true; - for (i = 0; i < boxes.length; i++) { if (boxes[i].checked === false) { all_checked = false; } } - for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; } -} - -function setCheckboxesBySelector(checked, selector) { - var boxes = $(selector); - boxes.each(function(ele) { - ele.checked = checked; - }); -} - -var fileFieldCount = 1; - -function addFileField() { - fileFieldCount++; - if (fileFieldCount >= 10) return false; - var clone = jQuery('#attachment_template').clone(true); - clone.removeAttr('id'); - clone.html(clone.html().replace(/\[1\]/g, '['+ fileFieldCount + ']')); - jQuery('#attachments_fields').append(clone); -} - -function randomKey(size) { - var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); - var key = ''; - for (i = 0; i < size; i++) { - key += chars[Math.floor(Math.random() * chars.length)]; - } - return key; -} - -// Automatic project identifier generation -var projectIdentifierLocked; -var projectIdentifierDefault; -var projectIdentifierMaxLength; - -function generateProjectIdentifier() { - var identifier = jQuery('#project_name').val(); // project name - var diacriticsMap = [ - {'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g}, - {'base':'aa','letters':/[\uA733\uA732]/g}, - {'base':'ae','letters':/[\u00E4\u00E6\u01FD\u01E3\u00C4\u00C6\u01FC\u01E2]/g}, - {'base':'ao','letters':/[\uA735\uA734]/g}, - {'base':'au','letters':/[\uA737\uA736]/g}, - {'base':'av','letters':/[\uA739\uA73B\uA738\uA73A]/g}, - {'base':'ay','letters':/[\uA73D\uA73C]/g}, - {'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g}, - {'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g}, - {'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g}, - {'base':'dz','letters':/[\u01F3\u01C6\u01F1\u01C4\u01F2\u01C5]/g}, - {'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g}, - {'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g}, - {'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g}, - {'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g}, - {'base':'hv','letters':/[\u0195]/g}, - {'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g}, - {'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249\u004A\u24BF\uFF2A\u0134\u0248]/g}, - {'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g}, - {'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g}, - {'base':'lj','letters':/[\u01C9\u01C7\u01C8]/g}, - {'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g}, - {'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g}, - {'base':'nj','letters':/[\u01CC\u01CA\u01CB]/g}, - {'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g}, - {'base':'oe','letters': /[\u00F6\u0153\u00D6\u0152]/g}, - {'base':'oi','letters':/[\u01A3\u01A2]/g}, - {'base':'ou','letters':/[\u0223\u0222]/g}, - {'base':'oo','letters':/[\uA74F\uA74E]/g}, - {'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g}, - {'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759\u0051\u24C6\uFF31\uA756\uA758\u024A]/g}, - {'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g}, - {'base':'s','letters':/[\u0073\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g}, - {'base':'ss','letters':/[\u00DF]/g}, - {'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g}, - {'base':'tz','letters':/[\uA729\uA728]/g}, - {'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g}, - {'base':'ue','letters':/[\u00FC\u00DC]/g}, - {'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g}, - {'base':'vy','letters':/[\uA761\uA760]/g}, - {'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g}, - {'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D\u0058\u24CD\uFF38\u1E8A\u1E8C]/g}, - {'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g}, - {'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g} - ]; - - for(var i=0; i hyphen - identifier = identifier.replace(/^[-\d]*|-*$/g, ''); // remove hyphens and numbers at beginning and hyphens at end - identifier = identifier.toLowerCase(); // to lower - identifier = identifier.substr(0,projectIdentifierMaxLength); // max characters - return identifier; -} - -function observeProjectName() { - jQuery('#project_name').keyup(function() { - if(!projectIdentifierLocked) { - jQuery('#project_identifier').val(generateProjectIdentifier()); - } - }); -} - -function observeProjectIdentifier() { - jQuery('#project_identifier').keyup(function() { - if(jQuery('#project_identifier').getValue() !== '' && - jQuery('#project_identifier').getValue() != generateProjectIdentifier()) { - projectIdentifierLocked = true; - } else { - projectIdentifierLocked = false; - } - }); -} - -function hideOnLoad() { - jQuery('.hol').hide(); -} -jQuery(hideOnLoad); - -function addClickEventToAllErrorMessages() { - jQuery('a.afocus').each(function() { - var target = jQuery(this); - target.click(function(evt) { - var field = jQuery('#' + target.readAttribute('href').substr(1)); - if (field === null) { - // Cut off '_id' (necessary for select boxes) - field = jQuery('#' + target.readAttribute('href').substr(1).concat('_id')); - } - if (field) { - field.down('input, textarea, select').focus(); - } - target.unbind(evt); - return false; - }); - }); -} - -// a few constants for animations speeds, etc. -var animationRate = 100; - -/* jQuery code from #263 */ -// returns viewport height -jQuery.viewportHeight = function() { - return self.innerHeight || - jQuery.boxModel && document.documentElement.clientHeight || - document.body.clientHeight; -}; - - -/* -* 1 - registers a callback which copies the csrf token into the -* X-CSRF-Token header with each ajax request. Necessary to -* work with rails applications which have fixed -* CVE-2011-0447 -* 2 - shows and hides ajax indicator -*/ -jQuery(document).ready(function($) { - jQuery(document).ajaxSend(function (event, request) { - if ($(event.target.activeElement).closest('[ajax-indicated]').length && - $('ajax-indicator')) { - $('#ajax-indicator').show(); - } - - var csrf_meta_tag = $('meta[name=csrf-token]'); - - if (csrf_meta_tag) { - var header = 'X-CSRF-Token', - token = csrf_meta_tag.attr('content'); - - request.setRequestHeader(header, token); - } - - request.setRequestHeader('X-Authentication-Scheme', "Session"); - }); - - // ajaxStop gets called when ALL Requests finish, so we won't need a counter as in PT - jQuery(document).ajaxStop(function () { - if ($('#ajax-indicator')) { - $('#ajax-indicator').hide(); - } - addClickEventToAllErrorMessages(); - }); - - // show/hide the files table - jQuery(".attachments h4").click(function() { - jQuery(this).toggleClass("closed").next().slideToggle(animationRate); - }); - - jQuery(window).resize(function() { - // wait 200 milliseconds for no further resize event - // then readjust breadcrumb - - if(this.resizeTO) clearTimeout(this.resizeTO); - this.resizeTO = setTimeout(function() { - jQuery(this).trigger('resizeEnd'); - }, 200); - }); - - // Do not close the login window when using it - jQuery('#nav-login-content').click(function(event){ - event.stopPropagation(); - }); - - // Set focus on first error message - var error_focus = $('a.afocus').first(); - var input_focus = $('.autofocus').first(); - if (error_focus !== undefined) { - error_focus.focus(); - } - else if (input_focus !== undefined){ - input_focus.focus(); - if (input_focus.tagName === "INPUT") { - input_focus.select(); - } - } - // Focus on field with error - addClickEventToAllErrorMessages(); - - // Skip menu on content - jQuery('#skip-navigation--content').click(skipMenu); - - // Click handler for formatting help - jQuery(document.body).on('click', '.formatting-help-link-button', function() { - window.open(window.appBasePath + '/help/wiki_syntax', - "", - "resizable=yes, location=no, width=600, height=640, menubar=no, status=no, scrollbars=yes" - ); - return false; - }); -}); - - - -var Administration = (function ($) { - var update_default_language_options, - init_language_selection_handling, - toggle_default_language_select; - - update_default_language_options = function (input) { - var default_language_select = $('#setting_default_language select'), - default_language_select_active; - - if (input.attr('checked')) { - default_language_select.find('option[value="' + input.val() + '"]').removeAttr('disabled'); - } else { - default_language_select.find('option[value="' + input.val() + '"]').attr('disabled', 'disabled'); - } - - default_language_select_active = default_language_select.find('option:not([disabled="disabled"])'); - - toggle_disabled_state(default_language_select_active.length === 0); - - if (default_language_select_active.length === 1) { - default_language_select_active.attr('selected', true); - } else if (default_language_select.val() === input.val() && !input.attr('checked')) { - default_language_select_active.first().attr('selected', true); - } - }; - - toggle_disabled_state = function (active) { - jQuery('#setting_default_language select').attr('disabled', active) - .closest('form') - .find('input:submit') - .attr('disabled', active); - }; - - init_language_selection_handling = function () { - jQuery('#setting_available_languages input:not([checked="checked"])').each(function (index, input) { - update_default_language_options($(input)); - }); - jQuery('#setting_available_languages input').click(function () { - update_default_language_options($(this)); - }); - }; - - return { - init_language_selection_handling: init_language_selection_handling - }; -}(jQuery)); - -var activateFlash = function(selector) { - var flashMessages = jQuery(selector); - - // Ignore flash messages of class 'ignored-by-flash-activation' because those - // messages are completely handled via JavaScript (see types_checkboxes.js for - // details). We wouldn't have to ignore this message if the flash element - // would be completely created via JavaScript and not available in the DOM by - // default. - flashMessages.each(function (ix, e) { - flashMessage = jQuery(e); - if (!flashMessage.hasClass('ignored-by-flash-activation')) { - flashMessage.show(); - } - }); -}; - -var activateFlashNotice = function () { - var notice = '.flash'; - - activateFlash(notice); -}; - -var activateFlashError = function () { - var error = '.errorExplanation[role="alert"]'; - - activateFlash(error); -}; - -var focusFirstErroneousField = function() { - var firstErrorSpan = jQuery('span.errorSpan').first(); - var erroneousInput = firstErrorSpan.find('*').filter(":input"); - - erroneousInput.focus(); -}; - -function initMainMenuExpandStatus() { - let wrapper = jQuery('#wrapper'); - let upToggle = jQuery('ul.menu_root.closed li.open a.arrow-left-to-project'); - - if (upToggle.length === 1 && wrapper.hasClass('hidden-navigation')) { - upToggle.trigger('click'); - } -} - -var setupServerResponse = function() { - initMainMenuExpandStatus(); - focusFirstErroneousField(); - activateFlashNotice(); - activateFlashError(); - - jQuery(document).ajaxComplete(activateFlashNotice); - jQuery(document).ajaxComplete(activateFlashError); -}; - -jQuery(document).ready(setupServerResponse); - diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js deleted file mode 100644 index 2dbf1e700c7..00000000000 --- a/app/assets/javascripts/breadcrumb.js +++ /dev/null @@ -1,83 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 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 docs/COPYRIGHT.rdoc for more details. -//++ - -jQuery.fn.reverse = [].reverse; -(function($){ - $.fn.adjustBreadcrumbToWindowSize = function(){ - var breadcrumbElements = this.find(' > li'); - var breadcrumb = this; - var lastChanged; - - if (breadcrumb.breadcrumbOutOfBounds()){ - breadcrumbElements.each(function(index) { - if (breadcrumb.breadcrumbOutOfBounds()){ - if (!$(this).find(' > a').hasClass('nocut')){ - $(this).addClass('cutme ellipsis'); - } - } - else { - return false; - } - }); - } - else { - breadcrumbElements.reverse().each(function(index) { - if (!breadcrumb.breadcrumbOutOfBounds()){ - if (!$(this).find(' > a').hasClass('nocut')){ - $(this).removeClass('cutme ellipsis'); - lastChanged = $(this); - } - } - }); - - if (breadcrumb.breadcrumbOutOfBounds()){ - if (lastChanged != undefined){ - lastChanged.addClass('cutme ellipsis'); - return false; - } - } - } - }; - - $.fn.breadcrumbOutOfBounds = function(){ - var lastElement = this.find(' > li').last(); - if (lastElement) { - var rightCorner = lastElement.width() + lastElement.offset().left; - var windowSize = jQuery(window).width(); - - if ((Math.max(1000,windowSize) - rightCorner) < 10) { - return true; - } - else { - return false; - } - } else { - return false; - } - }; -})(jQuery); diff --git a/app/assets/javascripts/date-de-DE.js b/app/assets/javascripts/date-de-DE.js deleted file mode 100644 index 4d81966823c..00000000000 --- a/app/assets/javascripts/date-de-DE.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Version: 1.0 Alpha-1 - * Build Date: 13-Nov-2007 - * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. - * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. - * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/ - */ -Date.CultureInfo={name:"de-DE",englishName:"German (Germany)",nativeName:"Deutsch (Deutschland)",dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],abbreviatedDayNames:["So","Mo","Di","Mi","Do","Fr","Sa"],shortestDayNames:["So","Mo","Di","Mi","Do","Fr","Sa"],firstLetterDayNames:["S","M","D","M","D","F","S"],monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],abbreviatedMonthNames:["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],abbreviatedQuarterNames:["Q1","Q2","Q3","Q4"],quarterNames:["1. Quartal","2. Quartal","3. Quartal","4. Quartal"],amDesignator:"",pmDesignator:"",firstDayOfWeek:1,twoDigitYearMax:2029,dateElementOrder:"dmy",formatPatterns:{shortDate:"dd.MM.yyyy",longDate:"dddd, d. MMMM yyyy",shortTime:"HH:mm",longTime:"HH:mm:ss",fullDateTime:"dddd, d. MMMM yyyy HH:mm:ss",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"dd MMMM",yearMonth:"MMMM yyyy"},regexPatterns:{jan:/^jan(uar)?/i,feb:/^feb(ruar)?/i,mar:/^märz/i,apr:/^apr(il)?/i,may:/^mai/i,jun:/^jun(i)?/i,jul:/^jul(i)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^okt(ober)?/i,nov:/^nov(ember)?/i,dec:/^dez(ember)?/i,sun:/^sonntag/i,mon:/^montag/i,tue:/^dienstag/i,wed:/^mittwoch/i,thu:/^donnerstag/i,fri:/^freitag/i,sat:/^samstag/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}}; -Date.getMonthNumberFromName=function(e){var t=Date.CultureInfo.monthNames,n=Date.CultureInfo.abbreviatedMonthNames,r=e.toLowerCase();for(var i=0;ie?1:this=e.getTime()&&n<=t.getTime()},Date.prototype.addMilliseconds=function(e){return this.setMilliseconds(this.getMilliseconds()+e),this},Date.prototype.addSeconds=function(e){return this.addMilliseconds(e*1e3)},Date.prototype.addMinutes=function(e){return this.addMilliseconds(e*6e4)},Date.prototype.addHours=function(e){return this.addMilliseconds(e*36e5)},Date.prototype.addDays=function(e){return this.addMilliseconds(e*864e5)},Date.prototype.addWeeks=function(e){return this.addMilliseconds(e*6048e5)},Date.prototype.addMonths=function(e){var t=this.getDate();return this.setDate(1),this.setMonth(this.getMonth()+e),this.setDate(Math.min(t,this.getDaysInMonth())),this},Date.prototype.addQuarters=function(e){return this.addMonths(e*3)},Date.prototype.addYears=function(e){return this.addMonths(e*12)},Date.prototype.add=function(e){if(typeof e=="number")return this._orient=e,this;var t=e;return(t.millisecond||t.milliseconds)&&this.addMilliseconds(t.millisecond||t.milliseconds),(t.second||t.seconds)&&this.addSeconds(t.second||t.seconds),(t.minute||t.minutes)&&this.addMinutes(t.minute||t.minutes),(t.hour||t.hours)&&this.addHours(t.hour||t.hours),(t.month||t.months)&&this.addMonths(t.month||t.months),(t.year||t.years)&&this.addYears(t.year||t.years),(t.day||t.days)&&this.addDays(t.day||t.days),this},Date._validate=function(e,t,n,r){if(typeof e!="number")throw new TypeError(e+" is not a Number.");if(en)throw new RangeError(e+" is not a valid value for "+r+".");return!0},Date.validateMillisecond=function(e){return Date._validate(e,0,999,"milliseconds")},Date.validateSecond=function(e){return Date._validate(e,0,59,"seconds")},Date.validateMinute=function(e){return Date._validate(e,0,59,"minutes")},Date.validateHour=function(e){return Date._validate(e,0,23,"hours")},Date.validateDay=function(e,t,n){return Date._validate(e,1,Date.getDaysInMonth(t,n),"days")},Date.validateMonth=function(e){return Date._validate(e,0,11,"months")},Date.validateYear=function(e){return Date._validate(e,1,9999,"seconds")},Date.prototype.set=function(e){var t=e;return!t.millisecond&&t.millisecond!==0&&(t.millisecond=-1),!t.second&&t.second!==0&&(t.second=-1),!t.minute&&t.minute!==0&&(t.minute=-1),!t.hour&&t.hour!==0&&(t.hour=-1),!t.day&&t.day!==0&&(t.day=-1),!t.month&&t.month!==0&&(t.month=-1),!t.year&&t.year!==0&&(t.year=-1),t.millisecond!=-1&&Date.validateMillisecond(t.millisecond)&&this.addMilliseconds(t.millisecond-this.getMilliseconds()),t.second!=-1&&Date.validateSecond(t.second)&&this.addSeconds(t.second-this.getSeconds()),t.minute!=-1&&Date.validateMinute(t.minute)&&this.addMinutes(t.minute-this.getMinutes()),t.hour!=-1&&Date.validateHour(t.hour)&&this.addHours(t.hour-this.getHours()),t.month!==-1&&Date.validateMonth(t.month)&&this.addMonths(t.month-this.getMonth()),t.year!=-1&&Date.validateYear(t.year)&&this.addYears(t.year-this.getFullYear()),t.day!=-1&&Date.validateDay(t.day,this.getFullYear(),this.getMonth())&&this.addDays(t.day-this.getDate()),t.timezone&&this.setTimezone(t.timezone),t.timezoneOffset&&this.setTimezoneOffset(t.timezoneOffset),this},Date.prototype.clearTime=function(){return this.setHours(0),this.setMinutes(0),this.setSeconds(0),this.setMilliseconds(0),this},Date.prototype.isLeapYear=function(){var e=this.getFullYear();return e%4===0&&e%100!==0||e%400===0},Date.prototype.isWeekday=function(){return!this.is().sat()&&!this.is().sun()},Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth())},Date.prototype.getQuarter=function(){return Math.floor((this.getMonth()+1)/3)},Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1})},Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()})},Date.prototype.moveToDayOfWeek=function(e,t){var n=(e-this.getDay()+7*(t||1))%7;return this.addDays(n===0?n+=7*(t||1):n)},Date.prototype.moveToMonth=function(e,t){var n=(e-this.getMonth()+12*(t||1))%12;return this.addMonths(n===0?n+=12*(t||1):n)},Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/864e5)},Date.prototype.getWeekOfYear=function(e){return this.getWeek();var t,n,r,i,s,o,u},Date.prototype.getWeek=function(e,t,n){var r,i,s,o,u,a,f,l,c,h,p=this;return Date.CultureInfo.firstDayOfWeek!==1&&(this.getDay()===0||!(this.getDay()364+c?h=1:h=(l/7|0)+1,e=t=n=null,h},Date.prototype.getISOWeek=function(){var e=this.getUTCFullYear(),t=this.getUTCMonth()+1,n=this.getUTCDate();return this.getWeek(e,t,n)},Date.prototype.isDST=function(){return console.log("isDST"),this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D"},Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST())},Date.prototype.setTimezoneOffset=function(e){var t=this.getTimezoneOffset(),n=Number(e)*-6/10;return this.addMinutes(n-t),this},Date.prototype.setTimezone=function(e){return this.setTimezoneOffset(Date.getTimezoneOffset(e))},Date.prototype.getUTCOffset=function(){var e=this.getTimezoneOffset()*-10/6,t;return e<0?(t=(e-1e4).toString(),t[0]+t.substr(2)):(t=(e+1e4).toString(),"+"+t.substr(1))},Date.prototype.getDayName=function(e){return e?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()]},Date.prototype.getMonthName=function(e){return e?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()]},Date.prototype._toString=Date.prototype.toString,Date.prototype.toString=function(e){var t=this,n=function(t){return t.toString().length==1?"0"+t:t};return e?e.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(e){switch(e){case"hh":return n(t.getHours()<13?t.getHours():t.getHours()-12);case"h":return t.getHours()<13?t.getHours():t.getHours()-12;case"HH":return n(t.getHours());case"H":return t.getHours();case"mm":return n(t.getMinutes());case"m":return t.getMinutes();case"ss":return n(t.getSeconds());case"s":return t.getSeconds();case"yyyy":return t.getFullYear();case"yy":return t.getFullYear().toString().substring(2,4);case"dddd":return t.getDayName();case"ddd":return t.getDayName(!0);case"dd":return n(t.getDate());case"d":return t.getDate().toString();case"MMMM":return t.getMonthName();case"MMM":return t.getMonthName(!0);case"MM":return n(t.getMonth()+1);case"M":return t.getMonth()+1;case"t":return t.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return t.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return""}}):this._toString()}; -Date.now=function(){return new Date},Date.today=function(){return Date.now().clearTime()},Date.prototype._orient=1,Date.prototype.next=function(){return this._orient=1,this},Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){return this._orient=-1,this},Date.prototype._is=!1,Date.prototype.is=function(){return this._is=!0,this},Number.prototype._dateElement="day",Number.prototype.fromNow=function(){var e={};return e[this._dateElement]=this,Date.now().add(e)},Number.prototype.ago=function(){var e={};return e[this._dateElement]=this*-1,Date.now().add(e)},function(){var e=Date.prototype,t=Number.prototype,n="sunday monday tuesday wednesday thursday friday saturday".split(/\s/),r="january february march april may june july august september october november december".split(/\s/),i="Millisecond Second Minute Hour Day Week Month Year".split(/\s/),s,o=function(e){return function(){return this._is?(this._is=!1,this.getDay()==e):this.moveToDayOfWeek(e,this._orient)}};for(var u=0;u0&&!h)try{a=r.call(this,o[1])}catch(m){h=!0}else h=!0;!h&&a[1].length===0&&(h=!0);if(!h){var g=[];for(var y=0;y0&&(f[0]=f[0].concat(u[0]),f[1]=u[1])}f[1].length1?t=Array.prototype.slice.call(arguments):arguments[0]instanceof Array&&(t=arguments[0]);if(!t)return e.apply(null,arguments);for(var r=0,i=t.shift();r2?t:t+(t+2e3Date.getDaysInMonth(this.year,this.month))throw new RangeError(this.day+" is not a valid value for days.");var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);return this.timezone?r.set({timezone:this.timezone}):this.timezoneOffset&&r.set({timezoneOffset:this.timezoneOffset}),r},finish:function(t){t=t instanceof Array?e(t):[t];if(t.length===0)return null;for(var n=0;ne?1:this=e.getTime()&&n<=t.getTime()},Date.prototype.addMilliseconds=function(e){return this.setMilliseconds(this.getMilliseconds()+e),this},Date.prototype.addSeconds=function(e){return this.addMilliseconds(e*1e3)},Date.prototype.addMinutes=function(e){return this.addMilliseconds(e*6e4)},Date.prototype.addHours=function(e){return this.addMilliseconds(e*36e5)},Date.prototype.addDays=function(e){return this.addMilliseconds(e*864e5)},Date.prototype.addWeeks=function(e){return this.addMilliseconds(e*6048e5)},Date.prototype.addMonths=function(e){var t=this.getDate();return this.setDate(1),this.setMonth(this.getMonth()+e),this.setDate(Math.min(t,this.getDaysInMonth())),this},Date.prototype.addQuarters=function(e){return this.addMonths(e*3)},Date.prototype.addYears=function(e){return this.addMonths(e*12)},Date.prototype.add=function(e){if(typeof e=="number")return this._orient=e,this;var t=e;return(t.millisecond||t.milliseconds)&&this.addMilliseconds(t.millisecond||t.milliseconds),(t.second||t.seconds)&&this.addSeconds(t.second||t.seconds),(t.minute||t.minutes)&&this.addMinutes(t.minute||t.minutes),(t.hour||t.hours)&&this.addHours(t.hour||t.hours),(t.month||t.months)&&this.addMonths(t.month||t.months),(t.year||t.years)&&this.addYears(t.year||t.years),(t.day||t.days)&&this.addDays(t.day||t.days),this},Date._validate=function(e,t,n,r){if(typeof e!="number")throw new TypeError(e+" is not a Number.");if(en)throw new RangeError(e+" is not a valid value for "+r+".");return!0},Date.validateMillisecond=function(e){return Date._validate(e,0,999,"milliseconds")},Date.validateSecond=function(e){return Date._validate(e,0,59,"seconds")},Date.validateMinute=function(e){return Date._validate(e,0,59,"minutes")},Date.validateHour=function(e){return Date._validate(e,0,23,"hours")},Date.validateDay=function(e,t,n){return Date._validate(e,1,Date.getDaysInMonth(t,n),"days")},Date.validateMonth=function(e){return Date._validate(e,0,11,"months")},Date.validateYear=function(e){return Date._validate(e,1,9999,"seconds")},Date.prototype.set=function(e){var t=e;return!t.millisecond&&t.millisecond!==0&&(t.millisecond=-1),!t.second&&t.second!==0&&(t.second=-1),!t.minute&&t.minute!==0&&(t.minute=-1),!t.hour&&t.hour!==0&&(t.hour=-1),!t.day&&t.day!==0&&(t.day=-1),!t.month&&t.month!==0&&(t.month=-1),!t.year&&t.year!==0&&(t.year=-1),t.millisecond!=-1&&Date.validateMillisecond(t.millisecond)&&this.addMilliseconds(t.millisecond-this.getMilliseconds()),t.second!=-1&&Date.validateSecond(t.second)&&this.addSeconds(t.second-this.getSeconds()),t.minute!=-1&&Date.validateMinute(t.minute)&&this.addMinutes(t.minute-this.getMinutes()),t.hour!=-1&&Date.validateHour(t.hour)&&this.addHours(t.hour-this.getHours()),t.month!==-1&&Date.validateMonth(t.month)&&this.addMonths(t.month-this.getMonth()),t.year!=-1&&Date.validateYear(t.year)&&this.addYears(t.year-this.getFullYear()),t.day!=-1&&Date.validateDay(t.day,this.getFullYear(),this.getMonth())&&this.addDays(t.day-this.getDate()),t.timezone&&this.setTimezone(t.timezone),t.timezoneOffset&&this.setTimezoneOffset(t.timezoneOffset),this},Date.prototype.clearTime=function(){return this.setHours(0),this.setMinutes(0),this.setSeconds(0),this.setMilliseconds(0),this},Date.prototype.isLeapYear=function(){var e=this.getFullYear();return e%4===0&&e%100!==0||e%400===0},Date.prototype.isWeekday=function(){return!this.is().sat()&&!this.is().sun()},Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth())},Date.prototype.getQuarter=function(){return Math.floor((this.getMonth()+1)/3)},Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1})},Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()})},Date.prototype.moveToDayOfWeek=function(e,t){var n=(e-this.getDay()+7*(t||1))%7;return this.addDays(n===0?n+=7*(t||1):n)},Date.prototype.moveToMonth=function(e,t){var n=(e-this.getMonth()+12*(t||1))%12;return this.addMonths(n===0?n+=12*(t||1):n)},Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/864e5)},Date.prototype.getWeekOfYear=function(e){return this.getWeek();var t,n,r,i,s,o,u},Date.prototype.getWeek=function(e,t,n){var r,i,s,o,u,a,f,l,c,h,p=this;return Date.CultureInfo.firstDayOfWeek!==1&&(this.getDay()===0||!(this.getDay()364+c?h=1:h=(l/7|0)+1,e=t=n=null,h},Date.prototype.getISOWeek=function(){var e=this.getUTCFullYear(),t=this.getUTCMonth()+1,n=this.getUTCDate();return this.getWeek(e,t,n)},Date.prototype.isDST=function(){return console.log("isDST"),this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D"},Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST())},Date.prototype.setTimezoneOffset=function(e){var t=this.getTimezoneOffset(),n=Number(e)*-6/10;return this.addMinutes(n-t),this},Date.prototype.setTimezone=function(e){return this.setTimezoneOffset(Date.getTimezoneOffset(e))},Date.prototype.getUTCOffset=function(){var e=this.getTimezoneOffset()*-10/6,t;return e<0?(t=(e-1e4).toString(),t[0]+t.substr(2)):(t=(e+1e4).toString(),"+"+t.substr(1))},Date.prototype.getDayName=function(e){return e?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()]},Date.prototype.getMonthName=function(e){return e?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()]},Date.prototype._toString=Date.prototype.toString,Date.prototype.toString=function(e){var t=this,n=function(t){return t.toString().length==1?"0"+t:t};return e?e.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(e){switch(e){case"hh":return n(t.getHours()<13?t.getHours():t.getHours()-12);case"h":return t.getHours()<13?t.getHours():t.getHours()-12;case"HH":return n(t.getHours());case"H":return t.getHours();case"mm":return n(t.getMinutes());case"m":return t.getMinutes();case"ss":return n(t.getSeconds());case"s":return t.getSeconds();case"yyyy":return t.getFullYear();case"yy":return t.getFullYear().toString().substring(2,4);case"dddd":return t.getDayName();case"ddd":return t.getDayName(!0);case"dd":return n(t.getDate());case"d":return t.getDate().toString();case"MMMM":return t.getMonthName();case"MMM":return t.getMonthName(!0);case"MM":return n(t.getMonth()+1);case"M":return t.getMonth()+1;case"t":return t.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return t.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return""}}):this._toString()}; -Date.now=function(){return new Date},Date.today=function(){return Date.now().clearTime()},Date.prototype._orient=1,Date.prototype.next=function(){return this._orient=1,this},Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){return this._orient=-1,this},Date.prototype._is=!1,Date.prototype.is=function(){return this._is=!0,this},Number.prototype._dateElement="day",Number.prototype.fromNow=function(){var e={};return e[this._dateElement]=this,Date.now().add(e)},Number.prototype.ago=function(){var e={};return e[this._dateElement]=this*-1,Date.now().add(e)},function(){var e=Date.prototype,t=Number.prototype,n="sunday monday tuesday wednesday thursday friday saturday".split(/\s/),r="january february march april may june july august september october november december".split(/\s/),i="Millisecond Second Minute Hour Day Week Month Year".split(/\s/),s,o=function(e){return function(){return this._is?(this._is=!1,this.getDay()==e):this.moveToDayOfWeek(e,this._orient)}};for(var u=0;u0&&!h)try{a=r.call(this,o[1])}catch(m){h=!0}else h=!0;!h&&a[1].length===0&&(h=!0);if(!h){var g=[];for(var y=0;y0&&(f[0]=f[0].concat(u[0]),f[1]=u[1])}f[1].length1?t=Array.prototype.slice.call(arguments):arguments[0]instanceof Array&&(t=arguments[0]);if(!t)return e.apply(null,arguments);for(var r=0,i=t.shift();r2?t:t+(t+2e3Date.getDaysInMonth(this.year,this.month))throw new RangeError(this.day+" is not a valid value for days.");var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);return this.timezone?r.set({timezone:this.timezone}):this.timezoneOffset&&r.set({timezoneOffset:this.timezoneOffset}),r},finish:function(t){t=t instanceof Array?e(t):[t];if(t.length===0)return null;for(var n=0;n 0) { - return found; - } else { - if (parent.length === 0 || parent.is(options.stopAt)) { - return $([]); - } else { - return parent.findElementInDom(selector, options); - } - } - }; - -})( jQuery ); diff --git a/app/assets/javascripts/jquery_noconflict.js b/app/assets/javascripts/jquery_noconflict.js deleted file mode 100644 index 4843fe52781..00000000000 --- a/app/assets/javascripts/jquery_noconflict.js +++ /dev/null @@ -1,29 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 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 docs/COPYRIGHT.rdoc for more details. -//++ - -$.noConflict(); diff --git a/app/assets/javascripts/lib/jquery.is_visible_within.js b/app/assets/javascripts/lib/jquery.is_visible_within.js deleted file mode 100644 index 1d872ba5d5f..00000000000 --- a/app/assets/javascripts/lib/jquery.is_visible_within.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2012, Digital Fusion - * Licensed under the MIT license. - * http://teamdf.com/jquery-plugins/license/ - * - * @author Sam Sehnert - * @desc A small plugin that checks whether elements are within - * the user visible viewport of a web browser. - * only accounts for vertical position, not horizontal. - * - * Extended here to include an optional container used as parent, - * as the original plugin only supports window. - */ -(function ($) { - - $.fn.isVisibleWithin = function (container, partial, hidden) { - var $t = $(this).eq(0), - t = $t.get(0), - $w = (container != null ? container : $(window)), - viewTop = (container != null ? container.offset().top : $w.scrollTop()), - viewBottom = viewTop + $w.height(), - _top = $t.offset().top, - _bottom = _top + $t.height(), - compareTop = partial === true ? _bottom : _top, - compareBottom = partial === true ? _top : _bottom, - clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true; - return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)); - }; - -})(jQuery); diff --git a/app/assets/javascripts/lib/jquery.trap.js b/app/assets/javascripts/lib/jquery.trap.js deleted file mode 100644 index 78a2c043927..00000000000 --- a/app/assets/javascripts/lib/jquery.trap.js +++ /dev/null @@ -1,203 +0,0 @@ -/*! -Copyright (c) 2011, 2012 Julien Wajsberg -All rights reserved. - -Official repository: https://github.com/julienw/jquery-trap-input -License is there: https://github.com/julienw/jquery-trap-input/blob/master/LICENSE -This is version 1.2.0. -*/ - -(function( $, undefined ){ - -/* -(this comment is after the first line of code so that uglifyjs removes it) - -Redistribution and use in source and binary forms, with or without -modification, are permitted without condition. - -Although that's not an obligation, I would appreciate that you provide a -link to the official repository. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. -*/ - -/*jshint boss: true, bitwise: true, curly: true, expr: true, newcap: true, noarg: true, nonew: true, latedef: true, regexdash: true */ - - var DATA_ISTRAPPING_KEY = "trap.isTrapping"; - - function onkeypress(e) { - if (e.keyCode === 9) { - var goReverse = !!(e.shiftKey); - if (processTab(this, e.target, goReverse)) { - e.preventDefault(); - e.stopPropagation(); - } - } - } - - // will return true if we could process the tab event - // otherwise, return false - function processTab(container, elt, goReverse) { - var $focussable = getFocusableElementsInContainer(container), - curElt = elt, - index, nextIndex, prevIndex, lastIndex; - - do { - index = $focussable.index(curElt); - nextIndex = index + 1; - prevIndex = index - 1; - lastIndex = $focussable.length - 1; - - switch(index) { - case -1: - return false; // that's strange, let the browser do its job - case 0: - prevIndex = lastIndex; - break; - case lastIndex: - nextIndex = 0; - break; - } - - if (goReverse) { - nextIndex = prevIndex; - } - - curElt = $focussable.get(nextIndex); - if (!curElt || curElt === elt) { return true; } - - try { - curElt.focus(); - } catch(e) { // IE sometimes throws when an element is not visible - return true; - } - - } while ($focussable.length > 1 && elt === elt.ownerDocument.activeElement); - - return true; - } - - function filterKeepSpeciallyFocusable() { - return this.tabIndex > 0; - } - - function filterKeepNormalElements() { - return !this.tabIndex; // true if no tabIndex or tabIndex == 0 - } - - function sortFocusable(a, b) { - return (a.t - b.t) || (a.i - b.i); - } - - function getFocusableElementsInContainer(container) { - var $container = $(container); - var result = [], - cnt = 0; - - fixIndexSelector.enable && fixIndexSelector.enable(); - - // leaving away command and details for now - $container.find("a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex=0]") - .filter(":visible") - .filter(filterKeepNormalElements) - .each(function(i, val) { - result.push({ - v: val, // value - t: 0, // tabIndex - i: cnt++ // index for stable sort - }); - }); - - $container - .find("[tabindex]") - .filter(":visible") - .filter(filterKeepSpeciallyFocusable) - .each(function(i, val) { - result.push({ - v: val, // value - t: val.tabIndex, // tabIndex - i: cnt++ // index - }); - }); - - fixIndexSelector.disable && fixIndexSelector.disable(); - - result = $.map(result.sort(sortFocusable), // needs stable sort - function(val) { - return val.v; - } - ); - - - return $(result); - - } - - function trap() { - this.keydown(onkeypress); - this.data(DATA_ISTRAPPING_KEY, true); - return this; - } - - function untrap() { - this.unbind('keydown', onkeypress); - this.removeData(DATA_ISTRAPPING_KEY); - return this; - } - - function isTrapping() { - return !!this.data(DATA_ISTRAPPING_KEY); - } - - $.fn.extend({ - trap: trap, - untrap: untrap, - isTrapping: isTrapping - }); - - // jQuery 1.6.x tabindex attr hooks management - // this triggers problems for tabindex attribute - // selectors in IE7- - // see https://github.com/julienw/jquery-trap-input/issues/3 - - var fixIndexSelector = {}; - - if ($.find.find && $.find.attr !== $.attr) { - // jQuery uses Sizzle (this is jQuery >= 1.3) - // sizzle uses its own attribute handling (in jq 1.6.x and below) - (function() { - var tabindexKey = "tabindex"; - var sizzleAttrHandle = $.expr.attrHandle; - - // this function comes directly from jQuery 1.7.2 (propHooks.tabIndex.get) - // we have to put it here if we want to support jQuery < 1.6 which - // doesn't have an attrHooks object to reference. - function getTabindexAttr(elem) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode(tabindexKey); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - undefined; - } - - function fixSizzleAttrHook() { - // in jQ <= 1.6.x, we add to Sizzle the attrHook from jQuery's attr method - sizzleAttrHandle[tabindexKey] = sizzleAttrHandle.tabIndex = getTabindexAttr; - } - - function unfixSizzleAttrHook() { - delete sizzleAttrHandle[tabindexKey]; - delete sizzleAttrHandle.tabIndex; - } - - - fixIndexSelector = { - enable: fixSizzleAttrHook, - disable: unfixSizzleAttrHook - }; - })(); - } -})( jQuery ); \ No newline at end of file diff --git a/app/assets/javascripts/onboarding/backlogs_tour.js b/app/assets/javascripts/onboarding/backlogs_tour.js deleted file mode 100644 index fb760223203..00000000000 --- a/app/assets/javascripts/onboarding/backlogs_tour.js +++ /dev/null @@ -1,50 +0,0 @@ -(function ($) { - $(function() { - window.scrumBacklogsTourSteps = [ - { - 'next #content-wrapper': I18n.t('js.onboarding.steps.backlogs.overview'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow' - }, - { - 'event_type': 'next', - 'selector': '#sprint_backlogs_container .backlog .menu-trigger', - 'description': I18n.t('js.onboarding.steps.backlogs.task_board_arrow'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $('#sprint_backlogs_container .backlog .menu-trigger')[0].click(); - } - }, - { - 'event_type': 'next', - 'selector': '#sprint_backlogs_container .backlog .menu .items', - 'description': I18n.t('js.onboarding.steps.backlogs.task_board_select'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark', - onNext: function () { - $('#sprint_backlogs_container .backlog .show_task_board')[0].click(); - } - } - ]; - - window.scrumTaskBoardTourSteps = [ - { - 'next #content-wrapper': I18n.t('js.onboarding.steps.backlogs.task_board'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow' - }, - { - 'next #main-menu-work-packages-wrapper': I18n.t('js.onboarding.steps.wp.toggler'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $('#main-menu-work-packages')[0].click(); - } - }, - ]; - }); -}(jQuery)) diff --git a/app/assets/javascripts/onboarding/boards_tour.js b/app/assets/javascripts/onboarding/boards_tour.js deleted file mode 100644 index 0222b5a5921..00000000000 --- a/app/assets/javascripts/onboarding/boards_tour.js +++ /dev/null @@ -1,45 +0,0 @@ -(function ($) { - $(function() { - window.boardTourSteps = [ - { - 'next .board-view-menu-item': I18n.t('js.onboarding.steps.boards.overview'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $('.board-view-menu-item ~ .toggler')[0].click(); - - waitForElement('.boards--menu-items', '#main-menu', function() { - $(".main-menu--children-sub-item:contains('Kanban')")[0].click(); - }); - } - }, - { - 'next .board-list--container': I18n.t('js.onboarding.steps.boards.lists'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow', - 'timeout': function() { - return new Promise(function(resolve) { - waitForElement('.wp-card', '#content', function() { - resolve(); - }); - }); - } - }, - { - 'next .board-list--add-button': I18n.t('js.onboarding.steps.boards.add'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - }, - { - 'next .boards-list--container': I18n.t('js.onboarding.steps.boards.drag'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow', - onNext: function () { - $('.main-menu--arrow-left-to-project')[0].click(); - } - } - ]; - }); -}(jQuery)) diff --git a/app/assets/javascripts/onboarding/homescreen_tour.js b/app/assets/javascripts/onboarding/homescreen_tour.js deleted file mode 100644 index 7907d910528..00000000000 --- a/app/assets/javascripts/onboarding/homescreen_tour.js +++ /dev/null @@ -1,35 +0,0 @@ -(function ($) { - $(function() { - window.homescreenOnboardingTourSteps = [ - { - 'next #top-menu': I18n.t('js.onboarding.steps.welcome'), - 'skipButton': {className: 'enjoyhint_btn-transparent', text: I18n.t('js.onboarding.buttons.skip')}, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-hidden-arrow', - 'bottom': 7 - }, - { - 'description': I18n.t('js.onboarding.steps.project_selection'), - 'selector': '.widget-box.welcome', - 'event': 'custom', - 'showSkip': false, - 'containerClass': '-dark -hidden-arrow', - 'clickable': true, - onBeforeStart: function () { - // Handle the correct project selection and redirection - // This will be removed once the project selection is implemented - jQuery(".widget-box.welcome a:contains(" + scrumDemoProjectName + ")").click(function () { - tutorialInstance.trigger('next'); - window.location = this.href + '/backlogs/?start_scrum_onboarding_tour=true'; - }); - jQuery(".widget-box.welcome a:contains(" + demoProjectName + ")").click(function () { - tutorialInstance.trigger('next'); - window.location = this.href + '/work_packages/?start_onboarding_tour=true'; - }); - // Disable clicks on other links - $('.widget-box.welcome a').addClass('-disabled').bind('click', preventClickHandler); - } - } - ]; - }); -}(jQuery)) diff --git a/app/assets/javascripts/onboarding/menu_tour.js b/app/assets/javascripts/onboarding/menu_tour.js deleted file mode 100644 index 6d1031869e0..00000000000 --- a/app/assets/javascripts/onboarding/menu_tour.js +++ /dev/null @@ -1,22 +0,0 @@ -(function ($) { - $(function() { - window.menuTourSteps = [ - { - 'next .members-menu-item': I18n.t('js.onboarding.steps.members'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - }, - { - 'next .wiki-menu--main-item': I18n.t('js.onboarding.steps.wiki'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - }, - { - 'next .menu-item--help': I18n.t('js.onboarding.steps.help_menu'), - 'shape': 'circle', - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.got_it')} - } - ]; - }); -}(jQuery)) diff --git a/app/assets/javascripts/onboarding/onboarding_tour.js b/app/assets/javascripts/onboarding/onboarding_tour.js deleted file mode 100644 index b8c9d50a38f..00000000000 --- a/app/assets/javascripts/onboarding/onboarding_tour.js +++ /dev/null @@ -1,149 +0,0 @@ -(function ($) { - $(function() { - // ------------------------------- Global ------------------------------- - window.tutorialInstance; - window.preventClickHandler = function (e) { - e.preventDefault(); - e.stopPropagation(); - }; - window.waitForElement = function(element, container, execFunction) { - // Wait for the element to be ready - var observer = new MutationObserver(function (mutations, observerInstance) { - if ($(element).length) { - observerInstance.disconnect(); // stop observing - execFunction(); - return; - } - }); - observer.observe($(container)[0], { - childList: true, - subtree: true - }); - }; - window.demoProjectName = 'Demo project'; - window.scrumDemoProjectName = 'Scrum project'; - - var storageKey = 'openProject-onboardingTour'; - var currentTourPart = sessionStorage.getItem(storageKey); - var url = new URL(window.location.href); - var isMobile = document.body.classList.contains('-browser-mobile'); - var demoProjectsAvailable = $('meta[name=demo_projects_available]').attr('content') === "true"; - var boardsDemoDataAvailable = $('meta[name=boards_demo_data_available]').attr('content') === "true"; - var eeTokenAvailable = !$('body').hasClass('ee-banners-visible'); - var tourCancelled = false; - - // ------------------------------- Initial start ------------------------------- - // Do not show the tutorial on mobile or when the demo data has been deleted - if(!isMobile && demoProjectsAvailable) { - - // Start after the intro modal (language selection) - // This has to be changed once the project selection is implemented - if (url.searchParams.get("first_time_user") && demoProjectsLinks().length == 2) { - currentTourPart = ''; - sessionStorage.setItem(storageKey, 'readyToStart'); - - // Start automatically when the language selection is closed - $('.op-modal--modal-close-button').click(function () { - tourCancelled = true; - homescreenTour(); - }); - - //Start automatically when the escape button is pressed - document.addEventListener('keydown', function(event) { - if (event.key == "Escape" && !tourCancelled) { - tourCancelled = true; - homescreenTour(); - } - }, { once: true }); - } - - // ------------------------------- Tutorial Homescreen page ------------------------------- - if (currentTourPart === "readyToStart") { - homescreenTour(); - } - - // ------------------------------- Tutorial WP page ------------------------------- - if (currentTourPart === "startMainTourFromBacklogs" || url.searchParams.get("start_onboarding_tour")) { - mainTour(); - } - - // ------------------------------- Tutorial Backlogs page ------------------------------- - if (url.searchParams.get("start_scrum_onboarding_tour")) { - if ($('.backlogs-menu-item').length > 0) { - backlogsTour(); - } - } - - // ------------------------------- Tutorial Task Board page ------------------------------- - if (currentTourPart === "startTaskBoardTour") { - taskboardTour(); - } - } - - function demoProjectsLinks() { - demoProjects = []; - demoProjectsLink = jQuery(".widget-box.welcome a:contains(" + demoProjectName + ")"); - scrumDemoProjectsLink = jQuery(".widget-box.welcome a:contains(" + scrumDemoProjectName + ")"); - if (demoProjectsLink.length) demoProjects.push(demoProjectsLink); - if (scrumDemoProjectsLink.length) demoProjects.push(scrumDemoProjectsLink); - - return demoProjects; - } - - function initializeTour(storageValue, disabledElements, projectSelection) { - tutorialInstance = new EnjoyHint({ - onStart: function () { - $('#content-wrapper, #menu-sidebar').addClass('-hidden-overflow'); - }, - onEnd: function () { - sessionStorage.setItem(storageKey, storageValue); - $('#content-wrapper, #menu-sidebar').removeClass('-hidden-overflow'); - }, - onSkip: function () { - sessionStorage.setItem(storageKey, 'skipped'); - if (disabledElements) jQuery(disabledElements).removeClass('-disabled').unbind('click', preventClickHandler); - if (projectSelection) $.each(demoProjectsLinks(), function(i, e) { $(e).off('click')}); - $('#content-wrapper, #menu-sidebar').removeClass('-hidden-overflow'); - } - }); - } - - function startTour(steps) { - tutorialInstance.set(steps); - tutorialInstance.run(); - } - - function homescreenTour() { - initializeTour('startProjectTour', '.widget-box--blocks--buttons a', true); - startTour(homescreenOnboardingTourSteps); - } - - function backlogsTour() { - initializeTour('startTaskBoardTour'); - startTour(scrumBacklogsTourSteps); - } - - function taskboardTour() { - initializeTour('startMainTourFromBacklogs'); - startTour(scrumTaskBoardTourSteps); - } - - function mainTour() { - initializeTour('mainTourFinished'); - - waitForElement('.work-package--results-tbody', '#content', function() { - var steps; - - // Check for EE edition, and available seed data of boards. - // Then add boards to the tour, otherwise skip it. - if (eeTokenAvailable && boardsDemoDataAvailable) { - steps = wpOnboardingTourSteps.concat(boardTourSteps).concat(menuTourSteps); - } else { - steps = wpOnboardingTourSteps.concat(menuTourSteps); - } - - startTour(steps); - }); - } - }); -}(jQuery)); diff --git a/app/assets/javascripts/onboarding/work_package_tour.js b/app/assets/javascripts/onboarding/work_package_tour.js deleted file mode 100644 index 93f1a7bacd7..00000000000 --- a/app/assets/javascripts/onboarding/work_package_tour.js +++ /dev/null @@ -1,70 +0,0 @@ -(function ($) { - $(function() { - window.wpOnboardingTourSteps = [ - { - 'next .wp-table--row': I18n.t('js.onboarding.steps.wp.list'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $(".inline-edit--display-field.id a ")[0].click(); - } - }, - { - 'next .work-packages-full-view--split-left': I18n.t('js.onboarding.steps.wp.full_view'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow' - }, - { - 'next .work-packages-back-button': I18n.t('js.onboarding.steps.wp.back_button'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $('.work-packages-back-button')[0].click(); - } - }, - { - 'next .add-work-package': I18n.t('js.onboarding.steps.wp.create_button'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'shape': 'circle', - 'timeout': function() { - return new Promise(function(resolve) { - // We are waiting here for the badge to appear, - // because its the last that appears and it shifts the WP create button to the left. - // Thus it is important that the tour rendering starts after the badge is visible - waitForElement('#work-packages-filter-toggle-button .badge', '#content', function() { - resolve(); - }); - }); - }, - onNext: function () { - $('#wp-view-toggle-button').click(); - } - }, - { - 'next #wp-view-toggle-button': I18n.t('js.onboarding.steps.wp.timeline_button'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'bottom': '-100', - onNext: function () { - $('#wp-view-context-menu .icon-view-timeline')[0].click(); - } - }, - { - 'next .work-packages-tabletimeline--timeline-side': I18n.t('js.onboarding.steps.wp.timeline'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - 'containerClass': '-dark -hidden-arrow' - }, - { - 'next .main-menu--arrow-left-to-project': I18n.t('js.onboarding.steps.sidebar_arrow'), - 'showSkip': false, - 'nextButton': {text: I18n.t('js.onboarding.buttons.next')}, - onNext: function () { - $('.main-menu--arrow-left-to-project')[0].click(); - } - } - ]; - }); -}(jQuery)) diff --git a/app/assets/javascripts/project/responsible_attribute.js b/app/assets/javascripts/project/responsible_attribute.js deleted file mode 100644 index 2bbc15a1321..00000000000 --- a/app/assets/javascripts/project/responsible_attribute.js +++ /dev/null @@ -1,43 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 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 docs/COPYRIGHT.rdoc for more details. -//++ - -jQuery(document).ready(function($) { - $("#project_responsible_id").autocomplete({ - ajax: { - null_element: {id: -1, name: I18n.t("js.filter.noneElement")}, - data: function (term, page) { - return { - q: term, //search term - page_limit: 10, // page size - page: page, // current page number - id: $("#project_responsible_id").attr("data-projectId") - }; - } - } - }); -}); diff --git a/app/assets/javascripts/select_list_move.js b/app/assets/javascripts/select_list_move.js deleted file mode 100644 index d6545992e06..00000000000 --- a/app/assets/javascripts/select_list_move.js +++ /dev/null @@ -1,66 +0,0 @@ -//-- copyright -// OpenProject is an open source project management software. -// Copyright (C) 2012-2020 the OpenProject GmbH -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 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 docs/COPYRIGHT.rdoc for more details. -//++ - -function moveOptions(sourceId, destId) { - var sourceSelection = jQuery('#' + sourceId); - var destSelection = jQuery('#' + destId); - - var selectedOptions = sourceSelection.find('option:selected'); - - selectedOptions.each(function() { - var option = jQuery('