lcms-engine 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (374) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.dockerignore +25 -0
  4. data/.env.docker +1 -1
  5. data/.eslintignore +2 -1
  6. data/.eslintrc +23 -73
  7. data/.nvmrc +1 -1
  8. data/.overcommit.yml +8 -2
  9. data/.prettierrc +7 -0
  10. data/.rubocop.yml +12 -8
  11. data/.ruby-version +1 -1
  12. data/.stylelintignore +9 -0
  13. data/.stylelintrc +8 -0
  14. data/CHANGELOG.md +50 -1
  15. data/Dockerfile +3 -3
  16. data/Gemfile.lock +408 -322
  17. data/README.md +20 -17
  18. data/app/assets/config/lcms_engine_manifest.js +4 -2
  19. data/app/assets/javascripts/lcms/engine/admin/{application.js → lcms_engine_application.js} +1 -3
  20. data/app/assets/javascripts/lcms/engine/initializers/foundation.js +1 -1
  21. data/app/assets/javascripts/lcms/engine/{application.js → lcms_engine_application.js} +0 -0
  22. data/app/assets/stylesheets/lcms/engine/admin/collections.scss +2 -1
  23. data/app/assets/stylesheets/lcms/engine/admin/components.scss +60 -19
  24. data/app/assets/stylesheets/lcms/engine/admin/curriculums.scss +12 -10
  25. data/app/assets/stylesheets/lcms/engine/admin/lessons.scss +21 -15
  26. data/app/assets/stylesheets/lcms/engine/admin/materials.scss +25 -17
  27. data/app/assets/stylesheets/lcms/engine/admin/resources.scss +8 -7
  28. data/app/assets/stylesheets/lcms/engine/admin/standards.scss +4 -1
  29. data/app/assets/stylesheets/lcms/engine/admin/users.scss +1 -1
  30. data/app/assets/stylesheets/lcms/engine/base/_colors.scss +8 -10
  31. data/app/assets/stylesheets/lcms/engine/base/_ld-colors.scss +10 -10
  32. data/app/assets/stylesheets/lcms/engine/components/_assoc-picker.scss +4 -5
  33. data/app/assets/stylesheets/lcms/engine/components/lesson/_activity.scss +6 -2
  34. data/app/assets/stylesheets/lcms/engine/components/lesson/_callout.scss +19 -5
  35. data/app/assets/stylesheets/lcms/engine/components/lesson/_columns.scss +4 -3
  36. data/app/assets/stylesheets/lcms/engine/components/lesson/_curriculum-map.scss +16 -7
  37. data/app/assets/stylesheets/lcms/engine/components/lesson/_def.scss +2 -2
  38. data/app/assets/stylesheets/lcms/engine/components/lesson/_expand.scss +9 -9
  39. data/app/assets/stylesheets/lcms/engine/components/lesson/_foundational-divider.scss +0 -1
  40. data/app/assets/stylesheets/lcms/engine/components/lesson/_group.scss +3 -1
  41. data/app/assets/stylesheets/lcms/engine/components/lesson/_icons.scss +1 -1
  42. data/app/assets/stylesheets/lcms/engine/components/lesson/_image-wrap.scss +2 -2
  43. data/app/assets/stylesheets/lcms/engine/components/lesson/_inset.scss +7 -2
  44. data/app/assets/stylesheets/lcms/engine/components/lesson/_materials.scss +1 -1
  45. data/app/assets/stylesheets/lcms/engine/components/lesson/_multiple-choice.scss +4 -1
  46. data/app/assets/stylesheets/lcms/engine/components/lesson/_override.scss +28 -9
  47. data/app/assets/stylesheets/lcms/engine/components/lesson/_pd.scss +7 -7
  48. data/app/assets/stylesheets/lcms/engine/components/lesson/_pv.scss +5 -4
  49. data/app/assets/stylesheets/lcms/engine/components/lesson/_section.scss +10 -3
  50. data/app/assets/stylesheets/lcms/engine/components/lesson/_selection-control.scss +14 -8
  51. data/app/assets/stylesheets/lcms/engine/components/lesson/_sidebar.scss +25 -10
  52. data/app/assets/stylesheets/lcms/engine/components/lesson/_title.scss +3 -1
  53. data/app/assets/stylesheets/lcms/engine/components/lesson/_unit-map.scss +1 -1
  54. data/app/assets/stylesheets/lcms/engine/components/material/_material.scss +3 -3
  55. data/app/assets/stylesheets/lcms/engine/components/material/_overlay.scss +12 -4
  56. data/app/assets/stylesheets/lcms/engine/components/material/_preview.scss +1 -1
  57. data/app/assets/stylesheets/lcms/engine/components/support/_survey.scss +3 -1
  58. data/app/assets/stylesheets/lcms/engine/layout/_footer.scss +29 -11
  59. data/app/assets/stylesheets/lcms/engine/layout/_header.scss +5 -5
  60. data/app/assets/stylesheets/lcms/engine/layout/_navigation.scss +4 -6
  61. data/app/assets/stylesheets/lcms/engine/layout/_page.scss +2 -2
  62. data/app/assets/stylesheets/lcms/engine/{admin.scss → lcms_engine_admin.scss} +26 -15
  63. data/app/assets/stylesheets/lcms/engine/lcms_engine_application.scss +9 -0
  64. data/app/assets/stylesheets/lcms/engine/pdf.scss +5 -26
  65. data/app/assets/stylesheets/lcms/engine/pdf_plain.scss +5 -23
  66. data/app/assets/stylesheets/lcms/engine/print/_base.scss +41 -12
  67. data/app/assets/stylesheets/lcms/engine/print/_cover.scss +12 -12
  68. data/app/assets/stylesheets/lcms/engine/print/_footer.scss +8 -3
  69. data/app/assets/stylesheets/lcms/engine/print/_gdoc-base.scss +10 -37
  70. data/app/assets/stylesheets/lcms/engine/print/_helpers.scss +5 -2
  71. data/app/assets/stylesheets/lcms/engine/print/_lesson-base.scss +2 -14
  72. data/app/assets/stylesheets/lcms/engine/print/_material-base.scss +1 -3
  73. data/app/assets/stylesheets/lcms/engine/print/_print.scss +15 -8
  74. data/app/assets/stylesheets/lcms/engine/print/_toc.scss +24 -9
  75. data/app/assets/stylesheets/lcms/engine/print/gdoc/_base-typography.scss +24 -6
  76. data/app/assets/stylesheets/lcms/engine/print/gdoc/_base.scss +10 -3
  77. data/app/assets/stylesheets/lcms/engine/print/gdoc/_colors.scss +3 -3
  78. data/app/assets/stylesheets/lcms/engine/print/gdoc/_header.scss +2 -2
  79. data/app/assets/stylesheets/lcms/engine/print/gdoc/_helpers.scss +1 -0
  80. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_activity.scss +1 -1
  81. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_agenda.scss +8 -2
  82. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_callout.scss +16 -6
  83. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_def.scss +1 -1
  84. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_dialogue.scss +3 -1
  85. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_expand.scss +5 -2
  86. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_image-wrap.scss +5 -3
  87. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_image.scss +1 -1
  88. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_optbreak.scss +1 -0
  89. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_section.scss +4 -1
  90. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_smp.scss +1 -0
  91. data/app/assets/stylesheets/lcms/engine/print/gdoc/lesson/_tables.scss +11 -3
  92. data/app/assets/stylesheets/lcms/engine/print/gdoc/material/_header.scss +5 -2
  93. data/app/assets/stylesheets/lcms/engine/print/lesson/_base-typography.scss +33 -9
  94. data/app/assets/stylesheets/lcms/engine/print/lesson/_group.scss +3 -1
  95. data/app/assets/stylesheets/lcms/engine/print/lesson/_image.scss +3 -1
  96. data/app/assets/stylesheets/lcms/engine/print/lesson/_materials.scss +1 -1
  97. data/app/assets/stylesheets/lcms/engine/print/lesson/_pd.scss +8 -4
  98. data/app/assets/stylesheets/lcms/engine/print/lesson/_section.scss +1 -1
  99. data/app/assets/stylesheets/lcms/engine/print/material/_header.scss +4 -1
  100. data/app/assets/stylesheets/lcms/engine/themes/_material.scss +11 -11
  101. data/app/assets/stylesheets/lcms/engine/utils/_colorcodes.scss +15 -5
  102. data/app/assets/stylesheets/lcms/engine/utils/_functions.scss +1 -1
  103. data/app/assets/stylesheets/lcms/engine/utils/_helpers.scss +23 -11
  104. data/app/assets/stylesheets/lcms/engine/utils/_placeholders.scss +1 -1
  105. data/app/assets/stylesheets/lcms/engine/utils/_variables.scss +11 -11
  106. data/app/assets/stylesheets/lcms/engine/vendors/{mathjax.css → mathjax.scss} +0 -0
  107. data/app/assets/stylesheets/lcms/engine/vendors/react-tagsinput.css +48 -0
  108. data/app/controllers/concerns/lcms/engine/reimportable.rb +12 -2
  109. data/app/controllers/lcms/engine/admin/access_codes_controller.rb +8 -3
  110. data/app/controllers/lcms/engine/admin/admin_controller.rb +6 -40
  111. data/app/controllers/lcms/engine/admin/association_picker_controller.rb +4 -1
  112. data/app/controllers/lcms/engine/admin/batch_reimports_controller.rb +2 -2
  113. data/app/controllers/lcms/engine/admin/curriculums_controller.rb +21 -2
  114. data/app/controllers/lcms/engine/admin/documents_controller.rb +41 -14
  115. data/app/controllers/lcms/engine/admin/materials_controller.rb +32 -13
  116. data/app/controllers/lcms/engine/admin/resource_bulk_edits_controller.rb +2 -2
  117. data/app/controllers/lcms/engine/admin/resources_controller.rb +9 -7
  118. data/app/controllers/lcms/engine/admin/settings_controller.rb +1 -1
  119. data/app/controllers/lcms/engine/admin/standards_controller.rb +7 -2
  120. data/app/controllers/lcms/engine/admin/users_controller.rb +15 -7
  121. data/app/controllers/lcms/engine/application_controller.rb +1 -1
  122. data/app/controllers/lcms/engine/resources_controller.rb +5 -5
  123. data/app/controllers/lcms/engine/welcome_controller.rb +11 -0
  124. data/app/entities/lcms/engine/grades.rb +17 -6
  125. data/app/entities/lcms/engine/hierarchical_position.rb +1 -2
  126. data/app/entities/lcms/engine/media_embed.rb +2 -2
  127. data/app/entities/lcms/engine/pagination.rb +14 -10
  128. data/app/entities/lcms/engine/roman_numerals.rb +2 -2
  129. data/app/exceptions/lcms/engine/document_error.rb +8 -0
  130. data/app/exceptions/lcms/engine/material_error.rb +8 -0
  131. data/app/forms/lcms/engine/document_form.rb +19 -14
  132. data/app/forms/lcms/engine/material_form.rb +3 -2
  133. data/app/helpers/admin/components_helper.rb +3 -3
  134. data/app/helpers/lcms/engine/path_helper.rb +32 -0
  135. data/app/helpers/lcms/engine/resource_helper.rb +1 -1
  136. data/app/helpers/lcms/engine/view_helper.rb +1 -9
  137. data/app/interactors/lcms/engine/explore_curriculum_interactor.rb +2 -2
  138. data/app/javascript/components/admin/ImportStatus.jsx +90 -56
  139. data/app/javascript/components/admin/Initializer.jsx +33 -35
  140. data/app/javascript/components/admin/MultiSelectedOperation.jsx +43 -18
  141. data/app/javascript/components/admin/association-picker/AssociationPicker.jsx +68 -47
  142. data/app/javascript/components/admin/association-picker/AssociationPickerItem.jsx +18 -7
  143. data/app/javascript/components/admin/association-picker/AssociationPickerResults.jsx +42 -17
  144. data/app/javascript/components/admin/association-picker/AssociationPickerWindow.jsx +47 -27
  145. data/app/javascript/components/admin/curriculum/CurriculumEditor.jsx +54 -32
  146. data/app/javascript/components/admin/curriculum/DirectoryPicker.jsx +80 -53
  147. data/app/javascript/components/admin/picker/PickerButton.jsx +16 -11
  148. data/app/javascript/components/admin/picker/pickerModal.jsx +6 -6
  149. data/app/javascript/components/admin/picker/pickerWindowWrapper.jsx +61 -40
  150. data/app/javascript/components/admin/resource-picker/ResourcePicker.jsx +54 -39
  151. data/app/javascript/components/admin/resource-picker/ResourcePickerResource.jsx +14 -3
  152. data/app/javascript/components/admin/resource-picker/ResourcePickerWindow.jsx +50 -21
  153. data/app/javascript/components/paginate/PageView.jsx +20 -8
  154. data/app/javascript/components/paginate/PaginationBoxView.jsx +78 -66
  155. data/app/javascript/components/paginate/PaginationListView.jsx +59 -45
  156. data/app/javascript/packs/lcms_engine_admin.js +15 -0
  157. data/app/javascript/packs/{application.js → lcms_engine_application.js} +5 -4
  158. data/app/javascript/packs/server_rendering.js +1 -0
  159. data/app/javascript/vendor/jstree/jstree.min.js +6 -0
  160. data/app/javascript/vendor/jstree/themes/default/32px.png +0 -0
  161. data/app/javascript/vendor/jstree/themes/default/40px.png +0 -0
  162. data/app/javascript/vendor/jstree/themes/default/style.css +1106 -0
  163. data/app/javascript/vendor/jstree/themes/default/style.min.css +1 -0
  164. data/app/javascript/vendor/jstree/themes/default/throbber.gif +0 -0
  165. data/app/javascript/vendor/jstree/themes/default-dark/32px.png +0 -0
  166. data/app/javascript/vendor/jstree/themes/default-dark/40px.png +0 -0
  167. data/app/javascript/vendor/jstree/themes/default-dark/style.css +1150 -0
  168. data/app/javascript/vendor/jstree/themes/default-dark/style.min.css +1 -0
  169. data/app/javascript/vendor/jstree/themes/default-dark/throbber.gif +0 -0
  170. data/app/jobs/concerns/lcms/engine/nested_resque_job.rb +1 -4
  171. data/app/jobs/lcms/engine/document_generate_gdoc_job.rb +2 -2
  172. data/app/jobs/lcms/engine/document_generate_job.rb +2 -2
  173. data/app/jobs/lcms/engine/document_generate_pdf_job.rb +5 -5
  174. data/app/jobs/lcms/engine/document_parse_job.rb +1 -1
  175. data/app/jobs/lcms/engine/material_generate_pdf_job.rb +4 -4
  176. data/app/models/concerns/lcms/engine/navigable.rb +6 -10
  177. data/app/models/concerns/lcms/engine/searchable.rb +7 -0
  178. data/app/models/lcms/engine/document.rb +1 -1
  179. data/app/models/lcms/engine/download.rb +1 -1
  180. data/app/models/lcms/engine/resource.rb +1 -1
  181. data/app/models/lcms/engine/search/document.rb +4 -3
  182. data/app/models/lcms/engine/search/repository.rb +1 -1
  183. data/app/presenters/lcms/engine/content_presenter.rb +1 -1
  184. data/app/presenters/lcms/engine/curriculum_presenter.rb +21 -18
  185. data/app/presenters/lcms/engine/document_presenter.rb +5 -3
  186. data/app/presenters/lcms/engine/resource_presenter.rb +6 -3
  187. data/app/queries/lcms/engine/admin_documents_query.rb +2 -2
  188. data/app/queries/lcms/engine/admin_materials_query.rb +11 -2
  189. data/app/queries/lcms/engine/base_query.rb +1 -1
  190. data/app/serializers/lcms/engine/previews_material_serializer.rb +1 -0
  191. data/app/services/lcms/engine/document_build_service.rb +6 -0
  192. data/app/services/lcms/engine/document_generator.rb +2 -2
  193. data/app/services/lcms/engine/google/drive_service.rb +7 -15
  194. data/app/services/lcms/engine/google/script_service.rb +7 -3
  195. data/app/services/lcms/engine/html_sanitizer.rb +6 -6
  196. data/app/services/lcms/engine/lessons_gdoc_bundler.rb +1 -1
  197. data/app/services/lcms/engine/lti_exporter.rb +1 -1
  198. data/app/services/lcms/engine/material_build_service.rb +6 -2
  199. data/app/services/lcms/engine/material_preview_generator.rb +3 -3
  200. data/app/services/lcms/engine/react_materials_resolver.rb +3 -2
  201. data/app/services/lcms/engine/s3_service.rb +14 -2
  202. data/app/tasks/resource_tasks.rb +2 -2
  203. data/app/views/layouts/lcms/engine/admin.html.erb +3 -3
  204. data/app/views/layouts/lcms/engine/application.html.erb +2 -2
  205. data/app/views/layouts/lcms/engine/lti.html.erb +1 -1
  206. data/app/views/lcms/engine/admin/access_codes/_form.html.erb +1 -1
  207. data/app/views/lcms/engine/admin/access_codes/index.html.erb +3 -3
  208. data/app/views/lcms/engine/admin/batch_reimports/_search_form.html.erb +2 -2
  209. data/app/views/lcms/engine/admin/curriculums/edit.html.erb +5 -5
  210. data/app/views/lcms/engine/admin/documents/_materials_links.html.erb +2 -2
  211. data/app/views/lcms/engine/admin/documents/_reimport.html.erb +1 -1
  212. data/app/views/lcms/engine/admin/documents/_search_form.html.erb +2 -2
  213. data/app/views/lcms/engine/admin/documents/import.html.erb +1 -1
  214. data/app/views/lcms/engine/admin/documents/index.html.erb +7 -5
  215. data/app/views/lcms/engine/admin/documents/new.html.erb +6 -2
  216. data/app/views/lcms/engine/admin/materials/_reimport.html.erb +1 -1
  217. data/app/views/lcms/engine/admin/materials/_search_form.html.erb +2 -2
  218. data/app/views/lcms/engine/admin/materials/import.html.erb +1 -1
  219. data/app/views/lcms/engine/admin/materials/index.html.erb +26 -22
  220. data/app/views/lcms/engine/admin/materials/new.html.erb +5 -1
  221. data/app/views/lcms/engine/admin/resource_bulk_edits/new.html.erb +2 -2
  222. data/app/views/lcms/engine/admin/resources/_fields.html.erb +4 -0
  223. data/app/views/lcms/engine/admin/resources/_form.html.erb +1 -1
  224. data/app/views/lcms/engine/admin/resources/_search_form.html.erb +2 -2
  225. data/app/views/lcms/engine/admin/resources/index.html.erb +7 -5
  226. data/app/views/lcms/engine/admin/shared/_header.html.erb +12 -12
  227. data/app/views/lcms/engine/admin/standards/_form.html.erb +3 -1
  228. data/app/views/lcms/engine/admin/standards/_search_form.html.erb +1 -1
  229. data/app/views/lcms/engine/admin/users/_form.html.erb +1 -1
  230. data/app/views/lcms/engine/admin/users/_search_form.html.erb +1 -1
  231. data/app/views/lcms/engine/admin/users/index.html.erb +6 -6
  232. data/app/views/lcms/engine/documents/gdoc/_agenda.html.erb +1 -1
  233. data/app/views/lcms/engine/documents/show.html.erb +1 -1
  234. data/app/views/lcms/engine/materials/show.html.erb +1 -1
  235. data/app/views/lcms/engine/pages/not_found.html.erb +5 -0
  236. data/app/views/lcms/engine/resources/_download.html.erb +2 -2
  237. data/app/views/lcms/engine/resources/_unit_bundles.html.erb +2 -2
  238. data/app/views/lcms/engine/resources/generic.html.erb +0 -4
  239. data/app/views/lcms/engine/resources/media.html.erb +0 -4
  240. data/app/views/lcms/engine/resources/show.html.erb +0 -2
  241. data/config/initializers/airbrake.rb +62 -10
  242. data/config/initializers/bitly.rb +1 -1
  243. data/config/initializers/carrier_wave.rb +6 -4
  244. data/config/initializers/ckeditor.rb +6 -0
  245. data/config/initializers/elasticsearch.rb +1 -1
  246. data/config/initializers/resque.rb +2 -2
  247. data/config/locales/admin/en.yml +1 -2
  248. data/config/locales/ui/en.yml +1 -0
  249. data/config/routes.rb +5 -2
  250. data/db/migrate/.keep +0 -0
  251. data/db/schema.rb +280 -312
  252. data/db/seeds.rb +0 -1
  253. data/docker-compose.ror4.yml +32 -0
  254. data/docker-compose.yml +6 -3
  255. data/docs/env-variables.md +40 -40
  256. data/docs/google-cloud-platform-setup.md +45 -17
  257. data/docs/how-to-build-and-publish.md +1 -0
  258. data/lcms-engine.gemspec +28 -20
  259. data/lib/doc_template/document.rb +3 -4
  260. data/lib/doc_template/document_toc.rb +2 -2
  261. data/lib/doc_template/objects/activity_metadata.rb +1 -1
  262. data/lib/doc_template/objects/agenda_metadata.rb +1 -1
  263. data/lib/doc_template/objects/metadata_helpers.rb +1 -1
  264. data/lib/doc_template/objects/toc_helpers.rb +4 -4
  265. data/lib/doc_template/objects/toc_metadata.rb +4 -6
  266. data/lib/doc_template/tables/base.rb +3 -2
  267. data/lib/doc_template/tags/activity_metadata_type_tag.rb +1 -1
  268. data/lib/doc_template/tags/answer_space_tag.rb +2 -2
  269. data/lib/doc_template/tags/base_tag.rb +5 -5
  270. data/lib/doc_template/tags/block_tag.rb +1 -1
  271. data/lib/doc_template/tags/columns_tag.rb +1 -1
  272. data/lib/doc_template/tags/def_tag.rb +1 -1
  273. data/lib/doc_template/tags/expand_tag.rb +1 -0
  274. data/lib/doc_template/tags/heading_tag.rb +1 -1
  275. data/lib/doc_template/tags/inset_tag.rb +2 -2
  276. data/lib/doc_template/tags/latex_tag.rb +1 -1
  277. data/lib/doc_template/tags/page_break_tag.rb +1 -1
  278. data/lib/doc_template/tags/pd_tag.rb +4 -4
  279. data/lib/doc_template/tags/section_tag.rb +2 -2
  280. data/lib/doc_template/tags/standard_tag.rb +3 -3
  281. data/lib/doc_template/tags/table_preserve_alignment_tag.rb +1 -1
  282. data/lib/doc_template/tags/table_tag.rb +1 -1
  283. data/lib/doc_template/template.rb +1 -1
  284. data/lib/doc_template.rb +9 -9
  285. data/lib/document_exporter/gdoc/base.rb +6 -3
  286. data/lib/document_exporter/pdf/base.rb +1 -1
  287. data/lib/document_exporter/pdf/document.rb +2 -2
  288. data/lib/document_exporter/pdf/material.rb +2 -2
  289. data/lib/document_exporter/pdf/student_material.rb +2 -2
  290. data/lib/document_exporter/pdf/teacher_material.rb +2 -2
  291. data/lib/document_renderer/part.rb +4 -6
  292. data/lib/elasticsearch/persistence/repository/response/results.rb +1 -1
  293. data/lib/lcms/engine/engine.rb +10 -9
  294. data/lib/lcms/engine/version.rb +1 -1
  295. data/lib/lcms/engine.rb +0 -1
  296. data/lib/lt/lcms/metadata/base_service.rb +2 -1
  297. data/lib/lt/lcms/metadata/context.rb +58 -54
  298. data/lib/lt/lcms/metadata/service.rb +6 -3
  299. data/lib/resque_job.rb +3 -6
  300. data/lib/standard_importer.rb +4 -4
  301. data/lib/tasks/cloud66.rake +8 -6
  302. data/lib/tasks/document.rake +7 -7
  303. data/lib/tasks/google.rake +29 -14
  304. data/lib/tasks/lcms/engine_tasks.rake +1 -1
  305. data/package.json +31 -9
  306. data/postcss.config.js +12 -0
  307. data/spec/controllers/admin/association_picker_controller_spec.rb +6 -8
  308. data/spec/controllers/admin/curriculums_controller_spec.rb +23 -0
  309. data/spec/controllers/admin/documents_controller_spec.rb +25 -3
  310. data/spec/controllers/admin/materials_controller_spec.rb +17 -4
  311. data/spec/controllers/admin/resource_bulk_edit_controller_spec.rb +1 -1
  312. data/spec/controllers/admin/resources_controller_spec.rb +3 -3
  313. data/spec/controllers/admin/settings_controller_spec.rb +1 -1
  314. data/spec/controllers/admin/standards_controller_spec.rb +1 -1
  315. data/spec/controllers/admin/welcome_controller_spec.rb +12 -10
  316. data/spec/controllers/resources_controller_spec.rb +3 -3
  317. data/spec/controllers/welcome_controller_spec.rb +38 -0
  318. data/spec/dummy/.env.docker +5 -0
  319. data/spec/dummy/.traceroute.yaml +0 -2
  320. data/spec/dummy/bin/webpack +18 -0
  321. data/spec/dummy/bin/webpack-dev-server +18 -0
  322. data/spec/dummy/config/application.rb +1 -1
  323. data/spec/dummy/config/environments/production.rb +1 -1
  324. data/spec/dummy/config/environments/test.rb +1 -1
  325. data/spec/dummy/config/initializers/assets.rb +6 -0
  326. data/spec/dummy/config/lcms-admin.yml +3 -7
  327. data/spec/dummy/config/puma.rb +3 -3
  328. data/spec/dummy/config/routes.rb +6 -0
  329. data/spec/dummy/db/schema.rb +5 -5
  330. data/spec/entities/grades_spec.rb +12 -0
  331. data/spec/factories/documents.rb +1 -0
  332. data/spec/factories/downloads.rb +1 -1
  333. data/spec/factories/resources.rb +2 -2
  334. data/spec/features/admin/lessons/add_lesson_spec.rb +3 -3
  335. data/spec/features/admin/materials/add_material_spec.rb +5 -3
  336. data/spec/features/admin/users_spec.rb +2 -2
  337. data/spec/forms/document_form_spec.rb +11 -1
  338. data/spec/{controllers/admin/admin_controller_spec.rb → helpers/path_helper_spec.rb} +6 -6
  339. data/spec/lib/doc_template/objects/activity_metadata_spec.rb +1 -1
  340. data/spec/lib/doc_template/objects/agenda_metadata_spec.rb +2 -0
  341. data/spec/lib/doc_template/objects/toc_metadata_spec.rb +1 -1
  342. data/spec/lib/doc_template/tables/shared_examples/remove_table.rb +1 -1
  343. data/spec/lib/doc_template/tags/page_break_tag_spec.rb +1 -1
  344. data/spec/lib/doc_template/tags/pd_tag_spec.rb +1 -1
  345. data/spec/models/document_spec.rb +1 -1
  346. data/spec/models/standard_spec.rb +2 -0
  347. data/spec/queries/lcms/engine/admin_materials_query_spec.rb +34 -0
  348. data/spec/rails_helper.rb +8 -2
  349. data/spec/services/document_build_service_spec.rb +4 -11
  350. data/spec/services/s3_service_spec.rb +31 -0
  351. data/spec/support/concerns/navigable.rb +2 -0
  352. data/spec/support/routes.rb +4 -0
  353. data/spec/support/shared_examples/content_tag.rb +4 -4
  354. data/templates/routes.rb +0 -1
  355. data/yarn.lock +3447 -2993
  356. metadata +208 -303
  357. data/app/assets/stylesheets/lcms/engine/application.scss +0 -36
  358. data/app/assets/stylesheets/lcms/engine/vendors/jquery.tagsinput.css +0 -1
  359. data/app/exceptions/components_api_error.rb +0 -4
  360. data/app/exceptions/document_error.rb +0 -4
  361. data/app/exceptions/material_error.rb +0 -4
  362. data/app/javascript/packs/admin.js +0 -14
  363. data/app/models/lcms/engine/component.rb +0 -88
  364. data/app/presenters/lcms/engine/social_media_presenter.rb +0 -83
  365. data/app/views/lcms/engine/shared/_social_sharing.html.erb +0 -22
  366. data/db/migrate/20200217160930_change_document_parts_to_polymorphic.rb +0 -36
  367. data/db/migrate/20200218144849_drop_material_parts_table.rb +0 -7
  368. data/db/migrate/20200422130652_add_reimported_at_to_documents.rb +0 -7
  369. data/db/migrate/20200429130353_drop_pages.rb +0 -13
  370. data/db/seeds/pages.seeds.rb +0 -26
  371. data/lib/document_exporter.rb +0 -6
  372. data/lib/lcms/engine/migration.rb +0 -16
  373. data/spec/models/component_spec.rb +0 -60
  374. data/vendor/assets/javascripts/jquery.tagsinput.js +0 -1
