Merge pull request #2188 from opf/feature/merge_release_4_into_dev

pull/2195/head
Hagen Schink 10 years ago
commit e7a027afff
  1. 2
      app/assets/javascripts/angular/helpers/path-helper.js
  2. 2
      app/assets/javascripts/angular/timelines/directives/index.js
  3. 25
      app/assets/javascripts/angular/timelines/directives/timeline-container-directive.js
  4. 33
      doc/operation_guides/packager/installation_and_upgrade_guide.md
  5. 3
      lib/redmine/i18n.rb
  6. 77
      spec/lib/redmine/i18n_spec.rb
  7. 14
      test/functional/application_controller_test.rb
  8. 17
      test/unit/lib/redmine/i18n_test.rb

@ -171,7 +171,7 @@ module.exports = function() {
return PathHelper.apiProjectPath(projectIdentifier) + PathHelper.subProjectsPath(); return PathHelper.apiProjectPath(projectIdentifier) + PathHelper.subProjectsPath();
}, },
apiProjectUsersPath: function(projectIdentifier) { apiProjectUsersPath: function(projectIdentifier) {
return PathHelper.apiProjectPath(projectIdentifier) + PathHelper.usersPath(); return PathHelper.apiProjectPath(projectIdentifier) + '/users';
}, },
apiVersionsPath: function(projectIdentifier) { apiVersionsPath: function(projectIdentifier) {
return PathHelper.apiExperimental + PathHelper.versionsPath(); return PathHelper.apiExperimental + PathHelper.versionsPath();

@ -33,7 +33,7 @@ angular.module('openproject.timelines.directives')
]) ])
.directive('timelineColumnName', ['I18n', 'CustomFieldHelper', require( .directive('timelineColumnName', ['I18n', 'CustomFieldHelper', require(
'./timeline-column-name-directive')]) './timeline-column-name-directive')])
.directive('timelineContainer', ['Timeline', require( .directive('timelineContainer', ['$window', 'Timeline', require(
'./timeline-container-directive')]) './timeline-container-directive')])
.directive('timelineGroupingLabel', [require( .directive('timelineGroupingLabel', [require(
'./timeline-grouping-label-directive')]) './timeline-grouping-label-directive')])

@ -26,7 +26,7 @@
// See doc/COPYRIGHT.rdoc for more details. // See doc/COPYRIGHT.rdoc for more details.
//++ //++
module.exports = function(Timeline) { module.exports = function($window, Timeline) {
getInitialOutlineExpansion = function(timelineOptions) { getInitialOutlineExpansion = function(timelineOptions) {
initialOutlineExpansion = timelineOptions.initial_outline_expansion; initialOutlineExpansion = timelineOptions.initial_outline_expansion;
if (initialOutlineExpansion && initialOutlineExpansion >= 0) { if (initialOutlineExpansion && initialOutlineExpansion >= 0) {
@ -36,6 +36,14 @@ module.exports = function(Timeline) {
} }
}; };
setTimelinesWidth = function(scope) {
var contentElement = angular.element('#content');
if (contentElement.length > 0) {
scope.timelineWidth = contentElement.width();
}
};
return { return {
restrict: 'E', restrict: 'E',
replace: true, replace: true,
@ -45,7 +53,7 @@ module.exports = function(Timeline) {
}; };
}], }],
transclude: true, transclude: true,
template: '<div>' + template: '<div ng-style="{ width: timelineWidth }">' +
'<div ng-hide="!!errorMessage" ng-transclude id="{{timelineContainerElementId}}"/>' + '<div ng-hide="!!errorMessage" ng-transclude id="{{timelineContainerElementId}}"/>' +
'<div ng-if="!!errorMessage" ng-bind="errorMessage" class="flash error"/>' + '<div ng-if="!!errorMessage" ng-bind="errorMessage" class="flash error"/>' +
'</div>', '</div>',
@ -60,6 +68,19 @@ module.exports = function(Timeline) {
// Set initial expansion index // Set initial expansion index
scope.timeline.expansionIndex = getInitialOutlineExpansion(scope.timelineOptions); scope.timeline.expansionIndex = getInitialOutlineExpansion(scope.timelineOptions);
// As part of a wiki the timeline container would have to stick to the wiki's width
// limitation. We set the timeline width programmatically to bypass the width
// limitation.
if (angular.element('.wiki-content').length > 0) {
setTimelinesWidth(scope);
angular.element($window).bind('resize', function() {
scope.$apply(function() {
setTimelinesWidth(scope);
});
});
}
} }
}; };
} }

