sufia 7.2.0 → 7.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/.rubocop_todo.yml +1 -2
  5. data/.travis.yml +0 -1
  6. data/Gemfile +2 -1
  7. data/README.md +23 -106
  8. data/app/actors/sufia/apply_permission_template_actor.rb +19 -0
  9. data/app/actors/sufia/create_with_remote_files_actor.rb +2 -2
  10. data/app/actors/sufia/default_admin_set_actor.rb +42 -0
  11. data/app/actors/sufia/interpret_visibility_actor.rb +115 -0
  12. data/app/assets/images/collection.png +0 -0
  13. data/app/assets/javascripts/sufia.js +6 -0
  14. data/app/assets/javascripts/sufia/admin/admin_set/participants.es6 +9 -0
  15. data/app/assets/javascripts/sufia/admin/admin_set/visibility.es6 +134 -0
  16. data/app/assets/javascripts/sufia/admin/admin_set_controls.es6 +11 -0
  17. data/app/assets/javascripts/sufia/app.js +27 -5
  18. data/app/assets/javascripts/sufia/autocomplete.es6 +15 -0
  19. data/app/assets/javascripts/sufia/autocomplete/work.es6 +29 -0
  20. data/app/assets/javascripts/sufia/dashboard_actions.js +2 -4
  21. data/app/assets/javascripts/sufia/save_work/save_work_control.es6 +14 -2
  22. data/app/assets/javascripts/sufia/save_work/uploaded_files.es6 +7 -2
  23. data/app/assets/javascripts/sufia/save_work/visibility_component.es6 +245 -4
  24. data/app/assets/javascripts/sufia/select_work_type.es6 +38 -0
  25. data/app/assets/javascripts/sufia/workflow_actions_affix.js +14 -0
  26. data/app/assets/stylesheets/sufia/_dashboard.scss +50 -29
  27. data/app/assets/stylesheets/sufia/_footer.scss +30 -0
  28. data/app/assets/stylesheets/sufia/_header.scss +3 -4
  29. data/app/assets/stylesheets/sufia/_home-page.scss +10 -8
  30. data/app/assets/stylesheets/sufia/_select_work_type.scss +43 -0
  31. data/app/assets/stylesheets/sufia/_sufia.scss +4 -1
  32. data/app/assets/stylesheets/sufia/_variables.scss +3 -0
  33. data/app/assets/stylesheets/sufia/admin.scss +66 -169
  34. data/app/assets/stylesheets/sufia/blacklight_gallery.scss +17 -0
  35. data/app/authorities/qa/authorities/find_works.rb +15 -0
  36. data/app/controllers/concerns/sufia/batch_edits_controller_behavior.rb +2 -1
  37. data/app/controllers/concerns/sufia/batch_uploads_controller_behavior.rb +26 -13
  38. data/app/controllers/concerns/sufia/collections_controller_behavior.rb +25 -0
  39. data/app/controllers/concerns/sufia/controller.rb +8 -0
  40. data/app/controllers/concerns/sufia/deny_access_override_behavior.rb +1 -1
  41. data/app/controllers/concerns/sufia/file_sets_controller_behavior.rb +5 -14
  42. data/app/controllers/concerns/sufia/homepage_controller_behavior.rb +2 -0
  43. data/app/controllers/concerns/sufia/users_controller_behavior.rb +18 -7
  44. data/app/controllers/concerns/sufia/works_controller_behavior.rb +13 -10
  45. data/app/controllers/my/collections_controller.rb +5 -0
  46. data/app/controllers/my/shares_controller.rb +5 -0
  47. data/app/controllers/my/works_controller.rb +5 -0
  48. data/app/controllers/stats_controller.rb +1 -1
  49. data/app/controllers/sufia/admin/admin_sets_controller.rb +20 -2
  50. data/app/controllers/sufia/admin/permission_template_accesses_controller.rb +15 -0
  51. data/app/controllers/sufia/admin/permission_templates_controller.rb +29 -0
  52. data/app/controllers/sufia/admin_controller.rb +2 -0
  53. data/app/controllers/sufia/trophies_controller.rb +0 -2
  54. data/app/forms/sufia/forms/admin_set_form.rb +19 -0
  55. data/app/forms/sufia/forms/batch_edit_form.rb +16 -6
  56. data/app/forms/sufia/forms/batch_upload_form.rb +3 -2
  57. data/app/forms/sufia/forms/permission_template_form.rb +115 -0
  58. data/app/forms/sufia/forms/work_form.rb +6 -0
  59. data/app/helpers/batch_edits_helper.rb +1 -1
  60. data/app/helpers/sufia/citations_behavior.rb +0 -5
  61. data/app/helpers/sufia/citations_behaviors/formatters.rb +0 -1
  62. data/app/helpers/sufia/sufia_helper_behavior.rb +38 -6
  63. data/app/indexers/sufia/collection_indexer.rb +6 -0
  64. data/app/jobs/batch_create_job.rb +7 -15
  65. data/app/models/batch_upload_item.rb +2 -0
  66. data/app/models/concerns/sufia/ability.rb +12 -1
  67. data/app/models/sufia/permission_template.rb +102 -0
  68. data/app/models/sufia/permission_template_access.rb +18 -0
  69. data/app/presenters/sufia/admin_set_presenter.rb +1 -1
  70. data/app/presenters/sufia/model_icon.rb +7 -0
  71. data/app/presenters/sufia/select_type_list_presenter.rb +37 -0
  72. data/app/presenters/sufia/select_type_presenter.rb +35 -0
  73. data/app/presenters/sufia/work_show_presenter.rb +0 -2
  74. data/app/search_builders/collection_search_builder.rb +0 -2
  75. data/app/search_builders/sufia/admin_set_search_builder.rb +24 -0
  76. data/app/search_builders/sufia/catalog_search_builder.rb +10 -4
  77. data/app/search_builders/sufia/find_works_search_builder.rb +44 -0
  78. data/app/search_builders/sufia/my_search_builder_behavior.rb +0 -4
  79. data/app/search_builders/sufia/my_works_search_builder.rb +1 -1
  80. data/app/services/sufia/actor_factory.rb +6 -2
  81. data/app/services/sufia/admin_set_create_service.rb +22 -0
  82. data/app/services/sufia/admin_set_service.rb +46 -16
  83. data/app/services/sufia/collection_thumbnail_path_service.rb +10 -0
  84. data/app/services/sufia/workflow/abstract_notification.rb +39 -0
  85. data/app/services/sufia/workflow/changes_required_notification.rb +22 -0
  86. data/app/services/sufia/workflow/complete_notification.rb +22 -0
  87. data/app/services/sufia/workflow/pending_review_notification.rb +21 -0
  88. data/app/services/sufia/workflow/workflow_by_admin_set_strategy.rb +15 -0
  89. data/app/views/_masthead.html.erb +4 -4
  90. data/app/views/_toolbar.html.erb +31 -9
  91. data/app/views/_user_util_links.html.erb +7 -7
  92. data/app/views/batch_edits/edit.html.erb +24 -12
  93. data/app/views/catalog/_thumbnail_list_collection.html.erb +1 -1
  94. data/app/views/collections/_form.html.erb +2 -2
  95. data/app/views/collections/_media_display.html.erb +1 -1
  96. data/app/views/curation_concerns/base/_find_work_widget.html.erb +16 -0
  97. data/app/views/curation_concerns/base/_form.html.erb +6 -0
  98. data/app/views/curation_concerns/base/_form_child_work_relationships.html.erb +1 -1
  99. data/app/views/curation_concerns/base/_form_metadata.html.erb +1 -1
  100. data/app/views/curation_concerns/base/_form_parent_work_relationships.html.erb +43 -0
  101. data/app/views/curation_concerns/base/_form_progress.html.erb +7 -4
  102. data/app/views/curation_concerns/base/_form_relationships.html.erb +6 -6
  103. data/app/views/curation_concerns/base/_form_share.html.erb +1 -2
  104. data/app/views/curation_concerns/base/_guts4form.html.erb +1 -1
  105. data/app/views/curation_concerns/base/_social_media.html.erb +1 -1
  106. data/app/views/curation_concerns/base/_workflow_actions_widget.erb +3 -0
  107. data/app/views/curation_concerns/base/edit.html.erb +1 -1
  108. data/app/views/curation_concerns/base/new.html.erb +1 -1
  109. data/app/views/curation_concerns/base/show.html.erb +4 -1
  110. data/app/views/curation_concerns/file_sets/_show_actions.html.erb +0 -3
  111. data/app/views/dashboard/_create_work_action.html.erb +20 -0
  112. data/app/views/dashboard/_index_partials/_heading_actions.html.erb +9 -22
  113. data/app/views/layouts/admin.html.erb +8 -68
  114. data/app/views/layouts/curation_concerns/1_column.html.erb +4 -31
  115. data/app/views/layouts/homepage.html.erb +15 -45
  116. data/app/views/layouts/sufia-dashboard.html.erb +1 -36
  117. data/app/views/layouts/sufia.html.erb +49 -0
  118. data/app/views/my/_document_list.html.erb +1 -1
  119. data/app/views/my/_facet_limit.html.erb +2 -2
  120. data/app/views/my/_index_partials/_default_group.html.erb +10 -10
  121. data/app/views/my/_index_partials/_list_collections.html.erb +1 -1
  122. data/app/views/my/_sort_and_per_page.html.erb +8 -8
  123. data/app/views/records/edit_fields/_rights.html.erb +0 -1
  124. data/app/views/shared/_footer.html.erb +1 -1
  125. data/app/views/shared/_select_work_type_modal.html.erb +34 -0
  126. data/app/views/sufia/admin/_collections.html.erb +31 -0
  127. data/app/views/sufia/admin/_sidebar.html.erb +35 -23
  128. data/app/views/sufia/admin/admin_sets/_form.html.erb +38 -15
  129. data/app/views/sufia/admin/admin_sets/_form_metadata.html.erb +2 -0
  130. data/app/views/sufia/admin/admin_sets/_form_participant_table.html.erb +21 -0
  131. data/app/views/sufia/admin/admin_sets/_form_participants.html.erb +68 -0
  132. data/app/views/sufia/admin/admin_sets/_form_visibility.html.erb +58 -0
  133. data/app/views/sufia/admin/admin_sets/index.html.erb +29 -33
  134. data/app/views/sufia/admin/admin_sets/show.html.erb +3 -0
  135. data/app/views/sufia/admin/show.html.erb +22 -19
  136. data/app/views/sufia/batch_uploads/_form.html.erb +2 -1
  137. data/app/views/sufia/homepage/index.html.erb +11 -3
  138. data/app/views/sufia/uploads/_js_templates.html.erb +15 -11
  139. data/app/views/users/_user_row.html.erb +10 -0
  140. data/app/views/users/index.html.erb +1 -12
  141. data/config/features.rb +2 -0
  142. data/config/locales/sufia.en.yml +122 -37
  143. data/config/routes.rb +4 -1
  144. data/db/migrate/20161021175854_create_permission_template.rb +11 -0
  145. data/db/migrate/20161021180154_create_permission_template_access.rb +11 -0
  146. data/db/migrate/20161116222307_add_release_to_permission_templates.rb +6 -0
  147. data/lib/generators/sufia/install_generator.rb +12 -3
  148. data/lib/generators/sufia/templates/catalog_controller.rb +3 -13
  149. data/lib/generators/sufia/templates/workflow.json.erb +65 -0
  150. data/lib/generators/sufia/upgrade700_generator.rb +1 -1
  151. data/lib/generators/sufia/work/templates/locale.en.yml.erb +37 -0
  152. data/lib/generators/sufia/{work_generator.rb → work/work_generator.rb} +25 -5
  153. data/lib/sufia.rb +0 -1
  154. data/lib/sufia/engine.rb +7 -0
  155. data/lib/sufia/move_all_works_to_admin_set.rb +8 -0
  156. data/lib/sufia/version.rb +1 -1
  157. data/lib/tasks/migrate.rake +8 -0
  158. data/spec/actors/sufia/apply_permission_template_actor_spec.rb +64 -0
  159. data/spec/actors/sufia/create_with_remote_files_actor_spec.rb +8 -0
  160. data/spec/actors/sufia/default_admin_set_actor_spec.rb +43 -0
  161. data/spec/actors/sufia/interpret_visibility_actor_spec.rb +266 -0
  162. data/spec/authorities/qa/authorities/find_works_spec.rb +55 -0
  163. data/spec/controllers/batch_edits_controller_spec.rb +1 -6
  164. data/spec/controllers/citations_controller_spec.rb +49 -10
  165. data/spec/controllers/collections_controller_spec.rb +39 -0
  166. data/spec/controllers/curation_concerns/generic_works_controller_spec.rb +22 -1
  167. data/spec/controllers/dashboard_controller_spec.rb +0 -8
  168. data/spec/controllers/depositors_controller_spec.rb +2 -2
  169. data/spec/controllers/downloads_controller_spec.rb +2 -2
  170. data/spec/controllers/my/collections_controller_spec.rb +5 -0
  171. data/spec/controllers/my/shares_controller_spec.rb +5 -0
  172. data/spec/controllers/my/works_controller_spec.rb +5 -0
  173. data/spec/controllers/stats_controller_spec.rb +1 -1
  174. data/spec/controllers/sufia/admin/admin_sets_controller_spec.rb +33 -5
  175. data/spec/controllers/sufia/admin/permission_template_accesses_controller_spec.rb +36 -0
  176. data/spec/controllers/sufia/admin/permission_templates_controller_spec.rb +46 -0
  177. data/spec/controllers/sufia/admin_controller_spec.rb +6 -0
  178. data/spec/controllers/sufia/batch_uploads_controller_spec.rb +40 -42
  179. data/spec/controllers/sufia/homepage_controller_spec.rb +14 -0
  180. data/spec/controllers/sufia/trophies_controller_spec.rb +17 -4
  181. data/spec/controllers/users_controller_spec.rb +13 -4
  182. data/spec/factories/permission_template_accesses.rb +5 -0
  183. data/spec/factories/permission_templates.rb +5 -0
  184. data/spec/factories/sipity_entities.rb +7 -0
  185. data/spec/factories/users.rb +4 -0
  186. data/spec/factories/workflow_states.rb +6 -0
  187. data/spec/factories/workflows.rb +5 -0
  188. data/spec/features/admin_admin_set_spec.rb +6 -4
  189. data/spec/features/batch_edit_spec.rb +0 -1
  190. data/spec/features/collection_spec.rb +4 -4
  191. data/spec/features/edit_work_spec.rb +1 -0
  192. data/spec/features/work_show_spec.rb +10 -0
  193. data/spec/forms/sufia/forms/admin_set_form_spec.rb +2 -1
  194. data/spec/forms/sufia/forms/batch_edit_form_spec.rb +30 -0
  195. data/spec/forms/sufia/forms/permission_template_form_spec.rb +196 -0
  196. data/spec/forms/sufia/forms/work_form_spec.rb +35 -1
  197. data/spec/helpers/batch_edits_helper_spec.rb +4 -4
  198. data/spec/helpers/blacklight_helper_spec.rb +1 -1
  199. data/spec/helpers/sufia_helper_spec.rb +39 -7
  200. data/spec/indexers/sufia/collection_indexer_spec.rb +12 -0
  201. data/spec/javascripts/autocomplete_spec.js.coffee +46 -6
  202. data/spec/javascripts/visibility_component_spec.js +491 -0
  203. data/spec/jobs/batch_create_job_spec.rb +27 -28
  204. data/spec/lib/sufia/arkivo_spec.rb +14 -0
  205. data/spec/lib/sufia/controlled_vocabulary/importer/downloader_spec.rb +31 -0
  206. data/spec/lib/sufia/move_all_works_to_admin_set_spec.rb +13 -0
  207. data/spec/lib/sufia/zotero_spec.rb +8 -0
  208. data/spec/models/sufia/ability_spec.rb +54 -14
  209. data/spec/models/sufia/permission_template_spec.rb +144 -0
  210. data/spec/models/sufia/user_usage_stats_spec.rb +8 -2
  211. data/spec/presenters/sufia/homepage_presenter_spec.rb +1 -1
  212. data/spec/presenters/sufia/select_type_list_presenter_spec.rb +26 -0
  213. data/spec/presenters/sufia/select_type_presenter_spec.rb +21 -0
  214. data/spec/search_builder/sufia/admin_set_search_builder_spec.rb +57 -0
  215. data/spec/search_builder/sufia/catalog_search_builder_spec.rb +40 -14
  216. data/spec/search_builder/sufia/find_works_search_builder_spec.rb +60 -0
  217. data/spec/search_builder/sufia/my_shares_search_builder_spec.rb +4 -1
  218. data/spec/search_builder/sufia/single_admin_set_search_builder_spec.rb +5 -1
  219. data/spec/services/sufia/actor_factory_spec.rb +13 -5
  220. data/spec/services/sufia/admin_set_create_service_spec.rb +27 -0
  221. data/spec/services/sufia/admin_set_service_spec.rb +104 -17
  222. data/spec/services/sufia/workflow/changes_required_notification_spec.rb +32 -0
  223. data/spec/services/sufia/workflow/complete_notification_spec.rb +32 -0
  224. data/spec/services/sufia/workflow/pending_review_notification_spec.rb +31 -0
  225. data/spec/services/sufia/workflow/workflow_by_admin_set_strategy_spec.rb +22 -0
  226. data/spec/spec_helper.rb +24 -5
  227. data/spec/support/proxies.rb +1 -1
  228. data/spec/test_app_templates/lib/generators/test_app_generator.rb +4 -0
  229. data/spec/views/_toolbar.html.erb_spec.rb +23 -6
  230. data/spec/views/batch_edits/edit.html.erb_spec.rb +7 -1
  231. data/spec/views/collections/_form_for_select_collection.html.erb_spec.rb +1 -3
  232. data/spec/views/curation_concerns/base/_find_work_widget.html.erb_spec.rb +22 -0
  233. data/spec/views/curation_concerns/base/_form.html.erb_spec.rb +7 -0
  234. data/spec/views/curation_concerns/base/_form_child_work_relationships.html.erb_spec.rb +1 -0
  235. data/spec/views/curation_concerns/base/_form_parent_work_relationships.html.erb_spec.rb +114 -0
  236. data/spec/views/curation_concerns/base/_form_progress.html.erb_spec.rb +3 -2
  237. data/spec/views/curation_concerns/base/_social_media.html.erb_spec.rb +1 -1
  238. data/spec/views/curation_concerns/base/edit.html.erb_spec.rb +1 -1
  239. data/spec/views/curation_concerns/base/show.html.erb_spec.rb +5 -1
  240. data/spec/views/curation_concerns/file_sets/_show_actions.html.erb_spec.rb +2 -2
  241. data/spec/views/dashboard/create_work_action.html.erb_spec.rb +27 -0
  242. data/spec/views/dashboard/index_spec.rb +7 -2
  243. data/spec/views/my/_sort_and_per_page.html.erb_spec.rb +33 -0
  244. data/spec/views/shared/select_work_type_modal.html.erb_spec.rb +32 -0
  245. data/spec/views/sufia/admin/admin_sets/_form.html.erb_spec.rb +18 -0
  246. data/spec/views/sufia/admin/admin_sets/_form_participants.html.erb_spec.rb +13 -0
  247. data/spec/views/sufia/admin/admin_sets/_form_visibility.html.erb_spec.rb +23 -0
  248. data/spec/views/sufia/batch_uploads/_form.html.erb_spec.rb +2 -12
  249. data/spec/views/sufia/homepage/index.html.erb_spec.rb +29 -8
  250. data/sufia.gemspec +5 -6
  251. data/tasks/sufia-dev.rake +6 -10
  252. data/template.rb +15 -0
  253. metadata +140 -28
  254. data/app/assets/stylesheets/sufia/widgets.css +0 -288
  255. data/app/helpers/sufia/citations_behaviors/formatters/endnote_formatter.rb +0 -49
  256. data/app/models/domain_term.rb +0 -4
  257. data/app/views/citations/file.html.erb +0 -0
  258. data/app/views/records/_rights_modal.html.erb +0 -1
  259. data/db/migrate/20160328222160_create_local_authorities.rb +0 -50