@@ -32,7 +32,7 @@ module Lcms
32
32
  end
33
33
 
34
34
  def grades_props
35
- ActiveModel::Serializer::CollectionSerializer.new(
35
+ ActiveModelSerializers::SerializableResource.new(
36
36
  grades,
37
37
  each_serializer: CurriculumResourceSerializer,
38
38
  root: :results
@@ -70,7 +70,7 @@ module Lcms
70
70
 
71
71
  def slug_param
72
72
  slug = params[:p]
73
- (slug.start_with?('/') ? slug[1..-1] : slug) if slug.present?
73
+ (slug.start_with?('/') ? slug[1..] : slug) if slug.present?
74
74
  end
75
75
 
76
76
  def expanded?
@@ -1,35 +1,37 @@
1
- import React from 'react'
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import _ from 'lodash';
2
4
 
3
5
  class ImportStatus extends React.Component {
4
6
  constructor(props) {
5
- super(props)
6
- this.state = { jobs: props.jobs }
7
- this.pollingInterval = 5000
8
- this.chunkSize = 50
9
- this.links = _.isEmpty(props.links) ? [`${props.type}/:id`] : props.links
7
+ super(props);
8
+ this.state = { jobs: props.jobs };
9
+ this.pollingInterval = 5000;
10
+ this.chunkSize = 50;
11
+ this.links = _.isEmpty(props.links) ? [`${props.type}/:id`] : props.links;
10
12
  if (_.isEmpty(props.path)) {
11
- const k = `lcms_engine_import_status_admin_${this.props.type}_path`
12
- this.path = Routes[k].call()
13
+ const k = `lcms_engine_import_status_admin_${this.props.type}_path`;
14
+ this.path = Routes[k].call();
13
15
  } else {
14
- this.path = props.path
16
+ this.path = props.path;
15
17
  }
16
- this.withPdf = props.with_pdf || false
18
+ this.withPdf = props.with_pdf || false;
17
19
  }
18
20
 
19
21
  componentDidMount() {
20
- this.intervalFn = setInterval(this.poll.bind(this), this.pollingInterval)
22
+ this.intervalFn = setInterval(this.poll.bind(this), this.pollingInterval);
21
23
  }
22
24
 
23
25
  componentWillUnmount() {
24
- clearInterval(this.intervalFn)
26
+ clearInterval(this.intervalFn);
25
27
  }
26
28
 
27
29
  poll() {
28
- const pendingJobs = _.compact(_.map(this.state.jobs, (job, jid) => job.status !== 'done' ? jid : null))
30
+ const pendingJobs = _.compact(_.map(this.state.jobs, (job, jid) => (job.status !== 'done' ? jid : null)));
29
31
  if (pendingJobs.length > 0) {
30
- _.each(_.chunk(pendingJobs, this.chunkSize), jids => this.updateChunkStatus(jids))
32
+ _.each(_.chunk(pendingJobs, this.chunkSize), jids => this.updateChunkStatus(jids));
31
33
  } else {
32
- clearInterval(this.intervalFn)
34
+ clearInterval(this.intervalFn);
33
35
  }
34
36
  }
35
37
 
@@ -38,88 +40,120 @@ class ImportStatus extends React.Component {
38
40
  jids: jids,
39
41
  type: this.props.type,
40
42
  _: Date.now(), // prevent cached response
41
- }).done(res => {
42
- let updatedJobs = {}
43
- _.each(res, (val, jid) => {
44
- updatedJobs[jid] = _.extend(this.state.jobs[jid], { status: val.status }, val.result)
45
- })
46
- this.setState({ jobs: _.extend(this.state.jobs, updatedJobs) })
47
- }).fail(res => {
48
- console.warn('check content export status', res)
49
43
  })
44
+ .done(res => {
45
+ let updatedJobs = {};
46
+ _.each(res, (val, jid) => {
47
+ updatedJobs[jid] = _.extend(this.state.jobs[jid], { status: val.status }, val.result);
48
+ });
49
+ this.setState({ jobs: _.extend(this.state.jobs, updatedJobs) });
50
+ })
51
+ .fail(res => {
52
+ console.warn('check content export status', res); // eslint-disable-line no-console
53
+ });
50
54
  }
51
55
 
52
56
  resourceButton(job) {
53
57
  if (this.withPdf) {
54
58
  return (
55
- <a href={job.link}
56
- className="o-adm-materials__resource ub-icon ub-file-pdf button primary u-margin-left--small u-margin-bottom--zero" target="_blank">
59
+ <a
60
+ href={job.link}
61
+ className="o-adm-materials__resource button primary u-margin-left--small u-margin-bottom--zero"
62
+ target="_blank"
63
+ rel="noreferrer"
64
+ >
65
+ <i className="far fa-file-pdf"></i>
57
66
  </a>
58
- )
67
+ );
59
68
  }
60
69
 
61
- let linkWithParams = function(route, params = {}) {
62
- let path = route
70
+ let linkWithParams = function (route, params = {}) {
71
+ let path = route;
63
72
  _.each(params, (v, k) => {
64
- path = _.replace(path, `:${k}`, v)
65
- })
66
- return path
67
- }
73
+ path = _.replace(path, `:${k}`, v);
74
+ });
75
+ return path;
76
+ };
68
77
 
