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 | 44 | class_eval <<-CODE |
45 | 45 | def #{setting} |
46 | 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 | 52 | end |
49 | 53 | def #{setting}=(value) |
50 | 54 | h = send(self.class.settings_field).clone | ... | ... |
plugins/serpro_integration/controllers/serpro_integration_plugin_admin_controller.rb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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> | ... | ... |