Commit 7a1494a24ac6f7761bb59c8776c0aa77a56a4e41
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
Merge branches 'rails3_AI3033-serpro_integration' and 'rails3_stable' into rails3_stable
Showing
29 changed files
with
1137 additions
and
2 deletions
Show diff stats
lib/acts_as_having_settings.rb
@@ -44,7 +44,11 @@ module ActsAsHavingSettings | @@ -44,7 +44,11 @@ module ActsAsHavingSettings | ||
44 | class_eval <<-CODE | 44 | class_eval <<-CODE |
45 | def #{setting} | 45 | def #{setting} |
46 | val = send(self.class.settings_field)[:#{setting}] | 46 | val = send(self.class.settings_field)[:#{setting}] |
47 | - val.nil? ? (#{default}.is_a?(String) ? gettext(#{default}) : #{default}) : val | 47 | + if val.nil? |
48 | + val = #{default}.is_a?(String) ? gettext(#{default}) : #{default} | ||
49 | + send(self.class.settings_field)[:#{setting}] = val | ||
50 | + end | ||
51 | + val | ||
48 | end | 52 | end |
49 | def #{setting}=(value) | 53 | def #{setting}=(value) |
50 | h = send(self.class.settings_field).clone | 54 | h = send(self.class.settings_field).clone |
plugins/serpro_integration/controllers/serpro_integration_plugin_admin_controller.rb
0 → 100644
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +class SerproIntegrationPluginAdminController < AdminController | ||
2 | + | ||
3 | + def index | ||
4 | + settings = params[:settings] | ||
5 | + settings ||= {} | ||
6 | + | ||
7 | + @settings = Noosfero::Plugin::Settings.new(environment, SerproIntegrationPlugin, settings) | ||
8 | + if request.post? | ||
9 | + @settings.save! | ||
10 | + session[:notice] = 'Settings succefully saved.' | ||
11 | + redirect_to :action => 'index' | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
15 | +end |
plugins/serpro_integration/controllers/serpro_integration_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class SerproIntegrationPluginMyprofileController < MyProfileController | ||
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../views') | ||
3 | + | ||
4 | + def create_gitlab | ||
5 | + profile.create_gitlab_project | ||
6 | + render :update do |page| | ||
7 | + page.replace_html 'gitlab', :partial => 'gitlab' | ||
8 | +# page.replace_html 'gitlab', 'teste' | ||
9 | + end | ||
10 | +# raise 'teste my profile' | ||
11 | + end | ||
12 | + | ||
13 | +end |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +Feature: require authentication to comment | ||
2 | + | ||
3 | + Background: | ||
4 | + Given plugin RequireAuthToCommentPlugin is enabled on environment | ||
5 | + And the following users | ||
6 | + | login | | ||
7 | + | bozo | | ||
8 | + | ||
9 | + Scenario: enabling unauthenticated comment per profile | ||
10 | + Given I am logged in as "bozo" | ||
11 | + When I edit my profile | ||
12 | + And I check "Accept comments from unauthenticated users" | ||
13 | + And I press "Save" | ||
14 | + Then I edit my profile | ||
15 | + And the "Accept comments from unauthenticated users" checkbox should be checked |
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +require_dependency 'community' | ||
2 | + | ||
3 | +class Community | ||
4 | + | ||
5 | + settings_items :allow_sonar_integration, :type => :boolean, :default => true | ||
6 | + settings_items :allow_gitlab_integration, :type => :boolean, :default => true | ||
7 | + settings_items :allow_jenkins_integration, :type => :boolean, :default => true | ||
8 | + | ||
9 | + settings_items :serpro_integration_plugin_gitlab, :type => Hash, :default => {} | ||
10 | + settings_items :serpro_integration_plugin_jenkins, :type => Hash, :default => {} | ||
11 | + settings_items :serpro_integration_plugin_sonar, :type => Hash, :default => {} | ||
12 | + | ||
13 | + attr_accessible :allow_unauthenticated_comments, :allow_gitlab_integration, :allow_sonar_integration, :allow_jenkins_integration, :serpro_integration_plugin_gitlab, :serpro_integration_plugin_jenkins, :serpro_integration_plugin_sonar | ||
14 | + | ||
15 | + before_update :create_integration_projects | ||
16 | + | ||
17 | + def create_integration_projects | ||
18 | + return unless setting_changed?(:serpro_integration_plugin_gitlab) | ||
19 | + | ||
20 | + if allow_gitlab_integration | ||
21 | + gitlab_integration = SerproIntegrationPlugin::GitlabIntegration.new(gitlab_host, gitlab_private_token) | ||
22 | + gitlab_project = gitlab_integration.create_gitlab_project(self) | ||
23 | + serpro_integration_plugin_gitlab[:project_id] = gitlab_project.id | ||
24 | + | ||
25 | + if allow_jenkins_integration | ||
26 | + jenkins_integration = SerproIntegrationPlugin::JenkinsIntegration.new(jenkins_host, jenkins_private_token, jenkins_user) | ||
27 | + jenkins_integration.create_jenkis_project(self, gitlab_project.path_with_namespace, gitlab_project.web_url, gitlab_project.http_url_to_repo) | ||
28 | + end | ||
29 | + end | ||
30 | + end | ||
31 | + | ||
32 | + def serpro_integration_plugin_settings | ||
33 | + @settings ||= Noosfero::Plugin::Settings.new(environment, SerproIntegrationPlugin) | ||
34 | + end | ||
35 | + | ||
36 | + def gitlab_group | ||
37 | + serpro_integration_plugin_gitlab[:group] || self.identifier | ||
38 | + end | ||
39 | + | ||
40 | + def gitlab_project_name | ||
41 | + serpro_integration_plugin_gitlab[:project_name] || self.identifier | ||
42 | + end | ||
43 | + | ||
44 | + def gitlab_host | ||
45 | + serpro_integration_plugin_settings.gitlab[:host] | ||
46 | + end | ||
47 | + | ||
48 | + def gitlab_private_token | ||
49 | + serpro_integration_plugin_settings.gitlab[:private_token] | ||
50 | + end | ||
51 | + | ||
52 | + def jenkins_host | ||
53 | + serpro_integration_plugin_settings.jenkins[:host] | ||
54 | + end | ||
55 | + | ||
56 | + def jenkins_private_token | ||
57 | + serpro_integration_plugin_settings.jenkins[:private_token] | ||
58 | + end | ||
59 | + | ||
60 | + def jenkins_user | ||
61 | + serpro_integration_plugin_settings.jenkins[:user] | ||
62 | + end | ||
63 | + | ||
64 | + def jenkins_project_name | ||
65 | + serpro_integration_plugin_jenkins[:project_name] || self.identifier | ||
66 | + end | ||
67 | + | ||
68 | +end |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +require_dependency 'profile' | ||
2 | + | ||
3 | +class Profile | ||
4 | + settings_items :allow_sonar_integration, :type => :boolean, :default => true | ||
5 | + settings_items :allow_gitlab_integration, :type => :boolean, :default => true | ||
6 | + | ||
7 | + #FIXME make test for default option | ||
8 | + settings_items :serpro_integration_plugin, :type => Hash, :default => {} | ||
9 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin.rb
0 → 100644
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +class SerproIntegrationPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + def self.plugin_name | ||
4 | + "Serpro Integration Plugin" | ||
5 | + end | ||
6 | + | ||
7 | + def self.plugin_description | ||
8 | + _("Make integration with serpro servers.") | ||
9 | + end | ||
10 | + | ||
11 | + #FIXME make this test | ||
12 | + # User could not have this block | ||
13 | + def self.extra_blocks | ||
14 | + { SerproIntegrationPlugin::SonarWidgetBlock => {:type => [Community] }, | ||
15 | + SerproIntegrationPlugin::SmileBlock => {:type => [Community] }, | ||
16 | + } | ||
17 | + end | ||
18 | + | ||
19 | + #FIXME make this test | ||
20 | + def profile_editor_extras | ||
21 | + lambda do | ||
22 | + render :file => 'profile-editor-extras' if profile.kind_of?(Community) | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + def profile_id | ||
27 | + context.profile | ||
28 | + end | ||
29 | + | ||
30 | + def stylesheet? | ||
31 | + true | ||
32 | + end | ||
33 | + | ||
34 | +# FIXME make this test | ||
35 | + def js_files | ||
36 | + ['smile_face.js'] | ||
37 | + end | ||
38 | + | ||
39 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/gitlab_integration.rb
0 → 100644
@@ -0,0 +1,62 @@ | @@ -0,0 +1,62 @@ | ||
1 | +require 'gitlab' | ||
2 | + | ||
3 | +class SerproIntegrationPlugin::GitlabIntegration | ||
4 | + | ||
5 | + def initialize(host, private_token) | ||
6 | + @client = Gitlab.client(:endpoint => host, :private_token => private_token) | ||
7 | + end | ||
8 | + | ||
9 | + def create_group(group_name) | ||
10 | + #FIXME find group by name | ||
11 | + group = @client.groups.select {|group| group.name == group_name}.first | ||
12 | + group ||= @client.create_group(group_name, group_name) | ||
13 | + end | ||
14 | + | ||
15 | + def create_project(project_name, group) | ||
16 | + path_with_namespace = "#{group.name}/#{project_name}" | ||
17 | + #FIXME find project by namespace | ||
18 | + project = @client.get("/projects/search/#{project_name}").select do |project| | ||
19 | + project.path_with_namespace == path_with_namespace | ||
20 | + end.first | ||
21 | + | ||
22 | + if project.nil? | ||
23 | + project_options = {} | ||
24 | + project_options[:namespace_id] = group.id | ||
25 | + project_options[:issues_enabled ] = true | ||
26 | + project_options[:wall_enabled] = true | ||
27 | + project_options[:wiki_enabled] = true | ||
28 | + project_options[:public] = true | ||
29 | + | ||
30 | + project = @client.create_project(project_name, project_options) | ||
31 | + #Create Web Hook for Jenkins' integration | ||
32 | + #Gitlab.add_project_hook(project.id, "#{self.jenkins[:url]}/gitlab/build_now") | ||
33 | + end | ||
34 | + project | ||
35 | + end | ||
36 | + | ||
37 | + def create_user(email, group) | ||
38 | + user = @client.users(:search => email).first | ||
39 | + username = name = email[/[^@]+/] | ||
40 | + user ||= @client.create_user(email, '123456', {:username => username, :name => name, :provider => 'ldap'}) | ||
41 | + | ||
42 | + begin | ||
43 | + @client.add_group_member(group.id, user.id, 40) | ||
44 | + rescue Gitlab::Error::Conflict => e | ||
45 | + #already member | ||
46 | + end | ||
47 | + user | ||
48 | + end | ||
49 | + | ||
50 | + #http://rubydoc.info/gems/gitlab/frames | ||
51 | + def create_gitlab_project(profile) | ||
52 | + group = create_group(profile.gitlab_group) | ||
53 | + | ||
54 | + #create admins and add to group | ||
55 | + profile.admins.each do |person| | ||
56 | + create_user(person.user.email, group) | ||
57 | + end | ||
58 | + | ||
59 | + project = create_project(profile.gitlab_project_name, group) | ||
60 | + end | ||
61 | + | ||
62 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/gitlab_issues_block.rb
0 → 100644
@@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
1 | +require 'open-uri' | ||
2 | +require 'json' | ||
3 | + | ||
4 | +class SerproIntegrationPlugin::GitlabIssuesBlock < Block | ||
5 | + | ||
6 | + def self.description | ||
7 | + _('Gitlab Issues') | ||
8 | + end | ||
9 | + | ||
10 | + def help | ||
11 | + _('This block list gitlab issues') | ||
12 | + end | ||
13 | + | ||
14 | + #FIXME make this test | ||
15 | + def content(args={}) | ||
16 | + gitlab_integration = SerproIntegrationPlugin::GitlabIntegration.new(owner.gitlab_host, owner.gitlab_private_token) | ||
17 | + issues = gitlab_integration.issues(owner) | ||
18 | + block = self | ||
19 | + proc do | ||
20 | + render :file => 'blocks/gitlab_issues', :locals => {:issues => issues, :block => block} | ||
21 | + end | ||
22 | + #content_tag(:div, | ||
23 | + # content_tag(:canvas, '', :id => smile_face_id, :width => '95%', :height => '95%' ) + | ||
24 | + # "<script type='text/javascript'>drawFace('#{smile_face_id}', '#{self.smile_factor}')</script>", | ||
25 | + # :class => 'smile' | ||
26 | + #) | ||
27 | + end | ||
28 | + | ||
29 | + def cacheable? | ||
30 | + false | ||
31 | + end | ||
32 | + | ||
33 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/jenkins_integration.rb
0 → 100644
@@ -0,0 +1,102 @@ | @@ -0,0 +1,102 @@ | ||
1 | +# encoding: UTF-8 | ||
2 | +require 'jenkins_api_client' | ||
3 | + | ||
4 | +class SerproIntegrationPlugin::JenkinsIntegration | ||
5 | + | ||
6 | + def initialize(host, private_token, user) | ||
7 | + @client = JenkinsApi::Client.new(:server_url => host, :password => private_token, :username => user) | ||
8 | + end | ||
9 | + | ||
10 | + #FIXME make jenkins integration works | ||
11 | + def create_jenkis_project(profile, repository_path, web_url, git_url) | ||
12 | + #begin | ||
13 | + project_name = repository_path.split('/').last | ||
14 | + if @client.job.list(project_name).blank? | ||
15 | + @client.job.create(profile.jenkins_project_name, xml_jenkins(repository_path, web_url, git_url)) | ||
16 | + end | ||
17 | + #rescue JenkinsApi::Exceptions::ApiException | ||
18 | + #end | ||
19 | + end | ||
20 | + | ||
21 | + #FIXME | ||
22 | + def xml_jenkins(repository_path, web_url, git_url) | ||
23 | + " | ||
24 | + <maven2-moduleset plugin='maven-plugin@1.509'> | ||
25 | + <actions/> | ||
26 | + <description>Projeto criado para o repositório #{repository_path} do Gitlab - #{web_url}</description> | ||
27 | + <logRotator class='hudson.tasks.LogRotator'> | ||
28 | + <daysToKeep>-1</daysToKeep> | ||
29 | + <numToKeep>2</numToKeep> | ||
30 | + <artifactDaysToKeep>-1</artifactDaysToKeep> | ||
31 | + <artifactNumToKeep>-1</artifactNumToKeep> | ||
32 | + </logRotator> | ||
33 | + <keepDependencies>false</keepDependencies> | ||
34 | + <properties/> | ||
35 | + <scm class='hudson.plugins.git.GitSCM' plugin='git@2.2.1'> | ||
36 | + <configVersion>2</configVersion> | ||
37 | + <userRemoteConfigs> | ||
38 | + <hudson.plugins.git.UserRemoteConfig> | ||
39 | + <url>#{git_url}</url> | ||
40 | + </hudson.plugins.git.UserRemoteConfig> | ||
41 | + </userRemoteConfigs> | ||
42 | + <branches> | ||
43 | + <hudson.plugins.git.BranchSpec> | ||
44 | + <name>*/master</name> | ||
45 | + </hudson.plugins.git.BranchSpec> | ||
46 | + </branches> | ||
47 | + <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations> | ||
48 | + <submoduleCfg class='list'/> | ||
49 | + <extensions/> | ||
50 | + </scm> | ||
51 | + <canRoam>true</canRoam> | ||
52 | + <disabled>false</disabled> | ||
53 | + <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> | ||
54 | + <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> | ||
55 | + <jdk>(Inherit From Job)</jdk> | ||
56 | + <triggers class='vector'/> | ||
57 | + <concurrentBuild>false</concurrentBuild> | ||
58 | + <goals>clean package install deploy</goals> | ||
59 | + <aggregatorStyleBuild>true</aggregatorStyleBuild> | ||
60 | + <incrementalBuild>false</incrementalBuild> | ||
61 | + <perModuleEmail>true</perModuleEmail> | ||
62 | + <ignoreUpstremChanges>false</ignoreUpstremChanges> | ||
63 | + <archivingDisabled>false</archivingDisabled> | ||
64 | + <resolveDependencies>false</resolveDependencies> | ||
65 | + <processPlugins>false</processPlugins> | ||
66 | + <mavenValidationLevel>-1</mavenValidationLevel> | ||
67 | + <runHeadless>false</runHeadless> | ||
68 | + <disableTriggerDownstreamProjects>false</disableTriggerDownstreamProjects> | ||
69 | + <settings class='jenkins.mvn.DefaultSettingsProvider'/> | ||
70 | + <globalSettings class='jenkins.mvn.DefaultGlobalSettingsProvider'/> | ||
71 | + <reporters> | ||
72 | + <hudson.maven.reporters.MavenMailer> | ||
73 | + <recipients/> | ||
74 | + <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild> | ||
75 | + <sendToIndividuals>true</sendToIndividuals> | ||
76 | + <perModuleEmail>true</perModuleEmail> | ||
77 | + </hudson.maven.reporters.MavenMailer> | ||
78 | + </reporters> | ||
79 | + <publishers> | ||
80 | + <hudson.plugins.sonar.SonarPublisher plugin='sonar@2.1'> | ||
81 | + <jdk>(Inherit From Job)</jdk> | ||
82 | + <branch/> | ||
83 | + <language/> | ||
84 | + <mavenOpts/> | ||
85 | + <jobAdditionalProperties/> | ||
86 | + <settings class='jenkins.mvn.DefaultSettingsProvider'/> | ||
87 | + <globalSettings class='jenkins.mvn.DefaultGlobalSettingsProvider'/> | ||
88 | + <usePrivateRepository>false</usePrivateRepository> | ||
89 | + </hudson.plugins.sonar.SonarPublisher> | ||
90 | + </publishers> | ||
91 | + <buildWrappers/> | ||
92 | + <prebuilders/> | ||
93 | + <postbuilders/> | ||
94 | + <runPostStepsIfResult> | ||
95 | + <name>FAILURE</name> | ||
96 | + <ordinal>2</ordinal> | ||
97 | + <color>RED</color> | ||
98 | + </runPostStepsIfResult> | ||
99 | + </maven2-moduleset> | ||
100 | + " | ||
101 | + end | ||
102 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/smile_block.rb
0 → 100644
@@ -0,0 +1,100 @@ | @@ -0,0 +1,100 @@ | ||
1 | +require 'open-uri' | ||
2 | +require 'json' | ||
3 | + | ||
4 | +class SerproIntegrationPlugin::SmileBlock < Block | ||
5 | + | ||
6 | + | ||
7 | + METRIC_SUCCESS_DENSITY = 'test_success_density' | ||
8 | + METRIC_LOC = 'ncloc' | ||
9 | + METRIC_UNCOVERED_LINE = 'uncovered_lines' | ||
10 | + METRIC_COVERAGE = 'coverage' | ||
11 | + | ||
12 | + #FIXME make this test | ||
13 | + settings_items :sonar_info, :type => Hash, :default => {} | ||
14 | + | ||
15 | + def self.description | ||
16 | + _('Sonar Smile') | ||
17 | + end | ||
18 | + | ||
19 | + def help | ||
20 | + _('This block adds a smile face that make tecnical debits visible with funny way.') | ||
21 | + end | ||
22 | + | ||
23 | + #FIXME make this test | ||
24 | + def sonar_host | ||
25 | + self.owner.sonar_plugin['host'] | ||
26 | + end | ||
27 | + | ||
28 | + #FIXME make this test | ||
29 | + def sonar_project | ||
30 | + self.owner.sonar_plugin['project'] #|| '' | ||
31 | + end | ||
32 | + | ||
33 | +#FIXME make this test | ||
34 | + def smile_factor | ||
35 | + collect_sonar_information | ||
36 | + factor = (self.sonar_info[METRIC_COVERAGE] * self.sonar_info[METRIC_SUCCESS_DENSITY]).to_f/1000 | ||
37 | + factor | ||
38 | + end | ||
39 | + | ||
40 | + #FIXME make this test | ||
41 | + def content(args={}) | ||
42 | + smile_face_id = 'smileFace-' + self.id.to_s | ||
43 | + | ||
44 | + content_tag(:div, | ||
45 | + content_tag(:canvas, '', :id => smile_face_id, :width => '95%', :height => '95%' ) + | ||
46 | + "<script type='text/javascript'>drawFace('#{smile_face_id}', '#{self.smile_factor}')</script>", | ||
47 | + :class => 'smile' | ||
48 | + ) | ||
49 | + end | ||
50 | + | ||
51 | + #FIXME make this test | ||
52 | + def self.metrics | ||
53 | + [ | ||
54 | + METRIC_SUCCESS_DENSITY, | ||
55 | + METRIC_LOC, | ||
56 | + METRIC_UNCOVERED_LINE, | ||
57 | + METRIC_COVERAGE | ||
58 | + ] | ||
59 | + end | ||
60 | + | ||
61 | + private | ||
62 | + | ||
63 | + #FIXME make this test | ||
64 | + def collect_sonar_information | ||
65 | + return false unless cache_expired? | ||
66 | + begin | ||
67 | + data = open("#{self.sonar_host}/api/resources?resource=#{self.sonar_project}&metrics=ncloc,coverage,weighted_violations,uncovered_lines,test_success_density&format=json").read | ||
68 | + self.sonar_info = parse_sonar_resource(JSON.parse(data).first) | ||
69 | + rescue | ||
70 | + self.sonar_info = {} | ||
71 | + end | ||
72 | + self.sonar_info[:updated_at] = Time.now | ||
73 | + self.save | ||
74 | + end | ||
75 | + | ||
76 | + #FIXME make this test | ||
77 | + def parse_sonar_resource(data) | ||
78 | + parsed_data = {} | ||
79 | + return {} if data['msr'].nil? | ||
80 | + data['msr'].map do |metric| | ||
81 | + self.class.metrics.map do |defined_metric| | ||
82 | + parsed_data[defined_metric] = metric['val'] if metric['key'] == defined_metric | ||
83 | + end | ||
84 | + end | ||
85 | + parsed_data | ||
86 | + end | ||
87 | + | ||
88 | + #FIXME make this test | ||
89 | + def cache_expired? | ||
90 | + return true if self.sonar_info[:updated_at].nil? | ||
91 | + (Time.now - self.sonar_info[:updated_at]) > cache_timestamp | ||
92 | + end | ||
93 | + | ||
94 | + #FIXME make this test | ||
95 | + # Cach time to load new data in seconds | ||
96 | + def cache_timestamp | ||
97 | + 60 * 60 | ||
98 | + end | ||
99 | + | ||
100 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/sonar_widget_block.rb
0 → 100644
@@ -0,0 +1,81 @@ | @@ -0,0 +1,81 @@ | ||
1 | +class SerproIntegrationPlugin::SonarWidgetBlock < Block | ||
2 | + | ||
3 | + #FIXME make this test | ||
4 | + AVAILABLE_WIDGETS = { | ||
5 | + 'project_motion_chart' => 'Project Motion Chart', | ||
6 | + 'timeline' => 'Timeline', | ||
7 | + 'complexity' => 'Complexity' | ||
8 | + } | ||
9 | + | ||
10 | + #FIXME make this test. Make test for default widget | ||
11 | + settings_items :widget, :type => String, :default => 'timeline' | ||
12 | + | ||
13 | + def self.description | ||
14 | + _('Sonar Widgets') | ||
15 | + end | ||
16 | + | ||
17 | + def help | ||
18 | + _('This block adds sonar widgets on profile.') | ||
19 | + end | ||
20 | + | ||
21 | + #FIXME make this test | ||
22 | + def sonar_host | ||
23 | + self.owner.serpro_integration_plugin['host'] | ||
24 | + end | ||
25 | + | ||
26 | + #FIXME make this test | ||
27 | + def sonar_project | ||
28 | + self.owner.serpro_integration_plugin['project'] | ||
29 | + end | ||
30 | + | ||
31 | + #FIXME make this test | ||
32 | + def widget_url | ||
33 | + self.sonar_host + 'widget?id=' + self.widget + '&resource=' + self.sonar_project + '&metric1=complexity&metric2=ncloc' | ||
34 | + end | ||
35 | + | ||
36 | + #FIXME make this test | ||
37 | + def is_widget_well_formed_url? | ||
38 | + !self.widget_url.match(/http[s]?:\/\/[\w|.|\/]+\/widget\?id=[\w]+&resource=[\w|\W]+/).nil? | ||
39 | + end | ||
40 | + | ||
41 | + #FIXME make this test | ||
42 | + def widget_width | ||
43 | + case widget | ||
44 | + when 'project_motion_chart' | ||
45 | + '360px' | ||
46 | + when 'timeline' | ||
47 | + '100%' | ||
48 | + when 'complexity' | ||
49 | + '100%' | ||
50 | + else | ||
51 | + '300px' | ||
52 | + end | ||
53 | + end | ||
54 | + | ||
55 | + #FIXME make this test | ||
56 | + def widget_height | ||
57 | + case widget | ||
58 | + when 'project_motion_chart' | ||
59 | + '450px' | ||
60 | + when 'timeline' | ||
61 | + '205px' | ||
62 | + when 'complexity' | ||
63 | + '170px' | ||
64 | + else | ||
65 | + '300px' | ||
66 | + end | ||
67 | + end | ||
68 | + | ||
69 | + def content(args={}) | ||
70 | +# render this url | ||
71 | +#http://sonar.serpro/widget?id=timeline&resource=br.gov.fazenda.coaf.siscoaf:siscoaf-parent&metric1=complexity&metric2=ncloc | ||
72 | + | ||
73 | + block = self | ||
74 | + | ||
75 | + lambda do | ||
76 | + render :file => 'sonar_widget_block', :locals => { :block => block } | ||
77 | + end | ||
78 | + | ||
79 | + end | ||
80 | + | ||
81 | +end |
@@ -0,0 +1,129 @@ | @@ -0,0 +1,129 @@ | ||
1 | +function drawBaseFace(element_id) { | ||
2 | + var canvas = document.getElementById(element_id); | ||
3 | + var ctx = canvas.getContext("2d"); | ||
4 | + | ||
5 | + var x = canvas.width / 2; | ||
6 | + var y = canvas.height / 2; | ||
7 | + var radius = canvas.width/2 - 1; | ||
8 | + var startAngle = 0; | ||
9 | + var endAngle = 2 * Math.PI; | ||
10 | + | ||
11 | + ctx.beginPath(); | ||
12 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
13 | + ctx.stroke(); | ||
14 | + ctx.fillStyle = "yellow"; | ||
15 | + ctx.fill(); | ||
16 | +} | ||
17 | + | ||
18 | +function drawSmile(element_id, factor){ | ||
19 | + var canvas = document.getElementById(element_id); | ||
20 | + var ctx = canvas.getContext("2d"); | ||
21 | + var x = canvas.width / 2; | ||
22 | + var y = canvas.height / 2 | ||
23 | + var radius = canvas.width/2 - canvas.width/4; | ||
24 | + | ||
25 | + var startAngle = 0; | ||
26 | + var endAngle = 0; | ||
27 | + var delta = 0; | ||
28 | + | ||
29 | + ctx.beginPath(); | ||
30 | + ctx.lineWidth = canvas.width/100 * 2; | ||
31 | + | ||
32 | + if (factor >= 0 && factor < 5){ | ||
33 | + //Draw sadness mouth | ||
34 | + delta = 0.5 - factor* 0.1 | ||
35 | + startAngle = (1.5 - delta) * Math.PI; | ||
36 | + endAngle = (1.5 + delta) * Math.PI; | ||
37 | + radius = radius - radius*delta; | ||
38 | + y = y + (radius + radius*(1 - delta)); | ||
39 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
40 | + } else if (factor == 5) { | ||
41 | + //Draw normal mouth | ||
42 | + ctx.moveTo(x-canvas.width/8,y+canvas.width/8); | ||
43 | + ctx.lineTo(x-canvas.width/8+(canvas.width/4),y+canvas.width/8); | ||
44 | + } else if (factor > 5 && factor <= 10) { | ||
45 | + //Draw happiness mouth | ||
46 | + delta = 1 - factor * 0.1 | ||
47 | + startAngle = delta * Math.PI; | ||
48 | + endAngle = (1 - delta) * Math.PI; | ||
49 | + radius = radius - radius*delta; | ||
50 | + y = y - (radius - radius*(1-delta)); | ||
51 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
52 | + }else{ | ||
53 | + //Draw scare mouth | ||
54 | + radius = radius*0.4 | ||
55 | + y = y + radius; | ||
56 | + ctx.ellipse(x,y,radius*0.4, radius,0,0,2 * Math.PI, false); | ||
57 | + ctx.fill(); | ||
58 | + } | ||
59 | + | ||
60 | + | ||
61 | + // line color | ||
62 | + ctx.strokeStyle = 'black'; | ||
63 | + ctx.stroke(); | ||
64 | +} | ||
65 | + | ||
66 | +function drawEyes(element_id){ | ||
67 | + var canvas = document.getElementById(element_id); | ||
68 | + var ctx = canvas.getContext("2d"); | ||
69 | + var centerX = canvas.width/5; | ||
70 | + var centerY = 0; | ||
71 | + var radius = canvas.width * 0.05; | ||
72 | + | ||
73 | + // save state | ||
74 | + ctx.save(); | ||
75 | + | ||
76 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
77 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
78 | + | ||
79 | + // scale context horizontally by 50% | ||
80 | + ctx.scale(.5, 1); | ||
81 | + | ||
82 | + // draw circle which will be stretched into an oval | ||
83 | + ctx.beginPath(); | ||
84 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
85 | + | ||
86 | + // restore to original state | ||
87 | + ctx.restore(); | ||
88 | + | ||
89 | + // apply styling | ||
90 | + ctx.fillStyle = 'black'; | ||
91 | + ctx.fill(); | ||
92 | + ctx.lineWidth = 2; | ||
93 | + ctx.strokeStyle = 'black'; | ||
94 | + ctx.stroke(); | ||
95 | + | ||
96 | + | ||
97 | + //left eye | ||
98 | + centerX = centerX * -1; | ||
99 | + | ||
100 | + // save state | ||
101 | + ctx.save(); | ||
102 | + | ||
103 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
104 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
105 | + | ||
106 | + // scale context horizontally by 50% | ||
107 | + ctx.scale(.5, 1); | ||
108 | + | ||
109 | + // draw circle which will be stretched into an oval | ||
110 | + ctx.beginPath(); | ||
111 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
112 | + | ||
113 | + // restore to original state | ||
114 | + ctx.restore(); | ||
115 | + | ||
116 | + // apply styling | ||
117 | + ctx.fillStyle = 'black'; | ||
118 | + ctx.fill(); | ||
119 | + ctx.lineWidth = 2; | ||
120 | + ctx.strokeStyle = 'black'; | ||
121 | + ctx.stroke(); | ||
122 | +} | ||
123 | + | ||
124 | + | ||
125 | +function drawFace(element_id, factor){ | ||
126 | + drawBaseFace(element_id); | ||
127 | + drawEyes(element_id); | ||
128 | + drawSmile(element_id, factor); | ||
129 | +} |
@@ -0,0 +1,142 @@ | @@ -0,0 +1,142 @@ | ||
1 | +<html> | ||
2 | + <head> </head> | ||
3 | + <body> | ||
4 | + <canvas id="smileFace" width="60" height="60"></canvas> | ||
5 | +<script> | ||
6 | + | ||
7 | +function drawBaseFace() { | ||
8 | + var canvas = document.getElementById("smileFace"); | ||
9 | + var ctx = canvas.getContext("2d"); | ||
10 | + | ||
11 | + var x = canvas.width / 2; | ||
12 | + var y = canvas.height / 2; | ||
13 | + var radius = canvas.width/2 - 1; | ||
14 | + var startAngle = 0; | ||
15 | + var endAngle = 2 * Math.PI; | ||
16 | + | ||
17 | + ctx.beginPath(); | ||
18 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
19 | + ctx.stroke(); | ||
20 | + ctx.fillStyle = "yellow"; | ||
21 | + ctx.fill(); | ||
22 | +} | ||
23 | + | ||
24 | +function drawSmile(factor){ | ||
25 | + var canvas = document.getElementById("smileFace"); | ||
26 | + var ctx = canvas.getContext("2d"); | ||
27 | + var x = canvas.width / 2; | ||
28 | + var y = canvas.height / 2 | ||
29 | + var radius = canvas.width/2 - canvas.width/4; | ||
30 | + | ||
31 | + var startAngle = 0; | ||
32 | + var endAngle = 0; | ||
33 | + var delta = 0; | ||
34 | + | ||
35 | + ctx.beginPath(); | ||
36 | + ctx.lineWidth = canvas.width/100 * 2; | ||
37 | + | ||
38 | + if (factor >= 0 && factor < 5){ | ||
39 | + //Draw sadness mouth | ||
40 | + delta = 0.5 - factor* 0.1 | ||
41 | + startAngle = (1.5 - delta) * Math.PI; | ||
42 | + endAngle = (1.5 + delta) * Math.PI; | ||
43 | + radius = radius - radius*delta; | ||
44 | + y = y + (radius + radius*(1 - delta)); | ||
45 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
46 | + } else if (factor == 5) { | ||
47 | + //Draw normal mouth | ||
48 | + ctx.moveTo(x-canvas.width/8,y+canvas.width/8); | ||
49 | + ctx.lineTo(x-canvas.width/8+(canvas.width/4),y+canvas.width/8); | ||
50 | + } else if (factor > 5 && factor <= 10) { | ||
51 | + //Draw happiness mouth | ||
52 | + delta = 1 - factor * 0.1 | ||
53 | + startAngle = delta * Math.PI; | ||
54 | + endAngle = (1 - delta) * Math.PI; | ||
55 | + radius = radius - radius*delta; | ||
56 | + y = y - (radius - radius*(1-delta)); | ||
57 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
58 | + }else{ | ||
59 | + //Draw scare mouth | ||
60 | + radius = radius*0.4 | ||
61 | + y = y + radius; | ||
62 | + ctx.ellipse(x,y,radius*0.4, radius,0,0,2 * Math.PI, false); | ||
63 | + ctx.fill(); | ||
64 | + } | ||
65 | + | ||
66 | + | ||
67 | + // line color | ||
68 | + ctx.strokeStyle = 'black'; | ||
69 | + ctx.stroke(); | ||
70 | +} | ||
71 | + | ||
72 | +function drawEyes(){ | ||
73 | + var canvas = document.getElementById("smileFace"); | ||
74 | + var ctx = canvas.getContext("2d"); | ||
75 | + var centerX = canvas.width/5; | ||
76 | + var centerY = 0; | ||
77 | + var radius = canvas.width * 0.05; | ||
78 | + | ||
79 | + // save state | ||
80 | + ctx.save(); | ||
81 | + | ||
82 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
83 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
84 | + | ||
85 | + // scale context horizontally by 50% | ||
86 | + ctx.scale(.5, 1); | ||
87 | + | ||
88 | + // draw circle which will be stretched into an oval | ||
89 | + ctx.beginPath(); | ||
90 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
91 | + | ||
92 | + // restore to original state | ||
93 | + ctx.restore(); | ||
94 | + | ||
95 | + // apply styling | ||
96 | + ctx.fillStyle = 'black'; | ||
97 | + ctx.fill(); | ||
98 | + ctx.lineWidth = 2; | ||
99 | + ctx.strokeStyle = 'black'; | ||
100 | + ctx.stroke(); | ||
101 | + | ||
102 | + | ||
103 | + //left eye | ||
104 | + centerX = centerX * -1; | ||
105 | + | ||
106 | + // save state | ||
107 | + ctx.save(); | ||
108 | + | ||
109 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
110 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
111 | + | ||
112 | + // scale context horizontally by 50% | ||
113 | + ctx.scale(.5, 1); | ||
114 | + | ||
115 | + // draw circle which will be stretched into an oval | ||
116 | + ctx.beginPath(); | ||
117 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
118 | + | ||
119 | + // restore to original state | ||
120 | + ctx.restore(); | ||
121 | + | ||
122 | + // apply styling | ||
123 | + ctx.fillStyle = 'black'; | ||
124 | + ctx.fill(); | ||
125 | + ctx.lineWidth = 2; | ||
126 | + ctx.strokeStyle = 'black'; | ||
127 | + ctx.stroke(); | ||
128 | +} | ||
129 | + | ||
130 | + | ||
131 | +function drawFace(factor){ | ||
132 | + drawBaseFace(); | ||
133 | + drawEyes(); | ||
134 | + drawSmile(factor); | ||
135 | +} | ||
136 | + | ||
137 | +drawFace(9); | ||
138 | + | ||
139 | +</script> | ||
140 | + | ||
141 | + </body> | ||
142 | +</html> |
plugins/serpro_integration/test/unit/sonar_plugin_test.rb
0 → 100644
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class RequireAuthToCommentPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @plugin = RequireAuthToCommentPlugin.new | ||
7 | + @comment = Comment.new | ||
8 | + end | ||
9 | + | ||
10 | + attr_reader :plugin, :comment | ||
11 | + | ||
12 | + should 'reject comments for unauthenticated users' do | ||
13 | + plugin.context = logged_in(false) | ||
14 | + plugin.filter_comment(comment) | ||
15 | + assert comment.rejected? | ||
16 | + end | ||
17 | + | ||
18 | + should 'allow comments from authenticated users' do | ||
19 | + plugin.context = logged_in(true) | ||
20 | + plugin.filter_comment(comment) | ||
21 | + assert !comment.rejected? | ||
22 | + end | ||
23 | + | ||
24 | + should 'allow comments from unauthenticated users if allowed by profile' do | ||
25 | + plugin.context = logged_in(false) | ||
26 | + plugin.context.profile.allow_unauthenticated_comments = true | ||
27 | + | ||
28 | + plugin.filter_comment(comment) | ||
29 | + assert !comment.rejected? | ||
30 | + end | ||
31 | + | ||
32 | + protected | ||
33 | + | ||
34 | + def logged_in(boolean) | ||
35 | + controller = mock() | ||
36 | + controller.stubs(:logged_in?).returns(boolean) | ||
37 | + controller.stubs(:profile).returns(Profile.new) | ||
38 | + controller | ||
39 | + end | ||
40 | + | ||
41 | +end |
plugins/serpro_integration/views/blocks/_gitlab_issue.html.erb
0 → 100644
plugins/serpro_integration/views/blocks/gitlab_issues.html.erb
0 → 100644
plugins/serpro_integration/views/profile-editor-extras.html.erb
0 → 100644
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +<script> | ||
2 | +jQuery( document ).ready(function( $ ) { | ||
3 | + function toggle_checkbox_selectors(el) { | ||
4 | + if( el.is(':checked')) { | ||
5 | + $(el.data('selector')).show('fast'); | ||
6 | + } else { | ||
7 | + $(el.data('selector')).hide('fast'); | ||
8 | + } | ||
9 | + } | ||
10 | + $(".toggle_checkbox").click(function() { | ||
11 | + toggle_checkbox_selectors($(this)); | ||
12 | + }); | ||
13 | + $(".toggle_checkbox").each(function() { | ||
14 | + toggle_checkbox_selectors($(this)); | ||
15 | + }); | ||
16 | +}); | ||
17 | +</script> | ||
18 | + | ||
19 | +<div id='serpro-integration'> | ||
20 | + <h2><%= _('Serpro Integration') %></h2> | ||
21 | + | ||
22 | + <%= render :partial => 'gitlab' %> | ||
23 | + <%= render :partial => 'jenkins' %> | ||
24 | + | ||
25 | + <div id="sonar"> | ||
26 | + <h3> | ||
27 | + <%= labelled_check_box('', 'profile_data[allow_sonar_integration]', true, profile.allow_sonar_integration, {:class => "toggle_checkbox", 'data-selector' => 'ul.sonar'}) %> | ||
28 | + <%= _('Sonar Integration') %> | ||
29 | + </h3> | ||
30 | + <ul class='sonar'> | ||
31 | + <li> | ||
32 | + <%= labelled_text_field(_('Server Host'), 'profile_data[serpro_integration_plugin_sonar][host]', profile.serpro_integration_plugin_sonar[:host]) %> | ||
33 | + </li> | ||
34 | + <li> | ||
35 | + <%= labelled_text_field(_('Project: '), 'profile_data[serpro_integration_plugin_sonar][project]', profile.serpro_integration_plugin_sonar[:project]) %> | ||
36 | + </li> | ||
37 | + </ul> | ||
38 | + </div> | ||
39 | + | ||
40 | +</div> |
plugins/serpro_integration/views/profile_design/sonar_plugin/_sonar_widget_block.rhtml
0 → 100644
plugins/serpro_integration/views/profile_editor/_gitlab.html.erb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +<div id="gitlab"> | ||
2 | + | ||
3 | +<h3> | ||
4 | + <%= labelled_check_box('', 'profile_data[allow_gitlab_integration]', true, profile.allow_gitlab_integration, {:class => "toggle_checkbox", 'data-selector' => "ul.gitlab"}) %> | ||
5 | + <%= _('Gitlab Integration') %> | ||
6 | +</h3> | ||
7 | +<ul class="gitlab"> | ||
8 | + <li> | ||
9 | + <span class="label"><%= _('Server Host:') %><span> | ||
10 | + <span class="value"><%= profile.gitlab_host %><span> | ||
11 | + <%= link_to _('Force'), {:controller => 'serpro_integration_plugin_myprofile', :action => 'create_gitlab'}, {:remote => true} %> | ||
12 | + </li> | ||
13 | + <li> | ||
14 | + <%= labelled_text_field(_('Group Name:'), 'profile_data[serpro_integration_plugin_gitlab][group]', profile.gitlab_group) %> | ||
15 | + </li> | ||
16 | + <li> | ||
17 | + <%= labelled_text_field(_('Project Name:'), 'profile_data[serpro_integration_plugin_gitlab][project_name]', profile.gitlab_project_name ) %> | ||
18 | + </li> | ||
19 | +</ul> | ||
20 | +</div> |
plugins/serpro_integration/views/profile_editor/_jenkins.html.erb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<div id="jenkins"> | ||
2 | +<h3> | ||
3 | + <%= labelled_check_box('', 'profile_data[allow_jenkins_integration]', true, profile.allow_jenkins_integration, {:class => "toggle_checkbox", 'data-selector' => 'ul.jenkins'}) %> | ||
4 | + <%= _('Jenkins Integration') %> | ||
5 | +</h3> | ||
6 | +<ul class='jenkins'> | ||
7 | + <li> | ||
8 | + <%= labelled_text_field(_('Project Name:'), 'profile_data[serpro_integration_plugin_jenkins][project_name]', profile.jenkins_project_name ) %> | ||
9 | + </li> | ||
10 | +</ul> | ||
11 | +</div> |
plugins/serpro_integration/views/serpro_integration_plugin_admin/index.html.erb
0 → 100644
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +<h1><%= _('Serpro Integration Settings')%></h1> | ||
2 | + | ||
3 | +<%= form_for(:settings) do |f| %> | ||
4 | + | ||
5 | + <div class="gitlab_settings"> | ||
6 | + <h2><%= _('Gitlab Settings')%></h2> | ||
7 | + <%= f.fields_for :gitlab, OpenStruct.new(@settings.gitlab) do |g| %> | ||
8 | + <%= labelled_form_field _('Server Host'), g.text_field("host") %> | ||
9 | + <%= labelled_form_field _('Private Token'), g.text_field(:private_token) %> | ||
10 | + <% end %> | ||
11 | + </div> | ||
12 | + | ||
13 | + <div class="jenkins_settings"> | ||
14 | + <h2><%= _('Jenkins Settings')%></h2> | ||
15 | + <%= f.fields_for :jenkins, OpenStruct.new(@settings.jenkins) do |g| %> | ||
16 | + <%= labelled_form_field _('Server Host'), g.text_field("host") %> | ||
17 | + <%= labelled_form_field _('Server User'), g.text_field(:user) %> | ||
18 | + <%= labelled_form_field _('Private Token'), g.text_field(:private_token) %> | ||
19 | + <% end %> | ||
20 | + </div> | ||
21 | + | ||
22 | + <% button_bar do %> | ||
23 | + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %> | ||
24 | + <% end %> | ||
25 | + | ||
26 | +<% end %> | ||
27 | + |
plugins/serpro_integration/views/sonar_widget_block.rhtml
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<div class='widget'> | ||
2 | + <% if block.is_widget_well_formed_url? %> | ||
3 | + <iframe width='<%=block.widget_width%>' height='<%=block.widget_height%>' src='<%=block.widget_url%>' frameborder="0" allowfullscreen></iframe> | ||
4 | + <% else %> | ||
5 | + <div class='wrong'> | ||
6 | + <iframe width='<%=block.widget_width%>' height='<%=block.widget_height%>' src='<%=block.widget_url%>' frameborder="0" allowfullscreen></iframe> | ||
7 | + <%= _('Something wrong happened. Please see your sonar configuration.') %> | ||
8 | + </div> | ||
9 | + <% end %> | ||
10 | +</div> |
test/fixtures/files/500.html
@@ -0,0 +1,151 @@ | @@ -0,0 +1,151 @@ | ||
1 | +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
2 | +<html xmlns="http://www.w3.org/1999/xhtml" > | ||
3 | + <head> | ||
4 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | ||
5 | + <meta http-equiv="refresh" content="60"/> | ||
6 | + <title>Technical problems</title> | ||
7 | + <link rel="stylesheet" type="text/css" href="/designs/themes/default/errors.css"/> | ||
8 | + <link rel="shortcut icon" href='/designs/themes/default/favicon.ico' type="image/x-icon" /> | ||
9 | + <script type='text/javascript' src='/javascripts/prototype.js'></script> | ||
10 | + <script type='text/javascript' src='/javascripts/errors.js'></script> | ||
11 | +</head> | ||
12 | +<body onload='display_error_message()'> | ||
13 | + <div id='wrap'> | ||
14 | + <div id='header'> | ||
15 | + <div id='logo'> | ||
16 | + | ||
17 | + </div> | ||
18 | + </div> | ||
19 | + | ||
20 | + | ||
21 | + <div id='de' style='display: none' class='message'> | ||
22 | + <h1>Kurzzeitiges Systemproblem</h1> | ||
23 | + <p> | ||
24 | + Unser technisches Team arbeitet gerade daran, bitte probieren Sie es nachher erneut. Wir entschuldigen uns für die Unannehmlichkeiten. | ||
25 | + </p> | ||
26 | + <ul> | ||
27 | + <li><a href='javascript: history.back()'>Zurück</a></li> | ||
28 | + <li><a href='/'>Gehe zur Homepage</a></li> | ||
29 | + </ul> | ||
30 | + </div> | ||
31 | + | ||
32 | + | ||
33 | + <div id='en' style='display: none' class='message'> | ||
34 | + <h1>Temporary system problem</h1> | ||
35 | + <p> | ||
36 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
37 | + </p> | ||
38 | + <ul> | ||
39 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
40 | + <li><a href='/'>Go to the site home page</a></li> | ||
41 | + </ul> | ||
42 | + </div> | ||
43 | + | ||
44 | + | ||
45 | + <div id='eo' style='display: none' class='message'> | ||
46 | + <h1>Temporary system problem</h1> | ||
47 | + <p> | ||
48 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
49 | + </p> | ||
50 | + <ul> | ||
51 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
52 | + <li><a href='/'>Go to the site home page</a></li> | ||
53 | + </ul> | ||
54 | + </div> | ||
55 | + | ||
56 | + | ||
57 | + <div id='es' style='display: none' class='message'> | ||
58 | + <h1>Problema temporal del sistema</h1> | ||
59 | + <p> | ||
60 | + Nuestro equipo técnico está trabajando en ello, por favor, inténtalo de nuevo más tarde. Disculpa las molestias. | ||
61 | + </p> | ||
62 | + <ul> | ||
63 | + <li><a href='javascript: history.back()'>Regresar</a></li> | ||
64 | + <li><a href='/'>Ir a la página de inicio del sitio</a></li> | ||
65 | + </ul> | ||
66 | + </div> | ||
67 | + | ||
68 | + | ||
69 | + <div id='fr' style='display: none' class='message'> | ||
70 | + <h1>Problème temporaire du système.</h1> | ||
71 | + <p> | ||
72 | + Notre équipe technique est en train d'y travailler. Merci de réessayer plus tard. Nous sommes désolés de la gêne occasionnée. | ||
73 | + </p> | ||
74 | + <ul> | ||
75 | + <li><a href='javascript: history.back()'>Retour</a></li> | ||
76 | + <li><a href='/'>Aller à la page d'accueil du site</a></li> | ||
77 | + </ul> | ||
78 | + </div> | ||
79 | + | ||
80 | + | ||
81 | + <div id='hy' style='display: none' class='message'> | ||
82 | + <h1>Temporary system problem</h1> | ||
83 | + <p> | ||
84 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
85 | + </p> | ||
86 | + <ul> | ||
87 | + <li><a href='javascript: history.back()'>Վերադառնալ</a></li> | ||
88 | + <li><a href='/'>Go to the site home page</a></li> | ||
89 | + </ul> | ||
90 | + </div> | ||
91 | + | ||
92 | + | ||
93 | + <div id='it' style='display: none' class='message'> | ||
94 | + <h1>Temporary system problem</h1> | ||
95 | + <p> | ||
96 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
97 | + </p> | ||
98 | + <ul> | ||
99 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
100 | + <li><a href='/'>Go to the site home page</a></li> | ||
101 | + </ul> | ||
102 | + </div> | ||
103 | + | ||
104 | + | ||
105 | + <div id='pt' style='display: none' class='message'> | ||
106 | + <h1>Problema temporário no sistema</h1> | ||
107 | + <p> | ||
108 | + Nossa equipe técnica está trabalhando nele, por favor tente mais tarde. Perdoe o incoveniente. | ||
109 | + </p> | ||
110 | + <ul> | ||
111 | + <li><a href='javascript: history.back()'>Voltar</a></li> | ||
112 | + <li><a href='/'>Ir para a página inicial do site.</a></li> | ||
113 | + </ul> | ||
114 | + </div> | ||
115 | + | ||
116 | + | ||
117 | + <div id='ru' style='display: none' class='message'> | ||
118 | + <h1>Временная ошибка системы</h1> | ||
119 | + <p> | ||
120 | + Техники уже работают над проблемой, пожалуйста, попробуйте позже. | ||
121 | + </p> | ||
122 | + <ul> | ||
123 | + <li><a href='javascript: history.back()'>Назад</a></li> | ||
124 | + <li><a href='/'>Перейти на домашнюю страницу сайта</a></li> | ||
125 | + </ul> | ||
126 | + </div> | ||
127 | + | ||
128 | + <div id='languages'> | ||
129 | + | ||
130 | + <a href="javascript: display_error_message('de')">Deutsch</a> | ||
131 | + | ||
132 | + <a href="javascript: display_error_message('en')">English</a> | ||
133 | + | ||
134 | + <a href="javascript: display_error_message('eo')">Esperanto</a> | ||
135 | + | ||
136 | + <a href="javascript: display_error_message('es')">Español</a> | ||
137 | + | ||
138 | + <a href="javascript: display_error_message('fr')">Français</a> | ||
139 | + | ||
140 | + <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> | ||
141 | + | ||
142 | + <a href="javascript: display_error_message('it')">Italiano</a> | ||
143 | + | ||
144 | + <a href="javascript: display_error_message('pt')">Português</a> | ||
145 | + | ||
146 | + <a href="javascript: display_error_message('ru')">русский язык</a> | ||
147 | + | ||
148 | + </div> | ||
149 | + </div> | ||
150 | +</body> | ||
151 | +</html> |