storytime 1.0.7 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/storytime/subscriptions.js +0 -2
- data/app/assets/javascripts/storytime/subscriptions.js.coffee +2 -0
- data/app/assets/stylesheets/storytime/posts.css.scss +5 -4
- data/app/assets/stylesheets/storytime/sites.css.scss +0 -4
- data/app/assets/stylesheets/storytime/subscriptions.css.scss +0 -0
- data/app/controllers/storytime/dashboard/posts_controller.rb +19 -2
- data/app/controllers/storytime/dashboard/subscriptions_controller.rb +83 -0
- data/app/controllers/storytime/posts_controller.rb +25 -0
- data/app/controllers/storytime/subscriptions_controller.rb +21 -5
- data/app/helpers/storytime/dashboard/media_helper.rb +1 -5
- data/app/helpers/storytime/subscriptions_helper.rb +16 -0
- data/app/mailers/storytime/subscription_mailer.rb +13 -0
- data/app/models/storytime/action.rb +1 -0
- data/app/models/storytime/permission.rb +12 -9
- data/app/models/storytime/post.rb +3 -3
- data/app/models/storytime/site.rb +15 -0
- data/app/models/storytime/subscription.rb +24 -0
- data/app/policies/storytime/post_policy.rb +1 -1
- data/app/policies/storytime/subscription_policy.rb +43 -0
- data/app/views/storytime/application/storytime/_header.html.erb +5 -1
- data/app/views/storytime/dashboard/_navigation.html.erb +2 -0
- data/app/views/storytime/dashboard/posts/_form.html.erb +6 -0
- data/app/views/storytime/dashboard/subscriptions/_subscription.html.erb +10 -0
- data/app/views/storytime/dashboard/subscriptions/edit.html.erb +10 -0
- data/app/views/storytime/dashboard/subscriptions/index.html.erb +19 -0
- data/app/views/storytime/dashboard/subscriptions/new.html.erb +9 -0
- data/app/views/storytime/subscription_mailer/new_post_email.html.erb +3 -2
- data/app/views/storytime/subscription_mailer/new_post_email.text.erb +7 -0
- data/app/views/storytime/subscriptions/_form.html.erb +5 -0
- data/app/views/storytime/subscriptions/_modal.html.erb +16 -0
- data/config/locales/en.yml +13 -1
- data/config/routes.rb +6 -15
- data/db/migrate/20141111164439_create_storytime_subscriptions.rb +14 -0
- data/db/migrate/20150122200805_add_title_and_content_index_to_storytime_post.rb +56 -0
- data/db/migrate/20150129215308_add_site_id_to_storytime_subscription.rb +5 -0
- data/lib/generators/templates/storytime.rb +9 -0
- data/lib/storytime/concerns/has_versions.rb +0 -1
- data/lib/storytime/engine.rb +2 -0
- data/lib/storytime/mysql_fulltext_search_adapter.rb +7 -0
- data/lib/storytime/mysql_search_adapter.rb +7 -0
- data/lib/storytime/postgres_search_adapter.rb +9 -0
- data/lib/storytime/sqlite3_search_adapter.rb +7 -0
- data/lib/storytime/version.rb +1 -1
- data/lib/storytime.rb +43 -0
- data/spec/controllers/subscriptions_controller_spec.rb +0 -0
- data/spec/dummy/config/environments/development.rb +8 -0
- data/spec/dummy/config/initializers/storytime.rb +37 -2
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150130213631_create_storytime_posts.storytime.rb +18 -0
- data/spec/dummy/db/migrate/20150130213632_create_friendly_id_slugs.storytime.rb +16 -0
- data/spec/dummy/db/migrate/20150130213633_create_storytime_media.storytime.rb +11 -0
- data/spec/dummy/db/migrate/20150130213634_create_storytime_sites.storytime.rb +14 -0
- data/spec/dummy/db/migrate/20150130213635_create_storytime_tags.storytime.rb +10 -0
- data/spec/dummy/db/migrate/20150130213636_create_storytime_taggings.storytime.rb +11 -0
- data/spec/dummy/db/migrate/20150130213637_create_storytime_versions.storytime.rb +13 -0
- data/spec/dummy/db/migrate/20150130213638_create_storytime_roles.storytime.rb +10 -0
- data/spec/dummy/db/migrate/20150130213639_add_storytime_role_id_to_users.storytime.rb +7 -0
- data/spec/dummy/db/migrate/20150130213640_create_storytime_permissions.storytime.rb +11 -0
- data/spec/dummy/db/migrate/20150130213641_create_storytime_actions.storytime.rb +11 -0
- data/spec/dummy/db/migrate/20150130213642_create_storytime_comments.storytime.rb +12 -0
- data/spec/dummy/db/migrate/20150130213643_add_storytime_name_to_users.storytime.rb +6 -0
- data/spec/dummy/db/migrate/20150130213644_create_storytime_autosaves.storytime.rb +13 -0
- data/spec/dummy/db/migrate/20150130213645_add_secondary_media_id_to_storytime_post.storytime.rb +6 -0
- data/spec/dummy/db/migrate/20150130213646_create_storytime_snippets.storytime.rb +22 -0
- data/spec/dummy/db/migrate/20150130213647_create_storytime_subscriptions.storytime.rb +15 -0
- data/spec/dummy/db/migrate/20150130213648_add_title_and_content_index_to_storytime_post.storytime.rb +57 -0
- data/spec/dummy/db/migrate/20150130213649_add_site_id_to_storytime_subscription.storytime.rb +6 -0
- data/spec/dummy/db/schema.rb +10 -2
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/factories/subscription_factories.rb +5 -5
- data/spec/features/dashboard/posts_spec.rb +0 -1
- data/spec/features/dashboard/subscription_spec.rb +37 -48
- data/spec/features/posts_spec.rb +2 -2
- data/spec/features/subscription_spec.rb +45 -15
- data/spec/lib/mysql_fulltext_search_adapter_spec.rb +31 -0
- data/spec/lib/mysql_search_adapter_spec.rb +31 -0
- data/spec/lib/postgres_search_adapter_spec.rb +31 -0
- data/spec/lib/sqlite3_search_adapter_spec.rb +31 -0
- data/spec/models/subscription_spec.rb +27 -27
- data/spec/requests/routings_spec.rb +2 -0
- metadata +71 -4
- data/app/views/storytime/subscription_mailer/new_post_email.txt.erb +0 -1
- data/lib/storytime/subscription_emails.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06f4a653cab5a07931cdc7c80d0892bd5a7daa12
|
4
|
+
data.tar.gz: 3fb261085ce26f70bf249ce1724a3005afa3c6f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d35eeeb18f0d289a16f3a7b312d2e76f17220dfd57b0c6077cea8de1012dc9a0227cdac33c8a05a444e5d819cd5b03e70b8e79138d8e14490ca959314cfe4e0
|
7
|
+
data.tar.gz: 5b5621d9c72c07e3ede66912eefc1c06a629ffca917075915e153bdf0e4a7f7aee85d14c262f8670654c520aea03fec3c435544f79384e06c724c540d3eb47a7
|
@@ -1,7 +1,3 @@
|
|
1
|
-
/*
|
2
|
-
Place all the styles related to the matching controller here.
|
3
|
-
They will automatically be included in application.css.
|
4
|
-
*/
|
5
1
|
.row.page-admin {
|
6
2
|
padding: 10px;
|
7
3
|
&:hover {
|
@@ -26,4 +22,9 @@
|
|
26
22
|
|
27
23
|
.post_field {
|
28
24
|
margin: 15px 0px;
|
25
|
+
}
|
26
|
+
|
27
|
+
.notify_subscribers_checkbox {
|
28
|
+
margin-right: 30px;
|
29
|
+
margin-top: -3px;
|
29
30
|
}
|
File without changes
|
@@ -38,7 +38,9 @@ module Storytime
|
|
38
38
|
|
39
39
|
if @post.save
|
40
40
|
@post.create_autosave(post_params.slice(:draft_content)) if params[:preview] == "true"
|
41
|
-
|
41
|
+
|
42
|
+
publish if post_params['published'] == "1"
|
43
|
+
|
42
44
|
opts = params[:preview] == "true" ? { preview: true } : {}
|
43
45
|
|
44
46
|
redirect_to edit_dashboard_post_path(@post, opts), notice: I18n.t('flash.posts.create.success')
|
@@ -51,9 +53,12 @@ module Storytime
|
|
51
53
|
def update
|
52
54
|
authorize @post
|
53
55
|
@post.draft_user_id = current_user.id
|
54
|
-
|
56
|
+
|
55
57
|
if @post.update(post_params)
|
56
58
|
@post.autosave.destroy unless @post.autosave.nil?
|
59
|
+
|
60
|
+
publish if post_params['published'] == "1"
|
61
|
+
|
57
62
|
redirect_to [:edit, :dashboard, @post], notice: I18n.t('flash.posts.update.success')
|
58
63
|
else
|
59
64
|
load_media
|
@@ -96,6 +101,18 @@ module Storytime
|
|
96
101
|
params.require(:post).permit(*permitted_attrs)
|
97
102
|
end
|
98
103
|
|
104
|
+
def publish
|
105
|
+
unless @post.published?
|
106
|
+
@post.publish!
|
107
|
+
|
108
|
+
if post_params[:send_subscriber_email] == "1"
|
109
|
+
@site.active_email_subscriptions.each do |subscription|
|
110
|
+
Storytime::SubscriptionMailer.new_post_email(@post, subscription).deliver
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
99
116
|
def current_post_type
|
100
117
|
@current_post_type ||= begin
|
101
118
|
type_param = params[:type] || (params[:post] && params[:post].delete(:type))
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_dependency "storytime/application_controller"
|
2
|
+
|
3
|
+
module Storytime
|
4
|
+
module Dashboard
|
5
|
+
class SubscriptionsController < DashboardController
|
6
|
+
skip_before_action :authenticate_user!, only: [:unsubscribe]
|
7
|
+
skip_before_action :verify_storytime_user, only: [:unsubscribe]
|
8
|
+
|
9
|
+
before_action :load_subscriptions, only: [:index]
|
10
|
+
before_action :set_subscription, only: [:edit, :update, :destroy]
|
11
|
+
|
12
|
+
skip_after_action :verify_authorized, only: [:unsubscribe]
|
13
|
+
|
14
|
+
respond_to :json, only: :destroy
|
15
|
+
|
16
|
+
def index
|
17
|
+
authorize @subscriptions
|
18
|
+
end
|
19
|
+
|
20
|
+
def new
|
21
|
+
@subscription = Storytime::Subscription.new
|
22
|
+
authorize @subscription
|
23
|
+
end
|
24
|
+
|
25
|
+
def create
|
26
|
+
@subscription = Storytime::Subscription.new(subscription_params)
|
27
|
+
authorize @subscription
|
28
|
+
|
29
|
+
if @subscription.save
|
30
|
+
redirect_to dashboard_subscriptions_path, notice: I18n.t('flash.subscriptions.create.success')
|
31
|
+
else
|
32
|
+
render :new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def edit
|
37
|
+
authorize @subscription
|
38
|
+
end
|
39
|
+
|
40
|
+
def update
|
41
|
+
authorize @subscription
|
42
|
+
|
43
|
+
if @subscription.update(subscription_params)
|
44
|
+
redirect_to dashboard_subscriptions_path, notice: I18n.t('flash.subscriptions.update.success')
|
45
|
+
else
|
46
|
+
render :edit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
authorize @subscription
|
52
|
+
@subscription.destroy
|
53
|
+
respond_with @subscription
|
54
|
+
end
|
55
|
+
|
56
|
+
def unsubscribe
|
57
|
+
@subscription = Storytime::Subscription.find_by(token: params[:t])
|
58
|
+
|
59
|
+
if @subscription.nil?
|
60
|
+
redirect_to main_app.storytime_path, alert: I18n.t('flash.subscriptions.unsubscribe.not_found')
|
61
|
+
else
|
62
|
+
@subscription.update_attributes(subscribed: false)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def subscription_params
|
69
|
+
subscription = @subscription || Storytime::Subscription.new
|
70
|
+
permitted_attrs = policy(subscription).permitted_attributes
|
71
|
+
params.require(:subscription).permit(*permitted_attrs)
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_subscription
|
75
|
+
@subscription = Storytime::Subscription.find(params[:id])
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_subscriptions
|
79
|
+
@subscriptions = Storytime::Subscription.order(created_at: :desc).page(params[:page_number]).per(10)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -12,6 +12,8 @@ module Storytime
|
|
12
12
|
Post.primary_feed
|
13
13
|
end
|
14
14
|
|
15
|
+
@posts = Storytime.search_adapter.search(params[:search], get_search_type) if (params[:search] && params[:search].length > 0)
|
16
|
+
|
15
17
|
@posts = @posts.tagged_with(params[:tag]) if params[:tag]
|
16
18
|
@posts = @posts.published.order(published_at: :desc).page(params[:page])
|
17
19
|
|
@@ -48,5 +50,28 @@ module Storytime
|
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
53
|
+
private
|
54
|
+
|
55
|
+
def get_search_type
|
56
|
+
if params[:type]
|
57
|
+
legal_search_types(params[:type])
|
58
|
+
else
|
59
|
+
Storytime::Post
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def legal_search_types(type)
|
64
|
+
begin
|
65
|
+
if Object.const_defined?("Storytime::#{type.camelize}")
|
66
|
+
"Storytime::#{type.camelize}".constantize
|
67
|
+
elsif Object.const_defined?("#{type.camelize}")
|
68
|
+
type.camelize.constantize
|
69
|
+
else
|
70
|
+
Storytime::Post
|
71
|
+
end
|
72
|
+
rescue NameError
|
73
|
+
Storytime::Post
|
74
|
+
end
|
75
|
+
end
|
51
76
|
end
|
52
77
|
end
|
@@ -4,19 +4,35 @@ module Storytime
|
|
4
4
|
class SubscriptionsController < ApplicationController
|
5
5
|
before_action :set_subscription, only: [:destroy]
|
6
6
|
|
7
|
-
def
|
8
|
-
@
|
9
|
-
|
7
|
+
def create
|
8
|
+
@subscription = Storytime::Subscription.new(permitted_attributes)
|
9
|
+
|
10
|
+
if @subscription.save
|
11
|
+
flash[:notice] = I18n.t('flash.subscriptions.create.success')
|
12
|
+
else
|
13
|
+
flash[:error] = I18n.t('flash.subscriptions.create.fail')
|
14
|
+
end
|
15
|
+
|
16
|
+
redirect_to :back
|
10
17
|
end
|
11
18
|
|
12
19
|
def destroy
|
13
|
-
|
20
|
+
if params[:t] == @subscription.token
|
21
|
+
flash[:notice] = I18n.t('flash.subscriptions.destroy.success') if @subscription.unsubscribe!
|
22
|
+
else
|
23
|
+
flash[:error] = I18n.t('flash.subscriptions.destroy.fail')
|
24
|
+
end
|
25
|
+
|
26
|
+
redirect_to Storytime.home_page_path
|
14
27
|
end
|
15
28
|
|
16
29
|
private
|
17
30
|
|
31
|
+
def permitted_attributes
|
32
|
+
params.require(:subscription).permit(:email, :t, :site_id)
|
33
|
+
end
|
34
|
+
|
18
35
|
def set_subscription
|
19
|
-
binding.pry
|
20
36
|
@subscription = Storytime::Subscription.find_by(email: params[:email])
|
21
37
|
end
|
22
38
|
end
|
@@ -24,11 +24,7 @@ module Storytime
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def full_media_file_url(media, size = nil)
|
27
|
-
|
28
|
-
media.file_url(size)
|
29
|
-
else
|
30
|
-
storytime_root_post_url[0..-2]+media.file_url(size)
|
31
|
-
end
|
27
|
+
media.file_url(size)
|
32
28
|
end
|
33
29
|
end
|
34
30
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Storytime
|
2
|
+
module SubscriptionsHelper
|
3
|
+
def subscription_label(subscription)
|
4
|
+
status_label = subscription.subscribed ? "label-info" : "label-warning"
|
5
|
+
status = subscription.subscribed ? "Subscribed" : "Unsubscribed"
|
6
|
+
|
7
|
+
"<label class='label #{status_label}'>#{status}</label>".html_safe
|
8
|
+
end
|
9
|
+
|
10
|
+
def storytime_email_subscription_form(site=Storytime::Site.last)
|
11
|
+
@storytime_site = site
|
12
|
+
|
13
|
+
render "storytime/subscriptions/form"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Storytime
|
2
|
+
class SubscriptionMailer < ActionMailer::Base
|
3
|
+
default from: Storytime.subscription_email_from
|
4
|
+
|
5
|
+
def new_post_email(post, subscription)
|
6
|
+
@post = post
|
7
|
+
@subscription = subscription
|
8
|
+
@site = subscription.site
|
9
|
+
|
10
|
+
mail(to: @subscription.email, subject: "New Post from #{@site.title}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -12,6 +12,7 @@ module Storytime
|
|
12
12
|
find_by(guid: "47342a") || create(guid: "47342a", name: "Manage Site Settings")
|
13
13
|
find_by(guid: "1f7d47") || create(guid: "1f7d47", name: "Manage Users")
|
14
14
|
find_by(guid: "5qg25i") || create(guid: "5qg25i", name: "Manage Text Snippets")
|
15
|
+
find_by(guid: "d29d76") || create(guid: "d29d76", name: "Manage Email Subscriptions")
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -13,19 +13,22 @@ module Storytime
|
|
13
13
|
manage_site = Action.find_by(guid: "47342a")
|
14
14
|
manage_users = Action.find_by(guid: "1f7d47")
|
15
15
|
manage_snippets = Action.find_by(guid: "5qg25i")
|
16
|
+
manage_subscriptions = Action.find_by(guid: "d29d76")
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
find_or_create_by(role: writer, action: publish_own)
|
19
|
+
find_or_create_by(role: editor, action: publish_own)
|
20
|
+
find_or_create_by(role: admin, action: publish_own)
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
find_or_create_by(role: editor, action: manage_others)
|
23
|
+
find_or_create_by(role: admin, action: manage_others)
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
find_or_create_by(role: admin, action: manage_site)
|
26
|
+
find_or_create_by(role: admin, action: manage_users)
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
find_or_create_by(role: editor, action: manage_snippets)
|
29
|
+
find_or_create_by(role: admin, action: manage_snippets)
|
30
|
+
|
31
|
+
find_or_create_by(role: admin, action: manage_subscriptions)
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
@@ -16,7 +16,7 @@ module Storytime
|
|
16
16
|
|
17
17
|
has_one :autosave, as: :autosavable, dependent: :destroy, class_name: "Autosave"
|
18
18
|
|
19
|
-
attr_accessor :preview, :published_at_date, :published_at_time
|
19
|
+
attr_accessor :preview, :published_at_date, :published_at_time, :send_subscriber_email
|
20
20
|
|
21
21
|
validates_presence_of :title, :draft_content
|
22
22
|
validates :title, length: { in: 1..Storytime.post_title_character_limit }
|
@@ -118,11 +118,11 @@ module Storytime
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def slug_candidates
|
121
|
-
if slug.
|
121
|
+
if slug.blank? then [:title] elsif slug_changed? then [:slug] end
|
122
122
|
end
|
123
123
|
|
124
124
|
def should_generate_new_friendly_id?
|
125
|
-
|
125
|
+
slug = nil if slug == ""
|
126
126
|
slug_changed? || (slug.nil? && published_at_changed? && published_at_change.first.nil?)
|
127
127
|
end
|
128
128
|
|
@@ -5,9 +5,20 @@ module Storytime
|
|
5
5
|
enum post_slug_style: [:default, :day_and_name, :month_and_name, :post_id]
|
6
6
|
enum root_page_content: [:posts, :page]
|
7
7
|
|
8
|
+
has_many :subscriptions, dependent: :destroy
|
9
|
+
|
8
10
|
validates :root_post_id, presence: true, if: ->(site){ site.root_page_content == "page" }
|
9
11
|
validates :title, length: { in: 1..200 }
|
10
12
|
|
13
|
+
after_create :ensure_routes_updated
|
14
|
+
after_update :ensure_routes_updated
|
15
|
+
|
16
|
+
def ensure_routes_updated
|
17
|
+
if id_changed? || root_post_id_changed? || post_slug_style_changed? || root_page_content_changed?
|
18
|
+
Rails.application.reload_routes!
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
def save_with_seeds(user)
|
12
23
|
self.class.setup_seeds
|
13
24
|
user.update_attributes(storytime_role: Storytime::Role.find_by(name: "admin"))
|
@@ -23,5 +34,9 @@ module Storytime
|
|
23
34
|
def root_post_options
|
24
35
|
Storytime::Page.published
|
25
36
|
end
|
37
|
+
|
38
|
+
def active_email_subscriptions
|
39
|
+
subscriptions.active
|
40
|
+
end
|
26
41
|
end
|
27
42
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Storytime
|
2
|
+
class Subscription < ActiveRecord::Base
|
3
|
+
belongs_to :site
|
4
|
+
|
5
|
+
scope :active, -> { where(subscribed: true) }
|
6
|
+
|
7
|
+
validates_presence_of :email
|
8
|
+
validates_format_of :email, with: Storytime.email_regexp
|
9
|
+
validates :email, uniqueness: true
|
10
|
+
|
11
|
+
before_create :generate_token
|
12
|
+
|
13
|
+
def generate_token
|
14
|
+
key = Rails.application.secrets.secret_key_base
|
15
|
+
digest = OpenSSL::Digest.new('sha1')
|
16
|
+
|
17
|
+
self.token = OpenSSL::HMAC.hexdigest(digest, key, self.email)
|
18
|
+
end
|
19
|
+
|
20
|
+
def unsubscribe!
|
21
|
+
update_attributes(subscribed: false)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -79,7 +79,7 @@ module Storytime
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def permitted_attributes
|
82
|
-
attrs = [:title, :draft_content, :draft_version_id, :excerpt, :featured_media_id, :secondary_media_id, :slug, :published_at_date, :published_at_time, {:tag_list => []}]
|
82
|
+
attrs = [:title, :draft_content, :draft_version_id, :excerpt, :featured_media_id, :secondary_media_id, :slug, :published_at_date, :send_subscriber_email, :published_at_time, {:tag_list => []}]
|
83
83
|
attrs << :published if publish?
|
84
84
|
attrs
|
85
85
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Storytime
|
2
|
+
class SubscriptionPolicy
|
3
|
+
attr_reader :user, :record
|
4
|
+
|
5
|
+
def initialize(user, record)
|
6
|
+
@user = user
|
7
|
+
@post = record
|
8
|
+
end
|
9
|
+
|
10
|
+
def index?
|
11
|
+
manage?
|
12
|
+
end
|
13
|
+
|
14
|
+
def new?
|
15
|
+
manage?
|
16
|
+
end
|
17
|
+
|
18
|
+
def create?
|
19
|
+
manage?
|
20
|
+
end
|
21
|
+
|
22
|
+
def edit?
|
23
|
+
manage?
|
24
|
+
end
|
25
|
+
|
26
|
+
def update?
|
27
|
+
manage?
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy?
|
31
|
+
manage?
|
32
|
+
end
|
33
|
+
|
34
|
+
def manage?
|
35
|
+
action = Storytime::Action.find_by(guid: "d29d76")
|
36
|
+
user.storytime_role.allowed_actions.include?(action)
|
37
|
+
end
|
38
|
+
|
39
|
+
def permitted_attributes
|
40
|
+
[:email, :subscribed, :site_id]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -18,6 +18,9 @@
|
|
18
18
|
<li><%= link_to "Blog", storytime.url_for(Storytime::BlogPost.type_name.pluralize) %></li>
|
19
19
|
</ul>
|
20
20
|
<ul class="nav navbar-nav navbar-right">
|
21
|
+
<li>
|
22
|
+
<%= link_to "#{t 'layout.subscribe_to', site_name: @site.title}", "#", data: {target: "#addSubscriptionModal", toggle: "modal"} %>
|
23
|
+
</li>
|
21
24
|
<% unless user_signed_in? %>
|
22
25
|
<li><%= link_to "Sign In", main_app.new_user_session_path %></li>
|
23
26
|
<% end %>
|
@@ -25,4 +28,5 @@
|
|
25
28
|
</div>
|
26
29
|
</div>
|
27
30
|
</div>
|
28
|
-
</header>
|
31
|
+
</header>
|
32
|
+
<%= render partial: "storytime/subscriptions/modal" %>
|
@@ -26,6 +26,8 @@
|
|
26
26
|
<li <%= active_nav_item_class("media") %>><%= link_to "Media", storytime.url_for([:dashboard, Storytime::Media]) %></li>
|
27
27
|
<% end %>
|
28
28
|
|
29
|
+
<li <%= active_nav_item_class("Subscriptions") %>><%= link_to "Subscriptions", dashboard_subscriptions_path %></li>
|
30
|
+
|
29
31
|
<% if Pundit.policy(current_user, Storytime.user_class).index? %>
|
30
32
|
<li <%= active_nav_item_class("users") %>><%= link_to "Users", storytime.url_for([:dashboard, :users]) %></li>
|
31
33
|
<% end %>
|
@@ -143,6 +143,12 @@
|
|
143
143
|
<%= f.submit "Publish", class: "btn btn-primary publish", publish: true unless @post.published? %>
|
144
144
|
<%= f.submit "Update", class: "btn btn-default save" if @post.published? %>
|
145
145
|
</div>
|
146
|
+
|
147
|
+
|
148
|
+
<div class="notify_subscribers_checkbox pull-right">
|
149
|
+
<%= f.input :send_subscriber_email, as: :boolean, label: "Notify subscribers of new post" unless @post.published? %>
|
150
|
+
</div>
|
151
|
+
|
146
152
|
</div>
|
147
153
|
<% end %>
|
148
154
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<tr id="subscription_<%= subscription.id %>">
|
2
|
+
<td><%= subscription.email %></td>
|
3
|
+
<td><%= subscription_label(subscription) %></td>
|
4
|
+
<td class="right">
|
5
|
+
<div class="btn-group">
|
6
|
+
<%= link_to "Edit", edit_polymorphic_url([:dashboard, subscription]), class: "btn btn-xs btn-default" %>
|
7
|
+
<%= delete_resource_link subscription, polymorphic_url([:dashboard, subscription]) %>
|
8
|
+
</div>
|
9
|
+
</td>
|
10
|
+
</tr>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<h2>Edit Subscription</h2>
|
3
|
+
|
4
|
+
<%= simple_form_for [:dashboard, @subscription] do |f| %>
|
5
|
+
<%= f.input :site_id, as: :hidden, input_html: { value: @site.id } %>
|
6
|
+
<%= f.input :email %>
|
7
|
+
<%= f.input :subscribed, as: :boolean %>
|
8
|
+
<%= f.submit class: "btn btn-info" %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<h2>
|
3
|
+
Subscriptions
|
4
|
+
<%= link_to "New Subscription", new_dashboard_subscription_path, class: "btn btn-default pull-right" %>
|
5
|
+
</h2>
|
6
|
+
|
7
|
+
<table class="table">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th>Email</th>
|
11
|
+
<th>Subscription Status</th>
|
12
|
+
<th class="right">Actions</th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<%= render partial: 'subscription', collection: @subscriptions %>
|
17
|
+
</tbody>
|
18
|
+
</table>
|
19
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<h2>New Subscription</h2>
|
3
|
+
|
4
|
+
<%= simple_form_for [:dashboard, @subscription] do |f| %>
|
5
|
+
<%= f.input :site_id, as: :hidden, input_html: { value: @site.id } %>
|
6
|
+
<%= f.input :email %>
|
7
|
+
<%= f.submit class: "btn btn-info" %>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
@@ -4,9 +4,10 @@
|
|
4
4
|
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
|
5
5
|
</head>
|
6
6
|
<body>
|
7
|
-
<
|
7
|
+
<h4>A new post was published on <%= @site.title %></h4>
|
8
8
|
<p>
|
9
|
-
|
9
|
+
We published a new post, "<%= link_to @post.title, post_url(@post) %>", on our blog.
|
10
10
|
</p>
|
11
11
|
</body>
|
12
|
+
<footer>If you no longer want to receive these emails, <%= link_to "click here", unsubscribe_mailing_list_url(email: @subscription.email, t: @subscription.token) %>.</footer>
|
12
13
|
</html>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
A new post was published on <%= @site.title %>
|
2
|
+
|
3
|
+
We published a new post, "<%= link_to @post.title, post_url(@post) %>", on our blog.
|
4
|
+
|
5
|
+
----------
|
6
|
+
|
7
|
+
If you no longer want to receive these emails, go to <%= unsubscribe_mailing_list_url(email: @subscription.email, t: @subscription.token) %>.
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<%= simple_form_for Storytime::Subscription.new do |f| %>
|
2
|
+
<%= f.input :site_id, as: :hidden, input_html: { value: @storytime_site.id } %>
|
3
|
+
<div class="storytime-subscription-input"><%= f.input :email %></div>
|
4
|
+
<div class="storytime-subscription-submit"><%= f.submit %></div>
|
5
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div id="addSubscriptionModal" class='modal fade'>
|
2
|
+
<div class='modal-dialog'>
|
3
|
+
<div class='modal-content'>
|
4
|
+
<div class='modal-header'>
|
5
|
+
<a class='close' data-dismiss='modal'>×</a>
|
6
|
+
<h4><%= t 'layout.subscribe_to', site_name: @site.title %></h4>
|
7
|
+
</div>
|
8
|
+
<div class='modal-body'>
|
9
|
+
<p><%= t 'layout.subscribe_modal_msg', site_name: @site.title %></p>
|
10
|
+
|
11
|
+
<br>
|
12
|
+
<%= storytime_email_subscription_form %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
data/config/locales/en.yml
CHANGED
@@ -27,6 +27,17 @@ en:
|
|
27
27
|
success: "Text snippet successfully updated."
|
28
28
|
destroy:
|
29
29
|
success: "Text snippet successfully deleted."
|
30
|
+
subscriptions:
|
31
|
+
create:
|
32
|
+
success: "Subscription successfully created."
|
33
|
+
fail: "Could not create a subscription."
|
34
|
+
update:
|
35
|
+
success: "Subscription successfully updated."
|
36
|
+
destroy:
|
37
|
+
success: >
|
38
|
+
You have been successfully removed form this subscriber list.
|
39
|
+
You will no longer hear from us.
|
40
|
+
fail: "Could not unsubscribe email."
|
30
41
|
users:
|
31
42
|
create:
|
32
43
|
success: "User successfully created."
|
@@ -87,6 +98,7 @@ en:
|
|
87
98
|
new:
|
88
99
|
header: "New %{resource}"
|
89
100
|
|
90
|
-
|
91
101
|
layout:
|
92
102
|
title: "Storytime"
|
103
|
+
subscribe_to: "Subscribe to %{site_name}"
|
104
|
+
subscribe_modal_msg: "Stay up-to-date with %{site_name} by signing up for our mailing list!"
|