storytime 1.0.7 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/storytime/subscriptions.js +0 -2
  3. data/app/assets/javascripts/storytime/subscriptions.js.coffee +2 -0
  4. data/app/assets/stylesheets/storytime/posts.css.scss +5 -4
  5. data/app/assets/stylesheets/storytime/sites.css.scss +0 -4
  6. data/app/assets/stylesheets/storytime/subscriptions.css.scss +0 -0
  7. data/app/controllers/storytime/dashboard/posts_controller.rb +19 -2
  8. data/app/controllers/storytime/dashboard/subscriptions_controller.rb +83 -0
  9. data/app/controllers/storytime/posts_controller.rb +25 -0
  10. data/app/controllers/storytime/subscriptions_controller.rb +21 -5
  11. data/app/helpers/storytime/dashboard/media_helper.rb +1 -5
  12. data/app/helpers/storytime/subscriptions_helper.rb +16 -0
  13. data/app/mailers/storytime/subscription_mailer.rb +13 -0
  14. data/app/models/storytime/action.rb +1 -0
  15. data/app/models/storytime/permission.rb +12 -9
  16. data/app/models/storytime/post.rb +3 -3
  17. data/app/models/storytime/site.rb +15 -0
  18. data/app/models/storytime/subscription.rb +24 -0
  19. data/app/policies/storytime/post_policy.rb +1 -1
  20. data/app/policies/storytime/subscription_policy.rb +43 -0
  21. data/app/views/storytime/application/storytime/_header.html.erb +5 -1
  22. data/app/views/storytime/dashboard/_navigation.html.erb +2 -0
  23. data/app/views/storytime/dashboard/posts/_form.html.erb +6 -0
  24. data/app/views/storytime/dashboard/subscriptions/_subscription.html.erb +10 -0
  25. data/app/views/storytime/dashboard/subscriptions/edit.html.erb +10 -0
  26. data/app/views/storytime/dashboard/subscriptions/index.html.erb +19 -0
  27. data/app/views/storytime/dashboard/subscriptions/new.html.erb +9 -0
  28. data/app/views/storytime/subscription_mailer/new_post_email.html.erb +3 -2
  29. data/app/views/storytime/subscription_mailer/new_post_email.text.erb +7 -0
  30. data/app/views/storytime/subscriptions/_form.html.erb +5 -0
  31. data/app/views/storytime/subscriptions/_modal.html.erb +16 -0
  32. data/config/locales/en.yml +13 -1
  33. data/config/routes.rb +6 -15
  34. data/db/migrate/20141111164439_create_storytime_subscriptions.rb +14 -0
  35. data/db/migrate/20150122200805_add_title_and_content_index_to_storytime_post.rb +56 -0
  36. data/db/migrate/20150129215308_add_site_id_to_storytime_subscription.rb +5 -0
  37. data/lib/generators/templates/storytime.rb +9 -0
  38. data/lib/storytime/concerns/has_versions.rb +0 -1
  39. data/lib/storytime/engine.rb +2 -0
  40. data/lib/storytime/mysql_fulltext_search_adapter.rb +7 -0
  41. data/lib/storytime/mysql_search_adapter.rb +7 -0
  42. data/lib/storytime/postgres_search_adapter.rb +9 -0
  43. data/lib/storytime/sqlite3_search_adapter.rb +7 -0
  44. data/lib/storytime/version.rb +1 -1
  45. data/lib/storytime.rb +43 -0
  46. data/spec/controllers/subscriptions_controller_spec.rb +0 -0
  47. data/spec/dummy/config/environments/development.rb +8 -0
  48. data/spec/dummy/config/initializers/storytime.rb +37 -2
  49. data/spec/dummy/db/development.sqlite3 +0 -0
  50. data/spec/dummy/db/migrate/20150130213631_create_storytime_posts.storytime.rb +18 -0
  51. data/spec/dummy/db/migrate/20150130213632_create_friendly_id_slugs.storytime.rb +16 -0
  52. data/spec/dummy/db/migrate/20150130213633_create_storytime_media.storytime.rb +11 -0
  53. data/spec/dummy/db/migrate/20150130213634_create_storytime_sites.storytime.rb +14 -0
  54. data/spec/dummy/db/migrate/20150130213635_create_storytime_tags.storytime.rb +10 -0
  55. data/spec/dummy/db/migrate/20150130213636_create_storytime_taggings.storytime.rb +11 -0
  56. data/spec/dummy/db/migrate/20150130213637_create_storytime_versions.storytime.rb +13 -0
  57. data/spec/dummy/db/migrate/20150130213638_create_storytime_roles.storytime.rb +10 -0
  58. data/spec/dummy/db/migrate/20150130213639_add_storytime_role_id_to_users.storytime.rb +7 -0
  59. data/spec/dummy/db/migrate/20150130213640_create_storytime_permissions.storytime.rb +11 -0
  60. data/spec/dummy/db/migrate/20150130213641_create_storytime_actions.storytime.rb +11 -0
  61. data/spec/dummy/db/migrate/20150130213642_create_storytime_comments.storytime.rb +12 -0
  62. data/spec/dummy/db/migrate/20150130213643_add_storytime_name_to_users.storytime.rb +6 -0
  63. data/spec/dummy/db/migrate/20150130213644_create_storytime_autosaves.storytime.rb +13 -0
  64. data/spec/dummy/db/migrate/20150130213645_add_secondary_media_id_to_storytime_post.storytime.rb +6 -0
  65. data/spec/dummy/db/migrate/20150130213646_create_storytime_snippets.storytime.rb +22 -0
  66. data/spec/dummy/db/migrate/20150130213647_create_storytime_subscriptions.storytime.rb +15 -0
  67. data/spec/dummy/db/migrate/20150130213648_add_title_and_content_index_to_storytime_post.storytime.rb +57 -0
  68. data/spec/dummy/db/migrate/20150130213649_add_site_id_to_storytime_subscription.storytime.rb +6 -0
  69. data/spec/dummy/db/schema.rb +10 -2
  70. data/spec/dummy/db/test.sqlite3 +0 -0
  71. data/spec/factories/subscription_factories.rb +5 -5
  72. data/spec/features/dashboard/posts_spec.rb +0 -1
  73. data/spec/features/dashboard/subscription_spec.rb +37 -48
  74. data/spec/features/posts_spec.rb +2 -2
  75. data/spec/features/subscription_spec.rb +45 -15
  76. data/spec/lib/mysql_fulltext_search_adapter_spec.rb +31 -0
  77. data/spec/lib/mysql_search_adapter_spec.rb +31 -0
  78. data/spec/lib/postgres_search_adapter_spec.rb +31 -0
  79. data/spec/lib/sqlite3_search_adapter_spec.rb +31 -0
  80. data/spec/models/subscription_spec.rb +27 -27
  81. data/spec/requests/routings_spec.rb +2 -0
  82. metadata +71 -4
  83. data/app/views/storytime/subscription_mailer/new_post_email.txt.erb +0 -1
  84. data/lib/storytime/subscription_emails.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91d49457b192f13b7c8bcd673c56032d66391651
