newsletter 3.0.2 → 3.2.0

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 (259) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +6 -0
  3. data/.ruby-version +1 -1
  4. data/Gemfile +17 -5
  5. data/README.md +40 -0
  6. data/app/assets/images/newsletter/BottomRight.gif +0 -0
  7. data/app/assets/images/newsletter/MidRight.gif +0 -0
  8. data/app/assets/images/newsletter/TopCenter.gif +0 -0
  9. data/app/assets/images/newsletter/TopRight.gif +0 -0
  10. data/app/assets/images/newsletter/calendar_date_select/calendar.gif +0 -0
  11. data/app/assets/images/newsletter/iReach_logo.gif +0 -0
  12. data/app/assets/images/newsletter/spacer.gif +0 -0
  13. data/app/assets/images/newsletter/topMid.gif +0 -0
  14. data/app/assets/javascripts/newsletter/application.js +6 -0
  15. data/app/assets/stylesheets/newsletter/admin.css +261 -0
  16. data/app/assets/stylesheets/newsletter/application.css +3 -1
  17. data/app/assets/stylesheets/newsletter/nav.css +68 -0
  18. data/app/assets/stylesheets/newsletter/timepicker.css +54 -0
  19. data/app/controllers/newsletter/application_controller.rb +5 -26
  20. data/app/controllers/newsletter/areas_controller.rb +0 -38
  21. data/app/controllers/newsletter/designs_controller.rb +5 -2
  22. data/app/controllers/newsletter/elements_controller.rb +7 -7
  23. data/app/controllers/newsletter/fields_controller.rb +1 -46
  24. data/app/controllers/newsletter/newsletters_controller.rb +6 -24
  25. data/app/controllers/newsletter/pieces_controller.rb +8 -21
  26. data/app/helpers/newsletter/designs_helper.rb +1 -8
  27. data/app/helpers/newsletter/layout_helper.rb +43 -0
  28. data/app/helpers/newsletter/newsletters_helper.rb +9 -5
  29. data/app/models/newsletter/area.rb +1 -4
  30. data/app/models/newsletter/asset.rb +7 -1
  31. data/app/models/newsletter/design.rb +48 -34
  32. data/app/models/newsletter/element.rb +0 -42
  33. data/app/models/newsletter/field.rb +7 -10
  34. data/app/models/newsletter/field/inline_asset.rb +15 -2
  35. data/app/models/newsletter/newsletter.rb +18 -11
  36. data/app/models/newsletter/piece.rb +20 -24
  37. data/app/views/layouts/newsletter/application.html.erb +20 -116
  38. data/app/views/layouts/newsletter/layout.html.erb +15 -0
  39. data/app/views/newsletter/areas/_area.html.erb +1 -1
  40. data/app/views/newsletter/designs/_area_fields.html.erb +1 -1
  41. data/app/views/newsletter/designs/_form.html.erb +11 -29
  42. data/app/views/newsletter/designs/_newsletter_area.html.erb +2 -2
  43. data/app/views/newsletter/designs/edit.html.erb +3 -6
  44. data/app/views/newsletter/designs/index.html.erb +7 -6
  45. data/app/views/newsletter/designs/new.html.erb +2 -2
  46. data/app/views/newsletter/designs/show.html.erb +5 -5
  47. data/app/views/newsletter/elements/_field_fields.html.erb +12 -25
  48. data/app/views/newsletter/elements/_form.html.erb +38 -34
  49. data/app/views/newsletter/elements/edit.html.erb +2 -5
  50. data/app/views/newsletter/elements/index.html.erb +7 -7
  51. data/app/views/newsletter/elements/new.html.erb +2 -2
  52. data/app/views/newsletter/elements/show.html.erb +5 -5
  53. data/app/views/newsletter/fields/_inline_asset.html.erb +12 -32
  54. data/app/views/newsletter/fields/_text.html.erb +2 -4
  55. data/app/views/newsletter/fields/_text_area.html.erb +2 -7
  56. data/app/views/newsletter/newsletters/_form.html.erb +6 -16
  57. data/app/views/newsletter/newsletters/_head.html.erb +2 -3
  58. data/app/views/newsletter/newsletters/_newsletter.html.erb +11 -6
  59. data/app/views/newsletter/newsletters/archive.html.erb +1 -1
  60. data/app/views/newsletter/newsletters/edit.html.erb +8 -16
  61. data/app/views/newsletter/newsletters/index.html.erb +7 -7
  62. data/app/views/newsletter/newsletters/new.html.erb +2 -2
  63. data/app/views/newsletter/newsletters/show.html.erb +11 -6
  64. data/app/views/newsletter/pieces/_form.html.erb +1 -8
  65. data/app/views/newsletter/pieces/edit.html.erb +2 -4
  66. data/app/views/newsletter/pieces/new.html.erb +3 -5
  67. data/config/locales/newsletters.en.yml +27 -0
  68. data/config/routes.rb +4 -4
  69. data/designs/exports/Example.yml +202 -0
  70. data/designs/exports/example-export.yaml +481 -87
  71. data/lib/deleteable.rb +12 -14
  72. data/lib/newsletter/engine.rb +112 -6
  73. data/lib/newsletter/version.rb +1 -1
  74. data/lib/tasks/newsletter.rake +54 -41
  75. data/newsletter.gemspec +3 -1
  76. data/spec/test_app/.rspec +2 -0
  77. data/spec/test_app/app/controllers/application_controller.rb +5 -0
  78. data/spec/test_app/app/models/ability.rb +8 -0
  79. data/spec/test_app/app/models/user.rb +10 -0
  80. data/spec/test_app/app/views/layouts/application.html.erb +3 -1
  81. data/spec/test_app/config/database.postgres.yml +21 -0
  82. data/spec/test_app/config/initializers/carrierwave.rb +23 -0
  83. data/spec/test_app/config/newsletter.yml +6 -3
  84. data/spec/test_app/config/routes.rb +1 -2
  85. data/spec/test_app/db/migrate/20131222171230_create_users.rb +13 -0
  86. data/spec/test_app/db/schema.rb +13 -2
  87. data/spec/test_app/features/newsletter_management.feature +39 -0
  88. data/spec/test_app/features/piece_management.feature +20 -0
  89. data/spec/test_app/features/step_definitions/debugging_steps.rb +3 -0
  90. data/spec/test_app/features/step_definitions/design_steps.rb +3 -0
  91. data/spec/test_app/features/step_definitions/login_steps.rb +4 -0
  92. data/spec/test_app/features/step_definitions/newsletter_steps.rb +24 -0
  93. data/spec/test_app/features/step_definitions/piece_steps.rb +26 -0
  94. data/{features → spec/test_app/features}/step_definitions/webrat_steps.rb +10 -6
  95. data/spec/test_app/features/support/env.rb +36 -0
  96. data/spec/test_app/features/support/functions.rb +3 -0
  97. data/{features → spec/test_app/features}/support/paths.rb +10 -1
  98. data/spec/test_app/lib/debugging.rb +61 -0
  99. data/spec/test_app/script/full_suite +44 -0
  100. data/spec/test_app/script/rspec_multi_db +26 -0
  101. data/spec/test_app/spec/controllers/newsletter/pieces_controller_spec.rb +175 -0
  102. data/spec/test_app/spec/factories/_functions.rb +19 -0
  103. data/spec/test_app/spec/factories/assets.rb +8 -0
  104. data/spec/test_app/spec/factories/designs.rb +1 -1
  105. data/spec/test_app/spec/factories/newsletters.rb +68 -6
  106. data/spec/test_app/spec/factories/pieces.rb +8 -0
  107. data/spec/test_app/spec/factories/users.rb +13 -0
  108. data/spec/test_app/spec/features/newsletter/design_spec.rb +175 -0
  109. data/spec/test_app/spec/features/newsletter/element_spec.rb +53 -0
  110. data/spec/test_app/spec/features/newsletter/newsletter_spec.rb +99 -3
  111. data/spec/test_app/spec/helpers/newsletter/newsletters_helper_spec.rb +65 -0
  112. data/spec/test_app/spec/models/newsletter/asset_spec.rb +23 -0
  113. data/spec/test_app/spec/models/newsletter/design_spec.rb +23 -2
  114. data/spec/test_app/spec/models/newsletter/element_spec.rb +4 -0
  115. data/spec/test_app/spec/models/newsletter/inline_asset_spec.rb +43 -0
  116. data/spec/test_app/spec/models/newsletter/newsletter_spec.rb +102 -2
  117. data/spec/test_app/spec/models/newsletter/piece_spec.rb +33 -0
  118. data/spec/test_app/spec/rails_helper.rb +82 -0
  119. data/spec/test_app/spec/routing/newsletter/pieces_routing_spec.rb +28 -0
  120. data/spec/test_app/spec/spec_helper.rb +73 -64
  121. data/spec/test_app/spec/support/carrierwave.rb +7 -0
  122. data/spec/test_app/spec/support/continuances.rb +18 -0
  123. data/spec/test_app/spec/support/files/iReach_logo.gif +0 -0
  124. data/spec/test_app/spec/support/files/test.pdf +0 -0
  125. data/spec/test_app/spec/support/functions.rb +3 -0
  126. metadata +145 -726
  127. data/README +0 -243
  128. data/README.rdoc +0 -3
  129. data/app/views/newsletter/elements/_newsletter_field.html.erb +0 -37
  130. data/features/support/env.rb +0 -17
  131. data/lib/tasks/newsletter_tasks.rake +0 -4
  132. data/lib/tasks/rspec.rake +0 -158
  133. data/spec/spec_helper.rb +0 -55
  134. data/spec/test_app/db/structure.sql +0 -12
  135. data/spec/test_app/newsletters/designs/My_Design/elements/_left_column_article.html.erb +0 -10
  136. data/spec/test_app/newsletters/designs/My_Design/elements/_left_column_image.html.erb +0 -2
  137. data/spec/test_app/newsletters/designs/My_Design/elements/_right_column_article.html.erb +0 -5
  138. data/spec/test_app/newsletters/designs/My_Design/elements/_right_column_headline.html.erb +0 -1
  139. data/spec/test_app/newsletters/designs/My_Design/elements/_right_column_image.html.erb +0 -1
  140. data/spec/test_app/newsletters/designs/My_Design/elements/_right_column_paragraph.html.erb +0 -3
  141. data/spec/test_app/newsletters/designs/My_Design/layout.html.erb +0 -66
  142. data/spec/test_app/newsletters/designs/Testo_Changeo/elements/_left_column_article.html.erb +0 -10
  143. data/spec/test_app/newsletters/designs/Testo_Changeo/layout.html.erb +0 -66
  144. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_left_column_article.html.erb +0 -10
  145. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_left_column_image.html.erb +0 -2
  146. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_right_column_article.html.erb +0 -5
  147. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_right_column_headline.html.erb +0 -1
  148. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_right_column_image.html.erb +0 -1
  149. data/spec/test_app/newsletters/designs/empower_innovative_e-business/elements/_right_column_paragraph.html.erb +0 -3
  150. data/spec/test_app/newsletters/designs/empower_innovative_e-business/layout.html.erb +0 -66
  151. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_left_column_article.html.erb +0 -10
  152. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_left_column_image.html.erb +0 -2
  153. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_right_column_article.html.erb +0 -5
  154. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_right_column_headline.html.erb +0 -1
  155. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_right_column_image.html.erb +0 -1
  156. data/spec/test_app/newsletters/designs/enable_extensible_systems/elements/_right_column_paragraph.html.erb +0 -3
  157. data/spec/test_app/newsletters/designs/enable_extensible_systems/layout.html.erb +0 -66
  158. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_left_column_article.html.erb +0 -10
  159. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_left_column_image.html.erb +0 -2
  160. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_right_column_article.html.erb +0 -5
  161. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_right_column_headline.html.erb +0 -1
  162. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_right_column_image.html.erb +0 -1
  163. data/spec/test_app/newsletters/designs/engage_innovative_schemas/elements/_right_column_paragraph.html.erb +0 -3
  164. data/spec/test_app/newsletters/designs/engage_innovative_schemas/layout.html.erb +0 -67
  165. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_left_column_article.html.erb +0 -10
  166. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_left_column_image.html.erb +0 -2
  167. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_right_column_article.html.erb +0 -5
  168. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_right_column_headline.html.erb +0 -1
  169. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_right_column_image.html.erb +0 -1
  170. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/elements/_right_column_paragraph.html.erb +0 -3
  171. data/spec/test_app/newsletters/designs/envisioneer_seamless_ROI/layout.html.erb +0 -66
  172. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_left_column_article.html.erb +0 -10
  173. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_left_column_image.html.erb +0 -2
  174. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_right_column_article.html.erb +0 -5
  175. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_right_column_headline.html.erb +0 -1
  176. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_right_column_image.html.erb +0 -1
  177. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/elements/_right_column_paragraph.html.erb +0 -3
  178. data/spec/test_app/newsletters/designs/harness_integrated_partnerships/layout.html.erb +0 -66
  179. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_left_column_article.html.erb +0 -10
  180. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_left_column_image.html.erb +0 -2
  181. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_right_column_article.html.erb +0 -5
  182. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_right_column_headline.html.erb +0 -1
  183. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_right_column_image.html.erb +0 -1
  184. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/elements/_right_column_paragraph.html.erb +0 -3
  185. data/spec/test_app/newsletters/designs/innovate_24_365_functionalities/layout.html.erb +0 -66
  186. data/spec/test_app/newsletters/designs/integrate_mission-critical_systems/elements/_left_column_article.html.erb +0 -10
  187. data/spec/test_app/newsletters/designs/integrate_mission-critical_systems/layout.html.erb +0 -66
  188. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_left_column_article.html.erb +0 -10
  189. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_left_column_image.html.erb +0 -2
  190. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_right_column_article.html.erb +0 -5
  191. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_right_column_headline.html.erb +0 -1
  192. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_right_column_image.html.erb +0 -1
  193. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/elements/_right_column_paragraph.html.erb +0 -3
  194. data/spec/test_app/newsletters/designs/iterate_real-time_web-readiness/layout.html.erb +0 -67
  195. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_left_column_article.html.erb +0 -10
  196. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_left_column_image.html.erb +0 -2
  197. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_right_column_article.html.erb +0 -5
  198. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_right_column_headline.html.erb +0 -1
  199. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_right_column_image.html.erb +0 -1
  200. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/elements/_right_column_paragraph.html.erb +0 -3
  201. data/spec/test_app/newsletters/designs/iterate_strategic_architectures/layout.html.erb +0 -67
  202. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_left_column_article.html.erb +0 -10
  203. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_left_column_image.html.erb +0 -2
  204. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_right_column_article.html.erb +0 -5
  205. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_right_column_headline.html.erb +0 -1
  206. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_right_column_image.html.erb +0 -1
  207. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/elements/_right_column_paragraph.html.erb +0 -3
  208. data/spec/test_app/newsletters/designs/orchestrate_sticky_communities/layout.html.erb +0 -67
  209. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_left_column_article.html.erb +0 -10
  210. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_left_column_image.html.erb +0 -2
  211. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_right_column_article.html.erb +0 -5
  212. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_right_column_headline.html.erb +0 -1
  213. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_right_column_image.html.erb +0 -1
  214. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/elements/_right_column_paragraph.html.erb +0 -3
  215. data/spec/test_app/newsletters/designs/repurpose_impactful_partnerships/layout.html.erb +0 -67
  216. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_left_column_article.html.erb +0 -10
  217. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_left_column_image.html.erb +0 -2
  218. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_right_column_article.html.erb +0 -5
  219. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_right_column_headline.html.erb +0 -1
  220. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_right_column_image.html.erb +0 -1
  221. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/elements/_right_column_paragraph.html.erb +0 -3
  222. data/spec/test_app/newsletters/designs/revolutionize_robust_partnerships/layout.html.erb +0 -66
  223. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_left_column_article.html.erb +0 -10
  224. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_left_column_image.html.erb +0 -2
  225. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_right_column_article.html.erb +0 -5
  226. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_right_column_headline.html.erb +0 -1
  227. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_right_column_image.html.erb +0 -1
  228. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/elements/_right_column_paragraph.html.erb +0 -3
  229. data/spec/test_app/newsletters/designs/revolutionize_turn-key_bandwidth/layout.html.erb +0 -66
  230. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_left_column_article.html.erb +0 -10
  231. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_left_column_image.html.erb +0 -2
  232. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_right_column_article.html.erb +0 -5
  233. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_right_column_headline.html.erb +0 -1
  234. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_right_column_image.html.erb +0 -1
  235. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/elements/_right_column_paragraph.html.erb +0 -3
  236. data/spec/test_app/newsletters/designs/scale_ubiquitous_synergies/layout.html.erb +0 -67
  237. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_left_column_article.html.erb +0 -10
  238. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_left_column_image.html.erb +0 -2
  239. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_right_column_article.html.erb +0 -5
  240. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_right_column_headline.html.erb +0 -1
  241. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_right_column_image.html.erb +0 -1
  242. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/elements/_right_column_paragraph.html.erb +0 -3
  243. data/spec/test_app/newsletters/designs/syndicate_visionary_metrics/layout.html.erb +0 -66
  244. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_left_column_article.html.erb +0 -10
  245. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_left_column_image.html.erb +0 -2
  246. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_right_column_article.html.erb +0 -5
  247. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_right_column_headline.html.erb +0 -1
  248. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_right_column_image.html.erb +0 -1
  249. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/elements/_right_column_paragraph.html.erb +0 -3
  250. data/spec/test_app/newsletters/designs/target_enterprise_functionalities/layout.html.erb +0 -67
  251. data/spec/test_app/newsletters/designs/transition_enterprise_systems/elements/_left_column_article.html.erb +0 -10
  252. data/spec/test_app/newsletters/designs/transition_enterprise_systems/layout.html.erb +0 -66
  253. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_left_column_article.html.erb +0 -10
  254. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_left_column_image.html.erb +0 -2
  255. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_right_column_article.html.erb +0 -5
  256. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_right_column_headline.html.erb +0 -1
  257. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_right_column_image.html.erb +0 -1
  258. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/elements/_right_column_paragraph.html.erb +0 -3
  259. data/spec/test_app/newsletters/designs/utilize_one-to-one_schemas/layout.html.erb +0 -66