69
78
  return _.map(this.links, (link, idx) => (
70
- <a key={`pl-${idx}`}
79
+ <a
80
+ key={`pl-${idx}`}
71
81
  href={linkWithParams(link, { id: job.model.id })}
72
- className="o-adm-materials__resource ub-icon ub-eye button primary u-margin-left--small u-margin-bottom--zero" target="_blank">
82
+ className="o-adm-materials__resource button primary u-margin-left--small u-margin-bottom--zero"
83
+ target="_blank"
84
+ rel="noreferrer"
85
+ >
86
+ <i className="fas fa-eye"></i>
73
87
  </a>
74
- ))
88
+ ));
75
89
  }
76
90
 
77
91
  spinner() {
78
- return <span className="o-adm-materials__spinner button primary u-margin-bottom--zero"><i className="fas fa-spin fa-spinner" /></span>
92
+ return (
93
+ <span className="o-adm-materials__spinner button primary u-margin-bottom--zero">
94
+ <i className="fas fa-spin fa-spinner" />
95
+ </span>
96
+ );
79
97
  }
80
98
 
81
99
  render() {
82
- const waitingCount = _.filter(this.state.jobs, (job) => job.status !== 'done').length
83
- const importedCount = _.filter(this.state.jobs, (job) => job.status === 'done' && job.ok ).length
84
- const failedCount = _.filter(this.state.jobs, (job) => job.status === 'done' && !job.ok ).length
100
+ const waitingCount = _.filter(this.state.jobs, job => job.status !== 'done').length;
101
+ const importedCount = _.filter(this.state.jobs, job => job.status === 'done' && job.ok).length;
102
+ const failedCount = _.filter(this.state.jobs, job => job.status === 'done' && !job.ok).length;
85
103
 
86
104
  const results = _.map(this.state.jobs, (job, key) => {
87
- let status
105
+ let status;
88
106
  if (job.status === 'done') {
89
- status = job.ok ? 'ok' : 'err'
107
+ status = job.ok ? 'ok' : 'err';
90
108
  } else {
91
- status = job.status
109
+ status = job.status;
92
110
  }
93
111
  return (
94
112
  <li className={`o-adm-materials__result o-adm-materials__result--${status}`} key={key}>
95
113
  <div className="u-flex align-justify align-middle">
96
- <a href={job.link} target='_blank' className='o-adm-materials__link'>
114
+ <a href={job.link} target="_blank" className="o-adm-materials__link" rel="noreferrer">
97
115
  {job.link}
98
116
  </a>
99
117
  {job.status !== 'done' ? this.spinner() : null}
100
118
  {job.status === 'done' && job.ok ? <span>{this.resourceButton(job)}</span> : null}
101
119
  </div>
102
- {job.errors ? (<p dangerouslySetInnerHTML={{__html: _.join(job.errors, '<br/>')}}></p>) : null}
120
+ {!_.isEmpty(job.errors) ? <p dangerouslySetInnerHTML={{ __html: _.join(job.errors, '<br/>') }}></p> : null}
121
+ {!_.isEmpty(job.warnings) ? (
122
+ <p
123
+ dangerouslySetInnerHTML={{
124
+ __html: _.join(job.warnings, '<br/>'),
125
+ }}
126
+ ></p>
127
+ ) : null}
103
128
  </li>
104
- )
105
- })
129
+ );
130
+ });
106
131
 
107
132
  return (
108
133
  <div>
109
134
  <p className="o-adm-materials__summary">
110
- <span className='summary-entry'>• {waitingCount} Files(s) Processing</span>
111
- <span className='summary-entry'>{`✓ ${importedCount} File(s) ${this.withPdf ? 'Generated' : 'Imported'}`}</span>
112
- <span className='summary-entry'>x {failedCount} File(s) Failed</span>
135
+ <span className="summary-entry">• {waitingCount} Files(s) Processing</span>
136
+ <span className="summary-entry">{`✓ ${importedCount} File(s) ${
137
+ this.withPdf ? 'Generated' : 'Imported'
138
+ }`}</span>
139
+ <span className="summary-entry">x {failedCount} File(s) Failed</span>
113
140
  </p>
114
- <aside className='o-adm-materials__summary--aside u-margin-bottom--small'>
115
- After the (re){`${this.withPdf ? 'generation' : 'import'}`} the files for export are still in process of being generated in the background. They will appear soon after.
141
+ <aside className="o-adm-materials__summary--aside u-margin-bottom--small">
142
+ After the (re){`${this.withPdf ? 'generation' : 'import'}`} the files for export are still in process of being
143
+ generated in the background. They will appear soon after.
116
144
  </aside>
117
- <ul className="o-adm-materials__results">
118
- {results}
119
- </ul>
145
+ <ul className="o-adm-materials__results">{results}</ul>
120
146
  </div>
121
- )
147
+ );
122
148
  }
