diff --git a/Gemfile b/Gemfile index 9d0ef7f..0fd931b 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://gems.ruby-china.com' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '5.0.0' +gem 'rails', '5.2.2' # Use mysql2 as the database for Active Record gem 'mysql2' # Use SCSS for stylesheets @@ -48,7 +48,7 @@ group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' gem 'rspec-rails' - gem 'factory_girl_rails' + gem 'factory_bot_rails' gem 'database_cleaner' gem 'letter_opener' end @@ -61,6 +61,5 @@ group :development do gem 'guard-livereload' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' - gem 'rack-mini-profiler' end diff --git a/Gemfile.lock b/Gemfile.lock index 400c792..9f47332 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,41 +1,45 @@ GEM remote: https://gems.ruby-china.com/ specs: - actioncable (5.0.0) - actionpack (= 5.0.0) - nio4r (~> 1.2) - websocket-driver (~> 0.6.1) - actionmailer (5.0.0) - actionpack (= 5.0.0) - actionview (= 5.0.0) - activejob (= 5.0.0) + actioncable (5.2.2) + actionpack (= 5.2.2) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.2) + actionpack (= 5.2.2) + actionview (= 5.2.2) + activejob (= 5.2.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.0.0) - actionview (= 5.0.0) - activesupport (= 5.0.0) + actionpack (5.2.2) + actionview (= 5.2.2) + activesupport (= 5.2.2) rack (~> 2.0) - rack-test (~> 0.6.3) + rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.0) - activesupport (= 5.0.0) + actionview (5.2.2) + activesupport (= 5.2.2) builder (~> 3.1) - erubis (~> 2.7.0) + erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (5.0.0) - activesupport (= 5.0.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.2) + activesupport (= 5.2.2) globalid (>= 0.3.6) - activemodel (5.0.0) - activesupport (= 5.0.0) - activerecord (5.0.0) - activemodel (= 5.0.0) - activesupport (= 5.0.0) - arel (~> 7.0) - activesupport (5.0.0) + activemodel (5.2.2) + activesupport (= 5.2.2) + activerecord (5.2.2) + activemodel (= 5.2.2) + activesupport (= 5.2.2) + arel (>= 9.0) + activestorage (5.2.2) + actionpack (= 5.2.2) + activerecord (= 5.2.2) + marcel (~> 0.3.1) + activesupport (5.2.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) + i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.6.0) @@ -43,7 +47,7 @@ GEM annotate (2.7.4) activerecord (>= 3.2, < 6.0) rake (>= 10.4, < 13.0) - arel (7.1.4) + arel (9.0.0) bcrypt (3.1.12) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) @@ -71,13 +75,14 @@ GEM em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) + erubi (1.8.0) erubis (2.7.0) eventmachine (1.2.7) execjs (2.7.0) - factory_girl (4.9.0) + factory_bot (4.11.1) activesupport (>= 3.0.0) - factory_girl_rails (4.9.0) - factory_girl (~> 4.9.0) + factory_bot_rails (4.11.1) + factory_bot (~> 4.11.1) railties (>= 3.0.0) ffi (1.10.0) formatador (0.2.5) @@ -117,7 +122,7 @@ GEM nokogiri (>= 1.6.0) ruby_parser (~> 3.5) http_parser.rb (0.6.0) - i18n (0.9.5) + i18n (1.5.3) concurrent-ruby (~> 1.0) jbuilder (2.8.0) activesupport (>= 4.2.0) @@ -141,14 +146,17 @@ GEM lumberjack (1.0.13) mail (2.7.1) mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) method_source (0.9.2) + mimemagic (0.3.3) mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) multi_json (1.13.1) mysql2 (0.5.2) nenv (0.3.0) - nio4r (1.2.1) + nio4r (2.3.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) notiffany (0.1.1) @@ -161,33 +169,32 @@ GEM public_suffix (3.0.3) puma (3.12.0) rack (2.0.6) - rack-mini-profiler (1.0.1) - rack (>= 1.2.0) - rack-test (0.6.3) - rack (>= 1.0) - rails (5.0.0) - actioncable (= 5.0.0) - actionmailer (= 5.0.0) - actionpack (= 5.0.0) - actionview (= 5.0.0) - activejob (= 5.0.0) - activemodel (= 5.0.0) - activerecord (= 5.0.0) - activesupport (= 5.0.0) - bundler (>= 1.3.0, < 2.0) - railties (= 5.0.0) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.2) + actioncable (= 5.2.2) + actionmailer (= 5.2.2) + actionpack (= 5.2.2) + actionview (= 5.2.2) + activejob (= 5.2.2) + activemodel (= 5.2.2) + activerecord (= 5.2.2) + activestorage (= 5.2.2) + activesupport (= 5.2.2) + bundler (>= 1.3.0) + railties (= 5.2.2) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - railties (5.0.0) - actionpack (= 5.0.0) - activesupport (= 5.0.0) + railties (5.2.2) + actionpack (= 5.2.2) + activesupport (= 5.2.2) method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rake (12.3.2) rb-fsevent (0.10.3) rb-inotify (0.10.0) @@ -258,7 +265,7 @@ GEM binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) - websocket-driver (0.6.5) + websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -271,7 +278,7 @@ DEPENDENCIES coffee-rails database_cleaner devise - factory_girl_rails + factory_bot_rails gon guard guard-livereload @@ -283,8 +290,7 @@ DEPENDENCIES letter_opener mysql2 puma - rack-mini-profiler - rails (= 5.0.0) + rails (= 5.2.2) rspec-rails sass-rails spring diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f05de94..6529019 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -18,6 +18,7 @@ //= require vue.min //= require vue-resource.min //= require Sortable.min +//= require vuedraggable.min //= require plans //= require lists //= require tasks diff --git a/app/assets/javascripts/vuedraggable.min.js b/app/assets/javascripts/vuedraggable.min.js new file mode 100755 index 0000000..43292c1 --- /dev/null +++ b/app/assets/javascripts/vuedraggable.min.js @@ -0,0 +1 @@ +"use strict";function _toConsumableArray(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);en-1?n:e[t]},getComponent:function(){return this.$slots["default"][0].componentInstance},resetTransitionData:function(t){if(this.noTransitionOnDrag&&this.transitionMode){var e=this.getChildrenNodes();e[t].data=null;var n=this.getComponent();n.children=[],n.kept=void 0}},onDragStart:function(t){this.context=this.getUnderlyingVm(t.item),t.item._underlying_vm_=this.clone(this.context.element),c=t.item},onDragAdd:function(t){this.updateEvenemt(t);var e=t.item._underlying_vm_;if(void 0!==e){n(t.item);var o=this.getVmIndex(t.newIndex);this.spliceList(o,0,e),this.computeIndexes();var i={element:e,newIndex:o};this.emitChanges({added:i})}},onDragRemove:function(t){if(this.updateEvenemt(t),o(this.rootContainer,t.item,t.oldIndex),this.isCloning)return void n(t.clone);var e=this.context.index;this.spliceList(e,1);var i={element:this.context.element,oldIndex:e};this.resetTransitionData(e),this.emitChanges({removed:i})},onDragUpdate:function(t){this.updateEvenemt(t),n(t.item),o(t.from,t.item,t.oldIndex);var e=this.context.index,i=this.getVmIndex(t.newIndex);this.updatePosition(e,i);var r={element:this.context.element,oldIndex:e,newIndex:i};this.emitChanges({moved:r})},updateEvenemt:function(t){this.updateProperty(t,"newIndex"),this.updateProperty(t,"oldIndex")},updateProperty:function(t,e){t.hasOwnProperty(e)&&(t[e]+=this.headerOffset)},computeFutureIndex:function(t,e){if(!t.element)return 0;var n=[].concat(_toConsumableArray(e.to.children)).filter(function(t){return"none"!==t.style.display}),o=n.indexOf(e.related),i=t.component.getVmIndex(o),r=n.indexOf(c)!=-1;return r||!e.willInsertAfter?i:i+1},onDragMove:function(t,e){var n=this.move;if(!n||!this.realList)return!0;var o=this.getRelatedContextFromMoveEvent(t),i=this.context,r=this.computeFutureIndex(o,t);return _extends(i,{futureIndex:r}),_extends(t,{relatedContext:o,draggedContext:i}),n(t,e)},onDragEnd:function(t){this.computeIndexes(),c=null}}};return h}if(Array.from||(Array.from=function(t){return[].slice.call(t)}),typeof exports == "object"){var n=require("sortablejs");module.exports=e(n)}else if("function"==typeof define&&define.amd)define(["sortablejs"],function(t){return e(t)});else if(window&&window.Vue&&window.Sortable){var o=e(window.Sortable);Vue.component("draggable",o)}}(); \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7c6ee67..43facb2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,7 +3,7 @@ class ApplicationController < ActionController::Base # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception, unless: Proc.new {|c| c.request.format.json? } - Rack::MiniProfiler.config.position = 'right' if Rails.env.development? + # Rack::MiniProfiler.config.position = 'right' if Rails.env.development? def json_request? request.format.json? diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index a2381e5..7b99aa1 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -4,7 +4,10 @@ class PlansController < ApplicationController # GET /p.json def index - @plans = current_user.plans if json_request? + if json_request? + sort = current_user.plan_sort.sort + @plans = current_user.plans.sort_by{|e| sort.index(e.id)} + end end # GET /p/ScAJJIBl.json @@ -29,6 +32,16 @@ class PlansController < ApplicationController end end + # PATCH/PUT /p/update_sort.json + def update_sort + plan_sort = current_user.plan_sort + plan_sort = current_user.build_plan_sort if plan_sort.nil? + plan_sort.sort = params[:sort].split(',').map(&:to_i) + unless plan_sort.save + render json: {status: 'failed', message: '更新失败,请稍后重试 !'} + end + end + # PATCH/PUT /plans/1 # PATCH/PUT /plans/1.json def update @@ -43,6 +56,7 @@ class PlansController < ApplicationController end end + # DELETE /plans/1.json def destroy @plan.destroy diff --git a/app/models/list.rb b/app/models/list.rb index 0bef69f..6c6c582 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -16,6 +16,7 @@ class List < ActiveRecord::Base has_many :tasks, -> { order('status DESC, updated_at DESC') }, dependent: :destroy belongs_to :plan belongs_to :user + has_one :task_sort, class_name: 'Sort', as: :sortable, dependent: :destroy scope :with_color_tag, -> (color_tag) { where(color_tag: color_tag) } end diff --git a/app/models/plan.rb b/app/models/plan.rb index 0b05866..d628771 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -17,6 +17,7 @@ class Plan < ActiveRecord::Base has_many :lists, -> { order('created_at DESC') }, dependent: :destroy has_many :tasks, -> { order('status DESC, updated_at DESC') }, dependent: :destroy belongs_to :user + has_one :list_sort, class_name: 'Sort', as: :sortable, dependent: :destroy COLOR_TAG = {'gray' => 0, 'blue' => 1, 'green' => 2, 'red' => 3, 'yellow' => 4, 'qing' => 5} diff --git a/app/models/sort.rb b/app/models/sort.rb new file mode 100644 index 0000000..39f2807 --- /dev/null +++ b/app/models/sort.rb @@ -0,0 +1,14 @@ +# == Schema Information +# +# Table name: sorts +# +# id :bigint(8) not null, primary key +# sortable_id :integer not null +# sortable_type :string(255) not null +# sort :text(65535) not null +# + +class Sort < ActiveRecord::Base + serialize :sort + belongs_to :sortable, polymorphic: true +end diff --git a/app/models/user.rb b/app/models/user.rb index aa24438..5657058 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -31,6 +31,7 @@ class User < ApplicationRecord has_many :plans has_many :lists has_many :tasks + has_one :plan_sort, class_name: 'Sort', as: :sortable, dependent: :destroy ACCESSABLE_ATTRS = [:ident, :email, :password, :password_confirmation, :remember_me] ALLOW_IDENT_CHARS_REGEXP = /\A[A-Za-z0-9\.\-\_]+\z/ diff --git a/app/views/plans/index.html.haml b/app/views/plans/index.html.haml index 04da9e6..8948904 100644 --- a/app/views/plans/index.html.haml +++ b/app/views/plans/index.html.haml @@ -1,14 +1,14 @@ - title '我的计划项' .row#plans-list - %template{'v-for' => 'plan in filterData'} - .col-md-3 - %span.hidden.plan-sort{':sort' => 'plan.id'} - %a{':href' => 'plan.path'} - .bs-callout{':class' => 'plan.color_tag_class'} - %h4 - {{plan.title}} - %p - {{plan.description}} + %draggable{':list' => "filterData", ':options' => "{ animation: 150 }", '@update' => 'updateSort'} + %plan-template{'v-for' => 'plan in filterData'} + .col-md-3 + %a{':href' => 'plan.path'} + .bs-callout{':class' => 'plan.color_tag_class'} + %h4 + {{plan.title}} + %p + {{plan.description}} .col-md-3{ 'v-show' => 'newPlanField' } .bs-callout.bs-callout-add#add-plan-field @@ -101,11 +101,14 @@ $('#title').css({'border-color':'#ccc'}) } xhr.send( "plan[title]="+ this.plan.title + "&plan[description]=" + this.plan.description + "&plan[color_tag]=" + this.plan.color_tag ) + }, + updateSort: function() { + var updateSortUrl = '/p/update_sort.json' + var xhr = new XMLHttpRequest() + var sort = this.plans.map(function(item) {return item.id}) + xhr.open("PUT", updateSortUrl) + xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded") + xhr.send( "sort=" + sort ) } } }) - var el = document.getElementById('plans-list'); - Sortable.create(el, { - handle: '.bs-callout', - animation: 150 - }); diff --git a/config/application.rb b/config/application.rb index 6f993df..7e345ac 100644 --- a/config/application.rb +++ b/config/application.rb @@ -21,6 +21,6 @@ module Taskover # config.i18n.default_locale = :de # Do not swallow errors in after_commit/after_rollback callbacks. - config.active_record.raise_in_transactional_callbacks = true + # config.active_record.raise_in_transactional_callbacks = true end end diff --git a/config/routes.rb b/config/routes.rb index 3ccdbbd..4007f03 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,9 @@ Rails.application.routes.draw do root to: 'home#index' resources :plans, path: :p do + collection do + put 'update_sort' + end resources :lists, only: [:new, :create, :update, :destroy] do resources :tasks, only: [:new, :create, :update, :destroy] do member do diff --git a/db/migrate/20190122143624_create_sorts.rb b/db/migrate/20190122143624_create_sorts.rb new file mode 100644 index 0000000..cc64b56 --- /dev/null +++ b/db/migrate/20190122143624_create_sorts.rb @@ -0,0 +1,9 @@ +class CreateSorts < ActiveRecord::Migration[5.2] + def change + create_table :sorts do |t| + t.integer :sortable_id, null: false + t.string :sortable_type, null: false + t.text :sort, null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e64afe6..2be6334 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,59 +10,65 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160723074411) do +ActiveRecord::Schema.define(version: 2019_01_22_143624) do - create_table "lists", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| - t.text "title", limit: 65535 - t.integer "plan_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "color_tag", default: 0 - t.integer "user_id", null: false + create_table "lists", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + t.text "title" + t.integer "plan_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "color_tag", default: 0 + t.integer "user_id", null: false end - create_table "plans", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| - t.text "title", limit: 65535 - t.text "description", limit: 65535 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "color_tag", default: 0 - t.string "ident", null: false - t.integer "user_id", null: false + create_table "plans", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + t.text "title" + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "color_tag", default: 0 + t.string "ident", null: false + t.integer "user_id", null: false end - create_table "tasks", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| - t.text "title", limit: 65535 - t.text "description", limit: 65535 - t.integer "status", default: 1 - t.integer "list_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "plan_id" - t.integer "user_id", null: false + create_table "sorts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + t.integer "sortable_id", null: false + t.string "sortable_type", null: false + t.text "sort", null: false end - create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + t.text "title" + t.text "description" + t.integer "status", default: 1 + t.integer "list_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "plan_id" + t.integer "user_id", null: false + end + + create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "ident", null: false - t.string "confirmation_token" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "ident", null: false + t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree - t.index ["email"], name: "index_users_on_email", unique: true, using: :btree - t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + t.string "unconfirmed_email" + t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index d388d30..64403c7 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -22,7 +22,7 @@ # unconfirmed_email :string(255) # -FactoryGirl.define do +FactoryBot.define do factory :user do end