@ -13,7 +13,11 @@ Ruby 2.1.3 (MRI) and necessary libraries to run the OpenProject source code.
The installation procedure assumes the following prerequisites to be met: The installation procedure assumes the following prerequisites to be met:
* A server running either _Debian 7.6 (amd64)_ or _Fedora 20 (amd64)_ to perform the installation on. * A server running one of the following Linux distributions:
* _Debian 7.6 Wheezy 64 bits server_
* _Ubuntu 14.04 Trusty 64bits server_
* _Fedora 20 64bits server_
* _CentOS 6 / RHEL 6 64 bits server_
* A mail server that is accessible via SMTP that can be used for sending notification emails. OpenProject supports authentication, yet does not provide support for SMTP via SSL/TLS. * A mail server that is accessible via SMTP that can be used for sending notification emails. OpenProject supports authentication, yet does not provide support for SMTP via SSL/TLS.
If you intend to use SSL for OpenProject: If you intend to use SSL for OpenProject:
@ -23,7 +27,7 @@ If you intend to use SSL for OpenProject:
The following steps have to be performed to initiate the actual installation of OpenProject via package manager. Note that all commands should either be run as root or should be prepended by sudo otherwise (typically depending what linux distribution is used). The following steps have to be performed to initiate the actual installation of OpenProject via package manager. Note that all commands should either be run as root or should be prepended by sudo otherwise (typically depending what linux distribution is used).
## Debian ## Debian 7.6 Wheezy 64bits server
# install https support # install https support
apt-get install apt-transport-https apt-get install apt-transport-https
@ -33,12 +37,29 @@ The following steps have to be performed to initiate the actual installation of
sudo apt-get update sudo apt-get update
sudo apt-get install openproject sudo apt-get install openproject
## Fedora ## Ubuntu 14.04 Trusty 64bits server
wget -qO - https://deb.packager.io/key | sudo apt-key add -
echo "deb https://deb.packager.io/gh/opf/openproject trusty stable" |
sudo tee /etc/apt/sources.list.d/openproject.list
sudo apt-get update
sudo apt-get install openproject
## Fedora 20 64bits server
sudo rpm --import https://rpm.packager.io/key
echo "[openproject]
name=Repository for opf/openproject application.
baseurl=https://rpm.packager.io/gh/opf/openproject/fedora20/stable
enabled=1" | sudo tee /etc/yum.repos.d/openproject.repo
sudo yum install openproject
## CentOS / RHEL 6 64 bits server
sudo rpm --import https://rpm.packager.io/key sudo rpm --import https://rpm.packager.io/key
echo "[openproject] echo "[openproject]
name=Repository for opf/openproject application. name=Repository for opf/openproject application.
baseurl=https://rpm.packager.io/gh/opf/openproject/fedora20/feature/packager-new-installer-stable baseurl=https://rpm.packager.io/gh/opf/openproject/centos6/stable
enabled=1" | sudo tee /etc/yum.repos.d/openproject.repo enabled=1" | sudo tee /etc/yum.repos.d/openproject.repo
sudo yum install openproject sudo yum install openproject
@ -116,13 +137,13 @@ The command above will bring up the installation wizard again. Please be aware t
Upgrading the OpenProject is as easy as installing a newer OpenProject package and running the openproject configure command. Upgrading the OpenProject is as easy as installing a newer OpenProject package and running the openproject configure command.
## Debian ## Debian / Ubuntu
sudo apt-get update sudo apt-get update
sudo apt-get install --only-upgrade openproject sudo apt-get install --only-upgrade openproject
sudo openproject configure sudo openproject configure
## Fedora ## Fedora / CentOS / RHEL
sudo yum update sudo yum update
sudo yum install openproject sudo yum install openproject

