storytime 1.0.7 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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!"
|