@@ -27,5 +27,11 @@ module Newsletter
27
27
  def self.build_public_dirname(id)
28
28
  "#{::Newsletter.asset_path}/#{("%08d" %id)[-8,4]}/#{("%08d" %id)[-4,4]}"
29
29
  end
30
+
31
+ def is_image?
32
+ image.content_type.include?('image')
33
+ rescue => e
34
+ false
35
+ end
30
36
  end
31
- end
37
+ end
@@ -21,7 +21,7 @@ module ::Newsletter
21
21
 
22
22
  scope :active, :conditions => {:deleted_at => nil}
23
23
 
24
- validates_presence_of :name
24
+ validates :name, presence: true, uniqueness: true
25
25
 
26
26
  # attr_protected :id
27
27
  #FIXME: make this work with deletable or convert to auditable, and extend it to access destroyed records
@@ -37,7 +37,8 @@ module ::Newsletter
37
37
  :html_text => html_text,
38
38
  :description => description,
39
39
  :areas => areas.collect{|area| area.export_fields},
40
- :elements => elements.collect{|element| element.export_fields}
40
+ :elements => elements.collect{|element| element.export_fields},
41
+ :images => base64_encoded_images
41
42
  },file)
42
43
  end
43
44
  end
@@ -52,7 +53,7 @@ module ::Newsletter
52
53
  design = nil
