diff options
26 files changed, 218 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore index 09230f9..702ff9b 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -22,6 +22,7 @@ | |||
22 | /tmux*.log | 22 | /tmux*.log |
23 | *.swp | 23 | *.swp |
24 | tags | 24 | tags |
25 | !tags/ | ||
25 | 26 | ||
26 | .byebug_history | 27 | .byebug_history |
27 | .DS_Store | 28 | .DS_Store |
diff --git a/Gemfile b/Gemfile index aee427f..f0c7c76 100644 --- a/Gemfile +++ b/Gemfile | |||
@@ -69,3 +69,4 @@ gem 'ckeditor' | |||
69 | gem 'paperclip' | 69 | gem 'paperclip' |
70 | gem 'jquery-rails' | 70 | gem 'jquery-rails' |
71 | gem 'pokeviewer', github: "hatkirby/pokeviewer" | 71 | gem 'pokeviewer', github: "hatkirby/pokeviewer" |
72 | gem 'acts-as-taggable-on' | ||
diff --git a/Gemfile.lock b/Gemfile.lock index 9fb12d0..09ff6ef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock | |||
@@ -55,6 +55,8 @@ GEM | |||
55 | i18n (>= 0.7, < 2) | 55 | i18n (>= 0.7, < 2) |
56 | minitest (~> 5.1) | 56 | minitest (~> 5.1) |
57 | tzinfo (~> 1.1) | 57 | tzinfo (~> 1.1) |
58 | acts-as-taggable-on (6.0.0) | ||
59 | activerecord (~> 5.0) | ||
58 | addressable (2.5.2) | 60 | addressable (2.5.2) |
59 | public_suffix (>= 2.0.2, < 4.0) | 61 | public_suffix (>= 2.0.2, < 4.0) |
60 | airbrussh (1.3.0) | 62 | airbrussh (1.3.0) |
@@ -269,6 +271,7 @@ PLATFORMS | |||
269 | ruby | 271 | ruby |
270 | 272 | ||
271 | DEPENDENCIES | 273 | DEPENDENCIES |
274 | acts-as-taggable-on | ||
272 | byebug | 275 | byebug |
273 | capistrano (~> 3.0) | 276 | capistrano (~> 3.0) |
274 | capistrano-bundler | 277 | capistrano-bundler |
diff --git a/app/assets/javascripts/admin/records.coffee b/app/assets/javascripts/admin/records.coffee index 3a1ed51..7a11ce1 100644 --- a/app/assets/javascripts/admin/records.coffee +++ b/app/assets/javascripts/admin/records.coffee | |||
@@ -23,3 +23,5 @@ $(document).on "turbolinks:load", -> | |||
23 | create_record_toggle($(this).prop("checked")) | 23 | create_record_toggle($(this).prop("checked")) |
24 | $(".published-field input[type=checkbox]").change -> | 24 | $(".published-field input[type=checkbox]").change -> |
25 | published_field_toggle($(this).prop("checked")) | 25 | published_field_toggle($(this).prop("checked")) |
26 | $("input[type=tags]").each -> | ||
27 | tagsInput(this) | ||
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f902906..a81b3b2 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js | |||
@@ -14,4 +14,5 @@ | |||
14 | //= require jquery_ujs | 14 | //= require jquery_ujs |
15 | //= require turbolinks | 15 | //= require turbolinks |
16 | //= require ckeditor/init | 16 | //= require ckeditor/init |
17 | //= require tags-input | ||
17 | //= require_tree ./admin | 18 | //= require_tree ./admin |
diff --git a/app/assets/stylesheets/admin.css.scss b/app/assets/stylesheets/admin.css.scss index 5235c4b..95d1ed0 100644 --- a/app/assets/stylesheets/admin.css.scss +++ b/app/assets/stylesheets/admin.css.scss | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | *= require normalize-rails | 2 | *= require normalize-rails |
3 | *= require tags-input | ||
3 | *= require_tree ./admin | 4 | *= require_tree ./admin |
4 | */ | 5 | */ |
diff --git a/app/assets/stylesheets/admin/layout.scss b/app/assets/stylesheets/admin/layout.scss index b825c25..220dcd5 100644 --- a/app/assets/stylesheets/admin/layout.scss +++ b/app/assets/stylesheets/admin/layout.scss | |||
@@ -196,6 +196,14 @@ body { | |||
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | .tags-field { | ||
200 | label { | ||
201 | font-size: .75em; | ||
202 | display: block; | ||
203 | margin-bottom: 0.5em; | ||
204 | } | ||
205 | } | ||
206 | |||
199 | .record-description-field { | 207 | .record-description-field { |
200 | display: none; | 208 | display: none; |
201 | margin-top: 1em; | 209 | margin-top: 1em; |
diff --git a/app/assets/stylesheets/main/records.scss b/app/assets/stylesheets/main/records.scss index f57dded..350fb16 100644 --- a/app/assets/stylesheets/main/records.scss +++ b/app/assets/stylesheets/main/records.scss | |||
@@ -31,6 +31,7 @@ | |||
31 | .tags { | 31 | .tags { |
32 | margin: .25em; | 32 | margin: .25em; |
33 | display: flex; | 33 | display: flex; |
34 | flex-wrap: wrap; | ||
34 | padding-left: 0; | 35 | padding-left: 0; |
35 | 36 | ||
36 | li { | 37 | li { |
@@ -58,6 +59,7 @@ | |||
58 | } | 59 | } |
59 | } | 60 | } |
60 | 61 | ||
62 | &.entry-tag { | ||
61 | & + li { | 63 | & + li { |
62 | margin-left: 1em; | 64 | margin-left: 1em; |
63 | } | 65 | } |
diff --git a/app/controllers/admin/blogs_controller.rb b/app/controllers/admin/blogs_controller.rb index 1035c12..e79dd81 100644 --- a/app/controllers/admin/blogs_controller.rb +++ b/app/controllers/admin/blogs_controller.rb | |||
@@ -56,7 +56,7 @@ class Admin::BlogsController < Admin::AdminController | |||
56 | private | 56 | private |
57 | 57 | ||
58 | def blog_params | 58 | def blog_params |
59 | params.require(:blog).permit(:title, :body, :slug, :published, records_attributes: [:description, :_destroy]) | 59 | params.require(:blog).permit(:title, :body, :slug, :published, :tag_list, records_attributes: [:description, :_destroy]) |
60 | end | 60 | end |
61 | 61 | ||
62 | def set_section | 62 | def set_section |
diff --git a/app/controllers/admin/streams_controller.rb b/app/controllers/admin/streams_controller.rb index 86dec06..252ebfa 100644 --- a/app/controllers/admin/streams_controller.rb +++ b/app/controllers/admin/streams_controller.rb | |||
@@ -42,7 +42,7 @@ class Admin::StreamsController < Admin::AdminController | |||
42 | private | 42 | private |
43 | 43 | ||
44 | def stream_params | 44 | def stream_params |
45 | params.require(:stream).permit(:title, :body, :slug, records_attributes: [:description, :_destroy]) | 45 | params.require(:stream).permit(:title, :body, :slug, :tag_list, records_attributes: [:description, :_destroy]) |
46 | end | 46 | end |
47 | 47 | ||
48 | def set_section | 48 | def set_section |
diff --git a/app/models/blog.rb b/app/models/blog.rb index 5742879..18f63f1 100644 --- a/app/models/blog.rb +++ b/app/models/blog.rb | |||
@@ -1,6 +1,8 @@ | |||
1 | class Blog < ApplicationRecord | 1 | class Blog < ApplicationRecord |
2 | include Recordable | 2 | include Recordable |
3 | 3 | ||
4 | acts_as_taggable | ||
5 | |||
4 | validates :title, presence: true | 6 | validates :title, presence: true |
5 | validates :body, presence: true, if: :published | 7 | validates :body, presence: true, if: :published |
6 | validates :slug, presence: true, format: /\A[-a-z0-9]+\z/, if: :published | 8 | validates :slug, presence: true, format: /\A[-a-z0-9]+\z/, if: :published |
@@ -12,6 +14,10 @@ class Blog < ApplicationRecord | |||
12 | "/says/#{slug}" | 14 | "/says/#{slug}" |
13 | end | 15 | end |
14 | 16 | ||
17 | def taggable | ||
18 | self | ||
19 | end | ||
20 | |||
15 | private | 21 | private |
16 | def set_draft_title | 22 | def set_draft_title |
17 | if self.title.blank? and not self.published | 23 | if self.title.blank? and not self.published |
diff --git a/app/models/stream.rb b/app/models/stream.rb index 1398b75..0773143 100644 --- a/app/models/stream.rb +++ b/app/models/stream.rb | |||
@@ -1,6 +1,8 @@ | |||
1 | class Stream < ApplicationRecord | 1 | class Stream < ApplicationRecord |
2 | include Recordable | 2 | include Recordable |
3 | 3 | ||
4 | acts_as_taggable | ||
5 | |||
4 | has_many :updates | 6 | has_many :updates |
5 | 7 | ||
6 | validates :title, presence: true | 8 | validates :title, presence: true |
@@ -9,4 +11,8 @@ class Stream < ApplicationRecord | |||
9 | def path | 11 | def path |
10 | "/thinks/#{slug}" | 12 | "/thinks/#{slug}" |
11 | end | 13 | end |
14 | |||
15 | def taggable | ||
16 | self | ||
17 | end | ||
12 | end | 18 | end |
diff --git a/app/models/update.rb b/app/models/update.rb index 73c4911..01907d8 100644 --- a/app/models/update.rb +++ b/app/models/update.rb | |||
@@ -8,4 +8,8 @@ class Update < ApplicationRecord | |||
8 | def path | 8 | def path |
9 | "/thinks/#{stream.slug}\#update-#{id}" | 9 | "/thinks/#{stream.slug}\#update-#{id}" |
10 | end | 10 | end |
11 | |||
12 | def taggable | ||
13 | stream | ||
14 | end | ||
11 | end | 15 | end |
diff --git a/app/views/admin/blogs/_form.html.haml b/app/views/admin/blogs/_form.html.haml index 12f7a82..36925af 100644 --- a/app/views/admin/blogs/_form.html.haml +++ b/app/views/admin/blogs/_form.html.haml | |||
@@ -22,6 +22,10 @@ | |||
22 | - else | 22 | - else |
23 | = link_to "Preview post", admin_blog_url(f.object), target: "entry-preview" | 23 | = link_to "Preview post", admin_blog_url(f.object), target: "entry-preview" |
24 | .details-module | 24 | .details-module |
25 | .tags-field | ||
26 | = f.label :tag_list, "Tags" | ||
27 | = f.text_field :tag_list, type: :tags, value: f.object.tag_list.join(",") | ||
28 | .details-module | ||
25 | .published-field | 29 | .published-field |
26 | = f.check_box :published | 30 | = f.check_box :published |
27 | = f.label :published | 31 | = f.label :published |
diff --git a/app/views/admin/streams/_form.html.haml b/app/views/admin/streams/_form.html.haml index ce457cb..e04a3fb 100644 --- a/app/views/admin/streams/_form.html.haml +++ b/app/views/admin/streams/_form.html.haml | |||
@@ -16,6 +16,10 @@ | |||
16 | - f.object.errors.full_messages.each do |error| | 16 | - f.object.errors.full_messages.each do |error| |
17 | %li= error | 17 | %li= error |
18 | .details-module | 18 | .details-module |
19 | .tags-field | ||
20 | = f.label :tag_list, "Tags" | ||
21 | = f.text_field :tag_list, type: :tags, value: f.object.tag_list.join(",") | ||
22 | .details-module | ||
19 | = f.fields_for :records, Record.new do |builder| | 23 | = f.fields_for :records, Record.new do |builder| |
20 | .should-create-record-field | 24 | .should-create-record-field |
21 | = builder.check_box :_destroy, {checked: false}, "0", "1" | 25 | = builder.check_box :_destroy, {checked: false}, "0", "1" |
diff --git a/app/views/records/_record.html.haml b/app/views/records/_record.html.haml new file mode 100644 index 0000000..80a365c --- /dev/null +++ b/app/views/records/_record.html.haml | |||
@@ -0,0 +1,7 @@ | |||
1 | %li | ||
2 | %span.description= link_to record.description, record.recordable.path | ||
3 | %ul.tags | ||
4 | %li.record-date= record.created_at.strftime("%m.%d.%y") | ||
5 | %li.entry-type{ class: "entry-type-#{record.recordable_type.downcase}" }= record.recordable_type | ||
6 | - record.recordable.taggable.tag_list.each do |tag| | ||
7 | %li.entry-tag= tag | ||
diff --git a/app/views/records/index.html.haml b/app/views/records/index.html.haml index 200321e..4ceed2c 100644 --- a/app/views/records/index.html.haml +++ b/app/views/records/index.html.haml | |||
@@ -1,7 +1 @@ | |||
1 | %ul#records | %ul#records= render @records | |
2 | - @records.each do |record| | ||
3 | %li | ||
4 | %span.description= link_to record.description, record.recordable.path | ||
5 | %ul.tags | ||
6 | %li.record-date= record.created_at.strftime("%m.%d.%y") | ||
7 | %li.entry-type{ class: "entry-type-#{record.recordable_type.downcase}" }= record.recordable_type | ||
diff --git a/db/migrate/20180707142415_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/db/migrate/20180707142415_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..461eae4 --- /dev/null +++ b/db/migrate/20180707142415_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,36 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 1) | ||
2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
3 | class ActsAsTaggableOnMigration < ActiveRecord::Migration[4.2]; end | ||
4 | else | ||
5 | class ActsAsTaggableOnMigration < ActiveRecord::Migration; end | ||
6 | end | ||
7 | ActsAsTaggableOnMigration.class_eval do | ||
8 | def self.up | ||
9 | create_table :tags do |t| | ||
10 | t.string :name | ||
11 | end | ||
12 | |||
13 | create_table :taggings do |t| | ||
14 | t.references :tag | ||
15 | |||
16 | # You should make sure that the column created is | ||
17 | # long enough to store the required class names. | ||
18 | t.references :taggable, polymorphic: true | ||
19 | t.references :tagger, polymorphic: true | ||
20 | |||
21 | # Limit is created to prevent MySQL error on index | ||
22 | # length for MyISAM table type: http://bit.ly/vgW2Ql | ||
23 | t.string :context, limit: 128 | ||
24 | |||
25 | t.datetime :created_at | ||
26 | end | ||
27 | |||
28 | add_index :taggings, :tag_id | ||
29 | add_index :taggings, [:taggable_id, :taggable_type, :context] | ||
30 | end | ||
31 | |||
32 | def self.down | ||
33 | drop_table :taggings | ||
34 | drop_table :tags | ||
35 | end | ||
36 | end | ||
diff --git a/db/migrate/20180707142416_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20180707142416_add_missing_unique_indices.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..514ac57 --- /dev/null +++ b/db/migrate/20180707142416_add_missing_unique_indices.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,26 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 2) | ||
2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
3 | class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]; end | ||
4 | else | ||
5 | class AddMissingUniqueIndices < ActiveRecord::Migration; end | ||
6 | end | ||
7 | AddMissingUniqueIndices.class_eval do | ||
8 | def self.up | ||
9 | add_index :tags, :name, unique: true | ||
10 | |||
11 | remove_index :taggings, :tag_id if index_exists?(:taggings, :tag_id) | ||
12 | remove_index :taggings, [:taggable_id, :taggable_type, :context] | ||
13 | add_index :taggings, | ||
14 | [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], | ||
15 | unique: true, name: 'taggings_idx' | ||
16 | end | ||
17 | |||
18 | def self.down | ||
19 | remove_index :tags, :name | ||
20 | |||
21 | remove_index :taggings, name: 'taggings_idx' | ||
22 | |||
23 | add_index :taggings, :tag_id unless index_exists?(:taggings, :tag_id) | ||
24 | add_index :taggings, [:taggable_id, :taggable_type, :context] | ||
25 | end | ||
26 | end | ||
diff --git a/db/migrate/20180707142417_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20180707142417_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..1d9b556 --- /dev/null +++ b/db/migrate/20180707142417_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,20 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 3) | ||
2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
3 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]; end | ||
4 | else | ||
5 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration; end | ||
6 | end | ||
7 | AddTaggingsCounterCacheToTags.class_eval do | ||
8 | def self.up | ||
9 | add_column :tags, :taggings_count, :integer, default: 0 | ||
10 | |||
11 | ActsAsTaggableOn::Tag.reset_column_information | ||
12 | ActsAsTaggableOn::Tag.find_each do |tag| | ||
13 | ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) | ||
14 | end | ||
15 | end | ||
16 | |||
17 | def self.down | ||
18 | remove_column :tags, :taggings_count | ||
19 | end | ||
20 | end | ||
diff --git a/db/migrate/20180707142418_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20180707142418_add_missing_taggable_index.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..5f46569 --- /dev/null +++ b/db/migrate/20180707142418_add_missing_taggable_index.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,15 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 4) | ||
2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
3 | class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]; end | ||
4 | else | ||
5 | class AddMissingTaggableIndex < ActiveRecord::Migration; end | ||
6 | end | ||
7 | AddMissingTaggableIndex.class_eval do | ||
8 | def self.up | ||
9 | add_index :taggings, [:taggable_id, :taggable_type, :context] | ||
10 | end | ||
11 | |||
12 | def self.down | ||
13 | remove_index :taggings, [:taggable_id, :taggable_type, :context] | ||
14 | end | ||
15 | end | ||
diff --git a/db/migrate/20180707142419_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20180707142419_change_collation_for_tag_names.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..f119b16 --- /dev/null +++ b/db/migrate/20180707142419_change_collation_for_tag_names.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,15 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 5) | ||
2 | # This migration is added to circumvent issue #623 and have special characters | ||
3 | # work properly | ||
4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
5 | class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end | ||
6 | else | ||
7 | class ChangeCollationForTagNames < ActiveRecord::Migration; end | ||
8 | end | ||
9 | ChangeCollationForTagNames.class_eval do | ||
10 | def up | ||
11 | if ActsAsTaggableOn::Utils.using_mysql? | ||
12 | execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") | ||
13 | end | ||
14 | end | ||
15 | end | ||
diff --git a/db/migrate/20180707142420_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb b/db/migrate/20180707142420_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000..94e1f2e --- /dev/null +++ b/db/migrate/20180707142420_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb | |||
@@ -0,0 +1,23 @@ | |||
1 | # This migration comes from acts_as_taggable_on_engine (originally 6) | ||
2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') | ||
3 | class AddMissingIndexesOnTaggings < ActiveRecord::Migration[4.2]; end | ||
4 | else | ||
5 | class AddMissingIndexesOnTaggings < ActiveRecord::Migration; end | ||
6 | end | ||
7 | AddMissingIndexesOnTaggings.class_eval do | ||
8 | def change | ||
9 | add_index :taggings, :tag_id unless index_exists? :taggings, :tag_id | ||
10 | add_index :taggings, :taggable_id unless index_exists? :taggings, :taggable_id | ||
11 | add_index :taggings, :taggable_type unless index_exists? :taggings, :taggable_type | ||
12 | add_index :taggings, :tagger_id unless index_exists? :taggings, :tagger_id | ||
13 | add_index :taggings, :context unless index_exists? :taggings, :context | ||
14 | |||
15 | unless index_exists? :taggings, [:tagger_id, :tagger_type] | ||
16 | add_index :taggings, [:tagger_id, :tagger_type] | ||
17 | end | ||
18 | |||
19 | unless index_exists? :taggings, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy' | ||
20 | add_index :taggings, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy' | ||
21 | end | ||
22 | end | ||
23 | end | ||
diff --git a/db/schema.rb b/db/schema.rb index 0279d8e..192c9c1 100644 --- a/db/schema.rb +++ b/db/schema.rb | |||
@@ -10,7 +10,7 @@ | |||
10 | # | 10 | # |
11 | # It's strongly recommended that you check this file into your version control system. | 11 | # It's strongly recommended that you check this file into your version control system. |
12 | 12 | ||
13 | ActiveRecord::Schema.define(version: 20180704144707) do | 13 | ActiveRecord::Schema.define(version: 20180707142420) do |
14 | 14 | ||
15 | create_table "blogs", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" do |t| | 15 | create_table "blogs", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" do |t| |
16 | t.string "title" | 16 | t.string "title" |
@@ -238,6 +238,31 @@ ActiveRecord::Schema.define(version: 20180704144707) do | |||
238 | t.datetime "updated_at", null: false | 238 | t.datetime "updated_at", null: false |
239 | end | 239 | end |
240 | 240 | ||
241 | create_table "taggings", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" do |t| | ||
242 | t.integer "tag_id" | ||
243 | t.string "taggable_type" | ||
244 | t.integer "taggable_id" | ||
245 | t.string "tagger_type" | ||
246 | t.integer "tagger_id" | ||
247 | t.string "context", limit: 128 | ||
248 | t.datetime "created_at" | ||
249 | t.index ["context"], name: "index_taggings_on_context" | ||
250 | t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true | ||
251 | t.index ["tag_id"], name: "index_taggings_on_tag_id" | ||
252 | t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context" | ||
253 | t.index ["taggable_id", "taggable_type", "tagger_id", "context"], name: "taggings_idy" | ||
254 | t.index ["taggable_id"], name: "index_taggings_on_taggable_id" | ||
255 | t.index ["taggable_type"], name: "index_taggings_on_taggable_type" | ||
256 | t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type" | ||
257 | t.index ["tagger_id"], name: "index_taggings_on_tagger_id" | ||
258 | end | ||
259 | |||
260 | create_table "tags", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" do |t| | ||
261 | t.string "name", limit: 255, collation: "utf8_bin" | ||
262 | t.integer "taggings_count", default: 0 | ||
263 | t.index ["name"], name: "index_tags_on_name", unique: true | ||
264 | end | ||
265 | |||
241 | create_table "updates", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" do |t| | 266 | create_table "updates", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" do |t| |
242 | t.bigint "stream_id" | 267 | t.bigint "stream_id" |
243 | t.text "body" | 268 | t.text "body" |
diff --git a/vendor/assets/javascripts/tags-input.js b/vendor/assets/javascripts/tags-input.js new file mode 100755 index 0000000..878339e --- /dev/null +++ b/vendor/assets/javascripts/tags-input.js | |||
@@ -0,0 +1,2 @@ | |||
1 | (function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','module'],factory);}else if(typeof exports !== 'undefined' && typeof module !== 'undefined'){factory(exports,module);}else {var mod={exports:{}};factory(mod.exports,mod);global.tagsInput = mod.exports;}})(this,function(exports,module){'use strict';module.exports = tagsInput;var BACKSPACE=8,TAB=9,ENTER=13,LEFT=37,RIGHT=39,DELETE=46,COMMA=188;var SEPERATOR=',';var COPY_PROPS='placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');function tagsInput(input){function createElement(type,name,text,attributes){var el=document.createElement(type);if(name)el.className = name;if(text)el.textContent = text;for(var key in attributes) {el.setAttribute('data-' + key,attributes[key]);}return el;}function $(selector,all){return all === true?Array.prototype.slice.call(base.querySelectorAll(selector)):base.querySelector(selector);}function getValue(){return $('.tag',true).map(function(tag){return tag.textContent;}).concat(base.input.value || []).join(SEPERATOR);}function setValue(value){$('.tag',true).forEach(function(t){return base.removeChild(t);});savePartialInput(value);}function save(){input.value = getValue();input.dispatchEvent(new Event('change'));}function addTag(text){if(~text.indexOf(SEPERATOR))text = text.split(SEPERATOR);if(Array.isArray(text))return text.forEach(addTag);var tag=text && text.trim();if(!tag)return false;if(!input.getAttribute('duplicates')){var _ret=(function(){var exisingTag=$('[data-tag="' + tag + '"]');if(exisingTag){exisingTag.classList.add('dupe');setTimeout(function(){return exisingTag.classList.remove('dupe');},100);return {v:false};}})();if(typeof _ret === 'object')return _ret.v;}base.insertBefore(createElement('span','tag',tag,{tag:tag}),base.input);}function select(el){var sel=$('.selected');if(sel)sel.classList.remove('selected');if(el)el.classList.add('selected');}function setInputWidth(){var last=$('.tag',true).pop(),w=base.offsetWidth;if(!w)return;base.input.style.width = Math.max(w - (last?last.offsetLeft + last.offsetWidth:5) - 5,w / 4) + 'px';}function savePartialInput(value){if(typeof value !== 'string' && !Array.isArray(value)){value = base.input.value || input.value;}if(addTag(value) !== false){base.input.value = '';save();setInputWidth();}}function refocus(e){if(e.target.classList.contains('tag'))select(e.target);if(e.target === base.input)return select();base.input.focus();e.preventDefault();return false;}var base=createElement('div','tags-input'),sib=input.nextSibling;input.parentNode[sib?'insertBefore':'appendChild'](base,sib);input.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';input.tabIndex = -1;base.input = createElement('input');base.input.setAttribute('type','text');COPY_PROPS.forEach(function(prop){if(input[prop] !== base.input[prop]){base.input[prop] = input[prop];try{delete input[prop];}catch(e) {}}});base.appendChild(base.input);input.addEventListener('focus',function(){base.input.focus();});base.input.addEventListener('focus',function(){base.classList.add('focus');select();});base.input.addEventListener('blur',function(){base.classList.remove('focus');select();savePartialInput();});base.input.addEventListener('keydown',function(e){var el=base.input,key=e.keyCode || e.which,selectedTag=$('.tag.selected'),pos=el.selectionStart === el.selectionEnd && el.selectionStart,last=$('.tag',true).pop();setInputWidth();if(key === ENTER || key === COMMA || key === TAB){if(!el.value && key !== COMMA)return;savePartialInput();}else if(key === DELETE && selectedTag){if(selectedTag.nextSibling !== base.input)select(selectedTag.nextSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(key === BACKSPACE){if(selectedTag){select(selectedTag.previousSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(last && pos === 0){select(last);}else {return;}}else if(key === LEFT){if(selectedTag){if(selectedTag.previousSibling){select(selectedTag.previousSibling);}}else if(pos !== 0){return;}else {select(last);}}else if(key === RIGHT){if(!selectedTag)return;select(selectedTag.nextSibling);}else {return select();}e.preventDefault();return false;});base.input.addEventListener('input',function(){input.value = getValue();input.dispatchEvent(new Event('input'));});base.input.addEventListener('paste',function(){return setTimeout(savePartialInput,0);});base.addEventListener('mousedown',refocus);base.addEventListener('touchstart',refocus);base.setValue = setValue;base.getValue = getValue;savePartialInput();}tagsInput.enhance = tagsInput.tagsInput = tagsInput;}); | ||
2 | //# sourceMappingURL=tags-input.js.map \ No newline at end of file | ||
diff --git a/vendor/assets/stylesheets/tags-input.css b/vendor/assets/stylesheets/tags-input.css new file mode 100755 index 0000000..ef4477b --- /dev/null +++ b/vendor/assets/stylesheets/tags-input.css | |||
@@ -0,0 +1,2 @@ | |||
1 | .tags-input{display:inline-block;padding:0 2px;background:#FFF;border:1px solid #CCC;width:16em;border-radius:2px;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.tags-input .tag{display:inline-block;background:#EEE;color:#444;padding:0 4px;margin:2px;border:1px solid #CCC;border-radius:2px;font:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;transition:all .1s ease}.tags-input .tag.selected{background-color:#777;border-color:#777;color:#EEE}.tags-input .tag.dupe{-webkit-transform:scale3d(1.2,1.2,1.2);transform:scale3d(1.2,1.2,1.2);background-color:#FCC;border-color:#700}.tags-input input{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;display:inline-block!important;padding:3px;margin:0!important;background:0 0!important;border:none!important;box-shadow:none!important;font:inherit!important;font-size:100%!important;outline:0!important}.tags-input .selected~input{opacity:.3} | ||
2 | /*# sourceMappingURL=tags-input.css.map */ \ No newline at end of file | ||