@ -110,8 +110,7 @@ module Redmine
end end
def find_language(lang) def find_language(lang)
@@languages_lookup = valid_languages.inject({}) { |k, v| k[v.to_s.downcase] = v; k } valid_languages.detect { |l| l =~ /#{lang}/i }
@@languages_lookup[lang.to_s.downcase]
end end
def set_language_if_valid(lang) def set_language_if_valid(lang)

@ -70,14 +70,83 @@ module OpenProject
end end
end end
describe :all_languages do describe 'all_languages' do
it 'should at least return en' do
# using this to ensure that the files are evaluated # Those are the two languages we support
it 'includes en' do
expect(all_languages).to include(:en) expect(all_languages).to include(:en)
end end
it 'includes de' do
expect(all_languages).to include(:de)
end
it 'should return no js language as they are duplicates of the rest of the other language' do it 'should return no js language as they are duplicates of the rest of the other language' do
expect(all_languages.any? { |l| /\Ajs-/.match(l.to_s) }).to be_false expect(all_languages.any? { |l| /\Ajs-/.match(l.to_s) }).to be_falsey
end
# it is OK if more languages exist
it 'has a language for every language file' do
lang_files_count = Dir.glob(Rails.root.join('config/locales/*.yml'))
.map { |f| File.basename(f) }
.reject { |b| b.starts_with? 'js' }
.size
expect(all_languages.size).to eql lang_files_count
end
end
describe 'valid_languages' do
it 'allows only languages that are available' do
allow(Setting).to receive(:available_languages).and_return([:en])
expect(valid_languages).to eql [:en]
end
it 'allows only languages that exist' do
allow(Setting).to receive(:available_languages).and_return([:'123'])
expect(valid_languages).to be_empty
end
end
describe 'set_language_if_valid' do
before do
allow(Setting).to receive(:available_languages).and_return(Setting.all_languages)
end
Setting.all_languages.each do |lang|
it "should set I18n.locale to #{lang}" do
allow(I18n).to receive(:locale=)
expect(I18n).to receive(:locale=).with(lang)
set_language_if_valid(lang)
end
end
it 'should not set I18n.locale to an invalid language' do
allow(Setting).to receive(:available_languages).and_return([:en])
expect(I18n).to_not receive(:locale=).with(:de)
end
end
describe 'find_language' do
it 'is nil if language is not active' do
allow(Setting).to receive(:available_languages).and_return([:de])
expect(find_language(:en)).to be_nil
end
it 'is the language if it is active' do
allow(Setting).to receive(:available_languages).and_return([:de])
expect(find_language(:de)).to eql :de
end
it 'can be found by uppercase if it is active' do
allow(Setting).to receive(:available_languages).and_return([:de])
expect(find_language(:DE)).to eql :de
end end
end end
end end

@ -42,20 +42,6 @@ class ApplicationControllerTest < ActionController::TestCase
@response = ActionController::TestResponse.new @response = ActionController::TestResponse.new
end end
# check that all language files are valid
def test_localization
lang_files_count = Dir.glob(Rails.root.join('config/locales/*.yml'))
.map { |f| File.basename(f) }
.reject { |b| b.starts_with? 'js' }
.size
Setting.available_languages = Setting.all_languages
assert_equal lang_files_count, valid_languages.size
valid_languages.each do |lang|
assert set_language_if_valid(lang)
end
set_language_if_valid('en')
end
def test_call_hook_mixed_in def test_call_hook_mixed_in
assert @controller.respond_to?(:call_hook) assert @controller.respond_to?(:call_hook)
end end

@ -133,23 +133,6 @@ class Redmine::I18nTest < ActiveSupport::TestCase
end end
end end
def test_valid_languages
assert valid_languages.is_a?(Array)
assert valid_languages.first.is_a?(Symbol)
end
def test_valid_language
Setting.available_languages = [:de, :zh]
to_test = {'de' => :de,
'DE' => :de,
'De' => :de,
'de-ZZ' => nil,
'zh' => nil }
to_test.each {|lang, expected| assert_equal expected, find_language(lang)}
end
def test_fallback def test_fallback
::I18n.backend.store_translations(:en, {:untranslated => "Untranslated string"}) ::I18n.backend.store_translations(:en, {:untranslated => "Untranslated string"})
::I18n.locale = 'en' ::I18n.locale = 'en'

Loading…
Cancel
Save