Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun
commit
a6f83cf601
@ -0,0 +1,19 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) {
|
||||
var $form = $('form.edit-mirror');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
"mirror_repository[type_name]": {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$form.submit(function(e){
|
||||
if(!$form.valid()){ e.preventDefault(); }
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-repositories-index-page').length > 0) {
|
||||
}
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-scripts-edit-page, body.admins-mirror-scripts-update-page, body.admins-mirror-scripts-new-page, body.admins-mirror-scripts-create-page').length > 0) {
|
||||
var $form = $('form.script-form');
|
||||
|
||||
// codemirror编辑器
|
||||
var scriptEditor = CodeMirror.fromTextArea(document.getElementById('mirror_script_script'), {
|
||||
lineNumbers: true,
|
||||
mode: 'shell',
|
||||
theme: "default",
|
||||
indentUnit: 4, //代码缩进为一个tab的距离
|
||||
matchBrackets: true,
|
||||
autoRefresh: true,
|
||||
smartIndent: true,//智能换行
|
||||
styleActiveLine: true,
|
||||
lint: true
|
||||
});
|
||||
scriptEditor.setSize('auto', '600px');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
"mirror_script[script_type]": {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$form.submit(function(e){
|
||||
if(!$form.valid()){ e.preventDefault(); }
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-choose-mirror-modal', function(){
|
||||
var $modal = $('.modal.admin-choose-mirror-modal');
|
||||
var $form = $modal.find('form.admin-choose-mirror-form');
|
||||
|
||||
var validateForm = function(){
|
||||
var checkedValue = $form.find('input[name="mirror_number"]:checked').val();
|
||||
|
||||
if(checkedValue == undefined){
|
||||
$modal.find('.error').html('必须选择一种镜像保存!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
var url = $form.attr('action');
|
||||
|
||||
if (validateForm()) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
}).done(function(){
|
||||
$modal.modal('hide');
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
@ -0,0 +1,89 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
var $modal = $('.modal.admin-replace-mirror-modal');
|
||||
if ($modal.length > 0) {
|
||||
var $form = $modal.find('form.admin-replace-mirror-form');
|
||||
var $mirrorIdInput = $modal.find('.modal-body input[name="mirror_id"]');
|
||||
var $mirrorSelect = $modal.find('.new-mirror-select');
|
||||
|
||||
var setMirror = function(id, name){
|
||||
$mirrorIdInput.val(id);
|
||||
$form.find('.mirror-id-container').html(id);
|
||||
$form.find('.mirror-name-container').html(name);
|
||||
}
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
new_mirror_id: {
|
||||
required: true
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
new_mirror_id: {
|
||||
required: '请选择新镜像'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal ready fire
|
||||
$modal.on('show.bs.modal', function (event) {
|
||||
var $link = $(event.relatedTarget);
|
||||
|
||||
var mirrorId = $link.data('id');
|
||||
var mirrorName = $link.data('name');
|
||||
|
||||
setMirror(mirrorId, mirrorName);
|
||||
$mirrorSelect.select2('val', ' ');
|
||||
});
|
||||
$modal.on('hide.bs.modal', function () {
|
||||
setMirror('', '');
|
||||
$mirrorSelect.select2('val', ' ');
|
||||
$('#new_mirror_id-error').remove();
|
||||
});
|
||||
|
||||
$mirrorSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '输入要合并的镜像名',
|
||||
minimumInputLength: 1,
|
||||
ajax: {
|
||||
url: '/admins/mirror_repositories/for_select',
|
||||
dataType: 'json',
|
||||
data: function(params){
|
||||
return { keyword: params.term };
|
||||
},
|
||||
processResults: function(data){
|
||||
return { results: data.mirrors }
|
||||
}
|
||||
},
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
$('#new_mirror_id-error').remove();
|
||||
$('#new_mirror_id').val(item.id);
|
||||
}
|
||||
return item.name || item.text;
|
||||
}
|
||||
});
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
|
||||
if ($form.valid()) {
|
||||
var url = $form.data('url');
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
}).done(function(){
|
||||
$modal.modal('hide');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
class Admins::ChooseMirrorRepositoriesController < Admins::BaseController
|
||||
def new
|
||||
@mirror = MirrorRepository.find(params[:mirror_id])
|
||||
@new_mirror = MirrorOperationRecord.where(mirror_repository_id: @mirror.id, status: 1, user_id: -1).first
|
||||
end
|
||||
|
||||
def create
|
||||
mirror = MirrorRepository.find(params[:mirror_id])
|
||||
Admins::ChooseMirrorService.call(mirror, current_user, params[:mirror_number])
|
||||
end
|
||||
end
|
@ -0,0 +1,97 @@
|
||||
class Admins::MirrorRepositoriesController < Admins::BaseController
|
||||
before_action :check_shixun_mirrors!, only: [:index]
|
||||
|
||||
def index
|
||||
mirrors = MirrorRepository.all
|
||||
mirrors = mirrors.reorder(status: :desc, main_type: :desc, type_name: :asc)
|
||||
|
||||
@mirrors = paginate mirrors.includes(:mirror_scripts)
|
||||
@error_mirror_names = MirrorRepository.where(status: 5).pluck(:name)
|
||||
end
|
||||
|
||||
def new
|
||||
@mirror = MirrorRepository.new
|
||||
end
|
||||
|
||||
def create
|
||||
@mirror = MirrorRepository.new
|
||||
Admins::SaveMirrorRepositoryService.call(@mirror, current_user, form_params)
|
||||
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_path(@mirror)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
flash.now[:danger] = '保存失败'
|
||||
render 'new'
|
||||
rescue Admins::SaveMirrorRepositoryService::Error => ex
|
||||
flash.now[:danger] = ex.message
|
||||
render 'new'
|
||||
end
|
||||
|
||||
def edit
|
||||
@mirror = current_mirror
|
||||
end
|
||||
|
||||
def update
|
||||
@mirror = current_mirror
|
||||
|
||||
Admins::SaveMirrorRepositoryService.call(current_mirror, current_user, form_params)
|
||||
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_path(current_mirror)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
flash.now[:danger] = '保存失败'
|
||||
render 'edit'
|
||||
rescue Admins::SaveMirrorRepositoryService::Error => ex
|
||||
flash.now[:danger] = ex.message
|
||||
render 'edit'
|
||||
end
|
||||
|
||||
def destroy
|
||||
return render_js_error('该状态下不允许删除') unless current_mirror.deletable?
|
||||
|
||||
current_mirror.destroy!
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def for_select
|
||||
mirrors = MirrorRepository.all
|
||||
|
||||
keyword = params[:keyword].to_s.strip
|
||||
mirrors = mirrors.where('name LIKE ?', "%#{keyword}%") if keyword.present?
|
||||
|
||||
@mirrors = paginate mirrors
|
||||
|
||||
render_ok(count: @mirrors.total_count, mirrors: @mirrors.as_json(only: %i[id name]))
|
||||
end
|
||||
|
||||
def merge
|
||||
origin_mirror = MirrorRepository.find(params[:mirror_id])
|
||||
mirror = MirrorRepository.find(params[:new_mirror_id])
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
origin_mirror.update!(name: mirror.name, mirrorID: mirror.mirrorID)
|
||||
mirror.destroy!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_mirror
|
||||
@_current_mirror ||= MirrorRepository.find(params[:id])
|
||||
end
|
||||
|
||||
def form_params
|
||||
columns = %i[type_name main_type time_limit resource_limit cpu_limit memory_limit description status]
|
||||
params.require(:mirror_repository).permit(*columns)
|
||||
end
|
||||
|
||||
def check_shixun_mirrors!
|
||||
return
|
||||
return unless request.format.html?
|
||||
|
||||
Admins::CheckShixunMirrorsService.call
|
||||
rescue Admins::CheckShixunMirrorsService::Error => e
|
||||
internal_server_error(e.message)
|
||||
end
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
class Admins::MirrorScriptsController < Admins::BaseController
|
||||
helper_method :current_mirror
|
||||
|
||||
def index
|
||||
scripts = current_mirror.mirror_scripts.order(updated_at: :desc)
|
||||
@scripts = paginate scripts
|
||||
end
|
||||
|
||||
def new
|
||||
@script = current_mirror.mirror_scripts.new
|
||||
end
|
||||
|
||||
def create
|
||||
@script = current_mirror.mirror_scripts.new(form_params)
|
||||
|
||||
if @script.save
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@script = current_script
|
||||
end
|
||||
|
||||
def update
|
||||
@script = current_script
|
||||
|
||||
if @script.update(form_params)
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
current_script.destroy!
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_script
|
||||
@_current_script ||= current_mirror.mirror_scripts.find(params[:id])
|
||||
end
|
||||
|
||||
def current_mirror
|
||||
@_current_mirror ||= MirrorRepository.find(params[:mirror_repository_id])
|
||||
end
|
||||
|
||||
def form_params
|
||||
params.require(:mirror_script).permit(:script_type, :description, :script)
|
||||
end
|
||||
end
|
@ -0,0 +1,23 @@
|
||||
module Admins::MirrorRepositoriesHelper
|
||||
def mirror_type_tag(mirror)
|
||||
case mirror.main_type
|
||||
when '1' then '<i class="fa fa-star text-success font-16" aria-hidden="true" data-toggle="tooltip" data-title="主类别"></i>'.html_safe
|
||||
when '0' then '<i class="fa fa-star text-secondary font-16" aria-hidden="true" data-toggle="tooltip" data-title="子类别"></i>'.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def mirror_status_tag(mirror)
|
||||
case mirror.status
|
||||
when 0
|
||||
'<i class="fa fa-check-circle text-secondary font-16" data-toggle="tooltip" data-title="未发布"></i>'.html_safe
|
||||
when 1
|
||||
'<i class="fa fa-check-circle text-success font-16" data-toggle="tooltip" data-title="已发布"></i>'.html_safe
|
||||
when 2, 3
|
||||
'<i class="fa fa-exclamation-circle text-danger font-16" data-toggle="tooltip" data-title="被修改"></i>'.html_safe
|
||||
when 4
|
||||
'<i class="fa fa-times-circle text-danger font-18" data-toggle="tooltip" data-title="被删除"></i>'.html_safe
|
||||
when 5
|
||||
'<i class="fa fa-exclamation-circle text-warning font-16" data-toggle="tooltip" data-title="子节点异常"></i>'.html_safe
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,21 @@
|
||||
class Admins::ChooseMirrorService < ApplicationService
|
||||
attr_reader :mirror, :user, :number
|
||||
|
||||
def initialize(mirror, user, mirror_number)
|
||||
@mirror = mirror
|
||||
@user = user
|
||||
@number = mirror_number
|
||||
end
|
||||
|
||||
def call
|
||||
if mirror.mirrorID == number
|
||||
mirror.update_column(:status, 1)
|
||||
return
|
||||
end
|
||||
|
||||
old_number = mirror.mirrorID
|
||||
mirror.update!(mirrorID: number, status: 1)
|
||||
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, mirror_id: number, mirror_name: mirror.name,
|
||||
status: 1, user_id: user.id, old_tag: old_number, new_tag: mirror.mirrorID)
|
||||
end
|
||||
end
|
@ -0,0 +1,37 @@
|
||||
class Admins::SaveMirrorRepositoryService < ApplicationService
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
attr_reader :mirror, :user, :params
|
||||
|
||||
def initialize(mirror, user, params)
|
||||
@mirror = mirror
|
||||
@user = user
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
mirror.assign_attributes(params)
|
||||
|
||||
raise Error, '镜像别名重复' if MirrorRepository.where.not(id: mirror.id).exists?(type_name: params[:type_name])
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
record_operation! if mirror.persisted?
|
||||
|
||||
mirror.save!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def record_operation!
|
||||
if mirror.type_name_changed?
|
||||
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, status: 5,
|
||||
user_id: user.id, old_tag: mirror.type_name_in_database,
|
||||
new_tag: mirror.type_name)
|
||||
elsif mirror.status_changed?
|
||||
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, status: 5,
|
||||
user_id: user.id, old_tag: mirror.status_in_database,
|
||||
new_tag: mirror.status)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
$.notify({ message: '操作成功' },{ type: 'success' });
|
||||
|
||||
setTimeout(function(){
|
||||
window.location.reload();
|
||||
}, 500)
|
@ -0,0 +1,2 @@
|
||||
$('.admin-modal-container').html("<%= j( render partial: 'admins/mirror_repositories/shared/choose_mirror_modal', locals: { mirror: @mirror, new_mirror: @new_mirror } ) %>");
|
||||
$('.modal.admin-choose-mirror-modal').modal('show');
|
@ -0,0 +1,8 @@
|
||||
<%
|
||||
define_admin_breadcrumbs do
|
||||
add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path)
|
||||
add_admin_breadcrumb('镜像详情')
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render partial: 'admins/mirror_repositories/shared/form', locals: { mirror: @mirror, form_action: 'update' } %>
|
@ -0,0 +1,23 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container mirror-repository-list-form">
|
||||
<form class="flex-1"></form>
|
||||
<%= link_to '新建', new_admins_mirror_repository_path, class: 'btn btn-primary' %>
|
||||
</div>
|
||||
|
||||
<% if @error_mirror_names.present? %>
|
||||
<div class="box pb-0">
|
||||
以下镜像异常:
|
||||
<% @error_mirror_names.each do |mirror_name| %>
|
||||
<span class="ml-2 text-danger"><%= mirror_name %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="box mirror-repository-list-container">
|
||||
<%= render partial: 'admins/mirror_repositories/shared/list', locals: { mirrors: @mirrors } %>
|
||||
</div>
|
||||
|
||||
<%= render 'admins/mirror_repositories/shared/replace_mirror_modal' %>
|
@ -0,0 +1 @@
|
||||
$('.mirror-repository-list-container').html("<%= j( render partial: 'admins/mirror_repositories/shared/list', locals: { mirrors: @mirrors } ) %>");
|
@ -0,0 +1,5 @@
|
||||
$.notify({ message: '操作成功' },{ type: 'success' });
|
||||
|
||||
setTimeout(function(){
|
||||
window.location.reload();
|
||||
}, 500)
|
@ -0,0 +1,8 @@
|
||||
<%
|
||||
define_admin_breadcrumbs do
|
||||
add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path)
|
||||
add_admin_breadcrumb('新建镜像')
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render partial: 'admins/mirror_repositories/shared/form', locals: { mirror: @mirror, form_action: 'create' } %>
|
@ -0,0 +1,42 @@
|
||||
<div class="modal fade admin-choose-mirror-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">更新镜像仓库</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%= form_tag(admins_choose_mirror_repositories_path(mirror_id: mirror.id), method: :post, class: 'admin-choose-mirror-form') do %>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2"></div>
|
||||
<div class="col-md-5">ID</div>
|
||||
<div class="col-md-5">名称</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">旧镜像</div>
|
||||
<div class="col-md-5 form-check">
|
||||
<input class="form-check-input" type="radio" name="mirror_number" id="old-mirror-check" value="<%= mirror.mirrorID %>">
|
||||
<label class="form-check-label" for="old-mirror-check"><%= mirror.mirrorID %></label>
|
||||
</div>
|
||||
<div class="col-md-5"><%= mirror.name %></div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">新镜像</div>
|
||||
<div class="col-md-5 form-check">
|
||||
<input class="form-check-input" type="radio" name="mirror_number" id="new-mirror-check" value="<%= new_mirror.mirror_id %>">
|
||||
<label class="form-check-label" for="new-mirror-check"><%= new_mirror.mirror_id %></label>
|
||||
</div>
|
||||
<div class="col-md-5"><%= new_mirror.mirror_name %></div>
|
||||
</div>
|
||||
<div class="mt-2 error text-danger"></div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary submit-btn">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
<div class="box edit-mirror-repository-container">
|
||||
<%= simple_form_for([:admins, mirror], url: { action: form_action }, html: { class: 'edit-mirror col-md-12' }, defaults: { wrapper_html: { class: 'col-md-4' } }) do |f| %>
|
||||
<% unless mirror.new_record? %>
|
||||
<div class="row">
|
||||
<%= f.input :mirrorID, label: '镜像ID', input_html: { readonly: true, class: 'form-control-plaintext' } %>
|
||||
<%= f.input :name, label: '镜像名称', input_html: { readonly: true, class: 'form-control-plaintext' } %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
<%= f.input :type_name, as: :string, label: '镜像别名 *' %>
|
||||
|
||||
<div class="form-group select optional col-md-4">
|
||||
<%= f.label :main_type, label: '类别' %>
|
||||
<%= f.select :main_type, [['主类别', 1],['小类别', 0]], {}, class: 'form-control optional' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<%= f.input :time_limit, as: :integer, label: '评测时限(S)' %>
|
||||
<%= f.input :resource_limit, as: :integer, label: '磁盘限制(K)' %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<%= f.input :cpu_limit, as: :integer, label: 'CPU限制(核)' %>
|
||||
<%= f.input :memory_limit, as: :integer, label: '内存限制(M)' %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<%= f.input :description, as: :text, label: '描述', wrapper_html: { class: 'col-md-8' } %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<%= f.input :status, as: :radio_buttons, label: '状态', collection: [%w(未发布 0), %w(已发布 1)], wrapper_html: { class: 'col-md-4' } %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4', 'data-disable-with': '保存中...' %>
|
||||
<%= link_to '取消', admins_mirror_repositories_path, class: 'btn btn-secondary px-4' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
@ -0,0 +1,54 @@
|
||||
<table class="table table-hover text-center mirror-repository-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="6%">ID</th>
|
||||
<th width="6%">类别</th>
|
||||
<th width="12%" class="text-left">镜像别名</th>
|
||||
<th width="16%" class="text-left">镜像名称</th>
|
||||
<th width="22%" class="text-left">镜像描述</th>
|
||||
<th width="14%">修改时间</th>
|
||||
<th width="6%">脚本</th>
|
||||
<th width="6%">状态</th>
|
||||
<th width="12%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if mirrors.present? %>
|
||||
<% mirrors.each do |mirror| %>
|
||||
<tr class="mirror-repository-item-<%= mirror.id %>">
|
||||
<td><%= mirror.id %></td>
|
||||
<td><%= mirror_type_tag(mirror) %></td>
|
||||
<td class="text-left"><%= display_text(mirror.type_name) %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span mirror.name, width: 150 %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span mirror.description, width: 240 %></td>
|
||||
<td><%= mirror.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td>
|
||||
<% if mirror.main_type == "1" %>
|
||||
<%= link_to admins_mirror_repository_mirror_scripts_path(mirror) do %>
|
||||
<i class="fa fa-file-text <%= mirror.mirror_scripts.blank? ? 'text-danger' : 'text-success' %>" aria-hidden="true" data-toggle="tooltip" data-title="查看脚本"></i>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td><%= mirror_status_tag mirror %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to '编辑', edit_admins_mirror_repository_path(mirror), class: 'action edit-action' %>
|
||||
|
||||
<% if mirror.status == 2 %>
|
||||
<%= link_to '同步', new_admins_choose_mirror_repository_path(mirror_id: mirror.id), remote: true, class: 'action sync-action' %>
|
||||
<% end %>
|
||||
|
||||
<%= javascript_void_link '替换', class: 'action replace-action', data: { toggle: 'modal', target: '.admin-replace-mirror-modal', id: mirror.id, name: mirror.name } %>
|
||||
|
||||
<% if mirror.deletable? %>
|
||||
<%= delete_link '删除', admins_mirror_repository_path(mirror, element: ".mirror-repository-item-#{mirror.id}"), class: 'delete-mirror-repository-action' %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: mirrors } %>
|
@ -0,0 +1,8 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('编辑脚本') %>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'update' } %>
|
@ -0,0 +1,14 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container mirror-script-list-form">
|
||||
<form class="flex-1"></form>
|
||||
<%= link_to '新建', new_admins_mirror_repository_mirror_script_path(current_mirror), class: 'btn btn-primary' %>
|
||||
</div>
|
||||
|
||||
<div class="box mirror-script-list-container">
|
||||
<%= render partial: 'admins/mirror_scripts/shared/list', locals: { mirror: current_mirror, scripts: @scripts } %>
|
||||
</div>
|
@ -0,0 +1,8 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('新建脚本') %>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'create' } %>
|
@ -0,0 +1,12 @@
|
||||
<div class="box edit-mirror-script-container">
|
||||
<%= simple_form_for([:admins, mirror, script], url: { action: form_action }, html: { class: 'script-form' }) do |f| %>
|
||||
<%= f.input :script_type, label: '名称', input_html: { class: 'col-md-6' } %>
|
||||
<%= f.input :description, as: :text, label: '说明', input_html: { class: 'col-md-6' } %>
|
||||
<%= f.input :script, as: :text, label: '评测脚本' %>
|
||||
|
||||
<div class="form-row">
|
||||
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4', 'data-disable-with': '保存中...' %>
|
||||
<%= link_to '取消', admins_mirror_repository_mirror_scripts_path(mirror), class: 'btn btn-secondary px-4' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
@ -0,0 +1,32 @@
|
||||
<table class="table table-hover text-center mirror-script-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="10%">ID</th>
|
||||
<th width="20%" class="text-left">名称</th>
|
||||
<th width="34%" class="text-left">说明</th>
|
||||
<th width="16%">更新时间</th>
|
||||
<th width="20%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if scripts.present? %>
|
||||
<% scripts.each do |script| %>
|
||||
<tr class="mirror-script-item-<%= script.id %>">
|
||||
<td><%= script.id %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span script.script_type, width: 200 %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span script.description, width: 400 %></td>
|
||||
<td><%= script.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to '编辑', edit_admins_mirror_repository_mirror_script_path(mirror, script), class: 'action edit-action' %>
|
||||
|
||||
<%= delete_link '删除', admins_mirror_repository_mirror_script_path(mirror, script, element: ".mirror-script-item-#{script.id}"), class: 'delete-mirror-script-action' %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: scripts } %>
|
@ -0,0 +1,6 @@
|
||||
<div class="d-flex flex-column align-items-center justify-content-center global-error">
|
||||
<div class="global-error-code">
|
||||
<span>403</span>
|
||||
</div>
|
||||
<div class="global-error-text">未授权</div>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<div class="paginate-container">
|
||||
<% if objects.size.nonzero? %>
|
||||
<% if objects && objects.size.nonzero? %>
|
||||
<div class="paginate-total"><%= page_entries_info objects %></div>
|
||||
<% end %>
|
||||
<%= paginate objects, views_prefix: 'admins', remote: true %>
|
||||
|
@ -1,2 +1,2 @@
|
||||
json.status 1
|
||||
json.message "创建参考答案成功"
|
||||
json.message "操作成功"
|
@ -1 +1 @@
|
||||
admins-users: admins-users
|
||||
admins-mirror_scripts: 'admins-mirror_repositories'
|
@ -0,0 +1,10 @@
|
||||
class ModifyChallnegeScoreForChoose < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
challenges = Challenge.where(st: 1)
|
||||
challenges.find_each do |c|
|
||||
puts(c.id)
|
||||
score = c.challenge_chooses.sum(:score)
|
||||
c.update_column(:score, score)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,6 @@
|
||||
class AddUpdateUserIdToStudentWorks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :student_works, :update_user_id, :integer
|
||||
StudentWork.update_all("update_user_id = commit_user_id")
|
||||
end
|
||||
end
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 137 KiB |
File diff suppressed because it is too large
Load Diff
@ -1,122 +1,124 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import {Link} from 'react-router-dom';
|
||||
import {Tooltip,Menu} from 'antd';
|
||||
import {getImageUrl} from 'educoder';
|
||||
|
||||
import "./usersInfo.css"
|
||||
import "../../courses/css/members.css"
|
||||
import "../../courses/css/Courses.css"
|
||||
|
||||
import { LinkAfterLogin } from 'educoder'
|
||||
|
||||
class InfosBanner extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
render(){
|
||||
let {
|
||||
data ,
|
||||
id,
|
||||
login,
|
||||
moduleName,
|
||||
current_user,
|
||||
}=this.props;
|
||||
let is_current=this.props.is_current;
|
||||
let {username}= this.props.match.params;
|
||||
let {pathname}=this.props.location;
|
||||
moduleName=pathname.split("/")[3];
|
||||
return(
|
||||
<div className="bannerPanel mb60">
|
||||
<div className="educontent">
|
||||
<div className="clearfix color-white mb25">
|
||||
<p className="myPhoto mr20 fl"><img alt="头像" src={data && `${getImageUrl('images/'+data.avatar_url)}`}/></p>
|
||||
<div className="fl">
|
||||
<p className="clearfix mt20">
|
||||
<span className="username task-hide" style={{"maxWidth":'370px'}}>{data && data.name}</span>
|
||||
{
|
||||
data && is_current == false && data.identity =="学生" ? "" :
|
||||
<span className="userpost"><label>{data && data.identity}</label></span>
|
||||
}
|
||||
</p>
|
||||
<p className="mt15">
|
||||
<Tooltip placement='bottom' title={ data && data.professional_certification ?"已职业认证":"未职业认证"}>
|
||||
<i className={ data && data.professional_certification ? "iconfont icon-shenfenzhenghaomaguizheng font-18 user-colorgrey-green mr20 ml2":"iconfont icon-shenfenzhenghaomaguizheng font-18 user-colorgrey-B8 mr20 ml2"}></i>
|
||||
</Tooltip>
|
||||
<Tooltip placement='bottom' title={ data && data.authentication ?"已实名认证":"未实名认证"}>
|
||||
<i className={ data && data.authentication ? "iconfont icon-renzhengshangjia font-18 user-colorgrey-green":"iconfont icon-renzhengshangjia font-18 user-colorgrey-B8"}></i>
|
||||
</Tooltip>
|
||||
</p>
|
||||
</div>
|
||||
<div className="fr">
|
||||
<div class="fl headtab mt20">
|
||||
<span>{is_current ? "我":"TA"}的经验值</span>
|
||||
<a style={{"cursor":"default"}}>{data && data.experience}</a>
|
||||
</div>
|
||||
<div class="fl headtab mt20 pr leftTransform pl20">
|
||||
<span>{is_current ? "我":"TA"}的金币</span>
|
||||
<a style={{"cursor":"default"}}>{data && data.grade}</a>
|
||||
</div>
|
||||
{
|
||||
is_current ?
|
||||
<span className="fl mt35 ml60">
|
||||
{
|
||||
data && data.attendance_signed ?
|
||||
<span className="user_default_btn user_grey_btn font-18">已签到</span>
|
||||
:
|
||||
<a herf="javascript:void(0);" onClick={this.props.signFor} className="user_default_btn user_yellow_btn fl font-18">签到</a>
|
||||
}
|
||||
</span>
|
||||
:
|
||||
<span className="fl mt35 ml60">
|
||||
<LinkAfterLogin
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
className="user_default_btn user_yellow_btn fl font-18"
|
||||
to={`/messages/${login}/message_detail?target_ids=${id}`}
|
||||
>
|
||||
私信
|
||||
</LinkAfterLogin>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="userNav">
|
||||
<li className={`${moduleName == 'courses' ||moduleName == undefined ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'courses'})}
|
||||
to={`/users/${username}/courses`}>翻转课堂</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'shixuns' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'shixuns'})}
|
||||
to={`/users/${username}/shixuns`}>开发社区</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'paths' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'paths'})}
|
||||
to={`/users/${username}/paths`}>实践课程</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'projects' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'projects'})}
|
||||
to={`/users/${username}/projects`}>项目</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'package' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'package'})}
|
||||
to={`/users/${username}/package`}>众包</Link>
|
||||
</li>
|
||||
{((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin)
|
||||
&& <li className={`${moduleName == 'videos' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'videos'})}
|
||||
to={`/users/${username}/videos`}>视频</Link>
|
||||
</li>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import {Link} from 'react-router-dom';
|
||||
import {Tooltip,Menu} from 'antd';
|
||||
import {getImageUrl} from 'educoder';
|
||||
|
||||
import "./usersInfo.css"
|
||||
import "../../courses/css/members.css"
|
||||
import "../../courses/css/Courses.css"
|
||||
|
||||
import { LinkAfterLogin } from 'educoder'
|
||||
|
||||
class InfosBanner extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
render(){
|
||||
let {
|
||||
data ,
|
||||
id,
|
||||
login,
|
||||
moduleName,
|
||||
current_user,
|
||||
}=this.props;
|
||||
let is_current=this.props.is_current;
|
||||
let {username}= this.props.match.params;
|
||||
let {pathname}=this.props.location;
|
||||
moduleName=pathname.split("/")[3];
|
||||
|
||||
return(
|
||||
<div className="bannerPanel mb60">
|
||||
<div className="educontent">
|
||||
<div className="clearfix color-white mb25">
|
||||
<p className="myPhoto mr20 fl"><img alt="头像" src={data && `${getImageUrl('images/'+data.avatar_url)}`}/></p>
|
||||
<div className="fl">
|
||||
<p className="clearfix mt20">
|
||||
<span className="username task-hide" style={{"maxWidth":'370px'}}>{data && data.name}</span>
|
||||
{
|
||||
data && is_current == false && data.identity =="学生" ? "" :
|
||||
<span className="userpost"><label>{data && data.identity}</label></span>
|
||||
}
|
||||
</p>
|
||||
<p className="mt15">
|
||||
<Tooltip placement='bottom' title={ data && data.professional_certification ?"已职业认证":"未职业认证"}>
|
||||
<i className={ data && data.professional_certification ? "iconfont icon-shenfenzhenghaomaguizheng font-18 user-colorgrey-green mr20 ml2":"iconfont icon-shenfenzhenghaomaguizheng font-18 user-colorgrey-B8 mr20 ml2"}></i>
|
||||
</Tooltip>
|
||||
<Tooltip placement='bottom' title={ data && data.authentication ?"已实名认证":"未实名认证"}>
|
||||
<i className={ data && data.authentication ? "iconfont icon-renzhengshangjia font-18 user-colorgrey-green":"iconfont icon-renzhengshangjia font-18 user-colorgrey-B8"}></i>
|
||||
</Tooltip>
|
||||
</p>
|
||||
</div>
|
||||
<div className="fr">
|
||||
<div class="fl headtab mt20">
|
||||
<span>{is_current ? "我":"TA"}的经验值</span>
|
||||
<a style={{"cursor":"default"}}>{data && data.experience}</a>
|
||||
</div>
|
||||
<div class="fl headtab mt20 pr leftTransform pl20">
|
||||
<span>{is_current ? "我":"TA"}的金币</span>
|
||||
<a style={{"cursor":"default"}}>{data && data.grade}</a>
|
||||
</div>
|
||||
{
|
||||
is_current ?
|
||||
<span className="fl mt35 ml60">
|
||||
{
|
||||
data && data.attendance_signed ?
|
||||
<span className="user_default_btn user_grey_btn font-18">已签到</span>
|
||||
:
|
||||
<a herf="javascript:void(0);" onClick={this.props.signFor} className="user_default_btn user_yellow_btn fl font-18">签到</a>
|
||||
}
|
||||
</span>
|
||||
:
|
||||
<span className="fl mt35 ml60">
|
||||
<LinkAfterLogin
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
className="user_default_btn user_yellow_btn fl font-18"
|
||||
to={`/messages/${login}/message_detail?target_ids=${id}`}
|
||||
>
|
||||
私信
|
||||
</LinkAfterLogin>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="userNav">
|
||||
<li className={`${moduleName == 'courses' ||moduleName == undefined ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'courses'})}
|
||||
to={`/users/${username}/courses`}>翻转课堂</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'shixuns' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'shixuns'})}
|
||||
to={`/users/${username}/shixuns`}>实训项目</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'paths' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'paths'})}
|
||||
to={`/users/${username}/paths`}>实践课程</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'projects' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'projects'})}
|
||||
to={`/users/${username}/projects`}>开发项目</Link>
|
||||
</li>
|
||||
<li className={`${moduleName == 'package' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'package'})}
|
||||
to={`/users/${username}/package`}>众包</Link>
|
||||
</li>
|
||||
{((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin)
|
||||
&& <li className={`${moduleName == 'videos' ? 'active' : '' }`}>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: 'videos'})}
|
||||
to={`/users/${username}/videos`}>视频</Link>
|
||||
</li>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default InfosBanner;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue