diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-07-07 16:23:04 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-07-07 16:23:04 -0400 |
commit | 42d9db526d3aef2e08848d6bc587feaf3700db42 (patch) | |
tree | 29bfcb6653bb6419fa087f87de72b00b00e68fd6 | |
parent | dd231a335758873dcd9024db7618837094fcc0a5 (diff) | |
download | thoughts-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
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 | ||