diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 26137b584..fe00088b5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -29,7 +29,7 @@ class ProjectsController < ApplicationController menu_item :share, :only => :share before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise, - :view_homework_attaches,:join_project, :project_home, :training_execute] + :view_homework_attaches,:join_project, :project_home, :training_execute, :training_task_status] before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course] before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches] before_filter :require_admin, :only => [ :copy, :unarchive, :destroy, :calendar] @@ -815,16 +815,29 @@ class ProjectsController < ApplicationController redirect_to admin_projects_url(:status => params[:status]) end + # 弹框提醒: + # 自己不能参加自己的实训项目 + # 没有建立版本库的项目不能开启实训 + # 已经实训过直接跳入 + # + def training_chiled_project_exec + respond_to do |format| + format.js + end + end + + # training_status: 默认为0; 1代表实训项目; 2:代表实训子项目 def training_project_execute jobName = "#{@project.id}" pipeLine = "#{Base64.encode64(@project.script)}" uri = URI("http://123.59.135.74:9999/jenkins-exec/api/createJob") res = Net::HTTP.post_form(uri, {jobName: jobName, pipeLine: pipeLine}).body - if res.code == 0 - @project.update_attribute(:training_status, 1) - else - flash[:notice] = "启动失败" - end + # if res.code == 0 + @project.update_attribute(:training_status, 1) + @notice = "实训开启成功" + # else + # flash[:notice] = "启动失败" + # end end def training_project_update @@ -832,42 +845,150 @@ class ProjectsController < ApplicationController pipeLine = "#{Base64.encode64(@project.script)}" uri = URI("http://123.59.135.74:9999/jenkins-exec/api/updateJob") res = Net::HTTP.post_form(uri, {jobName: jobName, pipeLine: pipeLine}).body - if res.code == 0 - @project.update_attribute(:training_status, 1) - else - flash[:notice] = "启动失败" - end + @notice = "重新开启实训成功" end + # TrainintTask.status 0:评测中 1:评测成功 2:评测惊醒中 def task_execute taskId = params[:training_task_id] jobName = @project.forked_from_project_id - params = {:jobName => "#{jobName}", :taskId => "#{taskId}"} - uri = URI.parse("http://123.59.135.74:9999/jenkins-exec/api/buildJob") - begin - task = TrainingTask.find(taskId) - respond_message = uri_exec uri, params - # status 标注第几步已完成,0表示未完成 - task.update_attribute(:status, position) - return - rescue - @message = "失败,请联系系统管理员" + @training_task = TrainingTask.find(taskId) + if @training_task.status == 0 + params = {:jobName => "#{jobName}", :taskId => "#{taskId}"} + uri = URI.parse("http://123.59.135.74:9999/jenkins-exec/api/buildJob") + begin + respond_message = uri_exec uri, params + @training_task.update_attribute(:status, 2) + return + rescue + @message = "失败,请联系系统管理员" + end end end def uri_exec uri, params - Net::HTTP.post_form(uri, {jobName: '222e', pipeLine: base64}).body - res = Net::HTTP.post_form(uri, params).body end - # 需要传Jobname(项目ID),Task ID, Stage - def training_task_status - task_id = params[:task_id] - stage = params[:stage].to_i - training_task = TrainingTask.find(task_id) - training_task.update_attribute(:status => stage) + # 开启实训项目,学生会fork一个项目并自动发送任务 + def training_project_extend + @project = Project.find(params[:id]) + @repository = Repository.where("project_id =? and type =?", @project.id, "Repository::Gitlab") + # 如果当前用户已经fork过该项目,不会新fork项目,则跳至已fork的项 + unless has_forked?(@project, User.current) + project = project_from_current_project(@project.id, User.current.id) + redirect_to project_path(project) + else + ActiveRecord::Base.transaction do + g = Gitlab.client + if User.current.gid.nil? + s = Trustie::Gitlab::Sync.new + s.sync_user(User.current) + end + gproject = g.fork(@project.gpid, User.current.gid) + if gproject + new_training_project = copy_project_and_module(@project, gproject) + forked_count = @project.forked_count.to_i + 1 + @project.update_attributes(:forked_count => forked_count) + # 发布实训任务,只发布实训任务的第一个 + publish_training_tasks(@project.id, new_training_project.id, 1) + end + end + end + end + # 需要传Task ID + # 判断任务是否完成 + # 如果完成则发送下一个任务直到任务结束 + # TrainingTask.status 1 成功,2 失败 + def training_task_status + status = params[:code].to_i + task_id = params[:taskId] + stage = params[:stage].to_i + @training_task = TrainingTask.find(task_id) + original_project_id = Project.find(@training_task.project_id).try(:forked_from_project_id) + original_project = Project.find(original_project_id) + original_tasks_count = original_project.training_tasks.count + position = @training_task.try(:position) + 1 + # 测试,默认成功 + if position <= original_tasks_count + # 继续下一个任务 + publish_training_tasks original_project_id, @training_task.project_id, position + @training_task.update_attribute(:status, 1) + end + end + + # 实训开启成功后,发布第一个任务 + # REDO:失败后提醒用户,及相关处理 + def publish_training_tasks original_project_id, new_training_project_id, position + original_task = TrainingTask.where(:project_id => original_project_id, :position => position).first + training_task = TrainingTask.new + training_task.save_attachments(params[:attachments] || (params[:training_task] && params[:training_task][:uploads])) + training_task.subject = original_task.subject + training_task.description = original_task.description + training_task.position = original_task.position + training_task.project_id = new_training_project_id + training_task.author_id = User.current.id + if training_task.save + respond_to do |format| + format.html{redirect_to project_training_tasks_url(:project_id => new_training_project_id)} + end + else + raise "create task failed" + end + end + + # 复制项目 + def copy_project_and_module tproject, gproject + project = Project.new + project.name = tproject.name + project.is_public = tproject.is_public + project.status = tproject.status + project.description = tproject.description + project.hidden_repo = tproject.hidden_repo + project.user_id = User.current.id + project.project_type = 0 + project.project_new_type = tproject.project_new_type + project.gpid = gproject.id + project.forked_from_project_id = tproject.id + project.enabled_module_names = tproject.enabled_module_names + if project.save + project.update_attribute(:training_status,2) + r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first + m = Member.new(:user => User.current, :roles => [r]) + if ProjectScore.where("project_id=?", project.id).first.nil? + ProjectScore.create(:project_id => project.id, :score => false) + end + project_info = ProjectInfo.new(:user_id => User.current.id, :project_id => project.id) + user_grades = UserGrade.create(:user_id => User.current.id, :project_id => project.id) + Rails.logger.debug "UserGrade created: #{user_grades.to_json}" + project_status = ProjectStatus.create(:project_id => @project.id, :watchers_count => 0, :changesets_count => 0, :project_type => @project.project_type,:grade => 0) + Rails.logger.debug "ProjectStatus created: #{project_status.to_json}" + project.members << m + project.project_infos << project_info + copy_repository(project, gproject) + return project + else + respond_to do |format| + format.html { render :action => 'forked', :layout => 'base_projects'} + format.api { render_validation_errors(@project) } + end + end + end + + # 判断用户是否已经fork过该项目 + def has_forked?(project, user) + projects = Project.where("user_id =?", user) + projects.map(&:forked_from_project_id).detect{|s| s == @project.id}.nil? ? true : false + end + + def copy_repository(project, gproject) + repository = Repository.factory('Git') + repository.project_id = project.id + repository.type = 'Repository::Gitlab' + repository.url = gproject.name + repository.identifier = gproject.name + repository = repository.save end # 资源库fork弹框 diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 50dbaec4d..5c58bc9d3 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -35,12 +35,12 @@ class RepositoriesController < ApplicationController before_filter :find_project_by_project_id, :only => [:new, :create, :newrepo, :stats, :quality_analysis] before_filter :find_repository, :only => [:edit, :update, :destroy, :committers] - before_filter :find_project_repository, :except => [:new, :create, :newcreate, :edit, :update, :destroy, :committers, :newrepo, :to_gitlab, :forked, :export_rep_static, :training_task_execute] + before_filter :find_project_repository, :except => [:new, :create, :newcreate, :edit, :update, :destroy, :committers, :newrepo, :to_gitlab, :forked, :export_rep_static, :training_project_extend] # 连接gitlab # before_filter :connect_gitlab, :only => [:quality_analysis, :commit_diff] before_filter :find_changeset, :only => [:revision, :add_related_issue, :remove_related_issue] - before_filter :authorize , :except => [:newrepo,:newcreate,:fork, :to_gitlab, :forked, :project_archive, :quality_analysis, :commit_diff, :training_task_execute] + before_filter :authorize , :except => [:newrepo,:newcreate,:fork, :to_gitlab, :forked, :project_archive, :quality_analysis, :commit_diff, :training_project_extend] # 版本库新增权限 # before_filter :show_rep, :only => [:show, :stats, :revisions, :revision, :diff, :commit_diff ] accept_rss_auth :revisions @@ -133,7 +133,7 @@ class RepositoriesController < ApplicationController end # 开启实训项目,学生会fork一个项目并自动发送任务 - def training_task_execute + def training_project_extend @project = Project.find(params[:id]) @repository = Repository.where("project_id =? and type =?", @project.id, "Repository::Gitlab") # 如果当前用户已经fork过该项目,不会新fork项目,则跳至已fork的项 diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index a7fef3dd7..f9b185ba4 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -544,7 +544,7 @@ module ProjectsHelper result = "manage_versions" elsif user.allowed_to?(:manage_repository, @project) result = "manage_repository" - elsif is_project_manager?(user.id, @project.id) + elsif @project.is_training_project? result = "training_task" end result diff --git a/app/models/project.rb b/app/models/project.rb index cd8ea3d7b..acf21f5a4 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -225,12 +225,12 @@ class Project < ActiveRecord::Base # 判断项目是否为实训项目 def is_training_project? - (self.enabled_modules.where("name = 'training_tasks'").empty? && self.training_status == 0) ? false : true + (self.enabled_modules.where("name = 'training_tasks'").empty? && self.training_status == 1) ? false : true end # 判断项目是否为开启实训的项目(eg:学生开启实训) def is_child_training_project? - self.training_status == 1 ? true :false + self.training_status == 2 ? true :false end def new_course diff --git a/app/views/layouts/_base_project_top.html.erb b/app/views/layouts/_base_project_top.html.erb index 6d26bc124..aaec20e26 100644 --- a/app/views/layouts/_base_project_top.html.erb +++ b/app/views/layouts/_base_project_top.html.erb @@ -15,7 +15,7 @@ - <% if true %> + <% if !@project.is_child_training_project? %>
diff --git a/app/views/projects/_applied_status.html.erb b/app/views/projects/_applied_status.html.erb index a528d8f20..dede9c7d3 100644 --- a/app/views/projects/_applied_status.html.erb +++ b/app/views/projects/_applied_status.html.erb @@ -37,7 +37,7 @@
  • <% if @project.is_training_project? %> - <%= link_to "开始实训", forked_pop_project_path(@project, :task => true), :class => "sy_btn_green fr", :remote => true %> + <%= link_to "开始实训", training_chiled_project_exec_project_path(@project), :class => "sy_btn_green fr", :remote => true %> <% else %> <%= link_to "".html_safe+"Fork", forked_pop_project_path(@project), :class=>"pro_new_topbtn_left fl", :remote => true %> diff --git a/app/views/projects/_training_child_project_exec.html.erb b/app/views/projects/_training_child_project_exec.html.erb new file mode 100644 index 000000000..e8747a384 --- /dev/null +++ b/app/views/projects/_training_child_project_exec.html.erb @@ -0,0 +1,39 @@ +
    +
    +

    提示

    + +
    +
    +
    +
      + <%# 实训项目和非实训项目,@type为true的时候为实训 %> + <% if User.current.id == @project.user_id %> +
    • + 很抱歉,您不能在自己的实训项目中启动训练 +
    • + <% else %> + <% if @project.gpid.blank? %> +
    • + 该项目还没有创建版本库,暂时不支持实训 +
    • + <% else %> +
    • + <% if has_forked_cur_project(@project) %> + 您已经实训过该项目,点击“确定”将会跳转到您的实训项目主页,请问您是否继续? + <% elsif @project.training_tasks.count == 0 %> + 该项目还没有创建实训任务,暂时不支持开启实训 + <% else %> + 实训将在后台为您创建一个新的同名项目,并为您推送第一个任务,请问您是否继续? + <% end %> +
    • +
    • + + 取  消 + <%= link_to "确 定", {:controller => 'projects', :action => 'training_project_extend'}, :class => "sy_btn_blue fl ml20", :onclick => "hideModal();", :target => "_blank" %> +
      +
    • + <% end %> + <% end %> +
    +
    +
    \ No newline at end of file diff --git a/app/views/projects/add_script.js.erb b/app/views/projects/add_script.js.erb index f4473a7da..5e1b2630c 100644 --- a/app/views/projects/add_script.js.erb +++ b/app/views/projects/add_script.js.erb @@ -1 +1,2 @@ -$("#training_project_exec_tip").html('<%= escape_javascript( render :partial => 'projects/settings/training_project_exec_tip') %>'); \ No newline at end of file +$("#training_project_exec_tip").html('<%= escape_javascript(render :partial => 'projects/settings/training_project_exec_tip') %>'); +$("#training_project_filter_tip").html('<%= escape_javascript(render :partial => 'projects/settings/training_projects_filter_tip') %>'); \ No newline at end of file diff --git a/app/views/projects/settings.html.erb b/app/views/projects/settings.html.erb index 21f5e2ecd..8147abb2a 100644 --- a/app/views/projects/settings.html.erb +++ b/app/views/projects/settings.html.erb @@ -19,7 +19,7 @@ <% if User.current.allowed_to?(:manage_repository, @project) %>
  • 版本库
  • <% end %> - <% if User.current.admin? %> + <% if @project.is_training_project? %>
  • 实训任务
  • <% end %> diff --git a/app/views/projects/settings/_training_projects_filter_tip.html.erb b/app/views/projects/settings/_training_projects_filter_tip.html.erb index e930bc4c7..28e936960 100644 --- a/app/views/projects/settings/_training_projects_filter_tip.html.erb +++ b/app/views/projects/settings/_training_projects_filter_tip.html.erb @@ -1,5 +1,7 @@ -<% if @project.training_status == 1 %> - <%= link_to "重启实训", training_project_update_project_path, :class => "fr sy_btn_green mb10", :remote => true %> -<% else %> - <%= link_to "开启实训", training_project_execute_project_path, :class => "fr sy_btn_green mb10", :remote => true %> +<% unless @project.script.blank? %> + <% if @project.training_status == 1 %> + <%= link_to "重启实训", training_project_update_project_path, :class => "fr sy_btn_green mb10", :remote => true %> + <% else %> + <%= link_to "开启实训", training_project_execute_project_path, :class => "fr sy_btn_green mb10", :remote => true %> + <% end %> <% end %> \ No newline at end of file diff --git a/app/views/projects/task_execute.js.erb b/app/views/projects/task_execute.js.erb new file mode 100644 index 000000000..1dd2affac --- /dev/null +++ b/app/views/projects/task_execute.js.erb @@ -0,0 +1 @@ +$("#task_action_status_<%= @training_task.id %>").html('<%= escape_javascript( render :partial => 'training_tasks/action_status', :locals => {:activity => @training_task}) %>'); \ No newline at end of file diff --git a/app/views/projects/training_chiled_project_exec.js.erb b/app/views/projects/training_chiled_project_exec.js.erb new file mode 100644 index 000000000..91b7651ea --- /dev/null +++ b/app/views/projects/training_chiled_project_exec.js.erb @@ -0,0 +1,3 @@ +var htmlvalue = "<%= escape_javascript(render :partial => 'projects/training_child_project_exec') %>"; +pop_box_new(htmlvalue,460,316); + diff --git a/app/views/projects/training_project_update.js.erb b/app/views/projects/training_project_update.js.erb new file mode 100644 index 000000000..5e1b2630c --- /dev/null +++ b/app/views/projects/training_project_update.js.erb @@ -0,0 +1,2 @@ +$("#training_project_exec_tip").html('<%= escape_javascript(render :partial => 'projects/settings/training_project_exec_tip') %>'); +$("#training_project_filter_tip").html('<%= escape_javascript(render :partial => 'projects/settings/training_projects_filter_tip') %>'); \ No newline at end of file diff --git a/app/views/projects/training_task_status.js.erb b/app/views/projects/training_task_status.js.erb new file mode 100644 index 000000000..1dd2affac --- /dev/null +++ b/app/views/projects/training_task_status.js.erb @@ -0,0 +1 @@ +$("#task_action_status_<%= @training_task.id %>").html('<%= escape_javascript( render :partial => 'training_tasks/action_status', :locals => {:activity => @training_task}) %>'); \ No newline at end of file diff --git a/app/views/repositories/_forked_popbox.html.erb b/app/views/repositories/_forked_popbox.html.erb index 8bd663cec..eca24ea24 100644 --- a/app/views/repositories/_forked_popbox.html.erb +++ b/app/views/repositories/_forked_popbox.html.erb @@ -7,60 +7,31 @@
    +
    \ No newline at end of file diff --git a/app/views/training_tasks/_action_status.html.erb b/app/views/training_tasks/_action_status.html.erb new file mode 100644 index 000000000..49876c3a3 --- /dev/null +++ b/app/views/training_tasks/_action_status.html.erb @@ -0,0 +1,8 @@ +<% activity = activity.nil? ? local_assigns[:activity] : activity %> +<% if activity.status == 1 %> + 评测通过 +<% elsif activity.status == 2 %> + 评测中 +<% else %> + <%= link_to "提交评测", task_execute_project_path(@project, :training_task_id => activity.id), :class => "btn btn-blue", :remote => true %> +<% end %> diff --git a/app/views/training_tasks/_content_list.html.erb b/app/views/training_tasks/_content_list.html.erb index 9af990c08..b304a35e8 100644 --- a/app/views/training_tasks/_content_list.html.erb +++ b/app/views/training_tasks/_content_list.html.erb @@ -1,10 +1,10 @@ <% unless activity.author.nil? %> - <% if activity.status == 0 %> -
    - <% elsif activity.status == 1 %> + <% if activity.status == 1 %>
    + <% else %> +
    <% end %>
    @@ -30,7 +30,11 @@ <% end %> - <%= link_to "提交评测", task_execute_project_path(@project, :training_task_id => activity.id), :class => "btn btn-blue", :remote => true %> + <% if @project.is_child_training_project? %> +
    + <%= render :partial => 'action_status', :locals => {:activity => activity} %> +
    + <% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index c0a91f5ca..25aa1c354 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -915,8 +915,10 @@ RedmineApp::Application.routes.draw do post 'reopen' get 'training_project_execute' get 'training_project_update' + get 'training_project_extend' get 'task_execute' get 'forked_pop' + get 'training_chiled_project_exec' get 'delete_member_pop', :to => 'projects#delete_member_pop', :via => :get, :as => "delete_member_pop" get 'search_public_orgs_not_in_project' match 'copy', :via => [:get, :post]