Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_forum
jingquan huang 5 years ago
commit 4212712edf

@ -0,0 +1,17 @@
class Users::ProjectPackagesController < Users::BaseController
def index
packages = Users::ProjectPackageService.call(observed_user, query_params)
@count = packages.count
@packages = paginate(packages.includes(:project_package_category))
bidding_users = BiddingUser.where(project_package_id: @packages.map(&:id), user_id: observed_user.id)
bidding_users = bidding_users.group(:project_package_id).select(:project_package_id, :status)
@bidding_status_map = bidding_users.each_with_object({}) { |u, h| h[u.project_package_id] = u.status }
end
def query_params
params.permit(:category, :status, :sort_by, :sort_direction)
end
end

@ -13,6 +13,9 @@ class ProjectPackage < ApplicationRecord
has_many :attachments, as: :container, dependent: :destroy
scope :visible, -> { where(status: %i[published bidding_ended bidding_finished]) }
scope :invisible, -> { where(status: %i[pending applying refused]) }
aasm(:status) do
state :pending, initiali: true
state :applying

@ -123,6 +123,11 @@ class User < ApplicationRecord
has_many :user_interests, dependent: :delete_all
has_many :interests, through: :user_interests, source: :repertoire
# 众包
has_many :project_packages, foreign_key: :creator_id, dependent: :destroy
has_many :bidding_users, dependent: :destroy
has_many :bidden_project_packages, through: :bidding_users, source: :project_package
# Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) }
@ -572,6 +577,10 @@ class User < ApplicationRecord
Attendance.find_by(user_id: id)&.next_gold || 60 # 基础50连续签到+10
end
def admin_or_business?
admin? || business?
end
protected
def validate_password_length
# 管理员的初始密码是5位

@ -0,0 +1,76 @@
class Users::ProjectPackageService < ApplicationService
include CustomSortable
sort_columns :published_at, default_by: :published_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
packages = category_scope_filter
packages = user_policy_filter(packages)
custom_sort(packages, :published_at, params[:sort_direction])
end
private
def category_scope_filter
case params[:category]
when 'bidden' then
user.bidden_project_packages
when 'manage' then
user.project_packages
else
ids = user.bidding_users.pluck(:project_package_id) + user.project_packages.pluck(:id)
ProjectPackage.where(id: ids)
end
end
def user_policy_filter(relations)
if self_or_admin?
status_filter(relations)
else
relations.visible
end
end
def status_filter(relations)
return relations unless self_or_admin?
case params[:category]
when 'bidden' then bidding_status_filter(relations)
when 'manage' then package_status_filter(relations)
else relations
end
end
def bidding_status_filter(relations)
case params[:status]
when 'bidding_lost' then
relations.where(bidding_users: { status: :bidding_lost })
when 'bidding_won' then
relations.where(bidding_users: { status: :bidding_won })
else
relations
end
end
def package_status_filter(relations)
case params[:status]
when 'unpublished' then relations.invisible
when 'bidding' then relations.where(status: :published)
when 'finished' then relations.where(status: %w[bidding_ended bidding_finished])
else relations
end
end
def self_or_admin?
User.current&.id == user.id || User.current&.admin_or_business?
end
end

@ -0,0 +1,20 @@
user = observed_user
json.count @count
json.project_packages do
json.array! @packages.each do |package|
json.extract! package, :id, :title, :status, :min_price, :max_price, :visit_count, :bidding_users_count
is_creator = user.id == package.creator_id
json.type is_creator ? 'manage' : 'bidden'
json.category_id package.project_package_category_id
json.category_name package.category_name
unless is_creator
json.bidden_status @bidding_status_map[package.id]
end
json.deadline_at package.display_deadline_at
json.published_at package.display_published_at
end
end

@ -50,6 +50,7 @@ Rails.application.routes.draw do
resource :experience_records, only: [:show]
resource :grade_records, only: [:show]
resource :watch, only: [:create, :destroy]
resources :project_packages, only: [:index]
end

@ -0,0 +1,15 @@
class ModifyFinalScoreForGames < ActiveRecord::Migration[5.2]
def change
grades = Grade.where(container_type: "Answer")
grades.each do |grade|
g = Game.find_by_id(grade.container_id)
if g.present?
if g.status == 2 && g.answer_open > 0 && g.final_score <= 0 && g.end_time < grade.created_at
g.update_column(:final_score, g.challenge.score)
elsif g.final_score < 0
g.update_column(:final_score, 0)
end
end
end
end
end

@ -301,8 +301,8 @@ module.exports = {
},
warnings: false,
compress: {
drop_debugger: true,
drop_console: true
drop_debugger: false,
drop_console: false
}
}
}),