123
149
  }
124
150
 
125
- export default ImportStatus
151
+ ImportStatus.propTypes = {
152
+ jobs: PropTypes.array,
153
+ links: PropTypes.array,
154
+ type: PropTypes.string,
155
+ path: PropTypes.string,
156
+ with_pdf: PropTypes.bool,
157
+ };
158
+
159
+ export default ImportStatus;
@@ -1,41 +1,39 @@
1
- function initializeResourcesForm() {
2
- const form = $('form#resource_form')
3
- if (!form.length) return
1
+ const Initializer = {
2
+ initializeResourcesForm: () => {
3
+ const form = $('form#resource_form');
4
+ if (!form.length) return;
4
5
 
5
- const opr_desc = form.find('.resource_opr_description')
6
- form.find('#resource_curriculum_type').change((ev) => {
7
- const el = $(ev.target)
8
- if (el.val() === 'unit') {
9
- opr_desc.slideDown()
10
- } else {
11
- opr_desc.slideUp()
12
- }
13
- })
14
- }
6
+ const opr_desc = form.find('.resource_opr_description');
7
+ form.find('#resource_curriculum_type').change(ev => {
8
+ const el = $(ev.target);
9
+ if (el.val() === 'unit') {
10
+ opr_desc.slideDown();
11
+ } else {
12
+ opr_desc.slideUp();
13
+ }
14
+ });
15
+ },
15
16
 
16
- function initializeResourcesList() {
17
- const page = $('.o-adm-list.o-adm-documents')
18
- if (!page.length) return
17
+ initializeResourcesList: () => {
18
+ const page = $('.o-adm-list.o-adm-documents');
19
+ if (!page.length) return;
19
20
 
20
- page.find('.c-reimport-with-materials__toggle input[type=checkbox]').change(() => {
21
- const value = $(this).prop('checked') ? 1 : 0
22
- page.find('.c-reimport-doc-form .c-reimport-with-materials__field').val(value)
23
- })
24
- }
21
+ page.find('.c-reimport-with-materials__toggle input[type=checkbox]').change(() => {
22
+ const value = $(this).prop('checked') ? 1 : 0;
23
+ page.find('.c-reimport-doc-form .c-reimport-with-materials__field').val(value);
24
+ });
25
+ },
25
26
 
26
- function initializeSelectAll() {
27
- const selector = $('.c-multi-selected--select-all')
28
- if (!selector.length) return
27
+ initializeSelectAll: () => {
28
+ const selector = $('.c-multi-selected--select-all');
29
+ if (!selector.length) return;
29
30
 
30
- selector.find('input').change((ev) => {
31
- const el = $(ev.target)
32
- const checked = el.prop('checked')
33
- $('.table input[type=checkbox][name="selected_ids[]"]').prop('checked', checked)
34
- })
35
- }
31
+ selector.find('input').change(ev => {
32
+ const el = $(ev.target);
33
+ const checked = el.prop('checked');
34
+ $('.table input[type=checkbox][name="selected_ids[]"]').prop('checked', checked);
35
+ });
36
+ },
37
+ };
36
38
 