@@ -0,0 +1,9 @@
1
+ export default class {
2
+ constructor(elem) {
3
+ this.user = elem.find('#user-participants-form input[type=text]')
4
+ }
5
+
6
+ setup() {
7
+ this.user.userSearch();
8
+ }
9
+ }
@@ -0,0 +1,134 @@
1
+ export default class {
2
+ constructor(element) {
3
+ this.element = element
4
+ }
5
+
6
+ setup() {
7
+ // Watch for changes to "release_period" radio inputs
8
+ let releasePeriodInput = this.element.find("input[type='radio'][name$='[release_period]']")
9
+ $(releasePeriodInput).on('change', () => { this.releasePeriodSelected() })
10
+ this.releasePeriodSelected()
11
+
12
+ // Watch for changes to "release_varies" radio inputs
13
+ let releaseVariesInput = this.element.find("input[type='radio'][name$='[release_varies]']")
14
+ $(releaseVariesInput).on('change', () => { this.releaseVariesSelected() })
15
+ this.releaseVariesSelected()
16
+ }
17
+
18
+ // Based on the "release_period" radio selected, enable/disable other options
19
+ releasePeriodSelected() {
20
+ let selected = this.element.find("input[type='radio'][name$='[release_period]']:checked")
21
+
22
+ switch(selected.val()) {
23
+ // If "No Delay" (now) selected
24
+ case "now":
25
+ this.disableReleaseVariesOptions()
26
+ this.disableReleaseFixedDate()
27
+ this.enableVisibilityRestricted()
28
+ break;
29
+
30
+ // If "Varies" ("") selected
31
+ case "":
32
+ this.enableReleaseVariesRadio()
33
+ this.disableReleaseFixedDate()
34
+ this.disableVisibilityRestricted()
35
+ // Also check if a release "Varies" sub-option previously selected
36
+ this.releaseVariesSelected()
37
+ break;
38
+
39
+ // If "Fixed" selected
40
+ case "fixed":
41
+ this.disableReleaseVariesOptions()
42
+ this.enableReleaseFixedDate()
43
+ this.disableVisibilityRestricted()
44
+ break;
45
+
46
+ // Nothing selected
47
+ default:
48
+ this.disableReleaseVariesOptions()
49
+ this.disableReleaseFixedDate()
50
+ this.disableVisibilityRestricted()
51
+ }
52
+ }
53
+
54
+ // Based on the "release_varies" radio selected, enable/disable other options
55
+ releaseVariesSelected() {
56
+ let selected = this.element.find("input[type='radio'][name$='[release_varies]']:checked")
57
+
58
+ switch(selected.val()) {
59
+ // If before specific date selected
60
+ case "before":
61
+ this.enableReleaseVariesDate();
62
+ this.disableReleaseVariesSelect();
63
+ break;
64
+
65
+ // If embargo option selected
66
+ case "embargo":
67
+ this.disableReleaseVariesDate();
68
+ this.enableReleaseVariesSelect();
69
+ break;
70
+
71
+ // Nothing selected
72
+ default:
73
+ this.disableReleaseVariesDate();
74
+ this.disableReleaseVariesSelect();
75
+ }
76
+ }
77
+
78
+ // Disable ALL sub-options under "Varies"
79
+ disableReleaseVariesOptions() {
80
+ this.disableReleaseVariesRadio()
81
+ this.disableReleaseVariesSelect()
82
+ this.disableReleaseVariesDate()
83
+ }
84
+
85
+ // Disable all radio inputs under the release "Varies" option
86
+ disableReleaseVariesRadio() {
87
+ this.element.find("#release-varies input[type='radio'][name$='[release_varies]']").prop("disabled", true)
88
+ }
89
+
90
+ // Enable all radio inputs under the release "Varies" option
91
+ enableReleaseVariesRadio() {
92
+ this.element.find("#release-varies input[type='radio'][name$='[release_varies]']").prop("disabled", false)
93
+ }
94
+
95
+ // Disable selectbox next to release "Varies" embargo option
96
+ disableReleaseVariesSelect() {
97
+ this.element.find("#release-varies select[name$='[release_embargo]']").prop("disabled", true)
98
+ }
99
+
100
+ // Enable selectbox next to release "Varies" embargo option
101
+ enableReleaseVariesSelect() {
102
+ this.element.find("#release-varies select[name$='[release_embargo]']").prop("disabled", false)
103
+ }
104
+
105
+ // Disable date input field next to release "Varies" before option
106
+ disableReleaseVariesDate() {
107
+ this.element.find("#release-varies input[type='date'][name$='[release_date]']").prop("disabled", true)
108
+ }
109
+
110
+ // Enable date input field next to release "Varies" before option
111
+ enableReleaseVariesDate() {
112
+ this.element.find("#release-varies input[type='date'][name$='[release_date]']").prop("disabled", false)
113
+ }
114
+
115
+ // Disable date input field next to release "Fixed" option
116
+ disableReleaseFixedDate() {
117
+ this.element.find("#release-fixed input[type='date'][name$='[release_date]']").prop("disabled", true)
118
+ }
119
+
120
+ // Enable date input field next to release "Fixed" option
121
+ enableReleaseFixedDate() {
122
+ this.element.find("#release-fixed input[type='date'][name$='[release_date]']").prop("disabled", false)
123
+ }
124
+
125
+ // Disable visibility "Restricted" option (not valid for embargoes)
126
+ disableVisibilityRestricted() {
127
+ this.element.find("input[type='radio'][name$='[visibility]'][value='restricted']").prop("disabled", true)
128
+ }
129
+
130
+ // Enable visibility "Restricted" option
131
+ enableVisibilityRestricted() {
132
+ this.element.find("input[type='radio'][name$='[visibility]'][value='restricted']").prop("disabled", false)
133
+ }
134
+ }
@@ -0,0 +1,11 @@
1
+ export default class {
2
+ constructor(elem) {
3
+ let Participants = require('sufia/admin/admin_set/participants');
4
+ let participants = new Participants(elem.find('#participants'))
5
+ participants.setup();
6
+
7
+ let Visibility = require('sufia/admin/admin_set/visibility');
8
+ let visibilityTab = new Visibility(elem.find('#visibility'));
9
+ visibilityTab.setup();
10
+ }
11
+ }
@@ -9,13 +9,24 @@ Sufia = {
9
9
  this.permissions();
10
10
  this.notifications();
11
11
  this.transfers();
12
- this.relationships_table();
13
- this.file_manager_init();
12
+ this.relationshipsTable();
13
+ this.fileManager();
14
+ this.selectWorkType();
14
15
  this.datatable();
16
+ this.admin();
17
+ },
18
+
19
+ admin: function() {
20
+ var AdminSetControls = require('sufia/admin/admin_set_controls');
21
+ var controls = new AdminSetControls($('#admin-set-controls'));
15
22
  },
