Merge branch 'rep_quality' into develop
Conflicts: db/schema.rb public/stylesheets/project.css public/stylesheets/public.css
This commit is contained in:
commit
46cde061a6
6
Gemfile
6
Gemfile
|
@ -6,7 +6,11 @@ unless RUBY_PLATFORM =~ /w32/
|
|||
gem 'iconv'
|
||||
end
|
||||
|
||||
gem 'certified'
|
||||
gem 'net-ssh'
|
||||
gem 'jenkins_api_client'
|
||||
gem 'nokogiri'
|
||||
|
||||
# gem 'certified'
|
||||
|
||||
gem 'wechat',path: 'lib/wechat'
|
||||
gem 'grack', path:'lib/grack'
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Place all the behaviors and hooks related to the matching controller here.
|
||||
# All this logic will automatically be available in application.js.
|
||||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
|
@ -0,0 +1,3 @@
|
|||
// Place all the styles related to the QualityAnalyses controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
|
@ -393,7 +393,7 @@ class ProjectsController < ApplicationController
|
|||
unless @project.gpid.nil?
|
||||
g = Gitlab.client
|
||||
@gitlab_branches = g.branches(@project.gpid)
|
||||
@branch_names = g.branches(@project.gpid).map{|b| b.name}
|
||||
@branch_names = @gitlab_branches.map{|b| b.name}
|
||||
@gitlab_default_branch = g.project(@project.gpid).default_branch
|
||||
end
|
||||
end
|
||||
|
@ -645,7 +645,7 @@ class ProjectsController < ApplicationController
|
|||
params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
|
||||
params[:project][:hidden_repo] ? @project.hidden_repo = 1 : @project.hidden_repo = 0
|
||||
# 更新公开私有时同步gitlab公开私有
|
||||
unless @project.gpid.nil?
|
||||
if !@project.gpid.nil? && @project.is_public != (params[:project][:is_public] == "on" ? true : false)
|
||||
g = Gitlab.client
|
||||
params[:project][:is_public] ? g.edit_project(@project.gpid, 20, params[:branch]) : g.edit_project(@project.gpid, 0, params[:branch])
|
||||
end
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
class QualityAnalysisController < ApplicationController
|
||||
before_filter :find_project_by_project_id#, :except => [:getattachtype]
|
||||
before_filter :authorize
|
||||
layout "base_projects"
|
||||
include ApplicationHelper
|
||||
require 'jenkins_api_client'
|
||||
require 'nokogiri'
|
||||
require 'json'
|
||||
require 'open-uri'
|
||||
|
||||
def show
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
gitlab_address = Redmine::Configuration['gitlab_address']
|
||||
jenkins_address = Redmine::Configuration['jenkins_address']
|
||||
@client = JenkinsApi::Client.new(:server_url => jenkins_address,
|
||||
:username => "temp",
|
||||
:password => '123123')
|
||||
#@client.exists?(job_name)
|
||||
@g = Gitlab.client
|
||||
user_name = User.find(params[:user_id]).try(:login)
|
||||
branch = params[:branch].nil? ? "master" : params[:branch]
|
||||
language = params[:language]
|
||||
path = params[:path]
|
||||
identifier = params[:identifier]
|
||||
qa = QualityAnalysis.where(:project_id => @project.id, :author_login => user_name).first
|
||||
version = qa.nil? ? 1 : qa.sonar_version + 1
|
||||
properties = "sonar.projectKey=#{user_name}:#{identifier}
|
||||
sonar.projectName=#{user_name}:#{identifier}
|
||||
sonar.projectVersion=#{version}
|
||||
sonar.sources=#{path}
|
||||
sonar.language=#{language.downcase}
|
||||
sonar.sourceEncoding=utf-8"
|
||||
git_url = gitlab_address.to_s+"/"+@project.owner.to_s+"/"+ identifier + "."+"git"
|
||||
|
||||
# # # modify config
|
||||
@doc = Nokogiri::XML(File.open(File.join(Rails.root, 'tmp', 'config.xml')))
|
||||
@doc.at_xpath("//hudson.plugins.git.UserRemoteConfig/url").content = git_url
|
||||
@doc.at_xpath("//hudson.plugins.git.BranchSpec/name").content = "*/#{branch}"
|
||||
@doc.at_xpath("//hudson.plugins.sonar.SonarRunnerBuilder/properties").content = properties #sonar-properties
|
||||
#
|
||||
# replace config.xml of jenkins
|
||||
@client = @client.job.create("#{user_name}_#{identifier}", @doc.to_xml)
|
||||
# relace gitlab hook
|
||||
# genkins address
|
||||
@g.add_project_hook(@project.gpid, jenkins_address + "/project/#{user_name}_#{identifier}")
|
||||
if qa.nil?
|
||||
QualityAnalysis.create(:project_id => @project.id, :author_login => user_name, :rep_identifier => identifier, :sonar_version => version, :path => path, :branch => branch, :language => language)
|
||||
|
||||
else
|
||||
qa.update_attribute(:sonar_version, version)
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
@sonar_address = Redmine::Configuration['sonar_address']
|
||||
# if params[:resource_id].nil?
|
||||
# @name_flag = true
|
||||
# @quality_analyses = QualityAnalysis.where(:project_id => @project.id)
|
||||
# # @quality_analyses.map {|qa| qa.}
|
||||
# # if @quality_analyses.count > 0
|
||||
# # @quality_analyses.each do |qa|
|
||||
# # ["Hjqreturn:cc_rep", "Hjqreturn:putong", "Hjqreturn:sonar_rep2", "shitou:sonar_rep"]
|
||||
# #
|
||||
# # end
|
||||
# # end
|
||||
# # projects_date = open(@sonar_address + "/api/projects/index").read
|
||||
# # arr = JSON.parse(projects_date).map {|m| m["nm"]}
|
||||
# # arr.map
|
||||
# else
|
||||
qa = QualityAnalysis.where(:project_id => @project.id).first
|
||||
@resource_id = qa.author_login+":"+qa.rep_identifier
|
||||
@name_flag = false
|
||||
complexity_date = open(@sonar_address + "/api/resources/index?resource=#{@resource_id}&depth=0&metrics=sqale_rating,function_complexity,duplicated_lines_density,comment_lines_density,sqale_index,lines,file_line,files,functions,classes,directories").read
|
||||
@complexity =JSON.parse(complexity_date).first
|
||||
issue_date = open(@sonar_address + "/api/resources/index?resource=#{@resource_id}&depth=0&metrics=blocker_violations,critical_violations,major_violations,minor_violations,info_violations,violations").read
|
||||
@sonar_issues = JSON.parse(issue_date).first
|
||||
# end
|
||||
end
|
||||
|
||||
# Find project of id params[:project_id]
|
||||
def find_project_by_project_id
|
||||
@project = Project.find(params[:project_id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
# Authorize the user for the requested action
|
||||
def authorize(ctrl = params[:controller], action = params[:action], global = false)
|
||||
unless @project.archived? && @project.gpid.nil?
|
||||
true
|
||||
else
|
||||
render_403 :message => :notice_not_authorized_archived_project
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -30,11 +30,13 @@ class RepositoriesController < ApplicationController
|
|||
menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
|
||||
default_search_scope :changesets
|
||||
|
||||
before_filter :find_project_by_project_id, :only => [:new, :create, :newrepo, :stats]
|
||||
before_filter :find_project_by_project_id, :only => [:new, :create, :newrepo, :stats, :quality_analysis]
|
||||
before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
|
||||
before_filter :find_project_repository, :except => [:new, :create, :newcreate, :edit, :update, :destroy, :committers, :newrepo, :to_gitlab, :forked, :project_archive]
|
||||
before_filter :find_changeset, :only => [:revision, :add_related_issue, :remove_related_issue]
|
||||
before_filter :authorize , :except => [:newrepo,:newcreate,:fork, :to_gitlab, :forked, :commit_diff, :project_archive]
|
||||
before_filter :authorize , :except => [:newrepo,:newcreate,:fork, :to_gitlab, :forked, :commit_diff, :project_archive, :quality_analysis]
|
||||
# 链接gitlab
|
||||
before_filter :connect_gitlab, :only => [:quality_analysis]
|
||||
accept_rss_auth :revisions
|
||||
# hidden repositories filter // 隐藏代码过滤器
|
||||
before_filter :check_hidden_repo, :only => [:show, :stats, :revisions, :revision, :diff ]
|
||||
|
@ -43,6 +45,7 @@ class RepositoriesController < ApplicationController
|
|||
helper :project_score
|
||||
#@root_path = RepositoriesHelper::ROOT_PATH
|
||||
$g=Gitlab.client
|
||||
require 'net/ssh'
|
||||
|
||||
rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
|
||||
def new
|
||||
|
@ -306,6 +309,37 @@ update
|
|||
end
|
||||
end
|
||||
|
||||
def quality_analysis
|
||||
gitlab_branches = @g.branches(@project.gpid)
|
||||
@branch_names = gitlab_branches.map{|b| b.name}
|
||||
@gitlab_default_branch = @g.project(@project.gpid).default_branch
|
||||
# language = params[:language]
|
||||
# branch = params[:branch]
|
||||
# path = params[:path]
|
||||
# user_name = User.find(@project.user_id).try(:login)
|
||||
# rep_name = params[:repository_id]
|
||||
# host = "192.168.0.200"
|
||||
# port = "1125"
|
||||
# username = "git"
|
||||
# password = "123123"
|
||||
# server_cmd1 = "sh gitclone.sh" + " " + user_name + " " + rep_name
|
||||
# # 连接到远程主机 foobar
|
||||
# ssh = Net::SSH.start(host, username, :port => port, :password => password) do |ssh|
|
||||
# result = ssh.exec!(server_cmd1)
|
||||
# path = "/home/git/repo/" + user_name + "/" + rep_name
|
||||
# # sonar 分析
|
||||
# # server_cmd2
|
||||
# # 删除clone的版本库
|
||||
# # server_cmd3
|
||||
# end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html{
|
||||
render :layout => "base_projects"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
DestroyRepositoryTask.new.destroy(User.current.id, @repository.id)
|
||||
@repository.hidden = true
|
||||
|
@ -615,6 +649,14 @@ update
|
|||
project.project_score.update_attribute(:commit_time, date.created_at)
|
||||
end
|
||||
|
||||
# 链接gitlab
|
||||
def connect_gitlab
|
||||
@g = Gitlab.client
|
||||
unless @project.gpid.nil?
|
||||
@g_project = @g.project(@project.gpid)
|
||||
end
|
||||
end
|
||||
|
||||
def find_repository
|
||||
@repository = Repository.find(params[:id])
|
||||
@project = @repository.project
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
module QualityAnalysisHelper
|
||||
|
||||
def sqale_rating_status val
|
||||
arr = []
|
||||
if val.to_i > 0 && val.to_i < 5
|
||||
arr << "很好"
|
||||
arr << "b_green2"
|
||||
elsif val.to_i > 5 && val.to_i < 10
|
||||
arr << "较好"
|
||||
arr << "b_slow_yellow"
|
||||
elsif val.to_i > 10 && val.to_i < 20
|
||||
arr << "中等"
|
||||
arr << "b_yellow"
|
||||
elsif val.to_i > 20 && val.to_i < 50
|
||||
arr << "较差"
|
||||
arr << "b_slow_red"
|
||||
elsif val.to_i > 20
|
||||
arr << "很差"
|
||||
arr << "b_red"
|
||||
end
|
||||
end
|
||||
|
||||
def complexity_status val
|
||||
arr = []
|
||||
if val.to_i < 10
|
||||
arr << "良好"
|
||||
arr << "b_green2"
|
||||
elsif val.to_i > 10 && val.to_i < 15
|
||||
arr << "较高"
|
||||
arr << "b_yellow"
|
||||
elsif val.to_i > 15
|
||||
arr << "很高"
|
||||
arr << "b_red"
|
||||
end
|
||||
end
|
||||
|
||||
def duplicated_lines_density_status val
|
||||
arr = []
|
||||
if val.to_i < 30
|
||||
arr << "良好"
|
||||
arr << "b_green2"
|
||||
elsif val.to_i > 30 && val.to_i < 50
|
||||
arr << "较高"
|
||||
arr << "b_yellow"
|
||||
elsif val.to_i > 50
|
||||
arr << "很高"
|
||||
arr << "b_red"
|
||||
end
|
||||
end
|
||||
|
||||
def comment_lines_density_status val
|
||||
arr = []
|
||||
if val.to_i < 20
|
||||
arr << "较低"
|
||||
arr << "b_yellow"
|
||||
elsif val.to_i > 20 && val.to_i < 50
|
||||
arr << "正常"
|
||||
arr << "b_green2"
|
||||
elsif val.to_i > 50
|
||||
arr << "较高"
|
||||
arr << "b_red"
|
||||
end
|
||||
end
|
||||
|
||||
def score_sqale_rating val
|
||||
if val.to_i > 0 && val.to_i < 5
|
||||
"5"
|
||||
elsif val.to_i > 5 && val.to_i < 10
|
||||
"4"
|
||||
elsif val.to_i > 10 && val.to_i < 20
|
||||
"3"
|
||||
elsif val.to_i > 20 && val.to_i < 50
|
||||
"2"
|
||||
elsif val.to_i > 20
|
||||
"1"
|
||||
end
|
||||
end
|
||||
|
||||
def lines_scale val
|
||||
if val.to_i < 5000
|
||||
"小型"
|
||||
elsif val.to_i >5000 && val.to_i < 50000
|
||||
"中型"
|
||||
else
|
||||
"大型"
|
||||
end
|
||||
end
|
||||
|
||||
#统计答题百分比,统计结果保留两位小数
|
||||
def statistics_result_percentage(e, t)
|
||||
e = e.to_f
|
||||
t = t.to_f
|
||||
t == 0 ? 0 : format("%.2f", e*100/t)
|
||||
end
|
||||
|
||||
end
|
|
@ -155,9 +155,9 @@ class Project < ActiveRecord::Base
|
|||
#ActiveModel::Dirty 这里有一个changed方法。对任何对象都可以用
|
||||
after_save :update_inherited_members, :if => Proc.new {|project| project.inherit_members_changed?}
|
||||
# 创建project之后默认创建一个board,之后的board去掉了board的概念
|
||||
after_create :create_board_sync,:acts_as_forge_activities,:create_project_ealasticsearch_index
|
||||
after_create :create_board_sync,:acts_as_forge_activities
|
||||
before_destroy :delete_all_members,:delete_project_ealasticsearch_index
|
||||
after_update :update_project_ealasticsearch_index
|
||||
# after_update :update_project_ealasticsearch_index
|
||||
def remove_references_before_destroy
|
||||
return if self.id.nil?
|
||||
Watcher.delete_all ['watchable_id = ?', id]
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
class QualityAnalysis < ActiveRecord::Base
|
||||
attr_accessible :author_login, :project_id, :rep_identifier, :sonar_version, :branch, :path, :rep_identifier, :language
|
||||
|
||||
def user_rep_name
|
||||
self.author_login+":"+self.rep_identifier
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class SonarAnalysis < ActiveRecord::Base
|
||||
attr_accessible :author_login, :project_id, :rep_identifier
|
||||
end
|
|
@ -0,0 +1,483 @@
|
|||
<script>
|
||||
// sqale_rating
|
||||
$(function () {
|
||||
$('#container_sqale_rating').highcharts({
|
||||
|
||||
chart: {
|
||||
type: 'gauge',
|
||||
plotBackgroundColor: null,
|
||||
plotBackgroundImage: null,
|
||||
plotBorderWidth: 0,
|
||||
plotShadow: false
|
||||
},
|
||||
title: false,
|
||||
pane: {
|
||||
startAngle: -150,
|
||||
endAngle: 150,
|
||||
background: [{
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#FFF'],
|
||||
[1, '#333']
|
||||
]
|
||||
},
|
||||
borderWidth: 0,
|
||||
outerRadius: '109%'
|
||||
}, {
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#333'],
|
||||
[1, '#FFF']
|
||||
]
|
||||
},
|
||||
borderWidth: 1,
|
||||
outerRadius: '107%'
|
||||
}, {
|
||||
// default background
|
||||
}, {
|
||||
backgroundColor: '#DDD',
|
||||
borderWidth: 0,
|
||||
outerRadius: '105%',
|
||||
innerRadius: '103%'
|
||||
}]
|
||||
},
|
||||
|
||||
// the value axis
|
||||
yAxis: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
minorTickInterval: 'auto',
|
||||
minorTickWidth: 1,
|
||||
minorTickLength: 10,
|
||||
minorTickPosition: 'inside',
|
||||
minorTickColor: '#666',
|
||||
tickPixelInterval: 30,
|
||||
tickWidth: 2,
|
||||
tickPosition: 'inside',
|
||||
tickLength: 10,
|
||||
tickColor: '#666',
|
||||
labels: {
|
||||
step: 2,
|
||||
rotation: 'auto'
|
||||
},
|
||||
// title: {
|
||||
// text: 'km/h'
|
||||
// },
|
||||
plotBands: [{
|
||||
from: 0,
|
||||
to: 5,
|
||||
color: '#55BF3B' // green
|
||||
}, {
|
||||
from: 6,
|
||||
to: 10,
|
||||
color: '#adde18' // yellow
|
||||
}, {
|
||||
from: 11,
|
||||
to: 20,
|
||||
color: '#DDDF0D' // red
|
||||
}, {
|
||||
from: 21,
|
||||
to: 50,
|
||||
color: '#df8538' // yellow
|
||||
}, {
|
||||
from: 51,
|
||||
to: 100,
|
||||
color: '#DF5353' // yellow
|
||||
}]
|
||||
},
|
||||
|
||||
// delete hightcharts.com
|
||||
credits:{
|
||||
enabled: false
|
||||
},
|
||||
series: [{
|
||||
name: '代码质量',
|
||||
data: [<%= @complexity["msr"][9]["val"] %>]
|
||||
// tooltip: {
|
||||
// valueSuffix: ' km/h'
|
||||
// }
|
||||
}]
|
||||
|
||||
},
|
||||
// Add some life
|
||||
function (chart) {
|
||||
// if (!chart.renderer.forExport) {
|
||||
// setInterval(function () {
|
||||
// var point = chart.series[0].points[0],
|
||||
// newVal,
|
||||
// inc = Math.round((Math.random() - 0.5) * 20);
|
||||
//
|
||||
// newVal = point.y + inc;
|
||||
// if (newVal < 0 || newVal > 200) {
|
||||
// newVal = point.y - inc;
|
||||
// }
|
||||
//
|
||||
// point.update(newVal);
|
||||
//
|
||||
// }, 3000);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// function_complexity
|
||||
$(function () {
|
||||
$('#container_function_complexity').highcharts({
|
||||
|
||||
chart: {
|
||||
type: 'gauge',
|
||||
plotBackgroundColor: null,
|
||||
plotBackgroundImage: null,
|
||||
plotBorderWidth: 0,
|
||||
plotShadow: false
|
||||
},
|
||||
title: false,
|
||||
pane: {
|
||||
startAngle: -150,
|
||||
endAngle: 150,
|
||||
background: [{
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#FFF'],
|
||||
[1, '#333']
|
||||
]
|
||||
},
|
||||
borderWidth: 0,
|
||||
outerRadius: '109%'
|
||||
}, {
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#333'],
|
||||
[1, '#FFF']
|
||||
]
|
||||
},
|
||||
borderWidth: 1,
|
||||
outerRadius: '107%'
|
||||
}, {
|
||||
// default background
|
||||
}, {
|
||||
backgroundColor: '#DDD',
|
||||
borderWidth: 0,
|
||||
outerRadius: '105%',
|
||||
innerRadius: '103%'
|
||||
}]
|
||||
},
|
||||
|
||||
// the value axis
|
||||
yAxis: {
|
||||
min: 0,
|
||||
max: 30,
|
||||
minorTickInterval: 'auto',
|
||||
minorTickWidth: 1,
|
||||
minorTickLength: 10,
|
||||
minorTickPosition: 'inside',
|
||||
minorTickColor: '#666',
|
||||
tickPixelInterval: 30,
|
||||
tickWidth: 2,
|
||||
tickPosition: 'inside',
|
||||
tickLength: 10,
|
||||
tickColor: '#666',
|
||||
labels: {
|
||||
step: 2,
|
||||
rotation: 'auto'
|
||||
},
|
||||
// title: {
|
||||
// text: 'km/h'
|
||||
// },
|
||||
plotBands: [{
|
||||
from: 0,
|
||||
to: 10,
|
||||
color: '#55BF3B' // green
|
||||
}, {
|
||||
from: 11,
|
||||
to: 15,
|
||||
color: '#DDDF0D' // yellow
|
||||
}, {
|
||||
from: 16,
|
||||
to: 30,
|
||||
color: '#DF5353' // red
|
||||
}]
|
||||
},
|
||||
|
||||
// delete hightcharts.com
|
||||
credits:{
|
||||
enabled: false
|
||||
},
|
||||
series: [{
|
||||
name: '复杂度',
|
||||
data: [<%= @complexity["msr"][6]["val"] %>]
|
||||
// tooltip: {
|
||||
// valueSuffix: ' km/h'
|
||||
// }
|
||||
}]
|
||||
|
||||
},
|
||||
// Add some life
|
||||
function (chart) {
|
||||
// if (!chart.renderer.forExport) {
|
||||
// setInterval(function () {
|
||||
// var point = chart.series[0].points[0],
|
||||
//// newVal,
|
||||
//// inc = Math.round((Math.random() - 0.5) * 20);
|
||||
//
|
||||
//// newVal = point.y + inc;
|
||||
//// if (newVal < 0 || newVal > 200) {
|
||||
//// newVal = point.y - inc;
|
||||
//// }
|
||||
//
|
||||
//// point.update(newVal);
|
||||
//
|
||||
// }, 3000);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
// duplicated_lines_density
|
||||
$(function () {
|
||||
$('#container_duplicated_lines_density').highcharts({
|
||||
|
||||
chart: {
|
||||
type: 'gauge',
|
||||
plotBackgroundColor: null,
|
||||
plotBackgroundImage: null,
|
||||
plotBorderWidth: 0,
|
||||
plotShadow: false
|
||||
},
|
||||
title: false,
|
||||
pane: {
|
||||
startAngle: -150,
|
||||
endAngle: 150,
|
||||
background: [{
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#FFF'],
|
||||
[1, '#333']
|
||||
]
|
||||
},
|
||||
borderWidth: 0,
|
||||
outerRadius: '109%'
|
||||
}, {
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#333'],
|
||||
[1, '#FFF']
|
||||
]
|
||||
},
|
||||
borderWidth: 1,
|
||||
outerRadius: '107%'
|
||||
}, {
|
||||
// default background
|
||||
}, {
|
||||
backgroundColor: '#DDD',
|
||||
borderWidth: 0,
|
||||
outerRadius: '105%',
|
||||
innerRadius: '103%'
|
||||
}]
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
style:{
|
||||
fontSize: '18px'
|
||||
}
|
||||
},
|
||||
|
||||
// the value axis
|
||||
yAxis: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
minorTickInterval: 'auto',
|
||||
minorTickWidth: 1,
|
||||
minorTickLength: 10,
|
||||
minorTickPosition: 'inside',
|
||||
minorTickColor: '#666',
|
||||
tickPixelInterval: 30,
|
||||
tickWidth: 2,
|
||||
tickPosition: 'inside',
|
||||
tickLength: 10,
|
||||
tickColor: '#666',
|
||||
labels: {
|
||||
step: 2,
|
||||
rotation: 'auto'
|
||||
},
|
||||
// title: {
|
||||
// text: 'km/h'
|
||||
// },
|
||||
plotBands: [{
|
||||
from: 0,
|
||||
to: 30,
|
||||
color: '#55BF3B' // green
|
||||
}, {
|
||||
from: 31,
|
||||
to: 50,
|
||||
color: '#DDDF0D' // red
|
||||
}, {
|
||||
from: 51,
|
||||
to: 100,
|
||||
color: '#DF5353' // yellow
|
||||
}]
|
||||
},
|
||||
|
||||
// delete hightcharts.com
|
||||
credits:{
|
||||
enabled: false
|
||||
},
|
||||
series: [{
|
||||
name: '重复率',
|
||||
data: [<%= @complexity["msr"][7]["val"] %>]
|
||||
// tooltip: {
|
||||
// valueSuffix: ' km/h'
|
||||
// }
|
||||
}]
|
||||
|
||||
},
|
||||
// Add some life
|
||||
function (chart) {
|
||||
// if (!chart.renderer.forExport) {
|
||||
// setInterval(function () {
|
||||
// var point = chart.series[0].points[0],
|
||||
// newVal,
|
||||
// inc = Math.round((Math.random() - 0.5) * 20);
|
||||
//
|
||||
// newVal = point.y + inc;
|
||||
// if (newVal < 0 || newVal > 200) {
|
||||
// newVal = point.y - inc;
|
||||
// }
|
||||
//
|
||||
// point.update(newVal);
|
||||
//
|
||||
// }, 3000);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
// comment_lines_density
|
||||
$(function () {
|
||||
$('#container_comment_lines_density').highcharts({
|
||||
|
||||
chart: {
|
||||
type: 'gauge',
|
||||
plotBackgroundColor: null,
|
||||
plotBackgroundImage: null,
|
||||
plotBorderWidth: 0,
|
||||
plotShadow: false
|
||||
},
|
||||
title: false,
|
||||
pane: {
|
||||
startAngle: -150,
|
||||
endAngle: 150,
|
||||
background: [{
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#FFF'],
|
||||
[1, '#333']
|
||||
]
|
||||
},
|
||||
borderWidth: 0,
|
||||
outerRadius: '109%'
|
||||
}, {
|
||||
backgroundColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
stops: [
|
||||
[0, '#333'],
|
||||
[1, '#FFF']
|
||||
]
|
||||
},
|
||||
borderWidth: 1,
|
||||
outerRadius: '107%'
|
||||
}, {
|
||||
// default background
|
||||
}, {
|
||||
backgroundColor: '#DDD',
|
||||
borderWidth: 0,
|
||||
outerRadius: '105%',
|
||||
innerRadius: '103%'
|
||||
}]
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
title: {
|
||||
text: '复杂度',
|
||||
x: -23, //center设置标题的位置
|
||||
y: 6
|
||||
},
|
||||
style:{
|
||||
fontSize: '18px'
|
||||
}
|
||||
},
|
||||
|
||||
// the value axis
|
||||
yAxis: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
minorTickInterval: 'auto',
|
||||
minorTickWidth: 1,
|
||||
minorTickLength: 10,
|
||||
minorTickPosition: 'inside',
|
||||
minorTickColor: '#666',
|
||||
tickPixelInterval: 30,
|
||||
tickWidth: 2,
|
||||
tickPosition: 'inside',
|
||||
tickLength: 10,
|
||||
tickColor: '#666',
|
||||
labels: {
|
||||
step: 2,
|
||||
rotation: 'auto'
|
||||
},
|
||||
// title: {
|
||||
// text: 'km/h'
|
||||
// },
|
||||
plotBands: [{
|
||||
from: 0,
|
||||
to: 20,
|
||||
color: '#DDDF0D' // green
|
||||
}, {
|
||||
from: 21,
|
||||
to: 50,
|
||||
color: '#55BF3B' // red
|
||||
}, {
|
||||
from: 51,
|
||||
to: 100,
|
||||
color: '#DF5353' // yellow
|
||||
}]
|
||||
},
|
||||
|
||||
// delete hightcharts.com
|
||||
credits:{
|
||||
enabled: false
|
||||
},
|
||||
series: [{
|
||||
name: '质量等级',
|
||||
data: [<%= @complexity["msr"][5]["val"] %>]
|
||||
// tooltip: {
|
||||
// valueSuffix: ' km/h'
|
||||
// }
|
||||
}]
|
||||
|
||||
},
|
||||
// Add some life
|
||||
function (chart) {
|
||||
// if (!chart.renderer.forExport) {
|
||||
// setInterval(function () {
|
||||
// var point = chart.series[0].points[0],
|
||||
// newVal,
|
||||
// inc = Math.round((Math.random() - 0.5) * 20);
|
||||
//
|
||||
// newVal = point.y + inc;
|
||||
// if (newVal < 0 || newVal > 200) {
|
||||
// newVal = point.y - inc;
|
||||
// }
|
||||
//
|
||||
// point.update(newVal);
|
||||
//
|
||||
// }, 3000);
|
||||
// }
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<div class="project_r_h">
|
||||
<h2 class="project_h2">分析结果</h2>
|
||||
</div>
|
||||
<ul class="analysis-result-list">
|
||||
<li class="analysis-result-name fl fontBlue2" >名称</li>
|
||||
<li class="analysis-result-version fl fontBlue2" >版本</li>
|
||||
<li class="analysis-result-loc fl fontBlue2" >分支</li>
|
||||
<li class="analysis-result-debt fl fontBlue2" >语言</li>
|
||||
<li class="analysis-result-time fl fontBlue2" >时间</li>
|
||||
<div class="cl"></div>
|
||||
</ul>
|
||||
<% if @quality_analyses.count >0 %>
|
||||
<% @quality_analyses.each do |qa| %>
|
||||
<ul class="analysis-result-list">
|
||||
<li title="Name" title="名称"><%=link_to "#{qa.author_login}:#{qa.rep_identifier}", project_quality_analysis_path(:resource_id => qa.author_login+":"+qa.rep_identifier, :branch => qa.branch.nil? ? "master" : qa.branch), :class => "analysis-result-name fl fontBlue2" %></li>
|
||||
<li class="analysis-result-version fl fontBlue2" title="版本">1.0</li>
|
||||
<li class="analysis-result-loc fl fontBlue2" title="分支名"><%= qa.branch %></li>
|
||||
<li class="analysis-result-debt fl fontBlue2" title="语言"><%= qa.language %></li>
|
||||
<li class="analysis-result-time fl fontBlue2" title="时间"><%= format_time(qa.created_at) %></li>
|
||||
<div class="cl"></div>
|
||||
</ul>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<%= javascript_include_tag 'highcharts','highcharts-more' %>
|
||||
<%= render :partial => "hightchars" %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2" style="width:180px;">质量分析</h2>
|
||||
</div>
|
||||
<div class="button-rep">当前分支:<%= params[:branch] %></div>
|
||||
<div class="cl"></div>
|
||||
<div class="tac f20 fb mt35 mb30">项目代码质量分析报告</div>
|
||||
<div class="analysis-tag-wrap f16"> <span class="analysis-tag fl mr15"></span> <span class="fb fl">概要信息</span></div>
|
||||
<div class="analysis-block mt10 mb40 f14">
|
||||
<div class="flex">
|
||||
<div class="analysis-genral">
|
||||
<p id="container_sqale_rating" style="max-width:200px;min-height:200px;width:200px; margin:0 auto;"></p>
|
||||
<p class="fontGrey3">质量等级</p>
|
||||
<p class="fontBlue2 pr"><%= @complexity["msr"][9]["frmt_val"] %><span class="f8 c_white analysis-genral-icon <%= sqale_rating_status(@complexity["msr"][9]["val"])[1] %> borderRadius"><%= sqale_rating_status(@complexity["msr"][9]["val"])[0] %></span></p>
|
||||
</div>
|
||||
<div class="analysis-genral" >
|
||||
<p id="container_function_complexity" style="max-width:200px;min-height:200px;width:200px; margin:0 auto;"></p>
|
||||
<p class="fontGrey3">复杂度</p>
|
||||
<p class="fontBlue2 pr"><%= @complexity["msr"][6]["val"] %><span class="f8 c_white analysis-genral-icon <%= complexity_status(@complexity["msr"][6]["val"])[1] %> borderRadius"><%= complexity_status(@complexity["msr"][6]["val"])[0] %></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="analysis-genral">
|
||||
<p id="container_duplicated_lines_density" style="max-width:200px;min-height:200px;width:200px; margin:0 auto;"></p>
|
||||
<p class="fontGrey3">代码重复度</p>
|
||||
<p class="fontBlue2 pr"><%= @complexity["msr"][7]["frmt_val"] %><span class="f8 c_white analysis-genral-icon <%= duplicated_lines_density_status(@complexity["msr"][7]["val"])[1] %> borderRadius"><%= duplicated_lines_density_status(@complexity["msr"][7]["val"])[0] %></span></p>
|
||||
</div>
|
||||
<div class="analysis-genral">
|
||||
<p id="container_comment_lines_density" style="max-width:200px;min-height:200px;width:200px; margin:0 auto;"></p>
|
||||
<p class="fontGrey3">注释率</p>
|
||||
<p class="fontBlue2 pr"><%= @complexity["msr"][5]["frmt_val"] %><span class="f8 c_white analysis-genral-icon <%= comment_lines_density_status(@complexity["msr"][5]["val"])[1] %> borderRadius"><%=comment_lines_density_status(@complexity["msr"][5]["val"])[0] %></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="analysis-tag-wrap f16"> <span class="analysis-tag fl mr15"></span> <span class="fb fl mr10">质量等级</span><span class="mr10 fontGrey2"><span class="c_red f18" style="margin-top:-5px; display:inline-block;"><%= score_sqale_rating(@complexity["msr"][9]["val"]) %></span>/5分</span><span class="fontGrey2">可定性评价为:<span class="c_red">质量<%= sqale_rating_status(@complexity["msr"][9]["val"])[0] %></span></span></div>
|
||||
<div class="analysis-block mt10 mb40 f14">
|
||||
<div><span class="fontGrey3 mr30">技术债务</span><span class="fontBlue2 w70 pInline"><%= @complexity["msr"][8]["frmt_val"] %></span><span class="fontGrey2"><a target="_blank" href="<%= @sonar_address %>/drilldown/measures/<%= @resource_id %>?metric=sqale_index">查看详情</a></span></div>
|
||||
<div><span class="fontGrey3 mr30">质量问题</span>
|
||||
<span class="fontBlue2 w70 pInline"><a class="fontBlue2 w70 pInline" target="_blank" href="<%= @sonar_address %>/component_issues?id=<%= @resource_id %>#resolved=false"><%= @sonar_issues["msr"][0]["frmt_val"] %></a></span><span class="fontGrey2">问题分类如下:</span></div>
|
||||
<div class="ml90 mt15">
|
||||
<div class="mb10"><span class="analysis-block-icon mr5"></span><span class="fontGrey3 mr45">阻断</span><span class="fontBlue2 w70 pInline"><%= @sonar_issues["msr"][1]["frmt_val"] %></span><span class="quality-percentage"><span class="quality-percentage-rate" style="width:<%= statistics_result_percentage(@sonar_issues["msr"][1]["frmt_val"].to_i, 200) %>%;"></span></span></div>
|
||||
<div class="mb10"><span class="analysis-serious-icon mr5"></span><span class="fontGrey3 mr45">严重</span><span class="fontBlue2 w70 pInline"><%= @sonar_issues["msr"][2]["frmt_val"] %></span><span class="quality-percentage"><span class="quality-percentage-rate" style="width:<%= statistics_result_percentage(@sonar_issues["msr"][2]["frmt_val"].to_i, 200) %>%;"></span></span></div>
|
||||
<div class="mb10"><span class="analysis-main-icon mr5"></span><span class="fontGrey3 mr45">主要</span><span class="fontBlue2 w70 pInline"><%= @sonar_issues["msr"][3]["frmt_val"] %></span><span class="quality-percentage"><span class="quality-percentage-rate" style="width:<%= statistics_result_percentage(@sonar_issues["msr"][3]["frmt_val"].to_i, 200) %>%;"></span></span></div>
|
||||
<div class="mb10"><span class="analysis-secondary-icon mr5"></span><span class="fontGrey3 mr45">次要</span><span class="fontBlue2 w70 pInline"><%= @sonar_issues["msr"][4]["frmt_val"] %></span><span class="quality-percentage"><span class="quality-percentage-rate" style="width:<%= statistics_result_percentage(@sonar_issues["msr"][4]["frmt_val"].to_i, 200) %>%;"></span></span></div>
|
||||
<div><span class="analysis-info-icon mr5"></span><span class="fontGrey3 mr45">信息</span><span class="fontBlue2 w70 pInline"><%= @sonar_issues["msr"][5]["frmt_val"] %></span><span class="quality-percentage"><span class="quality-percentage-rate" style="width:<%= statistics_result_percentage(@sonar_issues["msr"][5]["frmt_val"].to_i, 200) %>%;"></span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="analysis-tag-wrap f16"> <span class="analysis-tag fl mr15"></span> <span class="fb fl mr10">代码规模</span><span class="fontGrey2">可定性评价为:<span class="c_red"><%= lines_scale(@complexity["msr"][0]["frmt_val"]) %></span></span></div>
|
||||
<div class="analysis-block mt10 mb40 flex f14">
|
||||
<div class="analysis-genral">
|
||||
<p class="fontGrey3">代码行数</p>
|
||||
<p class="fontBlue2"><%= @complexity["msr"][0]["frmt_val"] %></p>
|
||||
</div>
|
||||
<div class="analysis-genral">
|
||||
<p class="fontGrey3">文件</p>
|
||||
<p class="fontBlue2"><%= @complexity["msr"][2]["frmt_val"] %></p>
|
||||
</div>
|
||||
<div class="analysis-genral">
|
||||
<p class="fontGrey3">目录</p>
|
||||
<p class="fontBlue2"><%= @complexity["msr"][3]["frmt_val"] %></p>
|
||||
</div>
|
||||
<div class="analysis-genral">
|
||||
<p class="fontGrey3">类</p>
|
||||
<p class="fontBlue2"><%= @complexity["msr"][1]["frmt_val"] %></p>
|
||||
</div>
|
||||
<div class="analysis-genral">
|
||||
<p class="fontGrey3">方法</p>
|
||||
<p class="fontBlue2"><%= @complexity["msr"][4]["frmt_val"] %></p>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="analysis-tag-wrap f16"> <span class="analysis-tag fl mr15"></span> <span class="fb fl">贡献统计</span></div>-->
|
||||
<!--<div class="analysis-block mt10 f12">-->
|
||||
<!--<ul class="contribute-list">-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-avatar"> </li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-code">代码行数</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-problem">引入质量问题数</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-rate">引入质量问题数/代码行数</li>-->
|
||||
<!--<div class="cl"></div>-->
|
||||
<!--</ul>-->
|
||||
<!--<ul class="contribute-list">-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-avatar contribute-list-height">-->
|
||||
<!--<div class="mt8"><img src="images/homepageImage.jpg" width="50" class="image-cir" />-->
|
||||
<!--<p class="fontGrey2 hidden">小明</p>-->
|
||||
<!--</div>-->
|
||||
<!--</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-code contribute-list-height contribute-list-line-height">18340</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-problem contribute-list-height contribute-list-line-height">230</li>-->
|
||||
<!--<li class="fl contribute-list-rate fontBlue2 contribute-list-height contribute-list-line-height">.012540</li>-->
|
||||
<!--<div class="cl"></div>-->
|
||||
<!--</ul>-->
|
||||
<!--<ul class="contribute-list">-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-avatar contribute-list-height">-->
|
||||
<!--<div class="mt8"><img src="images/homepageImage.jpg" width="50" class="image-cir" />-->
|
||||
<!--<p class="fontGrey2 hidden">小王</p>-->
|
||||
<!--</div>-->
|
||||
<!--</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-code contribute-list-height contribute-list-line-height">834</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-problem contribute-list-height contribute-list-line-height">34</li>-->
|
||||
<!--<li class="fl contribute-list-rate fontBlue2 contribute-list-height contribute-list-line-height">.04077</li>-->
|
||||
<!--<div class="cl"></div>-->
|
||||
<!--</ul>-->
|
||||
<!--<ul class="contribute-list">-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-avatar contribute-list-height">-->
|
||||
<!--<div class="mt8"><img src="images/homepageImage.jpg" width="50" class="image-cir" />-->
|
||||
<!--<p class="fontGrey2 hidden">小亮</p>-->
|
||||
<!--</div>-->
|
||||
<!--</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-code contribute-list-height contribute-list-line-height">134</li>-->
|
||||
<!--<li class="fl fontGrey2 contribute-list-problem contribute-list-height contribute-list-line-height">10</li>-->
|
||||
<!--<li class="fl contribute-list-rate fontBlue2 contribute-list-height contribute-list-line-height">.07462</li>-->
|
||||
<!--<div class="cl"></div>-->
|
||||
<!--</ul>-->
|
||||
<!--</div>-->
|
|
@ -0,0 +1,6 @@
|
|||
<% if @name_flag %>
|
||||
<%= render :partial => "result_list" %>
|
||||
<% else %>
|
||||
<%= render "show" %>
|
||||
<% end %>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<div class="f16 fb fontBlue mb10">代码质量分析</div>
|
||||
<div>
|
||||
<%= form_tag( url_for(:controller => 'quality_analysis', :action => 'create', :project_id => @project.id, :user_id => User.current.id, :identifier => @repository.identifier), :remote => true, :id => 'quality_analyses_form') do %>
|
||||
<div class="ui form">
|
||||
<div class="mb10" style="margin-right:13px;">
|
||||
<textarea id="path_description" name="path" rows="8" placeholder="目录相对于根目录,用半角逗号隔开。如:src/main/java,libs,res/script" style="height: 87px; resize:vertical;" class="analysis-option-box"></textarea>
|
||||
</div>
|
||||
<div class="mb10">
|
||||
<div>
|
||||
<%= select_tag :branch, options_for_select(["#{@gitlab_default_branch}"]+ @branch_names, @rev), :id => 'branch', :class => "analysis-option-box" %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb10">
|
||||
<div>
|
||||
<%= select_tag :language, options_for_select(["java","python","ruby","c++","c#", "Web"]), :id => 'branch', :class => "analysis-option-box" %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="courseSendSubmit mr15"><a href="javascript:void(0);" class="sendSourceText" onclick="$('#quality_analyses_form').submit();hideModal()">提交</a></div>
|
||||
<div class="courseSendCancel"><a href="javascript:void(0);" class="sendSourceText" onclick="hideModal()">取消</a></div>
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
|
@ -0,0 +1,76 @@
|
|||
<%= javascript_include_tag 'highcharts','highcharts-more' %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_quality_analyses) %></h2>
|
||||
</div>
|
||||
|
||||
<div class="repository_con " style="line-height:1.9;">
|
||||
<%#= render :partial => 'navigation' %>
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
|
||||
<div id = "container">
|
||||
</div>
|
||||
<div id = "container_quality" class="mt30">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
$('#container').highcharts({
|
||||
chart: {
|
||||
type: 'pie',
|
||||
options3d: {
|
||||
enabled: true,
|
||||
alpha: 45,
|
||||
beta: 0
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: 'Browser market shares at a specific website, 2014'
|
||||
},
|
||||
tooltip: {
|
||||
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
allowPointSelect: true,
|
||||
cursor: 'pointer',
|
||||
depth: 35,
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
format: '{point.name}'
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: 'pie',
|
||||
name: 'Browser share',
|
||||
data: [
|
||||
['Firefox', 45.0],
|
||||
['IE', 26.8],
|
||||
{
|
||||
name: 'Chrome',
|
||||
y: 12.8,
|
||||
sliced: true,
|
||||
selected: true
|
||||
},
|
||||
['Safari', 8.5],
|
||||
['Opera', 6.2],
|
||||
['Others', 0.7]
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
color: '#aaa',
|
||||
fontFamily: 'Arial',
|
||||
textShadow: '0px 0px 6px rgb(0, 0, 0), 0px 0px 3px rgb(f, f, f)',
|
||||
fontWeight: 'normal'
|
||||
}
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><%= link_to l(:button_back), :action => 'show', :id => @project %></p>
|
||||
<% html_title(l(:label_repository), l(:label_statistics)) -%>
|
|
@ -0,0 +1,8 @@
|
|||
$('#ajax-modal').html('<%= escape_javascript( render :partial => 'repositories/quality_analysis', :locals => {}) %>');
|
||||
showModal('ajax-modal', '615px');
|
||||
$('#ajax-modal').siblings().remove();
|
||||
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal()' style='margin-left: 580px;'><img src='/images/bid/close.png' width='26px' height='26px' /></a>");
|
||||
$('#ajax-modal').parent().css("top","20%").css("left","32%").css("border","3px solid #269ac9");
|
||||
$('#ajax-modal').parent().addClass("popbox_polls");
|
||||
|
||||
|
|
@ -2,7 +2,13 @@
|
|||
<div class="project_r_h">
|
||||
<div class="fl"><h2 class="project_h2_repository"><%= render :partial => 'breadcrumbs', :locals => {:path => @path, :kind => 'dir', :revision => @rev} %></h2></div>
|
||||
<a href="<%= @zip_path %>" class="btn_zipdown fr" onclick="">ZIP下载</a>
|
||||
|
||||
<% if is_project_manager?(User.current, @project.id) && QualityAnalysis.where(:project_id => @project.id).first.nil? %>
|
||||
<%# if User.current.member_of?(@project) %>
|
||||
<%= link_to "质量分析", quality_analysis_path(:id => @project.id), :remote => true, :class => "btn_zipdown fr" %>
|
||||
<%# end %>
|
||||
<% else %>
|
||||
<%= link_to "质量分析", project_quality_analysis_path(:project_id => @project.id, :resource_id => @proje), :class => "btn_zipdown fr" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="repository_con" style="line-height:1.9;">
|
||||
<% if @entries.nil? %>
|
||||
|
@ -45,7 +51,7 @@
|
|||
<div class="commit_content_dec fl" title="<%= @changesets_latest_coimmit.comments %>"><%= @changesets_latest_coimmit.message %></div>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="fl"><div class="fb fontGrey3 mr5 fl hidden maxwidth150"><%=@changesets_latest_coimmit.author_email %></div>
|
||||
<span class="fl"><div class="fb fontGrey3 mr5 fl hidden maxwidth150"><%=@changesets_latest_coimmit.author_email %></div>
|
||||
<div class="fl">提交于<%= time_tag(@changesets_latest_coimmit.created_at) %>:</div>
|
||||
<div class="commit_content_dec fl" title="<%= @changesets_latest_coimmit.comments %>"><%= @changesets_latest_coimmit.message %></div>
|
||||
</span>
|
||||
|
@ -57,7 +63,6 @@
|
|||
|
||||
<span class="fr mr5"><font class="fb ml2 mr2 vl_commit">
|
||||
<%=link_to @changesets_all_count, {:action => 'changes', :path => to_path_param(@path), :id => @project, :repository_id => @repository.identifier_param, :rev => @rev,:page=>1 ,:commit_count =>"#{@changesets_all_count}"} %></font> 提交
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
@ -602,6 +602,7 @@ en:
|
|||
label_time_tracking: Time tracking
|
||||
label_change_plural: Changes
|
||||
label_statistics: Statistics
|
||||
label_quality_analyses: Quality Analyses
|
||||
label_commits_per_month: Commits per month
|
||||
label_commits_per_author: Commits per author
|
||||
label_diff: diff
|
||||
|
|
|
@ -732,6 +732,7 @@ zh:
|
|||
label_time_tracking: 时间跟踪
|
||||
label_change_plural: 变更
|
||||
label_statistics: 统计
|
||||
label_quality_analyses: 质量分析
|
||||
|
||||
label_commits_per_month: 每月提交次数
|
||||
label_commits_per_author: 每用户提交次数
|
||||
|
|
|
@ -785,6 +785,13 @@ RedmineApp::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resources :quality_analysis, :only => [:index, :new, :create] do
|
||||
collection do
|
||||
end
|
||||
member do
|
||||
|
||||
end
|
||||
end
|
||||
# resources :files, :only => [:index, :new, :create] do
|
||||
# member do
|
||||
# match "quote_resource_show_project",:via => [:get]
|
||||
|
@ -905,6 +912,7 @@ RedmineApp::Application.routes.draw do
|
|||
|
||||
# repositories routes
|
||||
get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats', :as => "stats_repository_project"
|
||||
get 'projects/:id/repository/:repository_id/quality_analysis', :to => 'repositories#quality_analysis', :as => "quality_analysis"
|
||||
get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
|
||||
|
||||
get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))', :to => 'repositories#changes'
|
||||
|
@ -923,6 +931,7 @@ RedmineApp::Application.routes.draw do
|
|||
}
|
||||
|
||||
get 'projects/:id/repository/statistics', :to => 'repositories#stats'
|
||||
|
||||
get 'projects/:id/repository/graph', :to => 'repositories#graph'
|
||||
|
||||
get 'projects/:id/repository/changes(/*path(.:ext))', :to => 'repositories#changes'
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
class CreateQualityAnalyses < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :quality_analyses do |t|
|
||||
t.integer :project_id
|
||||
t.string :author_login
|
||||
t.string :rep_identifier
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddJkVersionToQualityAnalysis < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :quality_analyses, :sonar_version, :integer, :default => false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class AddColumnToQualityAnalyses < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :quality_analyses, :path, :string
|
||||
add_column :quality_analyses, :branch, :string
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddLanguaeToQualityAnalyses < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :quality_analyses, :language, :string
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddNameToQualityAnalyses < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :quality_analyses, :language, :string
|
||||
end
|
||||
end
|
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -1247,6 +1247,39 @@ a.pages-big{ width:50px;}
|
|||
.red-cir-btn{ background:#e74c3c; padding:1px 5px; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; color:#fff; font-weight:normal;font-size:12px;}
|
||||
.green-cir-btn{ background:#28be6c; padding:1px 5px; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; color:#fff; font-weight:normal;font-size:12px;}
|
||||
|
||||
/*20160622质量分析*/
|
||||
.analysis-tag-wrap {width:100%; color:#000; height:20px; line-height:20px; vertical-align:middle;}
|
||||
.analysis-tag {width:10px; height:20px; background-color:#777;}
|
||||
.analysis-block {padding:15px; border:1px solid #d9d9d9;}
|
||||
.flex {display:flex;}
|
||||
.analysis-genral {flex:1; display:block; text-align:center;}
|
||||
.analysis-block-icon {background:url(../images/code-analysis-icon.png) -2px -8px no-repeat; width:14px; height:14px; display:inline-block; vertical-align:middle;}
|
||||
.analysis-serious-icon {background:url(../images/code-analysis-icon.png) -2px -34px no-repeat; width:14px; height:14px; display:inline-block; vertical-align:middle;}
|
||||
.analysis-main-icon {background:url(../images/code-analysis-icon.png) -2px -59px no-repeat; width:14px; height:14px; display:inline-block; vertical-align:middle;}
|
||||
.analysis-secondary-icon {background:url(../images/code-analysis-icon.png) -2px -85px no-repeat; width:14px; height:14px; display:inline-block; vertical-align:middle;}
|
||||
.analysis-info-icon {background:url(../images/code-analysis-icon.png) -2px -111px no-repeat; width:14px; height:14px; display:inline-block; vertical-align:middle;}
|
||||
.quality-percentage {width:320px; height:14px; display:inline-block;}
|
||||
.quality-percentage-rate {width:50%; height:14px; background-color:#0a6c99; display:inline-block;}
|
||||
.image-cir {border-radius:50%;}
|
||||
.analysis-genral-icon {position:absolute; padding:1px 5px; display:inline-block; top:5px;}
|
||||
.contribute-list-avatar {width:80px; vertical-align:middle; text-align:center;}
|
||||
.contribute-list-code {width:160px; vertical-align:middle; text-align:center;}
|
||||
.contribute-list-problem {width:170px; vertical-align:middle; text-align:center;}
|
||||
.contribute-list-rate {width:228px; vertical-align:middle; text-align:center;}
|
||||
.contribute-list-height {height:80px;}
|
||||
.contribute-list-line-height {line-height:80px;}
|
||||
|
||||
/*20160623分析结果*/
|
||||
.analysis-result-list {padding:5px;}
|
||||
.analysis-result-list:nth-of-type(odd){background:#fff;}/*奇数行*/
|
||||
.analysis-result-list:nth-of-type(even){background:#f5f5f5;}/*偶数行*/
|
||||
.analysis-result-name {width:200px; cursor:pointer;}
|
||||
.analysis-result-version {width:90px; text-align:right; cursor:pointer;}
|
||||
.analysis-result-loc {width:60px; text-align:right; cursor:pointer;}
|
||||
.analysis-result-debt {width:160px; text-align:right; cursor:pointer;}
|
||||
.analysis-result-time {width:150px; text-align:right; cursor:pointer;}
|
||||
.analysis-name-icon {background:url(../images/code-analysis-icon.png) -2px -148px no-repeat; width:16px; height:16px; display:inline-block; vertical-align:middle;}
|
||||
|
||||
/*未登录回复提示*/
|
||||
.visitor-box {width:620px; height:33px; line-height:33px; text-align:center; vertical-align: middle; border:1px solid #ccc; background-color: #fff;}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ a.btn_message_free{ background:#ff5722; display:block; text-align:center; color
|
|||
h2{ font-size:18px; }
|
||||
h3{ font-size:14px; }
|
||||
h4{ font-size:14px; }
|
||||
.f8 {font-size:8px;}
|
||||
.f12{font-size:12px; font-weight:normal;}
|
||||
.f14{font-size:14px;}
|
||||
.f16{font-size:16px;}
|
||||
|
@ -130,6 +131,7 @@ h4{ font-size:14px; }
|
|||
.mt12 { margin-top:12px !important;}
|
||||
.mt15 {margin-top:15px;}
|
||||
.mt19 {margin-top:19px !important;}
|
||||
.mt35 {margin-top:35px;}
|
||||
.ml70{margin-left: 70px;}
|
||||
.mb0 {margin-bottom: 0px !important;}
|
||||
.mb4{ margin-bottom:4px;}
|
||||
|
@ -137,6 +139,8 @@ h4{ font-size:14px; }
|
|||
.mb8 {margin-bottom:8px;}
|
||||
.mb10{ margin-bottom:10px !important;}
|
||||
.mb20{ margin-bottom:20px;}
|
||||
.mb30 {margin-bottom:30px;}
|
||||
.mb40 {margin-bottom:40px;}
|
||||
.pl10 {padding-left:10px;}
|
||||
.pl15{ padding-left:15px;}
|
||||
.pl5{ padding-left:5px;}
|
||||
|
@ -228,6 +232,7 @@ a.c_green{ color:#28be6c;}
|
|||
|
||||
.b_grey{ background: #F5F5F5;}
|
||||
.b_dgrey{ background: #CCC;}
|
||||
.c_white {color:#fff;}
|
||||
.c_orange{color:#e8770d;}
|
||||
.c_dark{ color:#2d2d2d;}
|
||||
.c_lorange{ color:#ff9900;}
|
||||
|
@ -239,6 +244,11 @@ a.c_green{ color:#28be6c;}
|
|||
.c_dblue{ color:#09658c;}
|
||||
.b_blue{background:#64bdd9;}
|
||||
.b_green{background:#28be6c;}
|
||||
.b_slow_yellow{background:#adde18;}
|
||||
.b_yellow{background:#DDDF0D;}
|
||||
.b_slow_red{background:#df8538;}
|
||||
.b_green2 {background:#63c360;}
|
||||
.b_red {background:#d60308;}
|
||||
.b_w{ background:#fff !important;}
|
||||
|
||||
/*add by Tim*/
|
||||
|
@ -341,6 +351,8 @@ a:hover.bgreen_n_btn{background:#08a384;}
|
|||
.orange_btn_cir{ background:#e67e22; padding:1px 10px; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; color:#fff; font-weight:normal; font-size:12px;white-space:nowrap;}
|
||||
.bgreen_btn_cir{ background:#1abc9c; padding:1px 10px; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; color:#fff; font-weight:normal; font-size:12px;white-space:nowrap;}
|
||||
.grey_border{border:1px solid #dddddd !important;}
|
||||
.borderRadius {border-radius:5px;}
|
||||
.tac {text-align:center;}
|
||||
/* commonpic */
|
||||
.pic_date{ display:block; background:url(../images/new_project/public_icon.png) -31px 0 no-repeat; width:16px; height:15px; float:left;}
|
||||
.pic_add{ display:block; background:url(../images/new_project/public_icon.png) -31px -273px no-repeat; width:16px; height:15px; float:left;}
|
||||
|
@ -1168,3 +1180,6 @@ a.shadowbox_news_all{ display:block; width:305px; height:40px; line-height:40px;
|
|||
.visitor-box {width:620px; height:33px; line-height:33px; text-align:center; vertical-align: middle; border:1px solid #ccc; background-color: #fff;}
|
||||
|
||||
.reply_iconup{ position:absolute; top:21px; left:13px; color:#d4d4d4; font-size:16px; background:#f1f1f1; line-height:13px;}
|
||||
|
||||
/*20160622代码分析弹窗*/
|
||||
.analysis-option-box {width:100%; border:1px solid #ccc; padding:3px 5px;}
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe QualityAnalysisController, :type => :controller do
|
||||
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
FactoryGirl.define do
|
||||
factory :quality_analyasis, class: 'QualityAnalysis' do
|
||||
project_id 1
|
||||
author_login "MyString"
|
||||
rep_identifier "MyString"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe QualityAnalysis, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue