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.
- checksums.yaml +4 -4
- data/README.md +41 -4
- data/Rakefile +1 -2
- data/app/assets/javascripts/spotlight/spotlight.esm.js +2168 -4560
- data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
- data/app/assets/javascripts/spotlight/spotlight.js +2167 -4559
- data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
- data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +4 -0
- data/app/assets/stylesheets/spotlight/_browse.scss +0 -4
- data/app/assets/stylesheets/spotlight/{_collapse_toggle.scss → _collapse_toggle.css} +2 -2
- data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +8 -0
- data/app/assets/stylesheets/spotlight/_exhibits_index.scss +2 -1
- data/app/assets/stylesheets/spotlight/_footer.scss +2 -2
- data/app/assets/stylesheets/spotlight/_header.scss +8 -8
- data/app/assets/stylesheets/spotlight/_pages.scss +1 -1
- data/app/assets/stylesheets/spotlight/_slideshow_block.scss +15 -0
- data/app/assets/stylesheets/spotlight/_spotlight.scss +1 -1
- data/app/assets/stylesheets/spotlight/_translations.scss +3 -3
- data/app/assets/stylesheets/spotlight/_uploaded_items_block.css +7 -0
- data/app/assets/stylesheets/spotlight/_variables.css +15 -0
- data/app/assets/stylesheets/spotlight/browse_group_categories_block.scss +0 -76
- data/app/components/blacklight/icons/pause_component.rb +15 -0
- data/app/components/blacklight/icons/play_arrow_component.rb +15 -0
- data/app/components/spotlight/analytics/dashboard_component.html.erb +1 -1
- data/app/components/spotlight/custom_field_form_group_component.rb +40 -0
- data/app/components/spotlight/document_admin_table_component.html.erb +2 -2
- data/app/components/spotlight/edit_sidecar_component.html.erb +18 -0
- data/app/components/spotlight/edit_sidecar_component.rb +41 -0
- data/app/components/spotlight/masthead_component.html.erb +18 -0
- data/app/components/spotlight/masthead_component.rb +46 -0
- data/app/components/spotlight/save_search_component.html.erb +1 -1
- data/app/components/spotlight/sidecar_form_field_component.html.erb +18 -0
- data/app/components/spotlight/sidecar_form_field_component.rb +71 -0
- data/app/components/spotlight/solr_document_legacy_embed_component.html.erb +0 -4
- data/app/components/spotlight/solr_document_legacy_embed_component.rb +2 -2
- data/app/components/spotlight/tag_selector_component.html.erb +1 -1
- data/app/components/spotlight/tag_selector_component.rb +3 -2
- data/app/components/spotlight/upload_field_form_group_component.rb +33 -0
- data/app/controllers/concerns/spotlight/controller.rb +15 -14
- data/app/controllers/concerns/spotlight/search_helper.rb +2 -5
- data/app/controllers/spotlight/browse_controller.rb +1 -6
- data/app/controllers/spotlight/catalog_controller.rb +2 -3
- data/app/controllers/spotlight/concerns/application_controller.rb +4 -6
- data/app/controllers/spotlight/exhibits_controller.rb +22 -10
- data/app/controllers/spotlight/lock_controller.rb +1 -1
- data/app/controllers/spotlight/pages_controller.rb +11 -11
- data/app/controllers/spotlight/resources/upload_controller.rb +1 -1
- data/app/controllers/spotlight/resources_controller.rb +1 -1
- data/app/controllers/spotlight/solr_controller.rb +5 -1
- data/app/helpers/spotlight/application_helper.rb +14 -26
- data/app/helpers/spotlight/crud_link_helpers.rb +0 -12
- data/app/helpers/spotlight/main_app_helpers.rb +2 -2
- data/app/javascript/spotlight/admin/add_another.js +37 -25
- data/app/javascript/spotlight/admin/add_image_selector.js +43 -26
- data/app/javascript/spotlight/admin/add_new_button.js +51 -36
- data/app/javascript/spotlight/admin/blacklight_configuration.js +76 -54
- data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +102 -101
- data/app/javascript/spotlight/admin/block_mixins/formable.js +91 -75
- data/app/javascript/spotlight/admin/block_mixins/plustextable.js +46 -48
- data/app/javascript/spotlight/admin/blocks/block.js +27 -28
- data/app/javascript/spotlight/admin/blocks/browse_block.js +14 -10
- data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -10
- data/app/javascript/spotlight/admin/blocks/pages_block.js +5 -4
- data/app/javascript/spotlight/admin/blocks/resources_block.js +61 -41
- data/app/javascript/spotlight/admin/blocks/search_result_block.js +24 -7
- data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +103 -50
- data/app/javascript/spotlight/admin/blocks/solr_documents_carousel_block.js +50 -26
- data/app/javascript/spotlight/admin/blocks/solr_documents_features_block.js +47 -23
- data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +35 -19
- data/app/javascript/spotlight/admin/crop.js +146 -66
- data/app/javascript/spotlight/admin/croppable.js +5 -4
- data/app/javascript/spotlight/admin/croppable_modal.js +67 -32
- data/app/javascript/spotlight/admin/edit_in_place.js +69 -54
- data/app/javascript/spotlight/admin/exhibits.js +92 -45
- data/app/javascript/spotlight/admin/form_observer.js +92 -78
- data/app/javascript/spotlight/admin/multi_image_selector.js +201 -153
- data/app/javascript/spotlight/admin/pages.js +13 -7
- data/app/javascript/spotlight/admin/progress_monitor.js +65 -50
- data/app/javascript/spotlight/admin/readonly_checkbox.js +7 -3
- data/app/javascript/spotlight/admin/search_typeahead.js +20 -11
- data/app/javascript/spotlight/admin/select_related_input.js +23 -23
- data/app/javascript/spotlight/admin/serialize_json.js +120 -0
- data/app/javascript/spotlight/admin/sir-trevor/block_controls.js +24 -11
- data/app/javascript/spotlight/admin/sir-trevor/block_limits.js +9 -6
- data/app/javascript/spotlight/admin/sir-trevor/locales.js +2 -2
- data/app/javascript/spotlight/admin/spotlight_nestable.js +2 -5
- data/app/javascript/spotlight/admin/translation_progress.js +18 -13
- data/app/javascript/spotlight/admin/users.js +151 -64
- data/app/javascript/spotlight/user/carousel.js +104 -32
- data/app/javascript/spotlight/user/clear_form_button.js +24 -14
- data/app/javascript/spotlight/user/index.js +0 -2
- data/app/javascript/spotlight/user/zpr_links.js +99 -40
- data/app/jobs/concerns/spotlight/gather_documents.rb +1 -1
- data/app/jobs/spotlight/add_uploads_from_csv.rb +31 -8
- data/app/jobs/spotlight/cleanup_job_trackers_job.rb +5 -3
- data/app/models/concerns/spotlight/access_controls_enforcement_search_builder.rb +13 -2
- data/app/models/concerns/spotlight/browse_category_search_builder.rb +3 -3
- data/app/models/concerns/spotlight/exhibit_documents.rb +2 -2
- data/app/models/concerns/spotlight/sitemap.rb +2 -2
- data/app/models/concerns/spotlight/solr_document/finder.rb +2 -2
- data/app/models/concerns/spotlight/solr_document.rb +1 -47
- data/app/models/sir_trevor_rails/blocks/browse_block.rb +0 -4
- data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +2 -1
- data/app/models/spotlight/blacklight_configuration.rb +5 -3
- data/app/models/spotlight/contact_email.rb +2 -2
- data/app/models/spotlight/custom_field.rb +17 -0
- data/app/models/spotlight/exhibit.rb +28 -0
- data/app/models/spotlight/featured_image.rb +1 -1
- data/app/models/spotlight/field_metadata.rb +10 -5
- data/app/models/spotlight/job_tracker.rb +0 -18
- data/app/models/spotlight/main_navigation.rb +2 -2
- data/app/models/spotlight/page.rb +3 -3
- data/app/models/spotlight/resources/iiif_harvester.rb +7 -4
- data/app/models/spotlight/resources/iiif_manifest.rb +0 -4
- data/app/models/spotlight/resources/iiif_manifest_metadata.rb +1 -3
- data/app/models/spotlight/resources/iiif_service.rb +21 -6
- data/app/models/spotlight/resources/upload.rb +6 -0
- data/app/models/spotlight/search.rb +5 -9
- data/app/models/spotlight/solr_document_sidecar.rb +18 -0
- data/app/services/spotlight/bulk_updates_csv_template_service.rb +1 -1
- data/app/services/spotlight/etl/pipeline.rb +2 -2
- data/app/services/spotlight/etl/step.rb +2 -2
- data/app/views/catalog/_remove_tags.html.erb +2 -2
- data/app/views/layouts/spotlight/base.html.erb +3 -6
- data/app/views/layouts/spotlight/spotlight.html.erb +2 -2
- data/app/views/shared/_analytics.html.erb +4 -3
- data/app/views/shared/_masthead.html.erb +2 -18
- data/app/views/spotlight/about_pages/_empty.html.erb +1 -1
- data/app/views/spotlight/about_pages/_sidebar.html.erb +10 -8
- data/app/views/spotlight/browse/_search.html.erb +2 -2
- data/app/views/spotlight/browse/_search_box.html.erb +6 -14
- data/app/views/spotlight/browse/index.html.erb +1 -1
- data/app/views/spotlight/browse/show.html.erb +1 -1
- data/app/views/spotlight/catalog/_document_admin_table.html.erb +1 -1
- data/app/views/spotlight/catalog/_edit_default.html.erb +1 -1
- data/app/views/spotlight/catalog/edit.html.erb +1 -1
- data/app/views/spotlight/dashboards/_page.html.erb +1 -1
- data/app/views/spotlight/exhibits/_exhibit_card.html.erb +3 -1
- data/app/views/spotlight/exhibits/_export.html.erb +17 -1
- data/app/views/spotlight/exhibits/_form.html.erb +20 -4
- data/app/views/spotlight/exhibits/_missing_exhibits.html.erb +3 -3
- data/app/views/spotlight/exhibits/index.html.erb +21 -8
- data/app/views/spotlight/feature_pages/_empty.html.erb +1 -1
- data/app/views/spotlight/feature_pages/_sidebar.html.erb +17 -15
- data/app/views/spotlight/home_pages/_empty.html.erb +7 -7
- data/app/views/spotlight/pages/show.html.erb +1 -0
- data/app/views/spotlight/resources/upload/_form.html.erb +2 -2
- data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +5 -16
- data/app/views/spotlight/sir_trevor/blocks/_embedded_document.html.erb +3 -5
- data/app/views/spotlight/sir_trevor/blocks/_link_to_search_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +11 -2
- data/app/views/spotlight/sites/_exhibit.html.erb +1 -1
- data/config/i18n-tasks.yml +1 -1
- data/config/locales/spotlight.ar.yml +1 -2
- data/config/locales/spotlight.de.yml +1 -2
- data/config/locales/spotlight.en.yml +39 -10
- data/config/locales/spotlight.es.yml +1 -2
- data/config/locales/spotlight.fr.yml +1 -2
- data/config/locales/spotlight.it.yml +1 -2
- data/config/locales/spotlight.ja.yml +39 -0
- data/config/locales/spotlight.zh.yml +1 -2
- data/db/migrate/20261007133748_add_discovery_enabled_to_spotlight_exhibits.rb +5 -0
- data/lib/generators/spotlight/assets/importmap_generator.rb +2 -10
- data/lib/generators/spotlight/assets/propshaft_generator.rb +5 -4
- data/lib/generators/spotlight/install_generator.rb +2 -4
- data/lib/generators/spotlight/templates/catalog_controller.rb +0 -1
- data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +26 -4
- data/lib/generators/spotlight/templates/solr/conf/schema.xml +4 -3
- data/lib/generators/spotlight/templates/solr/conf/solrconfig.xml +3 -8
- data/lib/migration/page_language.rb +0 -2
- data/lib/spotlight/engine.rb +28 -9
- data/lib/spotlight/search_state.rb +7 -11
- data/lib/spotlight/upload_field_config.rb +19 -1
- data/lib/spotlight/version.rb +1 -1
- data/lib/spotlight.rb +1 -1
- data/spec/support/features/capybara_wait_metadata_helper.rb +3 -1
- data/spec/support/features/test_features_helpers.rb +24 -1
- data/spec/support/iiif_manifest_fixtures.rb +33 -0
- data/spec/support/stub_dns_resolution.rb +12 -0
- metadata +50 -80
- data/app/assets/stylesheets/spotlight/_uploaded_items_block.scss +0 -7
- data/app/assets/stylesheets/spotlight/_variables.scss +0 -13
- data/app/components/blacklight/icons/arrow_alt_circle_left_component.rb +0 -15
- data/app/components/blacklight/icons/arrow_alt_circle_right_component.rb +0 -15
- data/app/components/blacklight/icons/info_component.rb +0 -15
- data/app/components/blacklight/icons/zoom_in_component.rb +0 -15
- data/app/components/blacklight/icons/zoom_out_component.rb +0 -15
- data/app/components/spotlight/icon_component.rb +0 -13
- data/app/javascript/spotlight/user/browse_group_categories.js +0 -54
- data/app/mailers/spotlight/invitation_mailer.rb +0 -21
- data/app/models/concerns/spotlight/resources/web.rb +0 -38
- data/app/services/spotlight/iiif_resource_resolver.rb +0 -78
- data/app/views/catalog/_image_default.html.erb +0 -6
- data/app/views/shared/_exhibit_navbar.html.erb +0 -2
- data/app/views/shared/_header_navbar.html.erb +0 -6
- data/app/views/spotlight/catalog/_admin_index_header_default.html.erb +0 -23
- data/app/views/spotlight/catalog/_admin_thumbnail_default.html.erb +0 -7
- data/app/views/spotlight/catalog/_curation_mode_toggle_default.html.erb +0 -1
- data/app/views/spotlight/catalog/_document_row.html.erb +0 -2
- data/app/views/spotlight/catalog/_edit_sidecar.html.erb +0 -24
- data/app/views/spotlight/catalog/_index_compact_default.html.erb +0 -21
- data/app/views/spotlight/custom_fields/form_group/_text.html.erb +0 -23
- data/app/views/spotlight/custom_fields/form_group/_vocab.html.erb +0 -23
- data/app/views/spotlight/invitation_mailer/exhibit_invitation_notification.html.erb +0 -12
- data/lib/generators/spotlight/templates/javascript/jquery-shim.js +0 -1
- data/vendor/assets/javascripts/tiny-slider.js +0 -3221
- data/vendor/assets/stylesheets/tiny-slider.css +0 -1
- /data/app/assets/stylesheets/spotlight/{_breadcrumbs.scss → _breadcrumbs.css} +0 -0
- /data/app/assets/stylesheets/spotlight/{_croppable.scss → _croppable.css} +0 -0
- /data/app/assets/stylesheets/spotlight/{_modals.scss → _modals.css} +0 -0
- /data/app/assets/stylesheets/spotlight/{_utilities.scss → _utilities.css} +0 -0
|
@@ -3,75 +3,90 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export default class {
|
|
5
5
|
connect() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var
|
|
6
|
+
document
|
|
7
|
+
.querySelectorAll("[data-in-place-edit-target]")
|
|
8
|
+
.forEach(function (container) {
|
|
9
|
+
var label = container.querySelector(container.dataset.inPlaceEditTarget)
|
|
10
|
+
var input = container.querySelector(
|
|
11
|
+
container.dataset.inPlaceEditFieldTarget,
|
|
12
|
+
)
|
|
13
|
+
if (!label || !input) return
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
container.addEventListener("click", function (e) {
|
|
16
|
+
// hide the edit-in-place affordance icon while in edit mode
|
|
17
|
+
container.classList.add("hide-edit-icon")
|
|
18
|
+
label.style.display = "none"
|
|
19
|
+
input.value = label.textContent
|
|
20
|
+
input.setAttribute("type", "text")
|
|
21
|
+
input.select()
|
|
22
|
+
input.focus()
|
|
23
|
+
e.preventDefault()
|
|
24
|
+
e.stopPropagation()
|
|
25
|
+
})
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
if (e.
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
input.addEventListener("keypress", function (e) {
|
|
28
|
+
if (e.key === "Enter") {
|
|
29
|
+
input.blur()
|
|
30
|
+
e.preventDefault()
|
|
31
|
+
e.stopPropagation()
|
|
23
32
|
}
|
|
24
33
|
})
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
var value =
|
|
35
|
+
input.addEventListener("blur", function () {
|
|
36
|
+
var value = input.value
|
|
28
37
|
|
|
29
|
-
if (
|
|
30
|
-
|
|
38
|
+
if (value.trim().length == 0) {
|
|
39
|
+
input.value = label.textContent
|
|
31
40
|
} else {
|
|
32
|
-
|
|
41
|
+
label.textContent = value
|
|
33
42
|
}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
label.style.display = ""
|
|
45
|
+
input.setAttribute("type", "hidden")
|
|
37
46
|
// when leaving edit mode, should no longer hide edit-in-place affordance icon
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
document
|
|
48
|
+
.querySelectorAll("[data-in-place-edit-target]")
|
|
49
|
+
.forEach(function (el) {
|
|
50
|
+
el.classList.remove("hide-edit-icon")
|
|
51
|
+
})
|
|
41
52
|
})
|
|
42
|
-
|
|
43
|
-
return false
|
|
44
53
|
})
|
|
45
|
-
})
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
document
|
|
56
|
+
.querySelectorAll("[data-behavior='restore-default']")
|
|
57
|
+
.forEach(function (container) {
|
|
58
|
+
var hidden = container.querySelector("[data-default-value]")
|
|
59
|
+
var inPlaceEditContainer = container.querySelector(
|
|
60
|
+
"[data-in-place-edit-target]",
|
|
61
|
+
)
|
|
62
|
+
var button = container.querySelector("[data-restore-default]")
|
|
63
|
+
if (!hidden || !inPlaceEditContainer || !button) return
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return false
|
|
59
|
-
}
|
|
60
|
-
})
|
|
65
|
+
var value = container.querySelector(
|
|
66
|
+
inPlaceEditContainer.dataset.inPlaceEditTarget,
|
|
67
|
+
)
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
hidden.addEventListener("keypress", function (e) {
|
|
70
|
+
if (e.key === "Enter") {
|
|
71
|
+
hidden.blur()
|
|
72
|
+
e.preventDefault()
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
hidden.addEventListener("blur", function () {
|
|
77
|
+
if (hidden.value == hidden.dataset.defaultValue) {
|
|
78
|
+
button.classList.add("d-none")
|
|
79
|
+
} else {
|
|
80
|
+
button.classList.remove("d-none")
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
button.addEventListener("click", function (e) {
|
|
85
|
+
e.preventDefault()
|
|
86
|
+
hidden.value = hidden.dataset.defaultValue
|
|
87
|
+
if (value) value.textContent = hidden.dataset.defaultValue
|
|
88
|
+
button.style.display = "none"
|
|
89
|
+
})
|
|
74
90
|
})
|
|
75
|
-
})
|
|
76
91
|
}
|
|
77
92
|
}
|
|
@@ -3,54 +3,90 @@ import { URLify } from "parameterize"
|
|
|
3
3
|
export default class {
|
|
4
4
|
connect() {
|
|
5
5
|
// auto-fill the exhibit slug on the new exhibit form
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
URLify($(this).val(), $(this).val().length),
|
|
11
|
-
)
|
|
12
|
-
})
|
|
6
|
+
const newExhibit = document.getElementById("new_exhibit")
|
|
7
|
+
if (newExhibit) {
|
|
8
|
+
const exhibitTitle = document.getElementById("exhibit_title")
|
|
9
|
+
const exhibitSlug = document.getElementById("exhibit_slug")
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
if (exhibitTitle && exhibitSlug) {
|
|
12
|
+
const updatePlaceholder = () => {
|
|
13
|
+
const val = exhibitTitle.value || ""
|
|
14
|
+
exhibitSlug.placeholder = URLify(val, val.length)
|
|
17
15
|
}
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
exhibitTitle.addEventListener("change", updatePlaceholder)
|
|
18
|
+
exhibitTitle.addEventListener("keyup", updatePlaceholder)
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
exhibitSlug.addEventListener("focus", () => {
|
|
21
|
+
if (exhibitSlug.value === "") {
|
|
22
|
+
exhibitSlug.value = exhibitSlug.placeholder || ""
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"aria-label",
|
|
36
|
-
$(this)
|
|
37
|
-
.attr("aria-label")
|
|
38
|
-
.replace("1", contacts.length + 1),
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
})
|
|
28
|
+
const anotherEmail = document.getElementById("another-email")
|
|
29
|
+
if (anotherEmail) {
|
|
30
|
+
anotherEmail.addEventListener("click", (e) => {
|
|
31
|
+
e.preventDefault()
|
|
32
|
+
|
|
33
|
+
const container = anotherEmail.closest(".form-group")
|
|
34
|
+
if (!container) return
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
const contacts = container.querySelectorAll(".contact")
|
|
37
|
+
if (contacts.length === 0) return
|
|
45
38
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.find(".input-group input:only-child")
|
|
49
|
-
.closest(".input-group")
|
|
50
|
-
.removeClass("input-group")
|
|
39
|
+
const firstContact = contacts[0]
|
|
40
|
+
const inputContainer = firstContact.cloneNode(true)
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
// wipe out any values from the inputs
|
|
43
|
+
const inputs = inputContainer.querySelectorAll("input")
|
|
44
|
+
inputs.forEach((input) => {
|
|
45
|
+
input.value = ""
|
|
46
|
+
const originalId = input.getAttribute("id")
|
|
47
|
+
if (originalId) {
|
|
48
|
+
input.setAttribute(
|
|
49
|
+
"id",
|
|
50
|
+
originalId.replace("0", contacts.length.toString()),
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
const originalName = input.getAttribute("name")
|
|
54
|
+
if (originalName) {
|
|
55
|
+
input.setAttribute(
|
|
56
|
+
"name",
|
|
57
|
+
originalName.replace("0", contacts.length.toString()),
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
const originalAriaLabel = input.getAttribute("aria-label")
|
|
61
|
+
if (originalAriaLabel) {
|
|
62
|
+
input.setAttribute(
|
|
63
|
+
"aria-label",
|
|
64
|
+
originalAriaLabel.replace("1", (contacts.length + 1).toString()),
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
inputContainer
|
|
70
|
+
.querySelectorAll(".contact-email-delete-wrapper")
|
|
71
|
+
.forEach((el) => el.remove())
|
|
72
|
+
inputContainer
|
|
73
|
+
.querySelectorAll(".confirmation-status")
|
|
74
|
+
.forEach((el) => el.remove())
|
|
75
|
+
|
|
76
|
+
// bootstrap does not render input-groups with only one value in them correctly.
|
|
77
|
+
const onlyChildInputs = inputContainer.querySelectorAll(
|
|
78
|
+
".input-group input:only-child",
|
|
79
|
+
)
|
|
80
|
+
onlyChildInputs.forEach((input) => {
|
|
81
|
+
const group = input.closest(".input-group")
|
|
82
|
+
if (group) {
|
|
83
|
+
group.classList.remove("input-group")
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
contacts[contacts.length - 1].after(inputContainer)
|
|
88
|
+
})
|
|
89
|
+
}
|
|
54
90
|
|
|
55
91
|
if (document.getElementById("another-email")) {
|
|
56
92
|
document.addEventListener(
|
|
@@ -60,9 +96,15 @@ export default class {
|
|
|
60
96
|
}
|
|
61
97
|
|
|
62
98
|
// Put focus in saved search title input when Save this search modal is shown
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
99
|
+
const saveModal = document.getElementById("save-modal")
|
|
100
|
+
if (saveModal) {
|
|
101
|
+
saveModal.addEventListener("shown.bs.modal", () => {
|
|
102
|
+
const searchTitle = document.getElementById("search_title")
|
|
103
|
+
if (searchTitle) {
|
|
104
|
+
searchTitle.focus()
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
}
|
|
66
108
|
}
|
|
67
109
|
|
|
68
110
|
contactToDeleteNotFoundHandler(e) {
|
|
@@ -70,8 +112,13 @@ export default class {
|
|
|
70
112
|
e.detail.formSubmission?.delegate?.element?.querySelector(".contact")
|
|
71
113
|
if (contact && e.detail?.fetchResponse?.response?.status === 404) {
|
|
72
114
|
const error = contact.querySelector(".contact-email-delete-error")
|
|
73
|
-
error
|
|
74
|
-
|
|
115
|
+
if (error) {
|
|
116
|
+
error.style.display = "block"
|
|
117
|
+
const errorMsg = error.querySelector(".error-msg")
|
|
118
|
+
if (errorMsg) {
|
|
119
|
+
errorMsg.textContent = "Not Found"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
75
122
|
}
|
|
76
123
|
}
|
|
77
124
|
}
|
|
@@ -1,94 +1,108 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
* SerializedForm is built as a singleton. It needs to be able to
|
|
3
|
+
* handle instantiation from multiple sources, and use the [data-form-observer]
|
|
4
|
+
* as global state object.
|
|
5
|
+
*/
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* handle instantiation from multiple sources, and use the [data-form-observer]
|
|
7
|
-
* as global state object.
|
|
8
|
-
*/
|
|
9
|
-
$.SerializedForm = function () {
|
|
10
|
-
var $serializedForm
|
|
11
|
-
var plugin = this
|
|
7
|
+
// Per-form state (replaces jQuery's .data() storage)
|
|
8
|
+
const formState = new WeakMap()
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
10
|
+
function getState(form) {
|
|
11
|
+
if (!formState.has(form)) {
|
|
12
|
+
formState.set(form, {})
|
|
13
|
+
}
|
|
14
|
+
return formState.get(form)
|
|
15
|
+
}
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
// Do custom serialization of the sir-trevor form data. This needs to be a
|
|
18
|
+
// passed in argument for comparison later on.
|
|
19
|
+
function formSerialization(form) {
|
|
20
|
+
var params = new URLSearchParams()
|
|
21
|
+
for (const element of form.elements) {
|
|
22
|
+
if (!element.name || element.disabled) continue
|
|
23
|
+
const type = (element.type || "").toLowerCase()
|
|
24
|
+
if (
|
|
25
|
+
type === "file" ||
|
|
26
|
+
type === "submit" ||
|
|
27
|
+
type === "button" ||
|
|
28
|
+
type === "reset" ||
|
|
29
|
+
type === "image"
|
|
30
|
+
)
|
|
31
|
+
continue
|
|
32
|
+
if ((type === "checkbox" || type === "radio") && !element.checked) continue
|
|
33
|
+
params.append(element.name, element.value)
|
|
34
|
+
}
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
var content_editable = []
|
|
37
|
+
var i = 0
|
|
38
|
+
form.querySelectorAll("[contenteditable='true']").forEach((element) => {
|
|
39
|
+
content_editable.push("&contenteditable_" + i + "=" + element.textContent)
|
|
40
|
+
i++
|
|
41
|
+
})
|
|
42
|
+
return params.toString() + content_editable.join("")
|
|
43
|
+
}
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
// Unbind observing form on submit (which we have to do because of turbolinks)
|
|
46
|
+
function bindObservedFormSubmit(form) {
|
|
47
|
+
var state = getState(form)
|
|
48
|
+
if (state.submitBound) return
|
|
49
|
+
state.submitBound = true
|
|
50
|
+
form.addEventListener("submit", () => {
|
|
51
|
+
getState(form).beingSubmitted = true
|
|
52
|
+
})
|
|
53
|
+
}
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
54
|
-
return unsaved_changes
|
|
55
|
-
}
|
|
55
|
+
export const SerializedForm = {
|
|
56
|
+
// Store form serialization in state and bind submit handlers
|
|
57
|
+
init() {
|
|
58
|
+
document.querySelectorAll("[data-form-observer]").forEach((form) => {
|
|
59
|
+
getState(form).serialized = formSerialization(form)
|
|
60
|
+
bindObservedFormSubmit(form)
|
|
61
|
+
})
|
|
62
|
+
return this
|
|
63
|
+
},
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
// Check all observed forms on page for status change
|
|
66
|
+
observedFormsStatusHasChanged() {
|
|
67
|
+
return Array.from(document.querySelectorAll("[data-form-observer]")).some(
|
|
68
|
+
(form) => {
|
|
69
|
+
var state = getState(form)
|
|
70
|
+
if (state.beingSubmitted) return false
|
|
71
|
+
return state.serialized !== formSerialization(form)
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
},
|
|
75
|
+
}
|
|
62
76
|
|
|
63
|
-
|
|
77
|
+
var UNSAVED_CHANGES_MESSAGE =
|
|
78
|
+
"You have unsaved changes. Are you sure you want to leave this page?"
|
|
64
79
|
|
|
65
|
-
|
|
80
|
+
// Don't handle the same event twice #turbolinks
|
|
81
|
+
function handleNavigationEvent(event) {
|
|
82
|
+
if (event.handled === true) return
|
|
83
|
+
if (!SerializedForm.observedFormsStatusHasChanged()) return
|
|
84
|
+
event.handled = true
|
|
85
|
+
|
|
86
|
+
// There are variations in how Webkit browsers may handle this:
|
|
87
|
+
// https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
|
|
88
|
+
if (event.type === "beforeunload") {
|
|
89
|
+
event.preventDefault()
|
|
90
|
+
event.returnValue = UNSAVED_CHANGES_MESSAGE
|
|
91
|
+
return UNSAVED_CHANGES_MESSAGE
|
|
92
|
+
} else {
|
|
93
|
+
if (!confirm(UNSAVED_CHANGES_MESSAGE)) {
|
|
94
|
+
event.preventDefault()
|
|
95
|
+
}
|
|
66
96
|
}
|
|
67
|
-
}
|
|
97
|
+
}
|
|
68
98
|
|
|
69
99
|
export default class {
|
|
70
100
|
connect() {
|
|
71
101
|
// Instantiate the singleton SerializedForm plugin
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (event.handled !== true) {
|
|
78
|
-
if (serializedForm.observedFormsStatusHasChanged()) {
|
|
79
|
-
event.handled = true
|
|
80
|
-
var message =
|
|
81
|
-
"You have unsaved changes. Are you sure you want to leave this page?"
|
|
82
|
-
// There are variations in how Webkit browsers may handle this:
|
|
83
|
-
// https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
|
|
84
|
-
if (event.type == "beforeunload") {
|
|
85
|
-
return message
|
|
86
|
-
} else {
|
|
87
|
-
return confirm(message)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
)
|
|
102
|
+
SerializedForm.init()
|
|
103
|
+
window.addEventListener("beforeunload", handleNavigationEvent)
|
|
104
|
+
document.addEventListener("page:before-change", handleNavigationEvent)
|
|
105
|
+
document.addEventListener("turbolinks:before-visit", handleNavigationEvent)
|
|
106
|
+
document.addEventListener("turbo:before-visit", handleNavigationEvent)
|
|
93
107
|
}
|
|
94
108
|
}
|