37
- export default {
38
- initializeResourcesList,
39
- initializeResourcesForm,
40
- initializeSelectAll,
41
- }
39
+ export default Initializer;
@@ -1,39 +1,64 @@
1
- import React from 'react'
2
- import ReactDOM from 'react-dom'
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import PropTypes from 'prop-types';
4
+ import _ from 'lodash';
3
5
 
4
6
  class MultiSelectedOperation extends React.Component {
7
+ constructor(props) {
8
+ super(props);
9
+
10
+ this.onSubmit = this.onSubmit.bind(this);
11
+ }
12
+
5
13
  componentDidMount() {
6
- const $this = $(ReactDOM.findDOMNode(this))
7
- $this.parent().addClass('c-multi-selected-btn')
14
+ // eslint-disable-next-line react/no-find-dom-node
15
+ const $this = $(ReactDOM.findDOMNode(this));
16
+ $this.parent().addClass('c-multi-selected-btn');
8
17
  }
9
18
 
10
19
  onSubmit(evt) {
11
- if (this.props.operation === 'delete' && !confirm('Are you sure?')) return
20
+ if (this.props.operation === 'delete' && !confirm('Are you sure?')) return; // eslint-disable-line no-restricted-globals
12
21
 
13
- const entries = $('.o-page .table input[name="selected_ids[]"]')
14
- const ids = _.filter(entries, (e) => e.checked).map((e) => e.value)
15
- if (ids.length === 0) return evt.preventDefault()
22
+ const entries = $('.o-page .table input[name="selected_ids[]"]');
23
+ const ids = _.filter(entries, e => e.checked).map(e => e.value);
24
+ if (ids.length === 0) return evt.preventDefault();
16
25
 
17
- const form = $(this.formRef)
18
- form.find('input[name=selected_ids]').val(ids.join(','))
19
- form.find('[type=submit]').prop('disabled', true)
26
+ const form = $(this.formRef);
27
+ form.find('input[name=selected_ids]').val(ids.join(','));
28
+ form.find('[type=submit]').prop('disabled', true);
20
29
  }
21
30
 
22
31
  render() {
23
- const btnClass = `button ${this.props.btn_style}`
24
- const method = (this.props.operation === 'delete') ? 'delete' : 'post'
25
- const csrf_token = $('meta[name=csrf-token]').attr('content')
32
+ const btnClass = `button ${this.props.btn_style}`;
33
+ const method = this.props.operation === 'delete' ? 'delete' : 'post';
34
+ const csrf_token = $('meta[name=csrf-token]').attr('content');
26
35
  return (
27
- <form ref={ ref => { this.formRef = ref }} action={this.props.path} acceptCharset="UTF-8" method='post' className="c-reimport-doc-form" onSubmit={this.onSubmit.bind(this)} >
36
+ <form
37
+ ref={ref => {
38
+ this.formRef = ref;
39
+ }}
40
+ action={this.props.path}
41
+ acceptCharset="UTF-8"
42
+ method="post"
43
+ className="c-reimport-doc-form"
44
+ onSubmit={this.onSubmit}
45
+ >
28
46
  <input name="utf8" value="✓" type="hidden" />
29
47
  <input name="_method" value={method} type="hidden" />
30
48
  <input name="authenticity_token" value={csrf_token} type="hidden" />
31
49
  <input name="selected_ids" type="hidden" />
32
- <input name="with_materials" type="hidden" className="c-reimport-with-materials__field"/>
50
+ <input name="with_materials" type="hidden" className="c-reimport-with-materials__field" />
33
51
  <input value={this.props.text} className={btnClass} type="submit" />
34
52
  </form>
35
- )
53
+ );
36
54
  }
