about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-07-07 16:23:04 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-07-07 16:23:04 -0400
commit42d9db526d3aef2e08848d6bc587feaf3700db42 (patch)
tree29bfcb6653bb6419fa087f87de72b00b00e68fd6
parentdd231a335758873dcd9024db7618837094fcc0a5 (diff)
downloadthoughts-42d9db526d3aef2e08848d6bc587feaf3700db42.tar.gz
thoughts-42d9db526d3aef2e08848d6bc587feaf3700db42.tar.bz2
thoughts-42d9db526d3aef2e08848d6bc587feaf3700db42.zip
Added tags
Blogs and streams can now be tagged. Records now show the appropriate tags for an entry. Updates work oddly, because their records show the stream's tags, since updates do not have tags themselves.

refs #2
-rw-r--r--.gitignore1
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock3
-rw-r--r--app/assets/javascripts/admin/records.coffee2
-rw-r--r--app/assets/javascripts/application.js1
-rw-r--r--app/assets/stylesheets/admin.css.scss1
-rw-r--r--app/assets/stylesheets/admin/layout.scss8
-rw-r--r--app/assets/stylesheets/main/records.scss2
-rw-r--r--app/controllers/admin/blogs_controller.rb2
-rw-r--r--app/controllers/admin/streams_controller.rb2
-rw-r--r--app/models/blog.rb6
-rw-r--r--app/models/stream.rb6
-rw-r--r--app/models/update.rb4
-rw-r--r--app/views/admin/blogs/_form.html.haml4
-rw-r--r--app/views/admin/streams/_form.html.haml4
-rw-r--r--app/views/records/_record.html.haml7
-rw-r--r--app/views/records/index.html.haml8
-rw-r--r--db/migrate/20180707142415_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb36
-rw-r--r--db/migrate/20180707142416_add_missing_unique_indices.acts_as_taggable_on_engine.rb26
-rw-r--r--db/migrate/20180707142417_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb20
-rw-r--r--db/migrate/20180707142418_add_missing_taggable_index.acts_as_taggable_on_engine.rb15
-rw-r--r--db/migrate/20180707142419_change_collation_for_tag_names.acts_as_taggable_on_engine.rb15
-rw-r--r--db/migrate/20180707142420_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb23
-rw-r--r--db/schema.rb27
-rwxr-xr-xvendor/assets/javascripts/tags-input.js2
-rwxr-xr-xvendor/assets/stylesheets/tags-input.css2
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
24tags 24tags
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'
69gem 'paperclip' 69gem 'paperclip'
70gem 'jquery-rails' 70gem 'jquery-rails'
71gem 'pokeviewer', github: "hatkirby/pokeviewer" 71gem 'pokeviewer', github: "hatkirby/pokeviewer"
72gem '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
271DEPENDENCIES 273DEPENDENCIES
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 @@
1class Blog < ApplicationRecord 1class 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 @@
1class Stream < ApplicationRecord 1class 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
12end 18end
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
11end 15end
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)
2if ActiveRecord.gem_version >= Gem::Version.new('5.0')
3 class ActsAsTaggableOnMigration < ActiveRecord::Migration[4.2]; end
4else
5 class ActsAsTaggableOnMigration < ActiveRecord::Migration; end
6end
7ActsAsTaggableOnMigration.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
36end
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)
2if ActiveRecord.gem_version >= Gem::Version.new('5.0')
3 class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]; end
4else
5 class AddMissingUniqueIndices < ActiveRecord::Migration; end
6end
7AddMissingUniqueIndices.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
26end
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)
2if ActiveRecord.gem_version >= Gem::Version.new('5.0')
3 class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]; end
4else
5 class AddTaggingsCounterCacheToTags < ActiveRecord::Migration; end
6end
7AddTaggingsCounterCacheToTags.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
20end
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)
2if ActiveRecord.gem_version >= Gem::Version.new('5.0')
3 class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]; end
4else
5 class AddMissingTaggableIndex < ActiveRecord::Migration; end
6end
7AddMissingTaggableIndex.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
15end
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
4if ActiveRecord.gem_version >= Gem::Version.new('5.0')
5 class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end
6else
7 class ChangeCollationForTagNames < ActiveRecord::Migration; end
8end
9ChangeCollationForTagNames.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
15end
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)
2if ActiveRecord.gem_version >= Gem::Version.new('5.0')
3 class AddMissingIndexesOnTaggings < ActiveRecord::Migration[4.2]; end
4else
5 class AddMissingIndexesOnTaggings < ActiveRecord::Migration; end
6end
7AddMissingIndexesOnTaggings.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
23end
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
13ActiveRecord::Schema.define(version: 20180704144707) do 13ActiveRecord::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