16
23
 
17
24
  datatable: function () {
18
- $('.datatable').DataTable();
25
+ // This keeps the datatable from being added to a table that already has it.
26
+ // This is a problem when turbolinks is active.
27
+ if ($('.dataTables_wrapper').size() === 0) {
28
+ $('.datatable').DataTable();
29
+ }
19
30
  },
20
31
 
21
32
  autocomplete: function () {
@@ -50,8 +61,12 @@ Sufia = {
50
61
 
51
62
  permissions: function () {
52
63
  var perm = require('sufia/permissions/control');
64
+ // On the edit work page
53
65
  new perm.PermissionsControl($("#share"), 'tmpl-work-grant');
66
+ // On the edit fileset page
54
67
  new perm.PermissionsControl($("#permission"), 'tmpl-file-set-grant');
68
+ // On the batch edit page
69
+ new perm.PermissionsControl($("#form_permissions"), 'tmpl-work-grant');
55
70
  },
56
71
 
57
72
  notifications: function () {
@@ -67,14 +82,21 @@ Sufia = {
67
82
  $("#proxy_deposit_request_transfer_to").userSearch();
68
83
  },
69
84
 
70
- relationships_table: function () {
85
+ relationshipsTable: function () {
71
86
  var rel = require('sufia/relationships/table');
72
87
  $('table.relationships-ajax-enabled').each(function () {
73
88
  new rel.RelationshipsTable($(this));
74
89
  });
75
90
  },
76
91
 
77
- file_manager_init: function () {
92
+ selectWorkType: function () {
93
+ var selectWork = require('sufia/select_work_type');
94
+ $("[data-behavior=select-work]").each(function () {
95
+ new selectWork($(this))
96
+ });
97
+ },
98
+
99
+ fileManager: function () {
78
100
  var fm = require('curation_concerns/file_manager');
79
101
  var file_manager = new fm
80
102
  },
@@ -16,6 +16,11 @@ export class Autocomplete {
16
16
  case "based_near":
17
17
  this.autocompleteLocation(selector);
18
18
  break;
19
+ case "work":
20
+ var user = selector.data('user');
21
+ var id = selector.data('id');
22
+ this.autocompleteWork(selector, user, id);
23
+ break;
19
24
  }
20
25
  });
21
26
  }
@@ -48,4 +53,14 @@ export class Autocomplete {
48
53
  var lang = require('sufia/autocomplete/language');
49
54
  new lang.Language(field, field.data('autocomplete-url'))
50
55
  }
56
+
57
+ autocompleteWork(field, user, id) {
58
+ var work = require('sufia/autocomplete/work')
59
+ new work.Work(
60
+ field,
61
+ field.data('autocomplete-url'),
62
+ user,
63
+ id
64
+ )
65
+ }
51
66
  }
@@ -0,0 +1,29 @@
1
+ export class Work {
2
+ // Autocomplete for finding possible related works (child and parent).
3
+ constructor(element, url, user, id) {
4
+ this.url = url;
5
+ this.user = user;
6
+ this.work_id = id;
7
+ element.autocomplete(this.options());
8
+ }
9
+
10
+ options() {
11
+ return {
12
+ minLength: 2,
13
+ source: ( request, response ) => {
14
+ $.getJSON(this.url, {
15
+ q: request.term,
16
+ id: this.work_id,
17
+ user: this.user
18
+ }, response );
19
+ },
20
+ focus: function() {
21
+ // prevent value inserted on focus
22
+ return false;
23
+ },
24
+ complete: function(event) {
25
+ $('.ui-autocomplete-loading').removeClass("ui-autocomplete-loading");
26
+ }
27
+ };
28
+ }
29
+ }
@@ -10,17 +10,15 @@ Blacklight.onLoad(function() {
10
10
  });
11
11
 
12
12
  function show_details(item) {
13
- var button = $(this);
14
- //button.id format: "expand_NNNNNNNNNN"
15
13
  var array = item.id.split("expand_");
16
14
  if (array.length > 1) {
17
15
  var docId = array[1];
18
16
  $("#detail_" + docId + " .expanded-details").slideToggle();
19
- button.toggleClass('glyphicon-chevron-right glyphicon-chevron-down');
17
+ $(item).toggleClass('glyphicon-chevron-right glyphicon-chevron-down');
20
18
  }
21
19
  }
22
20
 
23
- // show/hide more information on the dashboard when clicking
21
+ // show/hide more information on the dashboard when clicking
24
22
  // plus/minus
25
23
  $('.glyphicon-chevron-right').on('click', function() {
26
24
  show_details(this);
@@ -54,7 +54,19 @@ export class SaveWorkControl {
54
54
  }
55
55
 
56
56
  /**
57
- * Is the form for a new object (vs edit an exisiting object)
57
+ * Keep the form from being submitted while uploads are running
58
+ *
59
+ */
60
+ preventSubmitIfUploading() {
61
+ this.form.on('submit', (evt) => {
62
+ if (this.uploads.inProgress) {
63
+ evt.preventDefault()
64
+ }
65
+ })
66
+ }
67
+
68
+ /**
69
+ * Is the form for a new object (vs edit an existing object)
58
70
  */
59
71
  get isNew() {
60
72
  return this.form.attr('id').startsWith('new')
@@ -80,6 +92,7 @@ export class SaveWorkControl {
80
92
  new VisibilityComponent(this.element.find('.visibility'))
81
93
  this.preventSubmitUnlessValid()
82
94
  this.preventSubmitIfAlreadyInProgress()
95
+ this.preventSubmitIfUploading()
83
96
  $('.multi_value.form-group', this.form).bind('managed_field:add', () => this.formChanged())
84
97
  $('.multi_value.form-group', this.form).bind('managed_field:remove', () => this.formChanged())
85
98
  this.formChanged()
@@ -136,4 +149,3 @@ export class SaveWorkControl {
136
149
  return this.depositAgreement.isAccepted
137
150
  }
138
151
  }
139
-
@@ -1,8 +1,9 @@
1
1
  export class UploadedFiles {
2
- // Monitors the form and runs the callback if any files are added
2
+ // Monitors the form and runs the callback when files are added
3
3
  constructor(form, callback) {
4
4
  this.form = form
5
- $('#fileupload').bind('fileuploadcompleted', callback)
5
+ this.element = $('#fileupload')
6
+ this.element.bind('fileuploadcompleted', callback)
6
7
  }
7
8
 
8
9
  get hasFileRequirement() {
@@ -10,6 +11,10 @@ export class UploadedFiles {
10
11
  return fileRequirement.size() > 0
11
12
  }
12
13
 
14
+ get inProgress() {
15
+ return this.element.fileupload('active') > 0
16
+ }
17
+
13
18
  get hasFiles() {
14
19
  let fileField = this.form.find('input[name="uploaded_files[]"]')
15
20
  return fileField.size() > 0
@@ -1,27 +1,268 @@
1
1
  export class VisibilityComponent {
2
2
  constructor(element) {
3
3
  this.element = element
4
+ this.form = element.closest('form')
4
5
  $('.collapse').collapse({ toggle: false })
5
6
  element.find("[type='radio']").on('change', () => { this.showForm() })
6
7
  this.showForm()
8
+ this.limitByAdminSet()
7
9
  }
8
10
 
9
11
  showForm() {
10
- this.collapseAll()
11
12
  this.openSelected()
12
13
  }
13
14
 
15
+ // Collapse all Visibility sub-options
14
16
  collapseAll() {
15
17
  $('.collapse').collapse('hide');
16
18
  }
17
19
 
20
+ // Open the selected Visibility's sub-options, collapsing all others
18
21
  openSelected() {
19
22
  let selected = this.element.find("[type='radio']:checked")
20
23
 
21
24
  let target = selected.data('target')
22
- if (!target) {
23
- return
25
+
26
+ if(target) {
27
+ // Show the target suboption and hide all others
28
+ $('.collapse' + target).collapse('show');
29
+ $('.collapse:not(' + target + ')').collapse('hide');
30
+ }
31
+ else {
32
+ this.collapseAll()
33
+ }
34
+ }
35
+
36
+ // Limit visibility options based on selected AdminSet (if enabled)
37
+ limitByAdminSet() {
38
+ let adminSetInput = this.form.find('select[id$="_admin_set_id"]')
39
+ if(adminSetInput) {
40
+ $(adminSetInput).on('change', () => { this.restrictToVisibility(adminSetInput.find(":selected")) })
41
+ this.restrictToVisibility(adminSetInput.find(":selected"))
42
+ }
43
+ }
44
+
45
+ // Restrict visibility and/or release date to match the AdminSet requirements (if any)
46
+ restrictToVisibility(selected) {
47
+ // visibility requirement is in HTML5 'data-visibility' attr
48
+ let visibility = selected.data('visibility')
49
+ // release date requirement is in HTML5 'data-release-date' attr
50
+ let release_date = selected.data('release-date')
51
+ // if release_date is flexible (i.e. before date), then 'data-release-before-date' attr will be true
52
+ let release_before = selected.data('release-before-date')
53
+
54
+ // Restrictions require either a visibility requirement or a release_date requirement (or both)
55
+ if(visibility || release_date) {
56
+ this.applyRestrictions(visibility, release_date, release_before)
57
+ }
58
+ else {
59
+ this.enableAllOptions()
60
+ }
61
+ }
62
+
63
+ // Apply visibility/release restrictions based on selected AdminSet
64
+ applyRestrictions(visibility, release_date, release_before)
65
+ {
66
+ // If immediate release required and visibility specified
67
+ if(this.isToday(release_date) && visibility) {
68
+ // Select required visibility
69
+ this.selectVisibility(visibility)
70
+ }
71
+ else if(this.isToday(release_date)) {
72
+ // No visibility required, but must be released today. Disable embargo & lease.
73
+ this.disableEmbargoAndLease();
74
+ }
75
+ // Otherwise if future date and release_before==true, must be released between today and release_date
76
+ else if(release_date && release_before) {
77
+ this.enableReleaseNowOrEmbargo(visibility, release_date, release_before)
78
+ }
79
+ // Otherwise if future date and release_before==false, this is a required embargo (must be released on specific future date)
80
+ else if(release_date) {
81
+ this.requireEmbargo(visibility, release_date)
82
+ }
83
+ // If nothing above matched, then there's no release date required. So, release now or embargo is fine
84
+ else {
85
+ this.enableReleaseNowOrEmbargo(visibility, release_date, release_before)
86
+ }
87
+ }
88
+
89
+ // Select given visibility option. All others disabled.
90
+ selectVisibility(visibility) {
91
+ this.element.find("[type='radio'][value='" + visibility + "']").prop("checked", true).prop("disabled", false)
92
+ this.element.find("[type='radio'][value!='" + visibility + "']").prop("disabled", true)
93
+ // Ensure required option is opened in form
94
+ this.showForm()
95
+ }
96
+
97
+ // Allow for immediate release or embargo, based on visibility settings (if any)
98
+ enableReleaseNowOrEmbargo(visibility, release_date, release_before) {
99
+ if(visibility) {
100
+ // Enable ONLY the allowable visibility options (specified visibility or embargo)
101
+ this.enableVisibilityOptions([visibility, "embargo"])
102
+ }
103
+ else {
104
+ // Allow all visibility options EXCEPT lease
105
+ this.disableVisibilityOptions(["lease"])
106
+ }
107
+
108
+ // Limit valid embargo release dates
109
+ this.restrictEmbargoDate(release_date, release_before)
110
+
111
+ // Select Visibility after embargo (if any)
112
+ this.selectVisibilityAfterEmbargo(visibility)
113
+ }
114
+
115
+ // Require a specific embargo date (and possibly also specific visibility)
116
+ requireEmbargo(visibility, release_date) {
117
+ // This a required embargo date
118
+ this.selectVisibility("embargo")
119
+
120
+ // Limit valid embargo release dates
121
+ this.restrictEmbargoDate(release_date, false)
122
+
123
+ // Select Visibility after embargo (if any)
124
+ this.selectVisibilityAfterEmbargo(visibility)
125
+ }
126
+
127
+ // Disable Embargo and Lease options. Work must be released immediately
128
+ disableEmbargoAndLease() {
129
+ this.disableVisibilityOptions(["embargo","lease"])
130
+ }
131
+
132
+ // Enable one or more visibility option (based on array of passed in options),
133
+ // disabling all other options
134
+ enableVisibilityOptions(options) {
135
+ let matchEnabled = this.getMatcherForVisibilities(options)
136
+ let matchDisabled = this.getMatcherForNotVisibilities(options)
137
+
138
+ // Enable all that match "matchEnabled" (if any), and disable those matching "matchDisabled"
139
+ if(matchEnabled) {
140
+ this.element.find(matchEnabled).prop("disabled", false)
141
+ }
142
+ this.element.find(matchDisabled).prop("disabled", true)
143
+ }
144
+
145
+ // Disable one or more visibility option (based on array of passed in options),
146
+ // disabling all other options
147
+ disableVisibilityOptions(options) {
148
+ let matchDisabled = this.getMatcherForVisibilities(options)
149
+ let matchEnabled = this.getMatcherForNotVisibilities(options)
150
+
151
+ // Disable those matching "matchDisabled" (if any), and enable all that match "matchEnabled"
152
+ if(matchDisabled) {
153
+ this.element.find(matchDisabled).prop("disabled", true)
154
+ }
155
+ this.element.find(matchEnabled).prop("disabled", false)
156
+ }
157
+
158
+ // Create a jQuery matcher which will match for all the specified options
159
+ // (expects an array of options).
160
+ // This creates a logical OR matcher, whose format looks like:
161
+ // "[type='radio'][value='one'],[type='radio'][value='two']"
162
+ getMatcherForVisibilities(options) {
163
+ let initialMatcher = "[type='radio']"
164
+ let matcher = ""
165
+ // Loop through specified visibility options, creating a logical OR matcher
166
+ for(let i = 0; i < options.length; i++) {
167
+ if(i > 0) {
168
+ matcher += ","
169
+ }
170
+ matcher += initialMatcher + "[value='" + options[i] + "']"
24
171
  }
25
- $(target).collapse('show');
172
+ return matcher
173
+ }
174
+
175
+ // Create a jQuery matcher which will match all options EXCEPT the specified options
176
+ // (expects an array of options).
177
+ // This creates a logical AND NOT matcher, whose format looks like:
178
+ // "[type='radio'][value!='one'][value!='two']"
179
+ getMatcherForNotVisibilities(options) {
180
+ let initialMatcher = "[type='radio']"
181
+ let matcher = initialMatcher
182
+ // Loop through specified visibility options, creating a logical AND NOT matcher
183
+ for(let i = 0; i < options.length; i++) {
184
+ matcher += "[value!='" + options[i] + "']"
185
+ }
186
+ return matcher
187
+ }
188
+
189
+ // Based on release_date/release_before, limit valid options for embargo date
190
+ // * release_date is a date of format YYYY-MM-DD
191
+ // * release_before is true if dates before release_date are allowabled, false otherwise.
192
+ restrictEmbargoDate(release_date, release_before) {
193
+ let embargoDateInput = this.getEmbargoDateInput()
194
+ // Dates before today are not valid
195
+ embargoDateInput.prop("min", this.getToday());
196
+
197
+ if(release_date) {
198
+ // Dates AFTER release_date are not valid
199
+ embargoDateInput.prop("max", release_date);
200
+ }
201
+ else {
202
+ embargoDateInput.prop("max", "");
203
+ }
204
+
205
+ // If release before dates are NOT allowed, set exact embargo date and disable field
206
+ if(release_date && !release_before) {
207
+ embargoDateInput.val(release_date)
208
+ embargoDateInput.prop("disabled", true)
209
+ }
210
+ else {
211
+ embargoDateInput.prop("disabled", false)
212
+ }
213
+ }
214
+
215
+ // Based on embargo visibility, select required visibility (if any)
216
+ selectVisibilityAfterEmbargo(visibility) {
217
+ let visibilityInput = this.getVisibilityAfterEmbargoInput()
218
+ // If a visibility is required, select it and disable field
219
+ if(visibility) {
220
+ visibilityInput.find("option[value='" + visibility + "']").prop("selected", true)
221
+ visibilityInput.prop("disabled", true)
222
+ }
223
+ else {
224
+ visibilityInput.prop("disabled", false)
225
+ }
226
+ }
227
+
228
+ // Ensure all visibility options are enabled
229
+ enableAllOptions() {
230
+ this.element.find("[type='radio']").prop("disabled", false)
231
+ this.getEmbargoDateInput().prop("disabled", false)
232
+ this.getVisibilityAfterEmbargoInput().prop("disabled", false)
233
+ }
234
+
235
+ // Get input field corresponding to embargo date
236
+ getEmbargoDateInput() {
237
+ return this.element.find("[type='date'][id$='_embargo_release_date']")
238
+ }
239
+
240
+ // Get input field corresponding to visibility after embargo expires
241
+ getVisibilityAfterEmbargoInput() {
242
+ return this.element.find("select[id$='_visibility_after_embargo']")
243
+ }
244
+
245
+ // Get today's date in YYYY-MM-DD format
246
+ getToday() {
247
+ let today = new Date()
248
+ let dd = today.getDate()
249
+ let mm = today.getMonth() + 1 // January is month 0
250
+ let yyyy = today.getFullYear()
251
+
252
+ // prepend zeros as needed
253
+ if(dd < 10) {
254
+ dd = '0' + dd
255
+ }
256
+ if(mm < 10) {
257
+ mm = '0' + mm
258
+ }
259
+ return yyyy + '-' + mm + '-' + dd
260
+ }
261
+
262
+ // Return true if datestring represents today's date
263
+ isToday(dateString) {
264
+ let today = new Date(this.getToday())
265
+ let date = new Date(dateString)
266
+ return date.getTime() === today.getTime()
26
267
  }
27
268
  }