53
54
  transaction do
54
55
  data[:name] = design_name if design_name
55
- design = Design.create!(:name => data[:name],
56
+ design = Design.create(:name => data[:name],
56
57
  :html_text => data[:html_text],
57
58
  :description => data[:description])
58
59
  data[:areas].each do |area_data|
@@ -61,21 +62,59 @@ module ::Newsletter
61
62
  data[:elements].each do |element_data|
62
63
  Element.import(design,element_data)
63
64
  end
65
+ design.import_images(data[:images])
64
66
  end
67
+ raise "Error importing design: #{design.errors.full_messages.join("\n ")}" unless design.valid?
65
68
  design
66
69
  end
67
70
 
68
71
  # returns path to newsletter design for use in views and is the same for actual file
69
72
  def view_path(this_name=nil)
70
- "#{base_design_path(this_name)}/layout.html.erb"
73
+ File.join(base_design_path(this_name),'layout.html.erb')
71
74
  end
72
75
 
73
- #
76
+ # returns the path to the base of the design's files
74
77
  def base_design_path(this_name=nil)
75
- "#{::Newsletter.designs_path}/designs/#{name_as_path(this_name)}"
78
+ File.join(::Newsletter.designs_path,'designs',name_as_path(this_name))
76
79
  end
77
-
78
80
 
81
+ # returns the image filenames inside a design
82
+ def images
83
+ Dir.glob(File.join(images_path,'*.*')).map{|f| File.basename(f)} || []
84
+ rescue => e
85
+ []
86
+ end
87
+
88
+ # returns the images as an array of base64 encoded strings
89
+ def base64_encoded_images
90
+ images.map {|image| {
91
+ name: image,
92
+ data: Base64.encode64(File.binread(File.join(images_path,image)))
93
+ }}
94
+ end
95
+
96
+ # returns where a design's images should go, can override for 'old_name'
97
+ def images_path(the_name=nil)
98
+ the_name ||= name
99
+ File.join('public','images',name_as_path(the_name))
100
+ end
101
+
102
+ # move a design's images on name change
103
+ def move_images
104
+ return unless @old_name && @old_name != name
105
+ FileUtils.mv(images_path(@old_name),images_path)
106
+ end
107
+
108
+ # imports images from array of base64 encoded images
109
+ def import_images(image_imports)
110
+ image_imports ||= []
111
+ FileUtils.mkdir_p(images_path)
112
+ image_imports.each do |image|
113
+ File.binwrite(File.join(images_path,image[:name]),
114
+ Base64.decode64(image[:data])
115
+ )
116
+ end
117
+ end
79
118
 
80
119
  def html_text
81
120
  return @html_text if @html_text
@@ -86,20 +125,6 @@ module ::Newsletter
86
125
  @html_text = text
87
126
  end
88
127
 
89
- # def area_attributes=(area_attributes)
90
- # area_attributes.each do |attributes|
91
- # if attributes[:id].blank?
92
- # Rails.logger.debug "Building Area : #{attributes.inspect}"
93
- # areas.build(attributes)
94
- # else
95
- # Rails.logger.debug "Setting Area data: #{attributes.inspect}"
96
- # area = areas.detect{|area| area.id == attributes[:id].to_i}
97
- # area.attributes = attributes
98
- # end
99
- # end
100
- # end
101
-
102
-
103
128
  def name=(new_name)
104
129
  return if self[:name].eql?(new_name)
105
130
  @old_name = self[:name] unless @old_name
@@ -121,6 +146,7 @@ module ::Newsletter
121
146
  end
122
147
 
123
148
  include Deleteable
149
+
124
150
  protected
125
151
  def read_design
126
152
  File.readlines(view_path).join
@@ -137,6 +163,7 @@ module ::Newsletter
137
163
  def move_design_on_name_change
138
164
  return unless @old_name and File.exists?(view_path(@old_name))
139
165
  FileUtils.mv(base_design_path(@old_name),base_design_path)
166
+ move_images(@old_name, name)
140
167
  end
141
168
 
142
169
  def write_design
@@ -145,18 +172,5 @@ module ::Newsletter
145
172
  file.write html_text
146
173
  end
147
174
  end
148
-
149
-
150
- # def save_areas
151
- # areas.each do |area|
152
- # if area.should_destroy?
153
- # Rails.logger.debug "Destroying newsletter area: #{area.inspect}"
154
- # area.destroy
155
- # else
156
- # Rails.logger.debug "Saving newsletter area: #{area.inspect}"
157
- # area.save
158
- # end
159
- # end
160
- # end
161
175
  end
162
176
  end
@@ -61,35 +61,6 @@ module Newsletter
61
61
  @html_text = text
62
62
  end
63
63
 
64
- def update_attributes(params={})
65
- transaction do
66
- super
67
- end
68
- end
69
-
70
- def save_fields
71
- return true unless @fields_attributes.present?
72
- @fields_attributes.each_pair do |index,attributes|
73
- should_destroy = ['true','1'].include?attributes.delete(:_destroy)
74
- if attributes[:id].blank?
75
- next if should_destroy
76
- attributes.delete(:id)
77
- klass = attributes.delete(:type)
78
- fields << klass.constantize.new(attributes)
79
- else
80
- id = attributes.delete(:id).to_i
81
- if should_destroy
82
- fields.where(id: id).limit(1).each(&:destroy)
83
- else
84
- type = attributes.delete(:type)
85
- field = fields.detect{|field| field.id == id}
86
- field.update_attributes(attributes)
87
- field = Field.morph(field,type) unless field.class.name.eql?(type)
88
- end
89
- end
90
- end
91
- end
92
-
93
64
  # returns field data so that Newsletter::Design.export(instance) can export itself to a YAML file
94
65
  def export_fields
95
66
  { :name => name,
@@ -121,7 +92,6 @@ module Newsletter
121
92
  move_design_on_name_change
122
93
  write_design
123
94
  super
124
- save_fields
125
95
  end
126
96
  end
127
97
 
@@ -146,17 +116,5 @@ module Newsletter
146
116
  FileUtils.mv(file_path(@old_name),file_path)
147
117
  end
148
118
 
149
- # def save_fields
150
- # Rails.logger.warn "Fields: #{fields.inspect}"
151
- # fields.each do |field|
152
- # if field.should_destroy?
153
- # Rails.logger.warn "Destroy Field: #{field.inspect}"
154
- # field.delete
155
- # else
156
- # Rails.logger.warn "Save Field: #{field.inspect}"
157
- # field.save!
158
- # end
159
- # end
160
- # end
161
119
  end
162
120
  end
@@ -15,6 +15,8 @@ module Newsletter
15
15
  has_many :field_values, :class_name => 'Newsletter::FieldValue'
16
16
  belongs_to :updated_by, :class_name => 'User'
17
17
 
18
+ acts_as_list :scope => :element, :column => :sequence
19
+
18
20
  validates_presence_of :name
19
21
  =begin
20
22
  FIXME: make this work with deletable or convert to auditable, and extend it to access destroyed records
@@ -25,9 +27,8 @@ module Newsletter
25
27
  ["name=? and element_id=? and id!=? and deleted_at is null", field.element_id,
26
28
  field.id]).nil? }
27
29
  =end
28
- attr_accessor :should_destroy
29
-
30
- attr_protected :id
30
+ attr_accessible :name, :type, :element_id, :label, :sequence, :is_required,
31
+ :description, :updated_by
31
32
 
32
33
  include Deleteable
33
34
 
@@ -58,8 +59,9 @@ module Newsletter
58
59
  end
59
60
 
60
61
  # returns a pieces value for a given Newsletter::Field
61
- def value_for_piece(piece)
62
- get_value(piece).to_s.html_safe
62
+ def value_for_piece(piece,safe=true)
63
+ return get_value(piece).to_s.html_safe if safe
64
+ get_value(piece).to_s
63
65
  end
64
66
 
65
67
  # sets a pieces value for a Newsletter::Field
@@ -92,11 +94,6 @@ module Newsletter
92
94
  Field.find(field.id)
93
95
  end
94
96
 
95
- # used in figuring out whether to destroy a field as we are editing fields inside an element form
96
- def should_destroy?
97
- should_destroy.to_i == 1
98
- end
99
-
100
97
  # find the partial to display a form for creating a Newsletter::Piece
101
98
  def form_partial_path
102
99
  "newsletter/fields/#{type.to_s.gsub(/.*Newsletter::Field::/,'').gsub(/([^A-Z])([A-Z])/,'\\1_\\2').downcase}"
@@ -11,8 +11,6 @@ module Newsletter
11
11
  has_many :assets, :foreign_key => :field_id,
12
12
  :class_name => 'Newsletter::Asset'
13
13
 
14
- attr_protected :id
15
-
16
14
  # overridden from main class to choose between a Newsletter::Asset or a given URL
17
15
  def value_for_piece(piece)
18
16
  Value.new(:url => url_for_piece(piece), :text => get_value(piece,:text), :asset => asset(piece))
@@ -55,6 +53,21 @@ module Newsletter
55
53
  # fields
56
54
  class Value
57
55
  attr_accessor :url, :text, :asset, :asset_id
56
+ def is_image?
57
+ if asset.present?
58
+ asset.is_image?
59
+ else
60
+ is_image_by_extension?
61
+ end
62
+ end
63
+
64
+ def is_image_by_extension?
65
+ extension = File.extname(url).gsub(/^\./,'')
66
+ [ 'bmp', 'cod', 'gif', 'ief', 'jpe', 'jpeg', 'jpg', 'png',
67
+ 'jfif', 'svg', 'tif', 'tiff'
68
+ ].include?(extension.downcase)
69
+ end
70
+
58
71
  def initialize(params)
59
72
  @url = params[:url]
60
73
  @text = params[:text]