37
55
  }
38
56
 
39
- export default MultiSelectedOperation
57
+ MultiSelectedOperation.propTypes = {
58
+ operation: PropTypes.string,
59
+ btn_style: PropTypes.string,
60
+ path: PropTypes.string,
61
+ text: PropTypes.string,
62
+ };
63
+
64
+ export default MultiSelectedOperation;
@@ -1,92 +1,103 @@
1
- import React from 'react'
2
- import ReactDOM from 'react-dom'
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import PropTypes from 'prop-types';
4
+ import _ from 'lodash';
3
5
  // eslint-disable-next-line no-unused-vars
4
- import AssociationPickerItem from './AssociationPickerItem'
5
- import AssociationPickerWindow from './AssociationPickerWindow'
6
+ import AssociationPickerItem from './AssociationPickerItem';
7
+ import AssociationPickerWindow from './AssociationPickerWindow';
6
8
  // eslint-disable-next-line no-unused-vars
7
- import PickerButton from '../picker/PickerButton'
8
- import pickerModal from '../picker/pickerModal'
9
- import pickerWindowWrapper from '../picker/pickerWindowWrapper'
9
+ import PickerButton from '../picker/PickerButton';
10
+ import pickerModal from '../picker/pickerModal';
11
+ import pickerWindowWrapper from '../picker/pickerWindowWrapper';
12
+ import { Foundation } from 'foundation-sites';
13
+ import $ from 'jquery';
10
14
 
11
15
  class AssociationPicker extends React.Component {
12
16
  constructor(props) {
13
- super(props)
17
+ super(props);
14
18
 
15
19
  this.state = {
16
20
  items: this.props.items || [],
17
- }
21
+ };
18
22
  }
19
23
 
