fanforce-plugin-factory 0.41.0 → 1.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. data/.gitignore +1 -0
  2. data/.ruby-version +1 -0
  3. data/.yardopts +5 -0
  4. data/.yardopts.rb +1 -0
  5. data/Gemfile +9 -0
  6. data/README.md +40 -75
  7. data/Rakefile +61 -4
  8. data/fanforce-plugin-factory.gemspec +21 -21
  9. data/lib/fanforce/plugin_factory.rb +16 -58
  10. data/lib/fanforce/plugin_factory/Rakefile +51 -0
  11. data/lib/fanforce/plugin_factory/Routes.rb +33 -0
  12. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/_bootstrap.scss +2 -0
  13. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/_common.scss +1 -0
  14. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/_directives.scss +7 -0
  15. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/_font-awesome.scss +1 -0
  16. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/_ui-select.scss +3 -0
  17. data/lib/fanforce/plugin_factory/{assets/lib/common → asset_framework/plugin_factory/bootstrap}/_bootstrap-overrides.scss +2 -0
  18. data/lib/fanforce/plugin_factory/{assets/lib/vendors/bootstrap/css → asset_framework/plugin_factory/bootstrap}/bootstrap.css +2 -2
  19. data/lib/fanforce/plugin_factory/{assets/lib/vendors/bootstrap/js → asset_framework/plugin_factory/bootstrap}/bootstrap.js +0 -0
  20. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/bootstrap/bootstrap.min.css +7 -0
  21. data/lib/fanforce/plugin_factory/{assets/lib/vendors/bootstrap/js → asset_framework/plugin_factory/bootstrap}/bootstrap.min.js +0 -0
  22. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/bootstrap/glyphicons-halflings-regular.eot +0 -0
  23. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/bootstrap/glyphicons-halflings-regular.svg +229 -0
  24. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  25. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/bootstrap/glyphicons-halflings-regular.woff +0 -0
  26. data/lib/fanforce/plugin_factory/{assets/lib → asset_framework/plugin_factory}/common/_mixins.scss +2 -1
  27. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives.coffee +1 -0
  28. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/error/_error.scss +6 -0
  29. data/lib/fanforce/plugin_factory/{assets/lib/common/module-error → asset_framework/plugin_factory/directives/error}/arrow-left.png +0 -0
  30. data/lib/fanforce/plugin_factory/{assets/lib/common/module-error → asset_framework/plugin_factory/directives/error}/icon-error.png +0 -0
  31. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/initiative-footer/_initiative-footer.coffee +16 -0
  32. data/lib/fanforce/plugin_factory/{assets/lib/common/_module-add-initiative-footer.scss → asset_framework/plugin_factory/directives/initiative-footer/_initiative-footer.scss} +4 -1
  33. data/lib/fanforce/plugin_factory/{assets/lib/common/_module-initiative-searcher.scss → asset_framework/plugin_factory/directives/initiative-searcher/_initiative-searcher.scss} +14 -13
  34. data/lib/fanforce/plugin_factory/{assets/lib/common/module-initiative-searcher → asset_framework/plugin_factory/directives/initiative-searcher}/icon-search.png +0 -0
  35. data/lib/fanforce/plugin_factory/{assets/lib/common/module-initiative-searcher → asset_framework/plugin_factory/directives/initiative-searcher}/spinner.gif +0 -0
  36. data/lib/fanforce/plugin_factory/{assets/lib/common/module-initiative-searcher → asset_framework/plugin_factory/directives/initiative-searcher}/sprite-arrows.png +0 -0
  37. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/loading/_loading.coffee +4 -0
  38. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/loading/_loading.scss +4 -0
  39. data/lib/fanforce/plugin_factory/{assets/js/add_source_popup.js → asset_framework/plugin_factory/directives/saving-to-server/_saving-to-server.coffee} +0 -0
  40. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/saving-to-server/_saving-to-server.scss +6 -0
  41. data/lib/fanforce/plugin_factory/{assets/lib/common/module-saving-initiative → asset_framework/plugin_factory/directives/saving-to-server}/spinner.gif +0 -0
  42. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/start-arrow/_start-arrow.coffee +8 -0
  43. data/lib/fanforce/plugin_factory/{assets/lib/common/_module-start-here.scss → asset_framework/plugin_factory/directives/start-arrow/_start-arrow.scss} +5 -4
  44. data/lib/fanforce/plugin_factory/{assets/lib/common/module-start-here → asset_framework/plugin_factory/directives/start-arrow}/arrow.png +0 -0
  45. data/lib/fanforce/plugin_factory/{assets/lib/common/_module-video-thumbnail.scss → asset_framework/plugin_factory/directives/video-thumbnail/_video-thumbnail.scss} +4 -4
  46. data/lib/fanforce/plugin_factory/{assets/lib/common/module-video-thumbnail → asset_framework/plugin_factory/directives/video-thumbnail}/icon-play.png +0 -0
  47. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/font-awesome.coffee +1 -0
  48. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/font → asset_framework/plugin_factory/font-awesome}/FontAwesome.otf +0 -0
  49. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/css → asset_framework/plugin_factory/font-awesome}/font-awesome.css +2 -2
  50. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/css → asset_framework/plugin_factory/font-awesome}/font-awesome.min.css +0 -0
  51. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/font → asset_framework/plugin_factory/font-awesome}/fontawesome-webfont.eot +0 -0
  52. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/font → asset_framework/plugin_factory/font-awesome}/fontawesome-webfont.svg +0 -0
  53. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/font → asset_framework/plugin_factory/font-awesome}/fontawesome-webfont.ttf +0 -0
  54. data/lib/fanforce/plugin_factory/{assets/lib/vendors/font-awesome/font → asset_framework/plugin_factory/font-awesome}/fontawesome-webfont.woff +0 -0
  55. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/lib.coffee +1 -0
  56. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/lib/ng-focus-blur.js +68 -0
  57. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/lib/ng-visible.js +7 -0
  58. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/ui-select.coffee +1 -0
  59. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/ui-select/select.css +171 -0
  60. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/ui-select/select.js +1281 -0
  61. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/ui-select/select_override.scss +1 -0
  62. data/lib/fanforce/plugin_factory/asset_framework/plugin_factory/ui-select/selectize.default.css +443 -0
  63. data/lib/fanforce/plugin_factory/cli.rb +5 -0
  64. data/lib/fanforce/plugin_factory/cli/lib/bitbucket.rb +77 -0
  65. data/lib/fanforce/plugin_factory/cli/lib/bundler.rb +21 -0
  66. data/lib/fanforce/plugin_factory/cli/lib/env.rb +96 -0
  67. data/lib/fanforce/plugin_factory/cli/lib/git.rb +59 -0
  68. data/lib/fanforce/plugin_factory/cli/lib/heroku.rb +94 -0
  69. data/lib/fanforce/plugin_factory/cli/lib/iron.rb +71 -0
  70. data/lib/fanforce/plugin_factory/cli/lib/pow.rb +46 -0
  71. data/lib/fanforce/plugin_factory/cli/lib/scaffolding.rb +74 -0
  72. data/lib/fanforce/plugin_factory/cli/lib/scaffolding_file.rb +510 -0
  73. data/lib/fanforce/plugin_factory/cli/lib/uranium.rb +77 -0
  74. data/lib/fanforce/plugin_factory/cli/lib/utils.rb +57 -0
  75. data/lib/fanforce/plugin_factory/cli/scripts/config.rb +9 -0
  76. data/lib/fanforce/plugin_factory/cli/scripts/create.rb +64 -0
  77. data/lib/fanforce/plugin_factory/cli/scripts/destroy.rb +61 -0
  78. data/lib/fanforce/plugin_factory/cli/scripts/diff.rb +156 -0
  79. data/lib/fanforce/plugin_factory/cli/scripts/push.rb +88 -0
  80. data/lib/fanforce/plugin_factory/cli/scripts/restart.rb +41 -0
  81. data/lib/fanforce/plugin_factory/cli/scripts/setup.rb +70 -0
  82. data/lib/fanforce/plugin_factory/cli/scripts/update.rb +132 -0
  83. data/lib/fanforce/plugin_factory/cli_directory_of_plugins.rb +51 -0
  84. data/lib/fanforce/plugin_factory/cli_single_plugin.rb +52 -0
  85. data/lib/fanforce/plugin_factory/controllers/base_controller.rb +15 -0
  86. data/lib/fanforce/plugin_factory/core_config.rb +94 -0
  87. data/lib/fanforce/plugin_factory/directive_views/initiative-footer.haml +8 -0
  88. data/lib/fanforce/plugin_factory/load.rb +7 -0
  89. data/lib/fanforce/plugin_factory/load_iron_worker.rb +2 -0
  90. data/lib/fanforce/plugin_factory/load_sprockets.rb +2 -0
  91. data/lib/fanforce/plugin_factory/plugin.rb +60 -0
  92. data/lib/fanforce/plugin_factory/scaffolding/._.gitignore.registry +1 -0
  93. data/lib/fanforce/plugin_factory/scaffolding/._Gemfile.registry +3 -0
  94. data/lib/fanforce/plugin_factory/scaffolding/._Rakefile.registry +3 -0
  95. data/lib/fanforce/plugin_factory/scaffolding/._config.json.registry +2 -0
  96. data/lib/fanforce/plugin_factory/scaffolding/._config.ru.registry +4 -0
  97. data/lib/fanforce/plugin_factory/scaffolding/._favicon.ico.registry +1 -0
  98. data/lib/fanforce/plugin_factory/scaffolding/._robots.txt.registry +3 -0
  99. data/lib/fanforce/plugin_factory/scaffolding/.gitignore +27 -0
  100. data/lib/fanforce/plugin_factory/scaffolding/Gemfile +9 -0
  101. data/lib/fanforce/plugin_factory/scaffolding/Rakefile +7 -0
  102. data/lib/fanforce/plugin_factory/scaffolding/Routes.rb +67 -0
  103. data/lib/fanforce/plugin_factory/scaffolding/assets/css/._fembedded.scss.registry +4 -0
  104. data/lib/fanforce/plugin_factory/scaffolding/assets/css/._promotional.scss.registry +4 -0
  105. data/lib/fanforce/plugin_factory/scaffolding/assets/css/._visitor.scss.registry +4 -0
  106. data/lib/fanforce/plugin_factory/scaffolding/assets/css/fembedded.scss +24 -0
  107. data/lib/fanforce/plugin_factory/scaffolding/assets/css/promotional.scss +33 -0
  108. data/lib/fanforce/plugin_factory/scaffolding/assets/css/visitor.scss +61 -0
  109. data/lib/fanforce/plugin_factory/scaffolding/assets/img/._icon-16.png.registry +1 -0
  110. data/lib/fanforce/plugin_factory/scaffolding/assets/img/._icon-32.png.registry +1 -0
  111. data/lib/fanforce/plugin_factory/scaffolding/assets/img/._icon-42.png.registry +1 -0
  112. data/lib/fanforce/plugin_factory/scaffolding/assets/img/._marketplace.png.registry +1 -0
  113. data/lib/fanforce/plugin_factory/{assets → scaffolding/assets}/img/icon-16.png +0 -0
  114. data/lib/fanforce/plugin_factory/{assets → scaffolding/assets}/img/icon-32.png +0 -0
  115. data/lib/fanforce/plugin_factory/{assets → scaffolding/assets}/img/icon-42.png +0 -0
  116. data/lib/fanforce/plugin_factory/scaffolding/assets/img/marketplace.png +0 -0
  117. data/lib/fanforce/plugin_factory/scaffolding/assets/img/promotional/._fanforce_bg.png.registry +1 -0
  118. data/lib/fanforce/plugin_factory/scaffolding/assets/img/promotional/._icon-42.png.registry +1 -0
  119. data/lib/fanforce/plugin_factory/scaffolding/assets/img/promotional/._icon-plus.png.registry +1 -0
  120. data/lib/fanforce/plugin_factory/{assets/lib → scaffolding/assets/img}/promotional/fanforce_bg.png +0 -0
  121. data/lib/fanforce/plugin_factory/{assets/lib → scaffolding/assets/img}/promotional/icon-42.png +0 -0
  122. data/lib/fanforce/plugin_factory/scaffolding/assets/img/promotional/icon-plus.png +0 -0
  123. data/lib/fanforce/plugin_factory/scaffolding/assets/js/._fembedded-app.coffee.registry +5 -0
  124. data/lib/fanforce/plugin_factory/scaffolding/assets/js/._fembedded.js.registry +3 -0
  125. data/lib/fanforce/plugin_factory/scaffolding/assets/js/._promotional.js.registry +3 -0
  126. data/lib/fanforce/plugin_factory/scaffolding/assets/js/fembedded-app.coffee +11 -0
  127. data/lib/fanforce/plugin_factory/scaffolding/assets/js/fembedded.js +12 -0
  128. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/._cookie.coffee.registry +3 -0
  129. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/._filters.coffee.registry +3 -0
  130. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/._utils.coffee.registry +3 -0
  131. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/cookie.coffee +24 -0
  132. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/filters.coffee +9 -0
  133. data/lib/fanforce/plugin_factory/scaffolding/assets/js/lib/utils.coffee +40 -0
  134. data/lib/fanforce/plugin_factory/scaffolding/assets/js/promotional.js +4 -0
  135. data/lib/fanforce/plugin_factory/scaffolding/config.json +24 -0
  136. data/lib/fanforce/plugin_factory/scaffolding/config.ru +8 -0
  137. data/lib/fanforce/plugin_factory/{public → scaffolding}/favicon.ico +0 -0
  138. data/lib/fanforce/plugin_factory/scaffolding/layouts/._fembedded.haml.registry +4 -0
  139. data/lib/fanforce/plugin_factory/scaffolding/layouts/._promotional.haml.registry +2 -0
  140. data/lib/fanforce/plugin_factory/scaffolding/layouts/._visitor.haml.registry +6 -0
  141. data/lib/fanforce/plugin_factory/scaffolding/layouts/fembedded.haml +26 -0
  142. data/lib/fanforce/plugin_factory/{layouts → scaffolding/layouts}/promotional.haml +6 -6
  143. data/lib/fanforce/plugin_factory/{layouts/engage.haml → scaffolding/layouts/visitor.haml} +10 -7
  144. data/lib/fanforce/plugin_factory/scaffolding/robots.txt +7 -0
  145. data/lib/fanforce/plugin_factory/scaffolding/views/._index.haml.registry +3 -0
  146. data/lib/fanforce/plugin_factory/{views → scaffolding/views}/index.haml +13 -7
  147. data/lib/fanforce/plugin_factory/sinatra/_load.rb +87 -0
  148. data/lib/fanforce/plugin_factory/sinatra/error_handling.rb +48 -0
  149. data/lib/fanforce/plugin_factory/sinatra/helper_routes/com_behavior.rb +19 -0
  150. data/lib/fanforce/plugin_factory/sinatra/helper_routes/com_broadcaster.rb +7 -0
  151. data/lib/fanforce/plugin_factory/sinatra/helper_routes/com_connector.rb +11 -0
  152. data/lib/fanforce/plugin_factory/sinatra/helper_routes/com_identifier.rb +3 -0
  153. data/lib/fanforce/plugin_factory/sinatra/helper_routes/com_js_widget.rb +8 -0
  154. data/lib/fanforce/plugin_factory/sinatra/helper_routes/plugin.rb +50 -0
  155. data/lib/fanforce/plugin_factory/sinatra/helpers/assets.rb +23 -0
  156. data/lib/fanforce/plugin_factory/sinatra/helpers/css_frameworks.rb +70 -0
  157. data/lib/fanforce/plugin_factory/sinatra/helpers/fanforce.rb +18 -0
  158. data/lib/fanforce/plugin_factory/{config → sinatra}/helpers/json.rb +2 -2
  159. data/lib/fanforce/plugin_factory/sinatra/helpers/ractive.rb +45 -0
  160. data/lib/fanforce/plugin_factory/sprockets/compiler.rb +5 -11
  161. data/lib/fanforce/plugin_factory/sprockets/hacks.rb +2 -2
  162. data/lib/fanforce/plugin_factory/version.rb +2 -2
  163. metadata +201 -195
  164. data/.rbenv-gemsets +0 -1
  165. data/.rbenv-version +0 -1
  166. data/lib/fanforce/plugin_factory.rake +0 -72
  167. data/lib/fanforce/plugin_factory/_init_sinatra.rb +0 -54
  168. data/lib/fanforce/plugin_factory/assets/css/add_edit_initiative.scss +0 -1
  169. data/lib/fanforce/plugin_factory/assets/css/add_source.scss +0 -1
  170. data/lib/fanforce/plugin_factory/assets/css/convert_pending_initiative.scss +0 -1
  171. data/lib/fanforce/plugin_factory/assets/css/engage.scss +0 -1
  172. data/lib/fanforce/plugin_factory/assets/css/new_message.scss +0 -1
  173. data/lib/fanforce/plugin_factory/assets/css/promotional.scss +0 -1
  174. data/lib/fanforce/plugin_factory/assets/css/source_details.scss +0 -1
  175. data/lib/fanforce/plugin_factory/assets/js/add_edit_initiative.js +0 -1
  176. data/lib/fanforce/plugin_factory/assets/js/add_source.js +0 -1
  177. data/lib/fanforce/plugin_factory/assets/js/convert_pending_initiative.js +0 -1
  178. data/lib/fanforce/plugin_factory/assets/js/engage.js +0 -1
  179. data/lib/fanforce/plugin_factory/assets/js/new_message.js +0 -1
  180. data/lib/fanforce/plugin_factory/assets/js/promotional.js +0 -2
  181. data/lib/fanforce/plugin_factory/assets/js/source_details.js +0 -0
  182. data/lib/fanforce/plugin_factory/assets/lib/common/_module-error.scss +0 -11
  183. data/lib/fanforce/plugin_factory/assets/lib/common/_module-page-loading.scss +0 -1
  184. data/lib/fanforce/plugin_factory/assets/lib/common/_module-saving-initiative.scss +0 -6
  185. data/lib/fanforce/plugin_factory/assets/lib/common/_tags.scss +0 -1
  186. data/lib/fanforce/plugin_factory/assets/lib/common/_variables.scss +0 -27
  187. data/lib/fanforce/plugin_factory/assets/lib/common/broadcaster-divider-arrow.png +0 -0
  188. data/lib/fanforce/plugin_factory/assets/lib/common/icons/dropdown-arrow.png +0 -0
  189. data/lib/fanforce/plugin_factory/assets/lib/common/icons/initiative.png +0 -0
  190. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_add_edit_initiative.scss +0 -27
  191. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_add_source.scss +0 -18
  192. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_convert_pending_initiative.scss +0 -27
  193. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_engage.scss +0 -78
  194. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_new_message.scss +0 -24
  195. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_promotional.scss +0 -27
  196. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/_source_details.scss +0 -17
  197. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/add_edit_initiative.js +0 -6
  198. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/add_source.js +0 -6
  199. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/convert_pending_initiative.js +0 -6
  200. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/engage.js +0 -0
  201. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/new_message.js +0 -5
  202. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/promotional.js +0 -1
  203. data/lib/fanforce/plugin_factory/assets/lib/common/layouts/source_details.js +0 -5
  204. data/lib/fanforce/plugin_factory/assets/lib/promotional/icon-behavior.png +0 -0
  205. data/lib/fanforce/plugin_factory/assets/lib/promotional/icon-broadcaster.png +0 -0
  206. data/lib/fanforce/plugin_factory/assets/lib/promotional/icon-data-connector.png +0 -0
  207. data/lib/fanforce/plugin_factory/assets/lib/promotional/icon-data-processor.png +0 -0
  208. data/lib/fanforce/plugin_factory/assets/lib/promotional/icon-identifier.png +0 -0
  209. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap-datepicker/datepicker.css +0 -7
  210. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap-datepicker/datepicker.js +0 -454
  211. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap-timepicker/timepicker.css +0 -82
  212. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap-timepicker/timepicker.js +0 -803
  213. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap/css/bootstrap.min.css +0 -7
  214. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap/img/glyphicons-halflings-regular.eot +0 -0
  215. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap/img/glyphicons-halflings-regular.svg +0 -0
  216. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap/img/glyphicons-halflings-regular.ttf +0 -0
  217. data/lib/fanforce/plugin_factory/assets/lib/vendors/bootstrap/img/glyphicons-halflings-regular.woff +0 -0
  218. data/lib/fanforce/plugin_factory/assets/lib/vendors/chosen/_chosen_override.scss +0 -6
  219. data/lib/fanforce/plugin_factory/assets/lib/vendors/chosen/chosen-sprite.png +0 -0
  220. data/lib/fanforce/plugin_factory/assets/lib/vendors/chosen/chosen-sprite@2x.png +0 -0
  221. data/lib/fanforce/plugin_factory/assets/lib/vendors/chosen/chosen.jquery.js +0 -1166
  222. data/lib/fanforce/plugin_factory/assets/lib/vendors/chosen/chosen.scss +0 -434
  223. data/lib/fanforce/plugin_factory/assets/lib/vendors/jquery/jquery-1.10.2.js +0 -9789
  224. data/lib/fanforce/plugin_factory/assets/lib/vendors/jquery/jquery.inputHint.js +0 -154
  225. data/lib/fanforce/plugin_factory/assets/lib/vendors/jquery/jquery.tmpl.debug.js +0 -484
  226. data/lib/fanforce/plugin_factory/assets/lib/vendors/knockout/knockout.custom-handlers.coffee +0 -155
  227. data/lib/fanforce/plugin_factory/assets/lib/vendors/knockout/knockout.debug.js +0 -4469
  228. data/lib/fanforce/plugin_factory/assets/lib/vendors/knockout/knockout.min.js +0 -96
  229. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/_select2_override.scss +0 -47
  230. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/select2-spinner.gif +0 -0
  231. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/select2.png +0 -0
  232. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/select2.scss +0 -617
  233. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/select2_modified.js +0 -3225
  234. data/lib/fanforce/plugin_factory/assets/lib/vendors/select2/select2x2.png +0 -0
  235. data/lib/fanforce/plugin_factory/assets/lib/vendors/underscore/underscore.debug.js +0 -999
  236. data/lib/fanforce/plugin_factory/config/_error_handling.rb +0 -27
  237. data/lib/fanforce/plugin_factory/config/core_config.rb +0 -92
  238. data/lib/fanforce/plugin_factory/config/helpers/assets.rb +0 -72
  239. data/lib/fanforce/plugin_factory/config/helpers/fanforce.rb +0 -19
  240. data/lib/fanforce/plugin_factory/layouts/add_edit_initiative.haml +0 -19
  241. data/lib/fanforce/plugin_factory/layouts/add_source.haml +0 -19
  242. data/lib/fanforce/plugin_factory/layouts/convert_pending_initiative.haml +0 -19
  243. data/lib/fanforce/plugin_factory/layouts/new_message.haml +0 -19
  244. data/lib/fanforce/plugin_factory/layouts/source_details.haml +0 -19
  245. data/lib/fanforce/plugin_factory/public/robots.txt +0 -2
  246. data/lib/fanforce/plugin_factory/routes.rb +0 -48
  247. data/lib/fanforce/plugin_factory/routes_behavior.rb +0 -34
  248. data/lib/fanforce/plugin_factory/routes_broadcaster.rb +0 -9
  249. data/lib/fanforce/plugin_factory/routes_data_connector.rb +0 -21
  250. data/lib/fanforce/plugin_factory/routes_identifier.rb +0 -3
  251. data/lib/fanforce/plugin_factory/views/add_initiative.haml +0 -1
  252. data/lib/fanforce/plugin_factory/views/add_source.haml +0 -1
  253. data/lib/fanforce/plugin_factory/views/close_popup.haml +0 -8
  254. data/lib/fanforce/plugin_factory/views/convert_pending_initiative.haml +0 -1
  255. data/lib/fanforce/plugin_factory/views/edit_initiative.haml +0 -1
  256. data/lib/fanforce/plugin_factory/views/engage.haml +0 -1
  257. data/lib/fanforce/plugin_factory/views/new_message.haml +0 -1
  258. data/lib/fanforce/plugin_factory/views/source_details.haml +0 -1
  259. data/lib/fanforce/plugin_factory/views/widget_tmpls.haml +0 -1
  260. data/lib/fanforce/plugin_factory_workers.rb +0 -2