4
- data.tar.gz: 0d86828ad2e793852463fa1ac999cb1aa0000d65
3
+ metadata.gz: 06f4a653cab5a07931cdc7c80d0892bd5a7daa12
4
+ data.tar.gz: 3fb261085ce26f70bf249ce1724a3005afa3c6f7
5
5
  SHA512:
6
- metadata.gz: 2126e2e0e4b39b13e779683e21974382c9d8084791f8a4c6f0771739ab034405bada3235ab3856bd63ec96b141ad0e0e70767fc22b08ca07a0683e1267bde95a
7
- data.tar.gz: 75a7c2fb54395a4e660d0a862b9dd29209bd862765108b5101c7502d4906a72e2a6faa3c0cf31884846354a265300775dab7c54a46e2c1696e70208ac3198b2a
6
+ metadata.gz: 3d35eeeb18f0d289a16f3a7b312d2e76f17220dfd57b0c6077cea8de1012dc9a0227cdac33c8a05a444e5d819cd5b03e70b8e79138d8e14490ca959314cfe4e0
7
+ data.tar.gz: 5b5621d9c72c07e3ede66912eefc1c06a629ffca917075915e153bdf0e4a7f7aee85d14c262f8670654c520aea03fec3c435544f79384e06c724c540d3eb47a7
@@ -1,2 +0,0 @@
1
- // Place all the behaviors and hooks related to the matching controller here.
2
- // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ class Storytime.Dashboard.Subscriptions
2
+
@@ -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
  }
@@ -1,4 +0,0 @@
1
- /*
2
- Place all the styles related to the matching controller here.
3
- They will automatically be included in application.css.
4
- */
@@ -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 index
8
- @subscriptions = Storytime::Subscription.all
9
- render json: {subscriptions: @subscriptions}
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
- if media.file_url.starts_with?("http")
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
- create(role: writer, action: publish_own)
18
- create(role: editor, action: publish_own)
19
- create(role: admin, action: publish_own)
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
- create(role: editor, action: manage_others)
22
- create(role: admin, action: manage_others)
22
+ find_or_create_by(role: editor, action: manage_others)
23
+ find_or_create_by(role: admin, action: manage_others)
23
24
 
24
- create(role: admin, action: manage_site)
25
- create(role: admin, action: manage_users)
25
+ find_or_create_by(role: admin, action: manage_site)
26
+ find_or_create_by(role: admin, action: manage_users)
26
27
 
27
- create(role: editor, action: manage_snippets)
28
- create(role: admin, action: manage_snippets)
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.nil? then [:title] elsif slug_changed? then [:slug] end
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
- self.slug = nil if slug == ""
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
- <h1>There is some new post...</h1>
7
+ <h4>A new post was published on <%= @site.title %></h4>
8
8
  <p>
9
- Yay, that's so awesome... Check it out here?
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'>&times;</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>
@@ -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!"