comfy_middle_seat 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 (436) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +4 -0
  3. data/.gitattributes +3 -0
  4. data/.github/dependabot.yml +7 -0
  5. data/.github/issue_template.md +19 -0
  6. data/.github/pull_request_template.md +6 -0
  7. data/.github/workflows/claude-code-review.yml +46 -0
  8. data/.github/workflows/claude.yml +148 -0
  9. data/.github/workflows/coveralls.yml +53 -0
  10. data/.github/workflows/rubyonrails.yml +94 -0
  11. data/.gitignore +25 -0
  12. data/.rubocop.yml +82 -0
  13. data/.travis.yml +44 -0
  14. data/CHANGELOG.md +147 -0
  15. data/CONTRIBUTING.md +42 -0
  16. data/Gemfile +44 -0
  17. data/LICENSE +20 -0
  18. data/README.md +158 -0
  19. data/Rakefile +206 -0
  20. data/app/assets/builds/.keep +0 -0
  21. data/app/assets/config/manifest.js +1 -0
  22. data/app/assets/fonts/comfy/admin/cms/lib/redactor-font.eot +0 -0
  23. data/app/assets/javascripts/comfy/admin/cms/application.js +27 -0
  24. data/app/assets/javascripts/comfy/admin/cms/base.js +48 -0
  25. data/app/assets/javascripts/comfy/admin/cms/categories.js +17 -0
  26. data/app/assets/javascripts/comfy/admin/cms/codemirror.js +43 -0
  27. data/app/assets/javascripts/comfy/admin/cms/custom.js +1 -0
  28. data/app/assets/javascripts/comfy/admin/cms/diff.js +12 -0
  29. data/app/assets/javascripts/comfy/admin/cms/file_link.js +96 -0
  30. data/app/assets/javascripts/comfy/admin/cms/file_upload.js +229 -0
  31. data/app/assets/javascripts/comfy/admin/cms/files_modal.js +97 -0
  32. data/app/assets/javascripts/comfy/admin/cms/page_fragments.js +22 -0
  33. data/app/assets/javascripts/comfy/admin/cms/slugify.js +34 -0
  34. data/app/assets/javascripts/comfy/admin/cms/sortable_list.js +49 -0
  35. data/app/assets/javascripts/comfy/admin/cms/timepicker.js +38 -0
  36. data/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +91 -0
  37. data/app/assets/javascripts/comfy/vendor/diff/diff_match_patch.min.js +49 -0
  38. data/app/assets/javascripts/comfy/vendor/diff/pretty_text_diff.js +88 -0
  39. data/app/assets/javascripts/comfy/vendor/flatpickr.min.js +2 -0
  40. data/app/assets/javascripts/comfy/vendor/fontawesome.js +5 -0
  41. data/app/assets/javascripts/comfy/vendor/redactor/definedlinks.js +50 -0
  42. data/app/assets/javascripts/comfy/vendor/redactor/filemanager.js +79 -0
  43. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ar.js +76 -0
  44. data/app/assets/javascripts/comfy/vendor/redactor/i18n/az.js +75 -0
  45. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ba.js +79 -0
  46. data/app/assets/javascripts/comfy/vendor/redactor/i18n/bg.js +77 -0
  47. data/app/assets/javascripts/comfy/vendor/redactor/i18n/by.js +77 -0
  48. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ca.js +75 -0
  49. data/app/assets/javascripts/comfy/vendor/redactor/i18n/cs.js +87 -0
  50. data/app/assets/javascripts/comfy/vendor/redactor/i18n/da.js +75 -0
  51. data/app/assets/javascripts/comfy/vendor/redactor/i18n/de.js +80 -0
  52. data/app/assets/javascripts/comfy/vendor/redactor/i18n/el.js +76 -0
  53. data/app/assets/javascripts/comfy/vendor/redactor/i18n/en.js +75 -0
  54. data/app/assets/javascripts/comfy/vendor/redactor/i18n/eo.js +76 -0
  55. data/app/assets/javascripts/comfy/vendor/redactor/i18n/es.js +75 -0
  56. data/app/assets/javascripts/comfy/vendor/redactor/i18n/es_AR.js +76 -0
  57. data/app/assets/javascripts/comfy/vendor/redactor/i18n/fa.js +76 -0
  58. data/app/assets/javascripts/comfy/vendor/redactor/i18n/fi.js +75 -0
  59. data/app/assets/javascripts/comfy/vendor/redactor/i18n/fr.js +75 -0
  60. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ge.js +75 -0
  61. data/app/assets/javascripts/comfy/vendor/redactor/i18n/gr.js +75 -0
  62. data/app/assets/javascripts/comfy/vendor/redactor/i18n/he.js +75 -0
  63. data/app/assets/javascripts/comfy/vendor/redactor/i18n/hr.js +78 -0
  64. data/app/assets/javascripts/comfy/vendor/redactor/i18n/hu.js +77 -0
  65. data/app/assets/javascripts/comfy/vendor/redactor/i18n/id.js +76 -0
  66. data/app/assets/javascripts/comfy/vendor/redactor/i18n/it.js +78 -0
  67. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ja.js +76 -0
  68. data/app/assets/javascripts/comfy/vendor/redactor/i18n/kn.js +75 -0
  69. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ko.js +76 -0
  70. data/app/assets/javascripts/comfy/vendor/redactor/i18n/lt.js +75 -0
  71. data/app/assets/javascripts/comfy/vendor/redactor/i18n/lv.js +75 -0
  72. data/app/assets/javascripts/comfy/vendor/redactor/i18n/mk.js +75 -0
  73. data/app/assets/javascripts/comfy/vendor/redactor/i18n/nb.js +77 -0
  74. data/app/assets/javascripts/comfy/vendor/redactor/i18n/nl.js +80 -0
  75. data/app/assets/javascripts/comfy/vendor/redactor/i18n/pl.js +78 -0
  76. data/app/assets/javascripts/comfy/vendor/redactor/i18n/pt-BR.js +75 -0
  77. data/app/assets/javascripts/comfy/vendor/redactor/i18n/pt.js +75 -0
  78. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ro.js +76 -0
  79. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ru.js +76 -0
  80. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sk.js +76 -0
  81. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sl.js +79 -0
  82. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sq.js +79 -0
  83. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sr-CIR.js +79 -0
  84. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sr-LAT.js +79 -0
  85. data/app/assets/javascripts/comfy/vendor/redactor/i18n/sv.js +74 -0
  86. data/app/assets/javascripts/comfy/vendor/redactor/i18n/th.js +74 -0
  87. data/app/assets/javascripts/comfy/vendor/redactor/i18n/tr.js +75 -0
  88. data/app/assets/javascripts/comfy/vendor/redactor/i18n/ua.js +77 -0
  89. data/app/assets/javascripts/comfy/vendor/redactor/i18n/uk.js +77 -0
  90. data/app/assets/javascripts/comfy/vendor/redactor/i18n/vi.js +74 -0
  91. data/app/assets/javascripts/comfy/vendor/redactor/i18n/zh-CN.js +75 -0
  92. data/app/assets/javascripts/comfy/vendor/redactor/i18n/zh-TW.js +75 -0
  93. data/app/assets/javascripts/comfy/vendor/redactor/imagemanager.js +68 -0
  94. data/app/assets/javascripts/comfy/vendor/redactor/table.js +348 -0
  95. data/app/assets/javascripts/comfy/vendor/redactor/video.js +82 -0
  96. data/app/assets/javascripts/comfy/vendor/redactor.js +9563 -0
  97. data/app/assets/stylesheets/comfy/admin/cms/application.sass +11 -0
  98. data/app/assets/stylesheets/comfy/admin/cms/base.sass +256 -0
  99. data/app/assets/stylesheets/comfy/admin/cms/codemirror_overrides.sass +19 -0
  100. data/app/assets/stylesheets/comfy/admin/cms/custom.sass +1 -0
  101. data/app/assets/stylesheets/comfy/admin/cms/redactor_overrides.sass +22 -0
  102. data/app/assets/stylesheets/comfy/vendor/bootstrap/_alert.scss +51 -0
  103. data/app/assets/stylesheets/comfy/vendor/bootstrap/_badge.scss +54 -0
  104. data/app/assets/stylesheets/comfy/vendor/bootstrap/_breadcrumb.scss +41 -0
  105. data/app/assets/stylesheets/comfy/vendor/bootstrap/_button-group.scss +163 -0
  106. data/app/assets/stylesheets/comfy/vendor/bootstrap/_buttons.scss +137 -0
  107. data/app/assets/stylesheets/comfy/vendor/bootstrap/_card.scss +289 -0
  108. data/app/assets/stylesheets/comfy/vendor/bootstrap/_carousel.scss +197 -0
  109. data/app/assets/stylesheets/comfy/vendor/bootstrap/_close.scss +41 -0
  110. data/app/assets/stylesheets/comfy/vendor/bootstrap/_code.scss +48 -0
  111. data/app/assets/stylesheets/comfy/vendor/bootstrap/_custom-forms.scss +507 -0
  112. data/app/assets/stylesheets/comfy/vendor/bootstrap/_dropdown.scss +191 -0
  113. data/app/assets/stylesheets/comfy/vendor/bootstrap/_forms.scss +330 -0
  114. data/app/assets/stylesheets/comfy/vendor/bootstrap/_functions.scss +86 -0
  115. data/app/assets/stylesheets/comfy/vendor/bootstrap/_grid.scss +52 -0
  116. data/app/assets/stylesheets/comfy/vendor/bootstrap/_images.scss +42 -0
  117. data/app/assets/stylesheets/comfy/vendor/bootstrap/_input-group.scss +193 -0
  118. data/app/assets/stylesheets/comfy/vendor/bootstrap/_jumbotron.scss +17 -0
  119. data/app/assets/stylesheets/comfy/vendor/bootstrap/_list-group.scss +149 -0
  120. data/app/assets/stylesheets/comfy/vendor/bootstrap/_media.scss +8 -0
  121. data/app/assets/stylesheets/comfy/vendor/bootstrap/_mixins.scss +47 -0
  122. data/app/assets/stylesheets/comfy/vendor/bootstrap/_modal.scss +229 -0
  123. data/app/assets/stylesheets/comfy/vendor/bootstrap/_nav.scss +120 -0
  124. data/app/assets/stylesheets/comfy/vendor/bootstrap/_navbar.scss +294 -0
  125. data/app/assets/stylesheets/comfy/vendor/bootstrap/_pagination.scss +73 -0
  126. data/app/assets/stylesheets/comfy/vendor/bootstrap/_popover.scss +171 -0
  127. data/app/assets/stylesheets/comfy/vendor/bootstrap/_print.scss +141 -0
  128. data/app/assets/stylesheets/comfy/vendor/bootstrap/_progress.scss +43 -0
  129. data/app/assets/stylesheets/comfy/vendor/bootstrap/_reboot.scss +483 -0
  130. data/app/assets/stylesheets/comfy/vendor/bootstrap/_root.scss +19 -0
  131. data/app/assets/stylesheets/comfy/vendor/bootstrap/_spinners.scss +55 -0
  132. data/app/assets/stylesheets/comfy/vendor/bootstrap/_tables.scss +185 -0
  133. data/app/assets/stylesheets/comfy/vendor/bootstrap/_toasts.scss +44 -0
  134. data/app/assets/stylesheets/comfy/vendor/bootstrap/_tooltip.scss +115 -0
  135. data/app/assets/stylesheets/comfy/vendor/bootstrap/_transitions.scss +20 -0
  136. data/app/assets/stylesheets/comfy/vendor/bootstrap/_type.scss +125 -0
  137. data/app/assets/stylesheets/comfy/vendor/bootstrap/_utilities.scss +17 -0
  138. data/app/assets/stylesheets/comfy/vendor/bootstrap/_variables.scss +1123 -0
  139. data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap-grid.scss +29 -0
  140. data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap-reboot.scss +12 -0
  141. data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap.scss +44 -0
  142. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_alert.scss +13 -0
  143. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_background-variant.scss +21 -0
  144. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_badge.scss +17 -0
  145. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_border-radius.scss +63 -0
  146. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_box-shadow.scss +20 -0
  147. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_breakpoints.scss +123 -0
  148. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_buttons.scss +107 -0
  149. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_caret.scss +62 -0
  150. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_clearfix.scss +7 -0
  151. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_deprecate.scss +10 -0
  152. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_float.scss +14 -0
  153. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_forms.scss +192 -0
  154. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_gradients.scss +45 -0
  155. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_grid-framework.scss +66 -0
  156. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_grid.scss +51 -0
  157. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_hover.scss +37 -0
  158. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_image.scss +36 -0
  159. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_list-group.scss +21 -0
  160. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_lists.scss +7 -0
  161. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
  162. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_pagination.scss +22 -0
  163. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_reset-text.scss +17 -0
  164. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_resize.scss +6 -0
  165. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_screen-reader.scss +33 -0
  166. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_size.scss +7 -0
  167. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_table-row.scss +39 -0
  168. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-emphasis.scss +16 -0
  169. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-hide.scss +11 -0
  170. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-truncate.scss +8 -0
  171. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_transition.scss +16 -0
  172. data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_visibility.scss +8 -0
  173. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_align.scss +8 -0
  174. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_background.scss +19 -0
  175. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_borders.scss +75 -0
  176. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_clearfix.scss +3 -0
  177. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_display.scss +26 -0
  178. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_embed.scss +39 -0
  179. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_flex.scss +51 -0
  180. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_float.scss +11 -0
  181. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_overflow.scss +5 -0
  182. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_position.scss +32 -0
  183. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_screenreaders.scss +11 -0
  184. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_shadows.scss +6 -0
  185. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_sizing.scss +20 -0
  186. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_spacing.scss +73 -0
  187. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_stretched-link.scss +19 -0
  188. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_text.scss +72 -0
  189. data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_visibility.scss +13 -0
  190. data/app/assets/stylesheets/comfy/vendor/bootstrap/vendor/_rfs.scss +204 -0
  191. data/app/assets/stylesheets/comfy/vendor/fontawesome.css +343 -0
  192. data/app/assets/stylesheets/comfy/vendor/redactor.css +948 -0
  193. data/app/controllers/application_controller.rb +5 -0
  194. data/app/controllers/comfy/admin/base_controller.rb +20 -0
  195. data/app/controllers/comfy/admin/cms/base_controller.rb +54 -0
  196. data/app/controllers/comfy/admin/cms/categories_controller.rb +38 -0
  197. data/app/controllers/comfy/admin/cms/files_controller.rb +140 -0
  198. data/app/controllers/comfy/admin/cms/layouts_controller.rb +69 -0
  199. data/app/controllers/comfy/admin/cms/pages_controller.rb +193 -0
  200. data/app/controllers/comfy/admin/cms/revisions/base_controller.rb +48 -0
  201. data/app/controllers/comfy/admin/cms/revisions/layout_controller.rb +16 -0
  202. data/app/controllers/comfy/admin/cms/revisions/page_controller.rb +28 -0
  203. data/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb +16 -0
  204. data/app/controllers/comfy/admin/cms/revisions/translation_controller.rb +29 -0
  205. data/app/controllers/comfy/admin/cms/sites_controller.rb +68 -0
  206. data/app/controllers/comfy/admin/cms/snippets_controller.rb +66 -0
  207. data/app/controllers/comfy/admin/cms/translations_controller.rb +117 -0
  208. data/app/controllers/comfy/cms/assets_controller.rb +38 -0
  209. data/app/controllers/comfy/cms/base_controller.rb +35 -0
  210. data/app/controllers/comfy/cms/content_controller.rb +90 -0
  211. data/app/controllers/concerns/comfy/paginate.rb +11 -0
  212. data/app/controllers/concerns/comfy/reorder_action.rb +19 -0
  213. data/app/helpers/comfy/admin/cms_helper.rb +50 -0
  214. data/app/helpers/comfy/cms_helper.rb +71 -0
  215. data/app/models/comfy/cms/categorization.rb +23 -0
  216. data/app/models/comfy/cms/category.rb +22 -0
  217. data/app/models/comfy/cms/file.rb +65 -0
  218. data/app/models/comfy/cms/fragment.rb +65 -0
  219. data/app/models/comfy/cms/layout.rb +119 -0
  220. data/app/models/comfy/cms/page.rb +182 -0
  221. data/app/models/comfy/cms/revision.rb +10 -0
  222. data/app/models/comfy/cms/site.rb +93 -0
  223. data/app/models/comfy/cms/snippet.rb +43 -0
  224. data/app/models/comfy/cms/translation.rb +47 -0
  225. data/app/models/concerns/comfy/cms/with_categories.rb +51 -0
  226. data/app/models/concerns/comfy/cms/with_fragments.rb +123 -0
  227. data/app/views/comfy/admin/cms/categories/_categories.html.haml +4 -0
  228. data/app/views/comfy/admin/cms/categories/_edit.html.haml +7 -0
  229. data/app/views/comfy/admin/cms/categories/_form.html.haml +5 -0
  230. data/app/views/comfy/admin/cms/categories/_index.html.haml +28 -0
  231. data/app/views/comfy/admin/cms/categories/_show.html.haml +15 -0
  232. data/app/views/comfy/admin/cms/categories/create.js.erb +7 -0
  233. data/app/views/comfy/admin/cms/categories/destroy.js.erb +8 -0
  234. data/app/views/comfy/admin/cms/categories/edit.js.erb +3 -0
  235. data/app/views/comfy/admin/cms/categories/update.js.erb +6 -0
  236. data/app/views/comfy/admin/cms/files/_file.html.haml +31 -0
  237. data/app/views/comfy/admin/cms/files/_form.html.haml +26 -0
  238. data/app/views/comfy/admin/cms/files/_modal.html.haml +3 -0
  239. data/app/views/comfy/admin/cms/files/destroy.js.erb +4 -0
  240. data/app/views/comfy/admin/cms/files/edit.html.haml +5 -0
  241. data/app/views/comfy/admin/cms/files/index.html.haml +31 -0
  242. data/app/views/comfy/admin/cms/files/new.html.haml +5 -0
  243. data/app/views/comfy/admin/cms/fragments/_form_fragment_attachments.html.haml +23 -0
  244. data/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml +38 -0
  245. data/app/views/comfy/admin/cms/layouts/_form.html.haml +20 -0
  246. data/app/views/comfy/admin/cms/layouts/_index_branch.html.haml +26 -0
  247. data/app/views/comfy/admin/cms/layouts/edit.html.haml +9 -0
  248. data/app/views/comfy/admin/cms/layouts/index.html.haml +10 -0
  249. data/app/views/comfy/admin/cms/layouts/new.html.haml +5 -0
  250. data/app/views/comfy/admin/cms/pages/_form.html.haml +31 -0
  251. data/app/views/comfy/admin/cms/pages/_index_branch.html.haml +44 -0
  252. data/app/views/comfy/admin/cms/pages/edit.html.haml +14 -0
  253. data/app/views/comfy/admin/cms/pages/index.html.haml +13 -0
  254. data/app/views/comfy/admin/cms/pages/new.html.haml +5 -0
  255. data/app/views/comfy/admin/cms/pages/toggle_branch.js.erb +19 -0
  256. data/app/views/comfy/admin/cms/revisions/_sidebar.html.haml +2 -0
  257. data/app/views/comfy/admin/cms/revisions/show.html.haml +36 -0
  258. data/app/views/comfy/admin/cms/sites/_form.html.haml +15 -0
  259. data/app/views/comfy/admin/cms/sites/edit.html.haml +5 -0
  260. data/app/views/comfy/admin/cms/sites/index.html.haml +28 -0
  261. data/app/views/comfy/admin/cms/sites/new.html.haml +5 -0
  262. data/app/views/comfy/admin/cms/snippets/_form.html.haml +19 -0
  263. data/app/views/comfy/admin/cms/snippets/edit.html.haml +9 -0
  264. data/app/views/comfy/admin/cms/snippets/index.html.haml +33 -0
  265. data/app/views/comfy/admin/cms/snippets/new.html.haml +5 -0
  266. data/app/views/comfy/admin/cms/translations/_form.html.haml +20 -0
  267. data/app/views/comfy/admin/cms/translations/_sidebar.html.haml +19 -0
  268. data/app/views/comfy/admin/cms/translations/edit.html.haml +10 -0
  269. data/app/views/comfy/admin/cms/translations/new.html.haml +5 -0
  270. data/app/views/kaminari/comfy/_first_page.html.haml +3 -0
  271. data/app/views/kaminari/comfy/_gap.html.haml +2 -0
  272. data/app/views/kaminari/comfy/_last_page.html.haml +3 -0
  273. data/app/views/kaminari/comfy/_next_page.html.haml +2 -0
  274. data/app/views/kaminari/comfy/_page.html.haml +2 -0
  275. data/app/views/kaminari/comfy/_paginator.html.haml +11 -0
  276. data/app/views/kaminari/comfy/_prev_page.html.haml +2 -0
  277. data/app/views/layouts/comfy/admin/cms/_body.html.haml +14 -0
  278. data/app/views/layouts/comfy/admin/cms/_flash.html.haml +4 -0
  279. data/app/views/layouts/comfy/admin/cms/_footer_js.html.haml +6 -0
  280. data/app/views/layouts/comfy/admin/cms/_head.html.haml +19 -0
  281. data/app/views/layouts/comfy/admin/cms/_left.html.haml +46 -0
  282. data/app/views/layouts/comfy/admin/cms/_right.html.haml +5 -0
  283. data/app/views/layouts/comfy/admin/cms.html.haml +4 -0
  284. data/bin/bundle +3 -0
  285. data/bin/rails +4 -0
  286. data/bin/rake +4 -0
  287. data/bin/setup +36 -0
  288. data/bin/update +31 -0
  289. data/bin/yarn +11 -0
  290. data/comfy_middle_seat.gemspec +35 -0
  291. data/config/application.rb +62 -0
  292. data/config/boot.rb +5 -0
  293. data/config/cable.yml +10 -0
  294. data/config/cms_routes.rb +8 -0
  295. data/config/database.yml +40 -0
  296. data/config/environment.rb +7 -0
  297. data/config/environments/development.rb +81 -0
  298. data/config/environments/production.rb +93 -0
  299. data/config/environments/test.rb +74 -0
  300. data/config/initializers/comfortable_media_surfer.rb +122 -0
  301. data/config/initializers/content_security_policy.rb +27 -0
  302. data/config/initializers/filter_parameter_logging.rb +10 -0
  303. data/config/initializers/inflections.rb +18 -0
  304. data/config/initializers/json.rb +11 -0
  305. data/config/initializers/new_framework_defaults_7_0.rb +144 -0
  306. data/config/initializers/new_framework_defaults_7_1.rb +225 -0
  307. data/config/initializers/permissions_policy.rb +15 -0
  308. data/config/locales/ar.yml +268 -0
  309. data/config/locales/ca.yml +268 -0
  310. data/config/locales/cs.yml +268 -0
  311. data/config/locales/da.yml +268 -0
  312. data/config/locales/de.yml +268 -0
  313. data/config/locales/en.yml +268 -0
  314. data/config/locales/es.yml +268 -0
  315. data/config/locales/fi.yml +268 -0
  316. data/config/locales/fr.yml +268 -0
  317. data/config/locales/gr.yml +268 -0
  318. data/config/locales/hr.yml +268 -0
  319. data/config/locales/it.yml +268 -0
  320. data/config/locales/ja.yml +268 -0
  321. data/config/locales/nb.yml +268 -0
  322. data/config/locales/nl.yml +268 -0
  323. data/config/locales/pl.yml +268 -0
  324. data/config/locales/pt-BR.yml +268 -0
  325. data/config/locales/ru.yml +268 -0
  326. data/config/locales/sk.yml +268 -0
  327. data/config/locales/sv.yml +268 -0
  328. data/config/locales/tr.yml +268 -0
  329. data/config/locales/uk.yml +268 -0
  330. data/config/locales/zh-CN.yml +268 -0
  331. data/config/locales/zh-TW.yml +268 -0
  332. data/config/puma.rb +43 -0
  333. data/config/storage.yml +35 -0
  334. data/config.ru +6 -0
  335. data/db/cms_seeds/sample-site/files/_default.jpg.yml +5 -0
  336. data/db/cms_seeds/sample-site/files/default.jpg +0 -0
  337. data/db/cms_seeds/sample-site/layouts/default/content.html +16 -0
  338. data/db/cms_seeds/sample-site/layouts/default/nested/content.html +14 -0
  339. data/db/cms_seeds/sample-site/pages/index/child_a/content.html +7 -0
  340. data/db/cms_seeds/sample-site/pages/index/child_b/child_a/content.html +6 -0
  341. data/db/cms_seeds/sample-site/pages/index/child_b/content.html +6 -0
  342. data/db/cms_seeds/sample-site/pages/index/cms logo.png +0 -0
  343. data/db/cms_seeds/sample-site/pages/index/content.es.html +6 -0
  344. data/db/cms_seeds/sample-site/pages/index/content.fr.html +6 -0
  345. data/db/cms_seeds/sample-site/pages/index/content.html +25 -0
  346. data/db/cms_seeds/sample-site/pages/index/footer.png +0 -0
  347. data/db/cms_seeds/sample-site/pages/index/header.png +0 -0
  348. data/db/cms_seeds/sample-site/snippets/default.html +8 -0
  349. data/db/migrate/00_create_active_storage_tables.active_storage.rb +50 -0
  350. data/db/migrate/01_create_cms.rb +142 -0
  351. data/db/migrate/02_add_markdown_to_snippets.rb +5 -0
  352. data/gemfiles/7.2.gemfile +36 -0
  353. data/gemfiles/8.0.gemfile +36 -0
  354. data/gemfiles/8.1.gemfile +36 -0
  355. data/lib/comfortable_media_surfer/access_control/admin_authentication.rb +22 -0
  356. data/lib/comfortable_media_surfer/access_control/admin_authorization.rb +10 -0
  357. data/lib/comfortable_media_surfer/access_control/public_authentication.rb +10 -0
  358. data/lib/comfortable_media_surfer/access_control/public_authorization.rb +10 -0
  359. data/lib/comfortable_media_surfer/configuration.rb +138 -0
  360. data/lib/comfortable_media_surfer/content/block.rb +12 -0
  361. data/lib/comfortable_media_surfer/content/params_parser.rb +149 -0
  362. data/lib/comfortable_media_surfer/content/renderer.rb +146 -0
  363. data/lib/comfortable_media_surfer/content/tag.rb +48 -0
  364. data/lib/comfortable_media_surfer/content/tags/asset.rb +57 -0
  365. data/lib/comfortable_media_surfer/content/tags/audio.rb +39 -0
  366. data/lib/comfortable_media_surfer/content/tags/breadcrumbs.rb +43 -0
  367. data/lib/comfortable_media_surfer/content/tags/checkbox.rb +27 -0
  368. data/lib/comfortable_media_surfer/content/tags/children.rb +52 -0
  369. data/lib/comfortable_media_surfer/content/tags/date.rb +19 -0
  370. data/lib/comfortable_media_surfer/content/tags/datetime.rb +42 -0
  371. data/lib/comfortable_media_surfer/content/tags/file.rb +70 -0
  372. data/lib/comfortable_media_surfer/content/tags/file_link.rb +58 -0
  373. data/lib/comfortable_media_surfer/content/tags/files.rb +41 -0
  374. data/lib/comfortable_media_surfer/content/tags/fragment.rb +64 -0
  375. data/lib/comfortable_media_surfer/content/tags/helper.rb +53 -0
  376. data/lib/comfortable_media_surfer/content/tags/image.rb +56 -0
  377. data/lib/comfortable_media_surfer/content/tags/markdown.rb +22 -0
  378. data/lib/comfortable_media_surfer/content/tags/mixins/file_content.rb +42 -0
  379. data/lib/comfortable_media_surfer/content/tags/number.rb +18 -0
  380. data/lib/comfortable_media_surfer/content/tags/page_file_link.rb +86 -0
  381. data/lib/comfortable_media_surfer/content/tags/partial.rb +47 -0
  382. data/lib/comfortable_media_surfer/content/tags/siblings.rb +66 -0
  383. data/lib/comfortable_media_surfer/content/tags/snippet.rb +36 -0
  384. data/lib/comfortable_media_surfer/content/tags/template.rb +42 -0
  385. data/lib/comfortable_media_surfer/content/tags/text.rb +18 -0
  386. data/lib/comfortable_media_surfer/content/tags/textarea.rb +19 -0
  387. data/lib/comfortable_media_surfer/content/tags/wysiwyg.rb +19 -0
  388. data/lib/comfortable_media_surfer/content/tags.rb +29 -0
  389. data/lib/comfortable_media_surfer/content.rb +11 -0
  390. data/lib/comfortable_media_surfer/engine.rb +24 -0
  391. data/lib/comfortable_media_surfer/error.rb +24 -0
  392. data/lib/comfortable_media_surfer/extensions/acts_as_tree.rb +114 -0
  393. data/lib/comfortable_media_surfer/extensions/has_revisions.rb +68 -0
  394. data/lib/comfortable_media_surfer/extensions.rb +8 -0
  395. data/lib/comfortable_media_surfer/form_builder.rb +43 -0
  396. data/lib/comfortable_media_surfer/render_methods.rb +106 -0
  397. data/lib/comfortable_media_surfer/routing.rb +87 -0
  398. data/lib/comfortable_media_surfer/seeds/file/exporter.rb +37 -0
  399. data/lib/comfortable_media_surfer/seeds/file/importer.rb +55 -0
  400. data/lib/comfortable_media_surfer/seeds/layout/exporter.rb +38 -0
  401. data/lib/comfortable_media_surfer/seeds/layout/importer.rb +60 -0
  402. data/lib/comfortable_media_surfer/seeds/page/exporter.rb +88 -0
  403. data/lib/comfortable_media_surfer/seeds/page/importer.rb +245 -0
  404. data/lib/comfortable_media_surfer/seeds/snippet/exporter.rb +32 -0
  405. data/lib/comfortable_media_surfer/seeds/snippet/importer.rb +47 -0
  406. data/lib/comfortable_media_surfer/seeds.rb +110 -0
  407. data/lib/comfortable_media_surfer/version.rb +3 -0
  408. data/lib/comfortable_media_surfer/view_hooks.rb +33 -0
  409. data/lib/comfortable_media_surfer.rb +56 -0
  410. data/lib/comfy_middle_seat/version.rb +5 -0
  411. data/lib/comfy_middle_seat.rb +3 -0
  412. data/lib/generators/comfy/cms/README +21 -0
  413. data/lib/generators/comfy/cms/assets_generator.rb +16 -0
  414. data/lib/generators/comfy/cms/cms_generator.rb +69 -0
  415. data/lib/generators/comfy/cms/controllers_generator.rb +15 -0
  416. data/lib/generators/comfy/cms/models_generator.rb +15 -0
  417. data/lib/generators/comfy/cms/views_generator.rb +15 -0
  418. data/lib/generators/comfy/scaffold/scaffold_generator.rb +79 -0
  419. data/lib/generators/comfy/scaffold/templates/controller.rb.tt +62 -0
  420. data/lib/generators/comfy/scaffold/templates/migration.rb.tt +11 -0
  421. data/lib/generators/comfy/scaffold/templates/model.rb.tt +21 -0
  422. data/lib/generators/comfy/scaffold/templates/tests/controller.rb.tt +115 -0
  423. data/lib/generators/comfy/scaffold/templates/tests/fixture.yml.tt +4 -0
  424. data/lib/generators/comfy/scaffold/templates/tests/model.rb.tt +26 -0
  425. data/lib/generators/comfy/scaffold/templates/views/_form.haml.tt +7 -0
  426. data/lib/generators/comfy/scaffold/templates/views/edit.haml.tt +5 -0
  427. data/lib/generators/comfy/scaffold/templates/views/index.haml.tt +21 -0
  428. data/lib/generators/comfy/scaffold/templates/views/new.haml.tt +5 -0
  429. data/lib/generators/comfy/scaffold/templates/views/show.haml.tt +4 -0
  430. data/lib/tasks/cms_assets.rake +19 -0
  431. data/lib/tasks/cms_seeds.rake +40 -0
  432. data/package-lock.json +989 -0
  433. data/package.json +23 -0
  434. data/public/favicon.ico +0 -0
  435. data/rakelib/create_release.rake +82 -0
  436. metadata +665 -0
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Comfy::Cms::WithFragments
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attr_accessor :fragments_attributes_changed
8
+
9
+ belongs_to :layout,
10
+ class_name: 'Comfy::Cms::Layout'
11
+
12
+ has_many :fragments,
13
+ class_name: 'Comfy::Cms::Fragment',
14
+ as: :record,
15
+ autosave: true,
16
+ dependent: :destroy
17
+
18
+ before_save :clear_content_cache
19
+
20
+ validates :layout,
21
+ presence: true
22
+ end
23
+
24
+ # Array of fragment hashes in the following format:
25
+ # [
26
+ # {identifier: "frag_a", format: "text", content: "fragment a content"},
27
+ # {identifier: "frag_b", format: "file", files: [{file_a}, {file_b}]}
28
+ # ]
29
+ # It also handles when frag hashes come in as a hash:
30
+ # {
31
+ # "0" => {identifer: "foo", content: "bar"},
32
+ # "1" => {identifier: "bar", content: "foo"}
33
+ # }
34
+ def fragments_attributes=(frag_hashes = [])
35
+ frag_hashes = frag_hashes.values if frag_hashes.is_a?(Hash)
36
+
37
+ frag_hashes.each do |frag_attrs|
38
+ unless frag_attrs.is_a?(HashWithIndifferentAccess)
39
+ frag_attrs.symbolize_keys!
40
+ end
41
+
42
+ identifier = frag_attrs.delete(:identifier)
43
+
44
+ fragment =
45
+ fragments.detect { |f| f.identifier == identifier } ||
46
+ fragments.build(identifier: identifier)
47
+
48
+ fragment.attributes = frag_attrs
49
+
50
+ # tracking dirty
51
+ self.fragments_attributes_changed ||= fragment.changed?
52
+ end
53
+ end
54
+
55
+ # Snapshop of page fragments data used primarily for saving revisions
56
+ def fragments_attributes(was = false)
57
+ fragments.collect do |frag|
58
+ attrs = {}
59
+ %i[identifier tag content datetime boolean].each do |column|
60
+ attrs[column] = frag.send(was ? "#{column}_was" : column)
61
+ end
62
+ # TODO: save files against revision (not on db though)
63
+ # attrs[:files] = frag.attachments.collect do |a|
64
+ # {io: a.download, filename: a.filename.to_s, content_type: a.content_type}
65
+ # end
66
+ attrs
67
+ end
68
+ end
69
+
70
+ # Method to collect prevous state of blocks for revisions
71
+ def fragments_attributes_was
72
+ fragments_attributes(:previous_values)
73
+ end
74
+
75
+ # Grabbing nodes that we need to render form elements in the admin area
76
+ # Rejecting duplicates as we'd need to render only one form field. Don't declare
77
+ # duplicate tags on the layout. That's wierd (but still works).
78
+ def fragment_nodes
79
+ nodes
80
+ .grep(ComfortableMediaSurfer::Content::Tags::Fragment)
81
+ .uniq(&:identifier)
82
+ end
83
+
84
+ # Rendered content of the page. We grab whatever layout is associated with the
85
+ # page and feed its content tokens to the renderer while passing this page as
86
+ # context.
87
+ def render(n = nodes)
88
+ renderer.render(n)
89
+ end
90
+
91
+ # If content_cache column is populated we don't need to call render for this
92
+ # page.
93
+ def content_cache
94
+ if (cache = read_attribute(:content_cache)).nil?
95
+ cache = render
96
+ update_column(:content_cache, cache) unless new_record?
97
+ end
98
+ cache
99
+ end
100
+
101
+ # Nuking content cache so it can be regenerated.
102
+ def clear_content_cache!
103
+ update_column(:content_cache, nil)
104
+ end
105
+
106
+ # Blanking cache on page saves so it can be regenerated on access
107
+ def clear_content_cache
108
+ write_attribute(:content_cache, nil)
109
+ end
110
+
111
+ protected
112
+
113
+ def renderer
114
+ ComfortableMediaSurfer::Content::Renderer.new(self)
115
+ end
116
+
117
+ def nodes
118
+ return [] unless layout.present?
119
+
120
+ tokens = layout.content_tokens
121
+ renderer.nodes(tokens)
122
+ end
123
+ end
@@ -0,0 +1,4 @@
1
+ - object ||= categories
2
+ - object.categories.each do |category|
3
+ %span.badge.badge-primary.mr-1.mb-1
4
+ = category.label
@@ -0,0 +1,7 @@
1
+ - url = comfy_admin_cms_site_category_path(@site, category)
2
+ = form_with model: @category, scope: :category, url: url, html: {class: "edit-category", id: dom_id(category)}, local: false do |form|
3
+ .input-group
4
+ = form.text_field :label, class: "form-control form-control-sm", id: nil
5
+ .input-group-btn
6
+ %button.btn.btn-primary.btn-sm{aria: {label: "Update Category"}}
7
+ %i.fas.fa-fw.fa-check
@@ -0,0 +1,5 @@
1
+ - object = form.object
2
+ - if (categories = @site.categories.of_type(object.class.to_s)).present?
3
+ - options = {bootstrap: {check_inline: true, label: {text: t(".label"), class: "pt-0"}}}
4
+ = form.collection_check_boxes :category_ids, categories, :id, :label, options
5
+
@@ -0,0 +1,28 @@
1
+ .box.categories-widget
2
+
3
+ .read
4
+ .categories
5
+ .category
6
+ - active_class = params[:categories].blank?? "active" : nil
7
+ = link_to t('.all'), {categories: nil}, class: "btn btn-sm btn-light btn-block #{active_class}"
8
+ - @site.categories.of_type(type).each do |category|
9
+ = render "comfy/admin/cms/categories/show", category: category, read: true
10
+ %button.toggle-cat-edit.btn.btn-secondary.btn-sm.btn-block{type: "button"}
11
+ = t(".edit")
12
+
13
+ .editable
14
+ .categories
15
+ - @site.categories.of_type(type).each do |category|
16
+ = render "comfy/admin/cms/categories/show", category: category
17
+
18
+ - url = comfy_admin_cms_site_categories_path(@site)
19
+ = form_with scope: :category, url: url, html: {id: "new-category"}, local: false do |form|
20
+ = form.hidden_field :categorized_type, value: type
21
+ .input-group
22
+ = form.text_field :label, placeholder: t('.add_placeholder'), class: 'form-control form-control-sm', id: nil
23
+ .input-group-btn
24
+ %button.btn.btn-primary.btn-sm{aria: {label: "Create Category"}}
25
+ %i.fas.fa-fw.fa-plus
26
+
27
+ %button.toggle-cat-edit.btn.btn-light.btn-sm.btn-block{type: "button"}
28
+ = t(".done")
@@ -0,0 +1,15 @@
1
+ - read ||= false
2
+ - categories = [params[:categories]].flatten.compact
3
+ - active = categories.flatten.member?(category.label)
4
+
5
+ .category{id: dom_id(category)}
6
+ - if read
7
+ - active_class = active ? "active" : nil
8
+ - categories = active ? categories.reject{|c| c == category.label} : categories << category.label
9
+ - url = "?#{{categories: categories}.to_query}"
10
+ = link_to category.label, url, class: "btn btn-sm btn-light btn-block text-left text-truncate #{active_class}"
11
+ - else
12
+ .btn-group.d-flex
13
+ = link_to category.label, edit_comfy_admin_cms_site_category_path(@site, category), remote: true, class: "btn btn-sm btn-light w-100 text-left text-truncate"
14
+ = link_to comfy_admin_cms_site_category_path(@site, category), method: :delete, remote: true, data: {confirm: t('.are_you_sure')}, class: 'btn btn-sm btn-danger', aria: {label: "Delete Category"} do
15
+ %i.fas.fa-fw.fa-times
@@ -0,0 +1,7 @@
1
+ $('.categories-widget .editable .categories').append(
2
+ '<%= escape_javascript(render "show", category: @category) %>'
3
+ );
4
+ $('.categories-widget .read .categories').append(
5
+ '<%= escape_javascript(render "show", category: @category, read: true) %>'
6
+ );
7
+ $('.categories-widget .editable form#new-category input[name="category[label]"]').val('');
@@ -0,0 +1,8 @@
1
+ (() => {
2
+ const categoryElements = document.querySelectorAll('.categories .category#<%= dom_id(@category) %>');
3
+ jQuery(categoryElements).fadeOut('slow', () => {
4
+ for (const element of categoryElements) {
5
+ element.remove();
6
+ }
7
+ });
8
+ })();
@@ -0,0 +1,3 @@
1
+ $('.editable .category#<%= dom_id(@category) %>').replaceWith(
2
+ '<%= escape_javascript(render "edit", category: @category ) %>'
3
+ );
@@ -0,0 +1,6 @@
1
+ $('.editable form#<%= dom_id(@category) %>').replaceWith(
2
+ '<%= escape_javascript(render "show", category: @category ) %>'
3
+ );
4
+ $('.read .category#<%= dom_id(@category) %>').replaceWith(
5
+ '<%= escape_javascript(render "show", category: @category, read: true) %>'
6
+ );
@@ -0,0 +1,31 @@
1
+ %li{data: {id: file.id}}
2
+ :ruby
3
+ file_tag = cms_file_link_tag(file)
4
+ thumb_url = url_for(file.attachment.representation(resize_to_limit: [200, nil])) if file.attachment.variable?
5
+ .row
6
+ .col-md-5.item
7
+ .item-controls.d-none.d-lg-block
8
+ - if !params[:categories].present? && @site.files.count > 1
9
+ .dragger
10
+ %i.fas.fa-bars
11
+ .item-content
12
+ .item-title
13
+ = link_to file.label, file.attachment, target: "_blank",
14
+ data: {cms_file_thumb_url: thumb_url, cms_file_link_tag: file_tag}
15
+ .item-meta
16
+ .content-type
17
+ = truncate(file.attachment.content_type)
18
+ .file-size
19
+ = number_to_human_size(file.attachment.byte_size)
20
+
21
+ .col-md-2.item-categories.d-flex.align-items-center
22
+ = render partial: "comfy/admin/cms/categories/categories", object: file
23
+
24
+ .col-md-2.d-flex.align-items-center
25
+ %span.file-path
26
+ = file_tag
27
+
28
+ .col-md-3.d-flex.align-items-center.justify-content-md-end
29
+ .btn-group.btn-group-sm
30
+ = link_to t(".edit"), edit_comfy_admin_cms_site_file_path(@site, file), class: "btn btn-outline-secondary"
31
+ = link_to t(".delete"), comfy_admin_cms_site_file_path(@site, file), method: :delete, remote: true, data: {confirm: t(".are_you_sure")}, class: "btn btn-danger"
@@ -0,0 +1,26 @@
1
+ = comfy_admin_partial "comfy/admin/cms/partials/file_form_before", form: form
2
+
3
+ = form.text_field :label
4
+ = form.file_field :file
5
+
6
+ - unless @file.new_record?
7
+
8
+ = form.form_group bootstrap: {label: {text: t('.current_file')}}do
9
+ - if @file.attachment.image?
10
+ .file-image
11
+ = image_tag @file.attachment
12
+ = link_to @file.attachment.filename, @file.attachment, target: '_blank'
13
+
14
+ = form.text_area :description
15
+
16
+ = render 'comfy/admin/cms/categories/form', form: form
17
+
18
+ = comfy_admin_partial 'comfy/admin/cms/partials/file_form_after', form: form
19
+
20
+ = form.form_actions do
21
+ = submit_tag t(@file.new_record? ? ".create" : ".update"), class: "btn btn-primary"
22
+
23
+ - unless @file.new_record?
24
+ = link_to t(".delete"), comfy_admin_cms_site_file_path(@site, @file), method: :delete, data: {confirm: t(".are_you_sure")}, class: "btn btn-danger"
25
+
26
+ = link_to t(".cancel"), comfy_admin_cms_site_files_path, class: "btn btn-link"
@@ -0,0 +1,3 @@
1
+ .modal.fade.cms-files-modal{'aria-hidden' => 'true', 'data-url' => comfy_admin_cms_site_files_path(@site, layout: false), role: 'dialog', tabindex: "-1"}
2
+ .modal-dialog.modal-lg
3
+ .modal-content
@@ -0,0 +1,4 @@
1
+ (() => {
2
+ const listItem = document.querySelector('li[data-id="<%= @file.id %>"]');
3
+ listItem.remove();
4
+ })();
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= t(".title")
3
+
4
+ = comfy_form_with model: @file, scope: :file, url: {action: :update} do |form|
5
+ = render form
@@ -0,0 +1,31 @@
1
+ - content_for :right_column do
2
+ = render "comfy/admin/cms/categories/index", type: "Comfy::Cms::File"
3
+
4
+ :ruby
5
+ session_id = request.session_options[:id]
6
+ session_id_value = session_id.respond_to?(:public_id) ? session_id.public_id : session_id.to_s
7
+ cms_uploader_data = {
8
+ cms_uploader: {
9
+ url: comfy_admin_cms_site_files_path(@site, source: :plupload, categories: params[:categories]),
10
+ token: { name: request_forgery_protection_token, value: form_authenticity_token },
11
+ session: { name: Rails.application.config.session_options[:key], value: session_id_value }
12
+ }
13
+ }
14
+
15
+ #cms-uploader{data: cms_uploader_data}
16
+ #cms-uploader-drag-drop-target
17
+
18
+ .page-header
19
+ = link_to t('.new_link'), new_comfy_admin_cms_site_file_path(@site), class: "btn btn-secondary float-right", id: "cms-uploader-browse"
20
+ %h2= t('.title')
21
+
22
+ = comfy_admin_partial "comfy/admin/cms/partials/files_before"
23
+
24
+ = comfy_paginate @files
25
+
26
+ %ul.list.sortable.cms-uploader-filelist
27
+ = render partial: "file", collection: @files
28
+
29
+ = comfy_admin_partial "comfy/admin/cms/partials/files_after"
30
+
31
+ = comfy_paginate @files
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= t(".title")
3
+
4
+ = comfy_form_with model: @file, scope: :file, url: {action: :create}, html: {multipart: true} do |form|
5
+ = render form
@@ -0,0 +1,23 @@
1
+ .fragment-attachments
2
+ - attachments.each do |attachment|
3
+ :ruby
4
+ thumb_url = if attachment.variable?
5
+ url_for(attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:thumb]))
6
+ end
7
+ filename = attachment.filename.to_s
8
+ truncated_filename = truncate(filename, length: 40, omission: "...#{filename.last(10)}")
9
+
10
+ link_data = {
11
+ cms_file_thumb_url: thumb_url,
12
+ cms_file_link_tag: cms_page_file_link_tag(
13
+ fragment_id: fragment_id,
14
+ attachment: attachment,
15
+ multiple: multiple
16
+ )
17
+ }
18
+
19
+ .fragment-attachment.btn-group.btn-group-sm.mb-1
20
+ = link_to truncated_filename, attachment, data: link_data, class: "btn btn-light text-truncate", target: "_blank"
21
+ = check_box_tag "#{object_name}[fragments_attributes][#{index}][file_ids_destroy][]", attachment.id, false, id: dom_id(attachment)
22
+ %label.btn.btn-light{for: dom_id(attachment)}
23
+ %i.fas.fa-fw.fa-times
@@ -0,0 +1,38 @@
1
+ - begin
2
+ - nodes = record.fragment_nodes
3
+ - namespace = nodes.group_by(&:namespace)
4
+
5
+ #form-fragments
6
+ - if nodes.empty?
7
+ .alert.alert-warning
8
+ - if record.layout
9
+ = link_to record.layout.label, edit_comfy_admin_cms_site_layout_path(@site, record.layout)
10
+ = t(".no_tags").html_safe
11
+
12
+ - else
13
+ .tabbable
14
+ - if namespace.size > 1
15
+ .row
16
+ .col-sm-2
17
+ .col-sm-10
18
+ %ul.nav.nav-tabs
19
+ - namespace.each_with_index do |(name, tags), index|
20
+ %li.nav-item
21
+ - active = index == 0 ? "active" : nil
22
+ - label = t("comfy.cms.content.namespace.#{name}", default: name.humanize)
23
+ = link_to label, "#ns-#{name}", class: "nav-link #{active}", data: {toggle: "tab"}
24
+
25
+ .tab-content
26
+ - frag_index = 0
27
+
28
+ - builder_opts = { builder: ComfortableMediaSurfer::FormBuilder, bootstrap: { layout: :horizontal }}
29
+ = fields scope, model: record, **builder_opts do |form|
30
+ - namespace.each_with_index do |(name, tags), index|
31
+ .tab-pane{id: "ns-#{name}", class: index == 0 ? "active" : nil}
32
+ - tags.each do |tag|
33
+ = form.fragment_field(tag, frag_index)
34
+ - frag_index += 1
35
+
36
+ - rescue ComfortableMediaSurfer::Content::Renderer::SyntaxError, ComfortableMediaSurfer::Content::Tag::Error => e
37
+ .alert.alert-danger
38
+ = e
@@ -0,0 +1,20 @@
1
+ = comfy_admin_partial "comfy/admin/cms/partials/layout_form_before", form: form
2
+
3
+ = form.text_field :label, data: {slugify: @layout.new_record?}
4
+ = form.text_field :identifier, data: {slug: true}
5
+
6
+ - if (options = Comfy::Cms::Layout.options_for_select(@site, @layout)).present?
7
+ = form.select :parent_id, [["---- #{t('.select_parent_layout')} ----", nil]] + options, bootstrap: {custom_control: true}
8
+
9
+ - if (options = Comfy::Cms::Layout.app_layouts_for_select(lookup_context.view_paths)).present?
10
+ = form.select :app_layout, [["---- #{t('.select_app_layout')} ----", nil]] + options, bootstrap: {custom_control: true}
11
+
12
+ = form.text_area :content, data: {'cms-cm-mode' => 'text/html'}
13
+ = form.text_area :css, data: {'cms-cm-mode' => 'css'}
14
+ = form.text_area :js, data: {'cms-cm-mode' => 'javascript'}
15
+
16
+ = comfy_admin_partial "comfy/admin/cms/partials/layout_form_after", form: form
17
+
18
+ = form.form_actions do
19
+ = submit_tag t(@layout.new_record? ? ".create" : ".update"), class: "btn btn-primary"
20
+ = link_to t('.cancel'), comfy_admin_cms_site_layouts_path, class: "btn btn-link"
@@ -0,0 +1,26 @@
1
+ - layout ||= index_branch
2
+ - has_siblings = layout.siblings.select{|l| l.site_id == @site.id}.size > 0
3
+
4
+ %li{data: {id: layout.id}}
5
+ .row
6
+ .col-md-8.item
7
+ .item-controls.d-none.d-md-block
8
+ - if has_siblings
9
+ .dragger
10
+ %i.fas.fa-bars
11
+
12
+ .item-content
13
+ .item-title
14
+ = link_to layout.label, edit_comfy_admin_cms_site_layout_path(@site, layout)
15
+ .item-meta
16
+ = layout.identifier
17
+
18
+ .col-md-4.d-flex.align-items-center.justify-content-md-end
19
+ .btn-group.btn-group-sm
20
+ = link_to t('.add_child_layout'), new_comfy_admin_cms_site_layout_path(@site, parent_id: layout.id), class: "btn btn-outline-secondary"
21
+ = link_to t('.edit'), edit_comfy_admin_cms_site_layout_path(@site, layout), class: "btn btn-outline-secondary"
22
+ = link_to t('.delete'), comfy_admin_cms_site_layout_path(@site, layout), method: :delete, data: {confirm: t('.are_you_sure')}, class: "btn btn-danger"
23
+
24
+ - if layout.children.present?
25
+ %ul.list.children.sortable.pl-md-3
26
+ = render partial: "index_branch", collection: layout.children.order(:position)
@@ -0,0 +1,9 @@
1
+ - content_for :right_column do
2
+ - link = comfy_admin_cms_site_layout_revisions_path(@site, @layout)
3
+ = render "comfy/admin/cms/revisions/sidebar", record: @layout, link: link
4
+
5
+ .page-header
6
+ %h2= t('.title')
7
+
8
+ = comfy_form_with model: @layout, scope: :layout, url: {action: :update} do |form|
9
+ = render form
@@ -0,0 +1,10 @@
1
+ .page-header
2
+ = link_to t('.new_link'), new_comfy_admin_cms_site_layout_path(@site), class: "btn btn-secondary float-right"
3
+ %h2= t('.title')
4
+
5
+ = comfy_admin_partial "comfy/admin/cms/partials/layouts_before"
6
+
7
+ %ul.list.sortable
8
+ = render partial: "index_branch", collection: @layouts
9
+
10
+ = comfy_admin_partial "comfy/admin/cms/partials/layouts_after"
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= t(".title")
3
+
4
+ = comfy_form_with model: @layout, scope: :layout, url: {action: :create} do |form|
5
+ = render form
@@ -0,0 +1,31 @@
1
+ = comfy_admin_partial "comfy/admin/cms/partials/page_form_before", form: form
2
+
3
+ = form.text_field :label, data: { slugify: @page.new_record? }
4
+
5
+ - if @page.parent.present?
6
+ = form.text_field :slug, data: { slug: true }, prepend: @page.parent.full_path
7
+
8
+ - if (options = ::Comfy::Cms::Page.options_for_select(site: @site, current_page: @page, exclude_self: true)).present?
9
+ = form.select :parent_id, options, bootstrap: {custom_control: true}
10
+
11
+ - if (options = ::Comfy::Cms::Layout.options_for_select(@site)).present?
12
+ = form.select :layout_id, options, {bootstrap: {custom_control: true}}, {data: {url: form_fragments_comfy_admin_cms_site_page_path(@site, @page.id.to_i)}, id: "fragments-toggle"}
13
+
14
+ = comfy_admin_partial "comfy/admin/cms/partials/page_form_inner", form: form
15
+
16
+ #form-fragments-container
17
+ = render "comfy/admin/cms/fragments/form_fragments", record: @page, scope: :page
18
+
19
+ = render "comfy/admin/cms/categories/form", form: form
20
+
21
+ - if (options = ::Comfy::Cms::Page.options_for_select(site: @site, current_page: @page)).present?
22
+ = form.select :target_page_id, [["---- #{t('.select_target_page')} ----", nil]] + options, bootstrap: {custom_control: true}
23
+
24
+ = form.check_box :is_published
25
+
26
+ = comfy_admin_partial "comfy/admin/cms/partials/page_form_after", form: form
27
+
28
+ = form.form_actions do
29
+ = submit_tag t(".preview"), name: "preview", formtarget: "comfy-cms-preview", id: nil, class: "btn btn-secondary"
30
+ = submit_tag t(@page.new_record?? ".create" : ".update"), class: "btn btn-primary ml-sm-1"
31
+ = link_to t(".cancel"), comfy_admin_cms_site_pages_path, class: "btn btn-link"
@@ -0,0 +1,44 @@
1
+ - page ||= index_branch
2
+ - children = @pages_by_parent[page.id]
3
+ - siblings = @pages_by_parent[page.parent_id]
4
+ - has_children = children.present?
5
+ - has_siblings = siblings.size > 1
6
+ - branch_open = (session[:cms_page_tree] || []).member?(page.id.to_s) || page.root?
7
+ - category_view = params[:categories].present?
8
+
9
+ %li{id: dom_id(page), data: {id: page.id}}
10
+ .row
11
+
12
+ .col-md-6.item
13
+ - unless category_view
14
+ .item-controls
15
+ - if has_siblings
16
+ .dragger.d-none.d-md-block
17
+ %i.fas.fa-bars
18
+
19
+ - if has_children && !page.root?
20
+ - status = branch_open ? "open" : ""
21
+ - url = toggle_branch_comfy_admin_cms_site_page_path(@site, page)
22
+ = link_to url, remote: true, title: t(".toggle"), class: "toggle #{status}" do
23
+ %i.fas.fa-plus-square.expand
24
+ %i.fas.fa-minus-square.collapse
25
+
26
+ .item-content
27
+ .item-title
28
+ - published_css_class = page.is_published? ? "published" : "draft"
29
+ = link_to page.label, edit_comfy_admin_cms_site_page_path(@site, page), class: published_css_class
30
+ .item-meta
31
+ = link_to page.url, page.url, target: "_blank"
32
+
33
+ .col-md-2.item-categories.d-flex.align-items-center
34
+ = render "comfy/admin/cms/categories/categories", object: page
35
+
36
+ .col-md-4.d-flex.align-items-center.justify-content-md-end
37
+ .btn-group.btn-group-sm
38
+ = link_to t(".add_child_page"), new_comfy_admin_cms_site_page_path(@site, parent_id: page.id), class: "btn btn-outline-secondary"
39
+ = link_to t(".edit"), edit_comfy_admin_cms_site_page_path(@site, page), class: "btn btn-outline-secondary"
40
+ = link_to t(".delete"), comfy_admin_cms_site_page_path(@site, page), method: :delete, data: {confirm: t('.are_you_sure')}, class: "btn btn-danger"
41
+
42
+ - if !category_view && has_children && branch_open
43
+ %ul.list.children.sortable.pl-md-3
44
+ = render partial: "index_branch", collection: children
@@ -0,0 +1,14 @@
1
+ - content_for :right_column do
2
+ - link = comfy_admin_cms_site_page_revisions_path(@site, @page)
3
+ = render "comfy/admin/cms/revisions/sidebar", record: @page, link: link
4
+ = render "comfy/admin/cms/translations/sidebar"
5
+
6
+ .page-header.d-flex.justify-content-between.align-items-center
7
+ %h2= t('.title')
8
+ - if @page.children.exists?
9
+ .btn-group.btn-group-sm
10
+ = link_to t('.publish_children', default: 'Publish children'), publish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.publish_children_confirmation', default: 'Publish all child pages?')}, class: 'btn btn-success'
11
+ = link_to t('.unpublish_children', default: 'Unpublish children'), unpublish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.unpublish_children_confirmation', default: 'Unpublish all child pages?')}, class: 'btn btn-outline-secondary'
12
+
13
+ = comfy_form_with model: @page, scope: :page, url: {action: :update}, html: {multipart: true} do |form|
14
+ = render form
@@ -0,0 +1,13 @@
1
+ - content_for :right_column do
2
+ = render "comfy/admin/cms/categories/index", type: "Comfy::Cms::Page"
3
+
4
+ .page-header
5
+ = link_to t('.new_link'), new_comfy_admin_cms_site_page_path(@site), class: "btn btn-secondary float-right"
6
+ %h2= t('.title')
7
+
8
+ = comfy_admin_partial "comfy/admin/cms/partials/pages_before"
9
+
10
+ %ul.list.sortable
11
+ = render partial: "index_branch", collection: @pages
12
+
13
+ = comfy_admin_partial "comfy/admin/cms/partials/pages_after"
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= t('.title')
3
+
4
+ = comfy_form_with model: @page, scope: :page, url: {action: :create}, html: {multipart: true} do |form|
5
+ = render form
@@ -0,0 +1,19 @@
1
+ // TODO: Extract this so the server only renders the HTML.
2
+ var li = document.querySelector('li#comfy_cms_page_<%=@page.id%>');
3
+ var toggle = li.querySelector('.item .toggle');
4
+ toggle.classList.toggle('open');
5
+ <% if session[:cms_page_tree].member?(@page.id.to_s) %>
6
+ if(!li.querySelector('ul.children')) {
7
+ var childrenList = document.createElement('ul');
8
+ childrenList.className = 'children sortable pl-md-3';
9
+ childrenList.innerHTML = '<%= escape_javascript(render partial: "index_branch", collection: @page.children) %>';
10
+ li.appendChild(childrenList);
11
+ CMS.sortableList.dispose();
12
+ CMS.sortableList.init();
13
+ }
14
+ <% else %>
15
+ var childrenList = li.querySelector('ul.children');
16
+ if (childrenList) {
17
+ childrenList.remove();
18
+ }
19
+ <% end %>
@@ -0,0 +1,2 @@
1
+ .box.revisions
2
+ = link_to t('.revision', count: record.revisions.count), link, class: "btn btn-sm btn-info d-block"