@@ -0,0 +1,77 @@
1
+ require 'bitbucket_rest_api'
2
+ require 'rest_client'
3
+ require 'open3'
4
+
5
+ class Fanforce::PluginFactory::CLI::Bitbucket
6
+ include Fanforce::PluginFactory::CLI::Utils
7
+
8
+ attr_reader :plugin
9
+
10
+ def initialize(plugin)
11
+ @plugin = plugin
12
+ end
13
+
14
+ def bitbucket
15
+ @@bitbucket = ::BitBucket.new(login: config[:bitbucket][:user], password: config[:bitbucket][:password])
16
+ end
17
+
18
+ def create
19
+ repo_name = "plugin-#{plugin.dir_name}"
20
+ error "Bitbucket repo already exists (#{repo_name})" if find_repo(repo_name)
21
+ create_repo(repo_name)
22
+ puts "#{'Created '.format(:green,:bold)}" + "#{repo_name} repository on bitbucket"
23
+ end
24
+
25
+ def setup
26
+ repo_name = "plugin-#{plugin.dir_name}"
27
+ error "Bitbucket repo does not exist (#{repo_name})" if !find_repo(repo_name)
28
+ "#{'Found '.format(:green,:bold)}" + "#{repo_name} repository already exists on bitbucket"
29
+ setup_git_remote(repo_name)
30
+ end
31
+
32
+ def destroy
33
+ repo_name = "plugin-#{plugin.dir_name}"
34
+ if find_repo(repo_name)
35
+ RestClient::Request.execute(:method => :delete, :url => "https://#{config[:bitbucket][:user]}:#{config[:bitbucket][:password]}@api.bitbucket.org/1.0/repositories/#{config[:bitbucket][:user]}/#{repo_name}", :ssl_version => 'SSLv23')
36
+ puts "#{'Removed'.format(:green,:bold)}" + " #{repo_name}"
37
+ else
38
+ puts "#{'Already Removed'.format(:green,:bold)}" + " #{repo_name}"
39
+ end
40
+ end
41
+
42
+ def find_repo(repo_name)
43
+ bitbucket.repos.find(config[:bitbucket][:user], repo_name)
44
+ rescue
45
+ return nil
46
+ end
47
+
48
+ def setup_git_remote(repo_name)
49
+ Dir.chdir(plugin.dir) do
50
+ if console_command('git remote').split(/\r?\n/).include?('bitbucket')
51
+ log "#{'Found '.format(:green,:bold)}" + "git remote for bitbucket (#{config[:bitbucket][:user]})"
52
+ else
53
+ console_command("git remote add bitbucket git@bitbucket.org:#{config[:bitbucket][:user]}/#{repo_name}.git")
54
+ console_command('git fetch bitbucket')
55
+ log "#{'Created '.format(:green,:bold)}" + "git remote for bitbucket (#{config[:bitbucket][:user]})"
56
+ end
57
+
58
+ upstream_error = Open3.popen3('git rev-parse --abbrev-ref master@{upstream}')[2].gets.to_s
59
+ if upstream_error.include?('fatal')
60
+ console_command('git branch -u bitbucket/master')
61
+ log "#{'Connected '.format(:green,:bold)}" + 'upstream to bitbucket/master'
62
+ else
63
+ log "#{'Found '.format(:green,:bold)}" + 'upstream connection to bitbucket/master'
64
+ end
65
+
66
+ log "#{'Pushing '.format(:green,:bold)}" + 'latest commit to bitbucket/master...'
67
+ console_command('git push bitbucket --all', true)
68
+ end
69
+ end
70
+
71
+ def create_repo(repo_name)
72
+ bitbucket.repos.create(name: repo_name, is_private: true)
73
+ rescue ::BitBucket::Error::Unauthorized => e
74
+ raise "Bitbucket user #{config[:bitbucket][:user]} does not seem to exist: #{e.message}"
75
+ end
76
+
77
+ end
@@ -0,0 +1,21 @@
1
+ class Fanforce::PluginFactory::CLI::Bundler
2
+ include Fanforce::PluginFactory::CLI::Utils
3
+
4
+ attr_reader :plugin
5
+
6
+ def initialize(plugin)
7
+ @plugin = plugin
8
+ end
9
+
10
+ def setup
11
+ if Gem::Specification::find_all_by_name('bundler').empty?
12
+ puts 'Installing Bundler... '
13
+ `gem install bundler`
14
+ puts 'DONE'
15
+ end
16
+
17
+ console_command('bundle', true)
18
+ puts 'DONE'.format(:green)
19
+ end
20
+
21
+ end
@@ -0,0 +1,96 @@
1
+ require 'yaml'
2
+
3
+ class Fanforce::PluginFactory::CLI::Env
4
+ include Fanforce::PluginFactory::CLI::Utils
5
+
6
+ attr_reader :plugin
7
+
8
+ def initialize(plugin)
9
+ @plugin = plugin
10
+ end
11
+
12
+ def setup(environment)
13
+ environment = environment.to_sym
14
+ bind_path = "#{plugin.dir}/../.env/_bind.yml"
15
+ error 'You must setup .env/_bind.yml before updating env variables.' if !File.exists?(bind_path)
16
+
17
+ vars = vars(environment)
18
+ has_workers = File.directory?("#{plugin.dir}/workers") ? true : false
19
+ return log "#{'Skipped'.format(:bold)} #{environment.to_s.titleize} has 0 env variables" if vars.blank? or vars.size == 0
20
+
21
+ push_to(environment, vars)
22
+ log "#{'Updated'.format(:green,:bold)} #{environment.to_s.titleize}#{has_workers ? '... and workers have' : ' has'} #{vars.size} env variables"
23
+ end
24
+
25
+ def push_to(environment, vars, create_worker_env=true)
26
+ environment = environment.to_sym
27
+ vars.each {|k,v| puts " - #{k}" }
28
+ workers_dir = "#{plugin.dir}/workers"
29
+ workers_env_dir = "#{workers_dir}/.env"
30
+ if create_worker_env and File.directory?(workers_dir) and vars['IRON_PROJECT_ID']
31
+ FileUtils.mkdir_p(workers_env_dir) unless File.directory?(workers_env_dir)
32
+ File.open("#{workers_env_dir}/#{environment}.rb", 'w') {|f| f.write convert_hash_to_ruby_env(vars) }
33
+ end
34
+ if environment == :development
35
+ update_powenv
36
+ File.open("#{plugin.dir}/.pluginenv", 'w') {|f| f.write convert_hash_to_shell_env(vars) }
37
+ else
38
+ error 'could not find heroku in .fanforce-plugin-factory' if config[:heroku][environment].blank?
39
+ Fanforce::PluginFactory::CLI::Heroku.new(plugin).update_config(environment, vars)
40
+ end
41
+ end
42
+
43
+ def convert_hash_to_shell_env(hash)
44
+ hash.inject('') {|script, (k,v)| script += "export #{k}=#{v.to_s.to_json}\n" }
45
+ end
46
+
47
+ def convert_hash_to_ruby_env(hash)
48
+ hash.inject('') {|script, (k,v)| script += "ENV['#{k}']=#{v.to_s.to_json}\n" }
49
+ end
50
+
51
+ def load_vars(environment)
52
+ environment = environment.to_sym
53
+ vars = {'FANFORCE_PLUGIN_ID' => plugin._id}
54
+ raw_yaml = File.read("#{plugin.dir}/../.env/_bind.yml")
55
+ bindings = (raw_yaml.present?) ? YAML.load(raw_yaml) : {}
56
+ bindings.each do |filename, dir_names|
57
+ file = YAML.load_file("#{plugin.dir}/../.env/#{filename}.yml").symbolize_keys
58
+ next if file[environment].blank?
59
+
60
+ dir_names = [plugin.dir_name] if dir_names.is_a?(String) and dir_names.upcase == 'ALL'
61
+ file[environment].each do |k,v|
62
+ dir_names.each {|dir_name| vars["#{filename}_#{k}".upcase] = v if dir_name == plugin.dir_name }
63
+ end
64
+ end
65
+ return vars
66
+ end
67
+
68
+ def vars(environment)
69
+ @vars ||= {}
70
+ @vars[environment] ||= load_vars(environment)
71
+ end
72
+
73
+ # .POWENV #######################################################################
74
+
75
+ def create_powenv
76
+ file = powenv_lines.join("\n") + "\n"
77
+ File.open("#{plugin.dir}/.powenv", 'w') {|f| f.write file }
78
+ end
79
+
80
+ def update_powenv
81
+ return create_powenv if !File.exists?("#{plugin.dir}/.powenv")
82
+
83
+ lines = File.open("#{plugin.dir}/.powenv", 'r') {|f| f.readlines}.map {|l| l.strip }
84
+
85
+ powenv_lines.each do |line|
86
+ lines << line if !lines.include?(line)
87
+ end
88
+
89
+ File.open("#{plugin.dir}/.powenv", 'w') {|f| f.write(lines.join "\n") }
90
+ end
91
+
92
+ def powenv_lines
93
+ ['source .pluginenv']
94
+ end
95
+
96
+ end
@@ -0,0 +1,59 @@
1
+ class Fanforce::PluginFactory::CLI::Git
2
+ include Fanforce::PluginFactory::CLI::Utils
3
+
4
+ attr_reader :plugin
5
+
6
+ def initialize(plugin)
7
+ @plugin = plugin
8
+ end
9
+
10
+ def setup
11
+ if init.include?('Reinitialized')
12
+ puts "#{'Found '.format(:green,:bold)}" + 'existing local repository'
13
+ else
14
+ puts "#{'Initialized '.format(:green,:bold)}" + 'local repository'
15
+ add_files and log '- git add .'
16
+ make_first_commit and log '- git commit -m "initial fanforce commit"'
17
+ puts "#{'Created '.format(:green,:bold)}" + 'initial fanforce commit'
18
+ end
19
+ end
20
+
21
+ def self.status_table_header(plugin_column_width)
22
+ sprintf('%-12s %-50s %85s', 'GIT STATUS', 'PLUGIN NAME', 'STATS OVERVIEW').format(:bold)
23
+ end
24
+
25
+ def status_row(plugin_column_width)
26
+ sprintf("%s%-12s#{fmt_end} %-50s %28s %28s %28s",
27
+ fmt_start(is_committed ? :green : :red),
28
+ (is_committed ? 'Committed' : 'Uncommitted'),
29
+ plugin.name,
30
+ *changed_stats
31
+ )
32
+ end
33
+
34
+ def is_committed
35
+ `git status`.include?('nothing to commit') ? true : false
36
+ end
37
+
38
+ def changed_stats
39
+ stats_line = `git diff --stat`.split("\n").last
40
+ stats_line ? stats_line.split(', ') : Array.new(3)
41
+ end
42
+
43
+ private
44
+
45
+ def init
46
+ response = `git init`
47
+ `git config core.fileMode false`
48
+ return response
49
+ end
50
+
51
+ def add_files
52
+ `git add .`
53
+ end
54
+
55
+ def make_first_commit
56
+ `git commit -m "initial fanforce commit"`
57
+ end
58
+
59
+ end
@@ -0,0 +1,94 @@
1
+ class Fanforce::PluginFactory::CLI::Heroku
2
+ include Fanforce::PluginFactory::CLI::Utils
3
+
4
+ attr_reader :plugin
5
+
6
+ require_gem 'heroku-api', 'heroku-api'
7
+
8
+ def initialize(plugin)
9
+ @plugin = plugin
10
+ end
11
+
12
+ def heroku(environment)
13
+ @heroku ||= {}
14
+ @heroku[environment] ||= Heroku::API.new(:username => config[:heroku][environment][:user], :password => config[:heroku][environment][:password])
15
+ rescue Exception => e
16
+ error "OOPS... #{environment.to_s.upcase}".format(:red,:bold) + ' has not been setup for Heroku' if config[:heroku].blank? or config[:heroku][environment].blank?
17
+ #raise "Heroku user #{config[:heroku][environment][:user]} does not seem to exist: #{e.message}" if e.response.status == 404
18
+ raise
19
+ end
20
+
21
+ def setup(environment)
22
+ environment = environment.to_sym
23
+ heroku = heroku(environment)
24
+ heroku_app_name = heroku_app_name_by_env(environment)
25
+
26
+ # Setup standard plugin domain
27
+ domain = "#{plugin._id}.#{Fanforce::Base::DomainEnvironments.method(environment).call[:plugins_base]}"
28
+ domain_found = heroku.get_domains(heroku_app_name).body.inject(false) {|result, d| d['domain'] == domain ? (break true) : false }
29
+ if domain_found
30
+ puts "#{'Found '.format(:green,:bold)}" + "#{domain} domain on #{environment}"
31
+ else
32
+ heroku.post_domain(heroku_app_name, domain)
33
+ puts "#{'Added '.format(:green,:bold)}" + "#{domain} domain to #{environment}"
34
+ end
35
+
36
+ # Setup default short domain
37
+ domain = "#{plugin._id}.#{Fanforce::Base::DomainEnvironments.method(environment).call[:default_short_domain]}"
38
+ domain_found = heroku.get_domains(heroku_app_name).body.inject(false) {|result, d| d['domain'] == domain ? (break true) : false }
39
+ if domain_found
40
+ puts "#{'Found '.format(:green,:bold)}" + "#{domain} domain on #{environment}"
41
+ else
42
+ heroku.post_domain(heroku_app_name, domain)
43
+ puts "#{'Added '.format(:green,:bold)}" + "#{domain} domain to #{environment}"
44
+ end
45
+
46
+ # Setup git remote
47
+ remote_name = "#{env(environment)}-heroku"
48
+ if (`git remote`).split(/\r?\n/).include?(remote_name)
49
+ puts "#{'Updated '.format(:green,:bold)}" + "git remote for #{remote_name}"
50
+ `git remote rm #{remote_name}`
51
+ else
52
+ puts "#{'Created '.format(:green,:bold)}" + "git remote for #{remote_name}"
53
+ end
54
+ `git remote add #{remote_name} git@#{config[:heroku][environment][:git_ssh_domain] || 'heroku.com'}:#{heroku_app_name}.git`
55
+ end
56
+
57
+ def heroku_app_exists?(heroku, heroku_app_name)
58
+ heroku.get_app(heroku_app_name)
59
+ return true
60
+ rescue
61
+ return false
62
+ end
63
+
64
+ def ensure_heroku_app_exists(environment)
65
+ heroku = heroku(environment)
66
+ heroku_app_name = heroku_app_name_by_env(environment)
67
+ if heroku_app_exists?(heroku, heroku_app_name)
68
+ puts "#{'Found '.format(:green,:bold)}" + "#{environment} plugin on heroku (#{heroku_app_name})"
69
+ else
70
+ heroku.post_app(name: heroku_app_name)
71
+ puts "#{'Created '.format(:green,:bold)}" + "#{environment} on heroku (#{heroku_app_name})"
72
+ end
73
+ end
74
+
75
+ def update_config(environment, vars)
76
+ heroku(environment).put_config_vars(heroku_app_name_by_env(environment), vars) if vars
77
+ end
78
+
79
+ def env(environment)
80
+ case environment
81
+ when :staging then env = :stg
82
+ when :production then env = :prd
83
+ end
84
+ end
85
+
86
+ def heroku_app_name_by_env(environment)
87
+ environment = environment.to_sym
88
+ raise 'unknown environment' if ![:production, :staging].include?(environment)
89
+
90
+ heroku_app_name = "#{env(environment)}-#{plugin.dir_name}"
91
+ heroku_app_name.length > 30 ? heroku_app_name.gsub!(/(a|e|i|o|u)/, '') : heroku_app_name
92
+ end
93
+
94
+ end
@@ -0,0 +1,71 @@
1
+ class Fanforce::PluginFactory::CLI::Iron
2
+ include Fanforce::PluginFactory::CLI::Utils
3
+
4
+ require_gem 'iron_worker_ng', 'iron_worker_ng'
5
+
6
+ attr_reader :plugin
7
+
8
+ def initialize(plugin)
9
+ @plugin = plugin
10
+ end
11
+
12
+ def upload(environment, worker_filename=nil)
13
+ if !File.directory?("#{plugin.dir}/workers")
14
+ return log "#{'Skipped '.format(:bold)} no workers folder was found"
15
+ end
16
+
17
+ env = Fanforce::PluginFactory::CLI::Env.new(plugin)
18
+ vars = env.vars(environment) || {}
19
+ factory_version = current_factory_version
20
+
21
+ return puts "#{'Skipped '.format(:bold)} #{environment.to_s.titleize} is missing IRON_TOKEN and/or IRON_PROJECT_ID env variables" if vars['IRON_TOKEN'].blank? or vars['IRON_PROJECT_ID'].blank?
22
+
23
+ puts "#{'Updating Env'.format(:green,:bold)} #{environment.to_s.titleize}... and workers have #{vars.size} env variables"
24
+ env.push_to(environment, vars, true)
25
+
26
+ iron_worker = IronWorkerNG::Client.new(:token => vars['IRON_TOKEN'], :project_id => vars['IRON_PROJECT_ID'])
27
+ Dir.chdir("#{plugin.dir}/workers") do
28
+ workers = Dir['*.worker']
29
+ return puts "#{'Skipped '.format(:bold)} #{environment.to_s.titleize} has 0 workers" if workers.size == 0
30
+
31
+ upload_processes = []
32
+ FileUtils.cp("#{plugin.dir}/workers/.env/#{environment}.rb", "#{plugin.dir}/workers/.env/.#{environment}env.rb")
33
+ workers.each do |filename|
34
+ next if worker_filename and !filename.include?(worker_filename)
35
+ code_name = filename.gsub('.worker', '')
36
+
37
+ puts "#{'Uploading'.format(:green,:bold)} #{filename.gsub('.worker', '')} to #{environment.to_s.titleize}..."
38
+ code = IronWorkerNG::Code::Base.new(:workerfile => "#{plugin.dir}/workers/#{filename}")
39
+ code.gem('fanforce-plugin-factory', factory_version)
40
+ code.remote
41
+ code.name = code_name
42
+ code.file("#{plugin.dir}/workers/.env/.#{environment}env.rb")
43
+
44
+ upload_processes << upload_iron_worker(iron_worker, code, filename, environment)
45
+ end
46
+ upload_processes.each { |pid| Process.waitpid(pid) }
47
+ FileUtils.remove_file("#{plugin.dir}/workers/.env/.#{environment}env.rb")
48
+ end
49
+ end
50
+
51
+ def current_factory_version
52
+ `bundle list`.lines.each do |line|
53
+ return $1 if line =~ /fanforce-plugin-factory \(([A-Za-z0-9.-]+)\)/
54
+ end
55
+ error 'fanforce-plugin-factory version was not found in `bundle list`'
56
+ end
57
+
58
+ def upload_iron_worker(iron_worker, code, filename, environment)
59
+ fork do
60
+ begin
61
+ iron_worker.codes.create(code, max_concurrency: 5)
62
+ rescue Exception => e
63
+ puts "#{'Aborted '.format(:red,:bold)} upload of #{filename.gsub('.worker', '')} to #{environment.to_s.titleize}..."
64
+ puts e.message
65
+ puts e.backtrace
66
+ puts ''
67
+ end
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,46 @@
1
+ class Fanforce::PluginFactory::CLI::Pow
2
+ include Fanforce::PluginFactory::CLI::Utils
3
+
4
+ attr_reader :plugin
5
+
6
+ def initialize(plugin)
7
+ @plugin = plugin
8
+ end
9
+
10
+ def setup
11
+ create_domain(plugin.root_domain)
12
+ create_domain(Fanforce.default_short_domain)
13
+ end
14
+
15
+ def destroy
16
+ destroy_domain(plugin.root_domain)
17
+ destroy_domain(Fanforce.default_short_domain)
18
+ end
19
+
20
+ def remove_domain_extension(domain)
21
+ domain.gsub(/\.[a-z]+$/, '')
22
+ end
23
+
24
+ def create_domain(root_domain)
25
+ domain = "#{plugin._id}.#{root_domain.gsub(/\.([a-z]+)$/, '')}"
26
+ domain_extension = $1
27
+ symlink = "#{ENV['HOME']}/.pow/#{domain}"
28
+
29
+ File.delete(symlink) if File.exists?(symlink) or File.symlink?(symlink)
30
+ `ln -s #{plugin.dir} #{symlink}`
31
+ puts "#{'Connected'.format(:bold,:green)} #{domain}.#{domain_extension} to #{plugin.dir}/"
32
+ end
33
+
34
+ def destroy_domain(root_domain)
35
+ domain = "#{plugin._id}.#{root_domain.gsub(/\.([a-z]+)$/, '')}"
36
+ domain_extension = $1
37
+ symlink = "#{ENV['HOME']}/.pow/#{domain}"
38
+ if File.exists?(symlink)
39
+ File.delete(symlink)
40
+ puts "#{'Removed'.format(:bold,:green)} #{domain}.#{domain_extension}"
41
+ else
42
+ puts "#{'Already Removed'.format(:bold,:green)} #{domain}.#{domain_extension} to #{plugin.dir}/"
43
+ end
44
+ end
45
+
46
+ end