From 945192f1d81153752cbfb83fe6f89e1dbe06669e Mon Sep 17 00:00:00 2001 From: alanlong9278 <547533434@qq.com> Date: Tue, 21 Apr 2015 09:41:40 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E6=B7=BB=E5=8A=A0memcached=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=20Signed-off-by:=20alanlong9278=20<547533434@qq.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- config/environments/development.rb | 3 +- config/environments/production.rb | 3 +- db/schema.rb | 2925 ++++++++++++++-------------- 4 files changed, 1464 insertions(+), 1469 deletions(-) diff --git a/Gemfile b/Gemfile index 976184793..887676c31 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'spreadsheet' gem 'ruby-ole' #gem 'email_verifier', path: 'lib/email_verifier' gem 'rufus-scheduler' -#gem 'dalli', path: 'lib/dalli-2.7.2' +gem 'dalli' gem 'rails_kindeditor',path:'lib/rails_kindeditor' group :development do gem 'grape-swagger' diff --git a/config/environments/development.rb b/config/environments/development.rb index 5c2427320..d3843ff68 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -11,7 +11,8 @@ RedmineApp::Application.configure do # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false - config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + #config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + config.cache_store = :dalli_store # Don't care if the mailer can't send config.action_mailer.raise_delivery_errors = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 160e0b8b0..d52d5840a 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -19,7 +19,8 @@ RedmineApp::Application.configure do # Full error reports are disabled and caching is turned on config.logger = Logger.new('log/production.log', 'daily',1048576) # daily, weekly or monthly config.action_controller.perform_caching = true - config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + config.cache_store = :dalli_store + #config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" # Enable serving of images, stylesheets, and javascripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" diff --git a/db/schema.rb b/db/schema.rb index e4c11e8ce..184f959c0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,1466 +1,1459 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended to check this file into your version control system. - -ActiveRecord::Schema.define(:version => 20150415032102) do - - create_table "activities", :force => true do |t| - t.integer "act_id", :null => false - t.string "act_type", :null => false - t.integer "user_id", :null => false - end - - add_index "activities", ["act_id", "act_type"], :name => "index_activities_on_act_id_and_act_type" - 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 - end - - create_table "apply_project_masters", :force => true do |t| - t.integer "user_id" - t.string "apply_type" - t.integer "apply_id" - t.integer "status" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "attachments", :force => true do |t| - t.integer "container_id" - t.string "container_type", :limit => 30 - t.string "filename", :default => "", :null => false - t.string "disk_filename", :default => "", :null => false - t.integer "filesize", :default => 0, :null => false - t.string "content_type", :default => "" - t.string "digest", :limit => 40, :default => "", :null => false - t.integer "downloads", :default => 0, :null => false - t.integer "author_id", :default => 0, :null => false - t.datetime "created_on" - t.string "description" - t.string "disk_directory" - t.integer "attachtype", :default => 1 - t.integer "is_public", :default => 1 - t.integer "copy_from" - t.integer "quotes" - end - - add_index "attachments", ["author_id"], :name => "index_attachments_on_author_id" - add_index "attachments", ["container_id", "container_type"], :name => "index_attachments_on_container_id_and_container_type" - add_index "attachments", ["created_on"], :name => "index_attachments_on_created_on" - - create_table "attachmentstypes", :force => true do |t| - t.integer "typeId", :null => false - t.string "typeName", :limit => 50 - end - - create_table "auth_sources", :force => true do |t| - t.string "type", :limit => 30, :default => "", :null => false - t.string "name", :limit => 60, :default => "", :null => false - t.string "host", :limit => 60 - t.integer "port" - t.string "account" - t.string "account_password", :default => "" - t.string "base_dn" - t.string "attr_login", :limit => 30 - t.string "attr_firstname", :limit => 30 - t.string "attr_lastname", :limit => 30 - t.string "attr_mail", :limit => 30 - t.boolean "onthefly_register", :default => false, :null => false - t.boolean "tls", :default => false, :null => false - t.string "filter" - t.integer "timeout" - end - - add_index "auth_sources", ["id", "type"], :name => "index_auth_sources_on_id_and_type" - - create_table "biding_projects", :force => true do |t| - t.integer "project_id" - t.integer "bid_id" - t.integer "user_id" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "reward" - end - - create_table "bids", :force => true do |t| - t.string "name" - t.string "budget", :null => false - t.integer "author_id" - t.date "deadline" - t.text "description" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - t.integer "commit" - t.integer "reward_type" - t.integer "homework_type" - t.integer "parent_id" - t.string "password" - t.integer "is_evaluation" - t.integer "proportion", :default => 60 - t.integer "comment_status", :default => 0 - t.integer "evaluation_num", :default => 3 - t.integer "open_anonymous_evaluation", :default => 1 - end - - create_table "boards", :force => true do |t| - t.integer "project_id", :null => false - t.string "name", :default => "", :null => false - t.string "description" - t.integer "position", :default => 1 - t.integer "topics_count", :default => 0, :null => false - t.integer "messages_count", :default => 0, :null => false - t.integer "last_message_id" - t.integer "parent_id" - t.integer "course_id" - end - - add_index "boards", ["last_message_id"], :name => "index_boards_on_last_message_id" - add_index "boards", ["project_id"], :name => "boards_project_id" - - create_table "bug_to_osps", :force => true do |t| - t.integer "osp_id" - t.integer "relative_memo_id" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "changes", :force => true do |t| - t.integer "changeset_id", :null => false - t.string "action", :limit => 1, :default => "", :null => false - t.text "path", :null => false - t.text "from_path" - t.string "from_revision" - t.string "revision" - t.string "branch" - end - - add_index "changes", ["changeset_id"], :name => "changesets_changeset_id" - - create_table "changeset_parents", :id => false, :force => true do |t| - t.integer "changeset_id", :null => false - t.integer "parent_id", :null => false - end - - add_index "changeset_parents", ["changeset_id"], :name => "changeset_parents_changeset_ids" - add_index "changeset_parents", ["parent_id"], :name => "changeset_parents_parent_ids" - - create_table "changesets", :force => true do |t| - t.integer "repository_id", :null => false - t.string "revision", :null => false - t.string "committer" - t.datetime "committed_on", :null => false - t.text "comments" - t.date "commit_date" - t.string "scmid" - t.integer "user_id" - end - - add_index "changesets", ["committed_on"], :name => "index_changesets_on_committed_on" - add_index "changesets", ["repository_id", "revision"], :name => "changesets_repos_rev", :unique => true - add_index "changesets", ["repository_id", "scmid"], :name => "changesets_repos_scmid" - add_index "changesets", ["repository_id"], :name => "index_changesets_on_repository_id" - add_index "changesets", ["user_id"], :name => "index_changesets_on_user_id" - - create_table "changesets_issues", :id => false, :force => true do |t| - t.integer "changeset_id", :null => false - t.integer "issue_id", :null => false - end - - add_index "changesets_issues", ["changeset_id", "issue_id"], :name => "changesets_issues_ids", :unique => true - - create_table "code_review_assignments", :force => true do |t| - t.integer "issue_id" - t.integer "change_id" - t.integer "attachment_id" - t.string "file_path" - t.string "rev" - t.string "rev_to" - t.string "action_type" - t.integer "changeset_id" - end - - create_table "code_review_project_settings", :force => true do |t| - t.integer "project_id" - t.integer "tracker_id" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "updated_by" - t.boolean "hide_code_review_tab", :default => false - t.integer "auto_relation", :default => 1 - t.integer "assignment_tracker_id" - t.text "auto_assign" - t.integer "lock_version", :default => 0, :null => false - t.boolean "tracker_in_review_dialog", :default => false - end - - create_table "code_review_user_settings", :force => true do |t| - t.integer "user_id", :default => 0, :null => false - t.integer "mail_notification", :default => 0, :null => false - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "code_reviews", :force => true do |t| - t.integer "project_id" - t.integer "change_id" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "line" - t.integer "updated_by_id" - t.integer "lock_version", :default => 0, :null => false - t.integer "status_changed_from" - t.integer "status_changed_to" - t.integer "issue_id" - t.string "action_type" - t.string "file_path" - t.string "rev" - t.string "rev_to" - t.integer "attachment_id" - t.integer "file_count", :default => 0, :null => false - t.boolean "diff_all" - end - - create_table "comments", :force => true do |t| - t.string "commented_type", :limit => 30, :default => "", :null => false - t.integer "commented_id", :default => 0, :null => false - t.integer "author_id", :default => 0, :null => false - t.text "comments" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - end - - add_index "comments", ["author_id"], :name => "index_comments_on_author_id" - add_index "comments", ["commented_id", "commented_type"], :name => "index_comments_on_commented_id_and_commented_type" - - create_table "contest_notifications", :force => true do |t| - t.text "title" - t.text "content" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "contesting_projects", :force => true do |t| - t.integer "project_id" - t.string "contest_id" - t.integer "user_id" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "reward" - end - - create_table "contesting_softapplications", :force => true do |t| - t.integer "softapplication_id" - t.integer "contest_id" - t.integer "user_id" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "reward" - end - - create_table "contestnotifications", :force => true do |t| - t.integer "contest_id" - t.string "title" - t.string "summary" - t.text "description" - t.integer "author_id" - t.integer "notificationcomments_count" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "contests", :force => true do |t| - t.string "name" - t.string "budget", :default => "" - t.integer "author_id" - t.date "deadline" - t.string "description" - t.integer "commit" - t.string "password" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - end - - create_table "course_attachments", :force => true do |t| - t.string "filename" - t.string "disk_filename" - t.integer "filesize" - t.string "content_type" - t.string "digest" - t.integer "downloads" - t.string "author_id" - t.string "integer" - t.string "description" - t.string "disk_directory" - t.integer "attachtype" - t.integer "is_public" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "container_id", :default => 0 - end - - create_table "course_groups", :force => true do |t| - t.string "name" - t.integer "course_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "course_infos", :force => true do |t| - t.integer "course_id" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "course_statuses", :force => true do |t| - t.integer "changesets_count" - t.integer "watchers_count" - t.integer "course_id" - t.float "grade", :default => 0.0 - t.integer "course_ac_para", :default => 0 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "courses", :force => true do |t| - t.integer "tea_id" - t.string "name" - t.integer "state" - t.string "code" - t.integer "time" - t.string "extra" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "location" - t.string "term" - t.string "string" - t.string "password" - t.string "setup_time" - t.string "endup_time" - t.string "class_period" - t.integer "school_id" - t.text "description" - t.integer "status", :default => 1 - t.integer "attachmenttype", :default => 2 - t.integer "lft" - t.integer "rgt" - t.integer "is_public", :limit => 1, :default => 1 - t.integer "inherit_members", :limit => 1, :default => 1 - t.integer "open_student", :default => 0 - end - - create_table "custom_fields", :force => true do |t| - t.string "type", :limit => 30, :default => "", :null => false - t.string "name", :limit => 30, :default => "", :null => false - t.string "field_format", :limit => 30, :default => "", :null => false - t.text "possible_values" - t.string "regexp", :default => "" - t.integer "min_length", :default => 0, :null => false - t.integer "max_length", :default => 0, :null => false - t.boolean "is_required", :default => false, :null => false - t.boolean "is_for_all", :default => false, :null => false - t.boolean "is_filter", :default => false, :null => false - t.integer "position", :default => 1 - t.boolean "searchable", :default => false - t.text "default_value" - t.boolean "editable", :default => true - t.boolean "visible", :default => true, :null => false - t.boolean "multiple", :default => false - end - - add_index "custom_fields", ["id", "type"], :name => "index_custom_fields_on_id_and_type" - - create_table "custom_fields_projects", :id => false, :force => true do |t| - t.integer "custom_field_id", :default => 0, :null => false - t.integer "project_id", :default => 0, :null => false - end - - add_index "custom_fields_projects", ["custom_field_id", "project_id"], :name => "index_custom_fields_projects_on_custom_field_id_and_project_id", :unique => true - - create_table "custom_fields_trackers", :id => false, :force => true do |t| - t.integer "custom_field_id", :default => 0, :null => false - t.integer "tracker_id", :default => 0, :null => false - end - - add_index "custom_fields_trackers", ["custom_field_id", "tracker_id"], :name => "index_custom_fields_trackers_on_custom_field_id_and_tracker_id", :unique => true - - create_table "custom_values", :force => true do |t| - t.string "customized_type", :limit => 30, :default => "", :null => false - t.integer "customized_id", :default => 0, :null => false - t.integer "custom_field_id", :default => 0, :null => false - t.text "value" - end - - add_index "custom_values", ["custom_field_id"], :name => "index_custom_values_on_custom_field_id" - add_index "custom_values", ["customized_type", "customized_id"], :name => "custom_values_customized" - - create_table "delayed_jobs", :force => true do |t| - t.integer "priority", :default => 0, :null => false - t.integer "attempts", :default => 0, :null => false - t.text "handler", :null => false - t.text "last_error" - t.datetime "run_at" - t.datetime "locked_at" - t.datetime "failed_at" - t.string "locked_by" - t.string "queue" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" - - create_table "discuss_demos", :force => true do |t| - t.string "title" - t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "documents", :force => true do |t| - t.integer "project_id", :default => 0, :null => false - t.integer "category_id", :default => 0, :null => false - t.string "title", :limit => 60, :default => "", :null => false - t.text "description" - t.datetime "created_on" - t.integer "user_id", :default => 0 - t.integer "is_public", :default => 1 - end - - add_index "documents", ["category_id"], :name => "index_documents_on_category_id" - add_index "documents", ["created_on"], :name => "index_documents_on_created_on" - add_index "documents", ["project_id"], :name => "documents_project_id" - - create_table "enabled_modules", :force => true do |t| - t.integer "project_id" - t.string "name", :null => false - t.integer "course_id" - end - - add_index "enabled_modules", ["project_id"], :name => "enabled_modules_project_id" - - create_table "enumerations", :force => true do |t| - t.string "name", :limit => 30, :default => "", :null => false - t.integer "position", :default => 1 - t.boolean "is_default", :default => false, :null => false - t.string "type" - t.boolean "active", :default => true, :null => false - t.integer "project_id" - t.integer "parent_id" - t.string "position_name", :limit => 30 - end - - add_index "enumerations", ["id", "type"], :name => "index_enumerations_on_id_and_type" - add_index "enumerations", ["project_id"], :name => "index_enumerations_on_project_id" - - create_table "first_pages", :force => true do |t| - t.string "web_title" - t.string "title" - t.text "description" - t.string "page_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "sort_type" - t.integer "image_width", :default => 107 - t.integer "image_height", :default => 63 - t.integer "show_course", :default => 1 - t.integer "show_contest", :default => 1 - end - - create_table "forge_activities", :force => true do |t| - t.integer "user_id" - t.integer "project_id" - t.integer "forge_act_id" - t.string "forge_act_type" - t.integer "org_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "forge_activities", ["forge_act_id"], :name => "index_forge_activities_on_forge_act_id" - - create_table "forums", :force => true do |t| - t.string "name", :null => false - t.text "description" - t.integer "topic_count", :default => 0 - t.integer "memo_count", :default => 0 - t.integer "last_memo_id", :default => 0 - t.integer "creator_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "sticky" - t.integer "locked" - end - - create_table "groups_users", :id => false, :force => true do |t| - t.integer "group_id", :null => false - t.integer "user_id", :null => false - end - - add_index "groups_users", ["group_id", "user_id"], :name => "groups_users_ids", :unique => true - - create_table "homework_attaches", :force => true do |t| - t.integer "bid_id" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "reward" - t.string "name" - t.text "description" - t.integer "state" - t.integer "project_id", :default => 0 - t.float "score", :default => 0.0 - t.integer "is_teacher_score", :default => 0 - end - - create_table "homework_evaluations", :force => true do |t| - t.string "user_id" - t.string "homework_attach_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "homework_for_courses", :force => true do |t| - t.integer "course_id" - t.integer "bid_id" - end - - create_table "homework_users", :force => true do |t| - t.string "homework_attach_id" - t.string "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "issue_categories", :force => true do |t| - t.integer "project_id", :default => 0, :null => false - t.string "name", :limit => 30, :default => "", :null => false - t.integer "assigned_to_id" - end - - add_index "issue_categories", ["assigned_to_id"], :name => "index_issue_categories_on_assigned_to_id" - add_index "issue_categories", ["project_id"], :name => "issue_categories_project_id" - - create_table "issue_relations", :force => true do |t| - t.integer "issue_from_id", :null => false - t.integer "issue_to_id", :null => false - t.string "relation_type", :default => "", :null => false - t.integer "delay" - end - - add_index "issue_relations", ["issue_from_id", "issue_to_id"], :name => "index_issue_relations_on_issue_from_id_and_issue_to_id", :unique => true - add_index "issue_relations", ["issue_from_id"], :name => "index_issue_relations_on_issue_from_id" - add_index "issue_relations", ["issue_to_id"], :name => "index_issue_relations_on_issue_to_id" - - create_table "issue_statuses", :force => true do |t| - t.string "name", :limit => 30, :default => "", :null => false - t.boolean "is_closed", :default => false, :null => false - t.boolean "is_default", :default => false, :null => false - t.integer "position", :default => 1 - t.integer "default_done_ratio" - end - - add_index "issue_statuses", ["is_closed"], :name => "index_issue_statuses_on_is_closed" - add_index "issue_statuses", ["is_default"], :name => "index_issue_statuses_on_is_default" - add_index "issue_statuses", ["position"], :name => "index_issue_statuses_on_position" - - create_table "issues", :force => true do |t| - t.integer "tracker_id", :null => false - t.integer "project_id", :null => false - t.string "subject", :default => "", :null => false - t.text "description" - t.date "due_date" - t.integer "category_id" - t.integer "status_id", :null => false - t.integer "assigned_to_id" - t.integer "priority_id", :null => false - t.integer "fixed_version_id" - t.integer "author_id", :null => false - t.integer "lock_version", :default => 0, :null => false - t.datetime "created_on" - t.datetime "updated_on" - t.date "start_date" - t.integer "done_ratio", :default => 0, :null => false - t.float "estimated_hours" - t.integer "parent_id" - t.integer "root_id" - t.integer "lft" - t.integer "rgt" - t.boolean "is_private", :default => false, :null => false - t.datetime "closed_on" - t.integer "project_issues_index" - end - - add_index "issues", ["assigned_to_id"], :name => "index_issues_on_assigned_to_id" - add_index "issues", ["author_id"], :name => "index_issues_on_author_id" - add_index "issues", ["category_id"], :name => "index_issues_on_category_id" - add_index "issues", ["created_on"], :name => "index_issues_on_created_on" - add_index "issues", ["fixed_version_id"], :name => "index_issues_on_fixed_version_id" - add_index "issues", ["priority_id"], :name => "index_issues_on_priority_id" - add_index "issues", ["project_id"], :name => "issues_project_id" - add_index "issues", ["root_id", "lft", "rgt"], :name => "index_issues_on_root_id_and_lft_and_rgt" - add_index "issues", ["status_id"], :name => "index_issues_on_status_id" - add_index "issues", ["tracker_id"], :name => "index_issues_on_tracker_id" - - create_table "join_in_competitions", :force => true do |t| - t.integer "user_id" - t.integer "competition_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "join_in_contests", :force => true do |t| - t.integer "user_id" - t.integer "bid_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "journal_details", :force => true do |t| - t.integer "journal_id", :default => 0, :null => false - t.string "property", :limit => 30, :default => "", :null => false - t.string "prop_key", :limit => 30, :default => "", :null => false - t.text "old_value" - t.text "value" - end - - add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" - - create_table "journal_replies", :id => false, :force => true do |t| - t.integer "journal_id" - t.integer "user_id" - t.integer "reply_id" - end - - add_index "journal_replies", ["journal_id"], :name => "index_journal_replies_on_journal_id" - add_index "journal_replies", ["reply_id"], :name => "index_journal_replies_on_reply_id" - add_index "journal_replies", ["user_id"], :name => "index_journal_replies_on_user_id" - - create_table "journals", :force => true do |t| - t.integer "journalized_id", :default => 0, :null => false - t.string "journalized_type", :limit => 30, :default => "", :null => false - t.integer "user_id", :default => 0, :null => false - t.text "notes" - t.datetime "created_on", :null => false - t.boolean "private_notes", :default => false, :null => false - end - - add_index "journals", ["created_on"], :name => "index_journals_on_created_on" - add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id" - add_index "journals", ["journalized_id"], :name => "index_journals_on_journalized_id" - add_index "journals", ["user_id"], :name => "index_journals_on_user_id" - - create_table "journals_for_messages", :force => true do |t| - t.integer "jour_id" - t.string "jour_type" - t.integer "user_id" - t.text "notes" - t.integer "status" - t.integer "reply_id" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - t.string "m_parent_id" - t.boolean "is_readed" - t.integer "m_reply_count" - t.integer "m_reply_id" - t.integer "is_comprehensive_evaluation" - end - - create_table "kindeditor_assets", :force => true do |t| - t.string "asset" - t.integer "file_size" - t.string "file_type" - t.integer "owner_id" - t.string "asset_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "owner_type", :default => 0 - end - - create_table "member_roles", :force => true do |t| - t.integer "member_id", :null => false - t.integer "role_id", :null => false - t.integer "inherited_from" - end - - add_index "member_roles", ["member_id"], :name => "index_member_roles_on_member_id" - add_index "member_roles", ["role_id"], :name => "index_member_roles_on_role_id" - - create_table "members", :force => true do |t| - t.integer "user_id", :default => 0, :null => false - t.integer "project_id", :default => 0 - t.datetime "created_on" - t.boolean "mail_notification", :default => false, :null => false - t.integer "course_id", :default => -1 - t.integer "course_group_id", :default => 0 - end - - add_index "members", ["project_id"], :name => "index_members_on_project_id" - add_index "members", ["user_id", "project_id", "course_id"], :name => "index_members_on_user_id_and_project_id", :unique => true - add_index "members", ["user_id"], :name => "index_members_on_user_id" - - create_table "memos", :force => true do |t| - t.integer "forum_id", :null => false - t.integer "parent_id" - t.string "subject", :null => false - t.text "content", :null => false - t.integer "author_id", :null => false - t.integer "replies_count", :default => 0 - t.integer "last_reply_id" - t.boolean "lock", :default => false - t.boolean "sticky", :default => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "viewed_count", :default => 0 - end - - create_table "messages", :force => true do |t| - t.integer "board_id", :null => false - t.integer "parent_id" - t.string "subject", :default => "", :null => false - t.text "content" - t.integer "author_id" - t.integer "replies_count", :default => 0, :null => false - t.integer "last_reply_id" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - t.boolean "locked", :default => false - t.integer "sticky", :default => 0 - end - - add_index "messages", ["author_id"], :name => "index_messages_on_author_id" - add_index "messages", ["board_id"], :name => "messages_board_id" - add_index "messages", ["created_on"], :name => "index_messages_on_created_on" - add_index "messages", ["last_reply_id"], :name => "index_messages_on_last_reply_id" - add_index "messages", ["parent_id"], :name => "messages_parent_id" - - create_table "news", :force => true do |t| - t.integer "project_id" - t.string "title", :limit => 60, :default => "", :null => false - t.string "summary", :default => "" - t.text "description" - t.integer "author_id", :default => 0, :null => false - t.datetime "created_on" - t.integer "comments_count", :default => 0, :null => false - t.integer "course_id" - end - - add_index "news", ["author_id"], :name => "index_news_on_author_id" - add_index "news", ["created_on"], :name => "index_news_on_created_on" - add_index "news", ["project_id"], :name => "news_project_id" - - create_table "no_uses", :force => true do |t| - t.integer "user_id", :null => false - t.string "no_use_type" - t.integer "no_use_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "notificationcomments", :force => true do |t| - t.string "notificationcommented_type" - t.integer "notificationcommented_id" - t.integer "author_id" - t.text "notificationcomments" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "open_id_authentication_associations", :force => true do |t| - t.integer "issued" - t.integer "lifetime" - t.string "handle" - t.string "assoc_type" - t.binary "server_url" - t.binary "secret" - end - - create_table "open_id_authentication_nonces", :force => true do |t| - t.integer "timestamp", :null => false - t.string "server_url" - t.string "salt", :null => false - end - - create_table "open_source_projects", :force => true do |t| - t.string "name" - t.text "description" - t.integer "commit_count", :default => 0 - t.integer "code_line", :default => 0 - t.integer "users_count", :default => 0 - t.date "last_commit_time" - t.string "url" - t.date "date_collected" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "option_numbers", :force => true do |t| - t.integer "user_id" - t.integer "memo" - t.integer "messages_for_issues" - t.integer "issues_status" - t.integer "replay_for_message" - t.integer "replay_for_memo" - t.integer "follow" - t.integer "tread" - t.integer "praise_by_one" - t.integer "praise_by_two" - t.integer "praise_by_three" - t.integer "tread_by_one" - t.integer "tread_by_two" - t.integer "tread_by_three" - t.integer "changeset" - t.integer "document" - t.integer "attachment" - t.integer "issue_done_ratio" - t.integer "post_issue" - t.integer "score_type" - t.integer "total_score" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "project_id" - end - - create_table "organizations", :force => true do |t| - t.string "name" - t.string "logo_link" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "phone_app_versions", :force => true do |t| - t.string "version" - t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "poll_answers", :force => true do |t| - t.integer "poll_question_id" - t.text "answer_text" - t.integer "answer_position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "poll_questions", :force => true do |t| - t.string "question_title" - t.integer "question_type" - t.integer "is_necessary" - t.integer "poll_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "question_number" - end - - create_table "poll_users", :force => true do |t| - t.integer "user_id" - t.integer "poll_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "poll_votes", :force => true do |t| - t.integer "user_id" - t.integer "poll_question_id" - t.integer "poll_answer_id" - t.text "vote_text" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "polls", :force => true do |t| - t.string "polls_name" - t.string "polls_type" - t.integer "polls_group_id" - t.integer "polls_status" - t.integer "user_id" - t.datetime "published_at" - t.datetime "closed_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "polls_description" - t.integer "show_result", :default => 1 - end - - create_table "praise_tread_caches", :force => true do |t| - t.integer "object_id", :null => false - t.string "object_type" - t.integer "praise_num" - t.integer "tread_num" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "praise_treads", :force => true do |t| - t.integer "user_id", :null => false - t.integer "praise_tread_object_id" - t.string "praise_tread_object_type" - t.integer "praise_or_tread" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "project_infos", :force => true do |t| - t.integer "project_id" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "project_scores", :force => true do |t| - t.string "project_id" - t.integer "score" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "issue_num", :default => 0 - t.integer "issue_journal_num", :default => 0 - t.integer "news_num", :default => 0 - t.integer "documents_num", :default => 0 - t.integer "changeset_num", :default => 0 - t.integer "board_message_num", :default => 0 - end - - create_table "project_statuses", :force => true do |t| - t.integer "changesets_count" - t.integer "watchers_count" - t.integer "project_id" - t.integer "project_type" - t.float "grade", :default => 0.0 - t.integer "course_ac_para", :default => 0 - end - - add_index "project_statuses", ["grade"], :name => "index_project_statuses_on_grade" - - create_table "projecting_softapplictions", :force => true do |t| - t.integer "user_id" - t.integer "softapplication_id" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "projects", :force => true do |t| - t.string "name", :default => "", :null => false - t.text "description" - t.string "homepage", :default => "" - t.boolean "is_public", :default => true, :null => false - t.integer "parent_id" - t.datetime "created_on" - t.datetime "updated_on" - t.string "identifier" - t.integer "status", :default => 1, :null => false - t.integer "lft" - t.integer "rgt" - t.boolean "inherit_members", :default => false, :null => false - t.integer "project_type" - t.boolean "hidden_repo", :default => false, :null => false - t.integer "attachmenttype", :default => 1 - t.integer "user_id" - t.integer "dts_test", :default => 0 - t.string "enterprise_name" - t.integer "organization_id" - end - - add_index "projects", ["lft"], :name => "index_projects_on_lft" - add_index "projects", ["rgt"], :name => "index_projects_on_rgt" - - create_table "projects_trackers", :id => false, :force => true do |t| - t.integer "project_id", :default => 0, :null => false - t.integer "tracker_id", :default => 0, :null => false - end - - add_index "projects_trackers", ["project_id", "tracker_id"], :name => "projects_trackers_unique", :unique => true - add_index "projects_trackers", ["project_id"], :name => "projects_trackers_project_id" - - create_table "queries", :force => true do |t| - t.integer "project_id" - t.string "name", :default => "", :null => false - t.text "filters" - t.integer "user_id", :default => 0, :null => false - t.boolean "is_public", :default => false, :null => false - t.text "column_names" - t.text "sort_criteria" - t.string "group_by" - t.string "type" - end - - add_index "queries", ["project_id"], :name => "index_queries_on_project_id" - add_index "queries", ["user_id"], :name => "index_queries_on_user_id" - - create_table "relative_memo_to_open_source_projects", :force => true do |t| - t.integer "osp_id" - t.integer "relative_memo_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "relative_memos", :force => true do |t| - t.integer "osp_id" - t.integer "parent_id" - t.string "subject", :null => false - t.text "content", :limit => 16777215, :null => false - t.integer "author_id" - t.integer "replies_count", :default => 0 - t.integer "last_reply_id" - t.boolean "lock", :default => false - t.boolean "sticky", :default => false - t.boolean "is_quote", :default => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "viewed_count_crawl", :default => 0 - t.integer "viewed_count_local", :default => 0 - t.string "url" - t.string "username" - t.string "userhomeurl" - t.date "date_collected" - t.string "topic_resource" - end - - create_table "repositories", :force => true do |t| - t.integer "project_id", :default => 0, :null => false - t.string "url", :default => "", :null => false - t.string "login", :limit => 60, :default => "" - t.string "password", :default => "" - t.string "root_url", :default => "" - t.string "type" - t.string "path_encoding", :limit => 64 - t.string "log_encoding", :limit => 64 - t.text "extra_info" - t.string "identifier" - t.boolean "is_default", :default => false - end - - add_index "repositories", ["project_id"], :name => "index_repositories_on_project_id" - - create_table "rich_rich_files", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "rich_file_file_name" - t.string "rich_file_content_type" - t.integer "rich_file_file_size" - t.datetime "rich_file_updated_at" - t.string "owner_type" - t.integer "owner_id" - t.text "uri_cache" - t.string "simplified_type", :default => "file" - end - - create_table "roles", :force => true do |t| - t.string "name", :limit => 30, :default => "", :null => false - t.integer "position", :default => 1 - t.boolean "assignable", :default => true - t.integer "builtin", :default => 0, :null => false - t.text "permissions" - t.string "issues_visibility", :limit => 30, :default => "default", :null => false - end - - create_table "schools", :force => true do |t| - t.string "name" - t.string "province" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "logo_link" - end - - create_table "seems_rateable_cached_ratings", :force => true do |t| - t.integer "cacheable_id", :limit => 8 - t.string "cacheable_type" - t.float "avg", :null => false - t.integer "cnt", :null => false - t.string "dimension" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "seems_rateable_rates", :force => true do |t| - t.integer "rater_id", :limit => 8 - t.integer "rateable_id" - t.string "rateable_type" - t.float "stars", :null => false - t.string "dimension" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "is_teacher_score", :default => 0 - end - - create_table "settings", :force => true do |t| - t.string "name", :default => "", :null => false - t.text "value" - t.datetime "updated_on" - end - - add_index "settings", ["name"], :name => "index_settings_on_name" - - create_table "shares", :force => true do |t| - t.date "created_on" - t.string "url" - t.string "title" - t.integer "share_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "project_id" - t.integer "user_id" - t.string "description" - end - - create_table "softapplications", :force => true do |t| - t.string "name" - t.text "description" - t.integer "app_type_id" - t.string "app_type_name" - t.string "android_min_version_available" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "contest_id" - t.integer "softapplication_id" - t.integer "is_public" - t.string "application_developers" - t.string "deposit_project_url" - t.string "deposit_project" - t.integer "project_id" - end - - create_table "students_for_courses", :force => true do |t| - t.integer "student_id" - t.integer "course_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "taggings", :force => true do |t| - t.integer "tag_id" - t.integer "taggable_id" - t.string "taggable_type" - t.integer "tagger_id" - t.string "tagger_type" - t.string "context", :limit => 128 - t.datetime "created_at" - end - - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" - add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" - add_index "taggings", ["taggable_type"], :name => "index_taggings_on_taggable_type" - - create_table "tags", :force => true do |t| - t.string "name" - end - - create_table "teachers", :force => true do |t| - t.string "tea_name" - t.string "location" - t.integer "couurse_time" - t.integer "course_code" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "extra" - end - - create_table "time_entries", :force => true do |t| - t.integer "project_id", :null => false - t.integer "user_id", :null => false - t.integer "issue_id" - t.float "hours", :null => false - t.string "comments" - t.integer "activity_id", :null => false - t.date "spent_on", :null => false - t.integer "tyear", :null => false - t.integer "tmonth", :null => false - t.integer "tweek", :null => false - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - end - - add_index "time_entries", ["activity_id"], :name => "index_time_entries_on_activity_id" - add_index "time_entries", ["created_on"], :name => "index_time_entries_on_created_on" - add_index "time_entries", ["issue_id"], :name => "time_entries_issue_id" - add_index "time_entries", ["project_id"], :name => "time_entries_project_id" - add_index "time_entries", ["user_id"], :name => "index_time_entries_on_user_id" - - create_table "tokens", :force => true do |t| - t.integer "user_id", :default => 0, :null => false - t.string "action", :limit => 30, :default => "", :null => false - t.string "value", :limit => 40, :default => "", :null => false - t.datetime "created_on", :null => false - end - - add_index "tokens", ["user_id"], :name => "index_tokens_on_user_id" - add_index "tokens", ["value"], :name => "tokens_value", :unique => true - - create_table "trackers", :force => true do |t| - t.string "name", :limit => 30, :default => "", :null => false - t.boolean "is_in_chlog", :default => false, :null => false - t.integer "position", :default => 1 - t.boolean "is_in_roadmap", :default => true, :null => false - t.integer "fields_bits", :default => 0 - end - - create_table "user_extensions", :force => true do |t| - t.integer "user_id", :null => false - t.date "birthday" - t.string "brief_introduction" - t.integer "gender" - t.string "location" - t.string "occupation" - t.integer "work_experience" - t.integer "zip_code" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "technical_title" - t.integer "identity" - t.string "student_id" - t.string "teacher_realname" - t.string "student_realname" - t.string "location_city" - t.integer "school_id" - end - - create_table "user_grades", :force => true do |t| - t.integer "user_id", :null => false - t.integer "project_id", :null => false - t.float "grade", :default => 0.0 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "user_grades", ["grade"], :name => "index_user_grades_on_grade" - add_index "user_grades", ["project_id"], :name => "index_user_grades_on_project_id" - add_index "user_grades", ["user_id"], :name => "index_user_grades_on_user_id" - - create_table "user_levels", :force => true do |t| - t.integer "user_id" - t.integer "level" - end - - create_table "user_preferences", :force => true do |t| - t.integer "user_id", :default => 0, :null => false - t.text "others" - t.boolean "hide_mail", :default => false - t.string "time_zone" - end - - add_index "user_preferences", ["user_id"], :name => "index_user_preferences_on_user_id" - - create_table "user_score_details", :force => true do |t| - t.integer "current_user_id" - t.integer "target_user_id" - t.string "score_type" - t.string "score_action" - t.integer "user_id" - t.integer "old_score" - t.integer "new_score" - t.integer "current_user_level" - t.integer "target_user_level" - t.integer "score_changeable_obj_id" - t.string "score_changeable_obj_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "user_scores", :force => true do |t| - t.integer "user_id", :null => false - t.integer "collaboration" - t.integer "influence" - t.integer "skill" - t.integer "active" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "user_statuses", :force => true do |t| - t.integer "changesets_count" - t.integer "watchers_count" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.float "grade", :default => 0.0 - end - - add_index "user_statuses", ["changesets_count"], :name => "index_user_statuses_on_changesets_count" - add_index "user_statuses", ["grade"], :name => "index_user_statuses_on_grade" - add_index "user_statuses", ["watchers_count"], :name => "index_user_statuses_on_watchers_count" - - create_table "users", :force => true do |t| - t.string "login", :default => "", :null => false - t.string "hashed_password", :limit => 40, :default => "", :null => false - t.string "firstname", :limit => 30, :default => "", :null => false - t.string "lastname", :default => "", :null => false - t.string "mail", :limit => 60, :default => "", :null => false - t.boolean "admin", :default => false, :null => false - t.integer "status", :default => 1, :null => false - t.datetime "last_login_on" - t.string "language", :limit => 5, :default => "" - t.integer "auth_source_id" - t.datetime "created_on" - t.datetime "updated_on" - t.string "type" - t.string "identity_url" - t.string "mail_notification", :default => "", :null => false - t.string "salt", :limit => 64 - end - - add_index "users", ["auth_source_id"], :name => "index_users_on_auth_source_id" - add_index "users", ["id", "type"], :name => "index_users_on_id_and_type" - add_index "users", ["type"], :name => "index_users_on_type" - - create_table "versions", :force => true do |t| - t.integer "project_id", :default => 0, :null => false - t.string "name", :default => "", :null => false - t.string "description", :default => "" - t.date "effective_date" - t.datetime "created_on" - t.datetime "updated_on" - t.string "wiki_page_title" - t.string "status", :default => "open" - t.string "sharing", :default => "none", :null => false - end - - add_index "versions", ["project_id"], :name => "versions_project_id" - add_index "versions", ["sharing"], :name => "index_versions_on_sharing" - - create_table "watchers", :force => true do |t| - t.string "watchable_type", :default => "", :null => false - t.integer "watchable_id", :default => 0, :null => false - t.integer "user_id" - end - - add_index "watchers", ["user_id", "watchable_type"], :name => "watchers_user_id_type" - add_index "watchers", ["user_id"], :name => "index_watchers_on_user_id" - add_index "watchers", ["watchable_id", "watchable_type"], :name => "index_watchers_on_watchable_id_and_watchable_type" - - create_table "web_footer_companies", :force => true do |t| - t.string "name" - t.string "logo_size" - t.string "url" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "web_footer_oranizers", :force => true do |t| - t.string "name" - t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "wiki_content_versions", :force => true do |t| - t.integer "wiki_content_id", :null => false - t.integer "page_id", :null => false - t.integer "author_id" - t.binary "data", :limit => 2147483647 - t.string "compression", :limit => 6, :default => "" - t.string "comments", :default => "" - t.datetime "updated_on", :null => false - t.integer "version", :null => false - end - - add_index "wiki_content_versions", ["updated_on"], :name => "index_wiki_content_versions_on_updated_on" - add_index "wiki_content_versions", ["wiki_content_id"], :name => "wiki_content_versions_wcid" - - create_table "wiki_contents", :force => true do |t| - t.integer "page_id", :null => false - t.integer "author_id" - t.text "text", :limit => 2147483647 - t.string "comments", :default => "" - t.datetime "updated_on", :null => false - t.integer "version", :null => false - end - - add_index "wiki_contents", ["author_id"], :name => "index_wiki_contents_on_author_id" - add_index "wiki_contents", ["page_id"], :name => "wiki_contents_page_id" - - create_table "wiki_pages", :force => true do |t| - t.integer "wiki_id", :null => false - t.string "title", :null => false - t.datetime "created_on", :null => false - t.boolean "protected", :default => false, :null => false - t.integer "parent_id" - end - - add_index "wiki_pages", ["parent_id"], :name => "index_wiki_pages_on_parent_id" - add_index "wiki_pages", ["wiki_id", "title"], :name => "wiki_pages_wiki_id_title" - add_index "wiki_pages", ["wiki_id"], :name => "index_wiki_pages_on_wiki_id" - - create_table "wiki_redirects", :force => true do |t| - t.integer "wiki_id", :null => false - t.string "title" - t.string "redirects_to" - t.datetime "created_on", :null => false - end - - add_index "wiki_redirects", ["wiki_id", "title"], :name => "wiki_redirects_wiki_id_title" - add_index "wiki_redirects", ["wiki_id"], :name => "index_wiki_redirects_on_wiki_id" - - create_table "wikis", :force => true do |t| - t.integer "project_id", :null => false - t.string "start_page", :null => false - t.integer "status", :default => 1, :null => false - end - - add_index "wikis", ["project_id"], :name => "wikis_project_id" - - create_table "workflows", :force => true do |t| - t.integer "tracker_id", :default => 0, :null => false - t.integer "old_status_id", :default => 0, :null => false - t.integer "new_status_id", :default => 0, :null => false - t.integer "role_id", :default => 0, :null => false - t.boolean "assignee", :default => false, :null => false - t.boolean "author", :default => false, :null => false - t.string "type", :limit => 30 - t.string "field_name", :limit => 30 - t.string "rule", :limit => 30 - end - - add_index "workflows", ["new_status_id"], :name => "index_workflows_on_new_status_id" - add_index "workflows", ["old_status_id"], :name => "index_workflows_on_old_status_id" - add_index "workflows", ["role_id", "tracker_id", "old_status_id"], :name => "wkfs_role_tracker_old_status" - add_index "workflows", ["role_id"], :name => "index_workflows_on_role_id" - - create_table "works_categories", :force => true do |t| - t.string "category" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "zip_packs", :force => true do |t| - t.integer "user_id" - t.integer "homework_id" - t.string "file_digest" - t.string "file_path" - t.integer "pack_times", :default => 1 - t.integer "pack_size", :default => 0 - t.text "file_digests" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - -end +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20150415032102) do + + create_table "activities", :force => true do |t| + t.integer "act_id", :null => false + t.string "act_type", :null => false + t.integer "user_id", :null => false + end + + add_index "activities", ["act_id", "act_type"], :name => "index_activities_on_act_id_and_act_type" + 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 + end + + create_table "apply_project_masters", :force => true do |t| + t.integer "user_id" + t.string "apply_type" + t.integer "apply_id" + t.integer "status" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "attachments", :force => true do |t| + t.integer "container_id" + t.string "container_type", :limit => 30 + t.string "filename", :default => "", :null => false + t.string "disk_filename", :default => "", :null => false + t.integer "filesize", :default => 0, :null => false + t.string "content_type", :default => "" + t.string "digest", :limit => 40, :default => "", :null => false + t.integer "downloads", :default => 0, :null => false + t.integer "author_id", :default => 0, :null => false + t.datetime "created_on" + t.string "description" + t.string "disk_directory" + t.integer "attachtype", :default => 1 + t.integer "is_public", :default => 1 + t.integer "copy_from" + t.integer "quotes" + end + + add_index "attachments", ["author_id"], :name => "index_attachments_on_author_id" + add_index "attachments", ["container_id", "container_type"], :name => "index_attachments_on_container_id_and_container_type" + add_index "attachments", ["created_on"], :name => "index_attachments_on_created_on" + + create_table "attachmentstypes", :force => true do |t| + t.integer "typeId", :null => false + t.string "typeName", :limit => 50 + end + + create_table "auth_sources", :force => true do |t| + t.string "type", :limit => 30, :default => "", :null => false + t.string "name", :limit => 60, :default => "", :null => false + t.string "host", :limit => 60 + t.integer "port" + t.string "account" + t.string "account_password", :default => "" + t.string "base_dn" + t.string "attr_login", :limit => 30 + t.string "attr_firstname", :limit => 30 + t.string "attr_lastname", :limit => 30 + t.string "attr_mail", :limit => 30 + t.boolean "onthefly_register", :default => false, :null => false + t.boolean "tls", :default => false, :null => false + t.string "filter" + t.integer "timeout" + end + + add_index "auth_sources", ["id", "type"], :name => "index_auth_sources_on_id_and_type" + + create_table "biding_projects", :force => true do |t| + t.integer "project_id" + t.integer "bid_id" + t.integer "user_id" + t.string "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "reward" + end + + create_table "bids", :force => true do |t| + t.string "name" + t.string "budget", :null => false + t.integer "author_id" + t.date "deadline" + t.text "description" + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + t.integer "commit" + t.integer "reward_type" + t.integer "homework_type" + t.integer "parent_id" + t.string "password" + t.integer "is_evaluation" + t.integer "proportion", :default => 60 + t.integer "comment_status", :default => 0 + t.integer "evaluation_num", :default => 3 + t.integer "open_anonymous_evaluation", :default => 1 + end + + create_table "boards", :force => true do |t| + t.integer "project_id", :null => false + t.string "name", :default => "", :null => false + t.string "description" + t.integer "position", :default => 1 + t.integer "topics_count", :default => 0, :null => false + t.integer "messages_count", :default => 0, :null => false + t.integer "last_message_id" + t.integer "parent_id" + t.integer "course_id" + end + + add_index "boards", ["last_message_id"], :name => "index_boards_on_last_message_id" + add_index "boards", ["project_id"], :name => "boards_project_id" + + create_table "bug_to_osps", :force => true do |t| + t.integer "osp_id" + t.integer "relative_memo_id" + t.string "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "changes", :force => true do |t| + t.integer "changeset_id", :null => false + t.string "action", :limit => 1, :default => "", :null => false + t.text "path", :null => false + t.text "from_path" + t.string "from_revision" + t.string "revision" + t.string "branch" + end + + add_index "changes", ["changeset_id"], :name => "changesets_changeset_id" + + create_table "changeset_parents", :id => false, :force => true do |t| + t.integer "changeset_id", :null => false + t.integer "parent_id", :null => false + end + + add_index "changeset_parents", ["changeset_id"], :name => "changeset_parents_changeset_ids" + add_index "changeset_parents", ["parent_id"], :name => "changeset_parents_parent_ids" + + create_table "changesets", :force => true do |t| + t.integer "repository_id", :null => false + t.string "revision", :null => false + t.string "committer" + t.datetime "committed_on", :null => false + t.text "comments" + t.date "commit_date" + t.string "scmid" + t.integer "user_id" + end + + add_index "changesets", ["committed_on"], :name => "index_changesets_on_committed_on" + add_index "changesets", ["repository_id", "revision"], :name => "changesets_repos_rev", :unique => true + add_index "changesets", ["repository_id", "scmid"], :name => "changesets_repos_scmid" + add_index "changesets", ["repository_id"], :name => "index_changesets_on_repository_id" + add_index "changesets", ["user_id"], :name => "index_changesets_on_user_id" + + create_table "changesets_issues", :id => false, :force => true do |t| + t.integer "changeset_id", :null => false + t.integer "issue_id", :null => false + end + + add_index "changesets_issues", ["changeset_id", "issue_id"], :name => "changesets_issues_ids", :unique => true + + create_table "code_review_assignments", :force => true do |t| + t.integer "issue_id" + t.integer "change_id" + t.integer "attachment_id" + t.string "file_path" + t.string "rev" + t.string "rev_to" + t.string "action_type" + t.integer "changeset_id" + end + + create_table "code_review_project_settings", :force => true do |t| + t.integer "project_id" + t.integer "tracker_id" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "updated_by" + t.boolean "hide_code_review_tab", :default => false + t.integer "auto_relation", :default => 1 + t.integer "assignment_tracker_id" + t.text "auto_assign" + t.integer "lock_version", :default => 0, :null => false + t.boolean "tracker_in_review_dialog", :default => false + end + + create_table "code_review_user_settings", :force => true do |t| + t.integer "user_id", :default => 0, :null => false + t.integer "mail_notification", :default => 0, :null => false + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "code_reviews", :force => true do |t| + t.integer "project_id" + t.integer "change_id" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "line" + t.integer "updated_by_id" + t.integer "lock_version", :default => 0, :null => false + t.integer "status_changed_from" + t.integer "status_changed_to" + t.integer "issue_id" + t.string "action_type" + t.string "file_path" + t.string "rev" + t.string "rev_to" + t.integer "attachment_id" + t.integer "file_count", :default => 0, :null => false + t.boolean "diff_all" + end + + create_table "comments", :force => true do |t| + t.string "commented_type", :limit => 30, :default => "", :null => false + t.integer "commented_id", :default => 0, :null => false + t.integer "author_id", :default => 0, :null => false + t.text "comments" + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + end + + add_index "comments", ["author_id"], :name => "index_comments_on_author_id" + add_index "comments", ["commented_id", "commented_type"], :name => "index_comments_on_commented_id_and_commented_type" + + create_table "contest_notifications", :force => true do |t| + t.text "title" + t.text "content" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "contesting_projects", :force => true do |t| + t.integer "project_id" + t.string "contest_id" + t.integer "user_id" + t.string "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "reward" + end + + create_table "contesting_softapplications", :force => true do |t| + t.integer "softapplication_id" + t.integer "contest_id" + t.integer "user_id" + t.string "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "reward" + end + + create_table "contestnotifications", :force => true do |t| + t.integer "contest_id" + t.string "title" + t.string "summary" + t.text "description" + t.integer "author_id" + t.integer "notificationcomments_count" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "contests", :force => true do |t| + t.string "name" + t.string "budget", :default => "" + t.integer "author_id" + t.date "deadline" + t.string "description" + t.integer "commit" + t.string "password" + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + end + + create_table "course_attachments", :force => true do |t| + t.string "filename" + t.string "disk_filename" + t.integer "filesize" + t.string "content_type" + t.string "digest" + t.integer "downloads" + t.string "author_id" + t.string "integer" + t.string "description" + t.string "disk_directory" + t.integer "attachtype" + t.integer "is_public" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "container_id", :default => 0 + end + + create_table "course_groups", :force => true do |t| + t.string "name" + t.integer "course_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "course_infos", :force => true do |t| + t.integer "course_id" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "course_statuses", :force => true do |t| + t.integer "changesets_count" + t.integer "watchers_count" + t.integer "course_id" + t.float "grade", :default => 0.0 + t.integer "course_ac_para", :default => 0 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "courses", :force => true do |t| + t.integer "tea_id" + t.string "name" + t.integer "state" + t.string "code" + t.integer "time" + t.string "extra" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "location" + t.string "term" + t.string "string" + t.string "password" + t.string "setup_time" + t.string "endup_time" + t.string "class_period" + t.integer "school_id" + t.text "description" + t.integer "status", :default => 1 + t.integer "attachmenttype", :default => 2 + t.integer "lft" + t.integer "rgt" + t.integer "is_public", :limit => 1, :default => 1 + t.integer "inherit_members", :limit => 1, :default => 1 + t.integer "open_student", :default => 0 + end + + create_table "custom_fields", :force => true do |t| + t.string "type", :limit => 30, :default => "", :null => false + t.string "name", :limit => 30, :default => "", :null => false + t.string "field_format", :limit => 30, :default => "", :null => false + t.text "possible_values" + t.string "regexp", :default => "" + t.integer "min_length", :default => 0, :null => false + t.integer "max_length", :default => 0, :null => false + t.boolean "is_required", :default => false, :null => false + t.boolean "is_for_all", :default => false, :null => false + t.boolean "is_filter", :default => false, :null => false + t.integer "position", :default => 1 + t.boolean "searchable", :default => false + t.text "default_value" + t.boolean "editable", :default => true + t.boolean "visible", :default => true, :null => false + t.boolean "multiple", :default => false + end + + add_index "custom_fields", ["id", "type"], :name => "index_custom_fields_on_id_and_type" + + create_table "custom_fields_projects", :id => false, :force => true do |t| + t.integer "custom_field_id", :default => 0, :null => false + t.integer "project_id", :default => 0, :null => false + end + + add_index "custom_fields_projects", ["custom_field_id", "project_id"], :name => "index_custom_fields_projects_on_custom_field_id_and_project_id", :unique => true + + create_table "custom_fields_trackers", :id => false, :force => true do |t| + t.integer "custom_field_id", :default => 0, :null => false + t.integer "tracker_id", :default => 0, :null => false + end + + add_index "custom_fields_trackers", ["custom_field_id", "tracker_id"], :name => "index_custom_fields_trackers_on_custom_field_id_and_tracker_id", :unique => true + + create_table "custom_values", :force => true do |t| + t.string "customized_type", :limit => 30, :default => "", :null => false + t.integer "customized_id", :default => 0, :null => false + t.integer "custom_field_id", :default => 0, :null => false + t.text "value" + end + + add_index "custom_values", ["custom_field_id"], :name => "index_custom_values_on_custom_field_id" + add_index "custom_values", ["customized_type", "customized_id"], :name => "custom_values_customized" + + create_table "delayed_jobs", :force => true do |t| + t.integer "priority", :default => 0, :null => false + t.integer "attempts", :default => 0, :null => false + t.text "handler", :null => false + t.text "last_error" + t.datetime "run_at" + t.datetime "locked_at" + t.datetime "failed_at" + t.string "locked_by" + t.string "queue" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" + + create_table "documents", :force => true do |t| + t.integer "project_id", :default => 0, :null => false + t.integer "category_id", :default => 0, :null => false + t.string "title", :limit => 60, :default => "", :null => false + t.text "description" + t.datetime "created_on" + t.integer "user_id", :default => 0 + t.integer "is_public", :default => 1 + end + + add_index "documents", ["category_id"], :name => "index_documents_on_category_id" + add_index "documents", ["created_on"], :name => "index_documents_on_created_on" + add_index "documents", ["project_id"], :name => "documents_project_id" + + create_table "enabled_modules", :force => true do |t| + t.integer "project_id" + t.string "name", :null => false + t.integer "course_id" + end + + add_index "enabled_modules", ["project_id"], :name => "enabled_modules_project_id" + + create_table "enumerations", :force => true do |t| + t.string "name", :limit => 30, :default => "", :null => false + t.integer "position", :default => 1 + t.boolean "is_default", :default => false, :null => false + t.string "type" + t.boolean "active", :default => true, :null => false + t.integer "project_id" + t.integer "parent_id" + t.string "position_name", :limit => 30 + end + + add_index "enumerations", ["id", "type"], :name => "index_enumerations_on_id_and_type" + add_index "enumerations", ["project_id"], :name => "index_enumerations_on_project_id" + + create_table "first_pages", :force => true do |t| + t.string "web_title" + t.string "title" + t.text "description" + t.string "page_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "sort_type" + t.integer "image_width", :default => 107 + t.integer "image_height", :default => 63 + t.integer "show_course", :default => 1 + t.integer "show_contest", :default => 1 + end + + create_table "forge_activities", :force => true do |t| + t.integer "user_id" + t.integer "project_id" + t.integer "forge_act_id" + t.string "forge_act_type" + t.integer "org_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "forge_activities", ["forge_act_id"], :name => "index_forge_activities_on_forge_act_id" + + create_table "forums", :force => true do |t| + t.string "name", :null => false + t.text "description" + t.integer "topic_count", :default => 0 + t.integer "memo_count", :default => 0 + t.integer "last_memo_id", :default => 0 + t.integer "creator_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "sticky" + t.integer "locked" + end + + create_table "groups_users", :id => false, :force => true do |t| + t.integer "group_id", :null => false + t.integer "user_id", :null => false + end + + add_index "groups_users", ["group_id", "user_id"], :name => "groups_users_ids", :unique => true + + create_table "homework_attaches", :force => true do |t| + t.integer "bid_id" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "reward" + t.string "name" + t.text "description" + t.integer "state" + t.integer "project_id", :default => 0 + t.float "score", :default => 0.0 + t.integer "is_teacher_score", :default => 0 + end + + create_table "homework_evaluations", :force => true do |t| + t.string "user_id" + t.string "homework_attach_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "homework_for_courses", :force => true do |t| + t.integer "course_id" + t.integer "bid_id" + end + + create_table "homework_users", :force => true do |t| + t.string "homework_attach_id" + t.string "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "issue_categories", :force => true do |t| + t.integer "project_id", :default => 0, :null => false + t.string "name", :limit => 30, :default => "", :null => false + t.integer "assigned_to_id" + end + + add_index "issue_categories", ["assigned_to_id"], :name => "index_issue_categories_on_assigned_to_id" + add_index "issue_categories", ["project_id"], :name => "issue_categories_project_id" + + create_table "issue_relations", :force => true do |t| + t.integer "issue_from_id", :null => false + t.integer "issue_to_id", :null => false + t.string "relation_type", :default => "", :null => false + t.integer "delay" + end + + add_index "issue_relations", ["issue_from_id", "issue_to_id"], :name => "index_issue_relations_on_issue_from_id_and_issue_to_id", :unique => true + add_index "issue_relations", ["issue_from_id"], :name => "index_issue_relations_on_issue_from_id" + add_index "issue_relations", ["issue_to_id"], :name => "index_issue_relations_on_issue_to_id" + + create_table "issue_statuses", :force => true do |t| + t.string "name", :limit => 30, :default => "", :null => false + t.boolean "is_closed", :default => false, :null => false + t.boolean "is_default", :default => false, :null => false + t.integer "position", :default => 1 + t.integer "default_done_ratio" + end + + add_index "issue_statuses", ["is_closed"], :name => "index_issue_statuses_on_is_closed" + add_index "issue_statuses", ["is_default"], :name => "index_issue_statuses_on_is_default" + add_index "issue_statuses", ["position"], :name => "index_issue_statuses_on_position" + + create_table "issues", :force => true do |t| + t.integer "tracker_id", :null => false + t.integer "project_id", :null => false + t.string "subject", :default => "", :null => false + t.text "description" + t.date "due_date" + t.integer "category_id" + t.integer "status_id", :null => false + t.integer "assigned_to_id" + t.integer "priority_id", :null => false + t.integer "fixed_version_id" + t.integer "author_id", :null => false + t.integer "lock_version", :default => 0, :null => false + t.datetime "created_on" + t.datetime "updated_on" + t.date "start_date" + t.integer "done_ratio", :default => 0, :null => false + t.float "estimated_hours" + t.integer "parent_id" + t.integer "root_id" + t.integer "lft" + t.integer "rgt" + t.boolean "is_private", :default => false, :null => false + t.datetime "closed_on" + t.integer "project_issues_index" + end + + add_index "issues", ["assigned_to_id"], :name => "index_issues_on_assigned_to_id" + add_index "issues", ["author_id"], :name => "index_issues_on_author_id" + add_index "issues", ["category_id"], :name => "index_issues_on_category_id" + add_index "issues", ["created_on"], :name => "index_issues_on_created_on" + add_index "issues", ["fixed_version_id"], :name => "index_issues_on_fixed_version_id" + add_index "issues", ["priority_id"], :name => "index_issues_on_priority_id" + add_index "issues", ["project_id"], :name => "issues_project_id" + add_index "issues", ["root_id", "lft", "rgt"], :name => "index_issues_on_root_id_and_lft_and_rgt" + add_index "issues", ["status_id"], :name => "index_issues_on_status_id" + add_index "issues", ["tracker_id"], :name => "index_issues_on_tracker_id" + + create_table "join_in_competitions", :force => true do |t| + t.integer "user_id" + t.integer "competition_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "join_in_contests", :force => true do |t| + t.integer "user_id" + t.integer "bid_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "journal_details", :force => true do |t| + t.integer "journal_id", :default => 0, :null => false + t.string "property", :limit => 30, :default => "", :null => false + t.string "prop_key", :limit => 30, :default => "", :null => false + t.text "old_value" + t.text "value" + end + + add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" + + create_table "journal_replies", :id => false, :force => true do |t| + t.integer "journal_id" + t.integer "user_id" + t.integer "reply_id" + end + + add_index "journal_replies", ["journal_id"], :name => "index_journal_replies_on_journal_id" + add_index "journal_replies", ["reply_id"], :name => "index_journal_replies_on_reply_id" + add_index "journal_replies", ["user_id"], :name => "index_journal_replies_on_user_id" + + create_table "journals", :force => true do |t| + t.integer "journalized_id", :default => 0, :null => false + t.string "journalized_type", :limit => 30, :default => "", :null => false + t.integer "user_id", :default => 0, :null => false + t.text "notes" + t.datetime "created_on", :null => false + t.boolean "private_notes", :default => false, :null => false + end + + add_index "journals", ["created_on"], :name => "index_journals_on_created_on" + add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id" + add_index "journals", ["journalized_id"], :name => "index_journals_on_journalized_id" + add_index "journals", ["user_id"], :name => "index_journals_on_user_id" + + create_table "journals_for_messages", :force => true do |t| + t.integer "jour_id" + t.string "jour_type" + t.integer "user_id" + t.text "notes" + t.integer "status" + t.integer "reply_id" + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + t.string "m_parent_id" + t.boolean "is_readed" + t.integer "m_reply_count" + t.integer "m_reply_id" + t.integer "is_comprehensive_evaluation" + end + + create_table "kindeditor_assets", :force => true do |t| + t.string "asset" + t.integer "file_size" + t.string "file_type" + t.integer "owner_id" + t.string "asset_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "owner_type", :default => 0 + end + + create_table "member_roles", :force => true do |t| + t.integer "member_id", :null => false + t.integer "role_id", :null => false + t.integer "inherited_from" + end + + add_index "member_roles", ["member_id"], :name => "index_member_roles_on_member_id" + add_index "member_roles", ["role_id"], :name => "index_member_roles_on_role_id" + + create_table "members", :force => true do |t| + t.integer "user_id", :default => 0, :null => false + t.integer "project_id", :default => 0 + t.datetime "created_on" + t.boolean "mail_notification", :default => false, :null => false + t.integer "course_id", :default => -1 + t.integer "course_group_id", :default => 0 + end + + add_index "members", ["project_id"], :name => "index_members_on_project_id" + add_index "members", ["user_id", "project_id", "course_id"], :name => "index_members_on_user_id_and_project_id", :unique => true + add_index "members", ["user_id"], :name => "index_members_on_user_id" + + create_table "memos", :force => true do |t| + t.integer "forum_id", :null => false + t.integer "parent_id" + t.string "subject", :null => false + t.text "content", :null => false + t.integer "author_id", :null => false + t.integer "replies_count", :default => 0 + t.integer "last_reply_id" + t.boolean "lock", :default => false + t.boolean "sticky", :default => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "viewed_count", :default => 0 + end + + create_table "messages", :force => true do |t| + t.integer "board_id", :null => false + t.integer "parent_id" + t.string "subject", :default => "", :null => false + t.text "content" + t.integer "author_id" + t.integer "replies_count", :default => 0, :null => false + t.integer "last_reply_id" + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + t.boolean "locked", :default => false + t.integer "sticky", :default => 0 + end + + add_index "messages", ["author_id"], :name => "index_messages_on_author_id" + add_index "messages", ["board_id"], :name => "messages_board_id" + add_index "messages", ["created_on"], :name => "index_messages_on_created_on" + add_index "messages", ["last_reply_id"], :name => "index_messages_on_last_reply_id" + add_index "messages", ["parent_id"], :name => "messages_parent_id" + + create_table "news", :force => true do |t| + t.integer "project_id" + t.string "title", :limit => 60, :default => "", :null => false + t.string "summary", :default => "" + t.text "description" + t.integer "author_id", :default => 0, :null => false + t.datetime "created_on" + t.integer "comments_count", :default => 0, :null => false + t.integer "course_id" + end + + add_index "news", ["author_id"], :name => "index_news_on_author_id" + add_index "news", ["created_on"], :name => "index_news_on_created_on" + add_index "news", ["project_id"], :name => "news_project_id" + + create_table "no_uses", :force => true do |t| + t.integer "user_id", :null => false + t.string "no_use_type" + t.integer "no_use_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "notificationcomments", :force => true do |t| + t.string "notificationcommented_type" + t.integer "notificationcommented_id" + t.integer "author_id" + t.text "notificationcomments" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "open_id_authentication_associations", :force => true do |t| + t.integer "issued" + t.integer "lifetime" + t.string "handle" + t.string "assoc_type" + t.binary "server_url" + t.binary "secret" + end + + create_table "open_id_authentication_nonces", :force => true do |t| + t.integer "timestamp", :null => false + t.string "server_url" + t.string "salt", :null => false + end + + create_table "open_source_projects", :force => true do |t| + t.string "name" + t.text "description" + t.integer "commit_count", :default => 0 + t.integer "code_line", :default => 0 + t.integer "users_count", :default => 0 + t.date "last_commit_time" + t.string "url" + t.date "date_collected" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "option_numbers", :force => true do |t| + t.integer "user_id" + t.integer "memo" + t.integer "messages_for_issues" + t.integer "issues_status" + t.integer "replay_for_message" + t.integer "replay_for_memo" + t.integer "follow" + t.integer "tread" + t.integer "praise_by_one" + t.integer "praise_by_two" + t.integer "praise_by_three" + t.integer "tread_by_one" + t.integer "tread_by_two" + t.integer "tread_by_three" + t.integer "changeset" + t.integer "document" + t.integer "attachment" + t.integer "issue_done_ratio" + t.integer "post_issue" + t.integer "score_type" + t.integer "total_score" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "project_id" + end + + create_table "organizations", :force => true do |t| + t.string "name" + t.string "logo_link" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "phone_app_versions", :force => true do |t| + t.string "version" + t.text "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "poll_answers", :force => true do |t| + t.integer "poll_question_id" + t.text "answer_text" + t.integer "answer_position" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "poll_questions", :force => true do |t| + t.string "question_title" + t.integer "question_type" + t.integer "is_necessary" + t.integer "poll_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "question_number" + end + + create_table "poll_users", :force => true do |t| + t.integer "user_id" + t.integer "poll_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "poll_votes", :force => true do |t| + t.integer "user_id" + t.integer "poll_question_id" + t.integer "poll_answer_id" + t.text "vote_text" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "polls", :force => true do |t| + t.string "polls_name" + t.string "polls_type" + t.integer "polls_group_id" + t.integer "polls_status" + t.integer "user_id" + t.datetime "published_at" + t.datetime "closed_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.text "polls_description" + t.integer "show_result", :default => 1 + end + + create_table "praise_tread_caches", :force => true do |t| + t.integer "object_id", :null => false + t.string "object_type" + t.integer "praise_num" + t.integer "tread_num" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "praise_treads", :force => true do |t| + t.integer "user_id", :null => false + t.integer "praise_tread_object_id" + t.string "praise_tread_object_type" + t.integer "praise_or_tread" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "project_infos", :force => true do |t| + t.integer "project_id" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "project_scores", :force => true do |t| + t.string "project_id" + t.integer "score" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "issue_num", :default => 0 + t.integer "issue_journal_num", :default => 0 + t.integer "news_num", :default => 0 + t.integer "documents_num", :default => 0 + t.integer "changeset_num", :default => 0 + t.integer "board_message_num", :default => 0 + end + + create_table "project_statuses", :force => true do |t| + t.integer "changesets_count" + t.integer "watchers_count" + t.integer "project_id" + t.integer "project_type" + t.float "grade", :default => 0.0 + t.integer "course_ac_para", :default => 0 + end + + add_index "project_statuses", ["grade"], :name => "index_project_statuses_on_grade" + + create_table "projecting_softapplictions", :force => true do |t| + t.integer "user_id" + t.integer "softapplication_id" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "projects", :force => true do |t| + t.string "name", :default => "", :null => false + t.text "description" + t.string "homepage", :default => "" + t.boolean "is_public", :default => true, :null => false + t.integer "parent_id" + t.datetime "created_on" + t.datetime "updated_on" + t.string "identifier" + t.integer "status", :default => 1, :null => false + t.integer "lft" + t.integer "rgt" + t.boolean "inherit_members", :default => false, :null => false + t.integer "project_type" + t.boolean "hidden_repo", :default => false, :null => false + t.integer "attachmenttype", :default => 1 + t.integer "user_id" + t.integer "dts_test", :default => 0 + t.string "enterprise_name" + t.integer "organization_id" + end + + add_index "projects", ["lft"], :name => "index_projects_on_lft" + add_index "projects", ["rgt"], :name => "index_projects_on_rgt" + + create_table "projects_trackers", :id => false, :force => true do |t| + t.integer "project_id", :default => 0, :null => false + t.integer "tracker_id", :default => 0, :null => false + end + + add_index "projects_trackers", ["project_id", "tracker_id"], :name => "projects_trackers_unique", :unique => true + add_index "projects_trackers", ["project_id"], :name => "projects_trackers_project_id" + + create_table "queries", :force => true do |t| + t.integer "project_id" + t.string "name", :default => "", :null => false + t.text "filters" + t.integer "user_id", :default => 0, :null => false + t.boolean "is_public", :default => false, :null => false + t.text "column_names" + t.text "sort_criteria" + t.string "group_by" + t.string "type" + end + + add_index "queries", ["project_id"], :name => "index_queries_on_project_id" + add_index "queries", ["user_id"], :name => "index_queries_on_user_id" + + create_table "relative_memo_to_open_source_projects", :force => true do |t| + t.integer "osp_id" + t.integer "relative_memo_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "relative_memos", :force => true do |t| + t.integer "osp_id" + t.integer "parent_id" + t.string "subject", :null => false + t.text "content", :limit => 16777215, :null => false + t.integer "author_id" + t.integer "replies_count", :default => 0 + t.integer "last_reply_id" + t.boolean "lock", :default => false + t.boolean "sticky", :default => false + t.boolean "is_quote", :default => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "viewed_count_crawl", :default => 0 + t.integer "viewed_count_local", :default => 0 + t.string "url" + t.string "username" + t.string "userhomeurl" + t.date "date_collected" + t.string "topic_resource" + end + + create_table "repositories", :force => true do |t| + t.integer "project_id", :default => 0, :null => false + t.string "url", :default => "", :null => false + t.string "login", :limit => 60, :default => "" + t.string "password", :default => "" + t.string "root_url", :default => "" + t.string "type" + t.string "path_encoding", :limit => 64 + t.string "log_encoding", :limit => 64 + t.text "extra_info" + t.string "identifier" + t.boolean "is_default", :default => false + end + + add_index "repositories", ["project_id"], :name => "index_repositories_on_project_id" + + create_table "rich_rich_files", :force => true do |t| + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "rich_file_file_name" + t.string "rich_file_content_type" + t.integer "rich_file_file_size" + t.datetime "rich_file_updated_at" + t.string "owner_type" + t.integer "owner_id" + t.text "uri_cache" + t.string "simplified_type", :default => "file" + end + + create_table "roles", :force => true do |t| + t.string "name", :limit => 30, :default => "", :null => false + t.integer "position", :default => 1 + t.boolean "assignable", :default => true + t.integer "builtin", :default => 0, :null => false + t.text "permissions" + t.string "issues_visibility", :limit => 30, :default => "default", :null => false + end + + create_table "schools", :force => true do |t| + t.string "name" + t.string "province" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "logo_link" + end + + create_table "seems_rateable_cached_ratings", :force => true do |t| + t.integer "cacheable_id", :limit => 8 + t.string "cacheable_type" + t.float "avg", :null => false + t.integer "cnt", :null => false + t.string "dimension" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "seems_rateable_rates", :force => true do |t| + t.integer "rater_id", :limit => 8 + t.integer "rateable_id" + t.string "rateable_type" + t.float "stars", :null => false + t.string "dimension" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "is_teacher_score", :default => 0 + end + + create_table "settings", :force => true do |t| + t.string "name", :default => "", :null => false + t.text "value" + t.datetime "updated_on" + end + + add_index "settings", ["name"], :name => "index_settings_on_name" + + create_table "shares", :force => true do |t| + t.date "created_on" + t.string "url" + t.string "title" + t.integer "share_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "project_id" + t.integer "user_id" + t.string "description" + end + + create_table "softapplications", :force => true do |t| + t.string "name" + t.text "description" + t.integer "app_type_id" + t.string "app_type_name" + t.string "android_min_version_available" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "contest_id" + t.integer "softapplication_id" + t.integer "is_public" + t.string "application_developers" + t.string "deposit_project_url" + t.string "deposit_project" + t.integer "project_id" + end + + create_table "students_for_courses", :force => true do |t| + t.integer "student_id" + t.integer "course_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "taggings", :force => true do |t| + t.integer "tag_id" + t.integer "taggable_id" + t.string "taggable_type" + t.integer "tagger_id" + t.string "tagger_type" + t.string "context", :limit => 128 + t.datetime "created_at" + end + + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" + add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + add_index "taggings", ["taggable_type"], :name => "index_taggings_on_taggable_type" + + create_table "tags", :force => true do |t| + t.string "name" + end + + create_table "teachers", :force => true do |t| + t.string "tea_name" + t.string "location" + t.integer "couurse_time" + t.integer "course_code" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "extra" + end + + create_table "time_entries", :force => true do |t| + t.integer "project_id", :null => false + t.integer "user_id", :null => false + t.integer "issue_id" + t.float "hours", :null => false + t.string "comments" + t.integer "activity_id", :null => false + t.date "spent_on", :null => false + t.integer "tyear", :null => false + t.integer "tmonth", :null => false + t.integer "tweek", :null => false + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + end + + add_index "time_entries", ["activity_id"], :name => "index_time_entries_on_activity_id" + add_index "time_entries", ["created_on"], :name => "index_time_entries_on_created_on" + add_index "time_entries", ["issue_id"], :name => "time_entries_issue_id" + add_index "time_entries", ["project_id"], :name => "time_entries_project_id" + add_index "time_entries", ["user_id"], :name => "index_time_entries_on_user_id" + + create_table "tokens", :force => true do |t| + t.integer "user_id", :default => 0, :null => false + t.string "action", :limit => 30, :default => "", :null => false + t.string "value", :limit => 40, :default => "", :null => false + t.datetime "created_on", :null => false + end + + add_index "tokens", ["user_id"], :name => "index_tokens_on_user_id" + add_index "tokens", ["value"], :name => "tokens_value", :unique => true + + create_table "trackers", :force => true do |t| + t.string "name", :limit => 30, :default => "", :null => false + t.boolean "is_in_chlog", :default => false, :null => false + t.integer "position", :default => 1 + t.boolean "is_in_roadmap", :default => true, :null => false + t.integer "fields_bits", :default => 0 + end + + create_table "user_extensions", :force => true do |t| + t.integer "user_id", :null => false + t.date "birthday" + t.string "brief_introduction" + t.integer "gender" + t.string "location" + t.string "occupation" + t.integer "work_experience" + t.integer "zip_code" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "technical_title" + t.integer "identity" + t.string "student_id" + t.string "teacher_realname" + t.string "student_realname" + t.string "location_city" + t.integer "school_id" + end + + create_table "user_grades", :force => true do |t| + t.integer "user_id", :null => false + t.integer "project_id", :null => false + t.float "grade", :default => 0.0 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "user_grades", ["grade"], :name => "index_user_grades_on_grade" + add_index "user_grades", ["project_id"], :name => "index_user_grades_on_project_id" + add_index "user_grades", ["user_id"], :name => "index_user_grades_on_user_id" + + create_table "user_levels", :force => true do |t| + t.integer "user_id" + t.integer "level" + end + + create_table "user_preferences", :force => true do |t| + t.integer "user_id", :default => 0, :null => false + t.text "others" + t.boolean "hide_mail", :default => false + t.string "time_zone" + end + + add_index "user_preferences", ["user_id"], :name => "index_user_preferences_on_user_id" + + create_table "user_score_details", :force => true do |t| + t.integer "current_user_id" + t.integer "target_user_id" + t.string "score_type" + t.string "score_action" + t.integer "user_id" + t.integer "old_score" + t.integer "new_score" + t.integer "current_user_level" + t.integer "target_user_level" + t.integer "score_changeable_obj_id" + t.string "score_changeable_obj_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_scores", :force => true do |t| + t.integer "user_id", :null => false + t.integer "collaboration" + t.integer "influence" + t.integer "skill" + t.integer "active" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_statuses", :force => true do |t| + t.integer "changesets_count" + t.integer "watchers_count" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.float "grade", :default => 0.0 + end + + add_index "user_statuses", ["changesets_count"], :name => "index_user_statuses_on_changesets_count" + add_index "user_statuses", ["grade"], :name => "index_user_statuses_on_grade" + add_index "user_statuses", ["watchers_count"], :name => "index_user_statuses_on_watchers_count" + + create_table "users", :force => true do |t| + t.string "login", :default => "", :null => false + t.string "hashed_password", :limit => 40, :default => "", :null => false + t.string "firstname", :limit => 30, :default => "", :null => false + t.string "lastname", :default => "", :null => false + t.string "mail", :limit => 60, :default => "", :null => false + t.boolean "admin", :default => false, :null => false + t.integer "status", :default => 1, :null => false + t.datetime "last_login_on" + t.string "language", :limit => 5, :default => "" + t.integer "auth_source_id" + t.datetime "created_on" + t.datetime "updated_on" + t.string "type" + t.string "identity_url" + t.string "mail_notification", :default => "", :null => false + t.string "salt", :limit => 64 + end + + add_index "users", ["auth_source_id"], :name => "index_users_on_auth_source_id" + add_index "users", ["id", "type"], :name => "index_users_on_id_and_type" + add_index "users", ["type"], :name => "index_users_on_type" + + create_table "versions", :force => true do |t| + t.integer "project_id", :default => 0, :null => false + t.string "name", :default => "", :null => false + t.string "description", :default => "" + t.date "effective_date" + t.datetime "created_on" + t.datetime "updated_on" + t.string "wiki_page_title" + t.string "status", :default => "open" + t.string "sharing", :default => "none", :null => false + end + + add_index "versions", ["project_id"], :name => "versions_project_id" + add_index "versions", ["sharing"], :name => "index_versions_on_sharing" + + create_table "watchers", :force => true do |t| + t.string "watchable_type", :default => "", :null => false + t.integer "watchable_id", :default => 0, :null => false + t.integer "user_id" + end + + add_index "watchers", ["user_id", "watchable_type"], :name => "watchers_user_id_type" + add_index "watchers", ["user_id"], :name => "index_watchers_on_user_id" + add_index "watchers", ["watchable_id", "watchable_type"], :name => "index_watchers_on_watchable_id_and_watchable_type" + + create_table "web_footer_companies", :force => true do |t| + t.string "name" + t.string "logo_size" + t.string "url" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "web_footer_oranizers", :force => true do |t| + t.string "name" + t.text "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "wiki_content_versions", :force => true do |t| + t.integer "wiki_content_id", :null => false + t.integer "page_id", :null => false + t.integer "author_id" + t.binary "data", :limit => 2147483647 + t.string "compression", :limit => 6, :default => "" + t.string "comments", :default => "" + t.datetime "updated_on", :null => false + t.integer "version", :null => false + end + + add_index "wiki_content_versions", ["updated_on"], :name => "index_wiki_content_versions_on_updated_on" + add_index "wiki_content_versions", ["wiki_content_id"], :name => "wiki_content_versions_wcid" + + create_table "wiki_contents", :force => true do |t| + t.integer "page_id", :null => false + t.integer "author_id" + t.text "text", :limit => 2147483647 + t.string "comments", :default => "" + t.datetime "updated_on", :null => false + t.integer "version", :null => false + end + + add_index "wiki_contents", ["author_id"], :name => "index_wiki_contents_on_author_id" + add_index "wiki_contents", ["page_id"], :name => "wiki_contents_page_id" + + create_table "wiki_pages", :force => true do |t| + t.integer "wiki_id", :null => false + t.string "title", :null => false + t.datetime "created_on", :null => false + t.boolean "protected", :default => false, :null => false + t.integer "parent_id" + end + + add_index "wiki_pages", ["parent_id"], :name => "index_wiki_pages_on_parent_id" + add_index "wiki_pages", ["wiki_id", "title"], :name => "wiki_pages_wiki_id_title" + add_index "wiki_pages", ["wiki_id"], :name => "index_wiki_pages_on_wiki_id" + + create_table "wiki_redirects", :force => true do |t| + t.integer "wiki_id", :null => false + t.string "title" + t.string "redirects_to" + t.datetime "created_on", :null => false + end + + add_index "wiki_redirects", ["wiki_id", "title"], :name => "wiki_redirects_wiki_id_title" + add_index "wiki_redirects", ["wiki_id"], :name => "index_wiki_redirects_on_wiki_id" + + create_table "wikis", :force => true do |t| + t.integer "project_id", :null => false + t.string "start_page", :null => false + t.integer "status", :default => 1, :null => false + end + + add_index "wikis", ["project_id"], :name => "wikis_project_id" + + create_table "workflows", :force => true do |t| + t.integer "tracker_id", :default => 0, :null => false + t.integer "old_status_id", :default => 0, :null => false + t.integer "new_status_id", :default => 0, :null => false + t.integer "role_id", :default => 0, :null => false + t.boolean "assignee", :default => false, :null => false + t.boolean "author", :default => false, :null => false + t.string "type", :limit => 30 + t.string "field_name", :limit => 30 + t.string "rule", :limit => 30 + end + + add_index "workflows", ["new_status_id"], :name => "index_workflows_on_new_status_id" + add_index "workflows", ["old_status_id"], :name => "index_workflows_on_old_status_id" + add_index "workflows", ["role_id", "tracker_id", "old_status_id"], :name => "wkfs_role_tracker_old_status" + add_index "workflows", ["role_id"], :name => "index_workflows_on_role_id" + + create_table "works_categories", :force => true do |t| + t.string "category" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "zip_packs", :force => true do |t| + t.integer "user_id" + t.integer "homework_id" + t.string "file_digest" + t.string "file_path" + t.integer "pack_times", :default => 1 + t.integer "pack_size", :default => 0 + t.text "file_digests" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + +end From 54078e114c00c4a5a1d2f867d673c9a97e79a94d Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Mon, 4 May 2015 15:20:40 +0800 Subject: [PATCH 02/30] =?UTF-8?q?redis=E7=BC=93=E5=AD=98=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E6=90=AD=E5=BB=BA=E4=BB=A5=E5=8F=8A=E5=AF=B9?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E7=9A=84=E7=BC=93=E5=AD=98=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=20Signed-off-by:=20alan=20<547533434@qq.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 ++ app/controllers/welcome_controller.rb | 2 +- config/additional_environment.rb.example | 10 ---------- config/environments/development.rb | 6 +++--- config/initializers/redis.rb | 1 + db/schema.rb | 17 ----------------- 6 files changed, 7 insertions(+), 31 deletions(-) delete mode 100644 config/additional_environment.rb.example create mode 100644 config/initializers/redis.rb diff --git a/Gemfile b/Gemfile index 13b410d9d..d3fb6de22 100644 --- a/Gemfile +++ b/Gemfile @@ -23,6 +23,8 @@ gem "builder", "3.0.0" gem 'acts-as-taggable-on', '2.4.1' gem 'spreadsheet' gem 'ruby-ole' +gem 'redis' +gem 'redis-store' gem 'rails_kindeditor',path:'lib/rails_kindeditor' group :development do gem 'grape-swagger' diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index f35210f01..df006c9b4 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -19,7 +19,7 @@ class WelcomeController < ApplicationController include ApplicationHelper include WelcomeHelper helper :project_score - caches_action :robots + caches_action :robots, :course, :contest, :index, expires_in: 2.hours, layout: false #before_filter :find_first_page, :only => [:index] # before_filter :fake, :only => [:index, :course] before_filter :entry_select, :only => [:index] diff --git a/config/additional_environment.rb.example b/config/additional_environment.rb.example deleted file mode 100644 index 2a317a396..000000000 --- a/config/additional_environment.rb.example +++ /dev/null @@ -1,10 +0,0 @@ -# Copy this file to additional_environment.rb and add any statements -# that need to be passed to the Rails::Initializer. `config` is -# available in this context. -# -# Example: -# -# config.log_level = :debug -# ... -# - diff --git a/config/environments/development.rb b/config/environments/development.rb index d3843ff68..2aca152cb 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -10,9 +10,9 @@ RedmineApp::Application.configure do config.logger = Logger.new('log/development.log', 'daily') # daily, weekly or monthly # Show full error reports and disable caching config.consider_all_requests_local = true - config.action_controller.perform_caching = false - #config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" - config.cache_store = :dalli_store + config.action_controller.perform_caching = true + config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + #config.cache_store = :dalli_store # Don't care if the mailer can't send config.action_mailer.raise_delivery_errors = true diff --git a/config/initializers/redis.rb b/config/initializers/redis.rb new file mode 100644 index 000000000..4aa95a27b --- /dev/null +++ b/config/initializers/redis.rb @@ -0,0 +1 @@ +$redis = Redis.new(:host => "127.0.0.1", :port => 6379) \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 7fb01a8aa..95766c5c2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -438,13 +438,6 @@ ActiveRecord::Schema.define(:version => 20150428021035) do add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" - create_table "discuss_demos", :force => true do |t| - t.string "title" - t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - create_table "documents", :force => true do |t| t.integer "project_id", :default => 0, :null => false t.integer "category_id", :default => 0, :null => false @@ -654,16 +647,6 @@ ActiveRecord::Schema.define(:version => 20150428021035) do add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" - create_table "journal_details_copy", :force => true do |t| - t.integer "journal_id", :default => 0, :null => false - t.string "property", :limit => 30, :default => "", :null => false - t.string "prop_key", :limit => 30, :default => "", :null => false - t.text "old_value" - t.text "value" - end - - add_index "journal_details_copy", ["journal_id"], :name => "journal_details_journal_id" - create_table "journal_replies", :id => false, :force => true do |t| t.integer "journal_id" t.integer "user_id" From 14a4cfa0dbaea916bf8ac4ddde031de57367127b Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Mon, 4 May 2015 16:25:00 +0800 Subject: [PATCH 03/30] Signed-off-by: alan <547533434@qq.com> --- config/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/application.rb b/config/application.rb index 4a0e56115..9e7a2ba81 100644 --- a/config/application.rb +++ b/config/application.rb @@ -31,7 +31,7 @@ module RedmineApp end # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) - + config.autoload_paths += %w(#{RAILS_ROOT}/app/sweepers) # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. # config.plugins = [ :exception_notification, :ssl_requirement, :all ] From 34893db4650b371ee0436471fedbe2f3e83d0942 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Mon, 18 May 2015 14:53:01 +0800 Subject: [PATCH 04/30] Signed-off-by: alan <547533434@qq.com> --- Gemfile | 2 +- app/views/boards/_form_project.html.erb | 52 ++++++++++++++++++++++++- app/views/boards/_project_show.html.erb | 4 +- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index fbe74f8dd..9642e320c 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'acts-as-taggable-on', '2.4.1' gem 'spreadsheet' gem 'ruby-ole' gem 'rails_kindeditor',path:'lib/rails_kindeditor' -gem "rmagick", ">= 2.0.0" +#gem "rmagick", ">= 2.0.0" group :development do gem 'grape-swagger' diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb index 8288debe2..69f8d7b2c 100644 --- a/app/views/boards/_form_project.html.erb +++ b/app/views/boards/_form_project.html.erb @@ -1,3 +1,16 @@ +<%= javascript_include_tag "/assets/kindeditor/kindeditor" %> + <%= error_messages_for 'message' %> <% replying ||= false %> <% extra_option = replying ? { readonly: true} : { maxlength: 200 } %> @@ -35,15 +48,50 @@
  • + <% unless replying %> <% end %> <%= text_area :quote,:quote,:style => 'display:none' %> +
    <% if replying%> - <%= f.text_area :content, :class => 'talk_text fl', :id => "message_content#{f.object.id}", :onkeyup => "regexContent('#{f.object.id}');", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)", :style=>"width: 575px;" %> + + <%= f.kindeditor :content, :editor_id => 'message_content_editor', + :width => '89%', + :height => 300, + :input_html => { :id => "message_content#{f.object.id}", + :onkeyup => "regexContent('#{f.object.id}');", + :class => 'talk_text fl', + :placeholder => "最多3000个汉字(或6000个英文字符)", + :maxlength => 5000 }%> + <% else %> - <%= f.text_area :content, :class => 'talk_text fl', :id => "message_content#{f.object.id}", :onkeyup => "regexContent('#{f.object.id}');", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)" %> + <%= f.kindeditor :content, :editor_id => 'message_content_editor', + :owner_id => @message.nil? ? 0: @message.id, + :owner_type => OwnerTypeHelper::MESSAGE, + :width => '90%', + :height => 300, + :class => 'talk_text fl', + :input_html => { :id => "message_content#{f.object.id}", + :onkeyup => "regexContent('#{f.object.id}');", + :class => 'talk_text fl', + :placeholder => "最多3000个汉字(或6000个英文字符)", + :maxlength => 5000 }%> + <% end %> +

  • diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index 63bb66a6a..db66b1a7e 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -112,11 +112,11 @@ <% end %> <% replies_all = topic.children. includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.created_on DESC").offset(2). + reorder("#{Message.table_name}.id asc").offset(2). all %> <% replies_show = topic.children. includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.created_on DESC").limit(2). + reorder("#{Message.table_name}.id asc").limit(2). all %> <% unless replies_show.empty? %> <% reply_count = 0 %> From 052868a6b404d680413579990953f0474948d891 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Tue, 19 May 2015 14:26:42 +0800 Subject: [PATCH 05/30] Signed-off-by: alan <547533434@qq.com> --- app/views/boards/_form_project.html.erb | 24 +-- public/assets/kindeditor/kindeditor-min.js | 182 +++++++++++++++++++++ public/javascripts/project.js | 4 +- 3 files changed, 198 insertions(+), 12 deletions(-) create mode 100644 public/assets/kindeditor/kindeditor-min.js diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb index 69f8d7b2c..4d38ca275 100644 --- a/app/views/boards/_form_project.html.erb +++ b/app/views/boards/_form_project.html.erb @@ -1,4 +1,4 @@ -<%= javascript_include_tag "/assets/kindeditor/kindeditor" %> +<%= javascript_include_tag "/assets/kindeditor/kindeditor-min" %> "];Z(c)||(c=[c]);m(c,function(a,b){b&&e.push('')});d&&e.push("");e.push("");return e.join("\n")}function pa(a,b){if(a.hasVal()){if(b===i){var c=a.val();return c=c.replace(/(<(?:p|p\s[^>]*)>) *(<\/p>)/ig,"")}return a.val(b)}return a.html(b)}function qa(a){this.init(a)}function Ab(a){return new qa(a)}function Bb(a,b){var c=this.get(a);c&&!c.hasClass("ke-disabled")&&b(c)}function Da(a){this.init(a)}function Cb(a){return new Da(a)}function ra(a){this.init(a)}function $a(a){return new ra(a)}function sa(a){this.init(a)}function Db(a){return new sa(a)} +function ab(a){this.init(a)}function ta(a){this.init(a)}function Eb(a){return new ta(a)}function bb(a,b){var c=document.getElementsByTagName("head")[0]||(P?document.body:document.documentElement),d=document.createElement("script");c.appendChild(d);d.src=a;d.charset="utf-8";d.onload=d.onreadystatechange=function(){if(!this.readyState||this.readyState==="loaded")b&&b(),d.onload=d.onreadystatechange=null,c.removeChild(d)}}function Fb(a){var b=a.indexOf("?");return b>0?a.substr(0,b):a}function cb(a){for(var b= +document.getElementsByTagName("head")[0]||(P?document.body:document.documentElement),c=document.createElement("link"),d=Fb(ia(a,"absolute")),e=f('link[rel="stylesheet"]',b),g=0,h=e.length;gc))c=this.width});d.length>0&&d[0].title=="-";)d.shift();for(;d.length>0&&d[d.length-1].title=="-";)d.pop();var e=null;m(d,function(a){this.title=="-"&&e.title=="-"&&delete d[a];e=this});if(d.length>0){b.preventDefault();var g=f(a.edit.iframe).pos(),h=$a({x:g.x+b.clientX,y:g.y+b.clientY,width:c,css:{visibility:"hidden"},shadowMode:a.shadowMode});m(d,function(){this.title&& +h.addItem(this)});var g=G(h.doc),j=h.div.height();b.clientY+j>=g.clientHeight-100&&h.pos(h.x,t(h.y)-j);h.div.css("visibility","visible");a.menu=h}}}else b.preventDefault()})}function bc(){function a(a){for(a=f(a.commonAncestor());a;){if(a.type==1&&!a.isStyle())break;a=a.parent()}return a.name}var b=this,c=b.edit.doc,d=b.newlineTag;if(!(o&&d!=="br")&&(!Y||!(A<3&&d!=="p"))&&!(Pa&&A<9)){var e=u("h1,h2,h3,h4,h5,h6,pre,li"),g=u("p,h1,h2,h3,h4,h5,h6,pre,li,blockquote");f(c).keydown(function(f){if(!(f.which!= +13||f.shiftKey||f.ctrlKey||f.altKey)){b.cmd.selection();var j=a(b.cmd.range);j=="marquee"||j=="select"||(d==="br"&&!e[j]?(f.preventDefault(),b.insertHtml("
    "+(o&&A<9?"":"\u200b"))):g[j]||Q(c,"formatblock","

    "))}});f(c).keyup(function(e){if(!(e.which!=13||e.shiftKey||e.ctrlKey||e.altKey)&&d!="br")if(Y){var e=b.cmd.commonAncestor("p"),j=b.cmd.commonAncestor("a");j&&j.text()==""&&(j.remove(!0),b.cmd.range.selectNodeContents(e[0]).collapse(!0),b.cmd.select())}else if(b.cmd.selection(),e=a(b.cmd.range), +!(e=="marquee"||e=="select"))if(g[e]||Q(c,"formatblock","

    "),e=b.cmd.commonAncestor("div")){for(var j=f("

    "),k=e[0].firstChild;k;){var n=k.nextSibling;j.append(k);k=n}e.before(j);e.remove();b.cmd.range.selectNodeContents(j[0]);b.cmd.select()}})}}function cc(){var a=this,b=a.edit.doc;f(b).keydown(function(c){if(c.which==9)if(c.preventDefault(),a.afterTab)a.afterTab.call(a,c);else{var c=a.cmd,d=c.range;d.shrink();d.collapsed&&d.startContainer.nodeType==1&&(d.insertNode(f("@ ",b)[0]),c.select()); +a.insertHtml("    ")}})}function dc(){var a=this;f(a.edit.textarea[0],a.edit.win).focus(function(b){a.afterFocus&&a.afterFocus.call(a,b)}).blur(function(b){a.afterBlur&&a.afterBlur.call(a,b)})}function T(a){return B(a.replace(/]*id="?__kindeditor_bookmark_\w+_\d+__"?[^>]*><\/span>/ig,""))}function Fa(a){return a.replace(/]+class="?__kindeditor_paste__"?[^>]*>[\s\S]*?<\/div>/ig,"")}function Jb(a,b){if(a.length===0)a.push(b);else{var c=a[a.length-1];T(b.html)!==T(c.html)&& +a.push(b)}}function Kb(a,b){var c=this.edit,d=c.doc.body,e,g;if(a.length===0)return this;c.designMode?(e=this.cmd.range,g=e.createBookmark(!0),g.html=d.innerHTML):g={html:d.innerHTML};Jb(b,g);var h=a.pop();T(g.html)===T(h.html)&&a.length>0&&(h=a.pop());c.designMode?(c.html(h.html),h.start&&(e.moveToBookmark(h),this.select())):f(d).html(T(h.html));return this}function ua(a){function b(a,b){ua.prototype[a]===i&&(c[a]=b);c.options[a]=b}var c=this;c.options={};m(a,function(c){b(c,a[c])});m(f.options, +function(a,d){c[a]===i&&b(a,d)});var d=f(c.srcElement||"').css("width","100%");c.tabIndex=isNaN(parseInt(a.tabIndex,10))?c.srcElement.attr("tabindex"):parseInt(a.tabIndex,10);c.iframe.attr("tabindex",c.tabIndex);c.textarea.attr("tabindex",c.tabIndex);c.width&&c.setWidth(c.width);c.height&&c.setHeight(c.height);c.designMode?c.textarea.hide():c.iframe.hide(); +j&&c.iframe.bind("load",function(){c.iframe.unbind("load");o?b():setTimeout(b,0)});c.div.append(c.iframe);c.div.append(c.textarea);c.srcElement.hide();!j&&b()},setWidth:function(a){this.width=a=s(a);this.div.css("width",a);return this},setHeight:function(a){this.height=a=s(a);this.div.css("height",a);this.iframe.css("height",a);if(o&&A<8||P)a=s(t(a)-2);this.textarea.css("height",a);return this},remove:function(){var a=this.doc;f(a.body).unbind();f(a).unbind();f(this.win).unbind();this._mousedownHandler&& +f(document).unbind("mousedown",this._mousedownHandler);pa(this.srcElement,this.html());this.srcElement.show();a.write("");this.iframe.unbind();this.textarea.unbind();qa.parent.remove.call(this)},html:function(a,b){var c=this.doc;if(this.designMode){c=c.body;if(a===i)return a=b?""+c.parentNode.innerHTML+"":c.innerHTML,this.beforeGetHtml&&(a=this.beforeGetHtml(a)),Y&&a=="
    "&&(a=""),a;this.beforeSetHtml&&(a=this.beforeSetHtml(a));o&&A>=9&&(a=a.replace(/(<.*?checked=")checked(".*>)/ig, +"$1$2"));f(c).html(a);this.afterSetHtml&&this.afterSetHtml();return this}if(a===i)return this.textarea.val();this.textarea.val(a);return this},design:function(a){if(a===i?!this.designMode:a){if(!this.designMode)a=this.html(),this.designMode=!0,this.html(a),this.textarea.hide(),this.iframe.show()}else if(this.designMode)a=this.html(),this.designMode=!1,this.html(a),this.iframe.hide(),this.textarea.show();return this.focus()},focus:function(){this.designMode?this.win.focus():this.textarea[0].focus(); +return this},blur:function(){if(o){var a=f('',this.div);this.div.append(a);a[0].focus();a.remove()}else this.designMode?this.win.blur():this.textarea[0].blur();return this},afterChange:function(a){function b(b){setTimeout(function(){a(b)},1)}var c=this.doc,d=c.body;f(c).keyup(function(b){!b.ctrlKey&&!b.altKey&&db[b.which]&&a(b)});f(c).mouseup(a).contextmenu(a);f(this.win).blur(a);f(d).bind("paste",b);f(d).bind("cut", +b);return this}});f.EditClass=qa;f.edit=Ab;f.iframeDoc=Xa;E(Da,S,{init:function(a){function b(a){a=f(a);if(a.hasClass("ke-outline"))return a;if(a.hasClass("ke-toolbar-icon"))return a.parent()}function c(a,c){var d=b(a.target);if(d&&!d.hasClass("ke-disabled")&&!d.hasClass("ke-selected"))d[c]("ke-on")}var d=this;Da.parent.init.call(d,a);d.disableMode=l(a.disableMode,!1);d.noDisableItemMap=u(l(a.noDisableItems,[]));d._itemMap={};d.div.addClass("ke-toolbar").bind("contextmenu,mousedown,mousemove",function(a){a.preventDefault()}).attr("unselectable", +"on");d.div.mouseover(function(a){c(a,"addClass")}).mouseout(function(a){c(a,"removeClass")}).click(function(a){var c=b(a.target);c&&!c.hasClass("ke-disabled")&&d.options.click.call(this,a,c.attr("data-name"))})},get:function(a){if(this._itemMap[a])return this._itemMap[a];return this._itemMap[a]=f("span.ke-icon-"+a,this.div).parent()},select:function(a){Bb.call(this,a,function(a){a.addClass("ke-selected")});return self},unselect:function(a){Bb.call(this,a,function(a){a.removeClass("ke-selected").removeClass("ke-on")}); +return self},enable:function(a){if(a=a.get?a:this.get(a))a.removeClass("ke-disabled"),a.opacity(1);return this},disable:function(a){if(a=a.get?a:this.get(a))a.removeClass("ke-selected").addClass("ke-disabled"),a.opacity(0.5);return this},disableAll:function(a,b){var c=this,d=c.noDisableItemMap;b&&(d=u(b));(a===i?!c.disableMode:a)?(f("span.ke-outline",c.div).each(function(){var a=f(this),b=a[0].getAttribute("data-name",2);d[b]||c.disable(a)}),c.disableMode=!0):(f("span.ke-outline",c.div).each(function(){var a= +f(this),b=a[0].getAttribute("data-name",2);d[b]||c.enable(a)}),c.disableMode=!1);return c}});f.ToolbarClass=Da;f.toolbar=Cb;E(ra,S,{init:function(a){a.z=a.z||811213;ra.parent.init.call(this,a);this.centerLineMode=l(a.centerLineMode,!0);this.div.addClass("ke-menu").bind("click,mousedown",function(a){a.stopPropagation()}).attr("unselectable","on")},addItem:function(a){if(a.title==="-")this.div.append(f('
    '));else{var b=f('
    '), +c=f('
    '),d=f('
    '),e=s(a.height),g=l(a.iconClass,"");this.div.append(b);e&&(b.css("height",e),d.css("line-height",e));var h;this.centerLineMode&&(h=f('
    '),e&&h.css("height",e));b.mouseover(function(){f(this).addClass("ke-menu-item-on");h&&h.addClass("ke-menu-item-center-on")}).mouseout(function(){f(this).removeClass("ke-menu-item-on");h&&h.removeClass("ke-menu-item-center-on")}).click(function(b){a.click.call(f(this)); +b.stopPropagation()}).append(c);h&&b.append(h);b.append(d);a.checked&&(g="ke-icon-checked");g!==""&&c.html('');d.html(a.title);return this}},remove:function(){this.options.beforeRemove&&this.options.beforeRemove.call(this);f(".ke-menu-item",this.div[0]).unbind();ra.parent.remove.call(this);return this}});f.MenuClass=ra;f.menu=$a;E(sa,S,{init:function(a){a.z=a.z||811213;sa.parent.init.call(this,a);var b=a.colors||[["#E53333", +"#E56600","#FF9900","#64451D","#DFC5A4","#FFE500"],["#009900","#006600","#99BB00","#B8D100","#60D978","#00D5FF"],["#337FE5","#003399","#4C33E5","#9933E5","#CC33E5","#EE33EE"],["#FFFFFF","#CCCCCC","#999999","#666666","#333333","#000000"]];this.selectedColor=(a.selectedColor||"").toLowerCase();this._cells=[];this.div.addClass("ke-colorpicker").bind("click,mousedown",function(a){a.stopPropagation()}).attr("unselectable","on");a=this.doc.createElement("table");this.div.append(a);a.className="ke-colorpicker-table"; +a.cellPadding=0;a.cellSpacing=0;a.border=0;var c=a.insertRow(0),d=c.insertCell(0);d.colSpan=b[0].length;this._addAttr(d,"","ke-colorpicker-cell-top");for(var e=0;e').css("background-color",b)):a.html(d.options.noColor);f(a).attr("unselectable","on");d._cells.push(a)},remove:function(){m(this._cells,function(){this.unbind()});sa.parent.remove.call(this);return this}});f.ColorPickerClass=sa;f.colorpicker=Db;E(ab,{init:function(a){var b=f(a.button),c=a.fieldName|| +"file",d=a.url||"",e=b.val(),g=a.extraParams||{},h=b[0].className||"",j=a.target||"kindeditor_upload_iframe_"+(new Date).getTime();a.afterError=a.afterError||function(a){alert(a)};var k=[],i;for(i in g)k.push('');c=['
    ',a.target?"":'',a.form?'
    ':'
    ','',k.join(""),'',"",'',a.form?"
    ":"","
    "].join("");c=f(c,b.doc);b.hide();b.before(c);this.div=c;this.button=b;this.iframe=a.target?f('iframe[name="'+j+'"]'):f("iframe",c);this.form=a.form?f(a.form):f("form",c);this.fileBox=f(".ke-upload-file",c);b=a.width||f(".ke-button-common",c).width(); +f(".ke-upload-area",c).width(b);this.options=a},submit:function(){var a=this,b=a.iframe;b.bind("load",function(){b.unbind();var c=document.createElement("form");a.fileBox.before(c);f(c).append(a.fileBox);c.reset();f(c).remove(!0);var c=f.iframeDoc(b),d=c.getElementsByTagName("pre")[0],e="",g,e=d?d.innerHTML:c.body.innerHTML,e=fa(e);b[0].src="javascript:false";try{g=f.json(e)}catch(h){a.options.afterError.call(a,""+c.body.parentNode.innerHTML+"")}g&&a.options.afterUpload.call(a, +g)});a.form[0].submit();return a},remove:function(){this.fileBox&&this.fileBox.unbind();this.iframe.remove();this.div.remove();this.button.show();return this}});f.UploadButtonClass=ab;f.uploadbutton=function(a){return new ab(a)};E(ta,S,{init:function(a){var b=l(a.shadowMode,!0);a.z=a.z||811213;a.shadowMode=!1;a.autoScroll=l(a.autoScroll,!0);ta.parent.init.call(this,a);var c=a.title,d=f(a.body,this.doc),e=a.previewBtn,g=a.yesBtn,h=a.noBtn,j=a.closeBtn,k=l(a.showMask,!0);this.div.addClass("ke-dialog").bind("click,mousedown", +function(a){a.stopPropagation()});var i=f('
    ').appendTo(this.div);o&&A<7?this.iframeMask=f('').appendTo(this.div):b&&f('
    ').appendTo(this.div);b=f('
    ');i.append(b);b.html(c);this.closeIcon=f('').click(j.click);b.append(this.closeIcon);this.draggable({clickEl:b,beforeDrag:a.beforeDrag}); +a=f('
    ');i.append(a);a.append(d);var q=f('');(e||g||h)&&i.append(q);m([{btn:e,name:"preview"},{btn:g,name:"yes"},{btn:h,name:"no"}],function(){if(this.btn){var a=this.btn,a=a||{},b=a.name||"",c=f(''),b=f('');a.click&&b.click(a.click);c.append(b);c.addClass("ke-dialog-"+this.name);q.append(c)}}); +this.height&&a.height(t(this.height)-b.height()-q.height());this.div.width(this.div.width());this.div.height(this.div.height());this.mask=null;if(k)d=G(this.doc),this.mask=Ya({x:0,y:0,z:this.z-1,cls:"ke-dialog-mask",width:Math.max(d.scrollWidth,d.clientWidth),height:Math.max(d.scrollHeight,d.clientHeight)});this.autoPos(this.div.width(),this.div.height());this.footerDiv=q;this.bodyDiv=a;this.headerDiv=b;this.isLoading=!1},setMaskIndex:function(a){this.mask.div.css("z-index",a)},showLoading:function(a){var a= +l(a,""),b=this.bodyDiv;this.loading=f('
    '+a+"
    ").width(b.width()).height(b.height()).css("top",this.headerDiv.height()+"px");b.css("visibility","hidden").after(this.loading);this.isLoading=!0;return this},hideLoading:function(){this.loading&&this.loading.remove();this.bodyDiv.css("visibility","visible");this.isLoading=!1;return this},remove:function(){this.options.beforeRemove&& +this.options.beforeRemove.call(this);this.mask&&this.mask.remove();this.iframeMask&&this.iframeMask.remove();this.closeIcon.unbind();f("input",this.div).unbind();f("button",this.div).unbind();this.footerDiv.unbind();this.bodyDiv.unbind();this.headerDiv.unbind();f("iframe",this.div).each(function(){f(this).remove()});ta.parent.remove.call(this);return this}});f.DialogClass=ta;f.dialog=Eb;f.tabs=function(a){var b=Ya(a),c=b.remove,d=a.afterSelect,a=b.div,e=[];a.addClass("ke-tabs").bind("contextmenu,mousedown,mousemove", +function(a){a.preventDefault()});var g=f('
      ');a.append(g);b.add=function(a){var b=f('
    • '+a.title+"
    • ");b.data("tab",a);e.push(b);g.append(b)};b.selectedIndex=0;b.select=function(a){b.selectedIndex=a;m(e,function(c,d){d.unbind();c===a?(d.addClass("ke-tabs-li-selected"),f(d.data("tab").panel).show("")):(d.removeClass("ke-tabs-li-selected").removeClass("ke-tabs-li-on").mouseover(function(){f(this).addClass("ke-tabs-li-on")}).mouseout(function(){f(this).removeClass("ke-tabs-li-on")}).click(function(){b.select(c)}), +f(d.data("tab").panel).hide())});d&&d.call(b,a)};b.remove=function(){m(e,function(){this.remove()});g.remove();c.call(b)};return b};f.loadScript=bb;f.loadStyle=cb;f.ajax=function(a,b,c,d,e){var c=c||"GET",e=e||"json",g=w.XMLHttpRequest?new w.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");g.open(c,a,!0);g.onreadystatechange=function(){if(g.readyState==4&&g.status==200&&b){var a=B(g.responseText);e=="json"&&(a=eb(a));b(a)}};if(c=="POST"){var f=[];m(d,function(a,b){f.push(encodeURIComponent(a)+ +"="+encodeURIComponent(b))});try{g.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}catch(j){}g.send(f.join("&"))}else g.send(null)};var N={},O={};ua.prototype={lang:function(a){return Ib(a,this.langType)},loadPlugin:function(a,b){var c=this;if(N[a]){if(!wa(N[a]))return setTimeout(function(){c.loadPlugin(a,b)},100),c;N[a].call(c,KindEditor);b&&b.call(c);return c}N[a]="loading";bb(c.pluginsPath+a+"/"+a+".js?ver="+encodeURIComponent(f.DEBUG?Ga:Ha),function(){setTimeout(function(){N[a]&& +c.loadPlugin(a,b)},0)});return c},handler:function(a,b){var c=this;c._handlers[a]||(c._handlers[a]=[]);if(wa(b))return c._handlers[a].push(b),c;m(c._handlers[a],function(){b=this.call(c,b)});return b},clickToolbar:function(a,b){var c=this,d="clickToolbar"+a;if(b===i){if(c._handlers[d])return c.handler(d);c.loadPlugin(a,function(){c.handler(d)});return c}return c.handler(d,b)},updateState:function(){var a=this;m("justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,insertunorderedlist,subscript,superscript,bold,italic,underline,strikethrough".split(","), +function(b,c){a.cmd.state(c)?a.toolbar.select(c):a.toolbar.unselect(c)});return a},addContextmenu:function(a){this._contextmenus.push(a);return this},afterCreate:function(a){return this.handler("afterCreate",a)},beforeRemove:function(a){return this.handler("beforeRemove",a)},beforeGetHtml:function(a){return this.handler("beforeGetHtml",a)},beforeSetHtml:function(a){return this.handler("beforeSetHtml",a)},afterSetHtml:function(a){return this.handler("afterSetHtml",a)},create:function(){function a(){k.height()=== +0?setTimeout(a,100):b.resize(d,e,!1)}var b=this,c=b.fullscreenMode;if(b.isCreated)return b;if(b.srcElement.data("kindeditor"))return b;b.srcElement.data("kindeditor","true");c?G().style.overflow="hidden":G().style.overflow="";var d=c?G().clientWidth+"px":b.width,e=c?G().clientHeight+"px":b.height;if(o&&A<8||P)e=s(t(e)+2);var g=b.container=f(b.layout);c?f(document.body).append(g):b.srcElement.before(g);var h=f(".toolbar",g),j=f(".edit",g),k=b.statusbar=f(".statusbar",g);g.removeClass("container").addClass("ke-container ke-container-"+ +b.themeType).css("width",d);if(c){g.css({position:"absolute",left:0,top:0,"z-index":811211});if(!Y)b._scrollPos=ca();w.scrollTo(0,0);f(document.body).css({height:"1px",overflow:"hidden"});f(document.body.parentNode).css("overflow","hidden");b._fullscreenExecuted=!0}else b._fullscreenExecuted&&(f(document.body).css({height:"",overflow:""}),f(document.body.parentNode).css("overflow","")),b._scrollPos&&w.scrollTo(b._scrollPos.x,b._scrollPos.y);var i=[];f.each(b.items,function(a,c){c=="|"?i.push(''): +c=="/"?i.push('
      '):(i.push(''),i.push(''))});var h=b.toolbar=Cb({src:h,html:i.join(""),noDisableItems:b.noDisableItems,click:function(a,c){a.stop();if(b.menu){var d=b.menu.name;b.hideMenu();if(d===c)return}b.clickToolbar(c)}}),l=t(e)-h.div.height(),m=b.edit=Ab({height:l>0&&t(e)>b.minHeight?l:b.minHeight, +src:j,srcElement:b.srcElement,designMode:b.designMode,themesPath:b.themesPath,bodyClass:b.bodyClass,cssPath:b.cssPath,cssData:b.cssData,beforeGetHtml:function(a){a=b.beforeGetHtml(a);a=T(Fa(a));return U(a,b.filterMode?b.htmlTags:null,b.urlType,b.wellFormatMode,b.indentChar)},beforeSetHtml:function(a){a=U(a,b.filterMode?b.htmlTags:null,"",!1);return b.beforeSetHtml(a)},afterSetHtml:function(){b.edit=m=this;b.afterSetHtml()},afterCreate:function(){b.edit=m=this;b.cmd=m.cmd;b._docMousedownFn=function(){b.menu&& +b.hideMenu()};f(m.doc,document).mousedown(b._docMousedownFn);ac.call(b);bc.call(b);cc.call(b);dc.call(b);m.afterChange(function(){m.designMode&&(b.updateState(),b.addBookmark(),b.options.afterChange&&b.options.afterChange.call(b))});m.textarea.keyup(function(a){!a.ctrlKey&&!a.altKey&&Ob[a.which]&&b.options.afterChange&&b.options.afterChange.call(b)});b.readonlyMode&&b.readonly();b.isCreated=!0;if(b.initContent==="")b.initContent=b.html();if(b._undoStack.length>0){var a=b._undoStack.pop();a.start&& +(b.html(a.html),m.cmd.range.moveToBookmark(a),b.select())}b.afterCreate();b.options.afterCreate&&b.options.afterCreate.call(b)}});k.removeClass("statusbar").addClass("ke-statusbar").append('').append('');if(b._fullscreenResizeHandler)f(w).unbind("resize",b._fullscreenResizeHandler),b._fullscreenResizeHandler=null;a();c?(b._fullscreenResizeHandler=function(){b.isCreated&&b.resize(G().clientWidth, +G().clientHeight,!1)},f(w).bind("resize",b._fullscreenResizeHandler),h.select("fullscreen"),k.first().css("visibility","hidden"),k.last().css("visibility","hidden")):(Y&&f(w).bind("scroll",function(){b._scrollPos=ca()}),b.resizeType>0?Wa({moveEl:g,clickEl:k,moveFn:function(a,c,d,e,g,f){e+=f;b.resize(null,e)}}):k.first().css("visibility","hidden"),b.resizeType===2?Wa({moveEl:g,clickEl:k.last(),moveFn:function(a,c,d,e,g,f){d+=g;e+=f;b.resize(d,e)}}):k.last().css("visibility","hidden"));return b},remove:function(){var a= +this;if(!a.isCreated)return a;a.beforeRemove();a.srcElement.data("kindeditor","");a.menu&&a.hideMenu();m(a.dialogs,function(){a.hideDialog()});f(document).unbind("mousedown",a._docMousedownFn);a.toolbar.remove();a.edit.remove();a.statusbar.last().unbind();a.statusbar.unbind();a.container.remove();a.container=a.toolbar=a.edit=a.menu=null;a.dialogs=[];a.isCreated=!1;return a},resize:function(a,b,c){c=l(c,!0);if(a&&(/%/.test(a)||(a=t(a),a=a/ig,"").replace(/ /ig," ")):this.html(C(a))},isEmpty:function(){return B(this.text().replace(/\r\n|\n|\r/,""))===""},isDirty:function(){return B(this.initContent.replace(/\r\n|\n|\r|t/g,""))!==B(this.html().replace(/\r\n|\n|\r|t/g,""))},selectedHtml:function(){var a=this.isCreated?this.cmd.range.html():"";return a=T(Fa(a))},count:function(a){a=(a||"html").toLowerCase();if(a==="html")return this.html().length; +if(a==="text")return this.text().replace(/<(?:img|embed).*?>/ig,"K").replace(/\r\n|\n|\r/g,"").length;return 0},exec:function(a){var a=a.toLowerCase(),b=this.cmd,c=J(a,"selectall,copy,paste,print".split(","))<0;c&&this.addBookmark(!1);b[a].apply(b,Ja(arguments,1));c&&(this.updateState(),this.addBookmark(!1),this.options.afterChange&&this.options.afterChange.call(this));return this},insertHtml:function(a,b){if(!this.isCreated)return this;a=this.beforeSetHtml(a);this.exec("inserthtml",a,b);return this}, +appendHtml:function(a){this.html(this.html()+a);if(this.isCreated)a=this.cmd,a.range.selectNodeContents(a.doc.body).collapse(!1),a.select();return this},sync:function(){pa(this.srcElement,this.html());return this},focus:function(){this.isCreated?this.edit.focus():this.srcElement[0].focus();return this},blur:function(){this.isCreated?this.edit.blur():this.srcElement[0].blur();return this},addBookmark:function(a){var a=l(a,!0),b=this.edit,c=b.doc.body,d=Fa(c.innerHTML);if(a&&this._undoStack.length> +0&&Math.abs(d.length-T(this._undoStack[this._undoStack.length-1].html).length)0){var c=b.dialogs[b.dialogs.length-1];b.dialogs[0].setMaskIndex(c.z+2);a.z=c.z+3;a.showMask=!1}a=Eb(a);b.dialogs.push(a);return a},hideDialog:function(){this.dialogs.length>0&&this.dialogs.pop().remove();this.dialogs.length>0&&this.dialogs[0].setMaskIndex(this.dialogs[this.dialogs.length- +1].z-1);return this},errorDialog:function(a){var b=this.createDialog({width:750,title:this.lang("uploadError"),body:'
      '}),b=f("iframe",b.div),c=f.iframeDoc(b);c.open();c.write(a);c.close();f(c.body).css("background-color","#FFF");b[0].contentWindow.focus();return this}};_instances=[];f.remove=function(a){va(a,function(a){this.remove();_instances.splice(a,1)})};f.sync=function(a){va(a,function(){this.sync()})}; +f.html=function(a,b){va(a,function(){this.html(b)})};f.insertHtml=function(a,b){va(a,function(){this.insertHtml(b)})};f.appendHtml=function(a,b){va(a,function(){this.appendHtml(b)})};o&&A<7&&Q(document,"BackgroundImageCache",!0);f.EditorClass=ua;f.editor=function(a){return new ua(a)};f.create=Lb;f.instances=_instances;f.plugin=Gb;f.lang=Ib;Gb("core",function(a){var b=this,c={undo:"Z",redo:"Y",bold:"B",italic:"I",underline:"U",print:"P",selectall:"A"};b.afterSetHtml(function(){b.options.afterChange&& +b.options.afterChange.call(b)});b.afterCreate(function(){if(b.syncType=="form"){for(var c=a(b.srcElement),d=!1;c=c.parent();)if(c.name=="form"){d=!0;break}if(d){c.bind("submit",function(){b.sync();a(w).bind("unload",function(){b.edit.textarea.remove()})});var f=a('[type="reset"]',c);f.click(function(){b.html(b.initContent);b.cmd.selection()});b.beforeRemove(function(){c.unbind();f.unbind()})}}});b.clickToolbar("source",function(){b.edit.designMode?(b.toolbar.disableAll(!0),b.edit.design(!1),b.toolbar.select("source")): +(b.toolbar.disableAll(!1),b.edit.design(!0),b.toolbar.unselect("source"),Y?setTimeout(function(){b.cmd.selection()},0):b.cmd.selection());b.designMode=b.edit.designMode});b.afterCreate(function(){b.designMode||b.toolbar.disableAll(!0).select("source")});b.clickToolbar("fullscreen",function(){b.fullscreen()});if(b.fullscreenShortcut){var d=!1;b.afterCreate(function(){a(b.edit.doc,b.edit.textarea).keyup(function(a){a.which==27&&setTimeout(function(){b.fullscreen()},0)});if(d){if(o&&!b.designMode)return; +b.focus()}d||(d=!0)})}m("undo,redo".split(","),function(a,d){c[d]&&b.afterCreate(function(){Ka(this.edit.doc,c[d],function(){b.clickToolbar(d)})});b.clickToolbar(d,function(){b[d]()})});b.clickToolbar("formatblock",function(){var a=b.lang("formatblock.formatBlock"),c={h1:28,h2:24,h3:18,H4:14,p:12},d=b.cmd.val("formatblock"),f=b.createMenu({name:"formatblock",width:b.langType=="en"?200:150});m(a,function(a,e){var i="font-size:"+c[a]+"px;";a.charAt(0)==="h"&&(i+="font-weight:bold;");f.addItem({title:''+e+"",height:c[a]+12,checked:d===a||d===e,click:function(){b.select().exec("formatblock","<"+a+">").hideMenu()}})})});b.clickToolbar("fontname",function(){var a=b.cmd.val("fontname"),c=b.createMenu({name:"fontname",width:150});m(b.lang("fontname.fontName"),function(d,f){c.addItem({title:''+f+"",checked:a===d.toLowerCase()||a===f.toLowerCase(),click:function(){b.exec("fontname",d).hideMenu()}})})});b.clickToolbar("fontsize", +function(){var a=b.cmd.val("fontsize"),c=b.createMenu({name:"fontsize",width:150});m(b.fontSizeTable,function(d,f){c.addItem({title:''+f+"",height:t(f)+12,checked:a===f,click:function(){b.exec("fontsize",f).hideMenu()}})})});m("forecolor,hilitecolor".split(","),function(a,c){b.clickToolbar(c,function(){b.createMenu({name:c,selectedColor:b.cmd.val(c)||"default",colors:b.colorTable,click:function(a){b.exec(c,a).hideMenu()}})})});m("cut,copy,paste".split(","), +function(a,c){b.clickToolbar(c,function(){b.focus();try{b.exec(c,null)}catch(a){alert(b.lang(c+"Error"))}})});b.clickToolbar("about",function(){var a='
      KindEditor '+Ha+'
      Copyright © kindsoft.net All rights reserved.
      ';b.createDialog({name:"about",width:350,title:b.lang("about"),body:a})});b.plugin.getSelectedLink=function(){return b.cmd.commonAncestor("a")};b.plugin.getSelectedImage=function(){return Ea(b.edit.cmd.range, +function(a){return!/^ke-\w+$/i.test(a[0].className)})};b.plugin.getSelectedFlash=function(){return Ea(b.edit.cmd.range,function(a){return a[0].className=="ke-flash"})};b.plugin.getSelectedMedia=function(){return Ea(b.edit.cmd.range,function(a){return a[0].className=="ke-media"||a[0].className=="ke-rm"})};b.plugin.getSelectedAnchor=function(){return Ea(b.edit.cmd.range,function(a){return a[0].className=="ke-anchor"})};m("link,image,flash,media,anchor".split(","),function(a,c){var d=c.charAt(0).toUpperCase()+ +c.substr(1);m("edit,delete".split(","),function(a,e){b.addContextmenu({title:b.lang(e+d),click:function(){b.loadPlugin(c,function(){b.plugin[c][e]();b.hideMenu()})},cond:b.plugin["getSelected"+d],width:150,iconClass:e=="edit"?"ke-icon-"+c:i})});b.addContextmenu({title:"-"})});b.plugin.getSelectedTable=function(){return b.cmd.commonAncestor("table")};b.plugin.getSelectedRow=function(){return b.cmd.commonAncestor("tr")};b.plugin.getSelectedCell=function(){return b.cmd.commonAncestor("td")};m("prop,cellprop,colinsertleft,colinsertright,rowinsertabove,rowinsertbelow,rowmerge,colmerge,rowsplit,colsplit,coldelete,rowdelete,insert,delete".split(","), +function(a,c){var d=J(c,["prop","delete"])<0?b.plugin.getSelectedCell:b.plugin.getSelectedTable;b.addContextmenu({title:b.lang("table"+c),click:function(){b.loadPlugin("table",function(){b.plugin.table[c]();b.hideMenu()})},cond:d,width:170,iconClass:"ke-icon-table"+c})});b.addContextmenu({title:"-"});m("selectall,justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,insertunorderedlist,indent,outdent,subscript,superscript,hr,print,bold,italic,underline,strikethrough,removeformat,unlink".split(","), +function(a,d){c[d]&&b.afterCreate(function(){Ka(this.edit.doc,c[d],function(){b.cmd.selection();b.clickToolbar(d)})});b.clickToolbar(d,function(){b.focus().exec(d,null)})});b.afterCreate(function(){function c(){f.range.moveToBookmark(j);f.select();X&&(a("div."+l,i).each(function(){a(this).after("
      ").remove(!0)}),a("span.Apple-style-span",i).remove(!0),a("span.Apple-tab-span",i).remove(!0),a("span[style]",i).each(function(){a(this).css("white-space")=="nowrap"&&a(this).remove(!0)}),a("meta",i).remove()); +var d=i[0].innerHTML;i.remove();d!==""&&(X&&(d=d.replace(/(
      )\1/ig,"$1")),b.pasteType===2&&(d=d.replace(/(<(?:p|p\s[^>]*)>) *(<\/p>)/ig,""),/schemas-microsoft-com|worddocument|mso-\w+/i.test(d)?d=nb(d,b.filterMode?b.htmlTags:a.options.htmlTags):(d=U(d,b.filterMode?b.htmlTags:null),d=b.beforeSetHtml(d))),b.pasteType===1&&(d=d.replace(/ /ig," "),d=d.replace(/\n\s*\n/g,"\n"),d=d.replace(/]*>/ig,"\n"),d=d.replace(/<\/p>]*>/ig,"\n"),d=d.replace(/<[^>]+>/g,""),d=d.replace(/ {2}/g,"  "), +b.newlineTag=="p"?/\n/.test(d)&&(d=d.replace(/^/,"

      ").replace(/$/,"

      ").replace(/\n/g,"

      ")):d=d.replace(/\n/g,"
      $&")),b.insertHtml(d,!0))}var d=b.edit.doc,f,j,i,l="__kindeditor_paste__",m=!1;a(d.body).bind("paste",function(p){if(b.pasteType===0)p.stop();else if(!m){m=!0;a("div."+l,d).remove();f=b.cmd.selection();j=f.range.createBookmark();i=a('

      ',d).css({position:"absolute",width:"1px",height:"1px",overflow:"hidden",left:"-1981px",top:a(j.start).pos().y+ +"px","white-space":"nowrap"});a(d.body).append(i);if(o){var s=f.range.get(!0);s.moveToElementText(i[0]);s.select();s.execCommand("paste");p.preventDefault()}else f.range.selectNodeContents(i[0]),f.select();setTimeout(function(){c();m=!1},0)}})});b.beforeGetHtml(function(a){o&&A<=8&&(a=a.replace(/]*data-ke-input-tag="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b){return unescape(b)}),a=a.replace(/(]*)?>)/ig,function(a,b,c){if(!/\s+type="[^"]+"/i.test(a))return b+' type="text"'+ +c;return a}));return a.replace(/(<(?:noscript|noscript\s[^>]*)>)([\s\S]*?)(<\/noscript>)/ig,function(a,b,c,d){return b+fa(c).replace(/\s+/g," ")+d}).replace(/]*class="?ke-(flash|rm|media)"?[^>]*>/ig,function(a){var a=I(a),b=ba(a.style||""),c=pb(a["data-ke-tag"]),d=l(b.width,""),b=l(b.height,"");/px/i.test(d)&&(d=t(d));/px/i.test(b)&&(b=t(b));c.width=l(a.width,d);c.height=l(a.height,b);return Ma(c)}).replace(/]*class="?ke-anchor"?[^>]*>/ig,function(a){a=I(a);return''}).replace(/]*data-ke-script-attr="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b,c){return""+unescape(c)+"<\/script>"}).replace(/]*data-ke-noscript-attr="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b,c){return""+unescape(c)+""}).replace(/(<[^>]*)data-ke-src="([^"]*)"([^>]*>)/ig,function(a,b,c){a=a.replace(/(\s+(?:href|src)=")[^"]*(")/i,function(a,b,d){return b+fa(c)+d});return a=a.replace(/\s+data-ke-src="[^"]*"/i, +"")}).replace(/(<[^>]+\s)data-ke-(on\w+="[^"]*"[^>]*>)/ig,function(a,b,c){return b+c})});b.beforeSetHtml(function(a){o&&A<=8&&(a=a.replace(/]*>|<(select|button)[^>]*>[\s\S]*?<\/\1>/ig,function(a){var b=I(a);if(ba(b.style||"").display=="none")return'
      ';return a}));return a.replace(/]*type="([^"]+)"[^>]*>(?:<\/embed>)?/ig,function(a){a=I(a);a.src=l(a.src,"");a.width=l(a.width,0);a.height=l(a.height,0);return qb(b.themesPath+ +"common/blank.gif",a)}).replace(/]*name="([^"]+)"[^>]*>(?:<\/a>)?/ig,function(a){var c=I(a);if(c.href!==i)return a;return''}).replace(/]*)>([\s\S]*?)<\/script>/ig,function(a,b,c){return'
      '+escape(c)+"
      "}).replace(/]*)>([\s\S]*?)<\/noscript>/ig,function(a,b,c){return'
      '+escape(c)+"
      "}).replace(/(<[^>]*)(href|src)="([^"]*)"([^>]*>)/ig,function(a,b,c,d,e){if(a.match(/\sdata-ke-src="[^"]*"/i))return a;return a=b+c+'="'+d+'" data-ke-src="'+C(d)+'"'+e}).replace(/(<[^>]+\s)(on\w+="[^"]*"[^>]*>)/ig,function(a,b,c){return b+"data-ke-"+c}).replace(/]*\s+border="0"[^>]*>/ig,function(a){if(a.indexOf("ke-zeroborder")>=0)return a;return Sb(a,"ke-zeroborder")})})})}})(window); diff --git a/public/javascripts/project.js b/public/javascripts/project.js index 0a04b2a7b..5a5d625ed 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -162,10 +162,11 @@ function regexSubject(id) { return false; } function regexContent(id) { - + editor[id].sync(); var contentid = "#message_content" + id; var message = "#message_content_span"+ id; var content = $.trim($(contentid).val()); + alert(content); if (content.length == 0) { $(message).text("描述不能为空"); @@ -186,6 +187,7 @@ function submitProjectsBoard(id) { var formid = "#message-form" + id; if (regexSubject(id) && regexContent(id)) { + $(formid).submit(); } } From 4a588506a420472025f63dfaf86ae7aac6931630 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Wed, 20 May 2015 17:38:40 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=20Signed-off-by:=20alan=20<547533434@qq.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/boards/_edit.html.erb | 6 +- app/views/boards/_form_project.html.erb | 16 +---- app/views/boards/_project_new_topic.html.erb | 4 +- app/views/boards/_project_show.html.erb | 61 ++++++++++++++++++-- app/views/boards/show.html.erb | 6 ++ public/javascripts/project.js | 11 +++- 6 files changed, 76 insertions(+), 28 deletions(-) diff --git a/app/views/boards/_edit.html.erb b/app/views/boards/_edit.html.erb index 0bb15b167..98008d33e 100644 --- a/app/views/boards/_edit.html.erb +++ b/app/views/boards/_edit.html.erb @@ -2,17 +2,17 @@ <% if topic.project %> <%#= board_breadcrumb(@message) %> -
      +
        <%= form_for topic, { :as => :message, :url => {:controller => 'messages',:action => 'edit', :is_board => 'true',:id => topic.id, :board_id => topic.board_id}, - :html => {:multipart => true, + :html => {:multipart => true, :name=>'message-form', :id => 'message-form' + topic.id.to_s, :method => :post} } do |f| %> <%= render :partial => 'form_project', :locals => {:f => f, :replying => !topic.parent.nil?, :topic => topic} %> - <%= l(:button_submit)%> + <%= l(:button_submit)%> <%= l(:button_cancel) %> <%#= link_to l(:button_cancel), board_message_url(topic.board, topic.root, :r => (topic.parent_id && topic.id)), :class => "blue_btn grey_btn fl c_white" %>
      diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb index 4d38ca275..b219c466d 100644 --- a/app/views/boards/_form_project.html.erb +++ b/app/views/boards/_form_project.html.erb @@ -48,24 +48,10 @@
    • - <% unless replying %> <% end %> - <%= text_area :quote,:quote,:style => 'display:none' %> + <%= f.text_area :quote,:quote,:style => 'display:none' %>
      <% if replying%> diff --git a/app/views/boards/_project_new_topic.html.erb b/app/views/boards/_project_new_topic.html.erb index cab1bbb7b..611a58738 100644 --- a/app/views/boards/_project_new_topic.html.erb +++ b/app/views/boards/_project_new_topic.html.erb @@ -1,10 +1,10 @@ -<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message-form'} do |f| %> +<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message-form', :name=>'message-form'} do |f| %> <%= render :partial => 'form_project', :locals => {:f => f, :topic => @message} %>
    • <%= l(:button_cancel) %> - <%= l(:button_submit)%> + <%= l(:button_submit)%>
    • <% end %> \ No newline at end of file diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index db66b1a7e..9a10d123d 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -22,7 +22,7 @@
      -
      +
        <%= render :partial => 'project_new_topic' %>
      @@ -41,6 +41,7 @@

        <%= h(topic.subject) %>

      <% if topic.editable_by?(User.current) %> + <%= l(:button_edit) %> <% end %> @@ -81,7 +82,7 @@ <%= l(:label_activity_time)%>:  <%= format_time topic.created_on %>
      - <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => 'message_content',:class => ' c_dblue fr' %> + <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => "about_newtalk#{topic.id}",:class => ' c_dblue fr' %>
      @@ -98,12 +99,12 @@ <% if !topic.locked? && authorize_for('messages', 'reply') %>
      -
      @@ -216,4 +237,34 @@ } } + + + \ No newline at end of file diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index c111aeaf0..16f2998ce 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -51,11 +51,17 @@ var getParam = function(name){ function show_newtalk() { $("#about_newtalk").toggle(); + + + } function show_newtalk1(id) { $(id).toggle(); + + + } diff --git a/public/javascripts/project.js b/public/javascripts/project.js index 5a5d625ed..481755410 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -161,10 +161,15 @@ function regexSubject(id) { } return false; } -function regexContent(id) { - editor[id].sync(); +function regexContent(){ +} +function regexContentxx(id) { + var contentid = "#message_content" + id; var message = "#message_content_span"+ id; + var ps=document.getElementById('message_content' + id).previousElementSibling.children[1].children[0]; + alert(ps); + document.getElementById('message_content' + id).value = ps.value; var content = $.trim($(contentid).val()); alert(content); if (content.length == 0) { @@ -188,7 +193,7 @@ function submitProjectsBoard(id) { if (regexSubject(id) && regexContent(id)) { - $(formid).submit(); + $(formid).submit(); } } // 提交新闻 From a0ca31780ebfda02d476c00fccc5e63532bbb04d Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Thu, 21 May 2015 16:35:53 +0800 Subject: [PATCH 07/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E3=80=8A=E5=B8=96?= =?UTF-8?q?=E5=AD=90=E6=8E=92=E5=BA=8F=E3=80=8B=E3=80=8A=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E5=8C=BA=E9=93=BE=E6=8E=A5=E9=94=99=E8=AF=AF=E3=80=8B=E3=80=8A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=9E=E5=B8=96=E5=9B=9E=E5=A4=8D=E3=80=8B?= =?UTF-8?q?=E3=80=8A=E6=B7=BB=E5=8A=A0=E7=BC=96=E8=BE=91=E5=99=A8=E3=80=8B?= =?UTF-8?q?=20=E3=80=8A=E5=B1=95=E5=BC=80=EF=BC=8C=E6=94=B6=E8=B5=B7?= =?UTF-8?q?=EF=BC=8C=E5=B1=95=E5=BC=80=E5=9B=9E=E5=A4=8D=EF=BC=8C=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=E5=9B=9E=E5=A4=8D=20=E7=9A=84=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=8B=20Signed-off-by:=20alan=20<54753343?= =?UTF-8?q?4@qq.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/boards_controller.rb | 8 ++-- app/views/boards/_course_new.html.erb | 2 +- app/views/boards/_course_show.html.erb | 45 +++++++++++++++---- app/views/boards/_edit.html.erb | 4 +- app/views/boards/_form_course.html.erb | 33 +++++++++++--- app/views/boards/_form_project.html.erb | 6 +-- app/views/boards/_project_show.html.erb | 55 ++++++++++++----------- app/views/boards/show.html.erb | 3 +- app/views/stores/index.html.erb | 21 ++++++++- public/javascripts/course.js | 58 ++++++++++++------------- public/javascripts/project.js | 4 ++ public/stylesheets/leftside.css | 2 +- public/stylesheets/pleft.css | 2 +- 13 files changed, 159 insertions(+), 84 deletions(-) diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 4a27f02ff..db5bded55 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -80,19 +80,19 @@ class BoardsController < ApplicationController if @project @topic_pages = Paginator.new @topic_count, per_page_option, params['page'] @topics = @board.topics. - reorder("#{Message.table_name}.sticky DESC"). + reorder("#{Message.table_name}.sticky DESC, #{Message.table_name}.created_on desc"). includes(:last_reply). limit(@topic_pages.per_page). offset(@topic_pages.offset). - order("last_replies_messages.created_on desc"). + preload(:author, {:last_reply => :author}). all elsif @course - board_topics = @board ? @board.topics.reorder("#{Message.table_name}.sticky DESC"). + board_topics = @board ? @board.topics.reorder("#{Message.table_name}.sticky DESC, #{Message.table_name}.created_on desc"). includes(:last_reply). # limit(@topic_pages.per_page). # offset(@topic_pages.offset). - order("last_replies_messages.created_on desc"). + preload(:author, {:last_reply => :author}). all : [] @topics = paginateHelper board_topics,10 diff --git a/app/views/boards/_course_new.html.erb b/app/views/boards/_course_new.html.erb index a380ad67f..aaf6d66e5 100644 --- a/app/views/boards/_course_new.html.erb +++ b/app/views/boards/_course_new.html.erb @@ -3,7 +3,7 @@ <%= render :partial => 'form_course', :locals => {:f => f, :topic => @message} %>
    • <%= l(:button_cancel) %> - <%= l(:button_submit)%> + <%= l(:button_submit)%>
    • <% end %> diff --git a/app/views/boards/_course_show.html.erb b/app/views/boards/_course_show.html.erb index 2a078553c..766340c1b 100644 --- a/app/views/boards/_course_show.html.erb +++ b/app/views/boards/_course_show.html.erb @@ -16,7 +16,7 @@
      -
      +
        <%= render :partial => 'course_new' %>
      @@ -40,7 +40,7 @@

        <%= h(topic.subject) %>

      <% if topic.course_editable_by?(User.current) %> - <%= l(:button_edit) %> <% end %> @@ -59,7 +59,7 @@
      @@ -70,7 +70,7 @@
      - @@ -40,7 +42,7 @@

        <%= h(topic.subject) %>

      <% if topic.course_editable_by?(User.current) %> - <%= l(:button_edit) %> <% end %> @@ -70,7 +72,7 @@
      - <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => 'message_content',:class => ' c_dblue fr' %> + <% if User.current.logged? %> + <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => "about_newtalk#{topic.id}",:class => ' c_dblue fr' %> + <% end %>
      @@ -98,11 +102,11 @@
      @@ -139,6 +143,15 @@ :title => l(:button_delete), :class => ' c_dblue fr' ) if message.course_destroyable_by?(User.current) %> + <%= link_to( + l(:button_reply), + {:controller => 'messages', :action => 'quote', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, + :remote => true, + :method => 'get', + :focus => "about_newtalk#{topic.id}", + :class => ' c_dblue fr', + :style => 'margin-right: 10px;', + :title => l(:button_quote)) if !topic.locked? && authorize_for('messages', 'reply') %>
      @@ -168,6 +181,15 @@ :title => l(:button_delete), :class => ' c_dblue fr' ) if message.course_destroyable_by?(User.current) %> + <%= link_to( + l(:button_reply), + {:controller => 'messages', :action => 'quote', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, + :remote => true, + :method => 'get', + :focus => "about_newtalk#{topic.id}", + :class => ' c_dblue fr', + :style => 'margin-right: 10px;', + :title => l(:button_quote)) if !topic.locked? && authorize_for('messages', 'reply') %>
      @@ -176,7 +198,7 @@
      <%if replies_all.first %> - + <% end %> <% end %>
      @@ -196,6 +218,7 @@ <% content_for :header_tags do %> <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@course}: #{@board}") %> <% end %> +
      -
      -
      - <%= topic.content.html_safe %> -
      + +
      +
      + <%= topic.content.html_safe %>
      +
      - - <%= link_to_attachments_course topic, :author => false %> +

      + <%= link_to_attachments_course topic, :author => false %> - <%= l(:label_activity_time)%>:  <%= format_time topic.created_on %> + <%= l(:label_activity_time)%>:  <%= format_time topic.created_on %> -
      - <% if User.current.logged? %> - <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => "about_newtalk#{topic.id}",:class => ' c_dblue fr' %> - <% end %> +
      + <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => 'message_content',:class => ' c_dblue fr' %> -
      +
      -
      - -
      - <% reply = Message.new(:subject => "RE: #{@message.subject}")%> - <% if !topic.locked? && authorize_for('messages', 'reply') %> - -
      - + +
      + <% reply = Message.new(:subject => "RE: #{@message.subject}")%> + <% if !topic.locked? && authorize_for('messages', 'reply') %> + +
      + - <% end %> - <% replies_all = topic.children. - includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.created_on DESC").offset(2). - all %> - <% replies_show = topic.children. - includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.created_on DESC").limit(2). - all %> - <% unless replies_show.empty? %> - <% reply_count = 0 %> -
      -
        - <% replies_show.each do |message| %> - -
      • - <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %> -
        - <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %> -
        -

        <%= textAreailizable message,:content,:attachments => message.attachments %>

        - -
        - <%= format_time(message.created_on) %> - <%= link_to( - - l(:button_delete), - {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, - :method => :post, - :data => {:confirm => l(:text_are_you_sure)}, - :title => l(:button_delete), - :class => ' c_dblue fr' - ) if message.course_destroyable_by?(User.current) %> - <%= link_to( - l(:button_reply), - {:controller => 'messages', :action => 'quote', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, - :remote => true, - :method => 'get', - :focus => "about_newtalk#{topic.id}", - :class => ' c_dblue fr', - :style => 'margin-right: 10px;', - :title => l(:button_quote)) if !topic.locked? && authorize_for('messages', 'reply') %> -
        -
        - -
      • - <% end %> -
      -
      - - <%if replies_all.first %> - + <%= render :partial => 'form_project', :locals => {:f => f, :replying => true} %> + <%= toggle_link l(:button_cancel), "reply" + topic.id.to_s, :focus => 'message_content',:class => 'grey_btn fr ml10' %> + <%= l(:label_memo_create)%> <% end %> - <% end %> -
      - <% end %> - <% else %> -

      <%= l(:label_no_data) %>

      - <% end %> +
      +
      + <% end %> + <% replies_all = topic.children. + includes(:author, :attachments, {:board => :project}). + reorder("#{Message.table_name}.created_on DESC").offset(2). + all %> + <% replies_show = topic.children. + includes(:author, :attachments, {:board => :project}). + reorder("#{Message.table_name}.created_on DESC").limit(2). + all %> + <% unless replies_show.empty? %> + <% reply_count = 0 %> +
      +
        + <% replies_show.each do |message| %> + +
      • + <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %> +
        + <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %> +
        +

        <%= textAreailizable message,:content,:attachments => message.attachments %>

        + +
        + <%= format_time(message.created_on) %> + <%= link_to( + + l(:button_delete), + {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, + :method => :post, + :data => {:confirm => l(:text_are_you_sure)}, + :title => l(:button_delete), + :class => ' c_dblue fr' + ) if message.course_destroyable_by?(User.current) %> +
        +
        + +
      • + <% end %> +
      +
      + + <%if replies_all.first %> + + <% end %> + <% end %> + + <% end %> +<% else %> +

      <%= l(:label_no_data) %>

      +<% end %>
        <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
      <%# other_formats_links do |f| %> - <%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> +<%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> <%# end %> <% html_title @board.name %> @@ -224,49 +202,52 @@ KindEditor.ready(function(K){ $("div[name='container_board']").each(function(){ var container=$(this); - + var messege = $("p[aa='message_show']",container); + var subject = $("input[aa='subject']",container); var textarea= $("textarea[aa='content']",container); - var message = $("p[aa='message_show']", container); + var form = $("form",container); var editor = K.create(textarea, { resizeType : 1, allowPreviewEmoticons : false, allowImageUpload : false, width:"89%", - items : ['emoticons'] + items : [] }); +// form.submit(function(){ +// alert(textarea.html()); +// }); +// $("a[name='submitbtn']",container).click(function(){ +// form.submit(); +// }); $("a[name='submitbtn']",container).click(function(){ - textarea[0].value = editor.html(); + textarea[0].value = editor.html() ; var id = textarea[0].id.toString().substr(15); - var subject = document.getElementById("message_subject"); - if(subject.value == "RE: ") { - if (textarea[0].value.length == 0) { - message[0].text("描述不能为空"); - message[0].css('color', '#ff0000'); + if(subject.val() == "RE: ") { + if (editor.html() == "") { + messege.html("回复内容不能为空") ; + messege.css('color', '#ff0000'); + messege.show(); } else { - - message[0].text("填写正确"); - message[0].css('color', '#008000'); + messege.html("填写正确"); + messege.css('color', '#008000'); + messege.show(); this.parentNode.submit(); } } else { - if (regexContent(id) && regexSubject(id)) { - if (this.parentNode.name.toString() == 'message-form') { + if(regexContent(id) && regexSubject(id)) { + if (this.parentNode.name == 'message-form') { this.parentNode.submit(); } - else { - + else this.parentNode.parentNode.submit(); - - } } } - - }); + }); }); }); diff --git a/app/views/boards/_form_course.html.erb b/app/views/boards/_form_course.html.erb index de5928923..cfef18f93 100644 --- a/app/views/boards/_form_course.html.erb +++ b/app/views/boards/_form_course.html.erb @@ -5,17 +5,17 @@
    • - <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585" }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585", :aa=>"subject" }.merge(extra_option) %> -

      +

    • <% else %> -
    • +
    • - <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", onkeyup: "regexSubject('#{f.object.id}');",:class=>"talk_input w585" }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", onkeyup: "regexSubject('#{f.object.id}');",:class=>"talk_input w585", :aa=>"subject" }.merge(extra_option) %>

    • diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb index 2ab36c774..eb9c4e416 100644 --- a/app/views/boards/_form_project.html.erb +++ b/app/views/boards/_form_project.html.erb @@ -18,7 +18,7 @@
    • - <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}",:class=>"talk_input w585" }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}",:class=>"talk_input w585", :aa=>'subject' }.merge(extra_option) %>

      @@ -28,7 +28,7 @@ - <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", onkeyup: "regexSubject('#{f.object.id}');",:class=>"talk_input w585" }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", onkeyup: "regexSubject('#{f.object.id}');",:class=>"talk_input w585", :aa=>'subject' }.merge(extra_option) %>

    • diff --git a/app/views/boards/_project_new_topic.html.erb b/app/views/boards/_project_new_topic.html.erb index 611a58738..5c8691529 100644 --- a/app/views/boards/_project_new_topic.html.erb +++ b/app/views/boards/_project_new_topic.html.erb @@ -4,7 +4,7 @@
    • <%= l(:button_cancel) %> - <%= l(:button_submit)%> + <%= l(:button_submit)%>
    • <% end %> \ No newline at end of file diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index 86c50897b..2129c3a9f 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -8,7 +8,7 @@ <% if User.current.logged? %> - <%= l(:label_message_new) %> + <%= l(:label_message_new) %> <% end %>
      @@ -174,7 +174,7 @@

      <%= textAreailizable message,:content,:attachments => message.attachments %>

      -
      +
      <%= format_time(message.created_on) %> <%= link_to( @@ -246,28 +246,32 @@ KindEditor.ready(function(K){ $("div[name='container_board']").each(function(){ var container=$(this); - + var form =$("form", container); + var messege = $("p[aa='message_show']",container); var textarea= $("textarea[aa='content']",container); var editor = K.create(textarea, { resizeType : 1, allowPreviewEmoticons : false, allowImageUpload : false, width:"89%", - items : ['emoticons'] + items : [] }); $("a[name='submitbtn']",container).click(function(){ textarea[0].value = editor.html(); - var id = textarea[0].id.toString().substr(15); - if(regexContent(id) && regexSubject(id)) { - if (this.parentNode.name.toString() == 'message-form') { - this.parentNode.submit(); - } - else { - this.parentNode.parentNode.submit(); - } + if (editor.html() == "") { + + messege.html("回复内容不能为空") ; + messege.css('color', '#ff0000'); + messege.show(); + } + else { + messege.html("填写正确"); + messege.css('color', '#008000'); + messege.show(); + form.submit(); } }); diff --git a/public/javascripts/project.js b/public/javascripts/project.js index 3611fe380..8c21e6ce0 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -77,7 +77,24 @@ function show_more_reply(contentid, id2, id3) { information.attr("style", "color:#0781b4;"); } } - +function show_more_reply1(contentid, id2, id3) { + $(contentid).toggleClass("course_description_none"); + var information = $(id2); + var arrow = $(id3); + var val = information.attr("value"); + if (val == "show_more") { + $(id2).text("[收起]"); + information.attr("value", "hide_more"); + information.attr("style", "color:#3ca5c6"); + arrow.attr("src", "/images/jiantouup.jpg") + } + else { + $(id2).text("[展开]"); + information.attr("value", "show_more"); + arrow.attr("src", "/images/jiantou.jpg") + information.attr("style", "color:#0781b4;"); + } +} //项目版本库git帮助文档显示 function showhelpAndScrollTo(id) { $('#' + id).toggle(); diff --git a/public/stylesheets/leftside.css b/public/stylesheets/leftside.css index 53d382f20..9095cc6e3 100644 --- a/public/stylesheets/leftside.css +++ b/public/stylesheets/leftside.css @@ -46,6 +46,7 @@ a:hover.subnav_green{ background:#14ad5a;} .project_intro{ width:220px; padding:10px; background:#fff; margin-top:10px; padding-top:5px; color:#6d6d6d; line-height:1.9;} .course_description{max-height: 112px;overflow:hidden; word-break: break-all;word-wrap: break-word;} .project_board_content{overflow: hidden;max-height: 182px;word-break: break-all;word-wrap: break-word;} +.project_board_content1{overflow: hidden;max-height: 72px;word-break: break-all;word-wrap: break-word;} .course_description_none{max-height: none;} .lg-foot{ border:1px solid #e8eef2; color: #929598; text-align:center; width:220px; height:23px; cursor:pointer;display: none;} .lg-foot:hover{ color:#787b7e; border:1px solid #d4d4d4;} diff --git a/public/stylesheets/pleft.css b/public/stylesheets/pleft.css index a8d4409e3..acf470dfe 100644 --- a/public/stylesheets/pleft.css +++ b/public/stylesheets/pleft.css @@ -50,6 +50,7 @@ a:hover.subnav_green{ background:#14ad5a;} .project_intro{ width:220px; padding:10px; background:#fff; margin-top:10px; padding-top:5px; color:#6d6d6d; line-height:1.9;} .course_description{max-height: 112px;overflow:hidden; word-break: break-all;word-wrap: break-word;} .project_board_content{overflow: hidden;max-height: 182px;word-break: break-all;word-wrap: break-word;} +.project_board_content1{overflow: hidden;max-height: 72px;word-break: break-all;word-wrap: break-word;} .course_description_none{max-height: none;} .lg-foot{ border:1px solid #e8eef2; color: #929598; text-align:center; width:220px; height:23px; cursor:pointer;display: none;} .lg-foot:hover{ color:#787b7e; border:1px solid #d4d4d4;} From 161edea8791d09f5e976d19397feae856f13f98b Mon Sep 17 00:00:00 2001 From: sw <939547590@qq.com> Date: Sat, 23 May 2015 14:46:30 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=BE=E7=A8=8B?= =?UTF-8?q?=E8=AE=A8=E8=AE=BA=E5=8C=BA=E6=97=A0=E6=B3=95=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E5=B8=96=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/boards/_course_new.html.erb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/boards/_course_new.html.erb b/app/views/boards/_course_new.html.erb index 6ca6b074a..10f23d4f2 100644 --- a/app/views/boards/_course_new.html.erb +++ b/app/views/boards/_course_new.html.erb @@ -2,8 +2,10 @@ <%= render :partial => 'form_course', :locals => {:f => f, :topic => @message} %>
    • - <%= l(:button_cancel) %> - <%= l(:button_submit)%> + <%= l(:button_cancel) %> + + <%= l(:button_submit)%> +
    • <% end %> From 72b93fa8f0c561850871ab9c5697dd9c296321c0 Mon Sep 17 00:00:00 2001 From: yutao <283765470@qq.com> Date: Sat, 23 May 2015 16:02:41 +0800 Subject: [PATCH 11/30] ... --- app/views/boards/_edit.html.erb | 16 +- app/views/boards/_form_project.html.erb | 14 +- app/views/boards/_project_new_topic.html.erb | 6 +- app/views/boards/_project_show.html.erb | 434 +++++++------------ app/views/boards/show.html.erb | 2 +- 5 files changed, 187 insertions(+), 285 deletions(-) diff --git a/app/views/boards/_edit.html.erb b/app/views/boards/_edit.html.erb index fb5adc1d6..562319e56 100644 --- a/app/views/boards/_edit.html.erb +++ b/app/views/boards/_edit.html.erb @@ -2,37 +2,37 @@ <% if topic.project %> <%#= board_breadcrumb(@message) %> -
      +
        <%= form_for topic, { :as => :message, :url => {:controller => 'messages',:action => 'edit', :is_board => 'true',:id => topic.id, :board_id => topic.board_id}, :html => {:multipart => true, :name=>'message-form', :id => 'message-form' + topic.id.to_s, - :method => :post} + :method => :post,:nhname=>'form'} } do |f| %> <%= render :partial => 'form_project', :locals => {:f => f, :replying => !topic.parent.nil?, :topic => topic} %> - <%= l(:button_submit)%> - <%= l(:button_cancel) %> + <%= l(:button_cancel) %> + <%= l(:button_submit)%> <%#= link_to l(:button_cancel), board_message_url(topic.board, topic.root, :r => (topic.parent_id && topic.id)), :class => "blue_btn grey_btn fl c_white" %>
      <% end %> <% elsif topic.course %> <%#= course_board_breadcrumb(@message) %> -
      +
        <%= form_for topic, { :as => :message, :url => {:controller => 'messages',:action => 'edit', :is_board => 'true',:id => topic.id, :board_id => topic.board_id}, :html => {:multipart => true, :name=>'message-form', :id => 'message-form' + topic.id.to_s, - :method => :post} + :method => :post,:nhname=>'form'} } do |f| %> <%= render :partial => 'form_course', :locals => {:f => f, :replying => !topic.parent.nil?, :topic => topic} %> - <%= l(:button_submit)%> - <%= l(:button_cancel) %> + <%= l(:button_cancel) %> + <%= l(:button_submit)%> <% end %>
      diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb index eb9c4e416..5cf20a993 100644 --- a/app/views/boards/_form_project.html.erb +++ b/app/views/boards/_form_project.html.erb @@ -18,19 +18,19 @@
    • - <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}",:class=>"talk_input w585", :aa=>'subject' }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}",:class=>"talk_input w585", :nhname=>'inputsubject' }.merge(extra_option) %> -

      +

    • <% else %>
    • - <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", onkeyup: "regexSubject('#{f.object.id}');",:class=>"talk_input w585", :aa=>'subject' }.merge(extra_option) %> + <%= f.text_field :subject, { size: 60, id: "message_subject#{f.object.id}", :class=>"talk_input w585", :nhname=>'inputsubject' }.merge(extra_option) %> -

      +

    • <% end %>
    • @@ -59,7 +59,7 @@ :width => '89%', :height => 300, :id => "message_content#{f.object.id}", - :aa => 'content', + :nhname => 'textarea', :onkeyup => "regexContent('#{f.object.id}');", :class => 'talk_text fl', :placeholder => "最多3000个汉字(或6000个英文字符)", @@ -74,14 +74,14 @@ :id => "message_content#{f.object.id}", :onkeyup => "regexContent('#{f.object.id}');", :class => 'talk_text fl', - :aa => 'content', + :nhname => 'textarea', :placeholder => "最多3000个汉字(或6000个英文字符)", :maxlength => 5000 %> <% end %>
    • -

      +

    • diff --git a/app/views/boards/_project_new_topic.html.erb b/app/views/boards/_project_new_topic.html.erb index 5c8691529..05304e978 100644 --- a/app/views/boards/_project_new_topic.html.erb +++ b/app/views/boards/_project_new_topic.html.erb @@ -1,10 +1,10 @@ -<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message-form', :name=>'message-form'} do |f| %> +<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'},:nhname=>'form', :html => {:multipart => true, :id => 'message-form', :name=>'message-form'} do |f| %> <%= render :partial => 'form_project', :locals => {:f => f, :topic => @message} %>
    • - <%= l(:button_cancel) %> + <%= l(:button_cancel) %> - <%= l(:button_submit)%> + <%= l(:button_submit)%>
    • <% end %> \ No newline at end of file diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index 2129c3a9f..0706860f9 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -1,280 +1,182 @@ -
      -

      - <% if User.current.language == "zh"%> - <%= h @board.name %> - <% else %> - <%= l(:project_module_boards) %> +
      +
      +

      + <% if User.current.language == "zh"%> + <%= h @board.name %> + <% else %> + <%= l(:project_module_boards) %> + <% end %> +

      + <% if User.current.logged? %> + <%= l(:label_message_new) %> <% end %> - -

      - <% if User.current.logged? %> - <%= l(:label_message_new) %> +
      +
      + <% if !User.current.logged? %> +
      + <%= l(:label_user_login_project_board) %> + <%= link_to l(:label_user_login_new), signin_path, :class => "c_blue ml5" %> +
      <% end %>
      +
      +
      +
        + <%= render :partial => 'project_new_topic' %> +
      +
      +
      - - -<% if !User.current.logged? %> -
      - <%= l(:label_user_login_project_board) %> - <%= link_to l(:label_user_login_new), signin_path, :class => "c_blue ml5" %> -
      -<% end %> - - -
      -
      -
        - <%= render :partial => 'project_new_topic' %> -
      -
      - -

      讨论区共有<%= @topic_count %>个帖子

      -<% if @topics.any? %> - <% @topics.each do |topic| %> - -
      - <%= link_to image_tag(url_to_avatar(topic.author), :width=>"42",:height=>"42"), user_path(topic.author),:class =>'talkmain_pic fl' %> -
      - <% author = topic.author.to_s + ":" %> - <%= link_to author, user_path(topic.author), :class =>"talkmain_name fl " %> - -

        <%= h(topic.subject) %>

      - <% if topic.editable_by?(User.current) %> - - <%= l(:button_edit) %> - <% end %> - - <%= link_to( - l(:button_delete), - {:controller =>'messages',:action => 'destroy', :id => topic.id, :board_id => topic.board_id, :is_board=>'true'}, - :method => :post, - :data => {:confirm => l(:text_are_you_sure)}, - :class => 'talk_edit fr', - :style => ' margin-right: 10px;' - ) if topic.destroyable_by?(User.current) %> - - <% if topic.sticky? %> - <%= l(:label_board_sticky)%> - <% end %> -
      - -
      -
      - <%= topic.content.html_safe %> -
      -
      - - -
      +
      + <%= link_to image_tag(url_to_avatar(topic.author), :width=>"42",:height=>"42"), user_path(topic.author),:class =>'talkmain_pic fl' %> +
      + <% author = topic.author.to_s + ":" %> + <%= link_to author, user_path(topic.author), :class =>"talkmain_name fl " %> +

        <%= h(topic.subject) %>

      + <% if topic.editable_by?(User.current) %> + <%= l(:button_edit) %> + <% end %> + <%= link_to( + l(:button_delete), + {:controller =>'messages',:action => 'destroy', :id => topic.id, :board_id => topic.board_id, :is_board=>'true'}, + :method => :post, + :data => {:confirm => l(:text_are_you_sure)}, + :class => 'talk_edit fr', + :style => ' margin-right: 10px;' + ) if topic.destroyable_by?(User.current) %> + <% if topic.sticky? %> + <%= l(:label_board_sticky)%> + <% end %> +
      +
      +
      + <%= topic.content.html_safe %> +
      +
      + + <%= link_to_attachments_course topic, :author => false %> + <%= l(:label_activity_time)%>:  <%= format_time topic.created_on %> +
      + <% if User.current.logged? %> + <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => "about_newtalk#{topic.id}",:class => ' c_dblue fr' %> + <% end %> +
      +
      + +
      +
      -

      - - <%= link_to_attachments_course topic, :author => false %> - - <%= l(:label_activity_time)%>:  <%= format_time topic.created_on %> - -
      - <% if User.current.logged? %> - <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => "about_newtalk#{topic.id}",:class => ' c_dblue fr' %> - <% end %> -
      - - -
      - - -
      - <% reply = Message.new(:subject => "RE: #{@message.subject}")%> - <% if !topic.locked? && authorize_for('messages', 'reply') %> - -
      - - <% end %> - <% replies_all = topic.children. - includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.id asc").offset(2). - all %> - <% replies_show = topic.children. - includes(:author, :attachments, {:board => :project}). - reorder("#{Message.table_name}.id asc").limit(2). - all %> - <% unless replies_show.empty? %> - <% reply_count = 0 %> -
      -
        - <% replies_show.each do |message| %> - -
      • - <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %> -
        - <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %> -
        -

        <%= textAreailizable message,:content,:attachments => message.attachments %>

        - -
        - <%= format_time(message.created_on) %> - <%= link_to( - - l(:button_delete), - {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, - :method => :post, - :data => {:confirm => l(:text_are_you_sure)}, - :title => l(:button_delete), - :class => ' c_dblue fr' - ) if message.course_destroyable_by?(User.current) %> - <%= link_to( - l(:button_reply), - {:controller => 'messages', :action => 'quote', :id => message.id, :board_id => message.board_id, :is_board => 'true'}, - :class => ' c_dblue fr', - :style => 'margin-right: 10px;', - :remote => true, - :method => 'get', - :onclick => "$('#reply#{topic.id}').slideToggle(); return false;", - :focus => "about_newtalk#{topic.id}", - :title => l(:button_quote)) if !topic.locked? && authorize_for('messages', 'reply') %> -
        -
        - -
      • - <% end %> -
      -
      - - <%if replies_all.first %> - - <% end %> - <% end %> -
      - +
      + <% reply = Message.new(:subject => "RE: #{@message.subject}")%> + <% if !topic.locked? && authorize_for('messages', 'reply') %> + +
      + <% end %> - <% else %> -

      <%= l(:label_no_data) %>

      - <% end %> -
        - <%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %> -
      - - -<%# other_formats_links do |f| %> - <%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> -<%# end %> +
      -<% html_title @board.name %> - -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@project}: #{@board}") %> -<% end %> -
      - + function nh_check_field(params){ + var result=true; + + if($.trim(params.subject.val()) == ""){ + params.subjectmsg.html('主题不能为空'); + params.subjectmsg.css({color:'#ff0000'}); + result=false; + }else{ + params.subjectmsg.html('填写正确'); + params.subjectmsg.css({color:'#008000'}); + } + params.subjectmsg.show(); + + if($.trim(params.content.html()) == ""){ + params.contentmsg.html('内容不能为空'); + params.contentmsg.css({color:'#ff0000'}); + result=false; + }else{ + params.contentmsg.html('填写正确'); + params.contentmsg.css({color:'#008000'}); + } + params.contentmsg.show(); + + return result; + } + function nh_init_board(params){ + params.showbtn.click(function(){//发帖/编辑/回复按钮的click + if(params.textarea.data('init') == undefined){ + var editor = params.kindutil.create(params.textarea, {//初始化编辑器 + resizeType : 1, + allowPreviewEmoticons : false, + allowImageUpload : false, + minWidth:"1px", + width:"565px", + items : [] + }); + params.submitbtn.click(function(){//提交按钮click + var is_checked = nh_check_field({ + subject:params.inputsubject, + subjectmsg:params.subjectmsg, + content:editor, + contentmsg:params.contentmsg, + }); + if(is_checked){ + alert('submit'); + params.textarea.html(editor.html()); +// params.form.submit(); + } + }); + params.cancelbtn.click(function(){//取消按钮click + params.about_talk.toggle();//显示/隐藏编辑区 + params.inputsubject.focus(); + }); + params.textarea.data('init','1') + } + params.cancelbtn.click();//显示/隐藏编辑区 + }); + } + $(function(){ + KindEditor.ready(function(K){ + $("div[nhname='container_board']").each(function(){ + var container = $(this); + nh_init_board({ + kindutil:K, + showbtn:$("a[nhname='showbtn']",container), + about_talk:$("div[nhname='about_talk']",container), + inputsubject:$("input[nhname='inputsubject']",container), + subjectmsg:$("p[nhname='subjectmsg']",container), + textarea:$("textarea[nhname='textarea']",container), + contentmsg:$("p[nhname='contentmsg']",container), + submitbtn:$("a[nhname='submitbtn']",container), + cancelbtn:$("a[nhname='cancelbtn']",container), + form:$("form[nhname='form']",container) + }); + }); + }); + }); + \ No newline at end of file diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index ed49f0adb..7ec7fd0fd 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -61,7 +61,7 @@ function show_newtalk1(id) $(id).toggle(); $(id).focus(); - + } From fe404f8cb14c74c296d24e48288febfa524cda58 Mon Sep 17 00:00:00 2001 From: yutao <283765470@qq.com> Date: Sat, 23 May 2015 16:35:57 +0800 Subject: [PATCH 12/30] ... --- app/views/boards/_project_show.html.erb | 37 ++++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index 0706860f9..ae8dd5ed2 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -31,7 +31,7 @@

      讨论区共有<%= @topic_count %>个帖子

      <% if @topics.any? %> <% @topics.each do |topic| %> -
      +
      <%= link_to image_tag(url_to_avatar(topic.author), :width=>"42",:height=>"42"), user_path(topic.author),:class =>'talkmain_pic fl' %>
      @@ -39,7 +39,7 @@ <%= link_to author, user_path(topic.author), :class =>"talkmain_name fl " %>

        <%= h(topic.subject) %>

      <% if topic.editable_by?(User.current) %> - <%= l(:button_edit) %> + <%= l(:button_edit) %> <% end %> <%= link_to( l(:button_delete), @@ -164,17 +164,34 @@ KindEditor.ready(function(K){ $("div[nhname='container_board']").each(function(){ var container = $(this); + var about_talk = $("div[nhname='about_talk']",container); nh_init_board({ kindutil:K, showbtn:$("a[nhname='showbtn']",container), - about_talk:$("div[nhname='about_talk']",container), - inputsubject:$("input[nhname='inputsubject']",container), - subjectmsg:$("p[nhname='subjectmsg']",container), - textarea:$("textarea[nhname='textarea']",container), - contentmsg:$("p[nhname='contentmsg']",container), - submitbtn:$("a[nhname='submitbtn']",container), - cancelbtn:$("a[nhname='cancelbtn']",container), - form:$("form[nhname='form']",container) + about_talk:about_talk, + inputsubject:$("input[nhname='inputsubject']",about_talk), + subjectmsg:$("p[nhname='subjectmsg']",about_talk), + textarea:$("textarea[nhname='textarea']",about_talk), + contentmsg:$("p[nhname='contentmsg']",about_talk), + submitbtn:$("a[nhname='submitbtn']",about_talk), + cancelbtn:$("a[nhname='cancelbtn']",about_talk), + form:$("form[nhname='form']",about_talk) + }); + }); + $("div[ecname='container_board_reply']").each(function(){ + var container = $(this); + var about_talk = $("div[nhname='about_talk_reply']",container); + nh_init_board({ + kindutil:K, + showbtn:$("a[nhname='showbtn_reply']",container), + about_talk:about_talk, + inputsubject:$("input[nhname='inputsubject']",about_talk), + subjectmsg:$("p[nhname='subjectmsg']",about_talk), + textarea:$("textarea[nhname='textarea']",about_talk), + contentmsg:$("p[nhname='contentmsg']",about_talk), + submitbtn:$("a[nhname='submitbtn']",about_talk), + cancelbtn:$("a[nhname='cancelbtn']",about_talk), + form:$("form[nhname='form']",about_talk) }); }); }); From a27b3e9dc667a3384f4b9f58537938d29cc31452 Mon Sep 17 00:00:00 2001 From: alanlong9278 <547533434@qq.com> Date: Mon, 25 May 2015 23:22:11 +0800 Subject: [PATCH 13/30] Signed-off-by: alanlong9278 <547533434@qq.com> --- db/schema.rb | 7 - test/test_helper.rb | 1042 +++++++++++++++++++++---------------------- 2 files changed, 521 insertions(+), 528 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index de6655544..f8d638a5f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -438,13 +438,6 @@ ActiveRecord::Schema.define(:version => 20150514133640) do add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" - create_table "discuss_demos", :force => true do |t| - t.string "title" - t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - create_table "documents", :force => true do |t| t.integer "project_id", :default => 0, :null => false t.integer "category_id", :default => 0, :null => false diff --git a/test/test_helper.rb b/test/test_helper.rb index b7d786704..4e75da59b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,521 +1,521 @@ -require 'rubygems' -# require 'spork' -#uncomment the following line to use spork with the debugger -#require 'spork/ext/ruby-debug' - -# Spork.prefork do -# # Loading more in this block will cause your tests to run faster. However, -# # if you change any configuration or code from libraries loaded here, you'll -# # need to restart spork for it take effect. -# ENV["RAILS_ENV"] = "test" -# require File.expand_path('../../config/environment', __FILE__) -# require 'rails/test_help' -# -# end -# -# Spork.each_run do -# # This code will be run each time you run your specs. -# -# end - -# --- Instructions --- -# Sort the contents of this file into a Spork.prefork and a Spork.each_run -# block. -# -# The Spork.prefork block is run only once when the spork server is started. -# You typically want to place most of your (slow) initializer code in here, in -# particular, require'ing any 3rd-party gems that you don't normally modify -# during development. -# -# The Spork.each_run block is run each time you run your specs. In case you -# need to load files that tend to change during development, require them here. -# With Rails, your application modules are loaded automatically, so sometimes -# this block can remain empty. -# -# Note: You can modify files loaded *from* the Spork.each_run block without -# restarting the spork server. However, this file itself will not be reloaded, -# so if you change any of the code inside the each_run block, you still need to -# restart the server. In general, if you have non-trivial code in this file, -# it's advisable to move it into a separate file so you can easily edit it -# without restarting spork. (For example, with RSpec, you could move -# non-trivial code into a file spec/support/my_helper.rb, making sure that the -# spec/support/* files are require'd from inside the each_run block.) -# -# Any code that is left outside the two blocks will be run during preforking -# *and* during each_run -- that's probably not what you want. -# -# These instructions should self-destruct in 10 seconds. If they don't, feel -# free to delete them. - - - - -# Redmine - project management software -# Copyright (C) 2006-2013 Jean-Philippe Lang -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#require 'shoulda' -ENV["RAILS_ENV"] = "test" -require File.expand_path(File.dirname(__FILE__) + "/../config/environment") -require 'rails/test_help' -require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s - -require File.expand_path(File.dirname(__FILE__) + '/object_helpers') -include ObjectHelpers - -class ActiveSupport::TestCase - include ActionDispatch::TestProcess - - self.use_transactional_fixtures = true - self.use_instantiated_fixtures = false - - def log_user(login, password) - User.anonymous - get "/login" - assert_equal nil, session[:user_id] - puts response.response_code() - assert_response :success - assert_template "account/login" - post "/login", :username => login, :password => password - assert_equal login, User.find(session[:user_id]).login - end - - def uploaded_test_file(name, mime) - fixture_file_upload("files/#{name}", mime, true) - end - - def credentials(user, password=nil) - {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)} - end - - # Mock out a file - def self.mock_file - file = 'a_file.png' - file.stubs(:size).returns(32) - file.stubs(:original_filename).returns('a_file.png') - file.stubs(:content_type).returns('image/png') - file.stubs(:read).returns(false) - file - end - - def mock_file - self.class.mock_file - end - - def mock_file_with_options(options={}) - file = '' - file.stubs(:size).returns(32) - original_filename = options[:original_filename] || nil - file.stubs(:original_filename).returns(original_filename) - content_type = options[:content_type] || nil - file.stubs(:content_type).returns(content_type) - file.stubs(:read).returns(false) - file - end - - # Use a temporary directory for attachment related tests - def set_tmp_attachments_directory - Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test") - unless File.directory?("#{Rails.root}/tmp/test/attachments") - Dir.mkdir "#{Rails.root}/tmp/test/attachments" - end - Attachment.storage_path = "#{Rails.root}/tmp/test/attachments" - end - - def set_fixtures_attachments_directory - Attachment.storage_path = "#{Rails.root}/test/fixtures/files" - end - - def with_settings(options, &block) - saved_settings = options.keys.inject({}) do |h, k| - h[k] = case Setting[k] - when Symbol, false, true, nil - Setting[k] - else - Setting[k].dup - end - h - end - options.each {|k, v| Setting[k] = v} - yield - ensure - saved_settings.each {|k, v| Setting[k] = v} if saved_settings - end - - # Yields the block with user as the current user - def with_current_user(user, &block) - saved_user = User.current - User.current = user - yield - ensure - User.current = saved_user - end - - def change_user_password(login, new_password) - user = User.first(:conditions => {:login => login}) - user.password, user.password_confirmation = new_password, new_password - user.save! - end - - def self.ldap_configured? - @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389) - return @test_ldap.bind - rescue Exception => e - # LDAP is not listening - return nil - end - - def self.convert_installed? - Redmine::Thumbnail.convert_available? - end - - # Returns the path to the test +vendor+ repository - def self.repository_path(vendor) - Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s - end - - # Returns the url of the subversion test repository - def self.subversion_repository_url - path = repository_path('subversion') - path = '/' + path unless path.starts_with?('/') - "file://#{path}" - end - - # Returns true if the +vendor+ test repository is configured - def self.repository_configured?(vendor) - File.directory?(repository_path(vendor)) - end - - def repository_path_hash(arr) - hs = {} - hs[:path] = arr.join("/") - hs[:param] = arr.join("/") - hs - end - - def assert_save(object) - saved = object.save - message = "#{object.class} could not be saved" - errors = object.errors.full_messages.map {|m| "- #{m}"} - message << ":\n#{errors.join("\n")}" if errors.any? - assert_equal true, saved, message - end - - def assert_error_tag(options={}) - assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options)) - end - - def assert_include(expected, s, message=nil) - assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"") - end - - def assert_not_include(expected, s) - assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\"" - end - - def assert_select_in(text, *args, &block) - d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root - assert_select(d, *args, &block) - end - - def assert_mail_body_match(expected, mail) - if expected.is_a?(String) - assert_include expected, mail_body(mail) - else - assert_match expected, mail_body(mail) - end - end - - def assert_mail_body_no_match(expected, mail) - if expected.is_a?(String) - assert_not_include expected, mail_body(mail) - else - assert_no_match expected, mail_body(mail) - end - end - - def mail_body(mail) - mail.parts.first.body.encoded - end -end - -module Redmine - module ApiTest - # Base class for API tests - class Base < ActionDispatch::IntegrationTest - # Test that a request allows the three types of API authentication - # - # * HTTP Basic with username and password - # * HTTP Basic with an api key for the username - # * Key based with the key=X parameter - # - # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) - # @param [String] url the request url - # @param [optional, Hash] parameters additional request parameters - # @param [optional, Hash] options additional options - # @option options [Symbol] :success_code Successful response code (:success) - # @option options [Symbol] :failure_code Failure response code (:unauthorized) - def self.should_allow_api_authentication(http_method, url, parameters={}, options={}) - should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options) - should_allow_http_basic_auth_with_key(http_method, url, parameters, options) - should_allow_key_based_auth(http_method, url, parameters, options) - end - - # Test that a request allows the username and password for HTTP BASIC - # - # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) - # @param [String] url the request url - # @param [optional, Hash] parameters additional request parameters - # @param [optional, Hash] options additional options - # @option options [Symbol] :success_code Successful response code (:success) - # @option options [Symbol] :failure_code Failure response code (:unauthorized) - def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={}) - success_code = options[:success_code] || :success - failure_code = options[:failure_code] || :unauthorized - - context "should allow http basic auth using a username and password for #{http_method} #{url}" do - context "with a valid HTTP authentication" do - setup do - @user = User.generate! do |user| - user.admin = true - user.password = 'my_password' - end - send(http_method, url, parameters, credentials(@user.login, 'my_password')) - end - - should_respond_with success_code - should_respond_with_content_type_based_on_url(url) - should "login as the user" do - assert_equal @user, User.current - end - end - - context "with an invalid HTTP authentication" do - setup do - @user = User.generate! - send(http_method, url, parameters, credentials(@user.login, 'wrong_password')) - end - - should_respond_with failure_code - should_respond_with_content_type_based_on_url(url) - should "not login as the user" do - assert_equal User.anonymous, User.current - end - end - - context "without credentials" do - setup do - send(http_method, url, parameters) - end - - should_respond_with failure_code - should_respond_with_content_type_based_on_url(url) - should "include_www_authenticate_header" do - assert @controller.response.headers.has_key?('WWW-Authenticate') - end - end - end - end - - # Test that a request allows the API key with HTTP BASIC - # - # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) - # @param [String] url the request url - # @param [optional, Hash] parameters additional request parameters - # @param [optional, Hash] options additional options - # @option options [Symbol] :success_code Successful response code (:success) - # @option options [Symbol] :failure_code Failure response code (:unauthorized) - def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={}) - success_code = options[:success_code] || :success - failure_code = options[:failure_code] || :unauthorized - - context "should allow http basic auth with a key for #{http_method} #{url}" do - context "with a valid HTTP authentication using the API token" do - setup do - @user = User.generate! do |user| - user.admin = true - end - @token = Token.create!(:user => @user, :action => 'api') - send(http_method, url, parameters, credentials(@token.value, 'X')) - end - should_respond_with success_code - should_respond_with_content_type_based_on_url(url) - should_be_a_valid_response_string_based_on_url(url) - should "login as the user" do - assert_equal @user, User.current - end - end - - context "with an invalid HTTP authentication" do - setup do - @user = User.generate! - @token = Token.create!(:user => @user, :action => 'feeds') - send(http_method, url, parameters, credentials(@token.value, 'X')) - end - should_respond_with failure_code - should_respond_with_content_type_based_on_url(url) - should "not login as the user" do - assert_equal User.anonymous, User.current - end - end - end - end - - # Test that a request allows full key authentication - # - # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) - # @param [String] url the request url, without the key=ZXY parameter - # @param [optional, Hash] parameters additional request parameters - # @param [optional, Hash] options additional options - # @option options [Symbol] :success_code Successful response code (:success) - # @option options [Symbol] :failure_code Failure response code (:unauthorized) - def self.should_allow_key_based_auth(http_method, url, parameters={}, options={}) - success_code = options[:success_code] || :success - failure_code = options[:failure_code] || :unauthorized - - context "should allow key based auth using key=X for #{http_method} #{url}" do - context "with a valid api token" do - setup do - @user = User.generate! do |user| - user.admin = true - end - @token = Token.create!(:user => @user, :action => 'api') - # Simple url parse to add on ?key= or &key= - request_url = if url.match(/\?/) - url + "&key=#{@token.value}" - else - url + "?key=#{@token.value}" - end - send(http_method, request_url, parameters) - end - should_respond_with success_code - should_respond_with_content_type_based_on_url(url) - should_be_a_valid_response_string_based_on_url(url) - should "login as the user" do - assert_equal @user, User.current - end - end - - context "with an invalid api token" do - setup do - @user = User.generate! do |user| - user.admin = true - end - @token = Token.create!(:user => @user, :action => 'feeds') - # Simple url parse to add on ?key= or &key= - request_url = if url.match(/\?/) - url + "&key=#{@token.value}" - else - url + "?key=#{@token.value}" - end - send(http_method, request_url, parameters) - end - should_respond_with failure_code - should_respond_with_content_type_based_on_url(url) - should "not login as the user" do - assert_equal User.anonymous, User.current - end - end - end - - context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do - setup do - @user = User.generate! do |user| - user.admin = true - end - @token = Token.create!(:user => @user, :action => 'api') - send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s}) - end - should_respond_with success_code - should_respond_with_content_type_based_on_url(url) - should_be_a_valid_response_string_based_on_url(url) - should "login as the user" do - assert_equal @user, User.current - end - end - end - - # Uses should_respond_with_content_type based on what's in the url: - # - # '/project/issues.xml' => should_respond_with_content_type :xml - # '/project/issues.json' => should_respond_with_content_type :json - # - # @param [String] url Request - def self.should_respond_with_content_type_based_on_url(url) - case - when url.match(/xml/i) - should "respond with XML" do - assert_equal 'application/xml', @response.content_type - end - when url.match(/json/i) - should "respond with JSON" do - assert_equal 'application/json', @response.content_type - end - else - raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}" - end - end - - # Uses the url to assert which format the response should be in - # - # '/project/issues.xml' => should_be_a_valid_xml_string - # '/project/issues.json' => should_be_a_valid_json_string - # - # @param [String] url Request - def self.should_be_a_valid_response_string_based_on_url(url) - case - when url.match(/xml/i) - should_be_a_valid_xml_string - when url.match(/json/i) - should_be_a_valid_json_string - else - raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}" - end - end - - # Checks that the response is a valid JSON string - def self.should_be_a_valid_json_string - should "be a valid JSON string (or empty)" do - assert(response.body.blank? || ActiveSupport::JSON.decode(response.body)) - end - end - - # Checks that the response is a valid XML string - def self.should_be_a_valid_xml_string - should "be a valid XML string" do - assert REXML::Document.new(response.body) - end - end - - def self.should_respond_with(status) - should "respond with #{status}" do - assert_response status - end - end - end - end -end - -# URL helpers do not work with config.threadsafe! -# https://github.com/rspec/rspec-rails/issues/476#issuecomment-4705454 -ActionView::TestCase::TestController.instance_eval do - helper Rails.application.routes.url_helpers -end -ActionView::TestCase::TestController.class_eval do - def _routes - Rails.application.routes - end -end +require 'rubygems' +# require 'spork' +#uncomment the following line to use spork with the debugger +#require 'spork/ext/ruby-debug' + +# Spork.prefork do +# # Loading more in this block will cause your tests to run faster. However, +# # if you change any configuration or code from libraries loaded here, you'll +# # need to restart spork for it take effect. +# ENV["RAILS_ENV"] = "test" +# require File.expand_path('../../config/environment', __FILE__) +# require 'rails/test_help' +# +# end +# +# Spork.each_run do +# # This code will be run each time you run your specs. +# +# end + +# --- Instructions --- +# Sort the contents of this file into a Spork.prefork and a Spork.each_run +# block. +# +# The Spork.prefork block is run only once when the spork server is started. +# You typically want to place most of your (slow) initializer code in here, in +# particular, require'ing any 3rd-party gems that you don't normally modify +# during development. +# +# The Spork.each_run block is run each time you run your specs. In case you +# need to load files that tend to change during development, require them here. +# With Rails, your application modules are loaded automatically, so sometimes +# this block can remain empty. +# +# Note: You can modify files loaded *from* the Spork.each_run block without +# restarting the spork server. However, this file itself will not be reloaded, +# so if you change any of the code inside the each_run block, you still need to +# restart the server. In general, if you have non-trivial code in this file, +# it's advisable to move it into a separate file so you can easily edit it +# without restarting spork. (For example, with RSpec, you could move +# non-trivial code into a file spec/support/my_helper.rb, making sure that the +# spec/support/* files are require'd from inside the each_run block.) +# +# Any code that is left outside the two blocks will be run during preforking +# *and* during each_run -- that's probably not what you want. +# +# These instructions should self-destruct in 10 seconds. If they don't, feel +# free to delete them. + + + + +# Redmine - project management software +# Copyright (C) 2006-2013 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#require 'shoulda' +ENV["RAILS_ENV"] = "test" +require File.expand_path(File.dirname(__FILE__) + "/../config/environment") +require 'rails/test_help' +require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s + +require File.expand_path(File.dirname(__FILE__) + '/object_helpers') +include ObjectHelpers + +class ActiveSupport::TestCase + include ActionDispatch::TestProcess + + self.use_transactional_fixtures = true + self.use_instantiated_fixtures = false + + def log_user(login, password) + User.anonymous + get "/login" + assert_equal nil, session[:user_id] + puts response.response_code() + assert_response :success + assert_template "account/login" + post "/login", :username => login, :password => password + assert_equal login, User.find(session[:user_id]).login + end + + def uploaded_test_file(name, mime) + fixture_file_upload("files/#{name}", mime, true) + end + + def credentials(user, password=nil) + {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)} + end + + # Mock out a file + def self.mock_file + file = 'a_file.png' + file.stubs(:size).returns(32) + file.stubs(:original_filename).returns('a_file.png') + file.stubs(:content_type).returns('image/png') + file.stubs(:read).returns(false) + file + end + + def mock_file + self.class.mock_file + end + + def mock_file_with_options(options={}) + file = '' + file.stubs(:size).returns(32) + original_filename = options[:original_filename] || nil + file.stubs(:original_filename).returns(original_filename) + content_type = options[:content_type] || nil + file.stubs(:content_type).returns(content_type) + file.stubs(:read).returns(false) + file + end + + # Use a temporary directory for attachment related tests + def set_tmp_attachments_directory + Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test") + unless File.directory?("#{Rails.root}/tmp/test/attachments") + Dir.mkdir "#{Rails.root}/tmp/test/attachments" + end + Attachment.storage_path = "#{Rails.root}/tmp/test/attachments" + end + + def set_fixtures_attachments_directory + Attachment.storage_path = "#{Rails.root}/test/fixtures/files" + end + + def with_settings(options, &block) + saved_settings = options.keys.inject({}) do |h, k| + h[k] = case Setting[k] + when Symbol, false, true, nil + Setting[k] + else + Setting[k].dup + end + h + end + options.each {|k, v| Setting[k] = v} + yield + ensure + saved_settings.each {|k, v| Setting[k] = v} if saved_settings + end + + # Yields the block with user as the current user + def with_current_user(user, &block) + saved_user = User.current + User.current = user + yield + ensure + User.current = saved_user + end + + def change_user_password(login, new_password) + user = User.first(:conditions => {:login => login}) + user.password, user.password_confirmation = new_password, new_password + user.save! + end + + def self.ldap_configured? + @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389) + return @test_ldap.bind + rescue Exception => e + # LDAP is not listening + return nil + end + + def self.convert_installed? + Redmine::Thumbnail.convert_available? + end + + # Returns the path to the test +vendor+ repository + def self.repository_path(vendor) + Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s + end + + # Returns the url of the subversion test repository + def self.subversion_repository_url + path = repository_path('subversion') + path = '/' + path unless path.starts_with?('/') + "file://#{path}" + end + + # Returns true if the +vendor+ test repository is configured + def self.repository_configured?(vendor) + File.directory?(repository_path(vendor)) + end + + def repository_path_hash(arr) + hs = {} + hs[:path] = arr.join("/") + hs[:param] = arr.join("/") + hs + end + + def assert_save(object) + saved = object.save + message = "#{object.class} could not be saved" + errors = object.errors.full_messages.map {|m| "- #{m}"} + message << ":\n#{errors.join("\n")}" if errors.any? + assert_equal true, saved, message + end + + def assert_error_tag(options={}) + assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options)) + end + + def assert_include(expected, s, message=nil) + assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"") + end + + def assert_not_include(expected, s) + assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\"" + end + + def assert_select_in(text, *args, &block) + d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root + assert_select(d, *args, &block) + end + + def assert_mail_body_match(expected, mail) + if expected.is_a?(String) + assert_include expected, mail_body(mail) + else + assert_match expected, mail_body(mail) + end + end + + def assert_mail_body_no_match(expected, mail) + if expected.is_a?(String) + assert_not_include expected, mail_body(mail) + else + assert_no_match expected, mail_body(mail) + end + end + + def mail_body(mail) + mail.parts.first.body.encoded + end +end + +module Redmine + module ApiTest + # Base class for API tests + class Base < ActionDispatch::IntegrationTest + # Test that a request allows the three types of API authentication + # + # * HTTP Basic with username and password + # * HTTP Basic with an api key for the username + # * Key based with the key=X parameter + # + # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) + # @param [String] url the request url + # @param [optional, Hash] parameters additional request parameters + # @param [optional, Hash] options additional options + # @option options [Symbol] :success_code Successful response code (:success) + # @option options [Symbol] :failure_code Failure response code (:unauthorized) + def self.should_allow_api_authentication(http_method, url, parameters={}, options={}) + should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options) + should_allow_http_basic_auth_with_key(http_method, url, parameters, options) + should_allow_key_based_auth(http_method, url, parameters, options) + end + + # Test that a request allows the username and password for HTTP BASIC + # + # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) + # @param [String] url the request url + # @param [optional, Hash] parameters additional request parameters + # @param [optional, Hash] options additional options + # @option options [Symbol] :success_code Successful response code (:success) + # @option options [Symbol] :failure_code Failure response code (:unauthorized) + def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={}) + success_code = options[:success_code] || :success + failure_code = options[:failure_code] || :unauthorized + + context "should allow http basic auth using a username and password for #{http_method} #{url}" do + context "with a valid HTTP authentication" do + setup do + @user = User.generate! do |user| + user.admin = true + user.password = 'my_password' + end + send(http_method, url, parameters, credentials(@user.login, 'my_password')) + end + + should_respond_with success_code + should_respond_with_content_type_based_on_url(url) + should "login as the user" do + assert_equal @user, User.current + end + end + + context "with an invalid HTTP authentication" do + setup do + @user = User.generate! + send(http_method, url, parameters, credentials(@user.login, 'wrong_password')) + end + + should_respond_with failure_code + should_respond_with_content_type_based_on_url(url) + should "not login as the user" do + assert_equal User.anonymous, User.current + end + end + + context "without credentials" do + setup do + send(http_method, url, parameters) + end + + should_respond_with failure_code + should_respond_with_content_type_based_on_url(url) + should "include_www_authenticate_header" do + assert @controller.response.headers.has_key?('WWW-Authenticate') + end + end + end + end + + # Test that a request allows the API key with HTTP BASIC + # + # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) + # @param [String] url the request url + # @param [optional, Hash] parameters additional request parameters + # @param [optional, Hash] options additional options + # @option options [Symbol] :success_code Successful response code (:success) + # @option options [Symbol] :failure_code Failure response code (:unauthorized) + def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={}) + success_code = options[:success_code] || :success + failure_code = options[:failure_code] || :unauthorized + + context "should allow http basic auth with a key for #{http_method} #{url}" do + context "with a valid HTTP authentication using the API token" do + setup do + @user = User.generate! do |user| + user.admin = true + end + @token = Token.create!(:user => @user, :action => 'api') + send(http_method, url, parameters, credentials(@token.value, 'X')) + end + should_respond_with success_code + should_respond_with_content_type_based_on_url(url) + should_be_a_valid_response_string_based_on_url(url) + should "login as the user" do + assert_equal @user, User.current + end + end + + context "with an invalid HTTP authentication" do + setup do + @user = User.generate! + @token = Token.create!(:user => @user, :action => 'feeds') + send(http_method, url, parameters, credentials(@token.value, 'X')) + end + should_respond_with failure_code + should_respond_with_content_type_based_on_url(url) + should "not login as the user" do + assert_equal User.anonymous, User.current + end + end + end + end + + # Test that a request allows full key authentication + # + # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) + # @param [String] url the request url, without the key=ZXY parameter + # @param [optional, Hash] parameters additional request parameters + # @param [optional, Hash] options additional options + # @option options [Symbol] :success_code Successful response code (:success) + # @option options [Symbol] :failure_code Failure response code (:unauthorized) + def self.should_allow_key_based_auth(http_method, url, parameters={}, options={}) + success_code = options[:success_code] || :success + failure_code = options[:failure_code] || :unauthorized + + context "should allow key based auth using key=X for #{http_method} #{url}" do + context "with a valid api token" do + setup do + @user = User.generate! do |user| + user.admin = true + end + @token = Token.create!(:user => @user, :action => 'api') + # Simple url parse to add on ?key= or &key= + request_url = if url.match(/\?/) + url + "&key=#{@token.value}" + else + url + "?key=#{@token.value}" + end + send(http_method, request_url, parameters) + end + should_respond_with success_code + should_respond_with_content_type_based_on_url(url) + should_be_a_valid_response_string_based_on_url(url) + should "login as the user" do + assert_equal @user, User.current + end + end + + context "with an invalid api token" do + setup do + @user = User.generate! do |user| + user.admin = true + end + @token = Token.create!(:user => @user, :action => 'feeds') + # Simple url parse to add on ?key= or &key= + request_url = if url.match(/\?/) + url + "&key=#{@token.value}" + else + url + "?key=#{@token.value}" + end + send(http_method, request_url, parameters) + end + should_respond_with failure_code + should_respond_with_content_type_based_on_url(url) + should "not login as the user" do + assert_equal User.anonymous, User.current + end + end + end + + context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do + setup do + @user = User.generate! do |user| + user.admin = true + end + @token = Token.create!(:user => @user, :action => 'api') + send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s}) + end + should_respond_with success_code + should_respond_with_content_type_based_on_url(url) + should_be_a_valid_response_string_based_on_url(url) + should "login as the user" do + assert_equal @user, User.current + end + end + end + + # Uses should_respond_with_content_type based on what's in the url: + # + # '/project/issues.xml' => should_respond_with_content_type :xml + # '/project/issues.json' => should_respond_with_content_type :json + # + # @param [String] url Request + def self.should_respond_with_content_type_based_on_url(url) + case + when url.match(/xml/i) + should "respond with XML" do + assert_equal 'application/xml', @response.content_type + end + when url.match(/json/i) + should "respond with JSON" do + assert_equal 'application/json', @response.content_type + end + else + raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}" + end + end + + # Uses the url to assert which format the response should be in + # + # '/project/issues.xml' => should_be_a_valid_xml_string + # '/project/issues.json' => should_be_a_valid_json_string + # + # @param [String] url Request + def self.should_be_a_valid_response_string_based_on_url(url) + case + when url.match(/xml/i) + should_be_a_valid_xml_string + when url.match(/json/i) + should_be_a_valid_json_string + else + raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}" + end + end + + # Checks that the response is a valid JSON string + def self.should_be_a_valid_json_string + should "be a valid JSON string (or empty)" do + assert(response.body.blank? || ActiveSupport::JSON.decode(response.body)) + end + end + + # Checks that the response is a valid XML string + def self.should_be_a_valid_xml_string + should "be a valid XML string" do + assert REXML::Document.new(response.body) + end + end + + def self.should_respond_with(status) + should "respond with #{status}" do + assert_response status + end + end + end + end +end + +# URL helpers do not work with config.threadsafe! +# https://github.com/rspec/rspec-rails/issues/476#issuecomment-4705454 +ActionView::TestCase::TestController.instance_eval do + helper Rails.application.routes.url_helpers +end +ActionView::TestCase::TestController.class_eval do + def _routes + Rails.application.routes + end +end From b1a60d31182fc72c19bfaf173de7b686695c9760 Mon Sep 17 00:00:00 2001 From: alanlong9278 <547533434@qq.com> Date: Tue, 26 May 2015 00:01:15 +0800 Subject: [PATCH 14/30] Signed-off-by: alanlong9278 <547533434@qq.com> --- .gitignore | 2 +- config/additional_environment.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 config/additional_environment.rb diff --git a/.gitignore b/.gitignore index ffa4a1bc7..5810401cb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ *.swp /config/database.yml /config/configuration.yml -/config/additional_environment.rb + /files/* /log/* /public/tmp/* diff --git a/config/additional_environment.rb b/config/additional_environment.rb new file mode 100644 index 000000000..5c73f6aab --- /dev/null +++ b/config/additional_environment.rb @@ -0,0 +1,3 @@ +if Rails.env.production? + config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', { expires_in: 90.minutes } +end \ No newline at end of file From f52058aaf38fa3feb61c244bcaa6a45ee3306fa4 Mon Sep 17 00:00:00 2001 From: huang Date: Tue, 26 May 2015 09:37:29 +0800 Subject: [PATCH 15/30] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E6=96=B0=E7=95=8C=E9=9D=A2=EF=BC=88=E6=9C=AA=E5=AE=8C=E6=88=90?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/welcome_controller.rb | 1 + app/views/layouts/base.html.erb | 4 ++-- app/views/layouts/base_welcome.html.erb | 23 ++++++++--------------- app/views/welcome/index.html.erb | 4 ++-- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 6e067fb83..787b1b050 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class WelcomeController < ApplicationController + layout "base_welcome" include ApplicationHelper include WelcomeHelper helper :project_score diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 439c5f7b2..483cabac5 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -12,7 +12,7 @@ <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %> <%= javascript_heads %> <%= javascript_include_tag "jquery.leanModal.min" %> -<%= javascript_include_tag 'seems_rateable/jRating', 'seems_rateable/rateable'%> +<%= javascript_include_tag 'seems_rateable/jRating', 'seems_rateable/rateable'%> <%= heads_for_theme %> <%= call_hook :view_layouts_base_html_head %> @@ -31,7 +31,7 @@
      <%=render :partial => 'layouts/base_footer'%>
      - +
      diff --git a/app/views/layouts/base_welcome.html.erb b/app/views/layouts/base_welcome.html.erb index d04f492ef..6d3b900c6 100644 --- a/app/views/layouts/base_welcome.html.erb +++ b/app/views/layouts/base_welcome.html.erb @@ -5,10 +5,9 @@ <%=h html_title %> - <%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'application', 'nyan', :media => 'all' %> - <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %> + <%= stylesheet_link_tag 'public', 'pleft', 'project', :media => 'all' %> + <%= javascript_include_tag "jquery.leanModal.min" %> - <%= javascript_include_tag 'seems_rateable/jRating', 'seems_rateable/rateable'%> <%= csrf_meta_tag %> <%= favicon %> @@ -18,32 +17,26 @@ <%= yield :header_tags -%> - -
      -
      -
      - <%=render :partial => 'layouts/base_header'%> + +
      + <%= render :partial => 'layouts/new_header' %> +
      <%= render_flash_messages %> <%= yield %> <%= call_hook :view_layouts_base_content %>
      - <%=render :partial => 'layouts/base_footer'%> + <%=render :partial => 'layouts/new_footer'%>
      - -
      -
      <%= call_hook :view_layouts_base_body_bottom %> diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index dc8ef7f35..0cd9622a5 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -23,7 +23,7 @@ $(document).ready(function($) { $("#loggedas").find("a").attr("target", "_blank"); //$("#content .tabs_new~ .pagination").find("a").removeAttr("target"); - }); + });
      @@ -45,7 +45,7 @@ <% if @organization.nil? %> <% unless @first_page.nil? %> <%= l(:label_welcome_trustie_project)%><%= l(:label_welcome_trustie_project_description)%> From 0b6f35055dd977931ef9a985f48dd80fde31e136 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Tue, 26 May 2015 17:44:39 +0800 Subject: [PATCH 16/30] Signed-off-by: alan <547533434@qq.com> --- app/views/layouts/_user_courses_list.html.erb | 2 +- app/views/layouts/base_projects.html.erb | 4 + .../projects/_development_group.html.erb | 73 ++++++++++--------- app/views/projects/_research_team.html.erb | 3 +- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/app/views/layouts/_user_courses_list.html.erb b/app/views/layouts/_user_courses_list.html.erb index 250ab1d5f..29366eb0e 100644 --- a/app/views/layouts/_user_courses_list.html.erb +++ b/app/views/layouts/_user_courses_list.html.erb @@ -3,7 +3,7 @@ <%=link_to l(:label_my_course), user_courses_user_path(User.current.id) %>
        <% course_index = 0 %> - <% User.current.courses.each do |course| %> + <% cache User.current.courses.each do |course| %> <% if !course_endTime_timeout?(course) %> <%= render :partial => 'layouts/user_homework_list', :locals => {:course => course,:course_index => course_index} %> <% course_index += 1 %> diff --git a/app/views/layouts/base_projects.html.erb b/app/views/layouts/base_projects.html.erb index beade0a7a..73fe7b6a8 100644 --- a/app/views/layouts/base_projects.html.erb +++ b/app/views/layouts/base_projects.html.erb @@ -70,6 +70,7 @@
        + <%= render :partial => 'layouts/new_header'%>
        @@ -103,6 +104,7 @@ <% end %>
      +
      @@ -165,6 +167,7 @@ <% end %> +
      <% if @project.project_new_type == 1 || @project.project_new_type.nil? %> <%= render :partial => 'projects/development_group', :locals => {:project => @project}%> @@ -174,6 +177,7 @@ <%= render :partial => 'projects/friend_group', :locals => {:project => @project}%> <% end %>
      +
      diff --git a/app/views/projects/_development_group.html.erb b/app/views/projects/_development_group.html.erb index 676761831..9e21c640b 100644 --- a/app/views/projects/_development_group.html.erb +++ b/app/views/projects/_development_group.html.erb @@ -1,52 +1,57 @@ -<% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %> +<% cache @project do %> + <% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %> - + <% end %> <% unless @project.enabled_modules.where("name = 'boards'").empty? %> - + <% end%> <% unless @project.enabled_modules.where("name = 'files'").empty? %> - + + + <% end %> <%# --版本库被设置成私有、module中设置不显示、没有创建版本库 三种情况不显示-- %> <% if visible_repository?(@project) %> - + <% end %> \ No newline at end of file + +<% end %> \ No newline at end of file diff --git a/app/views/projects/_research_team.html.erb b/app/views/projects/_research_team.html.erb index b2b0e3c33..21a6ab31c 100644 --- a/app/views/projects/_research_team.html.erb +++ b/app/views/projects/_research_team.html.erb @@ -1,3 +1,4 @@ +<% cache @project %> <% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %> -<% end%> \ No newline at end of file +<% end%> From 1b5c41b3ad696d3f0fce9ef569ef553f7adaf53e Mon Sep 17 00:00:00 2001 From: huang Date: Wed, 27 May 2015 17:40:18 +0800 Subject: [PATCH 17/30] =?UTF-8?q?=E9=82=AE=E4=BB=B6=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/welcome_controller.rb | 2 +- app/services/users_service.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 787b1b050..d570c238e 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class WelcomeController < ApplicationController - layout "base_welcome" + # layout "base_welcome" include ApplicationHelper include WelcomeHelper helper :project_score diff --git a/app/services/users_service.rb b/app/services/users_service.rb index 7d7976bb5..1121c98b4 100644 --- a/app/services/users_service.rb +++ b/app/services/users_service.rb @@ -62,7 +62,7 @@ class UsersService else @user.password = "" end - @user = automatically_register(@user) + @user = automatically_register_lock(@user) if @user.id != nil ue = @user.user_extensions ||= UserExtensions.new ue.user_id = @user.id From d2720d8fb8ea925d1214f2fa553244f5fc1170d7 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Wed, 27 May 2015 17:40:46 +0800 Subject: [PATCH 18/30] Signed-off-by: alan <547533434@qq.com> --- app/views/projects/_development_group.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/_development_group.html.erb b/app/views/projects/_development_group.html.erb index 9e21c640b..032c8192d 100644 --- a/app/views/projects/_development_group.html.erb +++ b/app/views/projects/_development_group.html.erb @@ -1,4 +1,4 @@ -<% cache @project do %> +<% cache 'develop' do %>
      diff --git a/app/views/layouts/_new_feedback.html.erb b/app/views/layouts/_new_feedback.html.erb index 67b4af32c..3b8098ed5 100644 --- a/app/views/layouts/_new_feedback.html.erb +++ b/app/views/layouts/_new_feedback.html.erb @@ -22,10 +22,9 @@ <% end %>
      diff --git a/config/locales/commons/zh.yml b/config/locales/commons/zh.yml index 9ba8cba7a..a023bc8cb 100644 --- a/config/locales/commons/zh.yml +++ b/config/locales/commons/zh.yml @@ -353,7 +353,7 @@ zh: # label_feedback: 意见反馈 label_feedback_tips: "欢迎反馈网站问题,课程中遇到的问题请反馈给相关老师!" - label_technical_support: "技术支持:" + label_technical_support: "QQ 在线支持:" label_feedback_success: "您的意见已经反馈到公共贴吧的新手讨论吧,我们会第一时间解决您的问题,谢谢支持!" label_feedback_value: "该帖来自用户反馈:)" diff --git a/public/stylesheets/public.css b/public/stylesheets/public.css index 6961b23c8..c8d18609f 100644 --- a/public/stylesheets/public.css +++ b/public/stylesheets/public.css @@ -287,7 +287,8 @@ html{ overflow-x:hidden;} .close_btn span { display:none;} .side_center .custom_service p { text-align:center; padding:6px 0; margin:0; vertical-align:middle;} .msgserver { margin-top:5px;} -.msgserver a { background:url(../images/sidebar_bg.png) no-repeat -119px -112px; padding-left:22px; height:21px; display:block; } +/*.msgserver a { background:url(../images/sidebar_bg.png) no-repeat -119px -112px; padding-left:22px; height:21px; display:block; }*/ +.msgserver a { padding-left:4px; height:21px; display:block; } .opnionText{box-shadow:none; width:122px; height:180px; border-color: #DFDFDF; background:#fff; color:#999; padding:3px; font-size:12px;overflow:auto; background-attachment:fixed;border-style:solid;} a.opnionButton{ display:block; background:#15bccf; width:130px; height:23px; margin-top:5px; text-align:center; padding-top:3px;} a:hover.opnionButton{background: #0fa9bb; } From 065c196edc8c0e91ca41a4289a074ce7d369a255 Mon Sep 17 00:00:00 2001 From: yutao <283765470@qq.com> Date: Thu, 28 May 2015 16:18:48 +0800 Subject: [PATCH 22/30] ... --- public/javascripts/project.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/javascripts/project.js b/public/javascripts/project.js index f9f88703d..918c438e3 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -419,7 +419,7 @@ $(function(){ cookiesave(personalized_expand_key,JSON.stringify(personalized_map)); target.toggle(timeout); } - $("*[nhtype='toggle4cookie']").click(function(){ + $("*[nhtype='toggle4cookie']").live('click',function(){ personalized_click($(this),500); }); From ad99cb8535468af88bd0103ca3a699afd996fedd Mon Sep 17 00:00:00 2001 From: lizanle <491823689@qq.com> Date: Thu, 28 May 2015 17:51:50 +0800 Subject: [PATCH 23/30] =?UTF-8?q?=E4=B8=8E=E6=88=91=E7=9B=B8=E5=85=B3=20?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E7=9B=B8=E5=85=B3=E7=9A=84=E8=AF=A6=E7=BB=86?= =?UTF-8?q?=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/mobile/apis/comments.rb | 13 +++++++ app/api/mobile/apis/users.rb | 14 ++++++++ app/api/mobile/entities/jours.rb | 10 ++++++ app/services/comment_service.rb | 13 +++++++ app/services/users_service.rb | 60 +++++++++++++++++++++++++++----- 5 files changed, 102 insertions(+), 8 deletions(-) diff --git a/app/api/mobile/apis/comments.rb b/app/api/mobile/apis/comments.rb index edc7bcf54..544ebf0ce 100644 --- a/app/api/mobile/apis/comments.rb +++ b/app/api/mobile/apis/comments.rb @@ -99,6 +99,19 @@ module Mobile present :status, 0 end + desc '留言详情' + params do + requires :token, type: String + requires :comment_parent_id,type:Integer,desc:'留言id' + optional :course_id,type:Integer,desc:'课程id' + end + get ':comment_parent_id/comment_details' do + cs = CommentService.new + jour = cs.comment_detail params,current_user + present :data, jour, with: Mobile::Entities::Jours + present :status, 0 + end + end end end diff --git a/app/api/mobile/apis/users.rb b/app/api/mobile/apis/users.rb index 96b788dab..583a130d1 100644 --- a/app/api/mobile/apis/users.rb +++ b/app/api/mobile/apis/users.rb @@ -115,6 +115,8 @@ module Mobile requires :ref_user_id,type:Integer,desc:'被回复的用户id' requires :parent_id,type:Integer,desc:'留言父id' requires :ref_message_id,type:Integer,desc:'引用消息id' + optional :type,type:Integer,desc:'回复类型' + optional :course_id,type:Integer,desc:'课程id' end post ':user_id/reply_message' do us = UsersService.new @@ -133,6 +135,18 @@ module Mobile us.leave_message params,current_user present :data,0 end + + desc "与我相关" + params do + requires :token, type: String + requires :page,type:Integer,desc:'页码' + end + get ':user_id/all_my_dynamic' do + us = UsersService.new + my_jours = us.reply_my_messages params,current_user + present :data,my_jours,with:Mobile::Entities::Jours + present :status,0 + end end end end diff --git a/app/api/mobile/entities/jours.rb b/app/api/mobile/entities/jours.rb index 10fd0f893..97eabd21f 100644 --- a/app/api/mobile/entities/jours.rb +++ b/app/api/mobile/entities/jours.rb @@ -14,6 +14,11 @@ module Mobile else f.send(field) end + else + case f + when :course_name + f[:jour_type] == "Course" ? f.course.name : "" + end end end end @@ -27,6 +32,11 @@ module Mobile jours_expose :notes jours_expose :m_reply_id jours_expose :m_parent_id + expose :course,using:Mobile::Entities::Course do |f,opt| + if f.is_a?(::JournalsForMessage) && f[:jour_type] == "Course" + f.course + end + end expose :reply_user,using: Mobile::Entities::User do |f, opt| f.at_user end diff --git a/app/services/comment_service.rb b/app/services/comment_service.rb index f75e14b85..a742d0eee 100644 --- a/app/services/comment_service.rb +++ b/app/services/comment_service.rb @@ -101,4 +101,17 @@ class CommentService @jours end + def comment_detail params,current_user + if !params[:course_id].nil? && params[:course_id] != 0 + course = Course.find(params[:course_id]) + jour = course.journals_for_messages.where("id = ? ",params[:comment_parent_id]) + jour + else + jour1 = JournalsForMessage.where("id = ? ",params[:comment_parent_id]) + jour1 + end + end + + + end \ No newline at end of file diff --git a/app/services/users_service.rb b/app/services/users_service.rb index 7d7976bb5..77cebe0b1 100644 --- a/app/services/users_service.rb +++ b/app/services/users_service.rb @@ -169,19 +169,26 @@ class UsersService # 回复用户 def reply_user_messages params,current_user user = User.find(params[:user_id]) - parent_id = params[:parent_id] + + m_parent_id = params[:parent_id] author_id = current_user.id - reply_user_id = params[:ref_user_id] - reply_id = params[:ref_message_id] + reply_id = params[:ref_user_id] + ref_message_id = params[:ref_message_id] content = params[:content] - options = {:user_id => author_id, + options = {:user_id => author_id, # 作者id :status => true, - :m_parent_id => parent_id, - :m_reply_id => reply_id, - :reply_id => reply_user_id, + :m_parent_id => m_parent_id,# 父留言id + :m_reply_id => ref_message_id, # 子留言 id + :reply_id => reply_id, # 被留言用户id :notes => content, :is_readed => false} - user.add_jour(nil, nil,nil,options) + if(params[:type] == 1) + user.add_jour(nil, nil,nil,options) + elsif(params[:type] == 2) + Course.find(params[:course_id]).journals_for_messages.build(options).save! unless params[:course_id].nil? + else + end + end # 给用户留言 @@ -258,4 +265,41 @@ class UsersService scope end + # 课程留言中与我相关的回复 + def my_course_messages params,current_user + #找到我所有的课程 + @user = current_user + if !current_user.admin? && !@user.active? + raise '404' + return + end + if current_user == @user || current_user.admin? + membership = @user.coursememberships.all + end + # membership.sort! {|older, newer| newer.created_on <=> older.created_on } + message_list = [] + membership.each do |mp| + #课程轮询找到与我相关的回复 + message_list << mp.course.journals_for_messages.where("reply_id = ?",current_user.id) + end + message_list + end + + # 获取与我相关的留言:我的留言,回复我的留言 + def my_personal_messages params,current_user + jours = current_user.journals_for_messages.where('m_parent_id is null or reply_id = ?',current_user.id) + jours.update_all(:is_readed => true, :status => false) + jours + end + + def reply_my_messages params,current_user + jours = my_personal_messages params,current_user + jours1 = my_course_messages params,current_user + my_jours = [] + my_jours << jours << jours1 + my_jours.flatten!.sort! {|older, newer| newer.created_on <=> older.created_on } + my_jours_arr = Kaminari.paginate_array(my_jours, total_count: my_jours.count).page(params[:page] || 1).per(10) + my_jours_arr + end + end From 6835fb29cd6e636011befb04966ad070aeb90be2 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Fri, 29 May 2015 10:34:04 +0800 Subject: [PATCH 24/30] Signed-off-by: alan <547533434@qq.com> --- app/views/welcome/course.html.erb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/views/welcome/course.html.erb b/app/views/welcome/course.html.erb index cbceec2c7..9e29dc1ef 100644 --- a/app/views/welcome/course.html.erb +++ b/app/views/welcome/course.html.erb @@ -129,6 +129,7 @@ <%# User.current.logged? ? course_count = 9 : course_count = 10 %> <% course_count = 9 %> <% all_new_hot_course = find_all_new_hot_course(course_count, @school_id, year_now, course_term)%> + <% while all_new_hot_course.count < course_count%> <% if course_term == "春季学期" year_now -= 1 @@ -140,9 +141,11 @@ <% all_new_hot_course += find_all_new_hot_course(course_count-all_new_hot_course.count, @school_id, year_now, course_term)%> <% end%> <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> +
      <% else %> + <% if cur_school_course.count < 9 %> <%= render :partial => 'more_course', :locals => {:school_id => nil}%> @@ -160,6 +163,7 @@ <%= render :partial => 'no_course_title', :locals => {:course_title => l(:label_school_less_course)} %> <% all_new_hot_course = find_all_new_hot_course(9-cur_school_course.count, @school_id, year_now, course_term)%> + <% while (all_new_hot_course.count + cur_school_course.count) < 9%> <% if course_term == "春季学期" year_now -= 1 @@ -171,9 +175,11 @@ <% all_new_hot_course += find_all_new_hot_course(9-(all_new_hot_course.count + cur_school_course.count), @school_id, year_now, course_term)%> <% end%> <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> + <% end %>
      + <% end %> From a76b345495fd8b5f8a9a326381471630aaac47f3 Mon Sep 17 00:00:00 2001 From: alan <547533434@qq.com> Date: Fri, 29 May 2015 11:40:12 +0800 Subject: [PATCH 25/30] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20Signed-off-by:=20alan=20<547533434@qq.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/welcome/course.html.erb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/views/welcome/course.html.erb b/app/views/welcome/course.html.erb index 9e29dc1ef..476471897 100644 --- a/app/views/welcome/course.html.erb +++ b/app/views/welcome/course.html.erb @@ -140,8 +140,9 @@ <%break if Time.new.strftime("%Y").to_i - year_now >= 2%> <% all_new_hot_course += find_all_new_hot_course(course_count-all_new_hot_course.count, @school_id, year_now, course_term)%> <% end%> - <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> - + <% cache all_new_hot_course.max().created_at do %> + <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> + <% end %> <% else %> @@ -174,8 +175,9 @@ <%break if Time.new.strftime("%Y").to_i - year_now >= 2%> <% all_new_hot_course += find_all_new_hot_course(9-(all_new_hot_course.count + cur_school_course.count), @school_id, year_now, course_term)%> <% end%> - <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> - + <% cache all_new_hot_course.max().created_at do %> + <%= render :partial => 'course_list', :locals => {:course_list => all_new_hot_course} %> + <% end %> <% end %> @@ -192,10 +194,12 @@ <%= link_to "更多>>", forums_path %> - + <% topics = find_new_forum_topics(10) %> + <%# cache topics.maximum(:created_at) do%>
        - <% find_new_forum_topics(10).each do |topic| %> + + <% topics.each do |topic| %>
      • <% end %> +
      + <%# end %>
      From 849af9b04b9135f77ff6f356695676365985c79f Mon Sep 17 00:00:00 2001 From: lizanle <491823689@qq.com> Date: Fri, 29 May 2015 14:22:43 +0800 Subject: [PATCH 26/30] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8A=E6=8B=89=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/mobile/apis/comments.rb | 1 + app/services/comment_service.rb | 2 +- app/services/users_service.rb | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/api/mobile/apis/comments.rb b/app/api/mobile/apis/comments.rb index 544ebf0ce..86132a93a 100644 --- a/app/api/mobile/apis/comments.rb +++ b/app/api/mobile/apis/comments.rb @@ -91,6 +91,7 @@ module Mobile desc '课程留言列表' params do optional :token, type: String + optional :page,type:Integer,desc:'页数' end get ':id/course_message' do cs = CommentService.new diff --git a/app/services/comment_service.rb b/app/services/comment_service.rb index a742d0eee..2464297da 100644 --- a/app/services/comment_service.rb +++ b/app/services/comment_service.rb @@ -94,7 +94,7 @@ class CommentService def course_messages params,current_user @course = ::Course.find(params[:id]) if (current_user.admin? || @course.is_public == 1 || (@course.is_public == 0 && current_user.member_of_course?(@course))) - @jours = @course.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC') + @jours = @course.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC').page(params[:page] ||= 1).per(10) else raise '403' end diff --git a/app/services/users_service.rb b/app/services/users_service.rb index 77cebe0b1..bd85e3340 100644 --- a/app/services/users_service.rb +++ b/app/services/users_service.rb @@ -292,6 +292,7 @@ class UsersService jours end + # 所有的与我相关 def reply_my_messages params,current_user jours = my_personal_messages params,current_user jours1 = my_course_messages params,current_user From d9ae9c80614943f4983a8c06f38000cdf5cbf4a1 Mon Sep 17 00:00:00 2001 From: huang Date: Fri, 29 May 2015 14:36:44 +0800 Subject: [PATCH 27/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=82=AE=E4=BB=B6?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=8F=90=E9=86=92=EF=BC=88=E9=82=80=E8=AF=B7?= =?UTF-8?q?=EF=BC=9A=E6=9C=AA=E6=BF=80=E6=B4=BB=20=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=EF=BC=9A=E6=BF=80=E6=B4=BB=E5=B9=B6=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E9=A1=B9=E7=9B=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/projects_controller.rb | 16 ++++++++++++++-- app/models/mailer.rb | 4 ++-- config/locales/projects/zh.yml | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b9e46daee..b8764cc48 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -248,8 +248,20 @@ class ProjectsController < ApplicationController # 2、加入项目、创建角色 # 3、用户得分 if params[:mail] - Member.create(:role_ids => [4], :user_id => params[:user],:project_id => params[:id]) - UserGrade.create(:user_id =>params[:user], :project_id => params[:id]) + user = User.find(params[:user_id]) + user.activate! + Member.create(:role_ids => [4], :user_id => params[:user_id],:project_id => params[:id]) + UserGrade.create(:user_id => params[:user_id], :project_id => params[:id]) + token = Token.get_token_from_user(user, 'autologin') + #user = User.try_to_autologin(token.value) + if user + start_user_session(user) + user.save + redirect_to project_member_path(params[:id]) + return + # account_ project_member_path(params[:id]) + flash[:notice] = l(:label_mail_invite_success) + end end if params[:jump] && redirect_to_project_menu_item(@project, params[:jump]) return diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 2c3a94874..4018f44a9 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -60,8 +60,8 @@ class Mailer < ActionMailer::Base user = us.register_auto(login, @email, @password) User.current = user unless User.current.nil? @user = user - @token = Token.get_token_from_user(user, 'autologin') - @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user => user.id, :mail => true, :token => @token.value) + + @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user_id => user.id, :mail => true) mail :to => email, :subject => @subject end diff --git a/config/locales/projects/zh.yml b/config/locales/projects/zh.yml index 180b0322a..8ca078084 100644 --- a/config/locales/projects/zh.yml +++ b/config/locales/projects/zh.yml @@ -342,6 +342,7 @@ zh: label_invite_trustie_user_tips: "输入姓名、邮箱、昵称" label_user_role_null: 用户和角色不能留空! label_invite_project: 邀请您加入项目 + label_mail_invite_success: 您已成功加入项目! label_invite_success: 邀请成功 label_invite_members: 邀请用户 # From ee7c1eff32e6cdd8ecb3acd48385b9c55b0f1314 Mon Sep 17 00:00:00 2001 From: huang Date: Fri, 29 May 2015 14:50:27 +0800 Subject: [PATCH 28/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B7=B2=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E7=94=A8=E6=88=B7=E9=82=AE=E4=BB=B6=E9=82=80=E8=AF=B7?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/mailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 4018f44a9..2760af323 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -73,7 +73,7 @@ class Mailer < ActionMailer::Base @project_name = "#{project.name}" @user = user @token = Token.get_token_from_user(user, 'autologin') - @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user => user.id, :mail => true, :token => @token.value) + @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user_id => user.id, :mail => true, :token => @token.value) mail :to => email, :subject => @subject end From 697f891546a9be1772bc700587d3da7e87535365 Mon Sep 17 00:00:00 2001 From: huang Date: Fri, 29 May 2015 16:04:21 +0800 Subject: [PATCH 29/30] =?UTF-8?q?=E7=A7=81=E6=9C=89=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=E9=82=80=E8=AF=B7=E6=9D=83=E9=99=90=E8=AE=A4?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/projects_controller.rb | 41 +++++++++++++------------- app/models/mailer.rb | 5 ++-- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b8764cc48..fbafd16e9 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -243,26 +243,7 @@ class ProjectsController < ApplicationController # Author lizanle # Description 项目动态展示方法,删除了不必要的代码 def show - # params[:login]为邮箱邀请用户加入,主要功能: - # 1、自动注册 - # 2、加入项目、创建角色 - # 3、用户得分 - if params[:mail] - user = User.find(params[:user_id]) - user.activate! - Member.create(:role_ids => [4], :user_id => params[:user_id],:project_id => params[:id]) - UserGrade.create(:user_id => params[:user_id], :project_id => params[:id]) - token = Token.get_token_from_user(user, 'autologin') - #user = User.try_to_autologin(token.value) - if user - start_user_session(user) - user.save - redirect_to project_member_path(params[:id]) - return - # account_ project_member_path(params[:id]) - flash[:notice] = l(:label_mail_invite_success) - end - end + if params[:jump] && redirect_to_project_menu_item(@project, params[:jump]) return end @@ -411,6 +392,26 @@ class ProjectsController < ApplicationController # by young # include CoursesHelper def member + # params[:login]为邮箱邀请用户加入,主要功能: + # 1、自动注册 + # 2、加入项目、创建角色 + # 3、用户得分 + if params[:mail] + user = User.find(params[:user_id]) + user.activate! + Member.create(:role_ids => [4], :user_id => params[:user_id],:project_id => params[:id]) + UserGrade.create(:user_id => params[:user_id], :project_id => params[:id]) + token = Token.get_token_from_user(user, 'autologin') + #user = User.try_to_autologin(token.value) + if user + start_user_session(user) + user.save + redirect_to project_member_path(params[:id]) + return + # account_ project_member_path(params[:id]) + flash[:notice] = l(:label_mail_invite_success) + end + end ## 有角色参数的才是课程,没有的就是项目 @render_file = 'project_member_list' # 判断是否课程 diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 2760af323..dbc5d3cff 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -61,7 +61,7 @@ class Mailer < ActionMailer::Base User.current = user unless User.current.nil? @user = user - @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user_id => user.id, :mail => true) + @project_url = url_for(:controller => 'projects', :action => 'member', :id => project.id, :user_id => user.id, :mail => true) mail :to => email, :subject => @subject end @@ -72,8 +72,9 @@ class Mailer < ActionMailer::Base @invitor_name = "#{invitor.name}" @project_name = "#{project.name}" @user = user + @project = project @token = Token.get_token_from_user(user, 'autologin') - @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user_id => user.id, :mail => true, :token => @token.value) + @project_url = url_for(:controller => 'projects', :action => 'member', :id => project.id, :user_id => user.id, :mail => true, :token => @token.value) mail :to => email, :subject => @subject end From 7197c33be4d552d68f3787c833a4b31d301bf7a4 Mon Sep 17 00:00:00 2001 From: huang Date: Fri, 29 May 2015 16:07:57 +0800 Subject: [PATCH 30/30] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=8E=89=E6=9A=82?= =?UTF-8?q?=E6=97=B6=E6=9C=AA=E5=AE=8C=E6=88=90=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/invite_list.rb | 4 ++-- app/models/project.rb | 2 +- app/models/user.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/invite_list.rb b/app/models/invite_list.rb index 605c35a07..f1ba8546f 100644 --- a/app/models/invite_list.rb +++ b/app/models/invite_list.rb @@ -1,5 +1,5 @@ class InviteList < ActiveRecord::Base attr_accessible :project_id, :user_id - belongs_to :user - belongs_to :project + # belongs_to :user + # belongs_to :project end diff --git a/app/models/project.rb b/app/models/project.rb index 249df8640..bf94df248 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -67,7 +67,7 @@ class Project < ActiveRecord::Base has_many :student, :through => :students_for_courses, :source => :user has_one :course_extra, :class_name => 'Course', :foreign_key => :extra,:primary_key => :identifier, :dependent => :destroy has_many :applied_projects - has_many :invite_lists + # has_many :invite_lists # end #ADDED BY NIE diff --git a/app/models/user.rb b/app/models/user.rb index fa3134a58..4c30012d7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -126,7 +126,7 @@ class User < Principal # end # 邮件邀请状态 - has_many :invite_lists + # has_many :invite_lists # end ######added by nie