storytime 2.1.6 → 2.1.7

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.
Files changed (236) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +54 -0
  3. data/.gitignore +2 -1
  4. data/.ruby-version +1 -1
  5. data/.tool-versions +1 -0
  6. data/Gemfile +5 -3
  7. data/Gemfile.lock +414 -425
  8. data/Guardfile +1 -1
  9. data/app/assets/fonts/storytime-icons.eot +0 -0
  10. data/app/assets/fonts/storytime-icons.svg +23 -0
  11. data/app/assets/fonts/storytime-icons.ttf +0 -0
  12. data/app/assets/fonts/storytime-icons.woff +0 -0
  13. data/app/assets/javascripts/storytime/application.js +1 -8
  14. data/app/assets/javascripts/storytime/off_canvas.coffee +16 -0
  15. data/app/assets/javascripts/storytime/wysiwyg.js.coffee +9 -7
  16. data/app/assets/stylesheets/storytime/_buttons.scss +33 -0
  17. data/app/assets/stylesheets/storytime/_list-group.scss +1 -1
  18. data/app/assets/stylesheets/storytime/application.scss +14 -2
  19. data/app/assets/stylesheets/storytime/icons.scss +5 -5
  20. data/app/assets/stylesheets/storytime/leather/_buttons.scss +31 -0
  21. data/app/assets/stylesheets/storytime/leather/_devise.scss +72 -0
  22. data/app/assets/stylesheets/storytime/leather/_grid.scss +19 -0
  23. data/app/assets/stylesheets/storytime/leather/_list_groups.scss +33 -0
  24. data/app/assets/stylesheets/storytime/leather/_nav_menus.scss +125 -0
  25. data/app/assets/stylesheets/storytime/leather/_navbar_transparent.scss +23 -0
  26. data/app/assets/stylesheets/storytime/leather/_off_canvas.scss +109 -0
  27. data/app/assets/stylesheets/storytime/leather/_scroll_panels.scss +85 -0
  28. data/app/assets/stylesheets/storytime/leather/_toggle_columns.scss +23 -0
  29. data/app/assets/stylesheets/storytime/leather/_typography.scss +12 -0
  30. data/app/assets/stylesheets/storytime/leather/_utilities.scss +54 -0
  31. data/app/assets/stylesheets/storytime/leather/_variables.scss +8 -0
  32. data/app/assets/stylesheets/storytime/posts.scss +9 -1
  33. data/app/controllers/storytime/application_controller.rb +1 -1
  34. data/app/controllers/storytime/dashboard/blog_posts_controller.rb +5 -3
  35. data/app/controllers/storytime/dashboard/blogs_controller.rb +1 -1
  36. data/app/controllers/storytime/dashboard/media_controller.rb +4 -4
  37. data/app/controllers/storytime/dashboard/memberships_controller.rb +1 -1
  38. data/app/controllers/storytime/dashboard/pages_controller.rb +26 -6
  39. data/app/controllers/storytime/dashboard/posts_controller.rb +30 -5
  40. data/app/controllers/storytime/dashboard/subscriptions_controller.rb +1 -1
  41. data/app/controllers/storytime/pages_controller.rb +31 -1
  42. data/app/controllers/storytime/posts_controller.rb +1 -1
  43. data/app/controllers/storytime/subscriptions_controller.rb +5 -1
  44. data/app/helpers/storytime/application_helper.rb +0 -4
  45. data/app/models/concerns/storytime/post_featured_images.rb +2 -2
  46. data/app/models/concerns/storytime/post_partial_inheritance.rb +2 -2
  47. data/app/models/storytime/autosave.rb +1 -1
  48. data/app/models/storytime/comment.rb +1 -1
  49. data/app/models/storytime/media.rb +1 -1
  50. data/app/models/storytime/membership.rb +2 -2
  51. data/app/models/storytime/post.rb +7 -3
  52. data/app/models/storytime/site.rb +4 -6
  53. data/app/models/storytime/snippet.rb +12 -1
  54. data/app/models/storytime/subscription.rb +2 -2
  55. data/app/models/storytime/version.rb +1 -1
  56. data/app/policies/storytime/post_policy.rb +1 -1
  57. data/app/views/storytime/dashboard/_navigation.html.erb +0 -9
  58. data/app/views/storytime/dashboard/blog_posts/_form.html.erb +5 -1
  59. data/app/views/storytime/dashboard/blogs/edit.json.jbuilder +1 -1
  60. data/app/views/storytime/dashboard/blogs/index.json.jbuilder +1 -1
  61. data/app/views/storytime/dashboard/blogs/new.json.jbuilder +1 -1
  62. data/app/views/storytime/dashboard/media/_gallery.html.erb +1 -1
  63. data/app/views/storytime/dashboard/media/_modal.html.erb +2 -2
  64. data/app/views/storytime/dashboard/media/show.json.jbuilder +1 -1
  65. data/app/views/storytime/dashboard/memberships/_edit.html.erb +1 -1
  66. data/app/views/storytime/dashboard/memberships/_index.html.erb +3 -3
  67. data/app/views/storytime/dashboard/memberships/_new.html.erb +1 -1
  68. data/app/views/storytime/dashboard/memberships/edit.json.jbuilder +1 -1
  69. data/app/views/storytime/dashboard/memberships/index.json.jbuilder +1 -1
  70. data/app/views/storytime/dashboard/memberships/new.json.jbuilder +1 -1
  71. data/app/views/storytime/dashboard/memberships/save.json.jbuilder +1 -1
  72. data/app/views/storytime/dashboard/pages/_form.html.erb +1 -1
  73. data/app/views/storytime/dashboard/posts/_directory.html.erb +18 -0
  74. data/app/views/storytime/dashboard/posts/_form.html.erb +1 -1
  75. data/app/views/storytime/dashboard/posts/_list.html.erb +2 -26
  76. data/app/views/storytime/dashboard/posts/_new_button.html.erb +1 -1
  77. data/app/views/storytime/dashboard/posts/_post.html.erb +28 -0
  78. data/app/views/storytime/dashboard/posts/_sorts.html.erb +21 -0
  79. data/app/views/storytime/dashboard/posts/index.html.erb +5 -3
  80. data/app/views/storytime/dashboard/roles/_form.html.erb +1 -1
  81. data/app/views/storytime/dashboard/roles/edit.json.jbuilder +1 -1
  82. data/app/views/storytime/dashboard/sites/_form.html.erb +1 -1
  83. data/app/views/storytime/dashboard/sites/site.json.jbuilder +1 -1
  84. data/app/views/storytime/dashboard/snippets/_index.html.erb +1 -1
  85. data/app/views/storytime/dashboard/snippets/edit.json.jbuilder +1 -1
  86. data/app/views/storytime/dashboard/snippets/index.json.jbuilder +1 -1
  87. data/app/views/storytime/dashboard/snippets/new.json.jbuilder +1 -1
  88. data/app/views/storytime/dashboard/subscriptions/_form.html.erb +1 -1
  89. data/app/views/storytime/dashboard/subscriptions/_index.html.erb +2 -2
  90. data/app/views/storytime/dashboard/subscriptions/form.json.jbuilder +1 -1
  91. data/app/views/storytime/dashboard/subscriptions/index.json.jbuilder +1 -1
  92. data/app/views/storytime/dashboard/versions/_versions_info.html.erb +1 -1
  93. data/app/views/storytime/posts/show.html.erb +6 -0
  94. data/app/views/storytime/sites/_google_analytics_code.html.erb +5 -8
  95. data/config/initializers/assets.rb +2 -1
  96. data/config/initializers/friendly_id.rb +1 -1
  97. data/config/initializers/url_for_patch.rb +19 -8
  98. data/config/locales/devise.zh-CN.yml +59 -0
  99. data/config/locales/kaminari.zh-CN.yml +17 -0
  100. data/config/locales/simple_form.zh-CN.yml +26 -0
  101. data/config/locales/zh-CN.yml +141 -0
  102. data/config/routes.rb +2 -4
  103. data/db/migrate/20140501174341_create_storytime_posts.rb +1 -1
  104. data/db/migrate/20140509191309_create_friendly_id_slugs.rb +1 -1
  105. data/db/migrate/20140511200849_create_storytime_media.rb +1 -1
  106. data/db/migrate/20140513161233_create_storytime_sites.rb +1 -1
  107. data/db/migrate/20140514200234_create_storytime_tags.rb +1 -1
  108. data/db/migrate/20140514200304_create_storytime_taggings.rb +1 -1
  109. data/db/migrate/20140516141252_create_storytime_versions.rb +1 -1
  110. data/db/migrate/20140521190606_create_storytime_roles.rb +1 -1
  111. data/db/migrate/20140521191048_add_storytime_role_id_to_users.rb +1 -1
  112. data/db/migrate/20140521191728_create_storytime_permissions.rb +1 -1
  113. data/db/migrate/20140521191744_create_storytime_actions.rb +1 -1
  114. data/db/migrate/20140813014447_create_storytime_comments.rb +1 -1
  115. data/db/migrate/20140813130534_add_storytime_name_to_users.rb +1 -1
  116. data/db/migrate/20140916183056_create_storytime_autosaves.rb +1 -1
  117. data/db/migrate/20141020213343_add_secondary_media_id_to_storytime_post.rb +1 -1
  118. data/db/migrate/20141021073356_create_storytime_snippets.rb +1 -1
  119. data/db/migrate/20141111164439_create_storytime_subscriptions.rb +1 -1
  120. data/db/migrate/20150122200805_add_title_and_content_index_to_storytime_post.rb +1 -1
  121. data/db/migrate/20150128185746_seed_new_actions_and_permissions.rb +1 -1
  122. data/db/migrate/20150129215308_add_site_id_to_storytime_subscription.rb +1 -1
  123. data/db/migrate/20150206201847_add_site_id_to_storytime_post.rb +1 -1
  124. data/db/migrate/20150206201919_add_site_id_to_storytime_snippet.rb +1 -1
  125. data/db/migrate/20150206201931_add_site_id_to_storytime_tag.rb +1 -1
  126. data/db/migrate/20150206205256_add_notification_fields_to_storytime_post.rb +1 -1
  127. data/db/migrate/20150216211257_add_subdomain_to_storytime_sites.rb +1 -1
  128. data/db/migrate/20150216225045_add_site_to_storytime_media.rb +1 -1
  129. data/db/migrate/20150219210528_remove_root_page_content_from_storytime_sites.rb +1 -1
  130. data/db/migrate/20150220184902_add_blog_id_to_posts.rb +1 -1
  131. data/db/migrate/20150224192138_add_homepage_path_to_storytime_sites.rb +1 -1
  132. data/db/migrate/20150224193151_add_subscription_email_from_to_storytime_sites.rb +1 -1
  133. data/db/migrate/20150224193551_add_layout_to_storytime_sites.rb +1 -1
  134. data/db/migrate/20150224194559_add_disqus_forum_shortname_to_storytime_sites.rb +1 -1
  135. data/db/migrate/20150224212453_remove_homepage_path_from_storytime_sites.rb +1 -1
  136. data/db/migrate/20150225143516_add_site_id_to_storytime_autosaves.rb +1 -1
  137. data/db/migrate/20150225143826_add_site_id_to_storytime_comments.rb +1 -1
  138. data/db/migrate/20150225145119_add_site_id_to_storytime_versions.rb +1 -1
  139. data/db/migrate/20150225145316_add_site_id_to_storytime_taggings.rb +1 -1
  140. data/db/migrate/20150225145608_update_storytime_site_id_columns.rb +1 -1
  141. data/db/migrate/20150225164232_add_site_id_to_storytime_permissions.rb +1 -1
  142. data/db/migrate/20150225212917_create_storytime_memberships.rb +1 -1
  143. data/db/migrate/20150225213535_create_memberships_for_storytime_users.rb +1 -1
  144. data/db/migrate/20150226201739_add_custom_domain_to_storytime_sites.rb +1 -1
  145. data/db/migrate/20150302171500_add_site_id_to_storytime_media.rb +1 -1
  146. data/db/migrate/20150302171722_set_site_layout.rb +1 -1
  147. data/db/migrate/20150302185138_remove_storytime_role_id_from_users.rb +1 -1
  148. data/db/migrate/20150302192525_transfer_posts_to_blogs.rb +1 -1
  149. data/db/migrate/20150302192759_seed_permissions.rb +1 -1
  150. data/db/migrate/20150331162329_add_discourse_name_to_storytime_sites.rb +1 -1
  151. data/db/migrate/20150402161427_remove_subdomain_from_storytime_site.rb +1 -1
  152. data/db/migrate/20150520181115_create_storytime_navigations.rb +1 -1
  153. data/db/migrate/20150520185227_create_storytime_links.rb +1 -1
  154. data/db/migrate/20150520190700_add_position_to_storytime_links.rb +1 -1
  155. data/db/migrate/20150529192058_add_url_to_storytime_links.rb +1 -1
  156. data/db/migrate/20260408001637_add_canonical_url_to_storytime_posts.rb +5 -0
  157. data/db/migrate/20260701000000_sanitize_existing_storytime_snippets.rb +22 -0
  158. data/lib/storytime/cli/install.rb +2 -20
  159. data/lib/storytime/concerns/action_controller_extension.rb +36 -0
  160. data/lib/storytime/constraints/page_constraint.rb +8 -2
  161. data/lib/storytime/engine.rb +3 -5
  162. data/lib/storytime/migrators/v1.rb +3 -3
  163. data/lib/storytime/post_notifier.rb +1 -1
  164. data/lib/storytime/post_url_handler.rb +18 -5
  165. data/lib/storytime/storytime_helpers.rb +4 -0
  166. data/lib/storytime/version.rb +1 -1
  167. data/lib/storytime.rb +1 -1
  168. data/spec/controllers/dashboard_controller_spec.rb +5 -6
  169. data/spec/dummy/app/assets/config/manifest.js +3 -0
  170. data/spec/dummy/config/database.yml +3 -3
  171. data/spec/dummy/config/initializers/devise.rb +1 -1
  172. data/spec/dummy/db/migrate/20140530185250_devise_create_users.rb +1 -1
  173. data/spec/dummy/db/migrate/20150127172846_create_widgets.rb +1 -1
  174. data/spec/dummy/db/migrate/20150206203824_add_video_url_to_storytime_posts.rb +1 -1
  175. data/spec/dummy/db/schema.rb +226 -244
  176. data/spec/factories/action_factories.rb +3 -3
  177. data/spec/factories/comment_factories.rb +1 -1
  178. data/spec/factories/media_factories.rb +1 -1
  179. data/spec/factories/membership_factories.rb +1 -1
  180. data/spec/factories/navigation_factories.rb +3 -3
  181. data/spec/factories/permission_factories.rb +1 -1
  182. data/spec/factories/post_factories.rb +2 -2
  183. data/spec/factories/role_factories.rb +11 -11
  184. data/spec/factories/site_factories.rb +3 -3
  185. data/spec/factories/snippet_factories.rb +1 -1
  186. data/spec/factories/subscription_factories.rb +1 -1
  187. data/spec/factories/user_factories.rb +2 -2
  188. data/spec/factories/widget_factories.rb +2 -2
  189. data/spec/features/blogs_spec.rb +7 -7
  190. data/spec/features/comments_spec.rb +11 -11
  191. data/spec/features/dashboard/media_spec.rb +17 -11
  192. data/spec/features/dashboard/memberships_spec.rb +13 -19
  193. data/spec/features/dashboard/navigations_spec.rb +1 -1
  194. data/spec/features/dashboard/pages_spec.rb +8 -8
  195. data/spec/features/dashboard/posts_spec.rb +19 -19
  196. data/spec/features/dashboard/sites_spec.rb +1 -1
  197. data/spec/features/dashboard/snippets_spec.rb +3 -3
  198. data/spec/features/dashboard/subscription_spec.rb +2 -2
  199. data/spec/features/pages_spec.rb +3 -3
  200. data/spec/features/posts_spec.rb +2 -2
  201. data/spec/features/subscription_spec.rb +3 -3
  202. data/spec/importers/wordpress_spec.rb +1 -1
  203. data/spec/lib/mysql_fulltext_search_adapter_spec.rb +3 -3
  204. data/spec/lib/mysql_search_adapter_spec.rb +3 -3
  205. data/spec/lib/postgres_search_adapter_spec.rb +3 -3
  206. data/spec/lib/sqlite3_search_adapter_spec.rb +3 -3
  207. data/spec/lib/storytime/constraints/page_constraint_spec.rb +40 -0
  208. data/spec/lib/storytime_helpers_spec.rb +2 -2
  209. data/spec/models/navigation_spec.rb +3 -3
  210. data/spec/models/post_spec.rb +29 -29
  211. data/spec/models/snippet_spec.rb +31 -0
  212. data/spec/models/subscription_spec.rb +4 -4
  213. data/spec/models/tagging_spec.rb +14 -14
  214. data/spec/models/version_spec.rb +29 -29
  215. data/spec/policies/comment_policy_spec.rb +11 -11
  216. data/spec/policies/post_policy_spec.rb +13 -13
  217. data/spec/requests/pages_spec.rb +37 -0
  218. data/spec/requests/routings_spec.rb +14 -15
  219. data/spec/spec_helper.rb +8 -15
  220. data/spec/support/domains.rb +2 -2
  221. data/spec/support/feature_macros.rb +5 -5
  222. data/spec/support/pundit_matcher.rb +3 -3
  223. data/storytime.gemspec +15 -20
  224. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +195 -0
  225. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +169 -0
  226. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +182 -0
  227. data/vendor/assets/javascripts/codemirror.js +8922 -0
  228. data/vendor/assets/javascripts/medium-editor.min.js +3 -3
  229. data/vendor/assets/stylesheets/codemirror/themes/solarized.css +169 -0
  230. data/vendor/assets/stylesheets/codemirror.css +347 -0
  231. metadata +94 -134
  232. data/config/initializers/storytime_admin.rb +0 -5
  233. data/config/spring.rb +0 -1
  234. data/spec/dummy/app/controllers/storytime_admin/widgets_controller.rb +0 -5
  235. data/spec/dummy/db/development.sqlite3 +0 -0
  236. data/spec/dummy/db/test.sqlite3 +0 -0
