Merge pull request #326 from indentlabs/page-tags

Add taggable functionality to content pages
This commit is contained in:
Andrew Brown 2019-02-16 02:21:39 -06:00 committed by GitHub
commit e5592e5dff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 482 additions and 139 deletions

View File

@ -12,6 +12,9 @@ $(document).ready(function () {
var focused_text_field = $(focus_event.target);
var parent_content_field = focused_text_field.closest('.content-field');
$('.show-when-focused').hide();
parent_content_field.find('.show-when-focused').show();
$('.content-field').removeClass('focused');
parent_content_field.addClass('focused');
$('.content-field-link-bar').hide();
@ -20,6 +23,23 @@ $(document).ready(function () {
add_link_bar(parent_content_field.find('.content-field-link-bar-container'));
});
// um sir excuse me why does this need to be in a setTimeout? It doesn't work
// unless it is... for whatever reason. Here be dragons.
setTimeout(function () {
$('.content-field').find('.chips input').focus(function (focus_event) {
var focused_text_field = $(focus_event.target);
var parent_content_field = focused_text_field.closest('.content-field');
$('.show-when-focused').hide();
parent_content_field.find('.show-when-focused').show();
$('.content-field').removeClass('focused');
parent_content_field.addClass('focused');
$('.content-field-link-bar').hide();
parent_content_field.find('.content-field-link-bar').show();
});
}, 100);
function add_link_bar_click_handlers() {
$('.js-content-link-option').click(function (click_event) {
var selected_option = $(click_event.target);

View File

@ -0,0 +1,8 @@
$(document).ready(function () {
$('.js-add-tag').click(function() {
var clicked_tag = $(this).find('.badge').data('badge-caption');
M.Chips.getInstance($('.chips')).addChip({tag: clicked_tag});
return false;
});
});

View File

@ -0,0 +1,20 @@
.tags-container {
padding-top: 8px;
.badge {
margin-bottom: 4px;
margin-left: 0;
margin-right: 5px;
}
}
.chip {
i.material-icons {
line-height: 26px;
}
}
.show-when-focused {
display: none;
}

View File

@ -26,8 +26,8 @@ class ContentController < ApplicationController
@content = @universe_scope.send(pluralized_content_name)
else
@content = (
current_user.send(pluralized_content_name) +
current_user.send("contributable_#{pluralized_content_name}")
current_user.send(pluralized_content_name).includes(:page_tags) +
current_user.send("contributable_#{pluralized_content_name}").includes(:page_tags)
)
unless @content_type_class == Universe
@ -36,7 +36,19 @@ class ContentController < ApplicationController
end
end
@content = @content.to_a.flatten.uniq.sort_by(&:name)
@content = @content.to_a.flatten.uniq
# Filters
@page_tags = PageTag.where(
page_type: @content_type_class.name,
page_id: @content.pluck(:id)
)
if params.key?(:slug)
filtered_page_tags = @page_tags.where(slug: params[:slug])
@content.select! { |content| filtered_page_tags.pluck(:page_id).include?(content.id) }
end
@content = @content.sort_by(&:name)
respond_to do |format|
format.html { render 'content/index' }
@ -97,6 +109,10 @@ class ContentController < ApplicationController
@serialized_categories_and_fields = CategoriesAndFieldsSerializer.new(
@content.class.attribute_categories(current_user)
)
@suggested_page_tags = (
current_user.page_tags.where(page_type: @content.class.name).pluck(:tag) +
PageTagService.suggested_tags_for(@content.class.name)
).uniq
# todo this is a good spot to audit to disable and see if create permissions are ok also
unless (current_user || User.new).can_create?(content_type_from_controller(self.class))
@ -119,6 +135,10 @@ class ContentController < ApplicationController
end
@serialized_content = ContentSerializer.new(@content)
@suggested_page_tags = (
current_user.page_tags.where(page_type: content_type_class.name).pluck(:tag) +
PageTagService.suggested_tags_for(content_type_class.name)
).uniq - @serialized_content.page_tags
unless @content.updatable_by? current_user
return redirect_to @content, notice: t(:no_do_permission)
@ -162,6 +182,8 @@ class ContentController < ApplicationController
upload_files params['image_uploads'], content_type.name, @content.id
end
update_page_tags
successful_response(content_creation_redirect_url, t(:create_success, model_name: @content.try(:name).presence || humanized_model_name))
else
failed_response('new', :unprocessable_entity, "Unable to save page. Error code: " + @content.errors.map(&:messages).to_sentence)
@ -192,6 +214,8 @@ class ContentController < ApplicationController
end
end
update_page_tags
if @content.user == current_user
# todo this needs some extra validation probably to ensure each attribute is one associated with this page
update_success = @content.update_attributes(content_params)
@ -333,6 +357,26 @@ class ContentController < ApplicationController
private
def update_page_tags
tag_list = page_tag_params.fetch(:page_tags, "").split(',,,|||,,,')
current_tags = @content.page_tags.pluck(:tag)
tags_to_add = tag_list - current_tags
tags_to_remove = current_tags - tag_list
tags_to_add.each do |tag|
@content.page_tags.find_or_create_by(
tag: tag,
slug: PageTagService.slug_for(tag),
user: @content.user
)
end
tags_to_remove.each do |tag|
@content.page_tags.find_by(tag: tag).destroy
end
end
def render_json(content)
render json: JSON.pretty_generate({
name: content.try(:name),
@ -403,6 +447,15 @@ class ContentController < ApplicationController
params.require(content_class).permit(content_param_list + [:deleted_at])
end
def page_tag_params
content_class = content_type_from_controller(self.class)
.name
.downcase
.to_sym
params.require(content_class).permit(:page_tags)
end
def content_deletion_redirect_url
send("#{@content.class.name.underscore.pluralize}_path")
end

View File

@ -40,6 +40,8 @@ class AttributeField < ApplicationRecord
Universe.icon
when 'textarea'
'text_fields'
when 'tags'
'label'
else
'text_fields'
end
@ -69,6 +71,10 @@ class AttributeField < ApplicationRecord
self.field_type == 'universe'
end
def tags_field?
self.field_type == 'tags'
end
private
def ensure_name

View File

@ -0,0 +1,9 @@
require 'active_support/concern'
module HasPageTags
extend ActiveSupport::Concern
included do
has_many :page_tags, as: :page
end
end

View File

@ -0,0 +1,14 @@
require 'active_support/concern'
module IsContentPage
extend ActiveSupport::Concern
included do
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include HasPageTags
end
end

View File

@ -7,11 +7,8 @@ class Building < ActiveRecord::Base
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -13,12 +13,7 @@ class Character < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -7,11 +7,7 @@ class Condition < ActiveRecord::Base
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -9,10 +9,7 @@ class Country < ApplicationRecord
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -15,12 +15,7 @@ class Creature < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -6,11 +6,7 @@ class Deity < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -8,11 +8,7 @@ class Flora < ApplicationRecord
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -6,11 +6,7 @@ class Government < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -8,11 +8,7 @@ class Group < ApplicationRecord
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -13,13 +13,7 @@ class Item < ApplicationRecord
belongs_to :user
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -7,11 +7,7 @@ class Job < ActiveRecord::Base
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -7,12 +7,7 @@ class Landmark < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -9,10 +9,7 @@ class Language < ApplicationRecord
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -17,12 +17,7 @@ class Location < ApplicationRecord
belongs_to :user
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -7,12 +7,7 @@ class Magic < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -6,11 +6,7 @@ class Planet < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -13,12 +13,7 @@ class Race < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -7,12 +7,7 @@ class Religion < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -7,13 +7,7 @@ class Scene < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -6,11 +6,7 @@ class Technology < ApplicationRecord
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -9,11 +9,7 @@ class Town < ApplicationRecord
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -7,11 +7,7 @@ class Tradition < ActiveRecord::Base
validates :user_id, presence: true
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern
include Authority::Abilities

View File

@ -8,10 +8,7 @@
class Universe < ApplicationRecord
acts_as_paranoid
include HasAttributes
include HasPrivacy
include HasImageUploads
include HasChangelog
include IsContentPage
include Serendipitous::Concern

View File

@ -6,12 +6,8 @@ class Vehicle < ActiveRecord::Base
validates :name, presence: true
validates :user_id, presence: true
include IsContentPage
include BelongsToUniverse
include HasAttributes
include HasPrivacy
include HasContentGroupers
include HasImageUploads
include HasChangelog
include Serendipitous::Concern
include Authority::Abilities

4
app/models/page_tag.rb Normal file
View File

@ -0,0 +1,4 @@
class PageTag < ApplicationRecord
belongs_to :page, polymorphic: true
belongs_to :user
end

View File

@ -4,6 +4,7 @@ class ContentSerializer
attr_accessor :categories
attr_accessor :fields
attr_accessor :attribute_values
attr_accessor :page_tags
attr_accessor :raw_model
attr_accessor :class_name, :class_color, :class_icon
@ -39,6 +40,8 @@ class ContentSerializer
self.class_color = content.class.color
self.class_icon = content.class.icon
self.page_tags = content.page_tags.pluck(:tag) || []
self.data = {
name: content.try(:name),
description: content.try(:description),

View File

@ -34,6 +34,7 @@ class User < ApplicationRecord
has_many :user_content_type_activators, dependent: :destroy
has_many :api_keys, dependent: :destroy
has_many :page_tags, dependent: :destroy
def contributable_universes
@user_contributable_universes ||= begin

View File

@ -0,0 +1,60 @@
class PageTagService < Service
def self.slug_for(text)
text.downcase.gsub(/[^0-9a-z ]/i, '').gsub(/ /, '-')
end
def self.suggested_tags_for(class_name)
case class_name
when Building.name
["School", "Business"]
when Character.name
["Main character", "Side character", "Background character"]
when Condition.name
["Disease", "Blessing", "Curse"]
when Country.name
["Kingdom", "Country", "Region"]
when Creature.name
["Domesticated", "Wild", "Humanoid"]
when Deity.name
["Good", "Evil"]
when Flora.name
["Floral", "Weed"]
when Government.name
["Republic", "Democracy", "Monarchy", "Dictatorship"]
when Group.name
["Good", "Evil"]
when Item.name
["Weapon", "Armor", "Artifact", "Relic"]
when Job.name
["Military", "Government", "Private sector"]
when Landmark.name
["Cave", "Mountain", "Temple", "Ruins"]
when Language.name
["Modern", "Ancient"]
when Location.name
["Town", "City", "River", "Mountains", "Desert"]
when Magic.name
["Spell", "Ability", "Superpower"]
when Planet.name
["Habitable", "Inhabitable"]
when Race.name
["Race", "Species", "Humanoid"]
when Religion.name
["Modern", "Ancient", "Monotheistic", "Polytheistic"]
when Scene.name
["Atmospheric", "Exposition", "Transition"]
when Technology.name
["Military", "Consumer", "Theoretical"]
when Town.name
["Village", "Town", "City", "Metropolis"]
when Tradition.name
["Holiday", "Practice"]
when Universe.name
["Favorite"]
when Vehicle.name
["Automobile", "Train", "Plane", "Spaceship"]
else
[]
end
end
end

View File

@ -103,7 +103,7 @@
</div>
<div>
<% if attribute_field.name_field? || attribute_field.universe_field? %>
<% if attribute_field.name_field? || attribute_field.universe_field? || attribute_field.tags_field? %>
<div>
This field cannot be deleted.
</div>

View File

@ -17,8 +17,7 @@
when 'universe'
Universe.find_by(id: serialized_field[:value].to_i)
# TODO: update all textearea/textarea --> text_area in prod data
when 'name', 'text_area', 'textearea', 'textarea'
when 'name', 'text_area'
serialized_field[:value]
when 'link'
@ -28,6 +27,9 @@
nil
end
when 'tags'
content.page_tags
else
raise "unknown field type = " + serialized_field[:type].inspect
end
@ -61,6 +63,24 @@
<% end %>
</div>
<% elsif serialized_field[:type] == 'tags' %>
<div class="tags-container">
<% value.each do |tag| %>
<% if user_signed_in? && @content.user == current_user %>
<%=
link_to send(
"page_tag_#{content.raw_model.class.name.downcase.pluralize}_path",
slug: PageTagService.slug_for(tag)
) do
%>
<span class="new badge <%= @content.class.color %> left" data-badge-caption="<%= tag %>"></span>
<% end %>
<% else %>
<span class="new badge <%= @content.class.color %> left" data-badge-caption="<%= tag %>"></span>
<% end %>
<% end %>
</div>
<% else # serialized_field[:type] == text %>
<div class="col s9 m9 l9 markdownable">
<%=

View File

@ -26,6 +26,62 @@
relation: through_class
%>
<% elsif field[:type] == 'tags' %>
<div class="content-field">
<div class="input-field">
<small><%= f.label field[:id], field[:label] %></small>
<div class="chips chips-autocomplete chips-initial"></div>
<%= f.hidden_field :page_tags, value: content.page_tags.join(',,,|||,,,'), id: 'hidden_page_tags_value' %>
<div class="help-text show-when-focused">
<i class="material-icons tiny">label</i>
Type and press enter to create a new tag, or click any of the suggested tags below to add it.
</div>
<div class="tags-container show-when-focused">
<% @suggested_page_tags.each do |tag| %>
<%=
link_to '#', class: 'js-add-tag' do
%>
<span class="new badge grey left hoverable" data-badge-caption="<%= tag %>"></span>
<% end %>
<% end %>
</div>
<div class="clearfix"></div>
</div>
</div>
<%= content_for :javascript do %>
function update_hidden_page_tag_value(e) {
var chips = M.Chips.getInstance($('.chips')).chipsData.map(function (c) {
return c['tag'];
});
var hidden_input = $('#hidden_page_tags_value').first();
hidden_input.val(chips.join(',,,|||,,,'));
}
var chips = $('.chips-autocomplete').chips({
placeholder: 'Tag this page',
secondaryPlaceholder: '+ Tag',
autocompleteOptions: {
data: {
<% @content.page_tags.pluck(:tag).each do |tag| %>
'<%= tag %>': null,
<% end %>
},
limit: 100,
minLength: 1
},
data: [
<% @content.page_tags.pluck(:tag).each do |tag| %>
{tag: '<%= tag %>'},
<% end %>
],
onChipAdd: update_hidden_page_tag_value,
onChipDelete: update_hidden_page_tag_value
});
<% end %>
<% elsif field[:type] == 'universe' %>
<div class="content-field">
<div class="input-field">

View File

@ -6,7 +6,29 @@
<%= render partial: 'content/components/parallax_header', locals: { content_type: content_type, content_class: @content_type_class } %>
<% end %>
<% if @page_tags.any? %>
<div class="tags-container">
<span class="left grey-text">View by tag:&nbsp;</span>
<%= link_to polymorphic_path(@content_type_class) do %>
<span class="new badge <%= params.key?(:slug) ? 'grey' : @content_type_class.color %> left" data-badge-caption="All <%= content_type.pluralize %>"></span>
<% end %>
<% @page_tags.each do |tag| %>
<%=
link_to send(
"page_tag_#{content_type.pluralize}_path",
slug: PageTagService.slug_for(tag.tag)
) do
%>
<span class="new badge <%= params[:slug] == tag.slug ? @content_type_class.color : 'grey' %> left" data-badge-caption="<%= tag.tag %>"></span>
<% end %>
<% end %>
</div>
<div style="clear: both"></div>
<% end %>
<% if @content.any? %>
<%= render partial: 'content/components/list_filter_bar', locals: { } %>
<div class="card">
<%= render partial: 'content/list/list', locals: { content_list: @content, content_type: @content_type_class, show_add_another_form: true } %>

View File

@ -53,7 +53,23 @@
data-position="bottom" data-delay="100" data-tooltip="You have been added as a contributor to this universe and its content."></span>
<% end %>
</span>
<p class='grey-text'>
<p class="tags-container">
<% content.page_tags.each do |tag| %>
<% if user_signed_in? && content.user == current_user %>
<%=
link_to send(
"page_tag_#{content.class.name.downcase.pluralize}_path",
slug: PageTagService.slug_for(tag.tag)
) do
%>
<span class="new badge <%= params[:slug] == tag.slug ? @content_type_class.color : 'grey' %> left" data-badge-caption="<%= tag.tag %>"></span>
<% end %>
<% else %>
<span class="new badge <%= params[:slug] == tag.slug ? @content_type_class.color : 'grey' %> left" data-badge-caption="<%= tag.tag %>"></span>
<% end %>
<% end %>
</p>
<p class='grey-text' style="clear: both">
<% if user_signed_in? %>
<span class="timestamp tooltipped" data-position="bottom" data-delay="500" data-tooltip="<%= content.updated_at.strftime("%m/%d/%Y %H:%M") %>" style="font-size: 80%">
<i class="material-icons">mode_edit</i>
@ -71,7 +87,7 @@
<% end %>
</p>
<span class="secondary-content hide-on-med-and-up">
<% if user_signed_in? && content.user_id == current_user.id %>
<% if user_signed_in? && content.updatable_by?(current_user) %>
<%# todo also show if you're a contributor %>
<%= link_to edit_polymorphic_path(content.page_type.downcase, id: content.id), class: 'js-edit-hover' do %>
<i class="material-icons">edit</i>

View File

@ -31,12 +31,12 @@
<%= render partial: 'content/keyboard_controls_help_modal' %>
<script type="text/javascript">
<%= yield :javascript %>
$(document).ready(function() {
$('.tooltipped').tooltip({ enterDelay: 50 });
M.AutoInit();
$('.dropdown-trigger').dropdown({coverTrigger: false});
<%= yield :javascript %>
});
</script>

View File

@ -15,6 +15,9 @@
:label: Type of building
- :name: alternate_names
:label: Alternate names
- :name:
:label: Tags
:field_type: tags
:occupants:
:label: Occupants
:icon: recent_actors

View File

@ -16,6 +16,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:looks:
:label: Looks
:icon: face

View File

@ -15,6 +15,9 @@
:label: Type of condition
- :name: alternate_names
:label: Alternate names
- :name:
:label: Tags
:field_type: tags
:causes:
:label: Causes
:icon: bubble_chart

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:points_of_interest:
:label: Points of interest
:icon: location_on

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:looks:
:label: Looks
:icon: pets

View File

@ -13,6 +13,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:appearance:
:label: Appearance
:icon: accessibility

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:classification:
:label: Classification
:icon: bubble_chart

View File

@ -11,6 +11,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:structure:
:label: Structure
:icon: view_list

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:hierarchy:
:label: Hierarchy
:icon: call_split

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:looks:
:label: Looks
:icon: redeem

View File

@ -14,6 +14,9 @@
:label: Type of job
- :name: alternate_names
:label: Alternate names
- :name:
:label: Tags
:field_type: tags
:requirements:
:label: Requirements
:icon: storage

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:location:
:label: Whereabouts
:icon: location_on

View File

@ -10,6 +10,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:info:
:label: Info
:icon: forum

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:culture:
:label: Culture
:icon: face

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:appearance:
:label: Appearance
:icon: flash_on

View File

@ -11,6 +11,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:geography:
:label: Geography
:icon: layers

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:looks:
:label: Looks
:icon: face

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:history:
:label: History
:icon: date_range

View File

@ -10,6 +10,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:looks:
:label: members
:icon: face

View File

@ -12,6 +12,9 @@
- :name: universe_id
:label: Universe
:field_type: universe
- :name:
:label: Tags
:field_type: tags
:production:
:label: Production
:icon: build

View File

@ -15,6 +15,9 @@
- :name: countries
:label: Country
:field_type: link
- :name:
:label: Tags
:field_type: tags
:populace:
:label: Populace
:icon: group

View File

@ -14,6 +14,9 @@
:label: Type of tradition
- :name: alternate_names
:label: Alternate names
- :name:
:label: Tags
:field_type: tags
:observance:
:label: Observance
:icon: track_changes

View File

@ -9,6 +9,12 @@
:label: Description
- :name: genre
:label: Genre
- :name:
:label: Tags
:field_type: tags
- :name:
:label: Tags
:field_type: tags
:history:
:label: History
:icon: date_range

View File

@ -14,6 +14,9 @@
:label: Type of vehicle
- :name: alternate_names
:label: Alternate names
- :name:
:label: Tags
:field_type: tags
:looks:
:label: Looks
:icon: airport_shuttle

View File

@ -10,6 +10,7 @@ Rails.application.routes.draw do
# get :characters, on: :member <...etc...>
Rails.application.config.content_types[:all].each do |content_type|
get content_type.name.downcase.pluralize.to_sym, on: :member
# todo page tags here
end
end
scope '/my' do
@ -82,11 +83,13 @@ Rails.application.routes.draw do
get content_type.name.downcase.pluralize.to_sym, on: :member
end
get :changelog, on: :member
get '/tagged/:slug', action: :index, on: :collection, as: :page_tag
end
Rails.application.config.content_types[:all_non_universe].each do |content_type|
# resources :characters do
resources content_type.name.downcase.pluralize.to_sym do
get :changelog, on: :member
get '/tagged/:slug', action: :index, on: :collection, as: :page_tag
end
end

View File

@ -0,0 +1,13 @@
class CreatePageTags < ActiveRecord::Migration[5.2]
def change
create_table :page_tags do |t|
t.references :page, polymorphic: true
t.string :tag
t.string :slug
t.string :color
t.references :user, foreign_key: true
t.timestamps
end
end
end

View File

@ -0,0 +1,5 @@
class AddIndexToPageTypes < ActiveRecord::Migration[5.2]
def change
add_index(:page_tags, [:user_id, :page_type])
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_01_09_201055) do
ActiveRecord::Schema.define(version: 2019_02_16_080611) do
create_table "api_keys", force: :cascade do |t|
t.integer "user_id"
@ -1434,6 +1434,20 @@ ActiveRecord::Schema.define(version: 2019_01_09_201055) do
t.datetime "updated_at", null: false
end
create_table "page_tags", force: :cascade do |t|
t.string "page_type"
t.integer "page_id"
t.string "tag"
t.string "slug"
t.string "color"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["page_type", "page_id"], name: "index_page_tags_on_page_type_and_page_id"
t.index ["user_id", "page_type"], name: "index_page_tags_on_user_id_and_page_type"
t.index ["user_id"], name: "index_page_tags_on_user_id"
end
create_table "past_ownerships", force: :cascade do |t|
t.integer "user_id"
t.integer "item_id"
@ -2374,11 +2388,13 @@ ActiveRecord::Schema.define(version: 2019_01_09_201055) do
t.string "age"
t.string "gender"
t.string "interests"
t.string "slug"
t.index ["deleted_at", "username"], name: "index_users_on_deleted_at_and_username"
t.index ["deleted_at"], name: "index_users_on_deleted_at"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["id", "deleted_at"], name: "index_users_on_id_and_deleted_at"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["slug"], name: "index_users_on_slug", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end

15
test/fixtures/page_tags.yml vendored Normal file
View File

@ -0,0 +1,15 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
page: one
page_type: Page
tag: MyString
color: MyString
user: one
two:
page: two
page_type: Page
tag: MyString
color: MyString
user: two

View File

@ -0,0 +1,7 @@
require 'test_helper'
class PageTagTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end