Merge branches 'dev_aliyun' and 'topic_bank' of https://bdgit.educoder.net/Hjqreturn/educoder into topic_bank
commit
3a445e8159
@ -0,0 +1,2 @@
|
|||||||
|
// Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
// All this logic will automatically be available in application.js.
|
@ -0,0 +1,3 @@
|
|||||||
|
// Place all the styles related to the homework_banks controller here.
|
||||||
|
// They will automatically be included in application.css.
|
||||||
|
// You can use Sass (SCSS) here: http://sass-lang.com/
|
@ -0,0 +1,60 @@
|
|||||||
|
#encoding: UTF-8
|
||||||
|
class ExerciseBanksController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_bank
|
||||||
|
before_action :bank_admin, only: [:update]
|
||||||
|
|
||||||
|
def show
|
||||||
|
@exercise_questions = @bank.exercise_bank_questions&.includes(:exercise_bank_choices, :exercise_bank_shixun_challenges,
|
||||||
|
:exercise_bank_standard_answers).order("question_number ASC")
|
||||||
|
@exercise_ques_count = @exercise_questions.size # 全部的题目数
|
||||||
|
@exercise_ques_scores = @exercise_questions.pluck(:question_score).sum
|
||||||
|
|
||||||
|
#单选题的数量及分数
|
||||||
|
exercise_single_ques = @exercise_questions.find_by_custom("question_type", Exercise::SINGLE)
|
||||||
|
@exercise_single_ques_count = exercise_single_ques.size
|
||||||
|
@exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum
|
||||||
|
|
||||||
|
#多选题的数量及分数
|
||||||
|
exercise_double_ques = @exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE)
|
||||||
|
@exercise_double_ques_count = exercise_double_ques.size
|
||||||
|
@exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum
|
||||||
|
|
||||||
|
# 判断题数量及分数
|
||||||
|
exercise_ques_judge = @exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT)
|
||||||
|
@exercise_ques_judge_count = exercise_ques_judge.size
|
||||||
|
@exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum
|
||||||
|
|
||||||
|
#填空题数量及分数
|
||||||
|
exercise_ques_null = @exercise_questions.find_by_custom("question_type", Exercise::COMPLETION)
|
||||||
|
@exercise_ques_null_count = exercise_ques_null.size
|
||||||
|
@exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum
|
||||||
|
|
||||||
|
#简答题数量及分数
|
||||||
|
exercise_ques_main = @exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE)
|
||||||
|
@exercise_ques_main_count = exercise_ques_main.size
|
||||||
|
@exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum
|
||||||
|
|
||||||
|
#实训题数量及分数
|
||||||
|
exercise_ques_shixun = @exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL)
|
||||||
|
@exercise_ques_shixun_count = exercise_ques_shixun.size
|
||||||
|
@exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
tip_exception("试卷标题不能为空!") if params[:exercise_name].blank?
|
||||||
|
@bank.update_attributes!(name: params[:exercise_name], description: params[:exercise_description])
|
||||||
|
normal_status(0,"试卷更新成功!")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_bank
|
||||||
|
@bank = ExerciseBank.find_by!(id: params[:id])
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && (@bank.is_public || @bank.user_id == current_user.id)) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def bank_admin
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && @bank.user_id == current_user.id) || current_user.admin?
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,39 @@
|
|||||||
|
class GtopicBanksController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_bank
|
||||||
|
before_action :bank_admin, only: [:edit, :update]
|
||||||
|
|
||||||
|
def show
|
||||||
|
@bank_attachments = @bank.attachments
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@attachments = @bank.attachments
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@bank.update_attributes(gtopic_bank_params)
|
||||||
|
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||||
|
normal_status(0, "更新成功")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_bank
|
||||||
|
@bank = GtopicBank.find_by!(id: params[:id])
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && (@bank.is_public || @bank.user_id == current_user.id)) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def bank_admin
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && @bank.user_id == current_user.id) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def gtopic_bank_params
|
||||||
|
tip_exception("name参数不能为空") if params[:gtopic_bank][:name].blank?
|
||||||
|
tip_exception("description参数不能为空") if params[:gtopic_bank][:description].blank?
|
||||||
|
params.require(:gtopic_bank).permit(:name, :topic_type, :topic_source, :topic_property_first, :description,
|
||||||
|
:topic_property_second, :source_unit, :topic_repeat, :province, :city)
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,63 @@
|
|||||||
|
class HomeworkBanksController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_bank
|
||||||
|
before_action :bank_params, only: [:update]
|
||||||
|
before_action :bank_admin, only: [:update, :destroy, :set_public]
|
||||||
|
|
||||||
|
def show
|
||||||
|
@bank_attachments = @bank.attachments.where(attachtype: 1)
|
||||||
|
@reference_attachments = @bank.attachments.where(attachtype: 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer])
|
||||||
|
|
||||||
|
# 作业描述的附件
|
||||||
|
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||||
|
# 作业参考答案的附件
|
||||||
|
Attachment.associate_container(params[:reference_attachment_ids], @bank.id, @bank.class, 2) if params[:reference_attachment_ids]
|
||||||
|
|
||||||
|
normal_status(0, "更新成功")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@bank.homework_commons.update_all(homework_bank_id: nil)
|
||||||
|
@bank.destroy!
|
||||||
|
normal_status("删除成功")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_public
|
||||||
|
@bank.update_attributes(is_public: 1)
|
||||||
|
normal_status("更新成功")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_bank
|
||||||
|
@bank = HomeworkBank.find_by!(id: params[:id])
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && (@bank.is_public || @bank.user_id == current_user.id)) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def bank_admin
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && @bank.user_id == current_user.id) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def bank_params
|
||||||
|
tip_exception("name参数不能为空") if params[:homework_bank][:name].blank?
|
||||||
|
tip_exception("description参数不能为空") if params[:homework_bank][:description].blank?
|
||||||
|
if @bank.homework_type == 3
|
||||||
|
tip_exception("base_on_project参数不能为空") if params[:homework_bank][:base_on_project].nil?
|
||||||
|
tip_exception("min_num参数不能为空") if params[:homework_bank][:min_num].blank?
|
||||||
|
tip_exception("max_num参数不能为空") if params[:homework_bank][:max_num].blank?
|
||||||
|
tip_exception("最小人数不能小于1") if params[:homework_bank][:min_num].to_i < 1
|
||||||
|
tip_exception("最大人数不能小于最小人数") if params[:homework_bank][:max_num].to_i < params[:homework_bank][:min_num].to_i
|
||||||
|
end
|
||||||
|
params.require(:homework_bank).permit(:name, :description, :reference_answer) if @bank.homework_type == 1
|
||||||
|
params.require(:homework_bank).permit(:name, :description, :reference_answer, :min_num, :max_num, :base_on_project) if @bank.homework_type == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,48 @@
|
|||||||
|
class TaskBanksController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_bank
|
||||||
|
before_action :bank_admin, only: [:update]
|
||||||
|
|
||||||
|
def show
|
||||||
|
@bank_attachments = @bank.attachments
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
begin
|
||||||
|
@bank.update_attributes(gtask_bank_params)
|
||||||
|
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||||
|
normal_status(0, "更新成功")
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
raise ActiveRecord::Rollback
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_bank
|
||||||
|
@bank = GtaskBank.find_by!(id: params[:id])
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && (@bank.is_public || @bank.user_id == current_user.id)) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def bank_admin
|
||||||
|
tip_exception(403, "无权限") unless (current_user.certification_teacher? && @bank.user_id == current_user.id) || current_user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def gtask_bank_params
|
||||||
|
tip_exception("name参数不能为空") if params[:gtask_bank][:name].blank?
|
||||||
|
tip_exception("description参数不能为空") if params[:gtask_bank][:description].blank?
|
||||||
|
if @bank.homework_type == 3
|
||||||
|
tip_exception("base_on_project参数不能为空") if params[:gtask_bank][:base_on_project].nil?
|
||||||
|
tip_exception("min_num参数不能为空") if params[:gtask_bank][:min_num].blank?
|
||||||
|
tip_exception("max_num参数不能为空") if params[:gtask_bank][:max_num].blank?
|
||||||
|
tip_exception("最小人数不能小于1") if params[:gtask_bank][:min_num].to_i < 1
|
||||||
|
tip_exception("最大人数不能小于最小人数") if params[:gtask_bank][:max_num].to_i < params[:gtask_bank][:min_num].to_i
|
||||||
|
end
|
||||||
|
params.require(:gtask_bank).permit(:name, :description) if @bank.task_type == 1
|
||||||
|
params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project) if @bank.task_type == 2
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,2 @@
|
|||||||
|
module ExerciseBankQuestionsHelper
|
||||||
|
end
|
@ -0,0 +1,2 @@
|
|||||||
|
module HomeworkBanksHelper
|
||||||
|
end
|
@ -1,4 +1,7 @@
|
|||||||
class ExerciseBankChoice < ApplicationRecord
|
class ExerciseBankChoice < ApplicationRecord
|
||||||
belongs_to :exercise_bank_question
|
belongs_to :exercise_bank_question
|
||||||
has_many :exercise_bank_standard_answers
|
has_many :exercise_bank_standard_answers
|
||||||
|
|
||||||
|
scope :find_choice_custom, lambda {|k,v| where("#{k} = ?",v)} #根据传入的参数查找问题
|
||||||
|
scope :left_choice_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题
|
||||||
end
|
end
|
@ -0,0 +1,29 @@
|
|||||||
|
wb = xlsx_package.workbook
|
||||||
|
wb.use_shared_strings = true
|
||||||
|
wb.styles do |s|
|
||||||
|
no_wrap_sz = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: false,:horizontal => :center,:vertical => :center }
|
||||||
|
sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center }
|
||||||
|
row_cell = s.add_style :bg_color=> "FAEBDC",:border => { :style => :thin, :color =>"000000" },alignment: {wrap_text: true,:horizontal => :center,:vertical => :center }
|
||||||
|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
|
||||||
|
|
||||||
|
#课堂信息摘要
|
||||||
|
wb.add_worksheet(name:course_info[0]) do |sheet|
|
||||||
|
sheet.sheet_view.show_grid_lines = false
|
||||||
|
course_main_info = course_info[1]
|
||||||
|
course_group_info = course_info[2]
|
||||||
|
group_info_d = course_group_info[0]
|
||||||
|
group_info_detail = course_group_info[1]
|
||||||
|
course_main_info.each do |c|
|
||||||
|
sheet.add_row c, :style => sz_all #用户id
|
||||||
|
end
|
||||||
|
sheet["A1:A7"].each { |c| c.style = row_cell }
|
||||||
|
sheet.add_row [],:style => sz_all
|
||||||
|
if group_info_detail.count > 0
|
||||||
|
sheet.add_row group_info_d, :style => blue_cell
|
||||||
|
group_info_detail.each do |group|
|
||||||
|
sheet.add_row group, :style => sz_all #用户id
|
||||||
|
end
|
||||||
|
sheet.column_info.second.width = 40
|
||||||
|
end
|
||||||
|
end #add_worksheet
|
||||||
|
end
|
@ -0,0 +1,25 @@
|
|||||||
|
wb = xlsx_package.workbook
|
||||||
|
wb.use_shared_strings = true
|
||||||
|
wb.styles do |s|
|
||||||
|
no_wrap_sz = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: false,:horizontal => :center,:vertical => :center }
|
||||||
|
sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center }
|
||||||
|
row_cell = s.add_style :bg_color=> "FAEBDC",:border => { :style => :thin, :color =>"000000" },alignment: {wrap_text: true,:horizontal => :center,:vertical => :center }
|
||||||
|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
|
||||||
|
|
||||||
|
#课堂活跃度统计
|
||||||
|
wb.add_worksheet(name:activity_level[0]) do |sheet|
|
||||||
|
sheet.sheet_view.show_grid_lines = false
|
||||||
|
sheet_title = activity_level[1]
|
||||||
|
sheet_content = activity_level[2]
|
||||||
|
sheet.add_row sheet_title, :height => 25,:style => blue_cell
|
||||||
|
if sheet_content.count > 0
|
||||||
|
sheet_content.each_with_index do |c,index|
|
||||||
|
c_1 = (index+1)
|
||||||
|
c_2 = [c_1] + c.values
|
||||||
|
sheet.add_row c_2, :height => 25, :style => sz_all #用户id
|
||||||
|
end
|
||||||
|
sheet.column_widths *([20]*sheet.column_info.count)
|
||||||
|
sheet.column_info.first.width = 8
|
||||||
|
end
|
||||||
|
end #add_worksheet
|
||||||
|
end
|
@ -0,0 +1,16 @@
|
|||||||
|
json.exercise do
|
||||||
|
json.extract! @bank, :id, :name, :description, :is_public
|
||||||
|
end
|
||||||
|
|
||||||
|
json.partial! "exercises/exercise_scores"
|
||||||
|
|
||||||
|
json.exercise_questions do
|
||||||
|
json.array! @exercise_questions do |q|
|
||||||
|
json.partial! "exercise_bank_questions/exercise_bank_questions",
|
||||||
|
question: q,
|
||||||
|
choices:q.exercise_bank_choices,
|
||||||
|
shixun_challenges: q.exercise_bank_shixun_challenges,
|
||||||
|
ques_position:nil,
|
||||||
|
edit_type:nil
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
json.topic_type topic_type
|
||||||
|
json.topic_source topic_source
|
||||||
|
json.topic_property_first topic_property_first
|
||||||
|
json.topic_property_second topic_property_second
|
||||||
|
json.topic_repeat topic_repeat
|
||||||
|
|
||||||
|
json.selected_data do
|
||||||
|
json.(@bank, :name, :topic_type, :topic_source, :topic_property_first,
|
||||||
|
:description, :topic_property_second, :source_unit, :topic_repeat,
|
||||||
|
:province, :city, :is_public)
|
||||||
|
end
|
||||||
|
|
||||||
|
json.attachments @attachments do |attachment|
|
||||||
|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
|
||||||
|
end
|
@ -0,0 +1,6 @@
|
|||||||
|
json.(@bank, :id, :name, :description, :is_public, :topic_type, :topic_source, :topic_property_first, :topic_property_second,
|
||||||
|
:source_unit, :topic_repeat, :province, :city)
|
||||||
|
|
||||||
|
json.attachment_list @bank_attachments do |attachment|
|
||||||
|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
|
||||||
|
end
|
@ -0,0 +1,9 @@
|
|||||||
|
json.(@bank, :id, :name, :description, :homework_type, :is_public, :min_num, :max_num, :base_on_project, :reference_answer)
|
||||||
|
|
||||||
|
json.attachments @bank_attachments do |attachment|
|
||||||
|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
|
||||||
|
end
|
||||||
|
|
||||||
|
json.reference_attachments @reference_attachments do |attachment|
|
||||||
|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
|
||||||
|
end
|
@ -0,0 +1,4 @@
|
|||||||
|
json.courses @courses do |course|
|
||||||
|
json.course_id course.id
|
||||||
|
json.course_name course.name
|
||||||
|
end
|
@ -0,0 +1,14 @@
|
|||||||
|
json.(@bank, :id, :name, :description, :task_type, :is_public)
|
||||||
|
# 附件
|
||||||
|
json.attachments @bank_attachments do |attachment|
|
||||||
|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
|
||||||
|
end
|
||||||
|
|
||||||
|
# 分组要求
|
||||||
|
if @bank.task_type == 2
|
||||||
|
json.group_info do
|
||||||
|
json.max_number @bank.max_num
|
||||||
|
json.min_number @bank.min_num
|
||||||
|
json.base_on_project @bank.base_on_project
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddIsOrderedToExerciseBankQuestion < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :exercise_bank_questions, :is_ordered, :boolean, :default => true
|
||||||
|
end
|
||||||
|
end
|
@ -1,189 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// Do this as the first thing so that any code reading it knows the right env.
|
|
||||||
process.env.BABEL_ENV = 'production';
|
|
||||||
process.env.NODE_ENV = 'production';
|
|
||||||
|
|
||||||
// Makes the script crash on unhandled rejections instead of silently
|
|
||||||
// ignoring them. In the future, promise rejections that are not handled will
|
|
||||||
// terminate the Node.js process with a non-zero exit code.
|
|
||||||
process.on('unhandledRejection', err => {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure environment variables are read.
|
|
||||||
require('../config/env');
|
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const fs = require('fs-extra');
|
|
||||||
const webpack = require('webpack');
|
|
||||||
const config = require('../config/webpack.config.prod');
|
|
||||||
const paths = require('../config/paths');
|
|
||||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
|
||||||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
|
||||||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
|
|
||||||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
|
|
||||||
const printBuildError = require('react-dev-utils/printBuildError');
|
|
||||||
|
|
||||||
var CombinedStream = require('combined-stream');
|
|
||||||
var fs2 = require('fs');
|
|
||||||
|
|
||||||
const measureFileSizesBeforeBuild =
|
|
||||||
FileSizeReporter.measureFileSizesBeforeBuild;
|
|
||||||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
|
|
||||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
|
||||||
|
|
||||||
// These sizes are pretty large. We'll warn for bundles exceeding them.
|
|
||||||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
|
||||||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
|
||||||
|
|
||||||
// Warn and crash if required files are missing
|
|
||||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, read the current file sizes in build directory.
|
|
||||||
// This lets us display how much they changed later.
|
|
||||||
measureFileSizesBeforeBuild(paths.appBuild)
|
|
||||||
.then(previousFileSizes => {
|
|
||||||
// Remove all content but keep the directory so that
|
|
||||||
// if you're in it, you don't end up in Trash
|
|
||||||
fs.emptyDirSync(paths.appBuild);
|
|
||||||
// Merge with the public folder
|
|
||||||
copyPublicFolder();
|
|
||||||
// Start the webpack build
|
|
||||||
return build(previousFileSizes);
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
({ stats, previousFileSizes, warnings }) => {
|
|
||||||
if (warnings.length) {
|
|
||||||
console.log(chalk.yellow('Compiled with warnings.\n'));
|
|
||||||
console.log(warnings.join('\n\n'));
|
|
||||||
console.log(
|
|
||||||
'\nSearch for the ' +
|
|
||||||
chalk.underline(chalk.yellow('keywords')) +
|
|
||||||
' to learn more about each warning.'
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
'To ignore, add ' +
|
|
||||||
chalk.cyan('// eslint-disable-next-line') +
|
|
||||||
' to the line before.\n'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log(chalk.green('Compiled successfully.\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('File sizes after gzip:\n');
|
|
||||||
printFileSizesAfterBuild(
|
|
||||||
stats,
|
|
||||||
previousFileSizes,
|
|
||||||
paths.appBuild,
|
|
||||||
WARN_AFTER_BUNDLE_GZIP_SIZE,
|
|
||||||
WARN_AFTER_CHUNK_GZIP_SIZE
|
|
||||||
);
|
|
||||||
console.log();
|
|
||||||
|
|
||||||
const appPackage = require(paths.appPackageJson);
|
|
||||||
const publicUrl = paths.publicUrl;
|
|
||||||
const publicPath = config.output.publicPath;
|
|
||||||
const buildFolder = path.relative(process.cwd(), paths.appBuild);
|
|
||||||
printHostingInstructions(
|
|
||||||
appPackage,
|
|
||||||
publicUrl,
|
|
||||||
publicPath,
|
|
||||||
buildFolder,
|
|
||||||
useYarn
|
|
||||||
);
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
console.log(chalk.red('Failed to compile.\n'));
|
|
||||||
printBuildError(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create the production build and print the deployment instructions.
|
|
||||||
function build(previousFileSizes) {
|
|
||||||
console.log('Creating an optimized production build...');
|
|
||||||
|
|
||||||
let compiler = webpack(config);
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
compiler.run((err, stats) => {
|
|
||||||
if (err) {
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
const messages = formatWebpackMessages(stats.toJson({}, true));
|
|
||||||
if (messages.errors.length) {
|
|
||||||
// Only keep the first error. Others are often indicative
|
|
||||||
// of the same problem, but confuse the reader with noise.
|
|
||||||
if (messages.errors.length > 1) {
|
|
||||||
messages.errors.length = 1;
|
|
||||||
}
|
|
||||||
return reject(new Error(messages.errors.join('\n\n')));
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
process.env.CI &&
|
|
||||||
(typeof process.env.CI !== 'string' ||
|
|
||||||
process.env.CI.toLowerCase() !== 'false') &&
|
|
||||||
messages.warnings.length
|
|
||||||
) {
|
|
||||||
console.log(
|
|
||||||
chalk.yellow(
|
|
||||||
'\nTreating warnings as errors because process.env.CI = true.\n' +
|
|
||||||
'Most CI servers set it automatically.\n'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return reject(new Error(messages.warnings.join('\n\n')));
|
|
||||||
}
|
|
||||||
|
|
||||||
generateNewIndexJsp();
|
|
||||||
|
|
||||||
return resolve({
|
|
||||||
stats,
|
|
||||||
previousFileSizes,
|
|
||||||
warnings: messages.warnings,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyPublicFolder() {
|
|
||||||
fs.copySync(paths.appPublic, paths.appBuild, {
|
|
||||||
dereference: true,
|
|
||||||
filter: file => file !== paths.appHtml,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function generateNewIndexJsp() {
|
|
||||||
// var combinedStream = CombinedStream.create();
|
|
||||||
var filePath = paths.appBuild + '/index.html';
|
|
||||||
// var htmlContent = fs2.createReadStream( filePath )
|
|
||||||
|
|
||||||
// stream没有replace方法
|
|
||||||
// htmlContent = htmlContent.replace('/js/js_min_all.js', '/react/build/js/js_min_all.js')
|
|
||||||
// htmlContent = htmlContent.replace('/css/css_min_all.css', '/react/build/css/css_min_all.css')
|
|
||||||
|
|
||||||
// combinedStream.append(htmlContent);
|
|
||||||
// combinedStream.pipe(fs2.createWriteStream( filePath ));
|
|
||||||
|
|
||||||
var outputPath = paths.appBuild + '/../../../app/views/common/index.html.erb'
|
|
||||||
fs2.readFile(filePath, 'utf8', function (err,data) {
|
|
||||||
if (err) {
|
|
||||||
return console.log(err);
|
|
||||||
}
|
|
||||||
var result = data.replace('/js/js_min_all.js', '/react/build/js/js_min_all.js')
|
|
||||||
.replace('/js/js_min_all_2.js', '/react/build/js/js_min_all_2.js')
|
|
||||||
|
|
||||||
.replace('/css/css_min_all.css', '/react/build/css/css_min_all.css')
|
|
||||||
.replace('/js/create_kindeditor.js', '/react/build/js/create_kindeditor.js')
|
|
||||||
.replace(/http:\/\/localhost:3000/g, '');
|
|
||||||
|
|
||||||
// .replace('/css/css_min_all.css', '/react/build/css/css_min_all.css');
|
|
||||||
|
|
||||||
fs2.writeFile(outputPath, result, 'utf8', function (err) {
|
|
||||||
if (err) return console.log(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// Do this as the first thing so that any code reading it knows the right env.
|
|
||||||
process.env.BABEL_ENV = 'development';
|
|
||||||
process.env.NODE_ENV = 'development';
|
|
||||||
|
|
||||||
|
|
||||||
// Makes the script crash on unhandled rejections instead of silently
|
|
||||||
// ignoring them. In the future, promise rejections that are not handled will
|
|
||||||
// terminate the Node.js process with a non-zero exit code.
|
|
||||||
process.on('unhandledRejection', err => {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure environment variables are read.
|
|
||||||
require('../config/env');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const webpack = require('webpack');
|
|
||||||
const WebpackDevServer = require('webpack-dev-server');
|
|
||||||
const clearConsole = require('react-dev-utils/clearConsole');
|
|
||||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
|
||||||
const {
|
|
||||||
choosePort,
|
|
||||||
createCompiler,
|
|
||||||
prepareProxy,
|
|
||||||
prepareUrls,
|
|
||||||
} = require('react-dev-utils/WebpackDevServerUtils');
|
|
||||||
const openBrowser = require('react-dev-utils/openBrowser');
|
|
||||||
const paths = require('../config/paths');
|
|
||||||
const config = require('../config/webpack.config.dev');
|
|
||||||
const createDevServerConfig = require('../config/webpackDevServer.config');
|
|
||||||
|
|
||||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
|
||||||
const isInteractive = process.stdout.isTTY;
|
|
||||||
|
|
||||||
const portSetting = require(paths.appPackageJson).port
|
|
||||||
if ( portSetting ) {
|
|
||||||
process.env.port = portSetting
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn and crash if required files are missing
|
|
||||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tools like Cloud9 rely on this.
|
|
||||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
|
||||||
const HOST = process.env.HOST || '0.0.0.0';
|
|
||||||
|
|
||||||
if (process.env.HOST) {
|
|
||||||
console.log(
|
|
||||||
chalk.cyan(
|
|
||||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
|
||||||
chalk.bold(process.env.HOST)
|
|
||||||
)}`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
|
|
||||||
);
|
|
||||||
console.log(`Learn more here: ${chalk.yellow('http://bit.ly/2mwWSwH')}`);
|
|
||||||
console.log();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We attempt to use the default port but if it is busy, we offer the user to
|
|
||||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
|
||||||
choosePort(HOST, DEFAULT_PORT)
|
|
||||||
.then(port => {
|
|
||||||
if (port == null) {
|
|
||||||
// We have not found a port.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
|
||||||
const appName = require(paths.appPackageJson).name;
|
|
||||||
const urls = prepareUrls(protocol, HOST, port);
|
|
||||||
// Create a webpack compiler that is configured with custom messages.
|
|
||||||
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
|
|
||||||
// Load proxy config
|
|
||||||
const proxySetting = require(paths.appPackageJson).proxy;
|
|
||||||
console.log('-------------------------proxySetting:', proxySetting)
|
|
||||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
|
||||||
// Serve webpack assets generated by the compiler over a web sever.
|
|
||||||
const serverConfig = createDevServerConfig(
|
|
||||||
proxyConfig,
|
|
||||||
urls.lanUrlForConfig
|
|
||||||
);
|
|
||||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
|
||||||
// Launch WebpackDevServer.
|
|
||||||
devServer.listen(port, HOST, err => {
|
|
||||||
if (err) {
|
|
||||||
return console.log(err);
|
|
||||||
}
|
|
||||||
if (isInteractive) {
|
|
||||||
clearConsole();
|
|
||||||
}
|
|
||||||
console.log(chalk.cyan('Starting the development server...\n'));
|
|
||||||
openBrowser(urls.localUrlForBrowser);
|
|
||||||
});
|
|
||||||
|
|
||||||
['SIGINT', 'SIGTERM'].forEach(function(sig) {
|
|
||||||
process.on(sig, function() {
|
|
||||||
devServer.close();
|
|
||||||
process.exit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
if (err && err.message) {
|
|
||||||
console.log(err.message);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// Do this as the first thing so that any code reading it knows the right env.
|
|
||||||
process.env.BABEL_ENV = 'test';
|
|
||||||
process.env.NODE_ENV = 'test';
|
|
||||||
process.env.PUBLIC_URL = '';
|
|
||||||
|
|
||||||
// Makes the script crash on unhandled rejections instead of silently
|
|
||||||
// ignoring them. In the future, promise rejections that are not handled will
|
|
||||||
// terminate the Node.js process with a non-zero exit code.
|
|
||||||
process.on('unhandledRejection', err => {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure environment variables are read.
|
|
||||||
require('../config/env');
|
|
||||||
|
|
||||||
const jest = require('jest');
|
|
||||||
const argv = process.argv.slice(2);
|
|
||||||
|
|
||||||
// Watch unless on CI or in coverage mode
|
|
||||||
if (!process.env.CI && argv.indexOf('--coverage') < 0) {
|
|
||||||
argv.push('--watch');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
jest.run(argv);
|
|
@ -0,0 +1,5 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe HomeworkBanksController, type: :controller do
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
# Specs in this file have access to a helper object that includes
|
||||||
|
# the HomeworkBanksHelper. For example:
|
||||||
|
#
|
||||||
|
# describe HomeworkBanksHelper do
|
||||||
|
# describe "string concat" do
|
||||||
|
# it "concats two strings with spaces" do
|
||||||
|
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
RSpec.describe HomeworkBanksHelper, type: :helper do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
Loading…
Reference in new issue