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
|
@@ -1,81 +1,96 @@
|
|
|
1
1
|
export default class {
|
|
2
2
|
connect() {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
document
|
|
4
|
+
.querySelectorAll("[data-expanded-add-button]")
|
|
5
|
+
.forEach((el) => this.addExpandBehaviorToButton(el))
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
addExpandBehaviorToButton(button) {
|
|
9
9
|
var settings = {
|
|
10
|
-
speed: button.
|
|
11
|
-
animate_width: button.
|
|
10
|
+
speed: parseInt(button.dataset.speed || "450", 10),
|
|
11
|
+
animate_width: parseInt(button.dataset.animateWidth || "425", 10),
|
|
12
12
|
}
|
|
13
|
-
var target =
|
|
14
|
-
var save =
|
|
15
|
-
var cancel =
|
|
16
|
-
var input =
|
|
17
|
-
var original_width = button.
|
|
13
|
+
var target = document.querySelector(button.dataset.fieldTarget)
|
|
14
|
+
var save = target.querySelector("input[data-behavior='save']")
|
|
15
|
+
var cancel = target.querySelector("input[data-behavior='cancel']")
|
|
16
|
+
var input = target.querySelector("input[type='text']")
|
|
17
|
+
var original_width = button.offsetWidth
|
|
18
18
|
var expanded = false
|
|
19
19
|
|
|
20
20
|
// Animate button open when the mouse enters or
|
|
21
21
|
// the button is given focus (i.e. clicked/tabbed)
|
|
22
|
-
button.
|
|
23
|
-
|
|
24
|
-
})
|
|
22
|
+
button.addEventListener("mouseenter", expandButton)
|
|
23
|
+
button.addEventListener("focus", expandButton)
|
|
25
24
|
|
|
26
25
|
// Don't allow blank titles
|
|
27
|
-
save.
|
|
26
|
+
save.addEventListener("click", function (e) {
|
|
28
27
|
if (inputEmpty()) {
|
|
29
|
-
|
|
28
|
+
e.preventDefault()
|
|
29
|
+
e.stopPropagation()
|
|
30
30
|
}
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
// Empty input and collapse
|
|
34
34
|
// button on cancel click
|
|
35
|
-
cancel.
|
|
35
|
+
cancel.addEventListener("click", function (e) {
|
|
36
36
|
e.preventDefault()
|
|
37
|
-
input.
|
|
37
|
+
input.value = ""
|
|
38
38
|
collapseButton()
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
// Collapse the button on when
|
|
42
42
|
// an empty input loses focus
|
|
43
|
-
input.
|
|
43
|
+
input.addEventListener("blur", function () {
|
|
44
44
|
if (inputEmpty()) {
|
|
45
45
|
collapseButton()
|
|
46
46
|
}
|
|
47
47
|
})
|
|
48
|
+
|
|
48
49
|
function expandButton() {
|
|
49
50
|
// If this has not yet been expanded, recalculate original_width to
|
|
50
51
|
// handle things that may have been originally hidden.
|
|
51
52
|
if (!expanded) {
|
|
52
|
-
original_width = button.
|
|
53
|
+
original_width = button.offsetWidth
|
|
53
54
|
}
|
|
54
|
-
if (button.
|
|
55
|
+
if (button.offsetWidth <= original_width + 5) {
|
|
55
56
|
expanded = true
|
|
56
|
-
button.animate(
|
|
57
|
+
var anim = button.animate(
|
|
57
58
|
{ width: settings.animate_width + "px" },
|
|
58
|
-
settings.speed,
|
|
59
|
-
function () {
|
|
60
|
-
target.show(0, function () {
|
|
61
|
-
input.focus()
|
|
62
|
-
// Set the button to auto width to make
|
|
63
|
-
// sure it has room for any inputs
|
|
64
|
-
button.width("auto")
|
|
65
|
-
// Explicitly set the width of the button
|
|
66
|
-
// so the close animation works properly
|
|
67
|
-
button.width(button.width())
|
|
68
|
-
})
|
|
69
|
-
},
|
|
59
|
+
{ duration: settings.speed },
|
|
70
60
|
)
|
|
61
|
+
anim.onfinish = function () {
|
|
62
|
+
button.style.width = settings.animate_width + "px"
|
|
63
|
+
showElement(target)
|
|
64
|
+
input.focus()
|
|
65
|
+
// Set the button to auto width to make
|
|
66
|
+
// sure it has room for any inputs
|
|
67
|
+
button.style.width = "auto"
|
|
68
|
+
// Explicitly set the width of the button
|
|
69
|
+
// so the close animation works properly
|
|
70
|
+
button.style.width = button.offsetWidth + "px"
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
function collapseButton() {
|
|
74
|
-
target.
|
|
75
|
-
button.animate(
|
|
75
|
+
target.style.display = "none"
|
|
76
|
+
var anim = button.animate(
|
|
77
|
+
{ width: original_width + "px" },
|
|
78
|
+
{ duration: settings.speed },
|
|
79
|
+
)
|
|
80
|
+
anim.onfinish = function () {
|
|
81
|
+
button.style.width = original_width + "px"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Show an element that may be hidden via a CSS class by overriding with an
|
|
85
|
+
// appropriate inline display value (mirrors jQuery's .show()).
|
|
86
|
+
function showElement(el) {
|
|
87
|
+
el.style.display = ""
|
|
88
|
+
if (window.getComputedStyle(el).display === "none") {
|
|
89
|
+
el.style.display = "inline-block"
|
|
90
|
+
}
|
|
76
91
|
}
|
|
77
92
|
function inputEmpty() {
|
|
78
|
-
return
|
|
93
|
+
return input.value.trim() == ""
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
}
|
|
@@ -7,70 +7,92 @@ export default class {
|
|
|
7
7
|
|
|
8
8
|
// Add Select/Deselect all behavior for metadata field names for a given view e.g. Item details.
|
|
9
9
|
addCheckboxToggleBehavior() {
|
|
10
|
-
$("[data-behavior='metadata-select']").each(function () {
|
|
11
|
-
var selectCheckbox = $(this)
|
|
12
|
-
var parentCell = selectCheckbox.parents("th")
|
|
13
|
-
var table = parentCell.closest("table")
|
|
14
|
-
var columnRows = $(
|
|
15
|
-
"tr td:nth-child(" + (parentCell.index() + 1) + ")",
|
|
16
|
-
table,
|
|
17
|
-
)
|
|
18
|
-
var checkboxes = $("input[type='checkbox']", columnRows)
|
|
19
|
-
updateSelectAllInput(selectCheckbox, columnRows)
|
|
20
|
-
// Add the check/uncheck behavior to the select/deselect all checkbox
|
|
21
|
-
selectCheckbox.on("click", function () {
|
|
22
|
-
var allChecked = allCheckboxesChecked(columnRows)
|
|
23
|
-
columnRows.each(function () {
|
|
24
|
-
$("input[type='checkbox']", $(this)).prop("checked", !allChecked)
|
|
25
|
-
})
|
|
26
|
-
})
|
|
27
|
-
// When a single checkbox is selected/unselected, the "All" checkbox should be updated accordingly.
|
|
28
|
-
checkboxes.each(function () {
|
|
29
|
-
$(this).on("change", function () {
|
|
30
|
-
updateSelectAllInput(selectCheckbox, columnRows)
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
10
|
// Check number of checkboxes against the number of checked
|
|
36
11
|
// checkboxes to determine if all of them are checked or not
|
|
37
|
-
function allCheckboxesChecked(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
12
|
+
function allCheckboxesChecked(cells) {
|
|
13
|
+
let total = 0
|
|
14
|
+
let checked = 0
|
|
15
|
+
cells.forEach((cell) => {
|
|
16
|
+
cell.querySelectorAll("input[type='checkbox']").forEach((cb) => {
|
|
17
|
+
total++
|
|
18
|
+
if (cb.checked) {
|
|
19
|
+
checked++
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
return total === checked
|
|
42
24
|
}
|
|
43
25
|
|
|
44
26
|
// Check or uncheck the "All" checkbox for each view column, e.g. Item details, List, etc.
|
|
45
|
-
function updateSelectAllInput(checkbox,
|
|
46
|
-
|
|
47
|
-
checkbox.prop("checked", true)
|
|
48
|
-
} else {
|
|
49
|
-
checkbox.prop("checked", false)
|
|
50
|
-
}
|
|
27
|
+
function updateSelectAllInput(checkbox, cells) {
|
|
28
|
+
checkbox.checked = allCheckboxesChecked(cells)
|
|
51
29
|
}
|
|
30
|
+
|
|
31
|
+
document
|
|
32
|
+
.querySelectorAll("[data-behavior='metadata-select']")
|
|
33
|
+
.forEach((selectCheckbox) => {
|
|
34
|
+
const parentCell = selectCheckbox.closest("th")
|
|
35
|
+
if (!parentCell) return
|
|
36
|
+
|
|
37
|
+
const table = parentCell.closest("table")
|
|
38
|
+
if (!table) return
|
|
39
|
+
|
|
40
|
+
const columnIndex = Array.from(parentCell.parentNode.children).indexOf(
|
|
41
|
+
parentCell,
|
|
42
|
+
)
|
|
43
|
+
const columnRows = table.querySelectorAll(
|
|
44
|
+
`tr td:nth-child(${columnIndex + 1})`,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
const checkboxes = []
|
|
48
|
+
columnRows.forEach((cell) => {
|
|
49
|
+
cell.querySelectorAll("input[type='checkbox']").forEach((cb) => {
|
|
50
|
+
checkboxes.push(cb)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
updateSelectAllInput(selectCheckbox, columnRows)
|
|
55
|
+
|
|
56
|
+
// Add the check/uncheck behavior to the select/deselect all checkbox
|
|
57
|
+
selectCheckbox.addEventListener("click", () => {
|
|
58
|
+
const allChecked = allCheckboxesChecked(columnRows)
|
|
59
|
+
columnRows.forEach((cell) => {
|
|
60
|
+
cell.querySelectorAll("input[type='checkbox']").forEach((cb) => {
|
|
61
|
+
cb.checked = !allChecked
|
|
62
|
+
cb.dispatchEvent(new Event("change", { bubbles: true }))
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
updateSelectAllInput(selectCheckbox, columnRows)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// When a single checkbox is selected/unselected, the "All" checkbox should be updated accordingly.
|
|
69
|
+
checkboxes.forEach((cb) => {
|
|
70
|
+
cb.addEventListener("change", () => {
|
|
71
|
+
updateSelectAllInput(selectCheckbox, columnRows)
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
52
75
|
}
|
|
53
76
|
|
|
54
77
|
addEnableToggleBehavior() {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
document
|
|
79
|
+
.querySelectorAll("[data-behavior='enable-feature']")
|
|
80
|
+
.forEach((checkbox) => {
|
|
81
|
+
const targetSelector = checkbox.dataset.target
|
|
82
|
+
if (!targetSelector) return
|
|
83
|
+
const target = document.querySelector(targetSelector)
|
|
84
|
+
if (!target) return
|
|
58
85
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
target
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.not("[data-behavior='enable-feature']")
|
|
70
|
-
.prop("checked", false)
|
|
71
|
-
.attr("disabled", true)
|
|
72
|
-
}
|
|
86
|
+
checkbox.addEventListener("change", () => {
|
|
87
|
+
const isChecked = checkbox.checked
|
|
88
|
+
target.querySelectorAll("input[type='checkbox']").forEach((cb) => {
|
|
89
|
+
if (!cb.matches("[data-behavior='enable-feature']")) {
|
|
90
|
+
cb.checked = isChecked
|
|
91
|
+
cb.disabled = !isChecked
|
|
92
|
+
cb.dispatchEvent(new Event("change", { bubbles: true }))
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
})
|
|
73
96
|
})
|
|
74
|
-
})
|
|
75
97
|
}
|
|
76
98
|
}
|
|
@@ -1,112 +1,113 @@
|
|
|
1
1
|
import { fetchAutocompleteJSON } from "spotlight/admin/search_typeahead"
|
|
2
|
-
;(function ($) {
|
|
3
|
-
;((SirTrevor.BlockMixins.Autocompleteable = {
|
|
4
|
-
mixinName: "Autocompleteable",
|
|
5
|
-
preload: true,
|
|
6
|
-
|
|
7
|
-
initializeAutocompleteable: function () {
|
|
8
|
-
this.on("onRender", this.addAutocompletetoSirTrevorForm)
|
|
9
|
-
|
|
10
|
-
if (this["autocomplete_url"] === undefined) {
|
|
11
|
-
this.autocomplete_url = function () {
|
|
12
|
-
return $("form[data-autocomplete-url]").data("autocomplete-url")
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
2
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
SirTrevor.BlockMixins.Autocompleteable = {
|
|
4
|
+
mixinName: "Autocompleteable",
|
|
5
|
+
preload: true,
|
|
19
6
|
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
initializeAutocompleteable: function () {
|
|
8
|
+
this.on("onRender", this.addAutocompletetoSirTrevorForm)
|
|
9
|
+
|
|
10
|
+
if (this["autocomplete_url"] === undefined) {
|
|
11
|
+
this.autocomplete_url = function () {
|
|
12
|
+
var el = document.querySelector("form[data-autocomplete-url]")
|
|
13
|
+
return el ? el.dataset.autocompleteUrl : undefined
|
|
22
14
|
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (this["autocomplete_fetch"] === undefined) {
|
|
18
|
+
this.autocomplete_fetch = this.fetchAutocompleteResults
|
|
19
|
+
}
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
if (this["transform_autocomplete_results"] === undefined) {
|
|
22
|
+
this.transform_autocomplete_results = (val) => val
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (this["highlight"] === undefined) {
|
|
26
|
+
this.highlight = function (value) {
|
|
27
|
+
if (!value) return ""
|
|
28
|
+
const queryValue = this.getQueryValue().trim()
|
|
29
|
+
return queryValue
|
|
30
|
+
? value.replace(new RegExp(queryValue, "gi"), "<strong>$&</strong>")
|
|
31
|
+
: value
|
|
32
32
|
}
|
|
33
|
+
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
35
|
+
if (this["autocomplete_control"] === undefined) {
|
|
36
|
+
this.autocomplete_control = function () {
|
|
37
|
+
const autocompleteID = this.autocompleteID()
|
|
38
|
+
return `
|
|
39
|
+
<auto-complete src="${this.autocomplete_url()}" for="${autocompleteID}-popup" fetch-on-empty>
|
|
40
|
+
<input type="text" name="${autocompleteID}" placeholder="${i18n.t("blocks:autocompleteable:placeholder")}" data-default-typeahead>
|
|
41
|
+
<ul id="${autocompleteID}-popup"></ul>
|
|
42
|
+
<div id="${autocompleteID}-popup-feedback" class="visually-hidden"></div>
|
|
43
|
+
</auto-complete>
|
|
44
|
+
`
|
|
45
45
|
}
|
|
46
|
+
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
48
|
+
if (this["autocomplete_element_template"] === undefined) {
|
|
49
|
+
this.autocomplete_element_template = function (item) {
|
|
50
|
+
return `<li role="option" data-autocomplete-value="${item.id}">${this.autocomplete_template(item)}</li>`
|
|
51
51
|
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
queryTokenizer: function (query) {
|
|
56
|
+
return query.trim().toLowerCase().split(/\s+/).filter(Boolean)
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
filterResults: function (data, query) {
|
|
60
|
+
const queryStrings = this.queryTokenizer(query)
|
|
61
|
+
return data.filter((item) => {
|
|
62
|
+
const lowerTitle = item.title.toLowerCase()
|
|
63
|
+
return queryStrings.some((queryString) =>
|
|
64
|
+
lowerTitle.includes(queryString),
|
|
65
|
+
)
|
|
66
|
+
})
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
fetchAutocompleteResults: async function (url) {
|
|
70
|
+
const result = await fetchAutocompleteJSON(url)
|
|
71
|
+
const transformed = this.transform_autocomplete_results(result)
|
|
72
|
+
this.fetchedData = {}
|
|
73
|
+
transformed.map((item) => (this.fetchedData[item.id] = item))
|
|
74
|
+
return transformed
|
|
75
|
+
.map((item) => this.autocomplete_element_template(item))
|
|
76
|
+
.join("")
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
fetchOnceAndFilterLocalResults: async function (url) {
|
|
80
|
+
if (this.fetchedData === undefined) {
|
|
81
|
+
await this.fetchAutocompleteResults(url)
|
|
82
|
+
}
|
|
83
|
+
const query = url.searchParams.get("q")
|
|
84
|
+
const data = Object.values(this.fetchedData)
|
|
85
|
+
const filteredData = query ? this.filterResults(data, query) : data
|
|
86
|
+
return filteredData
|
|
87
|
+
.map((item) => this.autocomplete_element_template(item))
|
|
88
|
+
.join("")
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
autocompleteID: function () {
|
|
92
|
+
return this.blockID + "-autocomplete"
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
getQueryValue: function () {
|
|
96
|
+
const completer = this.inner.querySelector("auto-complete > input")
|
|
97
|
+
return completer.value
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
addAutocompletetoSirTrevorForm: function () {
|
|
101
|
+
const completer = this.inner.querySelector("auto-complete")
|
|
102
|
+
completer.fetchResult = this.autocomplete_fetch.bind(this)
|
|
103
|
+
completer.addEventListener("auto-complete-change", (e) => {
|
|
104
|
+
const data = this.fetchedData[e.relatedTarget.value]
|
|
105
|
+
if (e.relatedTarget.value && data) {
|
|
106
|
+
e.value = e.relatedTarget.value = ""
|
|
107
|
+
this.createItemPanel({ ...data, display: "true" })
|
|
81
108
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.join("")
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
autocompleteID: function () {
|
|
91
|
-
return this.blockID + "-autocomplete"
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
getQueryValue: function () {
|
|
95
|
-
const completer = this.inner.querySelector("auto-complete > input")
|
|
96
|
-
return completer.value
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
addAutocompletetoSirTrevorForm: function () {
|
|
100
|
-
const completer = this.inner.querySelector("auto-complete")
|
|
101
|
-
completer.fetchResult = this.autocomplete_fetch.bind(this)
|
|
102
|
-
completer.addEventListener("auto-complete-change", (e) => {
|
|
103
|
-
const data = this.fetchedData[e.relatedTarget.value]
|
|
104
|
-
if (e.relatedTarget.value && data) {
|
|
105
|
-
e.value = e.relatedTarget.value = ""
|
|
106
|
-
this.createItemPanel({ ...data, display: "true" })
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
},
|
|
110
|
-
}),
|
|
111
|
-
SirTrevor.Block.prototype.availableMixins.push("autocompleteable"))
|
|
112
|
-
})(jQuery)
|
|
109
|
+
})
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
SirTrevor.Block.prototype.availableMixins.push("autocompleteable")
|
|
@@ -1,86 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
import serializeJSON from "spotlight/admin/serialize_json"
|
|
2
|
+
|
|
3
|
+
function setElementValue(el, values) {
|
|
4
|
+
var type = el.type || ""
|
|
5
|
+
if (type === "checkbox" || type === "radio") {
|
|
6
|
+
el.checked = values.indexOf(el.value) !== -1
|
|
7
|
+
} else if (el.nodeName.toLowerCase() === "select") {
|
|
8
|
+
Array.prototype.forEach.call(el.options, function (opt) {
|
|
9
|
+
opt.selected = values.indexOf(opt.value) !== -1
|
|
10
|
+
})
|
|
11
|
+
} else {
|
|
12
|
+
el.value = values[0] != null ? values[0] : ""
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
SirTrevor.BlockMixins.Formable = {
|
|
17
|
+
mixinName: "Formable",
|
|
18
|
+
preload: true,
|
|
19
|
+
|
|
20
|
+
initializeFormable: function () {
|
|
21
|
+
if (this["afterLoadData"] === undefined) {
|
|
22
|
+
this["afterLoadData"] = function (_data) {}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
formId: function (id) {
|
|
27
|
+
return this.blockID + "_" + id
|
|
28
|
+
},
|
|
15
29
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
_serializeData: function () {
|
|
31
|
+
var inputs = this.inner.querySelectorAll("input, select, textarea")
|
|
32
|
+
var nonRadioInputs = Array.prototype.filter.call(inputs, function (el) {
|
|
33
|
+
return el.type !== "radio"
|
|
34
|
+
})
|
|
35
|
+
var data = serializeJSON(nonRadioInputs)
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
this.inner
|
|
38
|
+
.querySelectorAll("input[type='radio']:checked")
|
|
39
|
+
.forEach(function (input) {
|
|
40
|
+
var key = input.getAttribute("data-key") || input.getAttribute("name")
|
|
23
41
|
|
|
24
|
-
if (
|
|
25
|
-
data[key] =
|
|
42
|
+
if (key && !/\[/.test(key)) {
|
|
43
|
+
data[key] = input.value
|
|
26
44
|
}
|
|
27
45
|
})
|
|
28
46
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
/* Simple to start. Add conditions later */
|
|
48
|
+
if (this.hasTextBlock()) {
|
|
49
|
+
data.text = this.getTextBlockHTML()
|
|
50
|
+
data.format = "html"
|
|
51
|
+
if (data.text && data.text.length > 0 && this.options.convertToMarkdown) {
|
|
52
|
+
data.text = stToMarkdown(data.text, this.type)
|
|
53
|
+
data.format = "markdown"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return data
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
loadData: function (data) {
|
|
61
|
+
if (this.hasTextBlock()) {
|
|
62
|
+
if (
|
|
63
|
+
data.text &&
|
|
64
|
+
data.text.length > 0 &&
|
|
65
|
+
this.options.convertFromMarkdown &&
|
|
66
|
+
data.format !== "html"
|
|
67
|
+
) {
|
|
68
|
+
this.setTextBlockHTML(SirTrevor.toHTML(data.text, this.type))
|
|
69
|
+
} else {
|
|
70
|
+
this.setTextBlockHTML(data.text)
|
|
41
71
|
}
|
|
72
|
+
}
|
|
73
|
+
this.loadFormDataByKey(data)
|
|
74
|
+
this.afterLoadData(data)
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
loadFormDataByKey: function (data) {
|
|
78
|
+
var elements = this.inner.querySelectorAll("input, select, textarea")
|
|
79
|
+
Array.prototype.forEach.call(elements, function (input) {
|
|
80
|
+
var type = input.type || ""
|
|
81
|
+
if (type === "button" || type === "submit" || type === "hidden") return
|
|
42
82
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
data.text &&
|
|
50
|
-
data.text.length > 0 &&
|
|
51
|
-
this.options.convertFromMarkdown &&
|
|
52
|
-
data.format !== "html"
|
|
53
|
-
) {
|
|
54
|
-
this.setTextBlockHTML(SirTrevor.toHTML(data.text, this.type))
|
|
55
|
-
} else {
|
|
56
|
-
this.setTextBlockHTML(data.text)
|
|
83
|
+
var key = input.getAttribute("data-key") || input.getAttribute("name")
|
|
84
|
+
|
|
85
|
+
if (key) {
|
|
86
|
+
if (/\[\]$/.test(key)) {
|
|
87
|
+
key = key.replace("[]", "")
|
|
57
88
|
}
|
|
89
|
+
|
|
90
|
+
// by wrapping it in an array, this'll "just work" for radio and checkbox fields too
|
|
91
|
+
var input_data = data[key]
|
|
92
|
+
|
|
93
|
+
if (!(input_data instanceof Array)) {
|
|
94
|
+
input_data = [input_data]
|
|
95
|
+
}
|
|
96
|
+
setElementValue(input, input_data)
|
|
58
97
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
$(":input", this.inner)
|
|
65
|
-
.not("button,:input[type=hidden]")
|
|
66
|
-
.each(function (index, input) {
|
|
67
|
-
var key = $(input).data("key") || input.getAttribute("name")
|
|
68
|
-
|
|
69
|
-
if (key) {
|
|
70
|
-
if (key.match("\\[\\]$")) {
|
|
71
|
-
key = key.replace("[]", "")
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// by wrapping it in an array, this'll "just work" for radio and checkbox fields too
|
|
75
|
-
var input_data = data[key]
|
|
76
|
-
|
|
77
|
-
if (!(input_data instanceof Array)) {
|
|
78
|
-
input_data = [input_data]
|
|
79
|
-
}
|
|
80
|
-
$(this).val(input_data)
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
},
|
|
84
|
-
}),
|
|
85
|
-
SirTrevor.Block.prototype.availableMixins.push("formable"))
|
|
86
|
-
})(jQuery)
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
SirTrevor.Block.prototype.availableMixins.push("formable")
|