Merge branch 'standalone_develop' into pm_project_develop
This commit is contained in:
commit
be531eb283
|
@ -11,6 +11,7 @@
|
|||
# Ignore lock config file
|
||||
*.log
|
||||
.rubocop.yml
|
||||
.env
|
||||
# mac
|
||||
*.DS_Store
|
||||
.bashrc
|
||||
|
@ -84,4 +85,5 @@ redis_data/
|
|||
dump.rdb
|
||||
.tags*
|
||||
ceshi_user.xlsx
|
||||
public/trace_task_results
|
||||
public/trace_task_results
|
||||
public/项目活跃度排行.xls
|
2
Gemfile
2
Gemfile
|
@ -141,4 +141,4 @@ gem 'doorkeeper'
|
|||
|
||||
gem 'doorkeeper-jwt'
|
||||
|
||||
gem 'gitea-client', '~> 1.4.3'
|
||||
gem 'gitea-client', '~> 1.4.6'
|
||||
|
|
|
@ -21,13 +21,75 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq
|
||||
month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq
|
||||
@day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count
|
||||
@weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
|
||||
@month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
|
||||
|
||||
@weekly_active_project_count = Rails.cache.fetch("dashboardscontroller:weekly_active_project_count", expires_in: 10.minutes) do
|
||||
Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
|
||||
end
|
||||
@month_active_project_count = Rails.cache.fetch("dashboardscontroller:month_active_project_count", expires_in: 1.hours) do
|
||||
Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
|
||||
end
|
||||
# 新增项目数
|
||||
@day_new_project_count = Project.where(created_on: today).count
|
||||
@weekly_new_project_count = Project.where(created_on: current_week).count
|
||||
@month_new_project_count = Project.where(created_on: current_month).count
|
||||
@day_new_project_count = Rails.cache.fetch("dashboardscontroller:day_new_project_count", expires_in: 10.minutes) do
|
||||
Project.where(created_on: today).count
|
||||
end
|
||||
@weekly_new_project_count = Rails.cache.fetch("dashboardscontroller:weekly_new_project_count", expires_in: 10.minutes) do
|
||||
Project.where(created_on: current_week).count
|
||||
end
|
||||
@month_new_project_count = Rails.cache.fetch("dashboardscontroller:month_new_project_count", expires_in: 1.hours) do
|
||||
Project.where(created_on: current_month).count
|
||||
end
|
||||
|
||||
|
||||
# 总的平台用户数
|
||||
# 总的平台项目数
|
||||
# 总的平台组织数
|
||||
# 总的平台Issue数、评论数、PR数、Commit数
|
||||
@user_count = Rails.cache.fetch("dashboardscontroller:platform:user_count", expires_in: 1.days) do
|
||||
User.count
|
||||
end
|
||||
@project_count = Rails.cache.fetch("dashboardscontroller:platform:project_count", expires_in: 1.days) do
|
||||
Project.count
|
||||
end
|
||||
@organization_count = Rails.cache.fetch("dashboardscontroller:platform:organization_count", expires_in: 1.days) do
|
||||
Organization.count
|
||||
end
|
||||
@issue_count = Rails.cache.fetch("dashboardscontroller:platform:issue_count", expires_in: 1.days) do
|
||||
Issue.count
|
||||
end
|
||||
@comment_count = Rails.cache.fetch("dashboardscontroller:platform:comment_count", expires_in: 1.days) do
|
||||
Journal.count
|
||||
end
|
||||
@pr_count = Rails.cache.fetch("dashboardscontroller:platform:pr_count", expires_in: 1.days) do
|
||||
PullRequest.count
|
||||
end
|
||||
@commit_count = Rails.cache.fetch("dashboardscontroller:platform:commit_count", expires_in: 1.days) do
|
||||
CommitLog.count
|
||||
end
|
||||
|
||||
@subject_name = ["用户数", "项目数", "组织数", "Issue数", "Issue评论数", "PR数", "Commit数"]
|
||||
@subject_icon = ["fa-user","fa-git", "fa-sitemap", "fa-warning", "fa-comments", "fa-share-alt", "fa-upload"]
|
||||
@subject_data = [@user_count, @project_count, @organization_count, @issue_count, @comment_count, @pr_count, @commit_count]
|
||||
|
||||
|
||||
tongji_service = Baidu::TongjiService.new
|
||||
@access_token = tongji_service.access_token
|
||||
Rails.logger.info "baidu_tongji_auth access_token ===== #{@access_token}"
|
||||
# @overview_data = tongji_service.api_overview
|
||||
last_date = DailyPlatformStatistic.order(:date).last
|
||||
start_date = last_date.date
|
||||
end_date = Time.now
|
||||
if @access_token.present?
|
||||
@overview_data = Rails.cache.fetch("dashboardscontroller:baidu_tongji:overview_data", expires_in: 10.minutes) do
|
||||
tongji_service.source_from_batch_add(start_date, end_date)
|
||||
@overview_data = tongji_service.overview_batch_add(start_date, end_date)
|
||||
@overview_data
|
||||
end
|
||||
end
|
||||
|
||||
@current_week_statistic = DailyPlatformStatistic.where(date: current_week)
|
||||
@pre_week_statistic = DailyPlatformStatistic.where(date: pre_week)
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
def month_active_user
|
||||
|
@ -42,6 +104,19 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
render_ok(data: data)
|
||||
end
|
||||
|
||||
def baidu_tongji
|
||||
tongji_service = Baidu::TongjiService.new
|
||||
redirect_to tongji_service.code_url
|
||||
end
|
||||
|
||||
def baidu_tongji_auth
|
||||
if params[:code].present?
|
||||
tongji_service = Baidu::TongjiService.new
|
||||
tongji_service.get_access_token(params[:code])
|
||||
end
|
||||
redirect_to "/admins/"
|
||||
end
|
||||
|
||||
def evaluate
|
||||
names = []
|
||||
data = []
|
||||
|
@ -63,8 +138,12 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
Time.now.beginning_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_week
|
||||
def pre_7_days
|
||||
7.days.ago.end_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_week
|
||||
Time.now.beginning_of_week..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_month
|
||||
|
@ -72,6 +151,7 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
end
|
||||
|
||||
def pre_week
|
||||
14.days.ago.end_of_day..7.days.ago.end_of_day
|
||||
# 14.days.ago.end_of_day..7.days.ago.end_of_day
|
||||
Time.now.prev_week..Time.now.prev_week.end_of_week
|
||||
end
|
||||
end
|
|
@ -14,12 +14,14 @@ class Admins::IdentityVerificationsController < Admins::BaseController
|
|||
end
|
||||
|
||||
def update
|
||||
if @identity_verification.update(update_params)
|
||||
if update_params[:state] == "已拒绝" && update_params[:description].blank?
|
||||
flash[:danger] = '拒绝理由不能为空'
|
||||
render 'edit'
|
||||
else
|
||||
UserAction.create(action_id: @identity_verification.id, action_type: "UpdateIdentityVerifications", user_id: current_user.id, :ip => request.remote_ip, data_bank: @identity_verification.attributes.to_json)
|
||||
@identity_verification.update(update_params)
|
||||
redirect_to admins_identity_verifications_path
|
||||
flash[:success] = "更新成功"
|
||||
else
|
||||
redirect_to admins_identity_verifications_path
|
||||
flash[:danger] = "更新失败"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
class Admins::IssuesRankController < Admins::BaseController
|
||||
|
||||
def index
|
||||
@statistics = DailyProjectStatistic.where('date >= ? AND date <= ?', begin_date, end_date)
|
||||
@statistics = @statistics.group(:project_id).joins(:project).select("project_id,
|
||||
sum(issues) as issues,
|
||||
sum(closed_issues) as closed_issues,
|
||||
projects.issues_count as issues_count")
|
||||
@statistics = @statistics.order("#{sort_by} #{sort_direction}").limit(50)
|
||||
end
|
||||
|
||||
private
|
||||
def begin_date
|
||||
params.fetch(:begin_date, (Date.yesterday-7.days).to_s)
|
||||
end
|
||||
|
||||
def end_date
|
||||
params.fetch(:end_date, Date.yesterday.to_s)
|
||||
end
|
||||
|
||||
def sort_by
|
||||
DailyProjectStatistic.column_names.include?(params.fetch(:sort_by, "issues")) ? params.fetch(:sort_by, "issues") : "issues"
|
||||
end
|
||||
|
||||
def sort_direction
|
||||
%w(desc asc).include?(params.fetch(:sort_direction, "desc")) ? params.fetch(:sort_direction, "desc") : "desc"
|
||||
end
|
||||
|
||||
end
|
|
@ -1,16 +1,55 @@
|
|||
class Admins::ProjectsRankController < Admins::BaseController
|
||||
|
||||
def index
|
||||
@rank_date = rank_date
|
||||
deleted_data = $redis_cache.smembers("v2-project-rank-deleted")
|
||||
$redis_cache.zrem("v2-project-rank-#{rank_date}", deleted_data) unless deleted_data.blank?
|
||||
@date_rank = $redis_cache.zrevrange("v2-project-rank-#{rank_date}", 0, -1, withscores: true)
|
||||
@statistics = DailyProjectStatistic.where("date >= ? AND date <= ?", begin_date, end_date)
|
||||
@statistics = @statistics.group(:project_id).select("project_id,
|
||||
sum(score) as score,
|
||||
sum(visits) as visits,
|
||||
sum(watchers) as watchers,
|
||||
sum(praises) as praises,
|
||||
sum(forks) as forks,
|
||||
sum(issues) as issues,
|
||||
sum(pullrequests) as pullrequests,
|
||||
sum(commits) as commits").includes(:project)
|
||||
@statistics = @statistics.order("#{sort_by} #{sort_direction}")
|
||||
export_excel(@statistics.limit(50))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rank_date
|
||||
params.fetch(:date, Date.today.to_s)
|
||||
def begin_date
|
||||
params.fetch(:begin_date, (Date.yesterday-7.days).to_s)
|
||||
end
|
||||
|
||||
def end_date
|
||||
params.fetch(:end_date, Date.yesterday.to_s)
|
||||
end
|
||||
|
||||
def sort_by
|
||||
DailyProjectStatistic.column_names.include?(params.fetch(:sort_by, "score")) ? params.fetch(:sort_by, "score") : "score"
|
||||
end
|
||||
|
||||
def sort_direction
|
||||
%w(desc asc).include?(params.fetch(:sort_direction, "desc")) ? params.fetch(:sort_direction, "desc") : "desc"
|
||||
end
|
||||
|
||||
def export_excel(data)
|
||||
book = Spreadsheet::Workbook.new
|
||||
sheet = book.create_worksheet :name => "项目活跃度排行"
|
||||
sheet.row(0).concat %w(排名 项目全称 项目地址 得分 访问数 关注数 点赞数 fork数 疑修数 合并请求数 提交数)
|
||||
data.each_with_index do |d, index|
|
||||
sheet[index+1,0] = index+1
|
||||
sheet[index+1,1] = "#{d&.project&.owner&.real_name}/#{d&.project&.name}"
|
||||
sheet[index+1,2] = "#{Rails.application.config_for(:configuration)['platform_url']}/#{d&.project&.owner&.login}/#{d&.project&.identifier}"
|
||||
sheet[index+1,3] = d.score
|
||||
sheet[index+1,4] = d.visits
|
||||
sheet[index+1,5] = d.watchers
|
||||
sheet[index+1,6] = d.praises
|
||||
sheet[index+1,7] = d.forks
|
||||
sheet[index+1,8] = d.issues
|
||||
sheet[index+1,9] = d.pullrequests
|
||||
sheet[index+1,10] = d.commits
|
||||
end
|
||||
book.write "#{Rails.root}/public/项目活跃度排行.xls"
|
||||
end
|
||||
|
||||
end
|
|
@ -29,8 +29,12 @@ class Admins::SitePagesController < Admins::BaseController
|
|||
end
|
||||
|
||||
def update
|
||||
@site_page.update(update_params)
|
||||
flash[:success] = '保存成功'
|
||||
if update_params[:state] == "false" && update_params[:state_description].blank?
|
||||
flash[:danger] = '关闭站点理由不能为空'
|
||||
else
|
||||
@site_page.update(update_params)
|
||||
flash[:success] = '保存成功'
|
||||
end
|
||||
render 'edit'
|
||||
end
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class Admins::SystemNotificationsController < Admins::BaseController
|
|||
@notification = SystemNotification.new(notification_params)
|
||||
if @notification.save
|
||||
redirect_to admins_system_notifications_path
|
||||
flash[:success] = '系统消息创建成功'
|
||||
flash[:success] = '系统公告创建成功'
|
||||
else
|
||||
redirect_to admins_system_notifications_path
|
||||
flash[:danger] = @notification.errors.full_messages.join(",")
|
||||
|
@ -37,7 +37,7 @@ class Admins::SystemNotificationsController < Admins::BaseController
|
|||
if @notification.update_attributes(notification_params)
|
||||
format.html do
|
||||
redirect_to admins_system_notifications_path
|
||||
flash[:success] = '系统消息更新成功'
|
||||
flash[:success] = '系统公告更新成功'
|
||||
end
|
||||
format.js {render_ok}
|
||||
else
|
||||
|
@ -53,10 +53,10 @@ class Admins::SystemNotificationsController < Admins::BaseController
|
|||
def destroy
|
||||
if @notification.destroy
|
||||
redirect_to admins_system_notifications_path
|
||||
flash[:success] = "系统消息删除成功"
|
||||
flash[:success] = "系统公告删除成功"
|
||||
else
|
||||
redirect_to admins_system_notifications_path
|
||||
flash[:danger] = "系统消息删除失败"
|
||||
flash[:danger] = "系统公告删除失败"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
class Api::V1::Projects::Actions::ActionsController < Api::V1::Projects::Actions::BaseController
|
||||
|
||||
def index
|
||||
begin
|
||||
gitea_result = $gitea_hat_client.get_repos_actions_by_owner_repo(@project&.owner&.login, @project&.identifier)
|
||||
@data = gitea_result[:data]["Workflows"]
|
||||
rescue
|
||||
@data = []
|
||||
end
|
||||
end
|
||||
|
||||
def disable
|
||||
return render_error("请输入正确的流水线文件!") if params[:workflow].blank?
|
||||
gitea_result = $gitea_hat_client.post_repos_actions_disable(@project&.owner&.login, @project&.identifier, {query: {workflow: params[:workflow]}}) rescue nil
|
||||
if gitea_result
|
||||
render_ok
|
||||
else
|
||||
render_error("禁用流水线失败")
|
||||
end
|
||||
end
|
||||
|
||||
def enable
|
||||
return render_error("请输入正确的流水线文件!") if params[:workflow].blank?
|
||||
gitea_result = $gitea_hat_client.post_repos_actions_enable(@project&.owner&.login, @project&.identifier, {query: {workflow: params[:workflow]}}) rescue nil
|
||||
if gitea_result
|
||||
render_ok
|
||||
else
|
||||
render_error("取消禁用流水线失败")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
class Api::V1::Projects::Actions::BaseController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above
|
||||
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class Api::V1::Projects::Actions::RunsController < Api::V1::Projects::Actions::BaseController
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Actions::Runs::ListService.call(@project, {workflow: params[:workflow], page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def job_show
|
||||
@result_object = Api::V1::Projects::Actions::Runs::JobShowService.call(@project, params[:run_id], params[:job], params[:log_cursors], current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
|
||||
end
|
|
@ -2,14 +2,14 @@ class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
|||
before_action :require_public_and_member_above, only: [:index, :all]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
|
||||
@result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], state: params[:state], page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def all
|
||||
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
before_action :require_operate_above, only: [:create, :destroy]
|
||||
before_action :require_operate_above, only: [:create, :destroy, :restore]
|
||||
|
||||
def create
|
||||
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
|
||||
|
@ -33,6 +33,15 @@ class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def restore
|
||||
@result_object = Api::V1::Projects::Branches::RestoreService.call(@project, params[:branch_id], params[:branch_name], current_user&.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('恢复分支失败!')
|
||||
end
|
||||
end
|
||||
|
||||
before_action :require_manager_above, only: [:update_default_branch]
|
||||
|
||||
def update_default_branch
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index, :diff]
|
||||
before_action :require_public_and_member_above, only: [:index, :diff, :recent]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
|
||||
|
@ -9,4 +9,8 @@ class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
|||
def diff
|
||||
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def recent
|
||||
@result_object = Api::V1::Projects::Commits::RecentService.call(@project, {page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
end
|
|
@ -4,17 +4,31 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
|||
before_action :check_user_can_edit_org, only: [:destroy]
|
||||
|
||||
def index
|
||||
@organization_users = @organization.organization_users.includes(:user)
|
||||
# @organization_users = @organization.organization_users.includes(:user)
|
||||
# if params[:search].present?
|
||||
# search = params[:search].to_s.downcase
|
||||
# user_condition_users = User.like(search).to_sql
|
||||
# team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||
# users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||
#
|
||||
# @organization_users = @organization_users.where(user_id: users).distinct
|
||||
# end
|
||||
#
|
||||
# @organization_users = kaminari_paginate(@organization_users)
|
||||
|
||||
organization_user_ids = @organization.organization_users.pluck(:user_id).uniq
|
||||
project_member_user_ids = @organization.projects.joins(:members).pluck("members.user_id").uniq
|
||||
ids = organization_user_ids + project_member_user_ids
|
||||
users = User.where(id: ids).reorder(Arel.sql("FIELD(users.id,#{ids.join(',')})"))
|
||||
if params[:search].present?
|
||||
search = params[:search].to_s.downcase
|
||||
user_condition_users = User.like(search).to_sql
|
||||
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||
user_ids = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users").pluck(:id)
|
||||
|
||||
@organization_users = @organization_users.where(user_id: users).distinct
|
||||
users = users.where(id: user_ids)
|
||||
end
|
||||
|
||||
@organization_users = kaminari_paginate(@organization_users)
|
||||
@users = kaminari_paginate(users)
|
||||
end
|
||||
|
||||
def pm_check_user
|
||||
|
|
|
@ -338,7 +338,7 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def project_params
|
||||
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
|
||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private,
|
||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private, :auto_init,
|
||||
:blockchain, :blockchain_token_all, :blockchain_init_token, :pr_view_admin)
|
||||
end
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ class RepositoriesController < ApplicationController
|
|||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
@repo_detail = $gitea_client.get_repos_by_owner_repo(@owner.login, @project.identifier)
|
||||
return render_not_found if @entries.blank? && !@repo_detail["empty"]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -17,23 +17,31 @@ class SitePagesController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
return normal_status(-1, "你还未开通Page服务,无法进行部署") unless current_user.website_permission
|
||||
return normal_status(-1, "你已使用了 #{params[:identifier]} 作为page标识") if Page.exists?(identifier: params[:identifier], user: current_user)
|
||||
return normal_status(-1, "该仓库已开通Page服务") if Page.exists?(project: @project)
|
||||
return normal_status(-1, '你还未开通Page服务,无法进行部署') unless current_user.website_permission
|
||||
return normal_status(-1, '你已开通Page服务') if Page.exists?(user: current_user)
|
||||
return normal_status(-1, '该仓库已开通Page服务') if Page.exists?(project: @project)
|
||||
@page = Page.new(create_params)
|
||||
@page.user = current_user
|
||||
@page.project = @project
|
||||
@page.save
|
||||
end
|
||||
|
||||
def update
|
||||
return normal_status(-1, '你还未开通Page服务') unless current_user.website_permission
|
||||
return normal_status(-1, '你还未开通Page站点') unless Page.exists?(user: current_user)
|
||||
@page = Page.find_by(user: current_user)
|
||||
@page.update(language_frame: params[:language_frame])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def build
|
||||
return normal_status(-1, "你还未开通Page服务,无法进行部署") unless current_user.website_permission
|
||||
return normal_status(-1, "该仓库还未开通Page服务,无法进行部署") unless Page.exists?(project: @project)
|
||||
return normal_status(-1, '你还未开通Page服务,无法进行部署') unless current_user.website_permission
|
||||
return normal_status(-1, '该仓库还未开通Page服务,无法进行部署') unless Page.exists?(project: @project)
|
||||
@page = Page.find params[:id]
|
||||
return normal_status(-1, @page.state_description) unless @page.state
|
||||
response_str = @page.deploy_page(params[:branch])
|
||||
data = JSON.parse(response_str)["result"] || data = JSON.parse(response_str)["error"]
|
||||
if data.to_s.include?("部署成功")
|
||||
data = JSON.parse(response_str)['result'] || (data = JSON.parse(response_str)['error'])
|
||||
if data.to_s.include?('部署成功')
|
||||
@page.update(last_build_at: Time.now, build_state: true, last_build_info: data)
|
||||
else
|
||||
@page.update(build_state:false, last_build_info: data)
|
||||
|
@ -42,22 +50,22 @@ class SitePagesController < ApplicationController
|
|||
end
|
||||
|
||||
def softbot_build
|
||||
branch = params[:ref].split("/").last
|
||||
branch = params[:ref].split('/').last
|
||||
user = User.find_by_login params[:repository][:owner][:login]
|
||||
return normal_status(-1, "你还未开通Page服务,无法进行部署") unless user.website_permission
|
||||
return normal_status(-1, '你还未开通Page服务,无法进行部署') unless user.website_permission
|
||||
|
||||
project = Project.where(identifier: params[:repository][:name],user_id: user.id)
|
||||
return normal_status(-1, "你没有权限操作") if project.owner?(user)
|
||||
return normal_status(-1, "该仓库还未开通Page服务,无法进行部署") if Page.exists?(user: user, project: project)
|
||||
return normal_status(-1, '你没有权限操作') if project.owner?(user)
|
||||
return normal_status(-1, '该仓库还未开通Page服务,无法进行部署') if Page.exists?(user: user, project: project)
|
||||
|
||||
@page = Page.find_by(user: user, project: project)
|
||||
response_str = @page.deploy_page(branch)
|
||||
data = JSON.parse(response_str)["result"]
|
||||
data = JSON.parse(response_str)['result']
|
||||
if data.nil?
|
||||
data = JSON.parse(response_str)["error"]
|
||||
data = JSON.parse(response_str)['error']
|
||||
end
|
||||
|
||||
if data.include?("部署成功")
|
||||
if data.include?('部署成功')
|
||||
@page.update(last_build_at: Time.now, build_state: true, last_build_info: data)
|
||||
else
|
||||
@page.update(build_state:false, last_build_info: data)
|
||||
|
@ -85,7 +93,7 @@ class SitePagesController < ApplicationController
|
|||
end
|
||||
|
||||
def theme_params
|
||||
params[:language_frame] || "hugo"
|
||||
params[:language_frame] || 'hugo'
|
||||
end
|
||||
|
||||
def create_params
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
class Organizations::CreateForm < BaseForm
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
NAME_REGEX = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname, :original_name
|
||||
|
||||
validates :name, :nickname, :visibility, presence: true
|
||||
validates :name, :nickname, length: { maximum: 100 }
|
||||
validates :location, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符" }
|
||||
|
||||
validate do
|
||||
check_name(name) unless name.blank? || name == original_name
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Projects::CreateForm < BaseForm
|
||||
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner,
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner, :auto_init,
|
||||
:blockchain, :blockchain_token_all, :blockchain_init_token
|
||||
|
||||
validates :user_id, :name, :repository_name, presence: true
|
||||
|
@ -10,7 +10,7 @@ class Projects::CreateForm < BaseForm
|
|||
validates :repository_name, length: { maximum: 100 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
|
||||
validate :check_ignore, :check_license, :check_owner, :check_max_repo_creation
|
||||
validate :check_ignore, :check_license, :check_auto_init, :check_owner, :check_max_repo_creation
|
||||
validate do
|
||||
check_project_category(project_category_id)
|
||||
check_project_language(project_language_id)
|
||||
|
@ -28,6 +28,10 @@ class Projects::CreateForm < BaseForm
|
|||
raise "ignore_id值无效." if ignore_id && Ignore.find_by(id: ignore_id).blank?
|
||||
end
|
||||
|
||||
def check_auto_init
|
||||
raise "auto_init值无效." if ignore_id && license_id && !auto_init
|
||||
end
|
||||
|
||||
def check_owner
|
||||
@project_owner = Owner.find_by(id: user_id)
|
||||
raise "user_id值无效." if user_id && @project_owner.blank?
|
||||
|
|
|
@ -45,6 +45,7 @@ module Gitea
|
|||
else
|
||||
Rails.logger.error("Gitea::Repository::Entries::DeleteService error[#{response.status}]======#{response.body}")
|
||||
@error = "删除失败,请确认该分支是否是保护分支。"
|
||||
@error = "删除失败,参数sha不匹配。" if response.body.to_s.include?("sha does not match")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# 按天获取百度统计数据,pv,访问,ip和来源分类占比
|
||||
# 其他统计:前一周用户留存率
|
||||
class DailyPlatformStatisticsJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(*args)
|
||||
Rails.logger.info("*********开始统计*********")
|
||||
|
||||
tongji_service = Baidu::TongjiService.new
|
||||
access_token = tongji_service.access_token
|
||||
Rails.logger.info "job baidu_tongji_auth access_token ===== #{access_token}"
|
||||
ActiveJob::Base.logger.info "job baidu_tongji_auth access_token ===== #{access_token}"
|
||||
# 从最后一个记录日期开始,如果遗漏日期数据可以补充数据
|
||||
last_date = DailyPlatformStatistic.order(:date).last
|
||||
start_date = last_date.date
|
||||
end_date = Time.now
|
||||
if access_token.present?
|
||||
tongji_service.overview_batch_add(start_date, end_date)
|
||||
|
||||
# 本周访问来源占比,每天记录一次,如果遗漏日期数据可以补充数据
|
||||
tongji_service.source_from_batch_add(start_date, end_date)
|
||||
end
|
||||
# 周用户留存率
|
||||
pre_week_user_ids = User.where(created_on: pre_week).pluck(:id).uniq
|
||||
weekly_keep_user_count = User.where(id: pre_week_user_ids).where(last_login_on: current_week).count
|
||||
weekly_keep_rate = format("%.2f", pre_week_user_ids.size > 0 ? weekly_keep_user_count.to_f / pre_week_user_ids.size : 0)
|
||||
|
||||
job_date = 1.days.ago
|
||||
daily_statistic = DailyPlatformStatistic.find_or_initialize_by(date: job_date)
|
||||
daily_statistic.weekly_keep_rate = weekly_keep_rate
|
||||
daily_statistic.save
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_week
|
||||
Time.now.beginning_of_week..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def pre_week
|
||||
# 7.days.ago.beginning_of_week..7.days.ago.beginning_of_week.end_of_week
|
||||
Time.now.prev_week..Time.now.prev_week.end_of_week
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
class DailyProjectStatisticsJob < ApplicationJob
|
||||
queue_as :cache
|
||||
|
||||
def perform
|
||||
date = (Date.today - 1.days).to_s
|
||||
daily_data_keys = $redis_cache.keys("v2-project-statistic:*-#{date}")
|
||||
daily_data_keys.each do |key|
|
||||
result = $redis_cache.hgetall(key)
|
||||
project_id = key.gsub('v2-project-statistic:', '').gsub("-#{date}", '')
|
||||
next unless Project.find_by_id(project_id).present?
|
||||
visits = result["visits"].to_i
|
||||
watchers = result["watchers"].to_i
|
||||
praises = result["praises"].to_i
|
||||
forks = result["forks"].to_i
|
||||
issues = result["issues"].to_i
|
||||
closed_issues = result["closed_issues"].to_i
|
||||
pullrequests = result["pullrequests"].to_i
|
||||
commits = result["commits"].to_i
|
||||
score = visits *1 + watchers *5 + praises * 5 + forks * 10 + issues *5 + pullrequests * 10 + commits * 5
|
||||
DailyProjectStatistic.create!(
|
||||
project_id: project_id,
|
||||
date: date,
|
||||
score: score ,
|
||||
visits: visits,
|
||||
watchers: watchers,
|
||||
praises: praises,
|
||||
forks: forks,
|
||||
issues: issues,
|
||||
closed_issues: closed_issues,
|
||||
pullrequests: pullrequests,
|
||||
commits: commits
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
class DelayExpiredIssueAndMilestoneJob < ApplicationJob
|
||||
queue_as :message
|
||||
|
||||
def perform
|
||||
Issue.where(due_date: Date.today + 1.days).find_each do |issue|
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
|
||||
end
|
||||
Version.where(effective_date: Date.today + 1.days).find_each do |version|
|
||||
SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', version.id) if Site.has_notice_menu?
|
||||
end
|
||||
Version.where(effective_date: Date.today - 1.days).find_each do |version|
|
||||
SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', version.id) if Site.has_notice_menu?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
class DelayExpiredIssueJob < ApplicationJob
|
||||
queue_as :message
|
||||
|
||||
def perform
|
||||
Issue.where(due_date: Date.today + 1.days).find_each do |issue|
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -221,6 +221,20 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectMilestoneExpired'
|
||||
milestone_id = args[0]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
return unless milestone.present? && milestone&.project.present?
|
||||
receivers = User.where(id: milestone.user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneExpired.get_message_content(receivers, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
|
||||
when 'ProjectMilestoneEarlyExpired'
|
||||
milestone_id = args[0]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
return unless milestone.present? && milestone&.project.present?
|
||||
receivers = User.where(id: milestone.user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(receivers, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
|
||||
when 'ProjectPraised'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: attachments
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(30)
|
||||
# filename :string(255) default(""), not null
|
||||
# disk_filename :string(255) default(""), not null
|
||||
# filesize :integer default("0"), not null
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default(""), not null
|
||||
# downloads :integer default("0"), not null
|
||||
# author_id :integer default("0"), not null
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer default("1")
|
||||
# is_public :integer default("1")
|
||||
# copy_from :integer
|
||||
# quotes :integer default("0")
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :datetime
|
||||
# resource_bank_id :integer
|
||||
# unified_setting :boolean default("1")
|
||||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
# memo_image :boolean default("0")
|
||||
# extra_type :integer default("0")
|
||||
# uuid :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachments_on_author_id (author_id)
|
||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
# index_attachments_on_uuid (uuid)
|
||||
#
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: attachments
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(30)
|
||||
# filename :string(255) default(""), not null
|
||||
# disk_filename :string(255) default(""), not null
|
||||
# filesize :integer default("0"), not null
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default(""), not null
|
||||
# downloads :integer default("0"), not null
|
||||
# author_id :integer default("0"), not null
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer default("1")
|
||||
# is_public :integer default("1")
|
||||
# copy_from :integer
|
||||
# quotes :integer default("0")
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :datetime
|
||||
# resource_bank_id :integer
|
||||
# unified_setting :boolean default("1")
|
||||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
# memo_image :boolean default("0")
|
||||
# extra_type :integer default("0")
|
||||
# uuid :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachments_on_author_id (author_id)
|
||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
# index_attachments_on_uuid (uuid)
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,68 +21,69 @@ module ProjectOperable
|
|||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
if self.owner.is_a?(Organization)
|
||||
case role_name
|
||||
when 'Manager'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.admin.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 新增对应的团队成员
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
|
||||
# 确保组织成员中有该用户
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
when 'Developer'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.write.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 新增对应的团队成员
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
|
||||
# 确保组织成员中有该用户
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
when 'Reporter'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.read.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 新增对应的团队成员
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
|
||||
# 确保组织成员中有该用户
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
end
|
||||
end
|
||||
member = members.create!(user_id: user_id, team_user_id: team_user&.id)
|
||||
# if self.owner.is_a?(Organization)
|
||||
# case role_name
|
||||
# when 'Manager'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.admin.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
#
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 新增对应的团队成员
|
||||
# team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
#
|
||||
# # 确保组织成员中有该用户
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# when 'Developer'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.write.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
#
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 新增对应的团队成员
|
||||
# team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
#
|
||||
# # 确保组织成员中有该用户
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# when 'Reporter'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.read.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
#
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 新增对应的团队成员
|
||||
# team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
#
|
||||
# # 确保组织成员中有该用户
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# end
|
||||
# end
|
||||
# member = members.create!(user_id: user_id, team_user_id: team_user&.id)
|
||||
member = members.create!(user_id: user_id)
|
||||
set_developer_role(member, role_name)
|
||||
end
|
||||
|
||||
|
@ -116,71 +117,71 @@ module ProjectOperable
|
|||
def change_member_role!(user_id, role)
|
||||
member = self.member(user_id)
|
||||
# 所有者为组织,并且该用户属于组织成员
|
||||
if self.owner.is_a?(Organization) && member.team_user.present?
|
||||
case role&.name
|
||||
when 'Manager'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.admin.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 更改对应的团队成员
|
||||
team_user = member.team_user
|
||||
$gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
|
||||
# 确保组织成员中有该用户
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
when 'Developer'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.write.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
$gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 更改对应的团队成员
|
||||
team_user = member.team_user
|
||||
$gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
when 'Reporter'
|
||||
# 构建相应的团队
|
||||
team = self.owner.teams.read.take
|
||||
if team.nil?
|
||||
team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
|
||||
gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
end
|
||||
|
||||
# 设置项目在团队中的访问权限
|
||||
team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
|
||||
# 更改对应的团队成员
|
||||
team_user = member.team_user
|
||||
$gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
$gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
|
||||
# 确保组织成员中有该用户
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
end
|
||||
end
|
||||
# if self.owner.is_a?(Organization) && member.team_user.present?
|
||||
# case role&.name
|
||||
# when 'Manager'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.admin.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
#
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 更改对应的团队成员
|
||||
# team_user = member.team_user
|
||||
# $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
# team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
#
|
||||
# # 确保组织成员中有该用户
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# when 'Developer'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.write.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 更改对应的团队成员
|
||||
# team_user = member.team_user
|
||||
# $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
# team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
#
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# when 'Reporter'
|
||||
# # 构建相应的团队
|
||||
# team = self.owner.teams.read.take
|
||||
# if team.nil?
|
||||
# team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
|
||||
# gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
|
||||
# team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
|
||||
# end
|
||||
#
|
||||
# # 设置项目在团队中的访问权限
|
||||
# team_project = TeamProject.build(self.user_id, team.id, self.id)
|
||||
# tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
|
||||
#
|
||||
# # 更改对应的团队成员
|
||||
# team_user = member.team_user
|
||||
# $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
|
||||
# $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
|
||||
# team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
|
||||
#
|
||||
# # 确保组织成员中有该用户
|
||||
# OrganizationUser.build(self.user_id, user_id)
|
||||
# end
|
||||
# end
|
||||
member.member_roles.last.update_attributes!(role: role)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: daily_platform_statistics
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# date :date
|
||||
# pv :integer default("0")
|
||||
# visitor :integer default("0")
|
||||
# ip :integer default("0")
|
||||
# weekly_keep_rate :float(24) default("0")
|
||||
# source_through :float(24) default("0")
|
||||
# source_link :float(24) default("0")
|
||||
# source_search :float(24) default("0")
|
||||
# source_custom :float(24) default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_daily_platform_statistics_on_date (date) UNIQUE
|
||||
#
|
||||
|
||||
class DailyPlatformStatistic < ApplicationRecord
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: daily_project_statistics
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# date :date
|
||||
# score :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# watchers :integer default("0")
|
||||
# praises :integer default("0")
|
||||
# forks :integer default("0")
|
||||
# issues :integer default("0")
|
||||
# pullrequests :integer default("0")
|
||||
# commits :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# closed_issues :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_daily_project_statistics_on_date (date)
|
||||
# index_daily_project_statistics_on_project_id (project_id)
|
||||
#
|
||||
|
||||
class DailyProjectStatistic < ApplicationRecord
|
||||
|
||||
|
||||
belongs_to :project
|
||||
end
|
|
@ -105,7 +105,7 @@ class Issue < ApplicationRecord
|
|||
scope :opened, ->{where.not(status_id: 5)}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
before_save :check_pm_and_update_due_date
|
||||
after_save :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container, :generate_uuid
|
||||
after_save :incre_or_decre_closed_issues_count, :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container, :generate_uuid
|
||||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
|
||||
|
||||
def check_pm_and_update_due_date
|
||||
|
@ -126,20 +126,35 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def is_issuely_issue?
|
||||
self.issue_classify.nil? || self.issue_classify == 'issue'
|
||||
end
|
||||
|
||||
def incre_or_decre_closed_issues_count
|
||||
if previous_changes[:status_id].present? && is_issuely_issue?
|
||||
if previous_changes[:status_id][1] == 5
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {closed_issues: 1}, self.project_id)
|
||||
end
|
||||
if previous_changes[:status_id][0] == 5
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {closed_issues: -1}, self.project_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def incre_project_common
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: 1}, self.project_id)
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: 1}, self.project_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: -1}, self.project_id)
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: -1}, self.project_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def incre_user_statistic
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: 1}, self.author_id)
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: 1}, self.author_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_user_statistic
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: -1}, self.author_id)
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: -1}, self.author_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def refresh_root_issue_count
|
||||
|
@ -150,11 +165,12 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def incre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: 1})
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: 1}) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: -1})
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: -1}) if is_issuely_issue?
|
||||
end
|
||||
end
|
||||
|
||||
def get_assign_user
|
||||
|
|
|
@ -52,6 +52,8 @@ class MessageTemplate < ApplicationRecord
|
|||
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{name}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑")
|
||||
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneEarlyExpired', sys_notice: '您创建的里程碑 <b>{name}</b> 已临近截止日期,请尽快处理.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneExpired', sys_notice: '您创建的里程碑 <b>{name}</b> 已逾期,请及时更新进度或联系项目团队.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 <b>{repository}</b> 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops')
|
||||
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我管理的仓库有里程碑完成
|
||||
class MessageTemplate::ProjectMilestoneEarlyExpired < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7))
|
||||
def self.get_message_content(receivers, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneEarlyExpired"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneEarlyExpired"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneEarlyExpired"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneEarlyExpired"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我管理的仓库有里程碑完成
|
||||
class MessageTemplate::ProjectMilestoneExpired < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestoneExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7))
|
||||
def self.get_message_content(receivers, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneExpired"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneExpired"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneExpired"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneExpired"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
|
@ -64,7 +64,7 @@
|
|||
|
||||
class Organization < Owner
|
||||
alias_attribute :name, :login
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
NAME_REGEX = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
|
||||
default_scope { where(type: "Organization") }
|
||||
|
||||
|
@ -79,7 +79,7 @@ class Organization < Owner
|
|||
|
||||
validates :login, presence: true
|
||||
validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, case_sensitive: false
|
||||
validates :login, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
validates :login, format: { with: NAME_REGEX, multiline: true, message: "只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符" }
|
||||
|
||||
delegate :description, :website, :location, :repo_admin_change_team_access, :recommend,
|
||||
:visibility, :max_repo_creation, :num_projects, :num_users, :num_teams,
|
||||
|
|
|
@ -34,6 +34,10 @@ class Page < ApplicationRecord
|
|||
PageService.genernate_user(user_id)
|
||||
end
|
||||
|
||||
before_destroy do
|
||||
PageService.close_site(user_id, identifier)
|
||||
end
|
||||
|
||||
before_save do
|
||||
if state_changed? && state == false
|
||||
PageService.close_site(user_id, identifier)
|
||||
|
@ -46,7 +50,7 @@ class Page < ApplicationRecord
|
|||
|
||||
def url
|
||||
@deploy_domain = EduSetting.find_by_name("site_page_deploy_domain").try(:value)
|
||||
"http://#{user.login}.#{@deploy_domain}/#{identifier}"
|
||||
"http://#{identifier}"
|
||||
end
|
||||
|
||||
def build_script_path
|
||||
|
|
|
@ -136,6 +136,7 @@ class Project < ApplicationRecord
|
|||
has_many :project_topic_ralates, dependent: :destroy
|
||||
has_many :project_topics, through: :project_topic_ralates
|
||||
has_many :commit_logs, dependent: :destroy
|
||||
has_many :daily_project_statistics, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
|
|
|
@ -189,7 +189,7 @@ class User < Owner
|
|||
has_many :user_clas, :dependent => :destroy
|
||||
has_many :clas, through: :user_clas
|
||||
|
||||
has_many :pages, :dependent => :destroy
|
||||
has_one :page, :dependent => :destroy
|
||||
|
||||
# Groups and active users
|
||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||
|
@ -465,7 +465,7 @@ class User < Owner
|
|||
$gitea_client.delete_users_tokens_by_username_token(self.login, e["name"], {query: {sudo: self.login} })
|
||||
}
|
||||
end
|
||||
new_result = $gitea_client.post_users_tokens_by_username(self.login, { query: {sudo: self.login}, body:{ name: self.login} })
|
||||
new_result = $gitea_client.post_users_tokens_by_username(self.login, { query: {sudo: self.login}, body:{ name: "#{self.login}-#{SecureRandom.hex(6)}", scopes: ["all"]}.to_json })
|
||||
if new_result["sha1"].present?
|
||||
update(gitea_token: new_result["sha1"])
|
||||
end
|
||||
|
@ -773,7 +773,7 @@ class User < Owner
|
|||
|
||||
def check_website_permission
|
||||
if website_permission_changed? && website_permission == false
|
||||
self.pages.update_all(state: false, state_description:"因违规使用,现关闭Page服务")
|
||||
self.page.update(state: false, state_description:"因违规使用,现关闭Page服务")
|
||||
PageService.close_site(self.id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,6 +44,8 @@ class UserTemplateMessageSetting < ApplicationRecord
|
|||
"ManageProject::Forked": true,
|
||||
"ManageProject::Milestone": true,
|
||||
"ManageProject::MilestoneCompleted": true,
|
||||
"ManageProject::MilestoneExpired": true,
|
||||
"ManageProject::MilestoneEarlyExpired": true,
|
||||
}.stringify_keys!
|
||||
end
|
||||
|
||||
|
@ -65,6 +67,8 @@ class UserTemplateMessageSetting < ApplicationRecord
|
|||
"ManageProject::Forked": false,
|
||||
"ManageProject::Milestone": false,
|
||||
"ManageProject::MilestoneCompleted": false,
|
||||
"ManageProject::MilestoneExpired": false,
|
||||
"ManageProject::MilestoneEarlyExpired": false,
|
||||
}.stringify_keys!
|
||||
end
|
||||
|
||||
|
|
|
@ -68,5 +68,7 @@ class Version < ApplicationRecord
|
|||
|
||||
def send_update_message_to_notice_system
|
||||
SendTemplateMessageJob.perform_later('ProjectMilestoneCompleted', self.id) if Site.has_notice_menu? && self.issue_percent == 1.0
|
||||
SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today + 1.days
|
||||
SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today - 1.days
|
||||
end
|
||||
end
|
||||
|
|
|
@ -76,10 +76,22 @@ class Api::V1::Issues::ListService < ApplicationService
|
|||
issues = issues.where(author_id: author_id) if author_id.present?
|
||||
|
||||
# issue_tag_ids
|
||||
issues = issues.ransack(issue_tags_value_cont: issue_tag_ids.sort!.join(',')).result unless issue_tag_ids.blank?
|
||||
if issue_tag_ids.present?
|
||||
if issue_tag_ids.include?('-1')
|
||||
issues = issues.where(issue_tags_value: nil).or(issues.where(issue_tags_value: ""))
|
||||
else
|
||||
issues = issues.ransack(issue_tags_value_cont: issue_tag_ids.sort!.join(',')).result
|
||||
end
|
||||
end
|
||||
|
||||
# milestone_id
|
||||
issues = issues.where(fixed_version_id: milestone_id) if milestone_id.present?
|
||||
if milestone_id.present?
|
||||
if milestone_id.to_i == -1
|
||||
issues = issues.where(fixed_version_id: nil)
|
||||
else
|
||||
issues = issues.where(fixed_version_id: milestone_id)
|
||||
end
|
||||
end
|
||||
|
||||
#pm相关
|
||||
# root_id# -1 查一级目录
|
||||
|
@ -102,7 +114,13 @@ class Api::V1::Issues::ListService < ApplicationService
|
|||
issues = issues.where(pm_sprint_id: pm_sprint_id) if pm_sprint_id.present?
|
||||
|
||||
# assigner_id
|
||||
issues = issues.joins(:assigners).where(users: {id: assigner_id}) if assigner_id.present?
|
||||
if assigner_id.present?
|
||||
if assigner_id.to_i == -1
|
||||
issues = issues.left_joins(:assigners).where(users: {id: nil})
|
||||
else
|
||||
issues = issues.joins(:assigners).where(users: {id: assigner_id})
|
||||
end
|
||||
end
|
||||
|
||||
# status_id
|
||||
issues = issues.where(status_id: status_id) if status_id.present? && category != 'closed'
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
class Api::V1::Projects::Actions::Runs::JobShowService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :token, :owner, :repo, :run, :job, :log_cursors
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :run, :job, :log_cursors, presence: true
|
||||
|
||||
def initialize(project, run, job, log_cursors, token = nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@run = run
|
||||
@job = job
|
||||
@log_cursors = log_cursors
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
load_gitea_data
|
||||
|
||||
@gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
logCursors: log_cursors
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_hat_client.post_repos_actions_runs_jobs_by_owner_repo_run_job(owner, repo, run, job, {query: request_params, body: request_body.to_json})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
class Api::V1::Projects::Actions::Runs::ListService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :token, :owner, :repo, :workflow, :page, :limit
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :workflow, presence: true
|
||||
|
||||
def initialize(project, params, token =nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@workflow = params[:workflow]
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
load_gitea_data
|
||||
|
||||
@gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token,
|
||||
workflow: workflow,
|
||||
page: page,
|
||||
limit: limit
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_hat_client.get_repos_actions_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, '获取流水线执行记录失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
class Api::V1::Projects::Branches::ListService < ApplicationService
|
||||
|
||||
attr_accessor :project, :token, :owner, :repo, :name, :page, :limit
|
||||
attr_accessor :project, :token, :owner, :repo, :name, :state, :page, :limit
|
||||
attr_accessor :gitea_data, :gitea_repo_data
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
|
@ -9,6 +9,7 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
|
|||
@repo = project&.identifier
|
||||
@token = token
|
||||
@name = params[:name]
|
||||
@state = params[:state]
|
||||
@page = params[:page]
|
||||
@limit = params[:limit]
|
||||
end
|
||||
|
@ -18,7 +19,6 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
|
|||
load_default_branch
|
||||
|
||||
@gitea_data[:default_branch] = @gitea_repo_data["default_branch"]
|
||||
|
||||
@gitea_data
|
||||
end
|
||||
|
||||
|
@ -30,7 +30,8 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
|
|||
limit: limit
|
||||
}
|
||||
params.merge!({name: name}) if name.present?
|
||||
|
||||
params.merge!({state: state}) if state.present?
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
class Api::V1::Projects::Branches::RestoreService < ApplicationService
|
||||
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project, :token, :owner, :repo, :branch_id, :branch_name
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :branch_id, :branch_name, presence: true
|
||||
|
||||
def initialize(project, branch_id, branch_name, token= nil)
|
||||
@project = project
|
||||
@owner = project&.owner&.login
|
||||
@repo = project&.identifier
|
||||
@branch_id = branch_id
|
||||
@branch_name = branch_name
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
excute_data_to_gitea
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
branch_id: branch_id,
|
||||
name: branch_name,
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
begin
|
||||
@gitea_data = $gitea_hat_client.post_repos_branches_restore_by_owner_repo(owner, repo, {query: request_params, body: request_body.to_json})
|
||||
rescue => e
|
||||
raise Error, '恢复分支失败!'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,37 @@
|
|||
class Api::V1::Projects::Commits::RecentService < ApplicationService
|
||||
|
||||
attr_reader :project, :page, :limit, :owner, :repo, :token
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
@owner = project&.owner&.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
param = {
|
||||
access_token: token,
|
||||
page: page,
|
||||
limit: limit
|
||||
}
|
||||
|
||||
param
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_hat_client.get_repos_recent_commits_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, "获取最近提交列表失败" unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
|
||||
end
|
|
@ -29,6 +29,6 @@ class Api::V1::Projects::CompareService < ApplicationService
|
|||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_compare_by_owner_repo_from_to(owner, repo, from, to, {query: request_params}) rescue nil
|
||||
@gitea_data = $gitea_hat_client.get_repos_compare_by_owner_repo_baseref_headref(owner, repo, to, from, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,221 @@
|
|||
module Baidu
|
||||
class TongjiService < ApplicationService
|
||||
attr_reader :client_id, :client_secret, :site_id
|
||||
# login、code、password、password_confirmation
|
||||
def initialize
|
||||
@client_id = "6dMO2kqKUaMZkBrMaUMxQSNAT49v0Mjq"
|
||||
@client_secret = "qvWqF33AOmGs1tPCgsROvis9EQCuNmd3"
|
||||
@site_id = 18657013
|
||||
end
|
||||
|
||||
def call
|
||||
|
||||
end
|
||||
|
||||
|
||||
def init_overview_data_by(start_date = nil, end_date = nil)
|
||||
start_date = Time.now.prev_year.beginning_of_year if start_date.nil?
|
||||
end_date = Time.now
|
||||
Rails.logger.info("*********开始百度统计-概览:#{start_date}-#{end_date}*********")
|
||||
sql_connection = ActiveRecord::Base.connection
|
||||
sql_connection.begin_db_transaction
|
||||
|
||||
# 如果存在数据 先清空
|
||||
# sql_connection.execute("delete from daily_platform_statistics where date between '#{start_date}' and '#{end_date}'")
|
||||
multiple_days_data = overview_multiple_days_data(start_date, end_date)
|
||||
if multiple_days_data.present?
|
||||
sql = "replace into daily_platform_statistics (date,pv,visitor,ip,created_at,updated_at) values #{multiple_days_data.join(",")}"
|
||||
sql_connection.execute(sql)
|
||||
end
|
||||
sql_connection.commit_db_transaction
|
||||
Rails.logger.info("*********结束百度统计-概览:#{start_date}-#{end_date}*********")
|
||||
end
|
||||
|
||||
def init_source_from_data_by(start_date = nil, end_date = nil)
|
||||
start_date = Time.now.prev_year.beginning_of_year if start_date.nil?
|
||||
end_date = Time.now
|
||||
Rails.logger.info("*********开始百度统计-来源:#{start_date}-#{end_date}*********")
|
||||
source_from_batch_add(start_date, end_date)
|
||||
Rails.logger.info("*********结束百度统计-来源:#{start_date}-#{end_date}*********")
|
||||
end
|
||||
|
||||
# 按日期获取来源数据
|
||||
def source_from_batch_add(start_date,end_date)
|
||||
# 补充更新开始时间的当天数据
|
||||
source_from_by_date(start_date)
|
||||
diff_days(start_date, end_date).times.each do |t|
|
||||
new_start_date = start_date + (t + 1).days
|
||||
source_from_by_date(new_start_date)
|
||||
end
|
||||
# 补充更新最后时间一天数据
|
||||
source_from_by_date(end_date)
|
||||
end
|
||||
|
||||
# 按天获取来源数据
|
||||
def source_from_by_date(start_date)
|
||||
return [] unless access_token.present? && start_date.present?
|
||||
source_from_data = api("source/all/a", start_date, start_date, "pv_count,visitor_count,ip_count")
|
||||
source_from = []
|
||||
source_from_data['items'][1].each_with_index do |source, index|
|
||||
source_from.push(((source[0].to_f / source_from_data['sum'][0][0].to_f) * 100).round(2))
|
||||
end
|
||||
daily_statistic = DailyPlatformStatistic.find_or_initialize_by(date: start_date)
|
||||
daily_statistic.source_through = source_from[0]
|
||||
daily_statistic.source_link = source_from[1]
|
||||
daily_statistic.source_search = source_from[2]
|
||||
daily_statistic.source_custom = source_from[3]
|
||||
daily_statistic.save
|
||||
end
|
||||
|
||||
def diff_days(start_date, end_date)
|
||||
(end_date.beginning_of_day.to_i - start_date.beginning_of_day.to_i) / (24 * 3600)
|
||||
end
|
||||
|
||||
def overview_batch_add(start_date, end_date)
|
||||
return [] unless access_token.present? && start_date.present? && end_date.present?
|
||||
start_date = Time.now - 1.days if start_date.strftime("%Y%m%d") == end_date.strftime("%Y%m%d")
|
||||
overview_data = api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count")
|
||||
overview_data['items'][0].each_with_index do |date, index|
|
||||
pv = overview_data['items'][1][index][0]
|
||||
visitor = overview_data['items'][1][index][1]
|
||||
ip = overview_data['items'][1][index][2]
|
||||
job_date = date[0].to_s.gsub("/", "-")
|
||||
daily_statistic = DailyPlatformStatistic.find_or_initialize_by(date: job_date)
|
||||
daily_statistic.date = job_date
|
||||
daily_statistic.pv = pv
|
||||
daily_statistic.visitor = visitor
|
||||
daily_statistic.ip = ip
|
||||
daily_statistic.save
|
||||
end
|
||||
overview_data
|
||||
end
|
||||
|
||||
def overview_multiple_days_data(start_date, end_date)
|
||||
return [] unless access_token.present? && start_date.present? && end_date.present?
|
||||
overview_data = api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count")
|
||||
data = []
|
||||
created_at = Time.now.strftime("%Y-%m-%d 00:00:00")
|
||||
overview_data['items'][0].each_with_index do |date, index|
|
||||
pv = overview_data['items'][1][index][0]
|
||||
visitor = overview_data['items'][1][index][1]
|
||||
ip = overview_data['items'][1][index][2]
|
||||
data.push("('#{date[0].to_s.gsub("/", "-")}', #{pv.to_s.gsub("--","0")}, #{visitor.to_s.gsub("--","0")}, #{ip.to_s.gsub("--","0")},\"#{created_at}\",\"#{created_at}\")")
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def code_url
|
||||
"http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=#{client_id}&redirect_uri=oob&scope=basic&display=popup"
|
||||
end
|
||||
|
||||
def oauth_url(code)
|
||||
"http://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=#{code}&client_id=#{client_id}&client_secret=#{client_secret}&redirect_uri=oob"
|
||||
end
|
||||
|
||||
def get_access_token(code)
|
||||
uri = URI.parse(oauth_url(code))
|
||||
response = Net::HTTP.get_response(uri)
|
||||
Rails.logger.info "baidu_tongji_auth response.body ===== #{response.body}"
|
||||
if response.code.to_i == 200
|
||||
data = JSON.parse(response.body)
|
||||
access_token = data['access_token']
|
||||
refresh_token = data['refresh_token']
|
||||
expires_in = data['expires_in']
|
||||
if access_token.present?
|
||||
Rails.cache.write("baidu_tongji_auth/access_token", access_token, expires_in: expires_in)
|
||||
Rails.cache.write("baidu_tongji_auth/refresh_token", refresh_token, expires_in: 1.year)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def refresh_access_token
|
||||
url = "http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token=#{refresh_token}&client_id=#{client_id}&client_secret=#{client_secret}"
|
||||
uri = URI.parse(url)
|
||||
response = Net::HTTP.get_response(uri)
|
||||
Rails.logger.info "baidu_tongji_auth response.body ===== #{response.body}"
|
||||
if response.code.to_i == 200
|
||||
data = JSON.parse(response.body)
|
||||
access_token = data['access_token']
|
||||
refresh_token = data['refresh_token']
|
||||
expires_in = data['expires_in']
|
||||
if access_token.present?
|
||||
Rails.cache.write("baidu_tongji_auth/access_token", access_token, expires_in: expires_in)
|
||||
Rails.cache.write("baidu_tongji_auth/refresh_token", refresh_token, expires_in: 1.year)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def access_token
|
||||
access_token = Rails.cache.read("baidu_tongji_auth/access_token")
|
||||
if access_token.blank? && refresh_token.present?
|
||||
refresh_access_token
|
||||
access_token = Rails.cache.read("baidu_tongji_auth/access_token")
|
||||
end
|
||||
access_token
|
||||
end
|
||||
|
||||
def refresh_token
|
||||
refresh_token = Rails.cache.read("baidu_tongji_auth/refresh_token")
|
||||
# 如果刷新token失效,access_token也重置
|
||||
if refresh_token.blank?
|
||||
Rails.cache.delete("baidu_tongji_auth/access_token")
|
||||
end
|
||||
refresh_token
|
||||
end
|
||||
|
||||
# 网站概况(趋势数据)
|
||||
def api_overview
|
||||
start_date = Time.now.beginning_of_week
|
||||
end_date = Time.now
|
||||
start_date = Time.now - 1.days if start_date.strftime("%Y%m%d") == end_date.strftime("%Y%m%d")
|
||||
api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count")
|
||||
end
|
||||
|
||||
# 网站概况(来源网站、搜索词、入口页面、受访页面)
|
||||
def api_overview_getCommonTrackRpt
|
||||
start_date = Time.now.beginning_of_week
|
||||
end_date = Time.now
|
||||
api("overview/getCommonTrackRpt", start_date, end_date, "pv_count")
|
||||
end
|
||||
|
||||
# 全部来源
|
||||
def source_from
|
||||
start_date = Time.now.beginning_of_week
|
||||
end_date = Time.now
|
||||
api("source/all/a", start_date, end_date, "pv_count,visitor_count,ip_count")
|
||||
end
|
||||
|
||||
def api(api_method, start_date, end_date, metrics = nil)
|
||||
start_date_fmt = start_date.strftime("%Y%m%d")
|
||||
end_date_fmt = end_date.strftime("%Y%m%d")
|
||||
api_url = "https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=#{access_token}&site_id=#{site_id}&method=#{api_method}&start_date=#{start_date_fmt}&end_date=#{end_date_fmt}&metrics=#{metrics}"
|
||||
data = url_http_post(api_url, {})
|
||||
data['result']
|
||||
end
|
||||
|
||||
def url_http_post(api_url, params)
|
||||
Rails.logger.info "api_url==#{api_url}"
|
||||
uri = URI.parse(api_url)
|
||||
http = Net::HTTP.new uri.host, uri.port
|
||||
http.open_timeout = 60
|
||||
http.read_timeout = 60
|
||||
if uri.scheme == 'https'
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
http.use_ssl = true
|
||||
end
|
||||
begin
|
||||
request = Net::HTTP::Post.new(uri)
|
||||
request.set_form_data(params) if params.present?
|
||||
request['Content-Type'] = 'application/json;charset=utf-8'
|
||||
# request['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'
|
||||
response = http.start { |http| http.request(request) }
|
||||
Rails.logger.info "api response.body==#{response.body}"
|
||||
JSON.parse response.body
|
||||
rescue => err
|
||||
Rails.logger.error("#############api_url:#{api_url},error:#{err.message.size}")
|
||||
# Rails.logger.error("#############api_url:#{api_url},error:#{err.message}")
|
||||
return {}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
class Cache::V2::ProjectCommonService < ApplicationService
|
||||
attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :pullrequests, :commits
|
||||
attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :closed_issues, :pullrequests, :commits
|
||||
attr_accessor :project
|
||||
|
||||
def initialize(project_id, params={})
|
||||
|
@ -13,6 +13,7 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
@praises = params[:praises]
|
||||
@forks = params[:forks]
|
||||
@issues = params[:issues]
|
||||
@closed_issues = params[:closed_issues]
|
||||
@pullrequests = params[:pullrequests]
|
||||
@commits = params[:commits]
|
||||
end
|
||||
|
@ -78,6 +79,10 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
"issues"
|
||||
end
|
||||
|
||||
def closed_issues_key
|
||||
"closed_issues"
|
||||
end
|
||||
|
||||
def pullrequests_key
|
||||
"pullrequests"
|
||||
end
|
||||
|
@ -151,6 +156,10 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
Cache::V2::ProjectRankService.call(@project_id, {issues: @issues})
|
||||
Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {issues: @issues})
|
||||
end
|
||||
if @closed_issues.present?
|
||||
$redis_cache.hincrby(project_common_key, closed_issues_key, @closed_issues)
|
||||
Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {closed_issues: @closed_issues})
|
||||
end
|
||||
if @pullrequests.present?
|
||||
$redis_cache.hincrby(project_common_key, pullrequests_key, @pullrequests)
|
||||
Cache::V2::ProjectRankService.call(@project_id, {pullrequests: @pullrequests})
|
||||
|
@ -202,6 +211,10 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
$redis_cache.hset(project_common_key, issues_key, Issue.issue_issue.where(project_id: @project_id).count)
|
||||
end
|
||||
|
||||
def reset_project_closed_issues
|
||||
$redis_cache.hset(project_common_key, closed_issues_key, Issue.issue_issue.closed.where(project_id: @project_id).count)
|
||||
end
|
||||
|
||||
def reset_project_pullrequests
|
||||
$redis_cache.hset(project_common_key, pullrequests_key, PullRequest.where(project_id: @project_id).count)
|
||||
end
|
||||
|
@ -224,6 +237,7 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
reset_project_praises
|
||||
reset_project_forks
|
||||
reset_project_issues
|
||||
reset_project_closed_issues
|
||||
reset_project_pullrequests
|
||||
reset_project_commits
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 项目日活跃度计算存储
|
||||
class Cache::V2::ProjectDateRankService < ApplicationService
|
||||
attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :pullrequests, :commits
|
||||
attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :closed_issues, :pullrequests, :commits
|
||||
attr_accessor :project_common
|
||||
|
||||
def initialize(project_id, rank_date=Date.today, params={})
|
||||
|
@ -11,6 +11,7 @@ class Cache::V2::ProjectDateRankService < ApplicationService
|
|||
@praises = params[:praises]
|
||||
@forks = params[:forks]
|
||||
@issues = params[:issues]
|
||||
@closed_issues = params[:closed_issues]
|
||||
@pullrequests = params[:pullrequests]
|
||||
@commits = params[:commits]
|
||||
end
|
||||
|
@ -57,6 +58,9 @@ class Cache::V2::ProjectDateRankService < ApplicationService
|
|||
$redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id)
|
||||
$redis_cache.hincrby(project_rank_statistic_key, "issues", @issues.to_i)
|
||||
end
|
||||
if @closed_issues.present?
|
||||
$redis_cache.hincrby(project_rank_statistic_key, "closed_issues", @closed_issues.to_i)
|
||||
end
|
||||
if @pullrequests.present?
|
||||
$redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id)
|
||||
$redis_cache.hincrby(project_rank_statistic_key, "pullrequests", @pullrequests.to_i)
|
||||
|
|
|
@ -16,6 +16,6 @@ class Getway::Cms::GetService < Getway::ClientService
|
|||
end
|
||||
|
||||
def url
|
||||
"/cms/doc/open/#{doc_id}".freeze
|
||||
"/cms/doc/open/baseInfo/#{doc_id}".freeze
|
||||
end
|
||||
end
|
|
@ -29,7 +29,7 @@ class Gitea::User::GenerateTokenService < Gitea::ClientService
|
|||
end
|
||||
|
||||
def request_params
|
||||
{ name: "#{@username}-#{token_name}" }
|
||||
{ name: "#{@username}-#{token_name}", scopes: ["all"] }
|
||||
end
|
||||
|
||||
def token_name
|
||||
|
|
|
@ -26,7 +26,7 @@ class PageService
|
|||
Rails.logger.info "################### PageService close_site #{user_id} / #{identifier}"
|
||||
user = User.find user_id
|
||||
uri = if identifier.present?
|
||||
URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=remove_dir&owner=#{user.login.downcase}/#{identifier}/")
|
||||
URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=remove_dir&owner=#{user.login.downcase}/*")
|
||||
else
|
||||
URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=remove_dir&owner=#{user.login.downcase}/")
|
||||
end
|
||||
|
|
|
@ -65,7 +65,8 @@ class Projects::CreateService < ApplicationService
|
|||
{
|
||||
hidden: !repo_is_public,
|
||||
user_id: params[:user_id],
|
||||
identifier: params[:repository_name]
|
||||
identifier: params[:repository_name],
|
||||
auto_init: params[:auto_init]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class Repositories::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def repository_params
|
||||
params.merge(project_id: project.id)
|
||||
params.merge(project_id: project.id).except(:auto_init)
|
||||
end
|
||||
|
||||
def gitea_repository_params
|
||||
|
@ -75,7 +75,7 @@ class Repositories::CreateService < ApplicationService
|
|||
name: params[:identifier],
|
||||
private: params[:hidden],
|
||||
# readme: "ReadMe",
|
||||
"auto_init": true,
|
||||
auto_init: params[:auto_init],
|
||||
# "description": "string",
|
||||
# "gitignores": "string",
|
||||
# "issue_labels": "string",
|
||||
|
@ -89,7 +89,7 @@ class Repositories::CreateService < ApplicationService
|
|||
license = project.license
|
||||
hash = hash.merge(license: license.name) if license
|
||||
hash = hash.merge(gitignores: ignore.name) if ignore
|
||||
hash = hash.merge(auto_init: true) if ignore || license
|
||||
hash = hash.merge(auto_init: true) if ignore && license
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<%
|
||||
define_admin_breadcrumbs do
|
||||
add_admin_breadcrumb('云上实验室', admins_laboratories_path)
|
||||
add_admin_breadcrumb('导航栏配置', admins_laboratories_path)
|
||||
add_admin_breadcrumb('轮播图')
|
||||
end
|
||||
%>
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<div>
|
||||
数据来源百度统计,本周 [<%= @current_week_statistic.first&.date %> / <%= @current_week_statistic.last&.date %>]
|
||||
</div>
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">日期</th>
|
||||
<th width="15%">访问量</th>
|
||||
<th width="15%">访客数</th>
|
||||
<th width="15%">IP数</th>
|
||||
<th width="15%">直接访问占比</th>
|
||||
<th width="15%">外部链接占比</th>
|
||||
<th width="15%">搜索引擎占比</th>
|
||||
<th width="20%">自定义</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if @current_week_statistic.size ==1 && @pre_week_statistic.present? %>
|
||||
<tr class="">
|
||||
<td>上周合计</td>
|
||||
<td><%= @pre_week_statistic.map(&:pv).sum %></td>
|
||||
<td><%= @pre_week_statistic.map(&:visitor).sum %></td>
|
||||
<td><%= @pre_week_statistic.map(&:ip).sum %></td>
|
||||
<td><%= (@pre_week_statistic.map(&:source_through).sum.to_f / 7).round(2) %>%</td>
|
||||
<td><%= (@pre_week_statistic.map(&:source_link).sum.to_f / 7).round(2) %>%</td>
|
||||
<td><%= (@pre_week_statistic.map(&:source_search).sum.to_f / 7).round(2) %>%</td>
|
||||
<td><%= ((@pre_week_statistic.map(&:source_custom) - [nil]).sum.to_f / 7).round(2) %>%</td>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% @current_week_statistic.each_with_index do |week, index| %>
|
||||
<tr class="">
|
||||
<td><%= week.date %> </td>
|
||||
<td><%= week.pv %></td>
|
||||
<td><%= week.visitor %></td>
|
||||
<td><%= week.ip %></td>
|
||||
<td><%= week.source_through %>%</td>
|
||||
<td><%= week.source_link %>%</td>
|
||||
<td><%= week.source_search %>%</td>
|
||||
<td><%= week.source_custom.to_f %>%</td>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr class="">
|
||||
<% current_week_size = @current_week_statistic.size %>
|
||||
<td><span style="color: #ff8200">本周合计</span></td>
|
||||
<td><span style="color: #ff8200"><%= @current_week_statistic.map(&:pv).sum %></span></td>
|
||||
<td><span style="color: #ff8200"><%= @current_week_statistic.map(&:visitor).sum %></span></td>
|
||||
<td><span style="color: #ff8200"><%= @current_week_statistic.map(&:ip).sum %></span></td>
|
||||
<td><span style="color: #ff8200"><%= (@current_week_statistic.map(&:source_through).sum.to_f / current_week_size).round(2) %>%</span></td>
|
||||
<td><span style="color: #ff8200"><%= (@current_week_statistic.map(&:source_link).sum.to_f / current_week_size).round(2) %>%</span></td>
|
||||
<td><span style="color: #ff8200"><%= (@current_week_statistic.map(&:source_search).sum.to_f / current_week_size).round(2) %>%</span></td>
|
||||
<td><span style="color: #ff8200"><%= ((@current_week_statistic.map(&:source_custom) - [nil]).sum.to_f / current_week_size).round(2) %>%</span></td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<% unless @access_token.present? && @overview_data.present? %>
|
||||
<div>
|
||||
<a href="/admins/baidu_tongji" target="_blank">1.百度统计需人工授权,点击去授权</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/admins/baidu_tongji_auth" onclick="this.href = '/admins/baidu_tongji_auth?code=' + document.getElementById('auth_code').value">2.获取百度统计授权码</a>
|
||||
<input name="code" id="auth_code" style="width: 380px" placeholder="请输入1.百度统计返回的code后,点击2.获取百度统计Token"/>
|
||||
</div>
|
||||
<% end %>
|
|
@ -0,0 +1,67 @@
|
|||
<% if @access_token.present? && @overview_data.present? %>
|
||||
<div>
|
||||
数据来源百度统计,本周 <%= @overview_data['timeSpan'] %>
|
||||
</div>
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">日期</th>
|
||||
<th width="15%">访问量</th>
|
||||
<th width="15%">访客数</th>
|
||||
<th width="15%">IP数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% pv_count = [] %>
|
||||
<% visitor_count = [] %>
|
||||
<% ip_count = [] %>
|
||||
<% @overview_data['items'][0].each_with_index do |date, index| %>
|
||||
<% pv = @overview_data['items'][1][index][0] %>
|
||||
<% visitor = @overview_data['items'][1][index][1] %>
|
||||
<% ip = @overview_data['items'][1][index][2] %>
|
||||
<tr class="">
|
||||
<td><%= date[0] %> </td>
|
||||
<td><%= pv %></td>
|
||||
<td><%= visitor %></td>
|
||||
<td><%= ip %></td>
|
||||
</td>
|
||||
</tr>
|
||||
<% pv_count.push(pv) %>
|
||||
<% visitor_count.push(visitor) %>
|
||||
<% ip_count.push(ip) %>
|
||||
<% end %>
|
||||
<tr class="">
|
||||
<td><span style="color: #ff8200">合计</span></td>
|
||||
<td><span style="color: #ff8200"><%= pv_count %></span></td>
|
||||
<td><span style="color: #ff8200"><%= visitor_count %></span></td>
|
||||
<td><span style="color: #ff8200"><%= ip_count %></span></td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="15%">直接访问占比</th>
|
||||
<th width="15%">外部链接占比</th>
|
||||
<th width="15%">搜索引擎占比</th>
|
||||
<th width="20%">自定义</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="">
|
||||
<% @source_from_data['items'][1].each_with_index do |source, index| %>
|
||||
<td><%= ((source[0].to_f / @source_from_data['sum'][0][0].to_f) * 100).round(2).to_s %>%</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<div>
|
||||
<a href="/admins/baidu_tongji" target="_blank">1.百度统计需人工授权,点击去授权</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/admins/baidu_tongji_auth" onclick="this.href = '/admins/baidu_tongji_auth?code=' + document.getElementById('auth_code').value">2.获取百度统计授权码</a>
|
||||
<input name="code" id="auth_code" style="width: 380px" placeholder="请输入1.百度统计返回的code后,点击2.获取百度统计Token"/>
|
||||
</div>
|
||||
<% end %>
|
|
@ -2,6 +2,38 @@
|
|||
<% add_admin_breadcrumb('概览', admins_path) %>
|
||||
<% end %>
|
||||
|
||||
<% cache "/admin/dashboards/#{Time.now.strftime('%Y-%m-%d')}", :expires_in => 1.days do %>
|
||||
<div class="header bg-gradient-primary pb-8 pt-md-8">
|
||||
<div class="container-fluid">
|
||||
<div class="header-body">
|
||||
<!-- Card stats -->
|
||||
<div class="row">
|
||||
<%@subject_name.each_with_index do |subject, index| %>
|
||||
<div class="col-xl-3 col-lg-6" style="padding-bottom: 15px;">
|
||||
<div class="card card-stats mb-4 mb-xl-0">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="card-title text-uppercase11 text-muted mb-0"><%=subject %></h5>
|
||||
<span class="h2 font-weight-bold mb-0"><%= @subject_data[index] %></span>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="icon icon-shape rounded-circle shadow">
|
||||
<i class="fa <%=@subject_icon[index] %>"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%end %>
|
||||
|
||||
<div class="box admin-list-container project-language-list-container">
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
|
@ -53,6 +85,7 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<%= render partial: 'admins/dashboards/baidu_tongji' %>
|
||||
</div>
|
||||
<div id="project-language-modals">
|
||||
</div>
|
|
@ -106,7 +106,7 @@
|
|||
</div>
|
||||
</br>
|
||||
<div class="form-row">
|
||||
<%= f.input :description, as: :text,label: '拒绝理由:(拒绝时请填写拒绝理由,可以为空)', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @identity_verification.description } %>
|
||||
<%= f.input :description, as: :text,label: '拒绝理由:(拒绝时请填写拒绝理由,不可以为空)', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @identity_verification.description } %>
|
||||
</div>
|
||||
<div class="form-row mt-4">
|
||||
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('疑修排行榜', admins_path) %>
|
||||
<% end %>
|
||||
|
||||
|
||||
<div class="box search-form-container user-list-form">
|
||||
<%= form_tag(admins_issues_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'issue-rank-date-form') do %>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">开始日期</span>
|
||||
<input class="form-control datetimepicker" type="text" name="begin_date" value="<%= params[:begin_date] || (Date.yesterday - 7.days).to_s%>" aria-label="选择日期">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">截止日期</span>
|
||||
<input class="form-control datetimepicker" type="text" name="end_date" value="<%= params[:end_date] || Date.yesterday.to_s%>" aria-label="选择日期">
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container issue-rank-list-container">
|
||||
<%= render partial: 'admins/issues_rank/shared/data_list', locals: { statistics: @statistics } %>
|
||||
</div>
|
||||
<script>
|
||||
$(".datetimepicker").on('change', function() {
|
||||
$("#issue-rank-date-form").submit()
|
||||
});
|
||||
$(".datetimepicker").on('change', function() {
|
||||
$("#issue-rank-date-form").submit()
|
||||
});
|
||||
$('.datetimepicker').datetimepicker({
|
||||
language: 'zh-CN', // 中文语言包
|
||||
autoclose: 1, // 选中日期后自动关闭
|
||||
format: 'yyyy-mm-dd', // 日期格式
|
||||
minView: "month", // 最小日期显示单元,这里最小显示月份界面,即可以选择到日
|
||||
todayBtn: 1, // 显示今天按钮
|
||||
todayHighlight: 1, // 显示今天高亮
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
$('.issue-rank-list-container').html("<%= j( render partial: 'admins/issues_rank/shared/data_list', locals: { statistics: @statistics } ) %>");
|
|
@ -0,0 +1,26 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">排名</th>
|
||||
<th width="20%">项目</th>
|
||||
<th width="20%">新增疑修数</th>
|
||||
<th width="20%">关闭疑修数</th>
|
||||
<th width="20%">当前疑修数量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% statistics.each_with_index do |item, index| %>
|
||||
<tr class="">
|
||||
<td><%= index + 1%></td>
|
||||
<td>
|
||||
<a target="_blank" href="<%= "/#{item&.project&.owner&.login}/#{item&.project&.identifier}"%>">
|
||||
<%= "#{item&.project&.owner&.real_name}/#{item&.project&.name}" %>
|
||||
</a>
|
||||
</td>
|
||||
<td><%= item&.issues %></td>
|
||||
<td><%= item&.closed_issues %></td>
|
||||
<td><%= item&.project&.issues&.issue_issue.count %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
|
@ -1,5 +1,5 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('云上实验室') %>
|
||||
<% add_admin_breadcrumb('导航栏配置') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container laboratory-list-form">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">新建云上实验室</h5>
|
||||
<h5 class="modal-title">新建导航栏配置</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('云上实验室', admins_laboratories_path) %>
|
||||
<% add_admin_breadcrumb('导航栏配置', admins_laboratories_path) %>
|
||||
<% add_admin_breadcrumb('单位定制') %>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -5,70 +5,34 @@
|
|||
|
||||
<div class="box search-form-container user-list-form">
|
||||
<%= form_tag(admins_projects_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'project-rank-date-form') do %>
|
||||
<div class="form-group mr-2">
|
||||
<label for="status">日期:</label>
|
||||
<% dates_array = (0..30).to_a.map { |item| [(Date.today-item.days).to_s, (Date.today-item.days).to_s] } %>
|
||||
<%= select_tag(:date, options_for_select(dates_array, params[:date]), class:"form-control",id: "project-rank-date-select")%>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">开始日期</span>
|
||||
<input class="form-control datetimepicker" type="text" name="begin_date" value="<%= params[:begin_date] || (Date.yesterday - 7.days).to_s%>" aria-label="选择日期">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">截止日期</span>
|
||||
<input class="form-control datetimepicker" type="text" name="end_date" value="<%= params[:end_date] || Date.yesterday.to_s%>" aria-label="选择日期">
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= link_to '导出', "/项目活跃度排行.xls", class: 'btn btn-primary mr-3' %>
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container project-language-list-container">
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">排名</th>
|
||||
<th width="30%">项目</th>
|
||||
<th width="10%">得分</th>
|
||||
<th width="10%">访问数</th>
|
||||
<th width="10%">关注数</th>
|
||||
<th width="10%">点赞数</th>
|
||||
<th width="10%">fork数</th>
|
||||
<th width="10%">疑修数</th>
|
||||
<th width="10%">合并请求数</th>
|
||||
<th width="10%">提交数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @date_rank.each_with_index do |item, index| %>
|
||||
<tr class="">
|
||||
<td><%= index + 1%></td>
|
||||
<% project_common = $redis_cache.hgetall("v2-project-common:#{item[0]}") %>
|
||||
<% owner_common = $redis_cache.hgetall("v2-owner-common:#{project_common["owner_id"]}")%>
|
||||
<td>
|
||||
<a href="/<%= owner_common["login"] %>/<%= project_common["identifier"]%>">
|
||||
<%= "#{owner_common["name"]}/#{project_common["name"]}" %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td><%= item[1] %></td>
|
||||
<% project_date_statistic_key = "v2-project-statistic:#{item[0]}-#{@rank_date}"%>
|
||||
<% if $redis_cache.exists(project_date_statistic_key)%>
|
||||
<% visits = $redis_cache.hget(project_date_statistic_key, "visits") %>
|
||||
<td><%= visits || 0 %></td>
|
||||
<% watchers = $redis_cache.hget(project_date_statistic_key, "watchers") %>
|
||||
<td><%= watchers || 0 %></td>
|
||||
<% praises = $redis_cache.hget(project_date_statistic_key, "praises") %>
|
||||
<td><%= praises || 0 %></td>
|
||||
<% forks = $redis_cache.hget(project_date_statistic_key, "forks") %>
|
||||
<td><%= forks || 0 %></td>
|
||||
<% issues = $redis_cache.hget(project_date_statistic_key, "issues") %>
|
||||
<td><%= issues || 0 %></td>
|
||||
<% pullrequests = $redis_cache.hget(project_date_statistic_key, "pullrequests") %>
|
||||
<td><%= pullrequests || 0 %></td>
|
||||
<% commits = $redis_cache.hget(project_date_statistic_key, "commits") %>
|
||||
<td><%= commits || 0 %></td>
|
||||
<% else %>
|
||||
<td colspan="7">暂无数据</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="box admin-list-container project-rank-list-container">
|
||||
<%= render partial: 'admins/projects_rank/shared/data_list', locals: { statistics: @statistics } %>
|
||||
</div>
|
||||
<script>
|
||||
$("#project-rank-date-select").on('change', function() {
|
||||
$(".datetimepicker").on('change', function() {
|
||||
$("#project-rank-date-form").submit()
|
||||
});
|
||||
$(".datetimepicker").on('change', function() {
|
||||
$("#project-rank-date-form").submit()
|
||||
});
|
||||
$('.datetimepicker').datetimepicker({
|
||||
language: 'zh-CN', // 中文语言包
|
||||
autoclose: 1, // 选中日期后自动关闭
|
||||
format: 'yyyy-mm-dd', // 日期格式
|
||||
minView: "month", // 最小日期显示单元,这里最小显示月份界面,即可以选择到日
|
||||
todayBtn: 1, // 显示今天按钮
|
||||
todayHighlight: 1, // 显示今天高亮
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
$('.project-rank-list-container').html("<%= j( render partial: 'admins/projects_rank/shared/data_list', locals: { statistics: @statistics } ) %>");
|
|
@ -0,0 +1,37 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">排名</th>
|
||||
<th width="30%">项目</th>
|
||||
<th width="10%">得分</th>
|
||||
<th width="10%"><%= sort_tag('访问数', name: 'visits', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('关注数', name: 'watchers', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('点赞数', name: 'praises', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('fork数', name: 'forks', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('疑修数', name: 'issues', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('合并请求数', name: 'pullrequests', path: admins_projects_rank_index_path) %></th>
|
||||
<th width="10%"><%= sort_tag('提交数', name: 'commits', path: admins_projects_rank_index_path) %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% statistics.each_with_index do |item, index| %>
|
||||
<tr class="">
|
||||
<td><%= index + 1%></td>
|
||||
<td>
|
||||
<a target="_blank" href="<%= "/#{item&.project&.owner&.login}/#{item&.project&.identifier}"%>">
|
||||
<%= "#{item&.project&.owner&.real_name}/#{item&.project&.name}" %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td><%= item&.score %></td>
|
||||
<td><%= item&.visits %></td>
|
||||
<td><%= item&.watchers %></td>
|
||||
<td><%= item&.praises %></td>
|
||||
<td><%= item&.forks %></td>
|
||||
<td><%= item&.issues %></td>
|
||||
<td><%= item&.pullrequests %></td>
|
||||
<td><%= item&.commits %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
|
@ -11,13 +11,13 @@
|
|||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
系统保留关键词标识 <span class="ml10 color-orange mr20">*</span>
|
||||
禁用词标识 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :identifier,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
系统保留关键词描述
|
||||
禁用词描述
|
||||
</label>
|
||||
<%= p.text_area :description,class: "form-control",placeholder: ""%>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('系统保留关键词') %>
|
||||
<% add_admin_breadcrumb('禁用词管理') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container project-list-form">
|
||||
|
|
|
@ -13,13 +13,7 @@
|
|||
|
||||
<!-- Sidebar Links -->
|
||||
<ul class="list-unstyled components">
|
||||
<li><%= sidebar_item(admins_path, '概览', icon: 'dashboard', controller: 'admins-dashboards') %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#rank-submenu', '排行榜', icon: 'calendar') do %>
|
||||
<li><%= sidebar_item(admins_users_rank_index_path, '用户排行榜', icon: 'user', controller: 'admins-users_rank') %></li>
|
||||
<li><%= sidebar_item(admins_projects_rank_index_path, '项目排行榜', icon: 'database', controller: 'admins-projects_rank') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
<li><%= sidebar_item(admins_path, '数据概览', icon: 'dashboard', controller: 'admins-dashboards') %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
|
||||
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
|
||||
|
@ -27,15 +21,23 @@
|
|||
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<%= sidebar_item_group('#pages-submenu', '站点管理', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_identity_verifications_path, '身份审核列表', icon: 'user', controller: 'admins-identity_verifications') %></li>
|
||||
<li><%= sidebar_item(admins_site_pages_path, '用户站点列表', icon: 'sitemap', controller: 'admins-site_pages') %></li>
|
||||
<li><%= sidebar_item(admins_page_themes_path, '站点主题配置', icon: 'cogs', controller: 'admins-page_themes') %></li>
|
||||
|
||||
<%= sidebar_item_group('#setting-submenu', '用户支持', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
||||
<li><%= sidebar_item(admins_nps_path, 'NPS用户调研', icon: 'question-circle', controller: 'admins-nps') %></li>
|
||||
<li><%= sidebar_item(admins_feedbacks_path, '用户反馈', icon: 'question-circle', controller: 'admins-feedbacks') %></li>
|
||||
<li><%= sidebar_item(admins_system_notifications_path, '系统公告配置', icon: 'bell', controller: 'admins-system_notifications') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
<li><%= sidebar_item(admins_laboratories_path, '导航栏配置', icon: 'cloud', controller: 'admins-laboratories') %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-system', '开发者配置', icon: 'wrench') do %>
|
||||
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li>
|
||||
<li><%= sidebar_item(admins_edu_settings_path, '全局变量配置', icon: 'pencil-square', controller: 'admins-edu_settings') %></li>
|
||||
<li><%= sidebar_item(admins_message_templates_path, '消息模版配置', icon: 'folder', controller: 'admins-message_templates') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
<li><%= sidebar_item(admins_reversed_keywords_path, '禁用词管理', icon: 'key', controller: 'admins-reversed_keywords') %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#projects-submenu', '开源项目', icon: 'database') do %>
|
||||
<li><%= sidebar_item(admins_projects_path, '项目列表', icon: 'database', controller: 'admins-projects') %></li>
|
||||
|
@ -45,9 +47,6 @@
|
|||
<li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li>
|
||||
<li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-index', '首页配置', icon: 'file') do %>
|
||||
<li><%= sidebar_item(admins_topic_banners_path, 'banner管理', icon: 'image', controller: 'admins-topic-banners') %></li>
|
||||
|
@ -71,25 +70,27 @@
|
|||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
||||
<li><%= sidebar_item(admins_nps_path, 'NPS用户调研', icon: 'question-circle', controller: 'admins-nps') %></li>
|
||||
<li><%= sidebar_item(admins_feedbacks_path, '用户反馈', icon: 'question-circle', controller: 'admins-feedbacks') %></li>
|
||||
<%= sidebar_item_group('#pages-submenu', '个人站点管理', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_identity_verifications_path, '身份审核列表', icon: 'user', controller: 'admins-identity_verifications') %></li>
|
||||
<li><%= sidebar_item(admins_site_pages_path, '用户站点列表', icon: 'sitemap', controller: 'admins-site_pages') %></li>
|
||||
<li><%= sidebar_item(admins_page_themes_path, '站点主题配置', icon: 'cogs', controller: 'admins-page_themes') %></li>
|
||||
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %>
|
||||
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li>
|
||||
<li><%= sidebar_item(admins_edu_settings_path, '全局变量配置', icon: 'pencil-square', controller: 'admins-edu_settings') %></li>
|
||||
<li><%= sidebar_item(admins_system_notifications_path, '系统通知配置', icon: 'bell', controller: 'admins-system_notifications') %></li>
|
||||
<li><%= sidebar_item(admins_message_templates_path, '消息模版配置', icon: 'folder', controller: 'admins-message_templates') %></li>
|
||||
<%= sidebar_item_group('#rank-submenu', '活跃度排行', icon: 'calendar') do %>
|
||||
<li><%= sidebar_item(admins_users_rank_index_path, '用户活跃度排行', icon: 'user', controller: 'admins-users_rank') %></li>
|
||||
<li><%= sidebar_item(admins_projects_rank_index_path, '项目活跃度排行', icon: 'database', controller: 'admins-projects_rank') %></li>
|
||||
<li><%= sidebar_item(admins_issues_rank_index_path, '疑修活跃度排行', icon: 'calendar', controller: 'admins-issues_rank') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<%= render_admin_statistics_item %>
|
||||
|
||||
<li>
|
||||
<%= sidebar_item('/admins/sidekiq', '定时任务', icon: 'bell', controller: 'root') %>
|
||||
</li>
|
||||
|
||||
<%= render_admin_statistics_item %>
|
||||
|
||||
<li><%= sidebar_item('/', '返回主站', icon: 'sign-out', controller: 'root') %></li>
|
||||
</ul>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="box search-form-container project-list-form">
|
||||
<div style="line-height: 38px;" class="flex-1"><%= type == "create" ? "新建" : "编辑" %>系统通知</div>
|
||||
<div style="line-height: 38px;" class="flex-1"><%= type == "create" ? "新建" : "编辑" %>系统公告</div>
|
||||
<%= link_to "返回", admins_system_notifications_path, class: "btn btn-default pull-right" %>
|
||||
</div>
|
||||
|
||||
|
@ -8,36 +8,36 @@
|
|||
<div class="form-group">
|
||||
<label>
|
||||
<span class="color-grey-6 pt10">
|
||||
系统通知标题
|
||||
系统公告标题
|
||||
<span class="ml10 color-orange mr20">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mt-10">
|
||||
<%= p.text_field :subject, class: "form-control input-lg", placeholder: "请输入系统通知标题" %>
|
||||
<%= p.text_field :subject, class: "form-control input-lg", placeholder: "请输入系统公告标题" %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<span class="color-grey-6 pt10">
|
||||
系统通知副标题
|
||||
系统公告副标题
|
||||
<span class="ml10 color-orange mr20">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mt-10">
|
||||
<%= p.text_field :sub_subject, class: "form-control input-lg", placeholder: "请输入系统通知副标题" %>
|
||||
<%= p.text_field :sub_subject, class: "form-control input-lg", placeholder: "请输入系统公告副标题" %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<span class="color-grey-6 pt10">
|
||||
系统通知正文
|
||||
系统公告正文
|
||||
<span class="ml10 color-orange mr20">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="pl-0 my-3 setting-item-body" id="system-notification-content-editor">
|
||||
<%= p.text_area :content, class:"form-control", style: 'display: none;', rows: "10", cols: "20", placeholer: "请输入系统通知正文" %>
|
||||
<%= p.text_area :content, class:"form-control", style: 'display: none;', rows: "10", cols: "20", placeholer: "请输入系统公告正文" %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('系统通知模版') %>
|
||||
<% add_admin_breadcrumb('系统公告配置') %>
|
||||
<% end %>
|
||||
|
||||
<div id="admins-system-notification-content">
|
||||
<div class="box search-form-container project-list-form">
|
||||
<%= form_tag(admins_system_notifications_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '系统通知标题检索') %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '系统公告标题检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||
<% end %>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<td><%= index + 1%></td>
|
||||
<% owner_common = $redis_cache.hgetall("v2-owner-common:#{item[0]}")%>
|
||||
<td>
|
||||
<a href="/<%= owner_common["login"] %>">
|
||||
<a target="_blank" href="/<%= owner_common["login"] %>">
|
||||
<%= owner_common["name"] %>
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @data.size
|
||||
json.files @data.each do |file|
|
||||
json.name file["Name"]
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
json.total_data @result_object[:total_data].to_i
|
||||
json.runs @result_object[:data]["Runs"].each do |run|
|
||||
json.workflow run["WorkflowID"]
|
||||
json.index run["Index"]
|
||||
json.title run["Title"]
|
||||
json.trigger_user do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(run['TriggerUser']), name: run['TriggerUser']['Name'] }
|
||||
end
|
||||
|
||||
if run["Ref"].starts_with?("refs/tags")
|
||||
json.ref run["Ref"].gsub!("/refs/tags/", "")
|
||||
else
|
||||
json.ref run["Ref"].gsub!("refs/heads/", "")
|
||||
end
|
||||
|
||||
json.status run["Status"]
|
||||
json.time_ago time_from_now(run["Stopped"])
|
||||
json.holding_time run["Stopped"]-run["Started"]
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
json.state do
|
||||
json.run do
|
||||
json.title @result_object["state"]["run"]["title"]
|
||||
json.status @result_object["state"]["run"]["status"]
|
||||
json.done @result_object["state"]["run"]["done"]
|
||||
json.jobs @result_object["state"]["run"]["jobs"]
|
||||
json.current_job do
|
||||
json.title @result_object["state"]["currentJob"]["title"]
|
||||
json.detail @result_object["state"]["currentJob"]["detail"]
|
||||
json.steps @result_object["state"]["currentJob"]["steps"]
|
||||
end
|
||||
end
|
||||
end
|
||||
json.logs do
|
||||
json.steps_log @result_object["logs"]["stepsLog"]
|
||||
end
|
|
@ -23,4 +23,14 @@ json.commit_time branch['commit']['timestamp']
|
|||
json.default_branch default_branch || nil
|
||||
json.http_url render_http_url(@project)
|
||||
json.zip_url render_zip_url(@owner, @project.repository, branch['name'])
|
||||
json.tar_url render_tar_url(@owner, @project.repository, branch['name'])
|
||||
json.tar_url render_tar_url(@owner, @project.repository, branch['name'])
|
||||
json.branch_id branch['id']
|
||||
json.is_deleted branch['is_deleted']
|
||||
json.deleted_unix branch['deleted_unix']
|
||||
json.deleted_by do
|
||||
if branch['is_deleted']
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['deleted_by']), name: branch['deleted_by']['name'] }
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
json.total_count @result_object[:total_data].to_i
|
||||
json.commits @result_object[:data].each do |commit|
|
||||
json.sha commit['sha']
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] }
|
||||
end
|
||||
json.commit_message commit['commit']['message']
|
||||
json.parent_shas commit['parents'].map{|x|x['sha']}
|
||||
end
|
|
@ -14,5 +14,9 @@ json.commits @result_object['Commits'] do |commit|
|
|||
json.parent_shas commit['Sha']['ParentShas']
|
||||
end
|
||||
json.diff do
|
||||
json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff']
|
||||
if @result_object['Diff'].present?
|
||||
json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff']
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
json.total_count @result_object['total_count']
|
||||
json.sha @result_object['sha']
|
||||
json.entries @result_object['tree'].each do |entry|
|
||||
json.total_count @result_object[:data]['total_count'].to_i
|
||||
json.sha @result_object[:data]['sha']
|
||||
json.entries @result_object[:data]['tree'].each do |entry|
|
||||
json.name entry['path']
|
||||
json.mode entry['mode']
|
||||
json.type entry['type'] === 'blob' ? 'file' : 'dir'
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
json.id org_user.id
|
||||
json.id user&.id
|
||||
json.user do
|
||||
json.partial! "organizations/user_detail", user: org_user.user
|
||||
json.partial! "organizations/user_detail", user: user
|
||||
end
|
||||
|
||||
json.team_names org_user.teams.pluck(:nickname)
|
||||
json.created_at org_user.created_at.strftime("%Y-%m-%d")
|
||||
json.team_names user.teams.where("teams.organization_id=?", organization.id).pluck(:nickname)
|
||||
join_date = if user.organization_users.find_by(:organization_id => organization.id).present?
|
||||
user.organization_users.find_by(:organization_id => organization.id).created_at.strftime("%Y-%m-%d")
|
||||
elsif user.members.joins(:project).find_by(project: organization.projects).present?
|
||||
user.members.joins(:project).find_by(project: organization.projects).created_on.strftime("%Y-%m-%d")
|
||||
else
|
||||
user.created_on.strftime("%Y-%m-%d")
|
||||
end
|
||||
json.created_at join_date
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
json.total_count @organization_users.total_count
|
||||
json.organization_users @organization_users do |org_user|
|
||||
next if org_user.user.blank?
|
||||
json.partial! "detail", org_user: org_user, organization: @organization
|
||||
json.total_count @users.total_count
|
||||
json.organization_users @users do |user|
|
||||
next if user.blank?
|
||||
json.partial! "detail", user: user, organization: @organization
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
json.empty @result[:repo]["empty"]
|
||||
json.content @project.content
|
||||
json.website @project.website
|
||||
json.lesson_url @project.lesson_url
|
||||
|
@ -19,6 +20,7 @@ json.version_releasesed_count @project.releases_size(@user.try(:id), "released")
|
|||
json.permission render_permission(@user, @project)
|
||||
json.mirror_url @project&.repository.remote_mirror_url
|
||||
json.mirror @project&.repository.mirror_url.present?
|
||||
json.web_site @project.page.try(:identifier)
|
||||
json.type @project.numerical_for_project_type
|
||||
json.open_devops @project.open_devops?
|
||||
json.topics @project.project_topics.each do |topic|
|
||||
|
|
|
@ -794,6 +794,8 @@ Rails.application.routes.draw do
|
|||
namespace :admins do
|
||||
mount Sidekiq::Web => '/sidekiq'
|
||||
get '/', to: 'dashboards#index'
|
||||
get '/baidu_tongji', to: 'dashboards#baidu_tongji'
|
||||
get '/baidu_tongji_auth', to: 'dashboards#baidu_tongji_auth'
|
||||
namespace :topic do
|
||||
resources :activity_forums
|
||||
resources :banners
|
||||
|
@ -819,6 +821,7 @@ Rails.application.routes.draw do
|
|||
resources :identity_verifications
|
||||
resources :site_pages
|
||||
resources :page_themes
|
||||
resources :issues_rank, only: [:index]
|
||||
resources :projects_rank, only: [:index]
|
||||
resources :sites
|
||||
resources :edu_settings
|
||||
|
|
|
@ -108,6 +108,15 @@ defaults format: :json do
|
|||
|
||||
# projects文件夹下的
|
||||
scope module: :projects do
|
||||
resources :actions, module: 'actions' do
|
||||
collection do
|
||||
post :disable
|
||||
post :enable
|
||||
resources :runs, only: [:index] do
|
||||
post '/jobs/:job', to: 'runs#job_show'
|
||||
end
|
||||
end
|
||||
end
|
||||
resources :pulls, module: 'pulls' do
|
||||
resources :versions, only: [:index] do
|
||||
member do
|
||||
|
@ -128,6 +137,7 @@ defaults format: :json do
|
|||
resources :branches, param: :name, only:[:index, :create, :destroy] do
|
||||
collection do
|
||||
get :all
|
||||
post :restore
|
||||
patch :update_default_branch
|
||||
end
|
||||
end
|
||||
|
@ -137,7 +147,11 @@ defaults format: :json do
|
|||
delete 'tags/*name', to: "tags#destroy", via: :all
|
||||
get 'tags/*name', to: "tags#show", via: :all
|
||||
|
||||
resources :commits, only: [:index]
|
||||
resources :commits, only: [:index] do
|
||||
collection do
|
||||
get :recent
|
||||
end
|
||||
end
|
||||
resources :code_stats, only: [:index]
|
||||
resources :contributors, only: [:index] do
|
||||
collection do
|
||||
|
|
|
@ -5,5 +5,15 @@ sync_gitea_repo_update_time:
|
|||
|
||||
delay_expired_issue:
|
||||
cron: "0 0 * * *"
|
||||
class: "DelayExpiredIssueJob"
|
||||
class: "DelayExpiredIssueAndMilestoneJob"
|
||||
queue: message
|
||||
|
||||
create_daily_project_statistics:
|
||||
cron: "0 1 * * *"
|
||||
class: "DailyProjectStatisticsJob"
|
||||
queue: cache
|
||||
|
||||
daily_platform_statistics:
|
||||
cron: "0 1 * * *"
|
||||
class: "DailyPlatformStatisticsJob"
|
||||
queue: default
|
|
@ -0,0 +1,19 @@
|
|||
class CreateDailyProjectStatistics < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :daily_project_statistics do |t|
|
||||
t.references :project
|
||||
t.date :date
|
||||
t.index :date
|
||||
t.integer :score, default: 0
|
||||
t.integer :visits, default: 0
|
||||
t.integer :watchers, default: 0
|
||||
t.integer :praises, default: 0
|
||||
t.integer :forks, default: 0
|
||||
t.integer :issues, default: 0
|
||||
t.integer :pullrequests, default: 0
|
||||
t.integer :commits, default: 0
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddIndexUuidToAttachments < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :attachments, :uuid
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
class CreateDailyPlatformStatistics < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :daily_platform_statistics do |t|
|
||||
t.date :date
|
||||
t.index :date, unique: true
|
||||
t.bigint :pv, default: 0
|
||||
t.bigint :visitor, default: 0
|
||||
t.bigint :ip, default: 0
|
||||
t.float :weekly_keep_rate, default: 0
|
||||
t.float :source_through, default: 0
|
||||
t.float :source_link, default: 0
|
||||
t.float :source_search, default: 0
|
||||
t.float :source_custom, default: 0
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddClosedIssuesToDailyProjectStatistics < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :daily_project_statistics, :closed_issues, :integer, default: 0
|
||||
end
|
||||
end
|
|
@ -68,7 +68,8 @@ namespace :batch_add_issues do
|
|||
UserExtension.create!(user_id: user.id)
|
||||
puts "import_user batch success: phone #{phone} email: #{email}"
|
||||
end
|
||||
|
||||
title = issue['title']
|
||||
title = title[0..190] if title.size > 190
|
||||
issue_params = {
|
||||
:status_id => issue_status,
|
||||
:priority_id => priority,
|
||||
|
@ -76,7 +77,7 @@ namespace :batch_add_issues do
|
|||
# :branch_name,
|
||||
# :start_date,
|
||||
# :due_date,
|
||||
:subject => issue['title'],
|
||||
:subject => title,
|
||||
:description => issue['body'],
|
||||
# :blockchain_token_num,
|
||||
:issue_tag_ids => [],
|
||||
|
@ -127,4 +128,152 @@ namespace :batch_add_issues do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
task github: :environment do
|
||||
project_id = ENV['project_id']
|
||||
puts "project_id=================#{project_id}"
|
||||
next if project_id.blank?
|
||||
project = Project.find project_id
|
||||
count = 0
|
||||
if ENV['count'].present?
|
||||
count = ENV['count'].to_i
|
||||
end
|
||||
|
||||
total_count = 3000
|
||||
puts "total_count==========#{total_count}"
|
||||
if total_count > 100
|
||||
total_page = (total_count / 100) + 1
|
||||
total_page.times do |i|
|
||||
sleep 1.seconds
|
||||
add_github_issues_to_project(project, i + 1 + count)
|
||||
end
|
||||
else
|
||||
add_github_issues_to_project(project, 1)
|
||||
end
|
||||
end
|
||||
|
||||
def add_github_issues_to_project(project,page)
|
||||
# curl -X GET --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/repos/mindspore/mindspore/issues?access_token=5ccebd935915fb6cfcae634b161047a2&state=open&sort=created&direction=desc&page=1&per_page=10'
|
||||
# api_url = "https://gitee.com/api/v5/repos/mindspore/mindspore/issues?access_token=96a637aa055f15056e77e3cf11a67525&state=all&sort=created&direction=desc&page=#{page}&per_page=100"
|
||||
api_url = "https://api.github.com/repos/OpenXiangShan/XiangShan/issues?sort=created&direction=desc&per_page=100&state=all&page=#{page}"
|
||||
uri = URI.parse(api_url)
|
||||
# response = Net::HTTP.get_response(uri)
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
http.use_ssl = true
|
||||
response = http.send_request('GET', uri, nil, {'Content-Type' => 'application/json','authorization' => "Bearer #{ENV['token']}"})
|
||||
|
||||
puts "gitee api response.code ===== #{response.code}"
|
||||
lists = JSON.parse(response.body)
|
||||
puts "lists.size =====#{lists.size}"
|
||||
|
||||
# "1" => "新增",
|
||||
# "2" => "正在解决",
|
||||
# "3" => "已解决",
|
||||
# "5" => "关闭",
|
||||
# "6" => "拒绝"
|
||||
# Issue的状态: open(开启的), progressing(进行中), closed(关闭的), rejected(拒绝的)。 默认: open
|
||||
lists.each do |issue|
|
||||
next if issue['pull_request'].present?
|
||||
title = issue['title']
|
||||
title = title[0..190] if title.size > 190
|
||||
created_issue = Issue.find_by(project_id: project.id, subject: title)
|
||||
issue_created_at = issue['created_at']
|
||||
issue_updated_at = issue['updated_at']
|
||||
unless created_issue.present?
|
||||
priority = [1, 2, 3, 4].include?(issue['priority'].to_i) ? issue['priority'].to_i : 2
|
||||
issue_status = ["", "open", "progressing", "", "", "closed", "rejected"].index(issue['state'])
|
||||
issue_status = 1 if issue_status.nil?
|
||||
user_login = issue['user']['login']
|
||||
user_login = user_login[0..20] if user_login.size > 29
|
||||
username = "gh-#{user_login}"
|
||||
user = User.find_by(login: username)
|
||||
unless user.present?
|
||||
email = "#{username}@gitlink.org.cn"
|
||||
phone = ""
|
||||
password = "a12345678"
|
||||
user = User.new(nickname: username, login: username, mail: email, password: password, type: 'User', phone: phone)
|
||||
interactor = Gitea::RegisterInteractor.call({ username: username, email: email, password: password })
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
user.created_on = issue_created_at
|
||||
user.updated_on = issue_created_at
|
||||
user.is_test = true
|
||||
user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
puts "import_user batch success: phone #{phone} email: #{email}"
|
||||
end
|
||||
issue_tags_value = []
|
||||
if issue['labels'].present?
|
||||
issue['labels'].each do |tag|
|
||||
label = project.issue_tags.find_or_create_by!(name: tag['name'], description: tag['description'], color: "##{tag['color']}")
|
||||
issue_tags_value.push(label.id)
|
||||
end
|
||||
end
|
||||
|
||||
issue_params = {
|
||||
:status_id => issue_status,
|
||||
:priority_id => priority,
|
||||
# :milestone_id,
|
||||
# :branch_name,
|
||||
# :start_date,
|
||||
# :due_date,
|
||||
:subject => title,
|
||||
:description => issue['body'],
|
||||
# :blockchain_token_num,
|
||||
:issue_tag_ids => issue_tags_value,
|
||||
:assigner_ids => [],
|
||||
:attachment_ids => [],
|
||||
:receivers_login => []
|
||||
}
|
||||
created_issue = Api::V1::Issues::CreateService.call(project, issue_params, user)
|
||||
end
|
||||
|
||||
issue_number = issue['number']
|
||||
sleep 1.seconds
|
||||
# comment_api_url = "https://gitee.com/api/v5/repos/mindspore/mindspore/issues/#{issue_number}/comments?access_token=96a637aa055f15056e77e3cf11a67525&page=1&per_page=100&order=asc"
|
||||
comment_api_url = "https://api.github.com/repos/OpenXiangShan/XiangShan/issues/#{issue_number}/comments?page=1&per_page=100"
|
||||
comment_uri = URI.parse(comment_api_url)
|
||||
# comment_response = Net::HTTP.get_response(comment_uri)
|
||||
http = Net::HTTP.new(comment_uri.hostname, comment_uri.port)
|
||||
http.use_ssl = true
|
||||
comment_response = http.send_request('GET', comment_uri, nil, {'Content-Type' => 'application/json','authorization' => "Bearer #{ENV['token']}"})
|
||||
comment_lists = JSON.parse(comment_response.body)
|
||||
|
||||
comment_lists.each do |comment|
|
||||
next if Journal.find_by(journalized_id: created_issue.id, journalized_type: 'Issue', notes: comment['body']).present?
|
||||
user_login = comment['user']['login']
|
||||
next if user_login.size >29
|
||||
comment_created_at = comment['created_at']
|
||||
comment_updated_at = comment['updated_at']
|
||||
username = "gh-#{user_login}"
|
||||
comment_user = User.find_by(login: username)
|
||||
unless comment_user.present?
|
||||
email = "#{username}@gitlink.org.cn"
|
||||
phone = ""
|
||||
password = "a12345678"
|
||||
comment_user = User.new(nickname: username, login: username, mail: email, password: password, type: 'User', phone: phone)
|
||||
interactor = Gitea::RegisterInteractor.call({ username: username, email: email, password: password })
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||
comment_user.gitea_token = result['sha1']
|
||||
comment_user.gitea_uid = gitea_user[:body]['id']
|
||||
comment_user.created_on = comment_created_at
|
||||
comment_user.updated_on = comment_created_at
|
||||
comment_user.save!
|
||||
UserExtension.create!(user_id: comment_user.id)
|
||||
end
|
||||
|
||||
journal_params = {:notes => comment['body'],
|
||||
:attachment_ids => [],
|
||||
:receivers_login => []}
|
||||
|
||||
object_result = Api::V1::Issues::Journals::CreateService.call(created_issue, journal_params, comment_user)
|
||||
object_result.update_columns(created_on: comment_created_at, updated_on: comment_updated_at)
|
||||
created_issue.update_columns(created_on: issue_created_at, updated_on: issue_updated_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe DailyPlatformStatistic, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue