Merge pull request #41 from indentlabs/issue-15

Make content shareable
This commit is contained in:
Andrew Brown 2016-09-23 23:05:10 +02:00 committed by GitHub
commit acd0ddea3b
21 changed files with 265 additions and 15 deletions

View File

@ -0,0 +1,3 @@
$(document).ready ->
$('.share').click ->
$('#share-modal').openModal()

View File

@ -14,6 +14,7 @@ class Character < ActiveRecord::Base
belongs_to :universe
include HasPrivacy
include HasContentGroupers
# Characters
@ -31,7 +32,7 @@ class Character < ActiveRecord::Base
# Items
relates :favorite_items, with: :ownerships, where: { favorite: true }
scope :is_public, -> { joins(:universe).where(universes: { privacy: "public" }) }
scope :is_public, -> { joins(:universe).where('universes.privacy = ? OR characters.privacy = ?', 'public', 'public') }
def description
role

View File

@ -0,0 +1,16 @@
require 'active_support/concern'
module HasPrivacy
extend ActiveSupport::Concern
included do
def private_content?
!public_content?
end
def public_content?
universe_is_public = respond_to?(:universe) && universe.present? && universe.public_content?
privacy == 'public' || universe_is_public
end
end
end

View File

@ -12,6 +12,7 @@ class Item < ActiveRecord::Base
belongs_to :user
belongs_to :universe
include HasPrivacy
include HasContentGroupers
# Characters
@ -19,7 +20,7 @@ class Item < ActiveRecord::Base
relates :current_owners, with: :current_ownerships
relates :makers, with: :maker_relationships
scope :is_public, -> { joins(:universe).where(universes: { privacy: "public" }) }
scope :is_public, -> { joins(:universe).where('universes.privacy = ? OR items.privacy = ?', 'public', 'public') }
def self.color
'amber'

View File

@ -15,6 +15,7 @@ class Location < ActiveRecord::Base
belongs_to :user
belongs_to :universe
include HasPrivacy
include HasContentGroupers
# Characters
@ -25,7 +26,7 @@ class Location < ActiveRecord::Base
relates :largest_cities, with: :largest_cities_relationships
relates :notable_cities, with: :notable_cities_relationships
scope :is_public, -> { joins(:universe).where(universes: { privacy: "public" }) }
scope :is_public, -> { joins(:universe).where('universes.privacy = ? OR locations.privacy = ?', 'public', 'public') }
def self.icon
'terrain'

View File

@ -6,6 +6,8 @@
#
# contains all canonically-related content created by Users
class Universe < ActiveRecord::Base
include HasPrivacy
validates :name, presence: true
belongs_to :user

View File

@ -0,0 +1,31 @@
<div id="share-modal" class="modal">
<div class="modal-content">
<h4>Share <%= shared_content.name %></h4>
<div class="row">
<div class="input-field col s12">
<input type="text" id="share_url" readonly onclick="this.focus();this.select()" value="<%= polymorphic_url(shared_content) %>">
<label for="share_url">Share URL</label>
</div>
</div>
<div class="row">
<p class="col s12">To be shareable, content must be <b>public</b> <em>or</em> in a <b>public</b> Universe.</p>
</div>
<% if ((shared_content.respond_to? :universe) && shared_content.universe.present?) %>
<div class="row">
<%= render partial: 'content/form/privacy_toggle', locals: { content: shared_content.universe } %>
</div>
<% end %>
<% if shared_content.respond_to? :privacy %>
<div class="row">
<%= render partial: 'content/form/privacy_toggle', locals: { content: shared_content } %>
</div>
<% end %>
</div>
<div class="modal-footer">
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">close</a>
</div>
</div>

View File

@ -20,6 +20,7 @@ set_meta_tags title: content.name, description: content.description
<div class="card-content">
<div class="card-title center">
<span class="<%= content.class.color %>-text"><i class="material-icons right"><%= content.class.icon %></i></span>
<a href="#" title="Share" class="share <%= content.class.color %>-text"><i class="material-icons right">share</i></a>
<%= content.name %>
</div>
<ul class="tabs">
@ -77,3 +78,5 @@ set_meta_tags title: content.name, description: content.description
</div>
</div>
</div>
<%= render partial: 'content/share', locals: { shared_content: @content} %>

View File

@ -6,7 +6,7 @@
<ul id='options-menu' class='dropdown-content'>
<%# TODO: something with these %>
<li><a href="#!">Share this <%= content.class.to_s.downcase %></a></li>
<li><a href="#!" class="share">Share this <%= content.class.to_s.downcase %></a></li>
<li><a href="#!">Do something else</a></li>
<li class="divider"></li>
<% if content.persisted? %>
@ -17,4 +17,4 @@
:confirm => 'Are you sure? This action cannot be undone!' %>
</li>
<% end %>
</ul>
</ul>

View File

@ -0,0 +1,13 @@
<%= form_for(content, remote: true, html: {role: :form, 'data-model': content.class.model_name}) do |form|%>
<div class="switch">
<div class="col s6">
<b><%= content.name %></b>s privacy setting:
</div>
<label class="col s6 right-align">
private
<%= form.check_box :privacy, { onchange: '$(this).submit();' }, 'public', 'private' %>
<span class="lever"></span>
public
</label>
</div>
<%end%>

View File

@ -1,3 +1,5 @@
<%= form_for @content do |form| %>
<%= render partial: 'content/form', locals: { f: form, content: @content } %>
<% end %>
<% end %>
<%= render partial: 'content/share', locals: { shared_content: @content} %>

View File

@ -0,0 +1,5 @@
class AddPrivacyToCharacters < ActiveRecord::Migration
def change
add_column :characters, :privacy, :string
end
end

View File

@ -0,0 +1,5 @@
class AddPrivacyToItems < ActiveRecord::Migration
def change
add_column :items, :privacy, :string, default: 'private', null: false
end
end

View File

@ -0,0 +1,5 @@
class AddPrivacyToLocations < ActiveRecord::Migration
def change
add_column :locations, :privacy, :string, default: 'private', null: false
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160903223957) do
ActiveRecord::Schema.define(version: 20160922204317) do
create_table "archenemyships", force: :cascade do |t|
t.integer "user_id"
@ -79,6 +79,7 @@ ActiveRecord::Schema.define(version: 20160903223957) do
t.integer "universe_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "privacy"
end
create_table "childrenships", force: :cascade do |t|
@ -102,7 +103,7 @@ ActiveRecord::Schema.define(version: 20160903223957) do
end
create_table "items", force: :cascade do |t|
t.string "name", null: false
t.string "name", null: false
t.string "item_type"
t.text "description"
t.string "weight"
@ -118,6 +119,7 @@ ActiveRecord::Schema.define(version: 20160903223957) do
t.integer "universe_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "privacy", default: "private", null: false
end
create_table "largest_cities_relationships", force: :cascade do |t|
@ -133,7 +135,7 @@ ActiveRecord::Schema.define(version: 20160903223957) do
end
create_table "locations", force: :cascade do |t|
t.string "name", null: false
t.string "name", null: false
t.string "type_of"
t.text "description"
t.string "map_file_name"
@ -158,6 +160,7 @@ ActiveRecord::Schema.define(version: 20160903223957) do
t.integer "universe_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "privacy", default: "private", null: false
end
create_table "maker_relationships", force: :cascade do |t|

View File

@ -27,4 +27,12 @@ FactoryGirl.define do
user
universe
end
factory :item do
sequence :name do |n|
"Item #{n}"
end
user
universe
end
end

47
test/has_privacy_test.rb Normal file
View File

@ -0,0 +1,47 @@
require 'active_support/concern'
module HasPrivacyTest
extend ActiveSupport::Concern
included do
test 'responds to public_content' do
assert_respond_to(@object, :public_content?)
end
test 'responds to private_content' do
assert_respond_to(@object, :private_content?)
end
test 'object is public when privacy field contains "public"' do
@object.universe.privacy = 'private'
@object.privacy = 'public'
assert @object.public_content?
refute @object.private_content?
end
test 'object is private when privacy field contains "private"' do
@object.universe.privacy = 'private'
@object.privacy = 'private'
assert @object.private_content?
refute @object.public_content?
end
test 'object is private when privacy field is empty' do
@object.universe.privacy = 'private'
@object.privacy = ''
assert @object.private_content?
refute @object.public_content?
end
test 'object is public when universe is public' do
@object.universe.privacy = 'public'
@object.privacy = 'private'
assert @object.public_content?
refute @object.private_content?
end
end
end

View File

