blacklight-spotlight 5.3.2 → 6.0.0.rc2

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -4
  3. data/Rakefile +1 -2
  4. data/app/assets/javascripts/spotlight/spotlight.esm.js +2168 -4560
  5. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
  6. data/app/assets/javascripts/spotlight/spotlight.js +2167 -4559
  7. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
  8. data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +4 -0
  9. data/app/assets/stylesheets/spotlight/_browse.scss +0 -4
  10. data/app/assets/stylesheets/spotlight/{_collapse_toggle.scss → _collapse_toggle.css} +2 -2
  11. data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +8 -0
  12. data/app/assets/stylesheets/spotlight/_exhibits_index.scss +2 -1
  13. data/app/assets/stylesheets/spotlight/_footer.scss +2 -2
  14. data/app/assets/stylesheets/spotlight/_header.scss +8 -8
  15. data/app/assets/stylesheets/spotlight/_pages.scss +1 -1
  16. data/app/assets/stylesheets/spotlight/_slideshow_block.scss +15 -0
  17. data/app/assets/stylesheets/spotlight/_spotlight.scss +1 -1
  18. data/app/assets/stylesheets/spotlight/_translations.scss +3 -3
  19. data/app/assets/stylesheets/spotlight/_uploaded_items_block.css +7 -0
  20. data/app/assets/stylesheets/spotlight/_variables.css +15 -0
  21. data/app/assets/stylesheets/spotlight/browse_group_categories_block.scss +0 -76
  22. data/app/components/blacklight/icons/pause_component.rb +15 -0
  23. data/app/components/blacklight/icons/play_arrow_component.rb +15 -0
  24. data/app/components/spotlight/analytics/dashboard_component.html.erb +1 -1
  25. data/app/components/spotlight/custom_field_form_group_component.rb +40 -0
  26. data/app/components/spotlight/document_admin_table_component.html.erb +2 -2
  27. data/app/components/spotlight/edit_sidecar_component.html.erb +18 -0
  28. data/app/components/spotlight/edit_sidecar_component.rb +41 -0
  29. data/app/components/spotlight/masthead_component.html.erb +18 -0
  30. data/app/components/spotlight/masthead_component.rb +46 -0
  31. data/app/components/spotlight/save_search_component.html.erb +1 -1
  32. data/app/components/spotlight/sidecar_form_field_component.html.erb +18 -0
  33. data/app/components/spotlight/sidecar_form_field_component.rb +71 -0
  34. data/app/components/spotlight/solr_document_legacy_embed_component.html.erb +0 -4
  35. data/app/components/spotlight/solr_document_legacy_embed_component.rb +2 -2
  36. data/app/components/spotlight/tag_selector_component.html.erb +1 -1
  37. data/app/components/spotlight/tag_selector_component.rb +3 -2
  38. data/app/components/spotlight/upload_field_form_group_component.rb +33 -0
  39. data/app/controllers/concerns/spotlight/controller.rb +15 -14
  40. data/app/controllers/concerns/spotlight/search_helper.rb +2 -5
  41. data/app/controllers/spotlight/browse_controller.rb +1 -6
  42. data/app/controllers/spotlight/catalog_controller.rb +2 -3
  43. data/app/controllers/spotlight/concerns/application_controller.rb +4 -6
  44. data/app/controllers/spotlight/exhibits_controller.rb +22 -10
  45. data/app/controllers/spotlight/lock_controller.rb +1 -1
  46. data/app/controllers/spotlight/pages_controller.rb +11 -11
  47. data/app/controllers/spotlight/resources/upload_controller.rb +1 -1
  48. data/app/controllers/spotlight/resources_controller.rb +1 -1
  49. data/app/controllers/spotlight/solr_controller.rb +5 -1
  50. data/app/helpers/spotlight/application_helper.rb +14 -26
  51. data/app/helpers/spotlight/crud_link_helpers.rb +0 -12
  52. data/app/helpers/spotlight/main_app_helpers.rb +2 -2
  53. data/app/javascript/spotlight/admin/add_another.js +37 -25
  54. data/app/javascript/spotlight/admin/add_image_selector.js +43 -26
  55. data/app/javascript/spotlight/admin/add_new_button.js +51 -36
  56. data/app/javascript/spotlight/admin/blacklight_configuration.js +76 -54
  57. data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +102 -101
  58. data/app/javascript/spotlight/admin/block_mixins/formable.js +91 -75
  59. data/app/javascript/spotlight/admin/block_mixins/plustextable.js +46 -48
  60. data/app/javascript/spotlight/admin/blocks/block.js +27 -28
  61. data/app/javascript/spotlight/admin/blocks/browse_block.js +14 -10
  62. data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -10
  63. data/app/javascript/spotlight/admin/blocks/pages_block.js +5 -4
  64. data/app/javascript/spotlight/admin/blocks/resources_block.js +61 -41
  65. data/app/javascript/spotlight/admin/blocks/search_result_block.js +24 -7
  66. data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +103 -50
  67. data/app/javascript/spotlight/admin/blocks/solr_documents_carousel_block.js +50 -26
  68. data/app/javascript/spotlight/admin/blocks/solr_documents_features_block.js +47 -23
  69. data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +35 -19
  70. data/app/javascript/spotlight/admin/crop.js +146 -66
  71. data/app/javascript/spotlight/admin/croppable.js +5 -4
  72. data/app/javascript/spotlight/admin/croppable_modal.js +67 -32
  73. data/app/javascript/spotlight/admin/edit_in_place.js +69 -54
  74. data/app/javascript/spotlight/admin/exhibits.js +92 -45
  75. data/app/javascript/spotlight/admin/form_observer.js +92 -78
  76. data/app/javascript/spotlight/admin/multi_image_selector.js +201 -153
  77. data/app/javascript/spotlight/admin/pages.js +13 -7
  78. data/app/javascript/spotlight/admin/progress_monitor.js +65 -50
  79. data/app/javascript/spotlight/admin/readonly_checkbox.js +7 -3
  80. data/app/javascript/spotlight/admin/search_typeahead.js +20 -11
  81. data/app/javascript/spotlight/admin/select_related_input.js +23 -23
  82. data/app/javascript/spotlight/admin/serialize_json.js +120 -0
  83. data/app/javascript/spotlight/admin/sir-trevor/block_controls.js +24 -11
  84. data/app/javascript/spotlight/admin/sir-trevor/block_limits.js +9 -6
  85. data/app/javascript/spotlight/admin/sir-trevor/locales.js +2 -2
  86. data/app/javascript/spotlight/admin/spotlight_nestable.js +2 -5
  87. data/app/javascript/spotlight/admin/translation_progress.js +18 -13
  88. data/app/javascript/spotlight/admin/users.js +151 -64
  89. data/app/javascript/spotlight/user/carousel.js +104 -32
  90. data/app/javascript/spotlight/user/clear_form_button.js +24 -14
  91. data/app/javascript/spotlight/user/index.js +0 -2
  92. data/app/javascript/spotlight/user/zpr_links.js +99 -40
  93. data/app/jobs/concerns/spotlight/gather_documents.rb +1 -1
  94. data/app/jobs/spotlight/add_uploads_from_csv.rb +31 -8
  95. data/app/jobs/spotlight/cleanup_job_trackers_job.rb +5 -3
  96. data/app/models/concerns/spotlight/access_controls_enforcement_search_builder.rb +13 -2
  97. data/app/models/concerns/spotlight/browse_category_search_builder.rb +3 -3
  98. data/app/models/concerns/spotlight/exhibit_documents.rb +2 -2
  99. data/app/models/concerns/spotlight/sitemap.rb +2 -2
  100. data/app/models/concerns/spotlight/solr_document/finder.rb +2 -2
  101. data/app/models/concerns/spotlight/solr_document.rb +1 -47
  102. data/app/models/sir_trevor_rails/blocks/browse_block.rb +0 -4
  103. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +2 -1
  104. data/app/models/spotlight/blacklight_configuration.rb +5 -3
  105. data/app/models/spotlight/contact_email.rb +2 -2
  106. data/app/models/spotlight/custom_field.rb +17 -0
  107. data/app/models/spotlight/exhibit.rb +28 -0
  108. data/app/models/spotlight/featured_image.rb +1 -1
  109. data/app/models/spotlight/field_metadata.rb +10 -5
  110. data/app/models/spotlight/job_tracker.rb +0 -18
  111. data/app/models/spotlight/main_navigation.rb +2 -2
  112. data/app/models/spotlight/page.rb +3 -3
  113. data/app/models/spotlight/resources/iiif_harvester.rb +7 -4
  114. data/app/models/spotlight/resources/iiif_manifest.rb +0 -4
  115. data/app/models/spotlight/resources/iiif_manifest_metadata.rb +1 -3
  116. data/app/models/spotlight/resources/iiif_service.rb +21 -6
  117. data/app/models/spotlight/resources/upload.rb +6 -0
  118. data/app/models/spotlight/search.rb +5 -9
  119. data/app/models/spotlight/solr_document_sidecar.rb +18 -0
  120. data/app/services/spotlight/bulk_updates_csv_template_service.rb +1 -1
  121. data/app/services/spotlight/etl/pipeline.rb +2 -2
  122. data/app/services/spotlight/etl/step.rb +2 -2
  123. data/app/views/catalog/_remove_tags.html.erb +2 -2
  124. data/app/views/layouts/spotlight/base.html.erb +3 -6
  125. data/app/views/layouts/spotlight/spotlight.html.erb +2 -2
  126. data/app/views/shared/_analytics.html.erb +4 -3
  127. data/app/views/shared/_masthead.html.erb +2 -18
  128. data/app/views/spotlight/about_pages/_empty.html.erb +1 -1
  129. data/app/views/spotlight/about_pages/_sidebar.html.erb +10 -8
  130. data/app/views/spotlight/browse/_search.html.erb +2 -2
  131. data/app/views/spotlight/browse/_search_box.html.erb +6 -14
  132. data/app/views/spotlight/browse/index.html.erb +1 -1
  133. data/app/views/spotlight/browse/show.html.erb +1 -1
  134. data/app/views/spotlight/catalog/_document_admin_table.html.erb +1 -1
  135. data/app/views/spotlight/catalog/_edit_default.html.erb +1 -1
  136. data/app/views/spotlight/catalog/edit.html.erb +1 -1
  137. data/app/views/spotlight/dashboards/_page.html.erb +1 -1
  138. data/app/views/spotlight/exhibits/_exhibit_card.html.erb +3 -1
  139. data/app/views/spotlight/exhibits/_export.html.erb +17 -1
  140. data/app/views/spotlight/exhibits/_form.html.erb +20 -4
  141. data/app/views/spotlight/exhibits/_missing_exhibits.html.erb +3 -3
  142. data/app/views/spotlight/exhibits/index.html.erb +21 -8
  143. data/app/views/spotlight/feature_pages/_empty.html.erb +1 -1
  144. data/app/views/spotlight/feature_pages/_sidebar.html.erb +17 -15
  145. data/app/views/spotlight/home_pages/_empty.html.erb +7 -7
  146. data/app/views/spotlight/pages/show.html.erb +1 -0
  147. data/app/views/spotlight/resources/upload/_form.html.erb +2 -2
  148. data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +5 -16
  149. data/app/views/spotlight/sir_trevor/blocks/_embedded_document.html.erb +3 -5
  150. data/app/views/spotlight/sir_trevor/blocks/_link_to_search_block.html.erb +1 -1
  151. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +11 -2
  152. data/app/views/spotlight/sites/_exhibit.html.erb +1 -1
  153. data/config/i18n-tasks.yml +1 -1
  154. data/config/locales/spotlight.ar.yml +1 -2
  155. data/config/locales/spotlight.de.yml +1 -2
  156. data/config/locales/spotlight.en.yml +39 -10
  157. data/config/locales/spotlight.es.yml +1 -2
  158. data/config/locales/spotlight.fr.yml +1 -2
  159. data/config/locales/spotlight.it.yml +1 -2
  160. data/config/locales/spotlight.ja.yml +39 -0
  161. data/config/locales/spotlight.zh.yml +1 -2
  162. data/db/migrate/20261007133748_add_discovery_enabled_to_spotlight_exhibits.rb +5 -0
  163. data/lib/generators/spotlight/assets/importmap_generator.rb +2 -10
  164. data/lib/generators/spotlight/assets/propshaft_generator.rb +5 -4
  165. data/lib/generators/spotlight/install_generator.rb +2 -4
  166. data/lib/generators/spotlight/templates/catalog_controller.rb +0 -1
  167. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +26 -4
  168. data/lib/generators/spotlight/templates/solr/conf/schema.xml +4 -3
  169. data/lib/generators/spotlight/templates/solr/conf/solrconfig.xml +3 -8
  170. data/lib/migration/page_language.rb +0 -2
  171. data/lib/spotlight/engine.rb +28 -9
  172. data/lib/spotlight/search_state.rb +7 -11
  173. data/lib/spotlight/upload_field_config.rb +19 -1
  174. data/lib/spotlight/version.rb +1 -1
  175. data/lib/spotlight.rb +1 -1
  176. data/spec/support/features/capybara_wait_metadata_helper.rb +3 -1
  177. data/spec/support/features/test_features_helpers.rb +24 -1
  178. data/spec/support/iiif_manifest_fixtures.rb +33 -0
  179. data/spec/support/stub_dns_resolution.rb +12 -0
  180. metadata +50 -80
  181. data/app/assets/stylesheets/spotlight/_uploaded_items_block.scss +0 -7
  182. data/app/assets/stylesheets/spotlight/_variables.scss +0 -13
  183. data/app/components/blacklight/icons/arrow_alt_circle_left_component.rb +0 -15
  184. data/app/components/blacklight/icons/arrow_alt_circle_right_component.rb +0 -15
  185. data/app/components/blacklight/icons/info_component.rb +0 -15
  186. data/app/components/blacklight/icons/zoom_in_component.rb +0 -15
  187. data/app/components/blacklight/icons/zoom_out_component.rb +0 -15
  188. data/app/components/spotlight/icon_component.rb +0 -13
  189. data/app/javascript/spotlight/user/browse_group_categories.js +0 -54
  190. data/app/mailers/spotlight/invitation_mailer.rb +0 -21
  191. data/app/models/concerns/spotlight/resources/web.rb +0 -38
  192. data/app/services/spotlight/iiif_resource_resolver.rb +0 -78
  193. data/app/views/catalog/_image_default.html.erb +0 -6
  194. data/app/views/shared/_exhibit_navbar.html.erb +0 -2
  195. data/app/views/shared/_header_navbar.html.erb +0 -6
  196. data/app/views/spotlight/catalog/_admin_index_header_default.html.erb +0 -23
  197. data/app/views/spotlight/catalog/_admin_thumbnail_default.html.erb +0 -7
  198. data/app/views/spotlight/catalog/_curation_mode_toggle_default.html.erb +0 -1
  199. data/app/views/spotlight/catalog/_document_row.html.erb +0 -2
  200. data/app/views/spotlight/catalog/_edit_sidecar.html.erb +0 -24
  201. data/app/views/spotlight/catalog/_index_compact_default.html.erb +0 -21
  202. data/app/views/spotlight/custom_fields/form_group/_text.html.erb +0 -23
  203. data/app/views/spotlight/custom_fields/form_group/_vocab.html.erb +0 -23
  204. data/app/views/spotlight/invitation_mailer/exhibit_invitation_notification.html.erb +0 -12
  205. data/lib/generators/spotlight/templates/javascript/jquery-shim.js +0 -1
  206. data/vendor/assets/javascripts/tiny-slider.js +0 -3221
  207. data/vendor/assets/stylesheets/tiny-slider.css +0 -1
  208. /data/app/assets/stylesheets/spotlight/{_breadcrumbs.scss → _breadcrumbs.css} +0 -0
  209. /data/app/assets/stylesheets/spotlight/{_croppable.scss → _croppable.css} +0 -0
  210. /data/app/assets/stylesheets/spotlight/{_modals.scss → _modals.css} +0 -0
  211. /data/app/assets/stylesheets/spotlight/{_utilities.scss → _utilities.css} +0 -0