@ -2,7 +2,7 @@ import React from "react";
import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage ,SetAppModel, isDev, queryString} from 'educoder';
import { broadcastChannelOnmessage ,SetAppModel} from 'educoder';
import { notification } from 'antd';
import './index.css'
broadcastChannelOnmessage('refreshPage', () => {
@ -18,19 +18,10 @@ function locationurl(list){
}
// TODO 开发期多个身份切换
let debugType = ""
if (isDev) {
const _search = window.location.search;
let parsed = {};
if (_search) {
parsed = queryString.parse(_search);
}
debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
window.location.search.indexOf('debug=s') != -1 ? 'student' :
window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || ''
}
window._debugType = debugType;
const debugType =""
// window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
// window.location.search.indexOf('debug=s') != -1 ? 'student' : 'admin'
// window._debugType = debugType;
export function initAxiosInterceptors(props) {
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation

@ -147,6 +147,8 @@ class Addcourses extends Component{
if(Addcoursestype===true){
this.props.hideAddcoursestype();
}else{
window.location.href = "/";
}
}

@ -88,11 +88,11 @@ class CoursesNew extends Component {
}
componentDidUpdate(prevProps){
if(prevProps.current_user!=this.props.current_user){
if(this.props.current_user.user_identity==="学生"){
window.location.href ="/403"
}
}
// if(prevProps.current_user!=this.props.current_user){
// if(this.props.current_user.user_identity==="学生"){
// window.location.href ="/403"
// }
// }
}
onChangeTimepublishs = (date, dateString) => {
if(dateString===""){
@ -132,7 +132,7 @@ class CoursesNew extends Component {
e.preventDefault();
let coursesId = this.props.match.params.coursesId;
let {is_public} = this.state
let {is_public,datatime} = this.state
// console.log(is_public)
if (coursesId != undefined) {
@ -173,7 +173,7 @@ class CoursesNew extends Component {
// console.log('Received values of form: ', values);
let {datatime} = this.state;
let url = "/courses/" + coursesId + ".json";
axios.put(url, {
course_list_name: values.course,
@ -227,7 +227,7 @@ class CoursesNew extends Component {
// debugger
//新建
// console.log('Received values of form: ', values);
let {datatime} = this.state;
let url = "/courses.json";
axios.post(url, {
course_list_name: values.course,

@ -382,7 +382,7 @@ class ShixunhomeWorkItem extends Component{
<a className="btn colorblue font-16" href={"/shixuns/"+discussMessage.shixun_identifier+"/challenges"} target={"_blank"}>实训详情</a>
{this.props.isAdminOrCreator()?<a onClick={()=>this.editname(discussMessage.name,discussMessage.homework_id)} className={"btn colorblue ml20 font-16"}>重命名</a>:""}
{/*<WordsBtn className="btn colorblue ml20 font-16" to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${discussMessage.homework_id}/settings?tab=3`} > 设置</WordsBtn>*/}
<WordsBtn className="btn colorblue font-16" to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${discussMessage.homework_id}/settings?tab=3`} > 设置</WordsBtn>
<WordsBtn className="btn colorblue font-16 ml15" to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${discussMessage.homework_id}/settings?tab=3`} > 设置</WordsBtn>
</div>:""}

@ -9,7 +9,7 @@
/* z-index: 20000; */
}
#DialogID .dialogBox {
width: 402px;
width: 400px;
}
.MuiPaper-elevation24-45{
box-shadow:none !important;
@ -24,7 +24,7 @@
top: 0px !important;
}
#log_reg_content{
width:400px !important;
width:405px !important;
border-radius:6px;
box-shadow:4px 8px 12px rgba(76,76,76,0.3);
}

@ -406,7 +406,7 @@ class Trialapplication extends Component {
top: 0px !important;
}
#log_reg_content{
width:400px !important;
width:405px !important;
border-radius:40px !important;
box-shadow:4px 8px 12px rgba(76,76,76,0.3);
}

@ -424,7 +424,7 @@ class Trialapplicationysl extends Component {
top: 0px !important;
}
#log_reg_content{
width:400px !important;
width:405px !important;
border-radius:40px !important;
box-shadow:4px 8px 12px rgba(76,76,76,0.3);
}

@ -139,7 +139,7 @@ class PathDetailIndex extends Component{
let pathid=this.props.match.params.pathId;
let url="/paths/"+pathid+".json";
axios.get(url).then((result)=>{
if (result.data.status == 407) {
if (result.data.status == 407 || result.data.status == 401) {
return;
}
if(result.data.allow_visit===true){
@ -164,9 +164,11 @@ class PathDetailIndex extends Component{
let pathid=this.props.match.params.pathId;
let url="/paths/"+pathid+".json";
axios.get(url).then((result)=>{
if (result.data.status == 407) {
// TODO 403 让后台返回status 403 比较好
if (result.data.status == 407 || result.data.status == 401) {
return;
}
if(result.data.allow_visit===true){
this.setState({
detailInfoList:result.data,

@ -487,20 +487,22 @@ submittojoinclass=(value)=>{
}
showSearchOpen=(e)=>{
debugger
this.setState({
showSearchOpentype:true
})
e.stopPropagation(e);//阻止冒泡
}
hideshowSearchOpen=(e)=>{
debugger
let {setevaluatinghides}=this.state;
if(setevaluatinghides===true){
this.setState({
showSearchOpentype:false,
setevaluatinghides:false
})
e.stopPropagation(e);//阻止冒泡
}
}
@ -518,6 +520,7 @@ submittojoinclass=(value)=>{
}
setevaluatinghides=()=>{
debugger
this.setState(
{
setevaluatinghides:true
@ -599,6 +602,7 @@ submittojoinclass=(value)=>{
// rolearr:["",""],
// console.log("618");
// console.log(user_phone_binded);
console.log(showSearchOpentype)
return (
<div className="newHeader" id="nHeader" >
@ -669,8 +673,21 @@ submittojoinclass=(value)=>{
><a href={this.props.Headertop===undefined?"":this.props.Headertop.auth}>工程认证</a></li>
</ul>
<div className="posi-search" id="posi-search">
<style>
{
`
.posi-searchs{
opacity: 1;
position: absolute;
top: -2px;
background: #fff;
z-index: 2;
right: -241px;
}
`
}
</style>
<div className="posi-searchs" >
<div className="search-all clearfix">
{/*<!--<a href="javascript:void(0)" className="search-clear fl" onclick="closeSearch();">×</a>-->*/}
<div className="fl pr search-clear edu-menu-panel" style={{display: 'none'}}>
@ -686,7 +703,9 @@ submittojoinclass=(value)=>{
{/*<input type="text" className="search-input fl" id="search-input" */}
{/*onKeyDown={this.onKeywordSearchKeyDown} name="search_keyword" placeholder="搜索实训项目"/>*/}
{/*搜索框*/}
{showSearchOpentype===true?<div className={"HeaderSearch"} onBlur={(e)=>this.hideshowSearchOpen(e)} onMouseLeave={()=>this.setevaluatinghides()}>
{showSearchOpentype===true?<div
className={"HeaderSearch"}
onBlur={(e)=>this.hideshowSearchOpen(e)} onMouseLeave={()=>this.setevaluatinghides()}>
<Search
id={"HeaderSearchs"}
placeholder="实践课程/翻转课堂/开发社区/交流问答"
@ -901,169 +920,3 @@ submittojoinclass=(value)=>{
export default NewHeader;
// <ul id="header-nav">
// <li className="active">1{/*<%= link_to "首页", home_path %>*/}</li>
// <li>2{/*<%= link_to "精选实训", shixuns_path %>*/}</li>
// <li>3{/*<%= link_to "实训路径", subjects_path %>*/}</li>
// <li>4{/*<%= link_to "在线课堂", courses_path %>*/}</li>
// <li>5{/*<%= link_to "讨论组", forums_path %>*/}</li>
// </ul>
{/*{*/}
{/*<a href={this.props.Headertop===undefined?"":this.props.Headertop.message_url}*/}
{/*style={{display:this.props.Headertop===undefined?"none":this.props.Headertop.new_message===true?"block":"none",position:'relative'}}*/}
{/*>*/}
{/*<span className="newslight" style={{display:user!=undefined&&user.login!=""?"block":"none"}}>*/}
{/*/!*{this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count > 99 ? '99+'*!/*/}
{/*/!*: this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count}*!/*/}
{/*</span>*/}
{/*</a>*/}
{/*}*/}
{/*{ this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count>0 &&*/}
{/*<a href={this.props.Headertop===undefined?"":this.props.Headertop.message_url}>*/}
{/*<span className="newslight" style={{display:user!=undefined&&user.login!=""?"block":"none"}}>*/}
{/*/!*{this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count > 99 ? '99+'*!/*/}
{/*/!*: this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count}*!/*/}
{/*</span>*/}
{/*</a>}*/}
{/*{ this.props.Headertop===undefined?"":user && this.props.Headertop.unread_message_count>0 &&*/}
{/*<span style={{display:user!=undefined&&user.login!=""?"block":"none"}}>*/}
{/*<div className="edu-menu-list edu-txt-center" style={{width: '220px', top: '60px'}}>*/}
{/*<a className="font-14 padding10" style={{lineHeight: '35px'}} href={this.props.Headertop===undefined?"":this.props.Headertop.message_url} >您有*/}
{/*<span className="color-orange">{this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count}</span>*/}
{/*条新消息,点击查看</a>*/}
{/*</div>*/}
{/*</span>*/}
{/*}*/}
{/*
需求消息数量
<div className="fl mr30 edu-menu-panel headIcon">
<a href={`/users/${user.login}/user_tidings`}><img src={getImageUrl(`images/educoder/icon/bell.svg`}></a>
<em className="newslight"></em>
<div className="edu-menu-list edu-txt-center" style="width:220px;top:60px">
<a className="font-14 padding10" style="line-height: 35px;" href={`/users/${user.login}/user_tidings`}>
您有<span className="color-orange">30</span>
</a>
</div>
</div>
*/}
// function loadHeader(){
// //头部导航条的----------显示搜索框
// $("#search-open").on("click",function(e){
// $(this).hide();
// // $("#header-nav").animate({opacity:"0"},1000);
// $(".posi-search").show() // animate({opacity:"1"},1000);
// $("#header-nav").css("z-index","2");
// $(".posi-search").css("z-index","3");
// $(".HeaderSearch").show();
// $(".HeaderSearch").val("");
// $(".search-input").focus();
// $(".search-all .search-content").hide();
// e.stopPropagation();//阻止冒泡
// });
// $(".HeaderSearch").on("click",function(e){
// debugger
// e.stopPropagation();//阻止冒泡
// });
//搜索框输入内容
// $("#HeaderSearchs").blur(function(e){
// closeSearch();
// e.stopPropagation();//阻止冒泡
// });
//点击页面其它(与搜索框无关的地方)都会将搜索框隐藏,所以与搜索框有关的地方需要阻止冒泡
// $("body").on("click",function(){
// closeSearch();
// });
// $(".HeaderSearch").on("input",function(e){
// $(".search-all .search-content").show();
// e.stopPropagation();//阻止冒泡
// });
//搜索
// $("#header_keyword_search").on("click", header_search);
// $("input[name='search_keyword']").on("keydown", function(event){
// var code;
// if (!event) {
// event = window.event; //针对ie浏览器
// code = event.keyCode;
// }
// else {
// code = event.keyCode;
// }
// if(code == 13) {
// header_search();
// return false;
// }
// });
// $(".search-clear").click(function(e){e.stopPropagation();});
// //切换搜索条件
// $("#searchkey li").click(function(e){
// var key=$($(this).children("a")[0]).html();
// switch (key){
// case '实训':
// $("#search_type").val('1');
// break;
// case '课堂':
// $("#search_type").val('2');
// break;
// case '用户':
// $("#search_type").val('3');
// break;
// }
// $("#searchkey").siblings(".searchkey").html(key);
// $("#searchkey").hide();
// e.stopPropagation();//阻止冒泡
// });
// //切换选择导航条
// $("#header-nav li").click(function(){
// $("#header-nav li").removeClass("active");
// $(this).addClass("active");
// });
//
//
// $(".search_history").on("click", function(){
// $("input[name='search_keyword']").val($(this).html());
// header_search();
// });
// }
//
// function header_search(reactHeaderComponnet){
// console.log(old_url)
// var keyword = $("input[name='search_keyword']").val(); // 搜索关键字
// window.location.href ="/search"+"?value="+keyword;
// // if (!reactHeaderComponnet) {
// // reactHeaderComponnet = window._header_componentHandler
// // }
// // if (!reactHeaderComponnet) {
// // var index = $("#search_type").val(); // 搜索课程/项目
// // keyword = encodeURIComponent(keyword);
// // // $.get('/users/search_shixuns_or_course',
// // // { search: keyword,
// // // index: index});
// // window.location.href = old_url+"/users/search_shixuns_or_courses" + "?search=" + keyword + "&index=" + index;
// //e.stopPropagation();//阻止冒泡
// // } else {
// // window.__headSearchKeyword = keyword
// // reactHeaderComponnet.props.history.push(`/shixuns`)
// // trigger('searchKeywordChange', keyword)
// // }
// }
// //头部导航条的隐藏
// function closeSearch(){
// $('#posi-search').hide();
// $("#search-open").show();
// // $(".posi-search").animate({opacity:"0"},800);
// $(".HeaderSearch").hide();
// $("#header-nav").animate({opacity:"1"},1000);
// $(".posi-search").css("z-index","2");
// $("#header-nav").css("z-index","3");
// }

@ -188,6 +188,10 @@ class InterestpageComponent extends Component {
if (response !== undefined) {
// this.Jumptotheinterestpage();
// window.location.href = "/"
if(response.data.message!==undefined){
return;
}
this.setMyEduCoderModals()
}

@ -189,6 +189,11 @@ class InterestpageMax extends Component {
if (response !== undefined) {
// this.Jumptotheinterestpage();
// window.location.href = "/"
if(response.data.message!==undefined){
return;
}
this.setMyEduCoderModals()
}

@ -263,3 +263,6 @@
width: 100px;
margin: 0 auto;
}
.ant-input-affix-wrapper .ant-input-prefix, .ant-input-affix-wrapper .ant-input-suffix {
background: #ffffff!important;
}
Loading…
Cancel
Save