@ -1,10 +1,38 @@
require 'test_helper'
require 'has_privacy_test'
# Tests for the model class Character
class CharacterTest < ActiveSupport::TestCase
test 'character not valid without a name' do
character = build(:character, name: nil)
include HasPrivacyTest
refute character.valid?, 'Character name not being validated for presence'
setup do
@character = build(:character)
# for HasPrivacyTest
@object = @character
end
test 'character not valid without a name' do
@character.name = nil
refute @character.valid?, 'Character name not being validated for presence'
end
test 'character is_public scope' do
public_universe = create(:universe, privacy: 'public')
private_universe = create(:universe, privacy: 'private')
pub_character_pub_universe = create(:character, privacy: 'public', universe: public_universe)
pub_character_priv_universe = create(:character, privacy: 'public', universe: private_universe)
priv_character_pub_universe = create(:character, privacy: 'private', universe: public_universe)
priv_character_priv_universe = create(:character, privacy: 'private', universe: private_universe)
public_scope = Character.is_public
assert_includes public_scope, pub_character_pub_universe, "didn't contain a public character in a public universe"
assert_includes public_scope, pub_character_priv_universe, "didn't contain a public character in a private universe"
assert_includes public_scope, priv_character_pub_universe, "didn't contain a private character in a public universe"
refute_includes public_scope, priv_character_priv_universe, "contained a private character in a private universe"
end
end

36
test/models/item_test.rb Normal file
View File

@ -0,0 +1,36 @@
require 'test_helper'
require 'has_privacy_test'
# Tests for the Location model class
class ItemTest < ActiveSupport::TestCase
include HasPrivacyTest
setup do
@item = create(:item)
@object = @item
end
test 'item not valid without a name' do
@item.name = nil
refute @item.valid?, 'Item name is not being validated for presence'
end
test 'item is_public scope' do
public_universe = create(:universe, privacy: 'public')
private_universe = create(:universe, privacy: 'private')
pub_item_pub_universe = create(:item, privacy: 'public', universe: public_universe)
pub_item_priv_universe = create(:item, privacy: 'public', universe: private_universe)
priv_item_pub_universe = create(:item, privacy: 'private', universe: public_universe)
priv_item_priv_universe = create(:item, privacy: 'private', universe: private_universe)
public_scope = Item.is_public
assert_includes public_scope, pub_item_pub_universe, "didn't contain a public item in a public universe"
assert_includes public_scope, pub_item_priv_universe, "didn't contain a public item in a private universe"
assert_includes public_scope, priv_item_pub_universe, "didn't contain a private item in a public universe"
refute_includes public_scope, priv_item_priv_universe, "contained a private item in a private universe"
end
end

View File

@ -1,10 +1,36 @@
require 'test_helper'
require 'has_privacy_test'
# Tests for the Location model class
class LocationTest < ActiveSupport::TestCase
test 'location not valid without a name' do
location = build(:location, name: nil)
include HasPrivacyTest
refute location.valid?, 'Location name is not being validated for presence'
setup do
@location = create(:location)
@object = @location
end
test 'location not valid without a name' do
@location.name = nil
refute @location.valid?, 'Location name is not being validated for presence'
end
test 'location is_public scope' do
public_universe = create(:universe, privacy: 'public')
private_universe = create(:universe, privacy: 'private')
pub_location_pub_universe = create(:location, privacy: 'public', universe: public_universe)
pub_location_priv_universe = create(:location, privacy: 'public', universe: private_universe)
priv_location_pub_universe = create(:location, privacy: 'private', universe: public_universe)
priv_location_priv_universe = create(:location, privacy: 'private', universe: private_universe)
public_scope = Location.is_public
assert_includes public_scope, pub_location_pub_universe, "didn't contain a public location in a public universe"
assert_includes public_scope, pub_location_priv_universe, "didn't contain a public location in a private universe"
assert_includes public_scope, priv_location_pub_universe, "didn't contain a private location in a public universe"
refute_includes public_scope, priv_location_priv_universe, "contained a private location in a private universe"
end
end

View File

@ -7,4 +7,18 @@ class UniverseTest < ActiveSupport::TestCase
refute universe.valid?, 'Universe name is not being validated for presence'
end
test 'universe is private when privacy field contains "private"' do
universe = build(:universe, privacy: 'private')
assert universe.private_content?
refute universe.public_content?
end
test 'universe is private when privacy field is empty' do
universe = build(:universe, privacy: '')
assert universe.private_content?
refute universe.public_content?
end
end