diff --git a/.gitignore b/.gitignore index 944ad4ef2..ca12f81a9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ /Gemfile.lock /lib/plugins/acts_as_versioned/test/debug.log .rbenv-gemsets +.DS_Store +public/api_doc/ diff --git a/Gemfile b/Gemfile index dc834e68d..42bfc83db 100644 --- a/Gemfile +++ b/Gemfile @@ -1,39 +1,44 @@ source 'http://rubygems.org' -#source 'http://ruby.sdutlinux.org/' - -unless RUBY_PLATFORM =~ /w32/ - # unix-like only - gem 'iconv' - gem 'rubyzip' - gem 'zip-zip' -end - -gem 'seems_rateable', path: 'lib/seems_rateable' -gem "rails", "3.2.13" -gem "jquery-rails", "~> 2.0.2" -gem "i18n", "~> 0.6.0" -gem "coderay", "~> 1.0.6" -gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] -gem "builder", "3.0.0" -gem 'acts-as-taggable-on', '2.4.1' +#source 'http://ruby.sdutlinux.org/' + +unless RUBY_PLATFORM =~ /w32/ + # unix-like only + gem 'iconv' + gem 'rubyzip' + gem 'zip-zip' +end + +gem 'grape', '~> 0.9.0' +gem 'grape-entity' +gem 'seems_rateable', path: 'lib/seems_rateable' +gem "rails", "3.2.13" +gem "jquery-rails", "~> 2.0.2" +gem "i18n", "~> 0.6.0" +gem "coderay", "~> 1.0.6" +gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] +gem "builder", "3.0.0" +gem 'acts-as-taggable-on', '2.4.1' gem 'spreadsheet' gem 'ruby-ole' #gem 'email_verifier' - -group :development do - gem 'better_errors', path: 'lib/better_errors' - gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' -end - -group :test do - gem "shoulda", "~> 3.5.0" - gem "mocha", "~> 1.1.0" - gem 'capybara', '~> 2.4.1' - gem 'nokogiri', '~> 1.6.3' - gem 'factory_girl', '~> 4.4.0' - gem 'selenium-webdriver', '~> 2.42.0' - - + +group :development do + gem 'grape-swagger' + gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' + #gem 'puma' + gem 'better_errors', path: 'lib/better_errors' + gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' +end + +group :test do + gem "shoulda", "~> 3.5.0" + gem "mocha", "~> 1.1.0" + gem 'capybara', '~> 2.4.1' + gem 'nokogiri', '~> 1.6.3' + gem 'factory_girl', '~> 4.4.0' + gem 'selenium-webdriver', '~> 2.42.0' + + # platforms :mri, :mingw do # group :rmagick do # # RMagick 2 supports ruby 1.9 @@ -42,97 +47,86 @@ group :test do # gem "rmagick", ">= 2.0.0" # end #end -end - -group :development, :test do - # gem "guard-rails", '~> 0.5.3' - gem 'spork-testunit', '~> 0.0.8' - # gem 'guard-spork', '~> 1.5.1' - # gem 'guard-test', '~> 1.0.0' - gem 'ruby-prof', '~> 0.15.1' unless RUBY_PLATFORM =~ /w32/ - gem 'pry' - gem 'pry-nav' +end + gem 'rspec-rails' , '2.13.1' gem 'guard-rspec','2.5.0' -end - - -# Gems used only for assets and not required -# in production environments by default. -group :assets do - gem 'sass-rails', '~> 3.2.3' - gem 'coffee-rails', '~> 3.2.1' - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - gem 'therubyracer', :platforms => :ruby - - gem 'uglifier', '>= 1.0.3' -end - -# Optional gem for LDAP authentication -group :ldap do - gem "net-ldap", "~> 0.3.1" -end - - -# Optional gem for OpenID authentication -group :openid do - gem "ruby-openid", "~> 2.1.4", :require => "openid" - gem "rack-openid" -end - -# Optional gem for exporting the gantt to a PNG file, not supported with jruby -platforms :jruby do - # jruby-openssl is bundled with JRuby 1.7.0 - gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0' - gem "activerecord-jdbc-adapter", "1.2.5" -end - -# Include database gems for the adapters found in the database -# configuration file -require 'erb' -require 'yaml' -database_file = File.join(File.dirname(__FILE__), "config/database.yml") -if File.exist?(database_file) - database_config = YAML::load(ERB.new(IO.read(database_file)).result) - adapters = database_config.values.map {|c| c['adapter']}.compact.uniq - if adapters.any? - adapters.each do |adapter| - case adapter - when 'mysql2' - gem "mysql2", "= 0.3.11", :platforms => [:mri, :mingw] - gem "activerecord-jdbcmysql-adapter", :platforms => :jruby - when 'mysql' - gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw] - gem "activerecord-jdbcmysql-adapter", :platforms => :jruby - when /postgresql/ - gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw] - gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby - when /sqlite3/ - gem "sqlite3", :platforms => [:mri, :mingw] - gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby - when /sqlserver/ - gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw] - gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw] - else - warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems") - end - end - else - warn("No adapter found in config/database.yml, please configure it first") - end -else - warn("Please configure your config/database.yml first") -end - -local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") -if File.exists?(local_gemfile) - puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v` - instance_eval File.read(local_gemfile) -end - -# Load plugins' Gemfiles -Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| - puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` - instance_eval File.read(file) -end +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.2.3' + gem 'coffee-rails', '~> 3.2.1' + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + gem 'therubyracer', :platforms => :ruby + + gem 'uglifier', '>= 1.0.3' +end + +# Optional gem for LDAP authentication +group :ldap do + gem "net-ldap", "~> 0.3.1" +end + + +# Optional gem for OpenID authentication +group :openid do + gem "ruby-openid", "~> 2.1.4", :require => "openid" + gem "rack-openid" +end + +# Optional gem for exporting the gantt to a PNG file, not supported with jruby +platforms :jruby do + # jruby-openssl is bundled with JRuby 1.7.0 + gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0' + gem "activerecord-jdbc-adapter", "1.2.5" +end + +# Include database gems for the adapters found in the database +# configuration file +require 'erb' +require 'yaml' +database_file = File.join(File.dirname(__FILE__), "config/database.yml") +if File.exist?(database_file) + database_config = YAML::load(ERB.new(IO.read(database_file)).result) + adapters = database_config.values.map {|c| c['adapter']}.compact.uniq + if adapters.any? + adapters.each do |adapter| + case adapter + when 'mysql2' + gem "mysql2", "= 0.3.11", :platforms => [:mri, :mingw] + gem "activerecord-jdbcmysql-adapter", :platforms => :jruby + when 'mysql' + gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw] + gem "activerecord-jdbcmysql-adapter", :platforms => :jruby + when /postgresql/ + gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw] + gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby + when /sqlite3/ + gem "sqlite3", :platforms => [:mri, :mingw] + gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby + when /sqlserver/ + gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw] + gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw] + else + warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems") + end + end + else + warn("No adapter found in config/database.yml, please configure it first") + end +else + warn("Please configure your config/database.yml first") +end + +local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") +if File.exists?(local_gemfile) + puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v` + instance_eval File.read(local_gemfile) +end + +# Load plugins' Gemfiles +Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| + puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` + instance_eval File.read(file) +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..6677141c9 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,340 @@ +GIT + remote: https://github.com/guange2015/grape-swagger-ui.git + revision: 4c33439f236c174ae0e774b3435ef2547995c21d + specs: + grape-swagger-ui (0.0.4) + railties (>= 3.1) + +PATH + remote: lib/better_errors + specs: + better_errors (1.1.0) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + +PATH + remote: lib/rack-mini-profiler + specs: + rack-mini-profiler (0.9.1) + rack (>= 1.1.3) + +PATH + remote: lib/seems_rateable + specs: + seems_rateable (1.0.13) + jquery-rails + rails + +GEM + remote: http://rubygems.org/ + remote: https://rubygems.org/ + specs: + actionmailer (3.2.13) + actionpack (= 3.2.13) + mail (~> 2.5.3) + actionpack (3.2.13) + activemodel (= 3.2.13) + activesupport (= 3.2.13) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.4) + rack (~> 1.4.5) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.2.1) + activemodel (3.2.13) + activesupport (= 3.2.13) + builder (~> 3.0.0) + activerecord (3.2.13) + activemodel (= 3.2.13) + activesupport (= 3.2.13) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activeresource (3.2.13) + activemodel (= 3.2.13) + activesupport (= 3.2.13) + activesupport (3.2.13) + i18n (= 0.6.1) + multi_json (~> 1.0) + acts-as-taggable-on (2.4.1) + rails (>= 3, < 5) + arel (3.0.3) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) + builder (3.0.0) + capybara (2.4.1) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + celluloid (0.16.0) + timers (~> 4.0.0) + childprocess (0.5.3) + ffi (~> 1.0, >= 1.0.11) + climate_control (0.0.3) + activesupport (>= 3.0) + cocaine (0.5.4) + climate_control (>= 0.0.3, < 1.0) + coderay (1.0.9) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) + coffee-rails (3.2.2) + coffee-script (>= 2.2.0) + railties (~> 3.2.0) + coffee-script (2.3.0) + coffee-script-source + execjs + coffee-script-source (1.7.1) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + diff-lcs (1.2.5) + equalizer (0.0.9) + erubis (2.7.0) + execjs (2.2.1) + factory_girl (4.4.0) + activesupport (>= 3.0.0) + fastercsv (1.5.5) + ffi (1.9.3) + ffi (1.9.3-x86-mingw32) + formatador (0.2.5) + grape (0.9.0) + activesupport + builder + hashie (>= 2.1.0) + multi_json (>= 1.3.2) + multi_xml (>= 0.5.2) + rack (>= 1.3.0) + rack-accept + rack-mount + virtus (>= 1.0.0) + grape-entity (0.4.4) + activesupport + multi_json (>= 1.3.2) + grape-swagger (0.8.0) + grape + grape-entity + guard (2.11.1) + formatador (>= 0.2.4) + listen (~> 2.7) + lumberjack (~> 1.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-rspec (2.5.0) + guard (>= 1.1) + rspec (~> 2.11) + hashie (3.3.1) + hike (1.2.3) + hitimes (1.2.2-x86-mingw32) + htmlentities (4.3.2) + i18n (0.6.1) + ice_nine (0.11.0) + journey (1.0.4) + jquery-rails (2.0.3) + railties (>= 3.1.0, < 5.0) + thor (~> 0.14) + json (1.8.1) + kaminari (0.16.1) + actionpack (>= 3.0.0) + activesupport (>= 3.0.0) + libv8 (3.16.14.3) + listen (2.8.5) + celluloid (>= 0.15.2) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + lumberjack (1.0.9) + mail (2.5.4) + mime-types (~> 1.16) + treetop (~> 1.4.8) + metaclass (0.0.4) + method_source (0.8.2) + mime-types (1.25.1) + mini_portile (0.6.0) + mocha (1.1.0) + metaclass (~> 0.0.1) + multi_json (1.10.1) + multi_xml (0.5.5) + mysql2 (0.3.11) + mysql2 (0.3.11-x86-mingw32) + nenv (0.2.0) + net-ldap (0.3.1) + nokogiri (1.6.3) + mini_portile (= 0.6.0) + nokogiri (1.6.3-x86-mingw32) + mini_portile (= 0.6.0) + notiffany (0.0.3) + nenv (~> 0.1) + shellany (~> 0.0) + paperclip (3.5.4) + activemodel (>= 3.0.0) + activesupport (>= 3.0.0) + cocaine (~> 0.5.3) + mime-types + polyglot (0.3.5) + pry (0.9.12.6-x86-mingw32) + coderay (~> 1.0) + method_source (~> 0.8) + slop (~> 3.4) + win32console (~> 1.3) + rack (1.4.5) + rack-accept (0.4.5) + rack (>= 0.4) + rack-cache (1.2) + rack (>= 0.4) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-openid (1.4.2) + rack (>= 1.1.0) + ruby-openid (>= 2.1.8) + rack-raw-upload (1.1.1) + multi_json + rack-ssl (1.3.4) + rack + rack-test (0.6.2) + rack (>= 1.0) + rails (3.2.13) + actionmailer (= 3.2.13) + actionpack (= 3.2.13) + activerecord (= 3.2.13) + activeresource (= 3.2.13) + activesupport (= 3.2.13) + bundler (~> 1.0) + railties (= 3.2.13) + railties (3.2.13) + actionpack (= 3.2.13) + activesupport (= 3.2.13) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (>= 0.14.6, < 2.0) + rake (10.3.2) + rb-fsevent (0.9.4) + rb-inotify (0.9.5) + ffi (>= 0.5.0) + rdoc (3.12.2) + json (~> 1.4) + ref (1.0.5) + rich (1.4.6) + jquery-rails + kaminari + mime-types + paperclip + rack-raw-upload + rails (>= 3.2.0) + sass-rails + rspec (2.13.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + rspec-core (2.13.1) + rspec-expectations (2.13.0) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.13.1) + rspec-rails (2.13.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + ruby-ole (1.2.11.7) + ruby-openid (2.1.8) + rubyzip (1.1.6) + sass (3.3.10) + sass-rails (3.2.6) + railties (~> 3.2.0) + sass (>= 3.1.10) + tilt (~> 1.3) + selenium-webdriver (2.42.0) + childprocess (>= 0.5.0) + multi_json (~> 1.0) + rubyzip (~> 1.0) + websocket (~> 1.0.4) + shellany (0.0.1) + shoulda (3.5.0) + shoulda-context (~> 1.0, >= 1.0.1) + shoulda-matchers (>= 1.4.1, < 3.0) + shoulda-context (1.2.1) + shoulda-matchers (2.6.1) + activesupport (>= 3.0.0) + slop (3.6.0) + spreadsheet (1.0.0) + ruby-ole (>= 1.0) + sprockets (2.2.2) + hike (~> 1.2) + multi_json (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + therubyracer (0.12.1) + libv8 (~> 3.16.14.0) + ref + thor (0.19.1) + thread_safe (0.3.4) + tilt (1.4.1) + timers (4.0.1) + hitimes + treetop (1.4.15) + polyglot + polyglot (>= 0.3.1) + tzinfo (0.3.40) + uglifier (2.5.1) + execjs (>= 0.3.0) + json (>= 1.8.0) + virtus (1.0.3) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) + equalizer (~> 0.0, >= 0.0.9) + websocket (1.0.7) + win32console (1.3.2-x86-mingw32) + xpath (2.0.0) + nokogiri (~> 1.3) + +PLATFORMS + ruby + x86-mingw32 + +DEPENDENCIES + activerecord-jdbc-adapter (= 1.2.5) + activerecord-jdbcmysql-adapter + acts-as-taggable-on (= 2.4.1) + better_errors! + builder (= 3.0.0) + capybara (~> 2.4.1) + coderay (~> 1.0.6) + coffee-rails (~> 3.2.1) + factory_girl (~> 4.4.0) + fastercsv (~> 1.5.0) + grape (~> 0.9.0) + grape-entity + grape-swagger + grape-swagger-ui! + guard-rspec (= 2.5.0) + htmlentities + i18n (~> 0.6.0) + jquery-rails (~> 2.0.2) + kaminari + mocha (~> 1.1.0) + mysql2 (= 0.3.11) + net-ldap (~> 0.3.1) + nokogiri (~> 1.6.3) + paperclip (~> 3.5.4) + rack-mini-profiler! + rack-openid + rails (= 3.2.13) + rich (= 1.4.6) + rspec-rails (= 2.13.1) + ruby-ole + ruby-openid (~> 2.1.4) + sass-rails (~> 3.2.3) + seems_rateable! + selenium-webdriver (~> 2.42.0) + shoulda (~> 3.5.0) + spreadsheet + therubyracer + uglifier (>= 1.0.3) diff --git a/app/api/mobile/api.rb b/app/api/mobile/api.rb new file mode 100644 index 000000000..8226a1020 --- /dev/null +++ b/app/api/mobile/api.rb @@ -0,0 +1,41 @@ +module Mobile + + class API < Grape::API + version 'v1', using: :path + format :json + content_type :json, "application/json;charset=UTF-8" + use Mobile::Middleware::ErrorHandler + + helpers do + def logger + API.logger + end + + def authenticate! + raise('Unauthorized. Invalid or expired token.') unless current_user + end + + def current_user + token = ApiKey.where(access_token: params[:token]).first + if token && !token.expired? + @current_user = User.find(token.user_id) + else + nil + end + end + end + + mount Apis::Auth + mount Apis::Users + mount Apis::Courses + mount Apis::Watches + mount Apis::Upgrade + mount Apis::Homeworks + + #add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'}) + add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) + + end +end + + diff --git a/app/api/mobile/apis/auth.rb b/app/api/mobile/apis/auth.rb new file mode 100644 index 000000000..320497e50 --- /dev/null +++ b/app/api/mobile/apis/auth.rb @@ -0,0 +1,48 @@ +#coding=utf-8 + +module Mobile + + module Entities + class Auth < Grape::Entity + expose :token + expose :user, using: User + end + end + + module Apis + class Auth < Grape::API + resource :auth do + desc "用户登录" + params do + requires :login, type: String, desc: 'Username or email' + requires :password, type: String, desc: 'Password' + end + post do + user,last_logon = ::User.try_to_login(params[:login], params[:password]) + if user + ::ApiKey.delete_all(user_id: user.id) + key = ::ApiKey.create!(user_id: user.id) + api_user = ::UsersService.new.show_user({id:user.id}) + present :data, {token: key.access_token, user: api_user}, using: Entities::Auth + present :status, 0 + else + raise 'Unauthorized.' + end + end + + desc "用户登出" + params do + requires :token, type: String + end + delete do + authenticate! + ::ApiKey.delete_all(user_id: current_user.id) + {status: 0} + end + + end + end + end +end + + diff --git a/app/api/mobile/apis/courses.rb b/app/api/mobile/apis/courses.rb new file mode 100644 index 000000000..7c1aa5e7e --- /dev/null +++ b/app/api/mobile/apis/courses.rb @@ -0,0 +1,216 @@ +#coding=utf-8 +module Mobile + module Apis + class Courses < Grape::API + resource :courses do + desc "获取所有课程" + params do + optional :school_id, type: Integer, desc: '传入学校id,返回该学校课程列表' + requires :per_page_count, type: Integer, desc: '每页总数' + requires :page, type: Integer, desc: '当前页码' + end + get do + cs = CoursesService.new + courses = cs.course_list(params) + present :data, courses, with: Mobile::Entities::Course + present :status, 0 + end + + desc "新建课程" + #current_user当前用户对象(不是id) + # params[:course][:name]:课程名称 + #params[:course][:password]:密码 + #params[:course][:description]:描述 + #params[:course][:is_public]:是否公开1公开,0私有 + #params[:course][:open_student]:是否公开学生列表1公开,0不公开,不公开时非课程成员无法看到学生列表 + #params[:course][:course_type]:暂时默认给1值。 + #params[:term]:学期(秋季学期或春季学期) + #params[:time]: 年份(例:2014) + #params[:setup_time]:暂不传(貌似已经没用了) + #params[:endup_time]: 暂不传(貌似已经没用了) + #params[:class_period]:学时总数 + params do + requires :token, type: String + requires :name, type: String, desc: '课程名称' + requires :password, type: String, desc: '密码' + requires :description, type: String, desc: '描述' + requires :is_public, type: Integer, desc: '是否公开 1公开 0私有' + requires :open_student, type: Integer, desc: '是否公开学生列表1公开,0不公开,不公开时非课程成员无法看到学生列表' + requires :course_type, type:Integer, desc: '暂时传1' + requires :term, type: String, desc: '学期(秋季学期或春季学期)' + requires :time, type: String, desc: '年份' + requires :class_period, type: String, desc: '学时总数' + end + post do + authenticate! + cs = CoursesService.new + cs_params = { + course: params.reject{|k,v| [:term,:time,:class_period].include?(k)}, + term: params[:term], + time: params[:time], + class_period: params[:class_period] + } + courses = cs.create_course(cs_params, current_user) + present :data, courses, with: Mobile::Entities::Course + present :status, 0 + end + + desc "编辑课程" + params do + requires :token, type: String + requires :course_id, type: Integer, desc: '课程id' + requires :name, type: String, desc: '课程名称' + requires :password, type: String, desc: '密码' + requires :description, type: String, desc: '描述' + requires :is_public, type: Integer, desc: '是否公开 1公开 0私有' + requires :open_student, type: Integer, desc: '是否公开学生列表1公开,0不公开,不公开时非课程成员无法看到学生列表' + requires :course_type, type:Integer, desc: '暂时传1' + requires :term, type: String, desc: '学期(秋季学期或春季学期)' + requires :time, type: String, desc: '年份' + requires :class_period, type: String, desc: '学时总数' + end + put do + authenticate! + cs = CoursesService.new + cs_params = { + course: params.reject{|k,v| [:term,:time,:class_period].include?(k)}, + term: params[:term], + time: params[:time], + class_period: params[:class_period] + } + course = ::Course.find(params[:course_id]) + cs.edit_course_authorize(current_user,course) + course = cs.edit_course(cs_params, course,current_user) + present :data, course, with: Mobile::Entities::Course + present :status, 0 + end + post do + end + + desc "加入课程" + params do + requires :token, type: String + requires :course_password, type: String + end + post ":id" do + authenticate! + cs = CoursesService.new + status = cs.join_course({:object_id => params[:id],:course_password => params[:course_password]},current_user) + out = {status: status[:state]} + message = case status[:state] + when 0; "加入成功" + when 1; "密码错误" + when 2; "课程已过期 请联系课程管理员重启课程。(在配置课程处)" + when 3; "您已经加入了课程" + when 4; "您加入的课程不存在" + when 5; "您还未登录" + else; "未知错误,请稍后再试" + end + out.merge(message: message) + end + + desc "退出课程" + params do + requires :token, type: String + end + delete ":id" do + authenticate! + cs = CoursesService.new + status = cs.exit_course({:object_id => params[:id]}, current_user) + out = {status: status} + message = case status + when 0; "退出成功" + when 1; "您不在课程中" + when 2; "您还未登录" + else; "未知错误,请稍后再试" + end + out.merge(message: message) + end + + desc "搜索课程" + params do + requires :name, type: String, desc: "课程名" + end + get 'search' do + cs = CoursesService.new + courses = cs.search_course(params) + present :data, courses, with: Mobile::Entities::Course + present :status, 0 + end + + desc "课程老师列表" + params do + requires :token, type: String + requires :course_id, type: Integer, desc: "课程id" + end + get 'teachers' do + cs = CoursesService.new + teachers = cs.course_teacher_or_student_list({role: '1'}, params[:course_id],current_user) + present :data, teachers, with: Mobile::Entities::User + present :status, 0 + end + + desc "课程学生列表" + params do + requires :token, type: String + requires :course_id, type: Integer, desc: "课程id" + end + get 'students' do + cs = CoursesService.new + students = cs.course_teacher_or_student_list({role: '2'}, params[:course_id],current_user) + present :data, students, with: Mobile::Entities::User + present :status, 0 + end + + desc "返回单个课程" + params do + requires :id, type: Integer + end + route_param :id do + get do + cs = CoursesService.new + course = cs.show_course(params,(current_user.nil? ? User.find(2):current_user)) + #course = Course.find(params[:id]) + {status: 0, data: course} + end + end + + desc "课程作业列表" + params do + requires :token, type: String + end + get "homeworks/:id" do + cs = CoursesService.new + homeworks = cs.homework_list params,current_user + present :data, homeworks, with: Mobile::Entities::Homework + present :status, 0 + end + + desc "课程通知列表" + params do + end + get ":course_id/news" do + cs = CoursesService.new + news = cs.course_news_list params + present :data, news, with: Mobile::Entities::News + present :status, 0 + end + + desc "显示课程通知" + params do + + end + get "news/:id" do + cs = CoursesService.new + cs.show_course_news_authorize(current_user.nil? ? User.find(2):current_user) + news = cs.show_course_news params,current_user.nil? ? User.find(2):current_user + present :data, news, with: Mobile::Entities::News + present :status, 0 + end + + + end + end + end +end + diff --git a/app/api/mobile/apis/homeworks.rb b/app/api/mobile/apis/homeworks.rb new file mode 100644 index 000000000..cba295064 --- /dev/null +++ b/app/api/mobile/apis/homeworks.rb @@ -0,0 +1,77 @@ +#coding=utf-8 + +module Mobile + module Apis + class Homeworks < Grape::API + + def self.get_service + HomeworkService.new + end + + resources :homeworks do + desc "作业详情" + params do + requires :id, type: Integer, desc: "作业ID" + end + route_param :id do + get do + homework = Homeworks.get_service.show_homework params + present :data, homework, with: Mobile::Entities::Homework + present :status, 0 + end + end + + desc "我的作品列表" + params do + requires :token, type: String + end + get ':user_id/homework_attachs' do + ue = Homeworks.get_service.my_homework_list params,current_user.nil? ? User.find(2):current_user + present :data, ue,with: Mobile::Entities::Course + present :status, 0 + end + + desc "启动匿评" + params do + requires :token, type: String + end + post ':id/start_anonymous_comment' do + statue = Homeworks.get_service.start_anonymous_comment params,current_user.nil? ? User.find(2):current_user + messages = "" + case statue + when 1 + messages = "启动成功" + when 2 + messages = "启动失败,作业总数大于等于2份时才能启动匿评" + when 3 + messages = "已开启匿评,请务重复开启" + end + present :data,messages + present :status, statue + end + + desc "关闭匿评" + params do + requires :token, type: String + end + post ':id/stop_anonymous_comment' do + Homeworks.get_service.stop_anonymous_comment params,current_user.nil? ? User.find(2):current_user + present :status, 0 + end + + desc "匿评作品详情" + params do + requires :token, type: String + end + get ':homework_id/anonymous_works_show' do + works,par = Homeworks.get_service.anonymous_works_show params.merge(:id => params[:homework_id]),current_user.nil? ? User.find(2):current_user + present :data, works ,with: Mobile::Entities::HomeworkAttach + present :otherdata,par,with: Mobile::Entities::AnonymousWorksParams + present :status, 0 + end + + + end + end + end +end diff --git a/app/api/mobile/apis/upgrade.rb b/app/api/mobile/apis/upgrade.rb new file mode 100644 index 000000000..02ff97185 --- /dev/null +++ b/app/api/mobile/apis/upgrade.rb @@ -0,0 +1,22 @@ +#coding=utf-8 + +module Mobile + module Apis + class Upgrade < Grape::API + resource :upgrade do + desc "get update info" + params do + requires :platform, type: String, desc: '平台名,android, ios' + end + get do + { + version: '2', + url: 'http://u06.shellinfo.cn/trustie/Trustie_Beta1.0.0_201412310917.apk', + desc: '更新了什么功能' + } + end + end + + end + end +end diff --git a/app/api/mobile/apis/users.rb b/app/api/mobile/apis/users.rb new file mode 100644 index 000000000..69260716e --- /dev/null +++ b/app/api/mobile/apis/users.rb @@ -0,0 +1,96 @@ +#coding=utf-8 +module Mobile + module Apis + class Users < Grape::API + resource :users do + + desc "注册用户" + params do + requires :login, type: String, desc: 'username' + requires :mail, type: String, desc: 'mail' + requires :password, type: String, desc: 'password' + end + post do + us = UsersService.new + user = us.register params.merge(:password_confirmation => params[:password], + :should_confirmation_password => true) + raise "register failed #{user.errors.full_messages}" if user.new_record? + + present :data, user, with: Mobile::Entities::User + present :status, 0 + end + + desc "显示用户" + params do + + end + get ':id' do + us = UsersService.new + ue = us.show_user params + present :data, ue,with: Mobile::Entities::User + present :status, 0 + end + + desc "修改用户" + params do + requires :token, type: String + #optional :file, type: File, desc: 'avatar' + optional :occupation, type: String + optional :brief_introduction, type: String + optional :province, type: String + optional :city, type: String + optional :gender, type: Integer + end + put ':id' do + authenticate! + us = UsersService.new + ue = us.edit_user params.merge(id: current_user.id) + present :data, ue,with: Mobile::Entities::User + present :status, 0 + end + + desc '获取用户课程' + params do + optional :token, type: String + end + + get ':id/courses' do + us = UsersService.new + ue = us.user_courses_list params,current_user.nil? ? User.find(2):current_user + present :data, ue,with: Mobile::Entities::Course + present :status, 0 + end + + + desc '修改密码' + params do + requires :token, type: String + requires :password, type:String , desc: '原密码' + requires :new_password, type: String, desc: '新密码' + end + post 'password' do + authenticate! + us = UsersService.new + user = us.change_password params.merge(current_user_id: current_user.id, + new_password_confirmation: params[:new_password]) + present :data, user, with: Mobile::Entities::User + present :status, 0 + end + + desc "用户搜索" + params do + requires :name, type: String, desc: '用户名关键字' + end + get 'search' do + us = UsersService.new + user = us.search_user params + present :data, user, with: Mobile::Entities::User + present :status, 0 + end + + end + end + end +end + + diff --git a/app/api/mobile/apis/watches.rb b/app/api/mobile/apis/watches.rb new file mode 100644 index 000000000..1603b311a --- /dev/null +++ b/app/api/mobile/apis/watches.rb @@ -0,0 +1,49 @@ +#coding=utf-8 +module Mobile + module Apis + class Watches < Grape::API + resource :watches do + + desc "获取所有关注" + params do + requires :token, type: String + end + get do + authenticate! + us = UsersService.new + ws = us.user_watcher(id: current_user.id) + present :data, ws, with: Mobile::Entities::User + present :status, 0 + end + + + desc "关注某人" + params do + requires :token, type: String + requires :object_id, type: Integer, desc: '关注的用户的id' + end + post do + authenticate! + ws = WatchesService.new + o = ws.watch(params.merge({current_user_id:current_user.id, object_type:'user' }) ) + present :data, o, with: Mobile::Entities::User + present :status, 0 + end + + + desc "取消关注" + params do + requires :token, type: String + requires :object_id, type: Integer, desc: '取消关注的用户的id' + end + delete do + authenticate! + ws = WatchesService.new + ws.unwatch(params.merge({current_user_id:current_user.id, object_type:'user' }) ) + {status: 0} + end + + end + end + end +end diff --git a/app/api/mobile/entities/anonymous_works_params.rb b/app/api/mobile/entities/anonymous_works_params.rb new file mode 100644 index 000000000..95cf9215d --- /dev/null +++ b/app/api/mobile/entities/anonymous_works_params.rb @@ -0,0 +1,35 @@ +module Mobile + module Entities + #匿评作品页面相关参数 + class AnonymousWorksParams < Grape::Entity + def self.anonymous_works_params_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(Hash) && !f.key?(field) + + end + end + end + anonymous_works_params_expose :is_teacher + anonymous_works_params_expose :m_score + anonymous_works_params_expose :is_anonymous_comments + anonymous_works_params_expose :cur_type + expose :jours ,using: Mobile::Entities::Jours do |f, opt| + if f.is_a?(Hash) && f.key?(:jours) + f[:jours] + end + end + expose :teacher_stars,using: Mobile::Entities::HomeworkJours do |f, opt| + if f.is_a?(Hash) && f.key?(:teacher_stars) + f[:teacher_stars] + end + end + expose :student_stars , using: Mobile::Entities::HomeworkJours do |f, opt| + if f.is_a?(Hash) && f.key?(:student_stars) + f[:student_stars] + end + end + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/attachment.rb b/app/api/mobile/entities/attachment.rb new file mode 100644 index 000000000..510db89be --- /dev/null +++ b/app/api/mobile/entities/attachment.rb @@ -0,0 +1,23 @@ +module Mobile + module Entities + class Attachment < Grape::Entity + def self.attachment_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(::Attachment) + if f.respond_to?(field) + f.send(field) + else + #case field + # when "" + #end + end + end + end + end + attachment_expose :filename + attachment_expose :description + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/course.rb b/app/api/mobile/entities/course.rb new file mode 100644 index 000000000..ec00579ce --- /dev/null +++ b/app/api/mobile/entities/course.rb @@ -0,0 +1,58 @@ +module Mobile + module Entities + class Course < Grape::Entity + def self.course_expose(field) + expose field do |f,opt| + c = nil + if f.is_a? ::Course + c = f + else + c = f[:course] + end + if field == :img_url + f[field] if f.is_a?(Hash) && f.key?(field) + #f.img_url if f.respond_to?(:img_url) + else + (c[field] if (c.is_a?(Hash) && c.key?(field))) || (c.send(field) if c.respond_to?(field)) + end + end + end + course_expose :img_url + course_expose :attachmenttype + course_expose :class_period + course_expose :code + course_expose :created_at + course_expose :description + course_expose :endup_time + course_expose :extra + course_expose :id + course_expose :inherit_members + course_expose :is_public + course_expose :lft + course_expose :location + course_expose :name + course_expose :open_student + # course_expose :password + course_expose :rgt + course_expose :school_id + course_expose :setup_time + course_expose :state + course_expose :status + course_expose :string + course_expose :tea_id + course_expose :term + course_expose :time + course_expose :updated_at + expose :teacher, using: Mobile::Entities::User do |c, opt| + if c.is_a? ::Course + c.teacher + else + c[:course].teacher + end + end + expose :my_homework,using: Mobile::Entities::HomeworkAttach do |f, opt| + f[:my_homework] if f.is_a?(Hash) && f.key?(:my_homework) + end + end + end +end diff --git a/app/api/mobile/entities/homework.rb b/app/api/mobile/entities/homework.rb new file mode 100644 index 000000000..ae3637106 --- /dev/null +++ b/app/api/mobile/entities/homework.rb @@ -0,0 +1,40 @@ +module Mobile + module Entities + class Homework < Grape::Entity + def self.homework_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(::Bid) + if f.respond_to?(field) + f.send(field) + else + + end + end + end + end + #作业id + homework_expose :id + #课程名称 + homework_expose :course_name + #课程老师 + homework_expose :course_teacher + #作业次数 + homework_expose :homework_times + #作业名称 + homework_expose :homework_name + #已提交的作业数量 + homework_expose :homework_count + #学生提问数量 + homework_expose :student_questions_count + #作业描述 + homework_expose :description + #作业是否启用匿评功能 0:不启用,1启用 + homework_expose :open_anonymous_evaluation + #作业状态 0:新建,1:已开启匿评,2:已关闭匿评 + #只有作业启用了匿评功能且当前用户是课程老师且已提交的作品数量大于或等于2才能开启匿评 + homework_expose :homework_state + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/homework_attach.rb b/app/api/mobile/entities/homework_attach.rb new file mode 100644 index 000000000..256dcdf61 --- /dev/null +++ b/app/api/mobile/entities/homework_attach.rb @@ -0,0 +1,39 @@ +module Mobile + module Entities + class HomeworkAttach < Grape::Entity + include Redmine::I18n + def self.homework_attach_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(::HomeworkAttach) + if f.respond_to?(field) + if field == :created_at + format_time(f.send(:created_at)) + else + f.send(field) + end + else + case field + when :homework_times + f.bid.courses.first.homeworks.index(f.bid) + 1 unless (f.bid.nil? || f.bid.courses.nil? || f.bid.courses.first.nil?) + end + end + end + end + end + + homework_attach_expose :id + homework_attach_expose :name + homework_attach_expose :homework_times + homework_attach_expose :description + homework_attach_expose :created_at + expose :attachments,using: Mobile::Entities::Attachment do |f, opt| + if f.respond_to?(:attachments) + f.send(:attachments) + end + end + #homework_attach_expose :user + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/homework_jours.rb b/app/api/mobile/entities/homework_jours.rb new file mode 100644 index 000000000..63c6997fd --- /dev/null +++ b/app/api/mobile/entities/homework_jours.rb @@ -0,0 +1,25 @@ +module Mobile + module Entities + #带评分的留言(教师评论、学生匿名评分都属于此类) + class HomeworkJours < Grape::Entity + include Redmine::I18n + def self.homework_jours_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(::SeemsRateableRates) + + end + end + end + homework_jours_expose :rater_id + homework_jours_expose :rater_name + homework_jours_expose :created_at + homework_jours_expose :stars + expose :comment,using: Mobile::Entities::Jours do |f,opt| + f[:comment] + end + + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/jours.rb b/app/api/mobile/entities/jours.rb new file mode 100644 index 000000000..5a9f48cbc --- /dev/null +++ b/app/api/mobile/entities/jours.rb @@ -0,0 +1,37 @@ +module Mobile + module Entities + #普通留言 + class Jours < Grape::Entity + include Redmine::I18n + include WordsHelper + def self.jours_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(::JournalsForMessage) && f.respond_to?(field) + if field == :created_on + format_time(f.send(field)) + else + f.send(field) + end + end + end + end + jours_expose :id + expose :user,using: Mobile::Entities::User do |f, opt| + f.user + end + jours_expose :created_on + jours_expose :notes + jours_expose :m_reply_id + expose :reply_user,using: Mobile::Entities::User do |f, opt| + f.at_user + end + expose :child_reply,using: Mobile::Entities::Jours do |f, opt| + if f.is_a?(::JournalsForMessage) + fetch_user_leaveWord_reply(f) + end + end + end + end +end diff --git a/app/api/mobile/entities/news.rb b/app/api/mobile/entities/news.rb new file mode 100644 index 000000000..7c77f8c82 --- /dev/null +++ b/app/api/mobile/entities/news.rb @@ -0,0 +1,42 @@ +module Mobile + module Entities + class News < Grape::Entity + def self.news_expose(field) + expose field do |f,opt| + if f.is_a?(Hash) && f.key?(field) + f[field] + elsif f.is_a?(Hash) && !f.key?(field) + n = f[:news] + comments = f[:comments] + if n.is_a?(::News) + n.send(field) if n.respond_to?(field) + end + + end + end + end + + #新闻标题 + news_expose :title + + expose :author,using: Mobile::Entities::User do |f, opt| + n = f[:news] + n.author if n.respond_to?(:author) + end + #作者id + news_expose :author_id + #作者名 + news_expose :author_name + #新闻内容 + news_expose :description + #发布时间 + news_expose :created_on + #评论数量 + news_expose :comments_count + #评论 + news_expose :comments + + + end + end +end \ No newline at end of file diff --git a/app/api/mobile/entities/user.rb b/app/api/mobile/entities/user.rb new file mode 100644 index 000000000..1f52ae841 --- /dev/null +++ b/app/api/mobile/entities/user.rb @@ -0,0 +1,51 @@ +module Mobile + module Entities + class User < Grape::Entity + include ApplicationHelper + include ApiHelper + def self.user_expose(f) + expose f do |u,opt| + if u.is_a?(Hash) && u.key?(f) + u[f] + elsif u.is_a?(::User) + if u.respond_to?(f) + u.send(f) + else + case f + when :img_url + url_to_avatar(u) + when :gender + u.user_extensions.gender.nil? ? 0 : u.user_extensions.gender + when :work_unit + get_user_work_unit u + when :location + get_user_location u + when :brief_introduction + u.user_extensions.brief_introduction + end + end + end + + end + end + + expose :id + #头像 + user_expose :img_url + #昵称 + expose :nickname + #性别 + user_expose :gender + #我的二维码 + #工作单位 + user_expose :work_unit + #邮箱地址 + user_expose :mail + #地区 + user_expose :location + #签名 + user_expose :brief_introduction + end + end + +end diff --git a/app/api/mobile/middleware/error_handler.rb b/app/api/mobile/middleware/error_handler.rb new file mode 100644 index 000000000..018191d8d --- /dev/null +++ b/app/api/mobile/middleware/error_handler.rb @@ -0,0 +1,19 @@ +module Mobile + module Middleware + class ErrorHandler < Grape::Middleware::Base + def call!(env) + @env = env + begin + @app.call(@env) + rescue =>e + message = {status: 1, message: e.message }.to_json + puts(e.backtrace.join("\n")) if Rails.env.development? + status = 200 + headers = { 'Content-Type' => content_type } + Rack::Response.new([message], status, headers).finish + # throw :error, :message => e.message || options[:default_message], :status => 500 + end + end + end + end +end diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index 69c2d3002..ff66b8d46 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -118,13 +118,30 @@ class AccountController < ApplicationController redirect_to my_account_path end else - create_and_save_user params[:user][:login],user_params[:password],user_params[:mail],user_params[:password_confirmation],true + us = UsersService.new + @user = us.register user_params.merge(:should_confirmation_password => true) + case Setting.self_registration + when '1' + #register_by_email_activation(@user) + unless @user.new_record? + flash[:notice] = l(:notice_account_register_done) + render action: 'email_valid', locals: {:mail => user.mail} + end + when '3' + #register_automatically(@user) + unless @user.new_record? + self.logged_user = @user + flash[:notice] = l(:notice_account_activated) + redirect_to my_account_url + end + else + #register_manually_by_administrator(@user) + unless @user.new_record? + account_pending + end + end end end - if params[:identity] == "2" - @user.firstname = firstname_code - @user.lastname = lastname_code - end end #should_confirmation_password是否验证密码 @@ -172,6 +189,11 @@ class AccountController < ApplicationController redirect_to signin_url end + def api_register login,password,email + users_service = UsersService.new + users_service.register({login: login, password: password, email: eamil}) + end + def valid_ajax req = Hash.new(false) req[:message] = '' diff --git a/app/controllers/applied_project_controller.rb b/app/controllers/applied_project_controller.rb index d7b65174f..f5c42f7b4 100644 --- a/app/controllers/applied_project_controller.rb +++ b/app/controllers/applied_project_controller.rb @@ -10,8 +10,10 @@ class AppliedProjectController < ApplicationController if @applieds.count == 0 appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id]) Mailer.applied_project(appliedproject).deliver + @status = 2 + else + @status = 1 end - @status = 1 else @status = 0 end diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index e34993663..161918094 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -26,36 +26,40 @@ class CoursesController < ApplicationController def join if User.current.logged? - course = Course.find_by_id params[:object_id] - if course - if course_endTime_timeout? course - @state = 2 - else - if User.current.member_of_course?(course) - @state = 3 - else - if params[:course_password] == course.password - members = [] - members << Member.new(:role_ids => [10], :user_id => User.current.id) - course.members << members - StudentsForCourse.create(:student_id => User.current.id, :course_id => params[:object_id]) - @state = 0 - else - @state = 1 - end - end - end - else - @state = 4 - end + cs = CoursesService.new + join = cs.join_course params,User.current + @state = join[:state] + course = join[:course] + #course = Course.find_by_id params[:object_id] + #if course + # if course_endTime_timeout? course + # @state = 2 + # else + # if User.current.member_of_course?(course) + # @state = 3 + # else + # if params[:course_password] == course.password + # members = [] + # members << Member.new(:role_ids => [10], :user_id => User.current.id) + # course.members << members + # StudentsForCourse.create(:student_id => User.current.id, :course_id => params[:object_id]) + # @state = 0 + # else + # @state = 1 + # end + # end + # end + #else + # @state = 4 + #end else - @state = 5 + @state = 5 #未登录 end respond_to do |format| format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => course, :object_id => params[:object_id]} } end rescue Exception => e - @state = 4 + @state = 4 #已经加入了课程 respond_to do |format| # format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => nil, :object_id => nil} } @@ -64,15 +68,18 @@ class CoursesController < ApplicationController def unjoin if User.current.logged? - - @member = Member.where('course_id = ? and user_id = ?', params[:object_id], User.current.id) - @member.first.destroy - - joined = StudentsForCourse.where('student_id = ? and course_id = ?', User.current.id, params[:object_id]) - joined.each do |join| - join.delete - end + # + # @member = Member.where('course_id = ? and user_id = ?', params[:object_id], User.current.id) + # @member.first.destroy + # + # joined = StudentsForCourse.where('student_id = ? and course_id = ?', User.current.id, params[:object_id]) + # joined.each do |join| + # join.delete + # end + cs = CoursesService.new + cs.exit_course params,User.current end + respond_to do |format| # format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => Course.find(params[:object_id]), :object_id => params[:object_id]} } @@ -89,27 +96,16 @@ class CoursesController < ApplicationController #更新课程信息 def update - @course.safe_attributes = params[:course] - @course.time = params[:time] - @course.term = params[:term] - @course.class_period = params[:class_period] - if @course.save - if params[:course][:is_public] == '0' - course_status = CourseStatus.find_by_course_id(@course.id) - course_status.destroy if course_status - elsif params[:course][:is_public] == '1' - course_status = CourseStatus.find_by_course_id(@course.id) - course_status.destroy if course_status - course_status = CourseStatus.create(:course_id => @course.id, :grade => 0) - end - - respond_to do |format| - format.html { - flash[:notice] = l(:notice_successful_update) - redirect_to settings_course_url(@course) - } - format.api { render_api_ok } - end + cs = CoursesService.new + @course = cs.edit_course params,@course,User.current + if @course.errors.full_messages.count <= 0 + respond_to do |format| + format.html { + flash[:notice] = l(:notice_successful_update) + redirect_to settings_course_url(@course) + } + format.api { render_api_ok } + end else respond_to do |format| format.html { @@ -119,6 +115,36 @@ class CoursesController < ApplicationController format.api { render_validation_errors(@course) } end end + #@course.safe_attributes = params[:course] + #@course.time = params[:time] + #@course.term = params[:term] + #@course.class_period = params[:class_period] + #if @course.save + # if params[:course][:is_public] == '0' + # course_status = CourseStatus.find_by_course_id(@course.id) + # course_status.destroy if course_status + # elsif params[:course][:is_public] == '1' + # course_status = CourseStatus.find_by_course_id(@course.id) + # course_status.destroy if course_status + # course_status = CourseStatus.create(:course_id => @course.id, :grade => 0) + # end + # + # respond_to do |format| + # format.html { + # flash[:notice] = l(:notice_successful_update) + # redirect_to settings_course_url(@course) + # } + # format.api { render_api_ok } + # end + #else + # respond_to do |format| + # format.html { + # settings + # render :action => 'settings' + # } + # format.api { render_validation_errors(@course) } + # end + #end end def new_join @@ -203,6 +229,11 @@ class CoursesController < ApplicationController render_feed(courses, :title => "#{Setting.app_title}: #{l(:label_course_latest)}") } end + + rescue Exception => e + if e.message == 'sumbit empty' + (redirect_to courses_url, :notice => l(:label_sumbit_empty);return) + end end def searchmembers @@ -212,7 +243,7 @@ class CoursesController < ApplicationController @is_remote = true @score_sort_by = "desc" q = "#{params[:name].strip}" - #(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank? + #(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank? if params[:incourse] @results = searchmember_by_name(student_homework_score(0,0,0,"desc"), q) @@ -448,57 +479,79 @@ class CoursesController < ApplicationController end def create - if User.current.user_extensions.identity - @course = Course.new - @course.extra='course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s - @course.safe_attributes = params[:course] - @course.tea_id = User.current.id - # added by bai - @course.term = params[:term] - @course.time = params[:time] - #@course.school_id = params[:occupation] - @course.school_id = User.current.user_extensions.school_id - @course.setup_time = params[:setup_time] - @course.endup_time = params[:endup_time] - @course.class_period = params[:class_period] - end - - @issue_custom_fields = IssueCustomField.sorted.all - @trackers = Tracker.sorted.all - - if @course.save - #unless User.current.admin? - 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]) - m.project_id = -1 - course = CourseInfos.new(:user_id => User.current.id, :course_id => @course.id) - #user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id) - if params[:course][:is_public] == '1' - course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag) - end - @course.members << m - @course.course_infos << course - #end - respond_to do |format| - format.html { - flash[:notice] = l(:notice_successful_create) - if params[:continue] - redirect_to new_course_url(attrs, :course => '0') - elsif params[:course_continue] - redirect_to new_course_url(:course => '1') - else - redirect_to settings_course_url(@course, :course_type => 1) + cs = CoursesService.new + @course = cs.create_course params,User.current + if @course.new_record? + respond_to do |format| + format.html { render :action => 'new', :layout => 'base' } #Added by young + format.api { render_validation_errors(@course) } + end + else + respond_to do |format| + format.html { + flash[:notice] = l(:notice_successful_create) + if params[:continue] + redirect_to new_course_url(attrs, :course => '0') + elsif params[:course_continue] + redirect_to new_course_url(:course => '1') + else + redirect_to settings_course_url(@course, :course_type => 1) + end + } + format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) } end - } - format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) } - end - else - #@course.destroy - respond_to do |format| - format.html { render :action => 'new', :layout => 'base' } #Added by young - format.api { render_validation_errors(@course) } - end - end + end + #if User.current.user_extensions.identity + # @course = Course.new + # @course.extra='course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s + # @course.safe_attributes = params[:course] + # @course.tea_id = User.current.id + # # added by bai + # @course.term = params[:term] + # @course.time = params[:time] + # #@course.school_id = params[:occupation] + # @course.school_id = User.current.user_extensions.school_id + # @course.setup_time = params[:setup_time] + # @course.endup_time = params[:endup_time] + # @course.class_period = params[:class_period] + #end + # + #@issue_custom_fields = IssueCustomField.sorted.all + #@trackers = Tracker.sorted.all + # + #if @course.save + # #unless User.current.admin? + # 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]) + # m.project_id = -1 + # course = CourseInfos.new(:user_id => User.current.id, :course_id => @course.id) + # #user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id) + # if params[:course][:is_public] == '1' + # course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag) + # end + # @course.members << m + # @course.course_infos << course + # #end + # respond_to do |format| + # format.html { + # flash[:notice] = l(:notice_successful_create) + # if params[:continue] + # redirect_to new_course_url(attrs, :course => '0') + # elsif params[:course_continue] + # redirect_to new_course_url(:course => '1') + # else + # redirect_to settings_course_url(@course, :course_type => 1) + # end + # } + # format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) } + # end + # else + # #@course.destroy + # respond_to do |format| + # format.html { render :action => 'new', :layout => 'base' } #Added by young + # format.api { render_validation_errors(@course) } + # end + # end end def course diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb index 8f00c49cd..7ff015fbc 100644 --- a/app/controllers/my_controller.rb +++ b/app/controllers/my_controller.rb @@ -183,17 +183,35 @@ class MyController < ApplicationController return end if request.post? - if @user.check_password?(params[:password]) - @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] - - if @user.save - flash.now[:notice] = l(:notice_account_password_updated) - redirect_to my_account_url - end - else - flash.now[:error] = l(:notice_account_wrong_password) + us = UsersService.new + @user = us.change_password params.merge(:current_user_id => @user.id) + if @user.errors.full_messages.count <= 0 + flash.now[:notice] = l(:notice_account_password_updated) + redirect_to my_account_url end end + rescue Exception => e + if e.message == 'wrong password' + flash.now[:error] = l(:notice_account_wrong_password) + end + # @user = User.current + # unless @user.change_password_allowed? + # flash.now[:error] = l(:notice_can_t_change_password) + # redirect_to my_account_url + # return + # end + # if request.post? + # if @user.check_password?(params[:password]) + # @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] + # + # if @user.save + # flash.now[:notice] = l(:notice_account_password_updated) + # redirect_to my_account_url + # end + # else + # flash.now[:error] = l(:notice_account_wrong_password) + # end + # end end # Create a new feeds key diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb index 23f8c18e9..2df17d73f 100644 --- a/app/controllers/news_controller.rb +++ b/app/controllers/news_controller.rb @@ -91,8 +91,12 @@ class NewsController < ApplicationController end def show - @comments = @news.comments - @comments.reverse! if User.current.wants_comments_in_reverse_order? + cs = CoursesService.new + result = cs.show_course_news params,User.current + @news = result[:news] + @comments = result[:comments] + #@comments = @news.comments + #@comments.reverse! if User.current.wants_comments_in_reverse_order? #modify by nwb if @news.course_id @course = Course.find(@news.course_id) diff --git a/app/controllers/poll_controller.rb b/app/controllers/poll_controller.rb index 8926c0be6..394c52f13 100644 --- a/app/controllers/poll_controller.rb +++ b/app/controllers/poll_controller.rb @@ -1,8 +1,8 @@ class PollController < ApplicationController - before_filter :find_poll_and_course, :only => [:edit,:update,:destroy,:show,:statistics_result,:create_poll_question,:commit_poll,:commit_answer,:publish_poll,:republish_poll,:poll_result] + before_filter :find_poll_and_course, :only => [:edit,:update,:destroy,:show,:statistics_result,:create_poll_question,:commit_poll,:commit_answer,:publish_poll,:republish_poll,:poll_result,:close_poll] before_filter :find_container, :only => [:new,:create, :index] before_filter :is_member_of_course, :only => [:index,:show,:poll_result] - before_filter :is_course_teacher, :only => [:new,:create,:edit,:update,:destroy,:publish_poll,:republish_poll] + before_filter :is_course_teacher, :only => [:new,:create,:edit,:update,:destroy,:publish_poll,:republish_poll,:close_poll] include PollHelper def index if @course @@ -339,6 +339,17 @@ class PollController < ApplicationController end end + #关闭问卷 + def close_poll + @poll.polls_status = 3 + @poll.closed_at = Time.now + if @poll.save + respond_to do |format| + format.js + end + end + end + private def find_poll_and_course @poll = Poll.find params[:id] diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e97615772..a2933c577 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -368,34 +368,35 @@ class UsersController < ApplicationController sort_init 'login', 'asc' sort_update %w(login firstname lastname mail admin created_on last_login_on) (redirect_to user_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank? - case params[:format] - when 'xml', 'json' - @offset, @limit = api_offset_and_limit({:limit => 15}) + case params[:format] + when 'xml', 'json' + @offset, @limit = api_offset_and_limit({:limit => 15}) + else + @limit = 15#per_page_option + end + # + #@status = params[:status] || 1 + #has = { + # "show_changesets" => true + #} + # scope = User.logged.status(@status) + # @search_by = params[:search_by] ? params[:search_by][:id] : 0 + # scope = scope.like(params[:name],@search_by) if params[:name].present? + us = UsersService.new + scope = us.search_user params + @user_count = scope.count + @user_pages = Paginator.new @user_count, @limit, params['page'] + @user_base_tag = params[:id] ? 'base_users':'users_base' + @offset ||= @user_pages.reverse_offset + unless @offset == 0 + @users = scope.offset(@offset).limit(@limit).all.reverse else - @limit = 15#per_page_option + limit = @user_count % @limit + if limit == 0 + limit = @limit + end + @users = scope.offset(@offset).limit(limit).all.reverse end - - @status = params[:status] || 1 - has = { - "show_changesets" => true - } - scope = User.logged.status(@status) - @search_by = params[:search_by] ? params[:search_by] :"0" - scope = scope.like(params[:name], @search_by) if params[:name].present? - @user_count = scope.count - @user_pages = Paginator.new @user_count, @limit, params['page'] - @user_base_tag = params[:id] ? 'base_users':'users_base' - @offset ||= @user_pages.reverse_offset - unless @offset == 0 - @users = scope.offset(@offset).limit(@limit).all.reverse - else - limit = @user_count % @limit - if limit == 0 - limit = @limit - end - @users = scope.offset(@offset).limit(limit).all.reverse - end - respond_to do |format| format.html { @groups = Group.all.sort diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb index 50bb2ccd8..f6d01a03d 100644 --- a/app/controllers/watchers_controller.rb +++ b/app/controllers/watchers_controller.rb @@ -15,13 +15,37 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class WatchersController < ApplicationController - before_filter :require_login, :find_watchables, :only => [:watch, :unwatch] + before_filter :require_login#, :find_watchables, :only => [:watch, :unwatch] def watch - set_watcher(@watchables, User.current, true) + s = WatchesService.new + watchables = s.watch params.merge(:current_user_id => User.current.id) + respond_to do |format| + format.html { redirect_to_referer_or {render :text => (true ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} + format.js { render :partial => 'set_watcher', :locals => {:user => User.current, :watched => watchables} } + end + rescue Exception => e + if e.message == "404" + render_404 + else + raise e + end + #set_watcher(@watchables, User.current, true) end def unwatch - set_watcher(@watchables, User.current, false) + s = WatchesService.new + watchables = s.unwatch params.merge(:current_user_id => User.current.id) + respond_to do |format| + format.html { redirect_to_referer_or {render :text => (false ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} + format.js { render :partial => 'set_watcher', :locals => {:user => User.current, :watched => watchables} } + end + rescue Exception => e + if e.message == "404" + render_404 + else + raise e + end + #set_watcher(@watchables, User.current, false) end def join @@ -162,4 +186,5 @@ class WatchersController < ApplicationController format.js { render :partial => 'set_watcher', :locals => {:user => user, :watched => watchables} } end end + end diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb index 8beeac363..8ef2d6095 100644 --- a/app/helpers/account_helper.rb +++ b/app/helpers/account_helper.rb @@ -18,4 +18,45 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module AccountHelper + + def email_activation_register(user, &block) + token = Token.new(:user => user, :action => "register") + if user.save and token.save + UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0) + Mailer.register(token).deliver + #flash[:notice] = l(:notice_account_register_done) + #render action: 'email_valid', locals: {:mail => user.mail} + else + yield if block_given? + end + user + end + + def automatically_register(user, &block) + # Automatic activation + user.activate + user.last_login_on = Time.now + if user.save + UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0) + #self.logged_user = user + #flash[:notice] = l(:notice_account_activated) + #redirect_to my_account_url + else + yield if block_given? + end + user + end + + def administrator_manually__register(user, &block) + if user.save + UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0) + # Sends an email to the administrators + Mailer.account_activation_request(user).deliver + #account_pending + else + yield if block_given? + end + user + end + end diff --git a/app/helpers/api_helper.rb b/app/helpers/api_helper.rb new file mode 100644 index 000000000..8ff6f725c --- /dev/null +++ b/app/helpers/api_helper.rb @@ -0,0 +1,40 @@ +module ApiHelper + #获取用户的工作单位 + def get_user_work_unit user + work_unit = "" + if user.user_extensions.identity == 0 || user.user_extensions.identity == 1 + work_unit = user.user_extensions.school.name unless user.user_extensions.school.nil? + elsif user.user_extensions.identity == 3 + work_unit = user.user_extensions.occupation + elsif user.user_extensions.identity == 2 + work_unit = user.firstname + end + work_unit + end + + #获取用户地区 + def get_user_location user + location = "" + location << (user.user_extensions.location || '') + location << (user.user_extensions.location_city || '') + location + end + + + def get_assigned_homeworks(homeworks, n, index) + homeworks += homeworks + homeworks[index + 1 .. index + n] + end + + + def stars_to_json_like starts,show_jour,homework,show_name + result = [] + starts.each do |s| + comment = get_homework_review homework,show_jour,s.rater + rater_name = show_name ? s.rater.login : l(:label_anonymous) + rater_id = show_name ? s.rater.id : '' + result << {:rater_id =>rater_id ,:rater_name => rater_name,:created_at => format_time(s.created_at),:stars => s.stars,:comment => comment} + end + result + end +end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index caf29ba90..1face5c38 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1961,4 +1961,8 @@ module ApplicationHelper end confirm_info end + + def get_technical_title user + #user.user_extensions.technical_title + end end diff --git a/app/helpers/poll_helper.rb b/app/helpers/poll_helper.rb index 60d82c096..3156f1b3a 100644 --- a/app/helpers/poll_helper.rb +++ b/app/helpers/poll_helper.rb @@ -64,13 +64,13 @@ module PollHelper def options_show pq case pq when 1 - "单选题" + l(:label_MC) when 2 - "多选题" + l(:label_MCQ) when 3 - "单行主观题" + l(:label_single) else - "多行主观题" + l(:label_mulit) end end diff --git a/app/models/api_key.rb b/app/models/api_key.rb new file mode 100644 index 000000000..e71896bc0 --- /dev/null +++ b/app/models/api_key.rb @@ -0,0 +1,21 @@ +class ApiKey < ActiveRecord::Base + attr_accessible :access_token, :active, :expires_at, :user_id + before_create :generate_access_token + before_create :set_experation + + # validates_presence_of :user_id, :access_token + + def expired? + DateTime.now >= self.expires_at + end + + private + def generate_access_token + self.access_token = SecureRandom.hex + end + + def set_experation + self.expires_at = DateTime.now + 30 + end + +end diff --git a/app/models/course.rb b/app/models/course.rb index c11f66d49..a5de93cf7 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -207,8 +207,8 @@ class Course < ActiveRecord::Base # 创建课程讨论区 def create_board_sync @board = self.boards.build - self.name=" #{l(:label_borad_course) }" - @board.name = self.name + #self.name=" #{l(:label_borad_course) }" + @board.name = " #{l(:label_borad_course) }"#self.name @board.description = self.name.to_s @board.project_id = -1 if @board.save diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb new file mode 100644 index 000000000..7e3b2a545 --- /dev/null +++ b/app/services/courses_service.rb @@ -0,0 +1,336 @@ +class CoursesService + include ApplicationHelper + include CoursesHelper + #TODO:尚未整合权限系统 + #参数school_id为0或不传时返回所有课程,否则返回对应学校的课程 + #参数per_page_count分页功能,每页显示的课程数 + #参数page分页功能,当前页码 + def course_list params + @school_id = params[:school_id] + per_page_option = params[:per_page_count] || 10 + page_no = params[:page] || 1 + if @school_id == "0" || @school_id.nil? + @courses_all = Course.active.visible. + joins("LEFT JOIN #{CourseStatus.table_name} ON #{Course.table_name}.id = #{CourseStatus.table_name}.course_id") + else + @courses_all = Course.active.visible. + joins("LEFT JOIN #{CourseStatus.table_name} ON #{Course.table_name}.id = #{CourseStatus.table_name}.course_id"). + where("#{Course.table_name}.school_id = ?", @school_id) + end + @course_count = @courses_all.count + @course_pages = Redmine::Pagination::Paginator.new @course_count, per_page_option,page_no + @courses = @courses_all.order("created_at desc") + @courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page) + course_list = [] + @courses.each do |course| + course_list << {:course => course,:img_url => url_to_avatar(course)} + end + course_list + end + + #搜索课程 + def search_course params + courses_all = Course.all_course + name = params[:name] + if name.blank? + raise 'sumbit empty' + end + @courses = courses_all.visible + if params[:name].present? + @courses_all = @courses.like(params[:name]) + else + @courses_all = @courses; + end + @courses_all + end + + #获取头像 + def get_img obj + url_to_avatar(obj) + end + + #课程老师或课程学生列表 + def course_teacher_or_student_list params,course,current_user + if course.is_a?(Course) + c = course + else + c = Course.find(course) + end + if current_user.nil? || !(current_user.admin? || c.is_public == 1 || (c.is_public == 0 && current_user.member_of_course?(c))) + raise '403' + end + @teachers= searchTeacherAndAssistant(c) + #@canShowCode = isCourseTeacher(User.current.id,course) && params[:role] != '1' + case params[:role] + when '1' + #@subPage_title = l :label_teacher_list + @members = searchTeacherAndAssistant(c) + when '2' + #@subPage_title = l :label_student_list + @members = searchStudent(c) + else + #@subPage_title = '' + @members = c.member_principals.includes(:roles, :principal).all.sort + end + users = [] + @members.each do |m| + img_url = url_to_avatar(m.user) + gender = m.user.user_extensions.gender.nil? ? 0 : m.user.user_extensions.gender + work_unit = get_user_work_unit m.user + location = get_user_location m.user + users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender, :work_unit => work_unit, :mail => m.user.mail, :location => location, :brief_introduction => m.user.user_extensions.brief_introduction} + end + users + end + + #获取用户的工作单位 + def get_user_work_unit user + work_unit = "" + if user.user_extensions.identity == 0 || user.user_extensions.identity == 1 + work_unit = user.user_extensions.school.name unless user.user_extensions.school.nil? + elsif user.user_extensions.identity == 3 + work_unit = user.user_extensions.occupation + elsif user.user_extensions.identity == 2 + work_unit = user.firstname + end + work_unit + end + + #获取用户地区 + def get_user_location user + location = "" + location << (user.user_extensions.location || '') + location << (user.user_extensions.location_city || '') + location + end + + #课程通知列表 + def course_news_list params + if params[:course_id] && @course==nil + @course = Course.find(params[:course_id]) + end + scope = @course ? @course.news.course_visible : News.course_visible + news = [] + scope.each do |n| + news << {:title => n.title,:author_name => n.author.name,:author_id => n.author.id, :description => n.description,:created_on => format_time(n.created_on),:comments_count => n.comments_count} + end + news + end + + #查看新闻权限验证 + def show_course_news_authorize(current_user) + unless current_user.allowed_to?({:controller => 'news', :action => 'show'}, false) + raise '403' + end + end + + #显示课程通知(包括评论) 需验证权限 + def show_course_news params,current_user + @news = News.find(params[:id]) + @comments = @news.comments + @comments.reverse! if current_user.wants_comments_in_reverse_order? + {:news => @news,:comments => @comments} + #comments = [] + #@comments.each do |comment| + # comments << {:author_id => comment.author_id,:author_name => comment.author.name,:commont_content => comment.comments,:time => format_time(comment.created_on)} + #end + #{:title => @news.title,:author_name => @news.author.name,:author_id => @news.author.id, :description => @news.description,:created_on => format_time(@news.created_on), + # :comments_count => @news.comments_count,:comments => comments} + end + + + + #显示课程 + def show_course(params,currnet_user) + course = Course.find(params[:id]) + unless (course.is_public == 1 || currnet_user.member_of_course?(@course)|| currnet_user.admin?) + raise '403' + end + course + end + + #创建课程 + #current_user当前用户对象(不是id) + # params[:course][:name]:课程名称 + #params[:course][:password]:密码 + #params[:course][:description]:描述 + #params[:course][:is_public]:是否公开1公开,0私有 + #params[:course][:open_student]:是否公开学生列表1公开,0不公开,不公开时非课程成员无法看到学生列表 + #params[:course][:course_type]:暂时默认给1值。 + #params[:term]:学期(秋季学期或春季学期) + #params[:time]: 年份(例:2014) + #params[:setup_time]:暂不传(貌似已经没用了) + #params[:endup_time]: 暂不传(貌似已经没用了) + #params[:class_period]:学时总数 + def create_course(params,current_user) + if current_user.user_extensions.identity + @course = Course.new + @course.extra = 'course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s + @course.send(:safe_attributes=, params[:course], current_user) + #@course.safe_attributes(current_user,params[:course]) + @course.tea_id = current_user.id + @course.term = params[:term] + @course.time = params[:time] + #@course.school_id = params[:occupation] + @course.school_id = current_user.user_extensions.school_id + @course.setup_time = params[:setup_time] + @course.endup_time = params[:endup_time] + @course.class_period = params[:class_period] + end + + @issue_custom_fields = IssueCustomField.sorted.all + @trackers = Tracker.sorted.all + + if @course.save + #unless User.current.admin? + r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first + m = Member.new(:user => current_user, :roles => [r]) + m.project_id = -1 + course = CourseInfos.new(:user_id => current_user.id, :course_id => @course.id) + #user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id) + if params[:course][:is_public] == '1' + course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag) + end + @course.members << m + @course.course_infos << course + end + @course + end + + #验证编辑课程的权限 + #当前 + def edit_course_authorize(current_user,course) + unless current_user.allowed_to?({:controller => 'courses', :action => 'update'}, course) + raise '403' + end + end + + #编辑课程 需验证权限 + # params[:course][:name]:课程名称 + #params[:course][:password]:密码 + #params[:course][:description]:描述 + #params[:course][:is_public]:是否公开1公开,0私有 + #params[:course][:open_student]:是否公开学生列表1公开,0不公开,不公开时非课程成员无法看到学生列表 + #params[:course][:course_type]:暂时默认给1值。 + #params[:term]:学期(秋季学期或春季学期) + #params[:time]: 年份(例:2014) + #params[:class_period]:学时总数 + def edit_course(params,course,current_user) + course.send(:safe_attributes=, params[:course], current_user) + #course.safe_attributes = params[:course] + course.time = params[:time] + course.term = params[:term] + course.class_period = params[:class_period] + if course.save + if params[:course][:is_public] == '0' + course_status = CourseStatus.find_by_course_id(course.id) + course_status.destroy if course_status + elsif params[:course][:is_public] == '1' + course_status = CourseStatus.find_by_course_id(course.id) + course_status.destroy if course_status + course_status = CourseStatus.create(:course_id => course.id, :grade => 0) + end + end + course + end + + #退出课程 + #object_id: 课程id + #user:当前用户 + #@state == 0 退出成功 + #@state == 1 不在课程中 + #@state == 2 您还未登录 + #@state 其他 未知错误,请稍后再试 + def exit_course params,user + if user.nil? + @state = 2 + return @state + end + @member = Member.where('course_id = ? and user_id = ?', params[:object_id], user.id) + if @member.nil? || @member.count == 0 + @state = 1 + return @state + end + @member.first.destroy + joined = StudentsForCourse.where('student_id = ? and course_id = ?', user.id, params[:object_id]) + joined.each do |join| + join.delete + @state = 0 + end + @state + end + + #加入课程 + #object_id:课程id + #course_password :加入课程的密码 + #@state == 0 加入成功 + #@state == 1 密码错误 + #@state == 2 课程已过期 请联系课程管理员重启课程。(在配置课程处) + #@state == 3 您已经加入了课程 + #@state == 4 您加入的课程不存在 + #@state == 5 您还未登录 + #@state 其他 未知错误,请稍后再试 + def join_course params,current_user + course = Course.find_by_id params[:object_id] + @state = 10 + if course + if course_endTime_timeout? course + @state = 2 + else + if current_user.member_of_course?(course) + @state = 3 + else + if params[:course_password] == course.password + members = [] + members << Member.new(:role_ids => [10], :user_id => current_user.id) + course.members << members + StudentsForCourse.create(:student_id => current_user.id, :course_id => params[:object_id]) + @state = 0 + else + @state = 1 + end + end + end + else + @state = 4 + end + {:state => @state,:course => course} + end + + #作业列表 + #已提交的作业数量获取 bid.homeworks.count + #学生提问数量获取 bid.commit.nil? ? 0 : bid.commit + def homework_list params,current_user + course = Course.find(params[:id]) + if course.is_public != 0 || current_user.member_of_course?(course) + bids = course.homeworks.order('deadline DESC') + bids = bids.like(params[:name]) if params[:name].present? + homeworks = [] + if is_course_teacher(current_user,course) + bids.each do |bid| + homeworks << show_homework_info(course,bid) + end + end + homeworks + else + raise '403' + end + end + + private + def show_homework_info course,bid + author = bid.author.lastname + bid.author.firstname + many_times = course.homeworks.index(bid) + 1 + name = bid.name + homework_count = bid.homeworks.count #已提交的作业数量 + student_questions_count = bid.commit.nil? ? 0 : bid.commit + description = bid.description + #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 + state = bid.comment_status + #end + open_anonymous_evaluation = bid.open_anonymous_evaluation + {:course_name => course.name,:id => bid.id, :course_teacher => author, :homework_times => many_times, :homework_name => name, :homework_count => homework_count,:student_questions_count => student_questions_count, + :description => description, :homework_state => state,:open_anonymous_evaluation => open_anonymous_evaluation} + end + +end \ No newline at end of file diff --git a/app/services/homework_service.rb b/app/services/homework_service.rb new file mode 100644 index 000000000..a2c063e15 --- /dev/null +++ b/app/services/homework_service.rb @@ -0,0 +1,248 @@ +#coding=utf-8 +class HomeworkService + include CoursesHelper + include AttachmentsHelper + include ApplicationHelper + include WordsHelper + include ApiHelper + include HomeworkAttachHelper + + # 作业详情(老师才显示启动匿评,学生不显示 ) + # many_times 第几次(作业) + # state=0 启动匿评 + # state=1 关闭匿评 + # state=2 匿评结束 + def show_homework params + @bid = Bid.find(params[:id]) + course = @bid.courses.first + author = @bid.author.lastname + @bid.author.firstname + many_times = course.homeworks.index(@bid) + 1 + name = @bid.name + homework_count = @bid.homeworks.count #已提交的作业数量 + student_questions_count = @bid.commit.nil? ? 0 : @bid.commit + description = @bid.description + #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 + state = @bid.comment_status + #end + open_anonymous_evaluation = @bid.open_anonymous_evaluation + {:course_name => course.name,:id => @bid.id, :course_teacher => author, :homework_times => many_times, :homework_name => name, :homework_count => homework_count,:student_questions_count => student_questions_count, + :description => description, :homework_state => state,:open_anonymous_evaluation => open_anonymous_evaluation} + end + + # 启动作业匿评前提示信息 + def alert_homework_anonymous_comment params + @bid = Bid.find params[:id] + @course = @bid.courses.first + if @bid.comment_status == 0 + @totle_size = searchStudent(@course).size + @cur_size = @bid.homeworks.size + elsif @bid.comment_status == 1 + @totle_size = 0 + @bid.homeworks.map { |homework| @totle_size += homework.homework_evaluations.count} + teachers = "(" + teacher_members = searchTeacherAndAssistant(@course) + teacher_members.each do |member| + if member == teacher_members.last + teachers += member.user_id.to_s + ")" + else + teachers += member.user_id.to_s + "," + end + end + @cur_size = 0 + @bid.homeworks.map { |homework| @cur_size += homework.rates(:quality).where("seems_rateable_rates.rater_id not in #{teachers}").count} + end + @percent = format("%.2f",(@cur_size.to_f / ( @totle_size == 0 ? 1 : @totle_size)) * 100) + [@bid,@totle_size,@cur_size,@percent] + end + + #启动匿评 + #statue 1:启动成功,2:启动失败,作业总数大于等于2份时才能启动匿评,3:已开启匿评,请务重复开启 + def start_anonymous_comment params,current_user + @bid = Bid.find(params[:id]) + @course = @bid.courses.first + unless is_course_teacher(current_user,@course) || current_user.admin? + @statue = 4 + raise '403' + end + if(@bid.comment_status == 0) + homeworks = @bid.homeworks + if(homeworks && homeworks.size >= 2) + homeworks.each_with_index do |homework, index| + user = homework.user + n = @bid.evaluation_num + n = n < homeworks.size ? n : homeworks.size - 1 + assigned_homeworks = get_assigned_homeworks(homeworks, n, index) + assigned_homeworks.each do |h| + @homework_evaluation = HomeworkEvaluation.new(user_id: user.id, homework_attach_id: h.id) + @homework_evaluation.save + end + end + @bid.update_column('comment_status', 1) + @statue = 1 + else + @statue = 2 + end + else + @statue = 3 + end + @statue + end + #关闭匿评 + def stop_anonymous_comment params,current_user + @bid = Bid.find(params[:id]) + @course = @bid.courses.first + unless is_course_teacher(current_user,@course) || current_user.admin? + raise '403' + end + @bid.update_column('comment_status', 2) + end + + # 匿评作品详情 + # attachs 该作品的所有附件 + # filename 文件名 + # filedesc 文件描述 + def anonymous_works_show(params,current_user) + @homework = HomeworkAttach.find(params[:id]) + @bid = @homework.bid + @course = @bid.courses.first + if current_user.admin? || current_user.member_of_course?(@course) + @stars_reates = @homework.rates(:quality) + @is_teacher = is_course_teacher current_user,@course + @has_evaluation = @stars_reates.where("rater_id = #{current_user.id} and is_teacher_score=#{@is_teacher ? 1 : 0}").first + @m_score = @has_evaluation.nil? ? 0 : @has_evaluation.stars + @teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表 + @student_stars = @stars_reates.where("is_teacher_score = 0") #学生评分列表 + @is_anonymous_comments = @bid.comment_status == 1 && !@homework.users.include?(current_user) && @homework.user != current_user && !@is_teacher #判断是不是匿评(开启匿评,当前用户不是作业的创建者或者参与者,不是老师) + jours = @homework.journals_for_messages.where("is_comprehensive_evaluation = 3 or is_comprehensive_evaluation is null").order("created_on DESC")#jours留言 is null条件用以兼容历史数据 + #@jour = paginateHelper jours,5 #留言 + #@cur_page = params[:cur_page] || 1 + @cur_type = params[:cur_type] || 5 + teacher_stars_json_like = stars_to_json_like(@teacher_stars,true,@homework,true) + student_stars_json_like = stars_to_json_like(@student_stars,false,@homework,(false || @is_teacher)) + else + raise '403' + end + + [@homework,{:is_teacher => @is_teacher,:m_score => @m_score,:jours => jours,:teacher_stars => teacher_stars_json_like, + :student_stars => student_stars_json_like,:is_anonymous_comments => @is_anonymous_comments,:cur_type => @cur_type}] + #name = @homework.name + #desc = @homework.description + #datetime = @homework.created_at + #files = [] + #unless @homework.attachments.empty? + # attachs = @homework.attachments + # attachs.each do |attach| + # filename = attach.filename + # filedesc = attach.description unless attach.description.blank? + # end + #end + + #{:name => name, :description => desc, :datetime => format_time(datetime)} + end + + #作品打分/留言 + def add_score_and_jour params + @is_teacher,@is_anonymous_comments,@m_score = params[:is_teacher]=="true",params[:is_anonymous_comments]=="true",params[:stars_value] + @cur_page,@cur_type = params[:cur_page] || 1,params[:cur_type] || 5 + @homework = HomeworkAttach.find(params[:homework_id]) + #保存评分 + @homework.rate(@m_score.to_i,User.current.id,:quality) if @m_score + #保存评论 + @is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言 + if params[:new_form] && params[:new_form][:user_message] && params[:new_form][:user_message] != "" #有没有留言 + @homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation + end + end + + #作品留言列表 + def get_works_jours_list params + @bid = Bid.find params[:id] + @user = @bid.author + @jours = @bid.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC') + @jour = paginateHelper @jours,10 + @jour + end + + # 学生匿评留言列表 + def anonymous_jour_list params + #jours留言 is null条件用以兼容历史数据 + jours = @homework.journals_for_messages.where("is_comprehensive_evaluation = 3 or is_comprehensive_evaluation is null").order("created_on DESC") + jours.each do |jour| + user = jour.user + img_url = url_to_avatar(jour.user) + datetime = jour.created_on + content = jour.notes + end + {:user => 'user', :img_url => 'img_url', :datetime => 'datetime', :content => 'content'} + end + + # 匿评教师留言/回复列表 + # 图像img_url = url_to_avatar(user) + # massage_user 留言者 + # parent_jour被回复的留言 + def teacher_jour_list params + @homework = HomeworkAttach.find(params[:homework_id]) + @stars_reates = @homework.rates(:quality) + @teacher_stars = @stars_reates.where("rater_id in (#{teachers})") #老师评分列表 + @teacher_stars.each do |ts| + #留言参数 + jour = get_homework_review @homework,true,massage_user + massage_content = jour.notes unless jour.nil? + massage_user = ts.rater + massage_score = ts.stars + #回复参数 + anonymous_repy(jour) + end + end + + # 学生匿评列表 + def student_jour_list params + @homework = HomeworkAttach.find(params[:homework_id]) + @stars_reates = @homework.rates(:quality) + @student_stars = @stars_reates.where("rater_id not in (#{teachers})") #学生评分列表 + @student_stars.each do |ss| + #留言参数 + massage_user = ss.rater + jour = get_homework_review @homework,false,massage_user + massage_score = ss.stars + massage_content = jour.notes unless jour.nil? + #回复参数 + anonymous_repy(jour) + end + end + + def anonymous_repy jour + fetch_user_leaveWord_reply(jour).each do |fulr| + parent_jour = JournalsForMessage.where("id = #{fulr.m_reply_id}").first + reply_name = fulr.user.name + parent_name = parent_jour.user.name if parent_jour + reply_content = fulr.notes + reply_time = fulr.created_on + end + end + + #我的作品列表 + def my_homework_list params,current_user + @user = User.find(params[:user_id]) + if !current_user.admin? && !@user.active? + raise '404' + return + end + if current_user == @user || current_user.admin? + membership = @user.coursememberships.all + else + membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user)) + end + membership.sort! {|older, newer| newer.created_on <=> older.created_on } + course_list = [] + membership.each do |mp| + my_homeworks = [] + mp.course.homeworks.each do |bid| + hw = bid.homeworks.where("user_id = #{current_user.id}") + my_homeworks << hw[0] unless (hw.nil? || hw[0].nil?) + end + course_list << {:course => mp.course,:img_url => url_to_avatar(mp.course),:my_homework => my_homeworks} + end + course_list + end +end \ No newline at end of file diff --git a/app/services/users_service.rb b/app/services/users_service.rb new file mode 100644 index 000000000..897171b55 --- /dev/null +++ b/app/services/users_service.rb @@ -0,0 +1,169 @@ +class UsersService + include ApplicationHelper + include AccountHelper + include AvatarHelper + include CoursesHelper + include ApiHelper + #将用户注册的功能函数写这里 + #参数约定 + #成功返回注册后的User实例,失败直接抛异常 + + def register(params) + @user = User.new + @user.admin = false + @user.register + @user.login = params[:login] + @user.mail = params[:mail] + password = params[:password] + password_confirmation = params[:password_confirmation] + should_confirmation_password = params[:should_confirmation_password] + if !password.blank? && !password_confirmation.blank? && should_confirmation_password + @user.password, @user.password_confirmation = password, password_confirmation + elsif !password.blank? && !should_confirmation_password + @user.password = password + else + @user.password = "" + end + case Setting.self_registration + when '1' + @user = email_activation_register(@user) + when '3' + @user = automatically_register(@user) + else + @user = administrator_manually__register(@user) + end + if @user.id != nil + ue = @user.user_extensions ||= UserExtensions.new + ue.user_id = @user.id + ue.save + end + @user + #img_url = url_to_avatar(@user) + #gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender + #work_unit = get_user_work_unit @user + #location = get_user_location @user + #{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction} + end + + #显示用户 + #id用户id + def show_user(params) + @user = User.find(params[:id]) + img_url = url_to_avatar(@user) + gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender + work_unit = get_user_work_unit @user + location = get_user_location @user + {:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction} + end + + #编辑用户 + #gender 1:female 0:male 其他:male + def edit_user params + @user = User.find(params[:id]) + fileio = params[:file] + + @se = @user.extensions + if @user.user_extensions.identity == 0 || @user.user_extensions.identity == 1 + @se.school_id = params[:occupation] + elsif @user.user_extensions.identity == 3 + @se.occupation = params[:occupation] + elsif @user.user_extensions.identity == 2 + @user.firstname = params[:occupation] + end + @se.brief_introduction = params[:brief_introduction] + @se.gender = params[:gender] + @se.location = params[:province] if params[:province] + @se.location_city = params[:city] if params[:city] + raise @se.errors.full_message unless @se.save + unless fileio.nil? + file = fileio[:tempfile] + diskfile=disk_filename(@user.class.to_s, @user.id) + @image_file = fileio[:name] + @urlfile='/' << File.join("images", "avatars", avatar_directory(@user.class.to_s), avatar_filename(@user.id, @image_file)) + + path = File.dirname(diskfile) + unless File.directory?(path) + FileUtils.mkdir_p(path) + end + File.rename(file.path, @urlfile) + begin + f = Magick::ImageList.new(diskfile) + # gif格式不再做大小处理 + if f.format != 'GIF' + width = 300.0 + proportion = (width/f[0].columns) + height = (f[0].rows*proportion) + f.resize_to_fill!(width, height) + f.write(diskfile) + end + + rescue Exception => e + logger.error "[Error] avatar : users_service#edit_user ===> #{e}" + end + end + #img_url = url_to_avatar(@user) + #gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender + #work_unit = get_user_work_unit @user + #location = get_user_location @user + #{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction} + @user + end + + + + + + #关注列表 + def user_watcher params + @user = User.find(params[:id]) + User.watched_by(@user.id) + end + + #用户课程列表 + def user_courses_list params,current_user + @user = User.find(params[:id]) + if !current_user.admin? && !@user.active? + raise '404' + return + end + if current_user == @user || current_user.admin? + membership = @user.coursememberships.all + else + membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user)) + end + membership.sort! {|older, newer| newer.created_on <=> older.created_on } + course_list = [] + membership.each do |mp| + course_list << {:course => mp.course,:img_url => url_to_avatar(mp.course)} + end + course_list + end + + #修改密码 + def change_password params + @current_user = User.find(params[:current_user_id]) + if @current_user.check_password?(params[:password]) + @current_user.password, @current_user.password_confirmation = params[:new_password], params[:new_password_confirmation] + @current_user.save + #raise @current_user.errors.full_message + #return @current_user + + else + raise 'wrong password' + end + @current_user + end + + #搜索用户 + def search_user params + @status = params[:status] || 1 + has = { + "show_changesets" => true + } + scope = User.logged.status(@status) + @search_by = params[:search_by] ? params[:search_by] : "0" + scope = scope.like(params[:name],@search_by) if params[:name].present? + scope + end + +end diff --git a/app/services/watches_service.rb b/app/services/watches_service.rb new file mode 100644 index 000000000..2b9bed3cd --- /dev/null +++ b/app/services/watches_service.rb @@ -0,0 +1,57 @@ +class WatchesService + def watch params + @current_user = User.find(params[:current_user_id]) + @watchables = find_watchables params + if @watchables.nil? + raise '404' + end + set_watcher(@watchables, @current_user, true) + end + + def unwatch params + @current_user = User.find(params[:current_user_id]) + @watchables = find_watchables params + if @watchables.nil? + raise '404' + end + set_watcher(@watchables, @current_user, false) + end + + def find_watchables params + #根据参数获取关注对象的类型(user、project) + klass = Object.const_get(params[:object_type].camelcase) rescue nil + #判断获取的对象类型能否响应‘watched_by’方法 + if klass && klass.respond_to?('watched_by') + @watchables = klass.find_all_by_id(Array.wrap(params[:object_id])) + raise Unauthorized if @watchables.any? {|w| w.respond_to?(:visible?) && !w.visible?} + end + @watchables.present? ? @watchables : nil + end + + def set_watcher(watchables, user, watching) + watchables.each do |watchable| + watchable.set_watcher(user, watching) + # @user = watchable # added by william + if watching + # 修改 user和project的状态 + if watchable.instance_of?(User) + #写user_statuses表 + UserStatus.find_by_user_id(watchable.id).update_watchers_count(1) + elsif watchable.instance_of?(Project) + #写project_statuese表 + ProjectStatus.find_by_project_id(watchable.id).update_watchers_count(1) + end + else + # 修改 user和project的状态 + if watchable.instance_of?(User) + #写user_statuses表 + UserStatus.find_by_user_id(watchable.id).update_watchers_count(-1) + elsif watchable.instance_of?(Project) + #写project_statuese表 :project_status + ProjectStatus.find_by_project_id(watchable.id).update_watchers_count(-1) + end + end + end + watchables + end +end \ No newline at end of file diff --git a/app/views/applied_project/applied_join_project.js.erb b/app/views/applied_project/applied_join_project.js.erb index 9fd358ede..deac2c9ce 100644 --- a/app/views/applied_project/applied_join_project.js.erb +++ b/app/views/applied_project/applied_join_project.js.erb @@ -1,6 +1,8 @@ <% if @status == 0%> alert("您申请的项目不存在"); <% elsif @status == 1%> + alert("请勿重复申请加入该项目"); +<% elsif @status == 2%> alert("申请成功"); <%else%> alert("申请失败"); diff --git a/app/views/courses/_course_form.html.erb b/app/views/courses/_course_form.html.erb index d54741295..85ca24c1b 100644 --- a/app/views/courses/_course_form.html.erb +++ b/app/views/courses/_course_form.html.erb @@ -42,7 +42,7 @@ <%= l(:label_class_period) %> *   - + <%= text_field_tag :class_period, @course.class_period, :placeholder => "#{l(:lable_input_class)}", :maxlength => 5 %>   diff --git a/app/views/courses/_set_course_time.html.erb b/app/views/courses/_set_course_time.html.erb index f1eec891f..0c28b90a7 100644 --- a/app/views/courses/_set_course_time.html.erb +++ b/app/views/courses/_set_course_time.html.erb @@ -5,9 +5,9 @@ <% if display #如果课程已结束%> <% linkPath = course_endTime_timeout?(course) ? restartcourse_course_path(course) : finishcourse_course_path(course, format: :js) %> - <% desc = course_endTime_timeout?(course) ? '重启' : '关闭' %> + <% desc = course_endTime_timeout?(course) ? l(:label_course_reload) : l(:label_course_closed) %> - <%= link_to "#{desc}", linkPath, :remote => true, :method => :post, :id => id, :confirm => ("确定要#{desc}课程?") %> + <%= link_to "#{desc}", linkPath, :remote => true, :method => :post, :id => id, :confirm => l(:label_course_closed_tips, :desc => desc) %> <% else %> <% end %> diff --git a/app/views/layouts/base_newcontest.html.erb b/app/views/layouts/base_newcontest.html.erb index 0d234a69c..d525f65a2 100644 --- a/app/views/layouts/base_newcontest.html.erb +++ b/app/views/layouts/base_newcontest.html.erb @@ -102,7 +102,7 @@ <% if User.current.login? %> diff --git a/app/views/layouts/base_projects.html.erb b/app/views/layouts/base_projects.html.erb index 67e4da0f4..b8cc2ddc9 100644 --- a/app/views/layouts/base_projects.html.erb +++ b/app/views/layouts/base_projects.html.erb @@ -132,8 +132,9 @@ + diff --git a/app/views/layouts/base_users.html.erb b/app/views/layouts/base_users.html.erb index f241875bd..dbd6503b0 100644 --- a/app/views/layouts/base_users.html.erb +++ b/app/views/layouts/base_users.html.erb @@ -267,27 +267,32 @@ <% end %> - - - - - - <% if @user.user_extensions.identity == 0 %> - - - <% end %> - + <% unless @user.user_extensions.location.empty?%> + + + + + + <% end %> + <% unless @user.user_extensions.technical_title.nil?%> + + <% if @user.user_extensions.identity == 0 %> + + + <% end %> + + <%end%> <% if @user.user_extensions.identity == 1 %> - <% if(is_watching?(@user) ) %> + <% if(is_watching?(@user) ) && !@user.user_extensions.student_id.empty? %>
- <%= link_to @contest.name, show_contest_contest_path(@contest) %> + <%= link_to @contest.name, contest_contestnotifications_path(@contest) %>
<%=link_to @project.watcher_users.count, :controller=>"projects", :action=>"watcherlist", :id => @project %> - <%=link_to "#{@project.issues.count}", project_issues_path(@project) %> + <%=link_to "#{@project.issues.where('status_id in (1,2,4,6)').count}", project_issues_path(@project) %>
- <%= l(:label_location) %>: - - <%= @user.user_extensions.location %> - <%= @user.user_extensions.location_city %> -
- <%= l(:label_technical_title) %>: - - -
+ <%= l(:label_location) %>: + + <%= @user.user_extensions.location %> + <%= @user.user_extensions.location_city %> +
+ <%= l(:label_technical_title) %>: + + +
<%= l(:label_bidding_user_studentcode)%>: diff --git a/app/views/news/_project_news.html.erb b/app/views/news/_project_news.html.erb index 79217f1fe..526c7a1a5 100644 --- a/app/views/news/_project_news.html.erb +++ b/app/views/news/_project_news.html.erb @@ -82,11 +82,11 @@ :html => {:id => 'news-form', :multipart => true} do |f| %> <%= render :partial => 'news/form', :locals => {:f => f} %> <%#= submit_tag l(:button_create), :class => 'whiteButton m3p10 h30', :name => nil %> - <%= link_to l(:button_create), "#", :onclick => 'submitNews();',:onmouseover => 'submitFocus(this);', :class => 'whiteButton m3p10' %> + <%= link_to l(:button_create), "#", :onclick => 'submitNews();',:onmouseover => 'submitFocus(this);', :class => 'ButtonColor m3p10' %> | <%#= preview_link preview_news_path(:project_id => @project), 'news-form', target='preview', {:class => 'whiteButton m3p10'} %> - <%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()', :class => 'whiteButton m3p10' %> + <%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()', :class => 'ButtonColor m3p10' %> <% end if @project %>
diff --git a/app/views/poll/_edit_MC.html.erb b/app/views/poll/_edit_MC.html.erb index 066eafe0d..f89407247 100644 --- a/app/views/poll/_edit_MC.html.erb +++ b/app/views/poll/_edit_MC.html.erb @@ -39,8 +39,12 @@
diff --git a/app/views/poll/_edit_MCQ.html.erb b/app/views/poll/_edit_MCQ.html.erb index 129f50e94..d6045f965 100644 --- a/app/views/poll/_edit_MCQ.html.erb +++ b/app/views/poll/_edit_MCQ.html.erb @@ -36,8 +36,12 @@
diff --git a/app/views/poll/_edit_head.html.erb b/app/views/poll/_edit_head.html.erb index ed90a5ef8..dfa5b5cfc 100644 --- a/app/views/poll/_edit_head.html.erb +++ b/app/views/poll/_edit_head.html.erb @@ -7,8 +7,12 @@
diff --git a/app/views/poll/_edit_mulit.html.erb b/app/views/poll/_edit_mulit.html.erb index d498169f4..5c694ff05 100644 --- a/app/views/poll/_edit_mulit.html.erb +++ b/app/views/poll/_edit_mulit.html.erb @@ -20,8 +20,12 @@
diff --git a/app/views/poll/_edit_single.html.erb b/app/views/poll/_edit_single.html.erb index 2c2d41e0f..5aff29984 100644 --- a/app/views/poll/_edit_single.html.erb +++ b/app/views/poll/_edit_single.html.erb @@ -16,8 +16,12 @@
diff --git a/app/views/poll/_new_MC.html.erb b/app/views/poll/_new_MC.html.erb index a7f9e441b..294c058f8 100644 --- a/app/views/poll/_new_MC.html.erb +++ b/app/views/poll/_new_MC.html.erb @@ -34,8 +34,12 @@
diff --git a/app/views/poll/_new_MCQ.html.erb b/app/views/poll/_new_MCQ.html.erb index 027a1c1f6..1478f9918 100644 --- a/app/views/poll/_new_MCQ.html.erb +++ b/app/views/poll/_new_MCQ.html.erb @@ -33,8 +33,12 @@
diff --git a/app/views/poll/_new_mulit.html.erb b/app/views/poll/_new_mulit.html.erb index 02f7a71a7..23ffb3d64 100644 --- a/app/views/poll/_new_mulit.html.erb +++ b/app/views/poll/_new_mulit.html.erb @@ -13,8 +13,12 @@
diff --git a/app/views/poll/_new_single.html.erb b/app/views/poll/_new_single.html.erb index ffc525546..4ee185070 100644 --- a/app/views/poll/_new_single.html.erb +++ b/app/views/poll/_new_single.html.erb @@ -8,8 +8,12 @@
diff --git a/app/views/poll/_poll.html.erb b/app/views/poll/_poll.html.erb index 1bf6b3716..fdf534405 100644 --- a/app/views/poll/_poll.html.erb +++ b/app/views/poll/_poll.html.erb @@ -22,7 +22,7 @@ <% end %> <%if @is_teacher%> - <% if poll.polls_status == 1 %> + <% if poll.polls_status == 1 || poll.polls_status == 3 %>
  • 统计结果
  • <% elsif poll.polls_status == 2%>
  • @@ -31,38 +31,61 @@ <% end%> <% end%> -
  • - <%if @is_teacher %> + +<%if @is_teacher %> <% if poll.polls_status == 1 %> - 发布问卷 +
  • + + 发布问卷 + +
  • <% elsif poll.polls_status == 2%> - 取消发布 +
  • + + 取消发布 + +
  • + <% else%> +
  • + 发布问卷 +
  • <% end%> - <% end%> - +<% end%> +
  • <% if @is_teacher %> <%= link_to(l(:button_delete), poll, - method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "polls_de fr ml20 mr10") %> + method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "polls_de fr ml15 mr10") %> <% end%>
  • -
  • - <% if @is_teacher%> - <% if poll.polls_status == 1 %> - <%= link_to l(:button_edit), edit_poll_path(poll.id), :class => "polls_de fr ml20"%> - <% elsif poll.polls_status == 2%> -
  • 编辑
  • - <% end%> + +<% if @is_teacher%> + <% if poll.polls_status == 1 %> +
  • + <%= link_to l(:button_edit), edit_poll_path(poll.id), :class => "polls_de fr ml15"%> +
  • + <% else%> +
  • + 编辑 +
  • <% end%> - - - - - - - - +<% end%> + +<% if @is_teacher%> + <% if poll.polls_status == 2 %> +
  • + 关闭 +
  • + <% else %> +
  • + 关闭 +
  • + <% end%> + +<% end %> + +
  • <%= format_time poll.created_at%>
  • \ No newline at end of file diff --git a/app/views/poll/close_poll.js.erb b/app/views/poll/close_poll.js.erb new file mode 100644 index 000000000..222ea7976 --- /dev/null +++ b/app/views/poll/close_poll.js.erb @@ -0,0 +1,2 @@ +$("#polls_<%= @poll.id %>").html("<%= escape_javascript(render :partial => 'poll',:locals => {:poll => @poll}) %>"); +alert("关闭成功"); \ No newline at end of file diff --git a/app/views/poll/index.html.erb b/app/views/poll/index.html.erb index 29a5ec51f..3db4d7caa 100644 --- a/app/views/poll/index.html.erb +++ b/app/views/poll/index.html.erb @@ -56,6 +56,30 @@ $('#ajax-modal').parent().addClass("popbox_polls"); } } + + function close_poll(poll_id) + { + $('#ajax-modal').html("
    " + + "
    " + + "
    " + + "

    问卷关闭后学生将不能继续提交问卷,
    是否确定关闭该问卷?

    " + + "
    " + + "确  定" + + "取  消" + + "
    " + + "
    " + + "
    " + + "
    " + + "
    "); + showModal('ajax-modal', '310px'); + $('#ajax-modal').css('height','120px'); + $('#ajax-modal').siblings().remove(); + $('#ajax-modal').before("" + + ""); + $('#ajax-modal').parent().removeClass("alert_praise"); + $('#ajax-modal').parent().css("top","").css("left",""); + $('#ajax-modal').parent().addClass("popbox_polls"); + }
    diff --git a/app/views/projects/_join_project.html.erb b/app/views/projects/_join_project.html.erb index d30ec73e1..fdc60904d 100644 --- a/app/views/projects/_join_project.html.erb +++ b/app/views/projects/_join_project.html.erb @@ -67,7 +67,7 @@
  • 项目ID是所在项目网址中显示的序号
  • - <%= l(:label_new_join) %> + <%= l(:label_apply_project) %> <%= l(:button_cancel)%> diff --git a/config/initializers/autoreload_grape.rb b/config/initializers/autoreload_grape.rb new file mode 100644 index 000000000..ceffb9425 --- /dev/null +++ b/config/initializers/autoreload_grape.rb @@ -0,0 +1,26 @@ +if Rails.env.development? + lib_ruby_files = Dir.glob(File.join("app/api/**", "*.rb")) + lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do + # lib_ruby_files.each do |lib_file| + # puts "start require #{lib_file}" + # require_dependency(lib_file) + # end + # + + # binding.pry + # if Object.const_defined?(:Mobile) + # Object.send(:remove_const, :Mobile) + # end + # + # $".delete_if {|s| s.include?('api/mobile') } + # require File.join(Rails.root,"app/api/mobile/api.rb") + Rails.application.reload_routes! + end + + ActionDispatch::Callbacks.to_prepare do + lib_reloader.execute_if_updated + end + +end + + diff --git a/config/locales/en.yml b/config/locales/en.yml index 38f33de22..972fd99a1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -237,7 +237,7 @@ en: mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}." # edit by meng - # emailer + # emailer translation mail_issue_greetings: "Dear user , Greetings from Trustie" mail_issue_footer: "Unsubscribe this message?" mail_issue_title_userin: "in" @@ -250,9 +250,14 @@ en: mail_issue_reply: "Want reply" #end # modified by meng + # file_upload translation label_file_upload: Resource files label_file_upload_error_messages: "Upload error, please check your network environment, and refresh the page to upload." button_confirm: Confirm + # shut down and restart course + label_course_closed: Close + label_course_reopen: Reopen + label_course_closed_tips: "Are you sure you want to reopen the course?" # end field_name: Name field_description: Description @@ -541,7 +546,7 @@ en: project_module_calendar: Calendar project_module_gantt: Gantt - #edit by meng + # edit by meng lable_hot_course: Hot projects lable_hot_projects: Active courses lable_user_active: User movements @@ -559,10 +564,10 @@ en: label_project_grade: Score label_user_for_project_grade: Score label_relation_files: Select an existing resource - + # Personal signature tips label_my_brief_introduction: How are feeling today? Leave your footprints ~ - label_submit: Submit - + label_submit: Submit + # create course and course info label_tags_course_name: Course Title label_new_course_password: Password label_new_course_description: Description @@ -572,39 +577,32 @@ en: label_teacher_list: Teacher list label_student_list: Student list label_export_excel: Export list - label_course_organizers: Institute label_poll: Questionnaire - + # homework info and anonymous info field_open_anonymous_evaluation: Use anonymous mutual-evaluation - field_evaluation_num: Number of anonymous works sent to each student - + field_evaluation_num: Number of anonymous works sent to each student label_edit_homework: Update homework - label_homework_list: Work list - + label_homework_list: Work list label_teacher_score: Teacher's score label_time: Commit time label_student_score: Student's score label_without_score: No evaluated label_homework_description: Description label_responses: Messages - lable_has_commit_homework: You have submitted your work - - label_user_create_project_homework: created the task label_commit_limit: Expired but can submit your work - + # steam the student label_current_group: Current group - + # DTS Test tool project_module_dts: DTS Test tool label_module_share: DTS Test tool field_dts_test: DTS Test tool - + # Feedback module label_technical_support: Support : label_feedback: Feedback #end - label_user: User label_user_plural: Users label_user_new: New user @@ -638,7 +636,7 @@ en: label_project_latest: Latest projects label_issue: Issue label_issue_new: New issue - label_issue_plural: Issues + label_issue_plural: Issues Tracking label_issue_view_all: View all issues label_issues_by: "Issues by %{value}" label_issue_added: Issue added @@ -691,7 +689,10 @@ en: label_my_page_block: My page block label_administration: Administration label_login: Login - label_logout: Sign out + # edit by meng + # Logout + label_logout: Logout + # end label_help: Help label_reported_issues: Reported issues label_assigned_to_me_issues: Issues assigned to me diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 115bc815b..d058a6c1b 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -252,7 +252,7 @@ zh: mail_body_wiki_content_updated: "'%{id}' wiki页面已由 %{author} 更新。" # edit by meng - # emailer + # 邮件中文格式 mail_issue_greetings: "亲爱的Trustie用户,您好!" mail_issue_footer: "退订该邮件!" mail_issue_title_userin: "在" @@ -263,11 +263,16 @@ zh: mail_issue_from_project: "项目问题跟踪" mail_issue_attachments: "附件:" mail_issue_reply: "我要回复" - #end + # end # modified by meng + # 课程资源上传 label_file_upload: 资源文件 label_file_upload_error_messages: "上传出现错误,请您检查您的网络环境,并刷新页面重新上传。" button_confirm: 确认 + # 教师权限课程关闭和重启 + label_course_closed: 关闭 + label_course_reload: 重开 + label_course_closed_tips: "确定要%{desc}课程?" # end field_name: 名称 #added by huang @@ -591,7 +596,7 @@ zh: label_project_latest: 最近的项目 label_issue: 问题 label_issue_new: 新建问题 - label_issue_plural: 缺陷 + label_issue_plural: 问题跟踪 label_issue_view_all: 查看所有问题 label_issues_by: "按 %{value} 分组显示问题" label_issue_added: 问题已添加 @@ -1034,7 +1039,7 @@ zh: label_user_activities_other: 该用户暂无任何动态! label_project_overview: "概述" label_project_tool: "项目工具集" - label_project_issues: "缺陷" + label_project_issues: "问题" label_project_newother: "查看其他评论" label_project_newshare: "分享了" label_project_notice: "发布了通知:" diff --git a/config/routes.rb b/config/routes.rb index 65498e4ec..122481d38 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,10 +26,10 @@ # Example: :via => :get ====> :via => :get RedmineApp::Application.routes.draw do - - #match '/contests/:id/contestnotifications', :controller => 'contestnotifications', :action => 'index' + mount Mobile::API => '/api' + resources :homework_users resources :no_uses delete 'no_uses', :to => 'no_uses#delete' @@ -67,6 +67,7 @@ RedmineApp::Application.routes.draw do get 'publish_poll' get 'republish_poll' get 'poll_result' + get 'close_poll' end collection do delete 'delete_poll_question' diff --git a/db/migrate/20141127015431_create_api_keys.rb b/db/migrate/20141127015431_create_api_keys.rb new file mode 100644 index 000000000..81a232848 --- /dev/null +++ b/db/migrate/20141127015431_create_api_keys.rb @@ -0,0 +1,14 @@ +class CreateApiKeys < ActiveRecord::Migration + def change + create_table :api_keys do |t| + t.string :access_token + t.datetime :expires_at + t.integer :user_id + t.boolean :active, default: true + + t.timestamps + end + add_index :api_keys, :user_id + add_index :api_keys, :access_token + end +end diff --git a/db/schema.rb b/db/schema.rb index 20c74ba1e..74ba6d652 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -12,6 +12,7 @@ # It's strongly recommended to check this file into your version control system. ActiveRecord::Schema.define(:version => 20150123020615) do +>>>>>>> szzh create_table "activities", :force => true do |t| t.integer "act_id", :null => false @@ -23,6 +24,18 @@ ActiveRecord::Schema.define(:version => 20150123020615) do add_index "activities", ["user_id", "act_type"], :name => "index_activities_on_user_id_and_act_type" add_index "activities", ["user_id"], :name => "index_activities_on_user_id" + create_table "api_keys", :force => true do |t| + t.string "access_token" + t.datetime "expires_at" + t.integer "user_id" + t.boolean "active", :default => true + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "api_keys", ["access_token"], :name => "index_api_keys_on_access_token" + add_index "api_keys", ["user_id"], :name => "index_api_keys_on_user_id" + create_table "applied_projects", :force => true do |t| t.integer "project_id", :null => false t.integer "user_id", :null => false diff --git a/public/Trustie_Beta1.0.0_201412310917.apk b/public/Trustie_Beta1.0.0_201412310917.apk new file mode 100644 index 000000000..0218f66a0 Binary files /dev/null and b/public/Trustie_Beta1.0.0_201412310917.apk differ diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 54e2a17aa..db57596bc 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -2916,4 +2916,5 @@ input[class~='m3p10'], .m3p10 { height: 20px; display: inline-block; color: #ffffff; + cursor:pointer; } \ No newline at end of file diff --git a/public/stylesheets/polls.css b/public/stylesheets/polls.css index 370a3c515..f0d670a1d 100644 --- a/public/stylesheets/polls.css +++ b/public/stylesheets/polls.css @@ -31,7 +31,7 @@ a.polls_title{ font-weight:bold; color:#3e6d8e;max-width: 300px;white-space: now a.pollsbtn{ display:block; width:66px; height:22px; text-align:center; border:1px solid #64bdd9; color:#64bdd9;} a:hover.pollsbtn{ background:#64bdd9; color:#fff; text-decoration:none;} .polls_date{ color:#666666;} -.polls_de{ color:#6883b6;} +.polls_de{ color:#6883b6;padding-left: 5px;} /****翻页***/ ul.wlist{ float:right; border-bottom:none; height:30px; margin-top:20px; } ul.wlist li{float: left;} @@ -143,5 +143,5 @@ a.btn_pu{ border:1px solid #3cb761; color:#3cb761; } a:hover.btn_pu{ background:#3cb761;} .pollsbtn_grey{ border:1px solid #b1b1b1; color:#b1b1b1; padding:0px 9px; } .polls_title_w { width:330px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;} -.polls_de_grey{ color:#b1b1b1;} +.polls_de_grey{ color:#b1b1b1;padding-left: 5px;} .ml5{ margin-left:5px;} diff --git a/test/mobile/auth_test.rb b/test/mobile/auth_test.rb new file mode 100644 index 000000000..afc5719e8 --- /dev/null +++ b/test/mobile/auth_test.rb @@ -0,0 +1,24 @@ +require File.expand_path('../../test_helper.rb',__FILE__) + +class AuthTest < ActionDispatch::IntegrationTest + def setup + ApiKey.delete_all + end + + test "login success when use correct password" do + post('/api/v1/auth/login.json', {login: 'guange', password: '123456'}) + o = ActiveSupport::JSON.decode response.body + puts o + puts o["token"] + assert_not_nil o["token"] + end + + test "login failure when incorrect password" do + post('/api/v1/auth/login.json', {login: 'guange', password: 'wrongpass'}) + o = ActiveSupport::JSON.decode response.body + assert_nil o["token"] + assert_equal o["error"], 'Unauthorized.' + end +end + + diff --git a/test/mobile/users_test.rb b/test/mobile/users_test.rb new file mode 100644 index 000000000..48b8010b4 --- /dev/null +++ b/test/mobile/users_test.rb @@ -0,0 +1,12 @@ +require File.expand_path('../../test_helper.rb',__FILE__) + +class UsersTest < ActionDispatch::IntegrationTest + test "register a user" do + end + test "get all users" do + get '/api/v1/users.json' + assert_response :success + end +end + +