@@ -27,6 +27,7 @@ module Newsletter
27
27
 
28
28
  attr_protected :id
29
29
 
30
+ # returns any piece that is a headline
30
31
  def headlines
31
32
  pieces.select{|piece| piece.respond_to?(:headline)}
32
33
  end
@@ -52,6 +53,7 @@ module Newsletter
52
53
  end
53
54
  end
54
55
 
56
+ # whether or not the newsletter will show on the archives page
55
57
  def published?
56
58
  !published_at.nil?
57
59
  end
@@ -70,6 +72,10 @@ module Newsletter
70
72
  def public_url(mode='')
71
73
  "#{::Newsletter.site_url}/newsletters/#{self[:id]}#{mode.blank? ? '' : "/#{mode}"}"
72
74
  end
75
+
76
+ def image_uri(filename)
77
+ File.join(design.images_path.gsub(/.*public\//,'/'), filename)
78
+ end
73
79
 
74
80
  # used to generate the newsletter from a model or someplace other than the web stack
75
81
  # FIXME: There has to be a better way, where railsy stuff works ... erb doesn't seem
@@ -82,7 +88,7 @@ module Newsletter
82
88
  fetch(public_url(mode))
83
89
  end
84
90
 
85
- # retrieve a newsletter area by name
91
+ # retrieve a newsletter area by name - for use in render/views
86
92
  def area(name)
87
93
  design.areas.by_name(name).first
88
94
  end
@@ -94,30 +100,31 @@ module Newsletter
94
100
  design.areas.each do |area|
95
101
  variables[area.name.to_sym] = area
96
102
  end
103
+ variables[:title] = self.name
97
104
  variables
98
105
  end
99
106
 
107
+ # :nodoc sets a pieces attributes coming from the form
108
+ # FIXME: this is probably covered by rails 3 accepts_attributes_for, but we
109
+ # will change when we go to 4 anyways
100
110
  def piece_attributes=(piece_attributes)
101
111
  piece_attributes.each do |attributes|
102
112
  pieces.build(attributes)
103
113
  end
104
114
  end
105
115
 
116
+ # helper to get areas for newsletter
106
117
  def areas
107
118
  design.try(:areas).to_a
108
119
  end
109
-
120
+
121
+ # fetch a url and return the body
110
122
  def fetch(uri_str, limit = 10)
111
- # You should choose better exception.
112
- Rails.logger.debug "Fetching #{uri_str}"
113
- raise ArgumentError, 'HTTP redirect too deep' if limit == 0
114
-
115
- response = Net::HTTP.get_response(URI.parse(uri_str))
116
- case response
117
- when Net::HTTPSuccess then response.body
118
- when Net::HTTPRedirection then fetch(response['location'], limit - 1)
123
+ uri = URI.parse(uri_str)
124
+ if uri.scheme.eql?('file')
125
+ File.binread(uri_str.gsub(%r#^file://#,''))
119
126
  else
120
- response.error!
127
+ uri.read
121
128
  end
122
129
  end
123
130
 
@@ -1,5 +1,5 @@
1
1
  =begin rdoc
2
- Author:: Chris Hauboldt (mailto:biz@lnstar.com)
2
+ Aduthor:: Chris Hauboldt (mailto:biz@lnstar.com)
3
3
  Copyright:: 2009 Lone Star Internet Inc.
4
4
 
5
5
  NewsletterPieces are the glue that tie data together to form a piece in an area of a design.
@@ -24,7 +24,10 @@ module Newsletter
24
24
 
25
25
  attr_accessor :field_values_attributes
26
26
 
27
+ #attr_accessible :field_values_attributes, :newsletter_id, :element_id, :area_id
27
28
  attr_protected :id
29
+
30
+ #validates_presence_of :newsletter, :element, :area, :field_values
28
31
 
29
32
  # returns locals to be used in its Newsletter::Element design
30
33
  def locals
@@ -32,51 +35,41 @@ module Newsletter
32
35
  @locals = Hash.new
33
36
  fields.each do |field|
34
37
  @locals[field.name.to_sym] = field.value_for_piece(self)
35
- define_getter_for_locals(field.name.to_sym) unless respond_to?(field.name.to_sym)
36
38
  end
37
39
  @locals
38
40
  end
39
41
 
42
+ # returns a pieces fields
40
43
  def fields
41
44
  element.try(:fields).try(:uniq) || []
42
45
  end
43
46
 
44
- def newsletter
45
- return nil unless newsletter_id.present?
46
- @newsletter ||= ::Newsletter::Newsletter.find(newsletter_id)
47
- end
48
-
49
47
  # used to save out a piece's fields, since they are inline in a piece's form
50
48
  def field_values_attributes=(values)
51
49
  @field_values_attributes = values
52
50
  end
53
51
 
54
- def set_field_values
55
- return unless defined?(@field_values_attributes) && @field_values_attributes.present?
56
- @field_values_attributes.each_pair do |field_id,key_value_pairs|
57
- field = Field.find(field_id)
58
- field.set_value_for_piece(self,key_value_pairs)
59
- end
60
- end
61
-
52
+ # whether it can respond to a 'method' in its locals hash
62
53
  def respond_to?(my_method,use_private=false)
63
54
  return true if super
64
55
  if locals.keys.include?(my_method.to_sym)
65
- define_getter_for_locals(my_method)
66
56
  true
67
57
  else
68
58
  false
69
59
  end
70
60
  end
71
61
 
62
+ # respond for its named methods for its element's template
63
+ # these values will be in its locals hash
72
64
  def method_missing(*args)
73
65
  if args.length == 1 and locals.has_key?(args[0].to_sym)
74
- define_getter_for_locals(args[0])
66
+ locals[args[0].to_sym]
75
67
  else
76
68
  super
77
69
  end
78
70
  end
79
71
 
72
+ # :nodoc override save for transaction to set its field values
80
73
  def save(*args)
81
74
  transaction do
82
75
  set_field_values
@@ -84,13 +77,16 @@ module Newsletter
84
77
  end
85
78
  end
86
79
 
87
- private
88
- def define_getter_for_locals(key)
89
- class_eval %Q|
90
- def #{key}
91
- locals[:#{key}]
92
- end|
93
- eval key.to_s
80
+ protected
81
+
82
+ # sets the piece's field values after a save
83
+ def set_field_values
84
+ return unless defined?(@field_values_attributes) && @field_values_attributes.present?
85
+ @field_values_attributes.each_pair do |field_id,key_value_pairs|
86
+ field = Field.find(field_id)
87
+ field.set_value_for_piece(self,key_value_pairs)
88
+ end
94
89
  end
90
+
95
91
  end
96
92
  end