20
24
  get jqmodal() {
21
- return $(this.modal)
25
+ return $(this.modal);
22
26
  }
23
27
 
24
28
  componentDidMount() {
29
+ Foundation.addToJquery($);
25
30
  // eslint-disable-next-line no-undef
26
- pickerModal.call(this)
31
+ pickerModal.call(this);
27
32
  }
28
33
 
29
34
  onClickSelect() {
30
35
  // eslint-disable-next-line no-undef
31
- const pickerComponent = pickerWindowWrapper(AssociationPickerWindow, 'lcms_engine_admin_association_picker_path')
32
- const picker = React.createElement(pickerComponent, {
33
- association: this.props.association,
34
- allowCreate: this.props.allow_create,
35
- allowMultiple: this.props.allow_multiple,
36
- onClickDone: this.closeModal.bind(this),
37
- onSelectItem: this.selectItem.bind(this),
38
- selectedItems: this.state.items,
39
- }, null)
40
- ReactDOM.render(picker, this.modal)
41
- this.jqmodal.foundation('open')
36
+ const pickerComponent = pickerWindowWrapper(AssociationPickerWindow, 'lcms_engine_admin_association_picker_path');
37
+ const picker = React.createElement(
38
+ pickerComponent,
39
+ {
40
+ association: this.props.association,
41
+ allowCreate: this.props.allow_create,
42
+ allowMultiple: this.props.allow_multiple,
43
+ onClickDone: this.closeModal.bind(this),
44
+ onSelectItem: this.selectItem.bind(this),
45
+ selectedItems: this.state.items,
46
+ },
47
+ null
48
+ );
49
+ ReactDOM.render(picker, this.modal);
50
+ this.jqmodal.foundation('open');
42
51
  }
43
52
 
44
53
  selectItem(item, operation) {
45
54
  if (!this.props.allow_multiple) {
46
- this.closeModal()
55
+ this.closeModal();
47
56
  }
48
- operation === 'added' ? this.addItem(item) : this.removeItem(item)
57
+ operation === 'added' ? this.addItem(item) : this.removeItem(item);
49
58
  }
50
59
 
51
60
  closeModal() {
52
- this.jqmodal.foundation('close')
61
+ this.jqmodal.foundation('close');
53
62
  }
54
63
 
55
64
  addItem(item) {
56
- const newItems = this.props.allow_multiple ?
57
- [...this.state.items, item] :
58
- [item]
65
+ const newItems = this.props.allow_multiple ? [...this.state.items, item] : [item];
59
66
 
60
67
  this.setState({
61
68
  ...this.state,
62
69
  items: newItems,
63
- })
70
+ });
64
71
  }
65
72
 
66
73
  removeItem(item) {
67
74
  this.setState({
68
75
  ...this.state,
69
76
  items: _.filter(this.state.items, r => r.id !== item.id),
70
- })
77
+ });
71
78
  }
72
79
 
73
80
  render() {
74
- const items = this.state.items.map((item) => {
75
- return <AssociationPickerItem
76
- key={item.id}
77
- name={this.props.name}
78
- createName={this.props.create_name}
79
- association={this.props.association}
80
- allowMultiple={this.props.allow_multiple}
81
- item={item}
82
- // eslint-disable-next-line react/jsx-no-bind
83
- onClickClose={() => this.removeItem(item)}
84
- />
85
- })
81
+ const items = this.state.items.map(item => {
82
+ return (
83
+ <AssociationPickerItem
84
+ key={item.id}
85
+ name={this.props.name}
86
+ createName={this.props.create_name}
87
+ association={this.props.association}
88
+ allowMultiple={this.props.allow_multiple}
89
+ item={item}
90
+ // eslint-disable-next-line react/jsx-no-bind
91
+ onClickClose={() => this.removeItem(item)}
92
+ />
93
+ );
94
+ });
86
95
 
87
- const blankInput = this.props.allow_multiple ?
88
- <input type="hidden" name={`${this.props.name}[]`} value="" /> :
96
+ const blankInput = this.props.allow_multiple ? (
97
+ <input type="hidden" name={`${this.props.name}[]`} value="" />
98
+ ) : (
89
99
  <span className="hide" />
100
+ );
90
101
 
91
102
  return (
92
103
  <PickerButton
@@ -95,10 +106,20 @@ class AssociationPicker extends React.Component {
95
106
  // eslint-disable-next-line react/jsx-no-bind
96
107
  onClick={this.onClickSelect.bind(this)}
97
108
  // eslint-disable-next-line react/jsx-no-bind
98
- onRef={m => this.modal = m}
109
+ onRef={m => (this.modal = m)}
99
110
  />
100
- )
111
+ );
101
112
  }
102
113
  }
103
114
 
104
- export default AssociationPicker
115
+ AssociationPicker.propTypes = {
116
+ item: PropTypes.object,
117
+ items: PropTypes.array,
118
+ association: PropTypes.string,
119
+ create_name: PropTypes.string,
120
+ allow_create: PropTypes.bool,
121
+ allow_multiple: PropTypes.bool,
122
+ name: PropTypes.string,
123
+ };
124
+
125
+ export default AssociationPicker;
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
+ import PropTypes from 'prop-types';
2
3
 
3
4
  // eslint-disable-next-line no-unused-vars
4
5
  function AssociationPickerItem(props) {
5
- let input
6
+ let input;
6
7
 
7
8
  if (props.item._create) {
8
- input = <input type="hidden" name={`${props.createName}[]`} value={props.item.name} />
9
+ input = <input type="hidden" name={`${props.createName}[]`} value={props.item.name} />;
9
10
  } else if (props.allowMultiple) {
10
- input = <input type="hidden" name={`${props.name}[]`} value={props.item.id} />
11
+ input = <input type="hidden" name={`${props.name}[]`} value={props.item.id} />;
11
12
  } else {
12
- input = <input type="hidden" name={props.name} value={props.item.id} />
13
+ input = <input type="hidden" name={props.name} value={props.item.id} />;
13
14
  }
14
15
 
15
16
  return (
@@ -17,10 +18,20 @@ function AssociationPickerItem(props) {
17
18
  {input}
18
19
  <div className="o-assocpicker-title">
19
20
  {props.item.name}
20
- <span className="o-assocpicker-close" onClick={props.onClickClose}>×</span>
21
+ <span className="o-assocpicker-close" onClick={props.onClickClose}>
22
+ ×
23
+ </span>
21
24
  </div>
22
25
  </div>
23
- )
26
+ );
24
27
  }
25
28
 
26
- export default AssociationPickerItem
29
+ AssociationPickerItem.propTypes = {
30
+ item: PropTypes.object,
31
+ createName: PropTypes.string,
32
+ allowMultiple: PropTypes.bool,
33
+ name: PropTypes.string,
34
+ onClickClose: PropTypes.func,
35
+ };
36
+
37
+ export default AssociationPickerItem;