@@ -0,0 +1,85 @@
1
+ .scroll-panel {
2
+ position: absolute;
3
+ top: 0;
4
+ right: 0;
5
+ bottom: 0;
6
+ left: 0;
7
+
8
+ .scroll-panel-header {
9
+ position: absolute;
10
+ top: 0;
11
+ width: 100%;
12
+ height: $scroll-panel-header-height;
13
+ padding: 10px 20px;
14
+ background: #FFF;
15
+ border-bottom: 1px solid #F1F1F1;
16
+
17
+ .scroll-panel-title {
18
+ margin-top: 0;
19
+ margin-bottom: 0;
20
+ font-size: 18px;
21
+ line-height: 30px;
22
+ }
23
+
24
+ .btn.pull-left ~ .scroll-panel-title {
25
+ margin-left: 15px;
26
+ float: left;
27
+ }
28
+
29
+ @media (max-width: $screen-xs-max) {
30
+ .btn.pull-left.visible-xs ~ .scroll-panel-title {
31
+ margin-left: 15px;
32
+ }
33
+ }
34
+
35
+ @media (max-width: $screen-sm-max) {
36
+ .btn.pull-left.visible-xs.visible-sm ~ .scroll-panel-title {
37
+ margin-left: 15px;
38
+ }
39
+ }
40
+
41
+ @media (min-width: $screen-sm-min) {
42
+ .btn.pull-left.visible-xs ~ .scroll-panel-title {
43
+ margin-left: 0;
44
+ }
45
+ }
46
+
47
+ @media (min-width: $screen-md-min) {
48
+ .btn.pull-left.visible-xs.visible-sm ~ .scroll-panel-title {
49
+ margin-left: 0;
50
+ }
51
+ }
52
+ }
53
+
54
+ .scroll-panel-body {
55
+ position: absolute;
56
+ top: 0;
57
+ right: 0;
58
+ bottom: 0;
59
+ left: 0;
60
+ padding: 20px;
61
+ overflow-y: auto;
62
+ -webkit-overflow-scrolling: touch;
63
+ }
64
+
65
+ .scroll-panel-header ~ .scroll-panel-body {
66
+ top: $scroll-panel-header-height;
67
+ }
68
+
69
+ .scroll-panel-header.visible-xs ~ .scroll-panel-body,
70
+ .scroll-panel-header.visible-sm ~ .scroll-panel-body {
71
+ top: 0;
72
+ }
73
+
74
+ @media (max-width: $screen-xs-max) {
75
+ .scroll-panel-header.visible-xs ~ .scroll-panel-body {
76
+ top: $scroll-panel-header-height;
77
+ }
78
+ }
79
+
80
+ @media (max-width: $screen-sm-max) {
81
+ .scroll-panel-header.visible-sm ~ .scroll-panel-body {
82
+ top: $scroll-panel-header-height;
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,23 @@
1
+ #left {
2
+ width: 40%;
3
+ position: absolute;
4
+ top: 0;
5
+ left: 0;
6
+ bottom: 0;
7
+ }
8
+
9
+ #right {
10
+ width: 60%;
11
+ position: absolute;
12
+ top: 0;
13
+ left: 40%;
14
+ bottom: 0;
15
+ }
16
+
17
+ @media (max-width: $screen-xs-max) {
18
+ .full-width-xs {
19
+ width: 100% !important;
20
+ left: 0 !important;
21
+ right: 0 !important;
22
+ }
23
+ }
@@ -0,0 +1,12 @@
1
+ .text-shadowed {
2
+ text-shadow: 1px 1px 2px $gray-dark;
3
+ }
4
+ .text-light {
5
+ font-weight: 200;
6
+ }
7
+ .text-lighter {
8
+ font-weight: lighter;
9
+ }
10
+ .blog-heading {
11
+ margin: 30px 0;
12
+ }
@@ -0,0 +1,54 @@
1
+ .abs-cover {
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ background-size: cover !important;
8
+ }
9
+
10
+ .vertical-center {
11
+ position: relative;
12
+ top: 50%;
13
+ -webkit-transform: translateY(-50%);
14
+ -ms-transform: translateY(-50%);
15
+ transform: translateY(-50%);
16
+ }
17
+
18
+ .bg-white { background:#FFF; }
19
+ .bg-gray-light { background: $gray-light; }
20
+ .bg-gray-lighter { background: $gray-lighter; }
21
+ .bg-gray-lightest { background: $navbar-default-bg; }
22
+ .bg-gray-radial-light {
23
+ background: #eeeeee;
24
+ background: -moz-radial-gradient(center, ellipse cover, #eeeeee 0%, #dddddd 100%) !important;
25
+ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)) !important;
26
+ background: -webkit-radial-gradient(center, ellipse cover, #eeeeee 0%, #dddddd 100%) !important;
27
+ background: -o-radial-gradient(center, ellipse cover, #eeeeee 0%, #dddddd 100%) !important;
28
+ background: -ms-radial-gradient(center, ellipse cover, #eeeeee 0%, #dddddd 100%) !important;
29
+ background: radial-gradient(ellipse at center, #eeeeee 0%, #dddddd 100%) !important;
30
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=1);
31
+ }
32
+ .bg-gray-radial-dark {
33
+ background: #333333;
34
+ background: -moz-radial-gradient(center, ellipse cover, #3b3b3b 0%, #222222 100%) !important;
35
+ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #3b3b3b), color-stop(100%, #222222)) !important;
36
+ background: -webkit-radial-gradient(center, ellipse cover, #3b3b3b 0%, #222222 100%) !important;
37
+ background: -o-radial-gradient(center, ellipse cover, #3b3b3b 0%, #222222 100%) !important;
38
+ background: -ms-radial-gradient(center, ellipse cover, #3b3b3b 0%, #222222 100%) !important;
39
+ background: radial-gradient(ellipse at center, #3b3b3b 0%, #222222 100%) !important;
40
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3b3b3b', endColorstr='#222222', GradientType=1) !important;
41
+ }
42
+
43
+ .no-margin { margin: 0; }
44
+ .no-padding { padding: 0; }
45
+ .no-overflow { overflow: hidden; }
46
+ .no-radius {
47
+ @include border-top-radius(0);
48
+ @include border-bottom-radius(0);
49
+ }
50
+
51
+ .absolute { position: absolute; }
52
+ .relative { position: relative; }
53
+ .block { display: block; }
54
+ .inline-block { display: inline-block; }
@@ -0,0 +1,8 @@
1
+ $devise-bg-gradient-start: #5D76A5 !default;
2
+ $devise-bg-gradient-end: #425472 !default;
3
+ $devise-box-border-color: #006699 !default;
4
+
5
+ $navbar-fixed-width: 300px !default;
6
+ $navbar-fixed-collapsed-width: 75px !default;
7
+ $scroll-panel-header-height: $navbar-height !default;
8
+ $navbar-tranparent-link-color: #FFFFFF !default;
@@ -1,3 +1,12 @@
1
+ .list-group-button-links .list-group-item .list-group-actions{
2
+ top: 15px;
3
+ margin-top: 0;
4
+ }
5
+
6
+ .post-row-subtext{
7
+ margin-top: 10px;
8
+ }
9
+
1
10
  .CodeMirror {
2
11
  height: auto;
3
12
  position: absolute;
@@ -8,7 +17,6 @@
8
17
  display: none;
9
18
  }
10
19
 
11
-
12
20
  .contenteditable {
13
21
  cursor: text;
14
22
  }
@@ -8,7 +8,7 @@ class Storytime::ApplicationController < Storytime.application_controller_superc
8
8
  include Storytime::Concerns::CurrentSite
9
9
  helper_method :current_storytime_site
10
10
 
11
- include Pundit
11
+ include Pundit::Authorization
12
12
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
13
13
 
14
14
  helper :all
@@ -1,3 +1,5 @@
1
+ require_dependency "storytime/dashboard/posts_controller"
2
+
1
3
  module Storytime
2
4
  module Dashboard
3
5
  class BlogPostsController < PostsController
@@ -34,12 +36,12 @@ module Storytime
34
36
  authorize @post
35
37
  @post.destroy
36
38
  flash[:notice] = I18n.t('flash.posts.destroy.success') unless request.xhr?
37
-
39
+
38
40
  respond_with [:dashboard, @post] do |format|
39
41
  format.html{ redirect_to [:dashboard, @post.blog, :blog_page_post_index] }
40
42
  end
41
43
  end
42
-
44
+
43
45
  private
44
46
  def current_post_type
45
47
  @current_post_type ||= Storytime::BlogPost
@@ -57,4 +59,4 @@ module Storytime
57
59
  end
58
60
  end
59
61
  end
60
- end
62
+ end
@@ -21,7 +21,7 @@ module Storytime
21
21
  @blog = @post
22
22
 
23
23
  respond_with @blog do |format|
24
- if @blog.update_attributes(post_params)
24
+ if @blog.update(post_params)
25
25
  format.json { render :index }
26
26
  else
27
27
  format.json { render :edit, status: :unprocessable_entity }
@@ -13,7 +13,7 @@ module Storytime
13
13
 
14
14
  @large_gallery = false if params[:large_gallery] == "false"
15
15
 
16
- render partial: "gallery", content_type: Mime::HTML if request.xhr?
16
+ render partial: "gallery", content_type: "text/html" if request.xhr?
17
17
  end
18
18
 
19
19
  def create
@@ -22,13 +22,13 @@ module Storytime
22
22
 
23
23
  authorize @upload_media
24
24
  @upload_media.save
25
-
25
+
26
26
  @media = Media.order("created_at DESC").page(params[:page]).per(10)
27
27
  @large_gallery = false
28
28
 
29
- render partial: "gallery", content_type: Mime::HTML
29
+ render partial: "gallery", content_type: "text/html"
30
30
  end
31
-
31
+
32
32
  def destroy
33
33
  @media = Media.find(params[:id])
34
34
  authorize @media
@@ -62,7 +62,7 @@ module Storytime
62
62
  membership_user_params = membership_params
63
63
  membership_user_params['user_attributes']['id'] = @membership.user.id
64
64
 
65
- if @membership.update_attributes(membership_user_params)
65
+ if @membership.update(membership_user_params)
66
66
  load_memberships
67
67
  format.json { render :index }
68
68
  else
@@ -4,24 +4,44 @@ module Storytime
4
4
  module Dashboard
5
5
  class PagesController < PostsController
6
6
 
7
-
8
7
  private
8
+
9
9
  def current_post_type
10
10
  @current_post_type ||= Storytime::Page
11
11
  end
12
12
  helper_method :current_post_type
13
13
 
14
+ def current_dir
15
+ params[:dir]
16
+ end
17
+
14
18
  def load_posts
15
- @posts = policy_scope(Storytime::Post).page(params[:page_number]).per(10)
16
- @posts = @posts.where(type: "Storytime::Page")
19
+ @posts = policy_scope(Storytime::Post).where(type: "Storytime::Page")
17
20
 
18
21
  @posts = if params[:published].present? && params[:published] == 'true'
19
- @posts.published.order(published_at: :desc)
22
+ @posts.published
20
23
  elsif params[:draft].present? && params[:draft] == "true"
21
- @posts.draft.order(updated_at: :desc)
24
+ @posts.draft
25
+ else
26
+ @posts
27
+ end
28
+
29
+ vals = if current_dir.blank?
30
+ ["%", "%/%"]
31
+ else
32
+ ["#{current_dir}/%", "#{current_dir}/%/%"]
33
+ end
34
+
35
+ @directories = if current_dir.blank?
36
+ @posts.where("slug like ?", vals[0]).pluck(:slug).select{|slug| slug.include?("/") }.map{|slug| slug.split("/").first }.uniq
22
37
  else
23
- @posts.order(published_at: :desc)
38
+ @posts.where("slug like ?", vals[1]).pluck(:slug).map{|slug| slug.gsub("#{current_dir}/", "").split("/") }.select{|slug| slug.length > 1 }.map{|slug| slug.first }.uniq
24
39
  end
40
+
41
+ @posts = @posts.where("slug like ?", vals[0])
42
+ .where.not("slug like ?", vals[1])
43
+ .page(params[:page_number])
44
+ .per(10)
25
45
  end
26
46
  end
27
47
  end
@@ -6,6 +6,7 @@ module Storytime
6
6
  before_action :hide_nav, only: [:new, :create, :edit, :update]
7
7
  before_action :set_post, only: [:edit, :update, :destroy]
8
8
  before_action :load_posts, only: :index
9
+ before_action :sort_posts, only: :index
9
10
  before_action :load_media, only: [:new, :edit]
10
11
 
11
12
  respond_to :json, only: :destroy
@@ -57,7 +58,7 @@ module Storytime
57
58
  authorize @post
58
59
  @post.draft_user_id = current_user.id
59
60
 
60
- if @post.update_attributes(post_params)
61
+ if @post.update(post_params)
61
62
  @post.autosave.destroy unless @post.autosave.nil?
62
63
 
63
64
  send_subscriber_notifications if @post.published? && post_params[:notifications_enabled] == "1"
@@ -80,6 +81,7 @@ module Storytime
80
81
  end
81
82
 
82
83
  private
84
+
83
85
  def hide_nav
84
86
  @hide_nav = true
85
87
  end
@@ -87,12 +89,35 @@ module Storytime
87
89
  def load_posts
88
90
  @blog = Blog.friendly.find(params[:blog_id])
89
91
  @posts = @blog.posts.page(params[:page_number]).per(10)
90
- if params[:published].present? && params[:published] == "true"
91
- @posts = @posts.published.order(created_at: :desc)
92
+
93
+ @posts = if params[:published].present? && params[:published] == "true"
94
+ @posts.published
92
95
  elsif params[:draft].present? && params[:draft] == "true"
93
- @posts = @posts.draft.order(updated_at: :desc)
96
+ @posts.draft
97
+ else
98
+ @posts
99
+ end
100
+ end
101
+
102
+ def sort_posts
103
+ @posts = if params[:sort].present?
104
+ if params[:sort] == "title"
105
+ @posts.order(title: :asc)
106
+ elsif params[:sort] == "slug"
107
+ @posts.order(slug: :asc)
108
+ elsif params[:sort] == "published_at"
109
+ @posts.order(published_at: :desc)
110
+ elsif params[:sort] == "created_at"
111
+ @posts.order(created_at: :desc)
112
+ else
113
+ @posts.order(published_at: :desc)
114
+ end
115
+ elsif params[:published] == "true"
116
+ @posts.order(created_at: :desc)
117
+ elsif params[:draft] == "true"
118
+ @posts.order(updated_at: :desc)
94
119
  else
95
- @posts = @posts.order(published_at: :desc)
120
+ @posts.order(published_at: :desc)
96
121
  end
97
122
  end
98
123
 
@@ -63,7 +63,7 @@ module Storytime
63
63
  if @subscription.nil?
64
64
  redirect_to main_app.storytime_path, alert: I18n.t('flash.subscriptions.unsubscribe.not_found')
65
65
  else
66
- @subscription.update_attributes(subscribed: false)
66
+ @subscription.update(subscribed: false)
67
67
  end
68
68
  end
69
69
 
@@ -17,12 +17,18 @@ module Storytime
17
17
  "storytime/#{@current_storytime_site.custom_view_path}/pages/show",
18
18
  "storytime/pages/#{slug}",
19
19
  "storytime/pages/show",
20
- ].each do |template|
20
+ ]
21
+
22
+ potential_templates.each do |template|
23
+ # The /show fallbacks dereference @page, so skip them when no page was loaded.
24
+ next if @page.nil? && template.end_with?("/show")
21
25
  if lookup_context.template_exists?(template)
22
26
  render template
23
27
  return
24
28
  end
25
29
  end
30
+
31
+ raise ActionController::RoutingError, "No page found for #{params[:id].inspect}"
26
32
  end
27
33
 
28
34
  private
@@ -40,5 +46,29 @@ module Storytime
40
46
  end
41
47
  redirect_to "/", status: :moved_permanently if @page == current_storytime_site(request).homepage
42
48
  end
49
+
50
+ def set_layout
51
+ return super if params[:id].blank?
52
+
53
+ path_segments = params[:id].split("/")
54
+
55
+ if path_segments.length > 1
56
+ path_segments.pop
57
+
58
+ potential_layout_dirs = [
59
+ "storytime/#{@current_storytime_site.custom_view_path}/layouts",
60
+ "storytime/layouts",
61
+ "layouts",
62
+ ].each do |dir|
63
+ path_segments.map.with_index do |segment, i|
64
+ potential_layout = "#{dir}/#{path_segments[0..i].join("/")}"
65
+ return potential_layout if lookup_context.template_exists?(potential_layout)
66
+ end
67
+ end
68
+ end
69
+
70
+ super
71
+ end
72
+
43
73
  end
44
74
  end
@@ -15,7 +15,7 @@ module Storytime
15
15
 
16
16
  content_for :title, "#{@current_storytime_site.title} | #{@post.title}"
17
17
 
18
- @comments = @post.comments.order("created_at DESC")
18
+ @comments = @post.comments.order("created_at DESC") if @post.show_comments?
19
19
  #allow overriding in the host app
20
20
  if params[:preview].nil? && !view_context.current_page?(storytime.post_path(@post))
21
21
  redirect_to storytime.post_path(@post), :status => :moved_permanently
@@ -14,7 +14,11 @@ module Storytime
14
14
  flash[:error] = I18n.t('flash.subscriptions.create.fail')
15
15
  end
16
16
 
17
- redirect_to :back
17
+ if respond_to?(:redirect_back)
18
+ redirect_back(fallback_location: "/")
19
+ else
20
+ redirect_to :back
21
+ end
18
22
  end
19
23
 
20
24
  def destroy
@@ -1,10 +1,6 @@
1
1
  module Storytime
2
2
  module ApplicationHelper
3
3
 
4
- def logged_in_storytime_user?
5
- user_signed_in? && current_user.respond_to?(:storytime_user?) && current_user.storytime_user?(current_storytime_site)
6
- end
7
-
8
4
  def dashboard_nav_site_path(site)
9
5
  site.nil? || site.new_record? ? storytime.new_dashboard_site_path : storytime.edit_dashboard_site_path(site)
10
6
  end
@@ -2,7 +2,7 @@ module Storytime::PostFeaturedImages
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- belongs_to :featured_media, class_name: "Storytime::Media"
6
- belongs_to :secondary_media, class_name: "Storytime::Media"
5
+ belongs_to :featured_media, class_name: "Storytime::Media", optional: true
6
+ belongs_to :secondary_media, class_name: "Storytime::Media", optional: true
7
7
  end
8
8
  end
@@ -14,9 +14,9 @@ module Storytime::PostPartialInheritance
14
14
  element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self))
15
15
  collection = ActiveSupport::Inflector.tableize(self.to_s)
16
16
 
17
- if site && File.exists?(Rails.root.join('app', 'views', "storytime/#{site.custom_view_path}/#{collection.sub("storytime/", "")}/_#{element}.html.erb"))
17
+ if site && File.exist?(Rails.root.join('app', 'views', "storytime/#{site.custom_view_path}/#{collection.sub("storytime/", "")}/_#{element}.html.erb"))
18
18
  "storytime/#{site.custom_view_path}/#{collection.sub("storytime/", "")}/#{element}"
19
- elsif File.exists?(Rails.root.join('app', 'views', collection, "_#{element}.html.erb")) ||
19
+ elsif File.exist?(Rails.root.join('app', 'views', collection, "_#{element}.html.erb")) ||
20
20
  self.superclass == ActiveRecord::Base
21
21
  "#{collection}/#{element}"
22
22
  else
@@ -2,7 +2,7 @@ module Storytime
2
2
  class Autosave < ActiveRecord::Base
3
3
  include Storytime::ScopedToSite
4
4
 
5
- belongs_to :user, class_name: Storytime.user_class
5
+ belongs_to :user, class_name: Storytime.user_class.to_s
6
6
  belongs_to :autosavable, polymorphic: true
7
7
 
8
8
  attr_accessor :draft_content
@@ -2,7 +2,7 @@ module Storytime
2
2
  class Comment < ActiveRecord::Base
3
3
  include Storytime::ScopedToSite
4
4
 
5
- belongs_to :user, class_name: Storytime.user_class
5
+ belongs_to :user, class_name: Storytime.user_class.to_s
6
6
  belongs_to :post
7
7
  belongs_to :site
8
8
 
@@ -1,7 +1,7 @@
1
1
  module Storytime
2
2
  class Media < ActiveRecord::Base
3
3
  include Storytime::ScopedToSite
4
- belongs_to :user, class_name: Storytime.user_class
4
+ belongs_to :user, class_name: Storytime.user_class.to_s
5
5
  has_many :posts # posts where this is the featured media
6
6
  belongs_to :site
7
7
 
@@ -1,7 +1,7 @@
1
1
  module Storytime
2
2
  class Membership < ActiveRecord::Base
3
3
  include Storytime::ScopedToSite
4
- belongs_to :user, class_name: Storytime.user_class
4
+ belongs_to :user, class_name: Storytime.user_class.to_s
5
5
  belongs_to :storytime_role, class_name: "Storytime::Role"
6
6
  belongs_to :site, class_name: "Storytime::Site"
7
7
 
@@ -16,4 +16,4 @@ module Storytime
16
16
  unscoped.where(user: user).includes(:site).where.not(site_id: nil)
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -9,7 +9,7 @@ module Storytime
9
9
  extend FriendlyId
10
10
  friendly_id :slug_candidates, use: [:history, :scoped], scope: :site
11
11
 
12
- belongs_to :user, class_name: Storytime.user_class
12
+ belongs_to :user, class_name: Storytime.user_class.to_s
13
13
  belongs_to :site
14
14
 
15
15
  has_one :autosave, as: :autosavable, dependent: :destroy, class_name: "Autosave"
@@ -72,7 +72,11 @@ module Storytime
72
72
  end
73
73
 
74
74
  def slug_candidates
75
- if slug.blank? then [:title] elsif slug_changed? then [:slug] end
75
+ if slug.blank?
76
+ [:title]
77
+ elsif slug_changed?
78
+ [:slug]
79
+ end
76
80
  end
77
81
 
78
82
  def normalize_friendly_id(value)
@@ -81,7 +85,7 @@ module Storytime
81
85
 
82
86
  def should_generate_new_friendly_id?
83
87
  current_slug = self.slug == "" ? nil : self.slug
84
- slug_changed? || (current_slug.nil? && published_at_changed? && published_at_change.first.nil?)
88
+ slug.blank? || slug_changed? || (current_slug.nil? && published_at_changed? && published_at_change.first.nil?)
85
89
  end
86
90
 
87
91
  def sanitize_content
@@ -1,21 +1,19 @@
1
1
  module Storytime
2
2
  class Site < ActiveRecord::Base
3
3
  require 'uri'
4
- extend Storytime::Enum if Rails::VERSION::MINOR < 1
5
4
 
6
- enum post_slug_style: [:default, :day_and_name, :month_and_name, :post_id]
7
- enum root_page_content: [:posts, :page]
5
+ enum :post_slug_style, [:default, :day_and_name, :month_and_name, :post_id]
8
6
 
9
7
  has_many :memberships, class_name: "Storytime::Membership", dependent: :destroy
10
- has_many :users, through: :memberships, class_name: Storytime.user_class
8
+ has_many :users, through: :memberships, class_name: Storytime.user_class.to_s
11
9
  has_many :subscriptions, dependent: :destroy
12
10
  has_many :posts, dependent: :destroy
13
11
  has_many :blog_posts, dependent: :destroy
14
12
  has_many :pages, -> { where(type: "Storytime::Page") }, dependent: :destroy
15
13
  has_many :blogs, dependent: :destroy
16
14
  has_many :navigations, dependent: :destroy
17
- belongs_to :homepage, class_name: "Storytime::Post", foreign_key: "root_post_id"
18
- belongs_to :creator, class_name: Storytime.user_class, foreign_key: "user_id"
15
+ has_one :homepage, class_name: "Storytime::Post", foreign_key: "id", primary_key: "root_post_id", required: false
16
+ belongs_to :creator, class_name: Storytime.user_class.to_s, foreign_key: "user_id"
19
17
 
20
18
  validates :subscription_email_from, presence: true
21
19
  validates :custom_domain, presence: true, uniqueness: true
@@ -4,6 +4,17 @@ module Storytime
4
4
  belongs_to :site
5
5
 
6
6
  validates :name, length: { in: 1..255 }
7
- validates :content, length: { in: 1..5000 }
7
+ validates :content, length: { in: 1..20000 }
8
+
9
+ before_save :sanitize_content
10
+
11
+ # Snippet content is rendered with `raw` in the front-end (see
12
+ # app/views/storytime/snippets/_snippet.html.erb), so it must be scrubbed
13
+ # on write with the same allow-list used for Post/Page content. Otherwise
14
+ # an editor could store arbitrary HTML/JS (stored XSS).
15
+ def sanitize_content
16
+ return if Storytime.post_sanitizer.blank? || content.blank?
17
+ self.content = Storytime.post_sanitizer.call(content)
18
+ end
8
19
  end
9
20
  end
@@ -12,14 +12,14 @@ module Storytime
12
12
  before_create :generate_token
13
13
 
14
14
  def generate_token
15
- key = Rails.application.secrets.secret_key_base
15
+ key = Rails.application.secret_key_base
16
16
  digest = OpenSSL::Digest.new('sha1')
17
17
 
18
18
  self.token = OpenSSL::HMAC.hexdigest(digest, key, self.email)
19
19
  end
20
20
 
21
21
  def unsubscribe!
22
- update_attributes(subscribed: false)
22
+ update!(subscribed: false)
23
23
  end
24
24
  end
25
25
  end