@@ -7,7 +7,7 @@ function highlight(value, query) {
7
7
  const queryValue = query.trim()
8
8
  return queryValue
9
9
  ? value.replace(new RegExp(queryValue, "gi"), "<strong>$&</strong>")
10
- : value
10
+ : ""
11
11
  }
12
12
 
13
13
  function templateFunc(obj, query) {
@@ -49,13 +49,18 @@ async function fetchResult(url) {
49
49
  }
50
50
 
51
51
  export function addAutocompletetoFeaturedImage() {
52
- const autocompletePath = $(
52
+ const autocompletePathElement = document.querySelector(
53
53
  "form[data-autocomplete-exhibit-catalog-path]",
54
- ).data("autocomplete-exhibit-catalog-path")
55
- const featuredImageTypeaheads = $("[data-featured-image-typeahead]")
54
+ )
55
+ const autocompletePath =
56
+ autocompletePathElement &&
57
+ autocompletePathElement.dataset.autocompleteExhibitCatalogPath
58
+ const featuredImageTypeaheads = document.querySelectorAll(
59
+ "[data-featured-image-typeahead]",
60
+ )
56
61
  if (featuredImageTypeaheads.length === 0) return
57
62
 
58
- $.each(featuredImageTypeaheads, function (index, autoCompleteInput) {
63
+ featuredImageTypeaheads.forEach((autoCompleteInput) => {
59
64
  const autoCompleteElement = autoCompleteInput.closest("auto-complete")
60
65
 
61
66
  autoCompleteElement.setAttribute("src", autocompletePath)
@@ -66,12 +71,16 @@ export function addAutocompletetoFeaturedImage() {
66
71
  )
67
72
  if (!data) return
68
73
 
69
- const inputElement = $(e.relatedTarget)
70
- const panel = document.querySelector(e.relatedTarget.dataset.targetPanel)
71
- e.relatedTarget.value = data.title
72
- addImageSelector(inputElement, $(panel), data.iiif_manifest, true)
73
- $(inputElement.data("id-field")).val(data["global_id"])
74
- inputElement.attr("type", "text")
74
+ const inputElement = e.relatedTarget
75
+ const panel = document.querySelector(inputElement.dataset.targetPanel)
76
+ inputElement.value = data.title
77
+ addImageSelector(inputElement, panel, data.iiif_manifest, true)
78
+ const idFieldSelector = inputElement.dataset.idField
79
+ const idField = document.querySelector(idFieldSelector)
80
+ if (idField) {
81
+ idField.value = data["global_id"]
82
+ }
83
+ inputElement.setAttribute("type", "text")
75
84
  })
76
85
  })
77
86
  }
@@ -1,37 +1,37 @@
1
1
  /*
2
- Simple plugin to select form elements
2
+ Simple helper to select form elements
3
3
  when other elements are clicked.
4
4
  */
5
- ;(function ($) {
6
- $.fn.selectRelatedInput = function () {
7
- var clickElements = this
5
+ export function selectRelatedInput(elements) {
6
+ if (!elements) return
8
7
 
9
- $(clickElements).each(function () {
10
- var target = $($(this).data("input-select-target"))
8
+ const nodes =
9
+ elements instanceof NodeList || Array.isArray(elements)
10
+ ? Array.from(elements)
11
+ : [elements]
11
12
 
12
- var event
13
+ nodes.forEach(function (element) {
14
+ if (!element) return
15
+ const targetSelector = element.getAttribute("data-input-select-target")
16
+ if (!targetSelector) return
17
+ const target = document.querySelector(targetSelector)
18
+ if (!target) return
13
19
 
14
- if ($(this).is("select")) {
15
- event = "change"
20
+ const event =
21
+ element.tagName.toLowerCase() === "select" ? "change" : "click"
22
+
23
+ element.addEventListener(event, function () {
24
+ if (target.type === "checkbox" || target.type === "radio") {
25
+ target.checked = true
16
26
  } else {
17
- event = "click"
27
+ target.focus()
18
28
  }
19
-
20
- $(this).on(event, function () {
21
- if (target.is(":checkbox") || target.is(":radio")) {
22
- target.prop("checked", true)
23
- } else {
24
- target.focus()
25
- }
26
- })
27
29
  })
28
-
29
- return this
30
- }
31
- })(jQuery)
30
+ })
31
+ }
32
32
 
33
33
  export default class {
34
34
  connect() {
35
- $("[data-input-select-target]").selectRelatedInput()
35
+ selectRelatedInput(document.querySelectorAll("[data-input-select-target]"))
36
36
  }
37
37
  }
@@ -0,0 +1,120 @@
1
+ // Vanilla JavaScript port of the default behavior of jquery.serializeJSON (v3.2.1).
2
+ // Serializes form elements with bracket-notation names (e.g. "item[0][title]")
3
+ // into a nested JavaScript object. Accepts a NodeList/array of elements.
4
+
5
+ var rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i
6
+ var rcheckableType = /^(?:checkbox|radio)$/i
7
+
8
+ function splitInputNameIntoKeysArray(name) {
9
+ var keys = name.split("[")
10
+ keys = keys.map(function (key) {
11
+ return key.replace(/\]/g, "")
12
+ })
13
+ if (keys[0] === "") {
14
+ keys.shift()
15
+ }
16
+ return keys
17
+ }
18
+
19
+ function deepGet(o, keys) {
20
+ if (
21
+ o === undefined ||
22
+ keys === undefined ||
23
+ keys.length === 0 ||
24
+ typeof o !== "object"
25
+ ) {
26
+ return o
27
+ }
28
+ var key = keys[0]
29
+ if (key === "") return undefined
30
+ if (keys.length === 1) return o[key]
31
+ return deepGet(o[key], keys.slice(1))
32
+ }
33
+
34
+ function deepSet(o, keys, value) {
35
+ if (keys.length === 0) return
36
+
37
+ var key = keys[0]
38
+
39
+ if (keys.length === 1) {
40
+ if (key === "") {
41
+ o.push(value)
42
+ } else {
43
+ o[key] = value
44
+ }
45
+ return
46
+ }
47
+
48
+ var nextKey = keys[1]
49
+ var tailKeys = keys.slice(1)
50
+
51
+ if (key === "") {
52
+ var lastIdx = o.length - 1
53
+ var lastVal = o[lastIdx]
54
+
55
+ if (
56
+ typeof lastVal === "object" &&
57
+ lastVal !== null &&
58
+ deepGet(lastVal, tailKeys) === undefined
59
+ ) {
60
+ key = lastIdx
61
+ } else {
62
+ key = lastIdx + 1
63
+ }
64
+ }
65
+
66
+ if (nextKey === "") {
67
+ if (o[key] === undefined || !Array.isArray(o[key])) {
68
+ o[key] = []
69
+ }
70
+ } else {
71
+ if (o[key] === undefined || typeof o[key] !== "object" || o[key] === null) {
72
+ o[key] = {}
73
+ }
74
+ }
75
+
76
+ deepSet(o[key], tailKeys, value)
77
+ }
78
+
79
+ function elementValue(el) {
80
+ var nodeName = el.nodeName.toLowerCase()
81
+ if (nodeName === "select" && el.multiple) {
82
+ var values = []
83
+ Array.prototype.forEach.call(el.options, function (opt) {
84
+ if (opt.selected) values.push(opt.value)
85
+ })
86
+ return values
87
+ }
88
+ return el.value
89
+ }
90
+
91
+ export default function serializeJSON(elements) {
92
+ var data = {}
93
+
94
+ Array.prototype.forEach.call(elements, function (el) {
95
+ if (!el.name) return
96
+ if (el.disabled) return
97
+
98
+ var type = el.type || ""
99
+ var nodeName = el.nodeName.toLowerCase()
100
+
101
+ if (nodeName === "input" && rsubmitterTypes.test(type)) return
102
+ if (rcheckableType.test(type) && !el.checked) return
103
+
104
+ var val = elementValue(el)
105
+ if (val == null) return
106
+
107
+ var assign = function (v) {
108
+ var value = String(v).replace(/\r?\n/g, "\r\n")
109
+ deepSet(data, splitInputNameIntoKeysArray(el.name), value)
110
+ }
111
+
112
+ if (Array.isArray(val)) {
113
+ val.forEach(assign)
114
+ } else {
115
+ assign(val)
116
+ }
117
+ })
118
+
119
+ return data
120
+ }
@@ -33,7 +33,7 @@ import Core from "spotlight/core"
33
33
  ) {
34
34
  var blockGroup
35
35
 
36
- if ($.isFunction(Blocks[type].prototype.blockGroup)) {
36
+ if (typeof Blocks[type].prototype.blockGroup === "function") {
37
37
  blockGroup = Blocks[type].prototype.blockGroup()
38
38
  } else {
39
39
  blockGroup = Blocks[type].prototype.blockGroup
@@ -52,16 +52,17 @@ import Core from "spotlight/core"
52
52
 
53
53
  function generateBlock(groups, key) {
54
54
  var group = groups[key]
55
- var groupEl = $(
56
- "<div class='st-controls-group'><div class='st-group-col-form-label'>" +
57
- key +
58
- "</div></div>",
59
- )
55
+ var groupEl = document.createElement("div")
56
+ groupEl.className = "st-controls-group"
57
+ var label = document.createElement("div")
58
+ label.className = "st-group-col-form-label"
59
+ label.textContent = key
60
+ groupEl.appendChild(label)
60
61
  var buttons = group.reduce(function (memo, btn) {
61
62
  return memo + btn
62
63
  }, "")
63
- groupEl.append(buttons)
64
- return groupEl[0].outerHTML
64
+ groupEl.insertAdjacentHTML("beforeend", buttons)
65
+ return groupEl.outerHTML
65
66
  }
66
67
 
67
68
  var standardWidgets = generateBlock(
@@ -94,6 +95,15 @@ import Core from "spotlight/core"
94
95
  return elButtons
95
96
  }
96
97
 
98
+ function delegate(root, selector, eventName, handler) {
99
+ root.addEventListener(eventName, function (e) {
100
+ var matcher = e.target.closest(selector)
101
+ if (matcher) {
102
+ handler.call(matcher, e)
103
+ }
104
+ })
105
+ }
106
+
97
107
  Core.BlockControls = function () {}
98
108
  Core.BlockControls.create = function (editor) {
99
109
  // REFACTOR - should probably not know about blockManager
@@ -122,12 +132,15 @@ import Core from "spotlight/core"
122
132
  if (!parent || hide() === parent) {
123
133
  return
124
134
  }
125
- $(".st-block__inner", parent).after(el)
135
+ var inner = parent.querySelector(".st-block__inner")
136
+ if (inner) {
137
+ inner.insertAdjacentElement("afterend", el)
138
+ }
126
139
  parent.classList.add("st-block--controls-active")
127
140
  }
128
141
 
129
- $(editor.wrapper).delegate(".st-block-replacer", "click", insert)
130
- $(editor.wrapper).delegate(".st-block-controls__button", "click", insert)
142
+ delegate(editor.wrapper, ".st-block-replacer", "click", insert)
143
+ delegate(editor.wrapper, ".st-block-controls__button", "click", insert)
131
144
 
132
145
  return {
133
146
  el: el,
@@ -18,12 +18,13 @@ Core.BlockLimits.prototype.checkBlockTypeLimitOnAdd = function () {
18
18
  var editor = this.editor
19
19
 
20
20
  return function (block) {
21
- var control = $(
21
+ var control = editor.blockControls.el.querySelector(
22
22
  ".st-block-controls__button[data-type='" + block.type + "']",
23
- editor.blockControls.el,
24
23
  )
25
24
 
26
- control.prop("disabled", !editor.blockManager.canCreateBlock(block.class()))
25
+ if (control) {
26
+ control.disabled = !editor.blockManager.canCreateBlock(block.class())
27
+ }
27
28
  }
28
29
  }
29
30
 
@@ -32,13 +33,15 @@ Core.BlockLimits.prototype.checkGlobalBlockTypeLimit = function () {
32
33
  var editor = this.editor
33
34
 
34
35
  return function () {
35
- $.each(editor.blockManager.blockTypes, function (i, type) {
36
+ editor.blockManager.blockTypes.forEach(function (type) {
36
37
  var block_type = SirTrevor.Blocks[type].prototype
37
38
 
38
- var control = $(editor.blockControls.el).find(
39
+ var control = editor.blockControls.el.querySelector(
39
40
  ".st-block-controls__button[data-type='" + block_type.type + "']",
40
41
  )
41
- control.prop("disabled", !editor.blockManager.canCreateBlock(type))
42
+ if (control) {
43
+ control.disabled = !editor.blockManager.canCreateBlock(type)
44
+ }
42
45
  })
43
46
  }
44
47
  }
@@ -1,4 +1,4 @@
1
- SirTrevor.Locales.en.blocks = $.extend(SirTrevor.Locales.en.blocks, {
1
+ SirTrevor.Locales.en.blocks = Object.assign(SirTrevor.Locales.en.blocks, {
2
2
  autocompleteable: {
3
3
  placeholder: "Enter a title...",
4
4
  },
@@ -14,7 +14,7 @@ SirTrevor.Locales.en.blocks = $.extend(SirTrevor.Locales.en.blocks, {
14
14
  autocomplete: "Enter a browse group title...",
15
15
  title: "Browse Group Categories",
16
16
  description:
17
- "This widget displays all browse categories associated with a selected browse group as a horizontally-scrolling row. Each selected browse group is displayed as a separate row. Each displayed category in a group links to the corresponding browse category results page.",
17
+ "This widget displays a limited number of browse categories from each selected browse group, with a link to view all categories in the group. Each selected group is displayed as a separate row. Each category links to the corresponding browse category results page.",
18
18
  item_counts: "Include category item counts?",
19
19
  },
20
20
 
@@ -37,7 +37,7 @@ const Module = (function () {
37
37
  nestedContainers = document.querySelectorAll(nestableContainerSelector)
38
38
  }
39
39
 
40
- // nestedContainers could be a jQuery selector result, normalize to an array.
40
+ // nestedContainers is a list of DOM nodes, normalize to an array.
41
41
  const containersToInit = Array.from(nestedContainers)
42
42
  containersToInit.forEach((container) => {
43
43
  // Sir Trevor listens for drag and drop events and will error on Sortable events.
@@ -167,10 +167,7 @@ const Module = (function () {
167
167
  )
168
168
  emptySortableElement.className = nestedSortableClass
169
169
  draggableElement.appendChild(emptySortableElement)
170
- new Sortable(emptySortableElement, {
171
- ...sortableOptions,
172
- group: group,
173
- })
170
+ new Sortable(emptySortableElement, { ...sortableOptions, group: group })
174
171
  }
175
172
  makeEmptyChildSortablesForEligibleParents(
176
173
  draggableElement,
@@ -4,19 +4,24 @@
4
4
  // present (indicated by data attributes) in each tab's content
5
5
  export default class {
6
6
  connect() {
7
- $('[data-behavior="translation-progress"]').each(function () {
8
- var currentTab = $(this)
9
- var tabName = $(this).attr("aria-controls")
10
- var translationFields = $("#" + tabName).find(
11
- '[data-translation-progress-item="true"]',
12
- )
13
- var completedTranslations = $("#" + tabName).find(
14
- '[data-translation-present="true"]',
15
- )
7
+ document
8
+ .querySelectorAll('[data-behavior="translation-progress"]')
9
+ .forEach(function (tab) {
10
+ var tabName = tab.getAttribute("aria-controls")
11
+ var tabContent = tabName && document.getElementById(tabName)
12
+ if (!tabContent) return
16
13
 
17
- currentTab
18
- .find("span")
19
- .text(completedTranslations.length + "/" + translationFields.length)
20
- })
14
+ var translationFields = tabContent.querySelectorAll(
15
+ '[data-translation-progress-item="true"]',
16
+ )
17
+ var completedTranslations = tabContent.querySelectorAll(
18
+ '[data-translation-present="true"]',
19
+ )
20
+
21
+ tab.querySelectorAll("span").forEach(function (span) {
22
+ span.textContent =
23
+ completedTranslations.length + "/" + translationFields.length
24
+ })
25
+ })
21
26
  }
22
27
  }
@@ -1,69 +1,156 @@
1
1
  export default class {
2
2
  connect() {
3
- var container
4
- function edit_user(event) {
5
- event.preventDefault()
6
- $(this).closest("tr").hide()
7
- const id = $(this).attr("data-target")
8
- const edit_view = $("[data-edit-for='" + id + "']", container).show()
9
- $.each(edit_view.find('input[type="text"], select'), function () {
10
- // Cache original values incase editing is canceled
11
- $(this).data("orig", $(this).val())
12
- })
13
- }
14
-
15
- function cancel_edit(event) {
16
- event.preventDefault()
17
- const id = $(this).closest("tr").attr("data-edit-for")
18
- const edit_view = $("[data-edit-for='" + id + "']", container).hide()
19
- clear_errors(edit_view)
20
- rollback_changes(edit_view)
21
- $("[data-show-for='" + id + "']", container).show()
22
- }
23
-
24
- function clear_errors(element) {
25
- element
26
- .find(".has-error")
27
- .removeClass("has-error")
28
- .find(".form-text")
29
- .remove() // Remove the error messages
30
- }
31
-
32
- function rollback_changes(element) {
33
- $.each(element.find('input[type="text"], select'), function () {
34
- $(this).val($(this).data("orig")).trigger("change")
35
- })
36
- }
37
-
38
- function destroy_user(_event) {
39
- const id = $(this).attr("data-target")
40
- $("[data-destroy-for='" + id + "']", container).val("1")
41
- }
42
-
43
- function new_user(event) {
44
- event.preventDefault()
45
- const edit_view = $("[data-edit-for='new']", container).show()
46
- $.each(edit_view.find('input[type="text"], select'), function () {
47
- // Cache original values incase editing is canceled
48
- $(this).data("orig", $(this).val())
3
+ document
4
+ .querySelectorAll(".edit_exhibit, .admin-users")
5
+ .forEach((container) => {
6
+ const edit_user = (event) => {
7
+ event.preventDefault()
8
+ const button = event.currentTarget
9
+ const row = button.closest("tr")
10
+ row.style.display = "none"
11
+
12
+ const id = button.getAttribute("data-target")
13
+ // Show ALL rows for this id (the fields row and the actions row)
14
+ container
15
+ .querySelectorAll(`[data-edit-for='${id}']`)
16
+ .forEach((edit_view) => {
17
+ edit_view.style.display = ""
18
+
19
+ // Cache original values in case editing is canceled
20
+ edit_view
21
+ .querySelectorAll('input[type="text"], select')
22
+ .forEach((input) => {
23
+ input.dataset.orig = input.value
24
+ })
25
+ })
26
+ }
27
+
28
+ const cancel_edit = (event) => {
29
+ event.preventDefault()
30
+ const button = event.currentTarget
31
+ const id = button
32
+ .closest("tr[data-edit-for]")
33
+ .getAttribute("data-edit-for")
34
+
35
+ // Hide all rows with this id
36
+ container
37
+ .querySelectorAll(`[data-edit-for='${id}']`)
38
+ .forEach((edit_view) => {
39
+ edit_view.style.display = "none"
40
+ clear_errors(edit_view)
41
+ rollback_changes(edit_view)
42
+ })
43
+
44
+ const show_view = container.querySelector(`[data-show-for='${id}']`)
45
+ if (show_view) {
46
+ show_view.style.display = ""
47
+ }
48
+ }
49
+
50
+ const clear_errors = (element) => {
51
+ element.querySelectorAll(".has-error").forEach((errorElement) => {
52
+ errorElement.classList.remove("has-error")
53
+ // Remove the error messages
54
+ errorElement.querySelectorAll(".form-text").forEach((formText) => {
55
+ formText.remove()
56
+ })
57
+ })
58
+ }
59
+
60
+ const rollback_changes = (element) => {
61
+ element
62
+ .querySelectorAll('input[type="text"], select')
63
+ .forEach((input) => {
64
+ if (input.dataset.orig !== undefined) {
65
+ input.value = input.dataset.orig
66
+ input.dispatchEvent(new Event("change", { bubbles: true }))
67
+ }
68
+ })
69
+ }
70
+
71
+ const destroy_user = (event) => {
72
+ const button = event.currentTarget
73
+ const id = button.getAttribute("data-target")
74
+ const destroyInput = container.querySelector(
75
+ `[data-destroy-for='${id}']`,
76
+ )
77
+ if (destroyInput) {
78
+ destroyInput.value = "1"
79
+ }
80
+ }
81
+
82
+ const new_user = (event) => {
83
+ event.preventDefault()
84
+ // Show ALL rows with data-edit-for='new'
85
+ container
86
+ .querySelectorAll(`[data-edit-for='new']`)
87
+ .forEach((edit_view) => {
88
+ edit_view.style.display = ""
89
+
90
+ // Cache original values in case editing is canceled
91
+ edit_view
92
+ .querySelectorAll('input[type="text"], select')
93
+ .forEach((input) => {
94
+ input.dataset.orig = input.value
95
+ })
96
+ })
97
+ }
98
+
99
+ const open_errors = () => {
100
+ // Find all rows with errors within this container
101
+ const allErrorElements = container.querySelectorAll(".has-error")
102
+ const rowsToShow = new Set()
103
+
104
+ allErrorElements.forEach((errorElement) => {
105
+ const edit_row = errorElement.closest("[data-edit-for]")
106
+ if (edit_row) {
107
+ // Show all rows with the same data-edit-for value
108
+ const id = edit_row.getAttribute("data-edit-for")
109
+ container
110
+ .querySelectorAll(`[data-edit-for='${id}']`)
111
+ .forEach((row) => {
112
+ rowsToShow.add(row)
113
+ })
114
+ }
115
+ })
116
+
117
+ rowsToShow.forEach((row) => {
118
+ row.style.display = ""
119
+ })
120
+ }
121
+
122
+ // First, hide all edit views
123
+ container.querySelectorAll("[data-edit-for]").forEach((element) => {
124
+ element.style.display = "none"
125
+ })
126
+
127
+ // Then show any with errors
128
+ open_errors()
129
+
130
+ // Attach event listeners
131
+ container
132
+ .querySelectorAll("[data-behavior='edit-user']")
133
+ .forEach((button) => {
134
+ button.addEventListener("click", edit_user)
135
+ })
136
+
137
+ container
138
+ .querySelectorAll("[data-behavior='cancel-edit']")
139
+ .forEach((button) => {
140
+ button.addEventListener("click", cancel_edit)
141
+ })
142
+
143
+ container
144
+ .querySelectorAll("[data-behavior='destroy-user']")
145
+ .forEach((button) => {
146
+ button.addEventListener("click", destroy_user)
147
+ })
148
+
149
+ container
150
+ .querySelectorAll("[data-behavior='new-user']")
151
+ .forEach((button) => {
152
+ button.addEventListener("click", new_user)
153
+ })
49
154
  })
50
- }
51
-
52
- function open_errors() {
53
- const edit_row = container.find(".has-error").closest("[data-edit-for]")
54
- edit_row.show()
55
- // The following row has the controls, so show it too.
56
- edit_row.next().show()
57
- }
58
-
59
- $(".edit_exhibit, .admin-users").each(function () {
60
- container = $(this)
61
- $("[data-edit-for]", container).hide()
62
- open_errors()
63
- $("[data-behavior='edit-user']", container).on("click", edit_user)
64
- $("[data-behavior='cancel-edit']", container).on("click", cancel_edit)
65
- $("[data-behavior='destroy-user']", container).on("click", destroy_user)
66
- $("[data-behavior='new-user']", container).on("click", new_user)
67
- })
68
155
  }
69
156
  }