blacklight-spotlight 4.7.1 → 5.0.0.pre.alpha2
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 +30 -12
- data/Rakefile +8 -1
- data/app/assets/javascripts/spotlight/application.js +0 -1
- data/app/assets/javascripts/spotlight/spotlight.esm.js +3621 -3847
- data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
- data/app/assets/javascripts/spotlight/spotlight.js +3620 -3852
- data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
- data/app/assets/stylesheets/spotlight/_accessibility.scss +0 -9
- data/app/assets/stylesheets/spotlight/_autocomplete.scss +49 -0
- data/app/assets/stylesheets/spotlight/_blacklight_configuration.scss +0 -1
- data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +1 -6
- data/app/assets/stylesheets/spotlight/_browse.scss +2 -2
- data/app/assets/stylesheets/spotlight/_catalog.scss +40 -41
- data/app/assets/stylesheets/spotlight/_curation.scss +1 -1
- data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +7 -0
- data/app/assets/stylesheets/spotlight/_exhibits_index.scss +8 -5
- data/app/assets/stylesheets/spotlight/_featured_browse_categories_block.scss +3 -3
- data/app/assets/stylesheets/spotlight/_header.scss +13 -0
- data/app/assets/stylesheets/spotlight/_mixins.scss +3 -4
- data/app/assets/stylesheets/spotlight/_nestable.scss +2 -12
- data/app/assets/stylesheets/spotlight/_pages.scss +11 -9
- data/app/assets/stylesheets/spotlight/_report_a_problem.scss +1 -3
- data/app/assets/stylesheets/spotlight/_sir-trevor_overrides.scss +2 -2
- data/app/assets/stylesheets/spotlight/_spotlight.scss +2 -1
- data/app/assets/stylesheets/spotlight/_tag_selector.scss +34 -0
- data/app/assets/stylesheets/spotlight/_variables.scss +0 -8
- data/app/components/spotlight/analytics/dashboard_component.html.erb +3 -3
- data/app/components/spotlight/blocks/heading_block_component.erb +2 -0
- data/app/components/spotlight/blocks/heading_block_component.rb +36 -0
- data/app/components/spotlight/breadcrumbs_component.html.erb +13 -19
- data/app/components/spotlight/bulk_action_component.rb +1 -1
- data/app/components/spotlight/document_component.rb +1 -1
- data/app/components/spotlight/save_search_component.rb +1 -1
- data/app/components/spotlight/select_image_component.html.erb +17 -0
- data/app/components/spotlight/select_image_component.rb +24 -0
- data/app/components/spotlight/skip_link_component.rb +16 -0
- data/app/components/spotlight/tag_selector_component.html.erb +40 -0
- data/app/components/spotlight/tag_selector_component.rb +41 -0
- data/app/components/spotlight/tag_selector_component.yml +6 -0
- data/app/components/spotlight/title_component.html.erb +8 -0
- data/app/components/spotlight/title_component.rb +22 -0
- data/app/controllers/spotlight/accessibility_controller.rb +2 -2
- data/app/controllers/spotlight/catalog_controller.rb +7 -2
- data/app/controllers/spotlight/contact_email_controller.rb +8 -2
- data/app/controllers/spotlight/languages_controller.rb +9 -4
- data/app/helpers/spotlight/application_helper.rb +7 -0
- data/app/helpers/spotlight/crop_helper.rb +4 -0
- data/app/helpers/spotlight/meta_helper.rb +59 -36
- data/app/javascript/spotlight/admin/blacklight_configuration.js +1 -1
- data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +70 -34
- data/app/javascript/spotlight/admin/blocks/block.js +1 -0
- data/app/javascript/spotlight/admin/blocks/browse_block.js +8 -12
- data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -18
- data/app/javascript/spotlight/admin/blocks/pages_block.js +6 -10
- data/app/javascript/spotlight/admin/blocks/resources_block.js +33 -15
- data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +11 -6
- data/app/javascript/spotlight/admin/blocks/solr_documents_embed_block.js +1 -0
- data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +4 -3
- data/app/javascript/spotlight/admin/copy_email_addresses.js +2 -0
- data/app/javascript/spotlight/admin/crop.js +45 -17
- data/app/javascript/spotlight/admin/croppable.js +8 -1
- data/app/javascript/spotlight/admin/croppable_modal.js +68 -0
- data/app/javascript/spotlight/admin/exhibits.js +15 -10
- data/app/javascript/spotlight/admin/form_observer.js +1 -1
- data/app/javascript/spotlight/admin/index.js +0 -10
- data/app/javascript/spotlight/admin/locks.js +15 -5
- data/app/javascript/spotlight/admin/pages.js +1 -1
- data/app/javascript/spotlight/admin/search_typeahead.js +62 -55
- data/app/javascript/spotlight/admin/spotlight_nestable.js +173 -50
- data/app/javascript/spotlight/admin/visibility_toggle.js +1 -11
- data/app/javascript/spotlight/controllers/index.js +8 -0
- data/app/javascript/spotlight/controllers/tag_selector_controller.js +203 -0
- data/app/javascript/spotlight/core.js +4 -6
- data/app/javascript/spotlight/index.js +2 -0
- data/app/javascript/spotlight/user/browse_group_categories.js +2 -0
- data/app/javascript/spotlight/user/carousel.js +3 -1
- data/app/javascript/spotlight/user/index.js +0 -2
- data/app/javascript/spotlight/user/zpr_links.js +2 -0
- data/app/models/sir_trevor_rails/block.rb +4 -5
- data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +1 -1
- data/app/models/sir_trevor_rails/blocks/solr_documents_embed_block.rb +1 -1
- data/app/models/sir_trevor_rails/blocks/uploaded_items_block.rb +1 -1
- data/app/models/spotlight/page_configurations.rb +1 -1
- data/app/services/spotlight/exhibit_import_export_service.rb +2 -2
- data/app/views/catalog/_add_tags.html.erb +2 -2
- data/app/views/catalog/_change_visibility.html.erb +1 -1
- data/app/views/catalog/_remove_tags.html.erb +2 -2
- data/app/views/layouts/spotlight/base.html.erb +24 -13
- data/app/views/layouts/spotlight/spotlight.html.erb +6 -6
- data/app/views/shared/_masthead.html.erb +4 -31
- data/app/views/shared/_site_sidebar.html.erb +1 -1
- data/app/views/shared/_user_util_links.html.erb +3 -1
- data/app/views/spotlight/accessibility/alt_text.html.erb +2 -2
- data/app/views/spotlight/admin_users/index.html.erb +3 -3
- data/app/views/spotlight/appearances/edit.html.erb +1 -1
- data/app/views/spotlight/browse/_search_box.html.erb +8 -8
- data/app/views/spotlight/browse/show.html.erb +1 -1
- data/app/views/spotlight/bulk_updates/_download.html.erb +1 -1
- data/app/views/spotlight/bulk_updates/_upload.html.erb +1 -1
- data/app/views/spotlight/catalog/_admin_header.html.erb +1 -1
- data/app/views/spotlight/catalog/_edit_default.html.erb +2 -1
- data/app/views/spotlight/catalog/select_image.html.erb +1 -0
- data/app/views/spotlight/contacts/_form.html.erb +1 -1
- data/app/views/spotlight/exhibits/_contact.html.erb +5 -6
- data/app/views/spotlight/exhibits/_delete.html.erb +1 -1
- data/app/views/spotlight/exhibits/_languages.html.erb +3 -2
- data/app/views/spotlight/featured_images/_form.html.erb +6 -2
- data/app/views/spotlight/featured_images/_upload_form.html.erb +1 -1
- data/app/views/spotlight/metadata_configurations/_metadata_field.html.erb +1 -1
- data/app/views/spotlight/metadata_configurations/edit.html.erb +6 -6
- data/app/views/spotlight/pages/show.html.erb +1 -1
- data/app/views/spotlight/resources/csv_upload/_form.html.erb +1 -1
- data/app/views/spotlight/resources/upload/_form.html.erb +1 -1
- data/app/views/spotlight/roles/index.html.erb +1 -1
- data/app/views/spotlight/searches/_form.html.erb +1 -1
- data/app/views/spotlight/shared/_dd3_item.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_solr_documents_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_uploaded_items_block.html.erb +1 -1
- data/app/views/spotlight/tags/index.html.erb +2 -3
- data/app/views/spotlight/translations/_import.html.erb +2 -2
- data/config/importmap.rb +5 -0
- data/config/locales/spotlight.en.yml +2 -0
- data/config/routes.rb +5 -3
- data/lib/generators/spotlight/assets/generator_common_utilities.rb +36 -0
- data/lib/generators/spotlight/assets/importmap_generator.rb +87 -0
- data/lib/generators/spotlight/assets/propshaft_generator.rb +96 -0
- data/lib/generators/spotlight/assets_generator.rb +22 -0
- data/lib/generators/spotlight/install_generator.rb +8 -36
- data/lib/generators/spotlight/scaffold_resource_generator.rb +1 -1
- data/lib/generators/spotlight/templates/assets/spotlight.scss +6 -0
- data/lib/generators/spotlight/templates/javascript/jquery-shim.js +1 -0
- data/lib/spotlight/engine.rb +7 -6
- data/lib/spotlight/version.rb +1 -1
- data/spec/support/features/capybara_wait_metadata_helper.rb +13 -0
- data/spec/support/features/test_features_helpers.rb +16 -30
- data/vendor/assets/javascripts/tiny-slider.js +3 -0
- metadata +37 -87
- data/app/assets/stylesheets/spotlight/#_accessibility.scss# +0 -12
- data/app/javascript/spotlight/admin/checkbox_submit.js +0 -75
- data/app/javascript/spotlight/admin/exhibit_tag_autocomplete.js +0 -39
- data/app/javascript/spotlight/user/report_a_problem.js +0 -30
- data/app/views/spotlight/browse/_tophat.html.erb +0 -1
- data/app/views/spotlight/catalog/_tophat_default.html.erb +0 -1
- data/app/views/spotlight/home_pages/_tophat.html.erb +0 -2
- data/app/views/spotlight/pages/_tophat.html.erb +0 -1
- data/lib/generators/spotlight/templates/spotlight.js +0 -1
- data/lib/generators/spotlight/templates/spotlight.scss +0 -5
- data/spec/support/features/capybara_default_max_wait_metadata_helper.rb +0 -20
- data/vendor/assets/javascripts/bootstrap-tagsinput.js +0 -530
- data/vendor/assets/javascripts/jquery.serializejson.js +0 -234
- data/vendor/assets/javascripts/nestable.js +0 -645
- data/vendor/assets/javascripts/sir-trevor.js +0 -23508
- data/vendor/assets/javascripts/typeahead.bundle.min.js +0 -7
- data/vendor/assets/stylesheets/bootstrap-tagsinput.css +0 -46
@@ -8,30 +8,26 @@ SirTrevor.Blocks.BrowseGroupCategories = (function(){
|
|
8
8
|
return Core.Block.Resources.extend({
|
9
9
|
type: "browse_group_categories",
|
10
10
|
icon_name: "browse",
|
11
|
-
bloodhoundOptions: function() {
|
12
|
-
var that = this;
|
13
|
-
return {
|
14
|
-
prefetch: {
|
15
|
-
url: this.autocomplete_url(),
|
16
|
-
ttl: 0,
|
17
|
-
filter: function(response) {
|
18
|
-
// Let the dom know that the response has been returned
|
19
|
-
$(that.inner).attr('data-browse-groups-fetched', true);
|
20
|
-
return response;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
};
|
24
|
-
},
|
25
11
|
|
26
12
|
autocomplete_control: function() {
|
27
|
-
|
13
|
+
const autocompleteID = this.blockID + '-autocomplete';
|
14
|
+
return `<auto-complete src="${this.autocomplete_url()}" for="${autocompleteID}-popup" fetch-on-empty>
|
15
|
+
<input type="text" name="${autocompleteID}" placeholder="${i18n.t("blocks:browse_group_categories:autocomplete")}" data-default-typeahead>
|
16
|
+
<ul id="${autocompleteID}-popup"></ul>
|
17
|
+
<div id="${autocompleteID}-popup-feedback" class="sr-only visually-hidden"></div>
|
18
|
+
</auto-complete>`
|
28
19
|
},
|
29
20
|
autocomplete_template: function(obj) {
|
30
21
|
return `<div class="autocomplete-item${!obj.published ? ' blacklight-private' : ''}">
|
31
|
-
<span class="autocomplete-title">${obj.title}</span><br/></div>`
|
22
|
+
<span class="autocomplete-title">${this.highlight(obj.title)}</span><br/></div>`
|
32
23
|
},
|
33
24
|
|
34
|
-
autocomplete_url: function() {
|
25
|
+
autocomplete_url: function() {
|
26
|
+
return document.getElementById(this.instanceID).closest('form[data-autocomplete-exhibit-browse-groups-path]').dataset.autocompleteExhibitBrowseGroupsPath;
|
27
|
+
},
|
28
|
+
autocomplete_fetch: function(url) {
|
29
|
+
return this.fetchOnceAndFilterLocalResults(url);
|
30
|
+
},
|
35
31
|
_itemPanel: function(data) {
|
36
32
|
var index = "item_" + this.globalIndex++;
|
37
33
|
var checked;
|
@@ -42,7 +38,7 @@ SirTrevor.Blocks.BrowseGroupCategories = (function(){
|
|
42
38
|
}
|
43
39
|
var resource_id = data.slug || data.id;
|
44
40
|
var markup = `
|
45
|
-
<li class="field
|
41
|
+
<li class="field dd-item dd3-item" data-resource-id="${resource_id}" data-id="${index}" id="${this.formId(index)}">
|
46
42
|
<input type="hidden" name="item[${index}][id]" value="${resource_id}" />
|
47
43
|
<input type="hidden" name="item[${index}][title]" value="${data.title}" />
|
48
44
|
<input data-property="weight" type="hidden" name="item[${index}][weight]" value="${data.weight}" />
|
@@ -7,20 +7,16 @@ SirTrevor.Blocks.FeaturedPages = (function(){
|
|
7
7
|
|
8
8
|
icon_name: "pages",
|
9
9
|
|
10
|
-
autocomplete_url: function() { return
|
10
|
+
autocomplete_url: function() { return document.getElementById(this.instanceID).closest('form[data-autocomplete-exhibit-pages-path]').dataset.autocompleteExhibitPagesPath; },
|
11
|
+
autocomplete_fetch: function(url) {
|
12
|
+
return this.fetchOnceAndFilterLocalResults(url);
|
13
|
+
},
|
11
14
|
autocomplete_template: function(obj) {
|
15
|
+
const description = obj.description ? `<small> ${obj.description}</small>` : '';
|
12
16
|
const thumbnail = obj.thumbnail_image_url ? `<div class="document-thumbnail"><img class="img-thumbnail" src="${obj.thumbnail_image_url}" /></div>` : ''
|
13
17
|
return `<div class="autocomplete-item${!obj.published ? ' blacklight-private' : ''}">${thumbnail}
|
14
|
-
<span class="autocomplete-title">${obj.title}</span><br
|
18
|
+
<span class="autocomplete-title">${this.highlight(obj.title)}</span><br/>${description}</div>`
|
15
19
|
},
|
16
|
-
bloodhoundOptions: function() {
|
17
|
-
return {
|
18
|
-
prefetch: {
|
19
|
-
url: this.autocomplete_url(),
|
20
|
-
ttl: 0
|
21
|
-
}
|
22
|
-
};
|
23
|
-
}
|
24
20
|
});
|
25
21
|
|
26
22
|
})();
|
@@ -8,11 +8,12 @@ Core.Block.Resources = (function(){
|
|
8
8
|
formable: true,
|
9
9
|
autocompleteable: true,
|
10
10
|
show_heading: true,
|
11
|
+
show_image_selection: true,
|
11
12
|
title: function() { return i18n.t("blocks:" + this.type + ":title"); },
|
12
13
|
description: function() { return i18n.t("blocks:" + this.type + ":description"); },
|
13
14
|
alt_text_guidelines: function() {
|
14
15
|
if (this.showAltText()) {
|
15
|
-
return i18n.t("blocks:alt_text_guidelines:intro");
|
16
|
+
return i18n.t("blocks:alt_text_guidelines:intro");
|
16
17
|
}
|
17
18
|
return "";
|
18
19
|
},
|
@@ -20,7 +21,7 @@ Core.Block.Resources = (function(){
|
|
20
21
|
if (this.showAltText()) {
|
21
22
|
var link_url = i18n.t("blocks:alt_text_guidelines:link_url");
|
22
23
|
var link_label = i18n.t("blocks:alt_text_guidelines:link_label");
|
23
|
-
return '<a target="_blank" href="' + link_url + '">' + link_label + '</a>';
|
24
|
+
return '<a target="_blank" href="' + link_url + '">' + link_label + '</a>';
|
24
25
|
}
|
25
26
|
return "";
|
26
27
|
},
|
@@ -59,7 +60,16 @@ Core.Block.Resources = (function(){
|
|
59
60
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
60
61
|
.join('');
|
61
62
|
},
|
62
|
-
|
63
|
+
_itemSelectImageLink: function(block_item_id, doc_id, index) {
|
64
|
+
// If image selection is not possible for this block, then do not show
|
65
|
+
// image selection link
|
66
|
+
if (!this.show_image_selection) return ``;
|
67
|
+
var url = $('form[data-exhibit-path]').data('exhibit-path') + '/select_image?';
|
68
|
+
var markup = `
|
69
|
+
<a name="selectimage" href="${url}block_item_id=${block_item_id}&index_id=${index}" data-blacklight-modal="trigger">Select image area</a>
|
70
|
+
`;
|
71
|
+
return markup;
|
72
|
+
},
|
63
73
|
_itemPanel: function(data) {
|
64
74
|
var index = "item_" + this.globalIndex++;
|
65
75
|
var checked;
|
@@ -69,8 +79,9 @@ Core.Block.Resources = (function(){
|
|
69
79
|
checked = "";
|
70
80
|
}
|
71
81
|
var resource_id = data.slug || data.id;
|
82
|
+
var block_item_id = this.formId(index);
|
72
83
|
var markup = `
|
73
|
-
<li class="field
|
84
|
+
<li class="field dd-item dd3-item" data-cropper="select_image_${block_item_id}" data-resource-id="${resource_id}" data-id="${index}" id="${block_item_id}" data-input-prefix="item[${index}]">
|
74
85
|
<input type="hidden" name="item[${index}][id]" value="${resource_id}" />
|
75
86
|
<input type="hidden" name="item[${index}][title]" value="${data.title}" />
|
76
87
|
${this._itemPanelIiifFields(index, data)}
|
@@ -79,13 +90,20 @@ Core.Block.Resources = (function(){
|
|
79
90
|
<div class="dd-handle dd3-handle">${i18n.t("blocks:resources:panel:drag")}</div>
|
80
91
|
<div class="card-header item-grid">
|
81
92
|
<div class="d-flex">
|
82
|
-
<div class="
|
83
|
-
<
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
93
|
+
<div class="d-inline-block">
|
94
|
+
<div class="d-flex">
|
95
|
+
<div class="checkbox">
|
96
|
+
<input name="item[${index}][display]" type="hidden" value="false" />
|
97
|
+
<input name="item[${index}][display]" id="${this.formId(this.display_checkbox + '_' + data.id)}" type="checkbox" ${checked} class="item-grid-checkbox" value="true" />
|
98
|
+
<label class="sr-only visually-hidden" for="${this.formId(this.display_checkbox + '_' + data.id)}">${i18n.t("blocks:resources:panel:display")}</label>
|
99
|
+
</div>
|
100
|
+
<div class="pic">
|
101
|
+
<img class="img-thumbnail" src="${(data.thumbnail_image_url || ((data.iiif_tilesource || "").replace("/info.json", "/full/!100,100/0/default.jpg")))}" />
|
102
|
+
</div>
|
103
|
+
</div>
|
104
|
+
<div class="d-inline-block">
|
105
|
+
${this._itemSelectImageLink(block_item_id,data.id, index)}
|
106
|
+
</div>
|
89
107
|
</div>
|
90
108
|
<div class="main">
|
91
109
|
<div class="title card-title">${data.title}</div>
|
@@ -118,7 +136,7 @@ Core.Block.Resources = (function(){
|
|
118
136
|
},
|
119
137
|
|
120
138
|
afterPanelRender: function(data, panel) {
|
121
|
-
|
139
|
+
|
122
140
|
},
|
123
141
|
|
124
142
|
afterPanelDelete: function() {
|
@@ -183,7 +201,7 @@ Core.Block.Resources = (function(){
|
|
183
201
|
<div class="me-2 mr-2">
|
184
202
|
<label class="col-form-label pb-0 pt-1" for="${this.formId(this.alt_text_textarea + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:alternative_text")}</label>
|
185
203
|
<div class="form-check mb-1 justify-content-end">
|
186
|
-
<input class="form-check-input" type="checkbox"
|
204
|
+
<input class="form-check-input" type="checkbox"
|
187
205
|
id="${this.formId(this.decorative_checkbox + '_' + data.id)}" name="item[${index}][decorative]" ${isDecorative ? 'checked' : ''}>
|
188
206
|
<label class="form-check-label" for="${this.formId(this.decorative_checkbox + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:decorative")}</label>
|
189
207
|
</div>
|
@@ -223,7 +241,6 @@ Core.Block.Resources = (function(){
|
|
223
241
|
|
224
242
|
onBlockRender: function() {
|
225
243
|
SpotlightNestable.init($('[data-behavior="nestable"]', this.inner));
|
226
|
-
|
227
244
|
$('[data-input-select-target]', this.inner).selectRelatedInput();
|
228
245
|
},
|
229
246
|
|
@@ -232,7 +249,8 @@ Core.Block.Resources = (function(){
|
|
232
249
|
$.each(Object.keys(data.item || {}).map(function(k) { return data.item[k]}).sort(function(a,b) { return a.weight - b.weight; }), function(index, item) {
|
233
250
|
context.createItemPanel(item);
|
234
251
|
});
|
235
|
-
|
252
|
+
|
253
|
+
}
|
236
254
|
});
|
237
255
|
|
238
256
|
})();
|
@@ -5,11 +5,11 @@ SirTrevor.Blocks.SolrDocumentsBase = (function(){
|
|
5
5
|
|
6
6
|
return Core.Block.Resources.extend({
|
7
7
|
plustextable: true,
|
8
|
-
autocomplete_url: function() { return this.$instance().closest('form[data-autocomplete-exhibit-catalog-path]').data('autocomplete-exhibit-catalog-path')
|
8
|
+
autocomplete_url: function() { return this.$instance().closest('form[data-autocomplete-exhibit-catalog-path]').data('autocomplete-exhibit-catalog-path') },
|
9
9
|
autocomplete_template: function(obj) {
|
10
10
|
const thumbnail = obj.thumbnail ? `<div class="document-thumbnail"><img class="img-thumbnail" src="${obj.thumbnail}" /></div>` : ''
|
11
11
|
return `<div class="autocomplete-item${obj.private ? ' blacklight-private' : ''}">${thumbnail}
|
12
|
-
<span class="autocomplete-title">${obj.title}</span><br/><small> ${obj.description}</small></div>`
|
12
|
+
<span class="autocomplete-title">${this.highlight(obj.title)}</span><br/><small> ${this.highlight(obj.description)}</small></div>`
|
13
13
|
},
|
14
14
|
transform_autocomplete_results: function(response) {
|
15
15
|
return $.map(response['docs'], function(doc) {
|
@@ -50,16 +50,21 @@ SirTrevor.Blocks.SolrDocumentsBase = (function(){
|
|
50
50
|
|
51
51
|
// Sets the first version of the IIIF information from autocomplete data.
|
52
52
|
_itemPanelIiifFields: function(index, autocomplete_data) {
|
53
|
-
|
54
|
-
// '<input type="hidden" name="item[' + index + '][iiif_region]" value="' + (data.iiif_region) + '"/>',
|
55
|
-
// for legacy compatiblity:
|
53
|
+
var iiifFields = [
|
56
54
|
'<input type="hidden" name="item[' + index + '][thumbnail_image_url]" value="' + (autocomplete_data.thumbnail_image_url || autocomplete_data.thumbnail || "") + '"/>',
|
57
55
|
'<input type="hidden" name="item[' + index + '][full_image_url]" value="' + (autocomplete_data.full_image_url || autocomplete_data.thumbnail_image_url || autocomplete_data.thumbnail || "") + '"/>',
|
58
56
|
'<input type="hidden" name="item[' + index + '][iiif_tilesource]" value="' + (autocomplete_data.iiif_tilesource) + '"/>',
|
59
57
|
'<input type="hidden" name="item[' + index + '][iiif_manifest_url]" value="' + (autocomplete_data.iiif_manifest_url) + '"/>',
|
60
58
|
'<input type="hidden" name="item[' + index + '][iiif_canvas_id]" value="' + (autocomplete_data.iiif_canvas_id) + '"/>',
|
61
59
|
'<input type="hidden" name="item[' + index + '][iiif_image_id]" value="' + (autocomplete_data.iiif_image_id) + '"/>',
|
62
|
-
]
|
60
|
+
];
|
61
|
+
|
62
|
+
// The region input is required for widgets that enable image cropping but not otherwise
|
63
|
+
if(this.show_image_selection) {
|
64
|
+
iiifFields.push('<input type="hidden" name="item[' + index + '][iiif_region]" value="' + (autocomplete_data.iiif_region || "") + '"/>');
|
65
|
+
}
|
66
|
+
|
67
|
+
return iiifFields.join("\n");
|
63
68
|
},
|
64
69
|
// Overwrites the hidden inputs from _itemPanelIiifFields with data from the
|
65
70
|
// manifest. Called by afterPanelRender - the manifest_data here is built
|
@@ -6,7 +6,8 @@ SirTrevor.Blocks.UploadedItems = (function(){
|
|
6
6
|
plustextable: true,
|
7
7
|
uploadable: true,
|
8
8
|
autocompleteable: false,
|
9
|
-
|
9
|
+
show_image_selection: false,
|
10
|
+
|
10
11
|
id_key: 'file',
|
11
12
|
|
12
13
|
type: 'uploaded_items',
|
@@ -70,7 +71,7 @@ SirTrevor.Blocks.UploadedItems = (function(){
|
|
70
71
|
var dataUrl = data.url || data.file.url;
|
71
72
|
|
72
73
|
var markup = `
|
73
|
-
<li class="field
|
74
|
+
<li class="field dd-item dd3-item" data-id="${index}" id="${this.formId(index)}">
|
74
75
|
<input type="hidden" name="item[${index}][id]" value="${dataId}" />
|
75
76
|
<input type="hidden" name="item[${index}][title]" value="${dataTitle}" />
|
76
77
|
<input type="hidden" name="item[${index}][url]" data-item-grid-thumbnail="true" value="${dataUrl}"/>
|
@@ -152,7 +153,7 @@ SirTrevor.Blocks.UploadedItems = (function(){
|
|
152
153
|
<div class="col-lg-3 ps-md-2 pl-md-2">
|
153
154
|
<label class="col-form-label text-nowrap pb-0 pt-1 justify-content-md-start justify-content-lg-end d-flex" for="${this.formId(this.alt_text_textarea + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:alternative_text")}</label>
|
154
155
|
<div class="form-check d-flex justify-content-md-start justify-content-lg-end">
|
155
|
-
<input class="form-check-input" type="checkbox"
|
156
|
+
<input class="form-check-input" type="checkbox"
|
156
157
|
id="${this.formId(this.decorative_checkbox + '_' + data.id)}" name="item[${index}][decorative]" ${isDecorative ? 'checked' : ''}>
|
157
158
|
<label class="form-check-label" for="${this.formId(this.decorative_checkbox + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:decorative")}</label>
|
158
159
|
</div>
|
@@ -2,22 +2,37 @@ import { addImageSelector } from 'spotlight/admin/add_image_selector'
|
|
2
2
|
import Core from 'spotlight/core'
|
3
3
|
|
4
4
|
export default class Crop {
|
5
|
-
constructor(cropArea) {
|
5
|
+
constructor(cropArea, preserveAspectRatio = true) {
|
6
6
|
this.cropArea = cropArea;
|
7
7
|
this.cropArea.data('iiifCropper', this);
|
8
|
+
// This element will also have the IIIF input elements contained
|
9
|
+
// There may be multiple elements with data-cropper attributes, but
|
10
|
+
// there should only one element with this data-cropper attribute value.
|
8
11
|
this.cropSelector = '[data-cropper="' + cropArea.data('cropperKey') + '"]';
|
9
12
|
this.cropTool = $(this.cropSelector);
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
this.
|
14
|
-
|
15
|
-
this.
|
16
|
-
|
13
|
+
// Exhibit and masthead cropping requires the ratio between image width and height
|
14
|
+
// to be consistent, whereas item widget cropping allows any combination of
|
15
|
+
// image width and height.
|
16
|
+
this.preserveAspectRatio = preserveAspectRatio;
|
17
|
+
// Get the IIIF input elements used to store/reference IIIF information
|
18
|
+
this.inputPrefix = this.cropTool.data('input-prefix');
|
19
|
+
this.iiifUrlField = this.iiifInputElement(this.inputPrefix, 'iiif_tilesource', this.cropTool);
|
20
|
+
this.iiifRegionField = this.iiifInputElement(this.inputPrefix, 'iiif_region', this.cropTool);
|
21
|
+
this.iiifManifestField = this.iiifInputElement(this.inputPrefix, 'iiif_manifest_url', this.cropTool);
|
22
|
+
this.iiifCanvasField = this.iiifInputElement(this.inputPrefix, 'iiif_canvas_id', this.cropTool);
|
23
|
+
this.iiifImageField = this.iiifInputElement(this.inputPrefix, 'iiif_image_id', this.cropTool);
|
24
|
+
// Get the closest form element
|
17
25
|
this.form = cropArea.closest('form');
|
18
26
|
this.tileSource = null;
|
19
27
|
}
|
20
28
|
|
29
|
+
// Return the iiif input element based on the fieldname.
|
30
|
+
// Multiple input fields with the same name on the page may be related
|
31
|
+
// to a cropper. We thus need to pass in a parent element.
|
32
|
+
iiifInputElement(inputPrefix, fieldName, inputParentElement) {
|
33
|
+
return $('input[name="' + inputPrefix + '[' + fieldName + ']"]', inputParentElement);
|
34
|
+
}
|
35
|
+
|
21
36
|
// Render the cropper environment and add hooks into the autocomplete and upload forms
|
22
37
|
render() {
|
23
38
|
this.setupAutoCompletes();
|
@@ -152,15 +167,21 @@ export default class Crop {
|
|
152
167
|
if (this.cropperMap) {
|
153
168
|
return;
|
154
169
|
}
|
155
|
-
|
170
|
+
|
171
|
+
var cropperOptions = {
|
156
172
|
editable: true,
|
157
173
|
center: [0, 0],
|
158
174
|
crs: L.CRS.Simple,
|
159
|
-
zoom: 0
|
160
|
-
|
175
|
+
zoom: 0
|
176
|
+
}
|
177
|
+
|
178
|
+
if(this.preserveAspectRatio) {
|
179
|
+
cropperOptions['editOptions'] = {
|
161
180
|
rectangleEditorClass: this.aspectRatioPreservingRectangleEditor(this.aspectRatio())
|
162
|
-
}
|
163
|
-
}
|
181
|
+
};
|
182
|
+
}
|
183
|
+
|
184
|
+
this.cropperMap = L.map(this.cropArea.attr('id'), cropperOptions);
|
164
185
|
this.invalidateMapSizeOnTabToggle();
|
165
186
|
}
|
166
187
|
|
@@ -228,9 +249,12 @@ export default class Crop {
|
|
228
249
|
}
|
229
250
|
|
230
251
|
var input = $('[data-behavior="autocomplete"]', this.cropTool);
|
231
|
-
|
232
|
-
|
233
|
-
|
252
|
+
|
253
|
+
// Not every page which uses this module has autocomplete linked directly to the cropping tool
|
254
|
+
if(input.length) {
|
255
|
+
var panel = $(input.data('target-panel'));
|
256
|
+
addImageSelector(input, panel, this.iiifManifestField.val(), !this.iiifImageField.val());
|
257
|
+
}
|
234
258
|
}
|
235
259
|
|
236
260
|
invalidateMapSizeOnTabToggle() {
|
@@ -280,7 +304,11 @@ export default class Crop {
|
|
280
304
|
}
|
281
305
|
|
282
306
|
setUploadId(id) {
|
283
|
-
|
307
|
+
// This input is currently used for exhibit masthead or thumbnail image upload.
|
308
|
+
// The name should be sufficient in this case, as we don't use this part of the
|
309
|
+
// code for solr document widgets where we enable cropping.
|
310
|
+
// If we require more specificity, we can scope this to this.cropTool.
|
311
|
+
$('input[name="' + this.inputPrefix + '[upload_id]"]').val(id);
|
284
312
|
}
|
285
313
|
|
286
314
|
aspectRatioPreservingRectangleEditor(aspect) {
|
@@ -1,10 +1,17 @@
|
|
1
1
|
import Crop from 'spotlight/admin/crop';
|
2
|
+
import CroppableModal from 'spotlight/admin/croppable_modal';
|
2
3
|
|
3
|
-
export default class {
|
4
|
+
export default class Croppable {
|
4
5
|
connect() {
|
6
|
+
// For exhibit masthead or thumbnail pages, where
|
7
|
+
// the div exists on page load
|
5
8
|
$('[data-behavior="iiif-cropper"]').each(function() {
|
6
9
|
var cropElement = $(this)
|
7
10
|
new Crop(cropElement).render()
|
8
11
|
})
|
12
|
+
|
13
|
+
// In the case of individual document thumbnails, selection
|
14
|
+
// of the image is through a modal. Here we attach the event
|
15
|
+
new CroppableModal().attachModalHandlers();
|
9
16
|
}
|
10
17
|
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import Crop from 'spotlight/admin/crop';
|
2
|
+
|
3
|
+
export default class CroppableModal {
|
4
|
+
|
5
|
+
attachModalHandlers() {
|
6
|
+
// Attach handler for when modal first loads, to show the cropper
|
7
|
+
this.attachModalLoadBehavior();
|
8
|
+
// Attach handler for save by checking if clicking in the modal is on a save button
|
9
|
+
this.attachModalSaveHandler();
|
10
|
+
}
|
11
|
+
|
12
|
+
attachModalLoadBehavior() {
|
13
|
+
// Listen for event thrown when modal is displayed with content
|
14
|
+
document.addEventListener('loaded.blacklight.blacklight-modal', function(e) {
|
15
|
+
var dataCropperDiv = $('#blacklight-modal [data-behavior="iiif-cropper"]');
|
16
|
+
|
17
|
+
if(dataCropperDiv) {
|
18
|
+
new Crop(dataCropperDiv, false).render();
|
19
|
+
}
|
20
|
+
});
|
21
|
+
}
|
22
|
+
|
23
|
+
// Field names are of the format item[item_0][iiif_image_id]
|
24
|
+
iiifInputField(itemIndex, fieldName, parentElement) {
|
25
|
+
var itemPrefix = 'item[' + itemIndex + ']';
|
26
|
+
var selector = 'input[name="' + itemPrefix + '[' + fieldName + ']"]';
|
27
|
+
return $(selector, parentElement);
|
28
|
+
}
|
29
|
+
|
30
|
+
attachModalSaveHandler() {
|
31
|
+
var context = this;
|
32
|
+
|
33
|
+
document.addEventListener('show.blacklight.blacklight-modal', function(e) {
|
34
|
+
$('#save-cropping-selection').on('click', () => {
|
35
|
+
context.saveCroppedRegion();
|
36
|
+
});
|
37
|
+
});
|
38
|
+
}
|
39
|
+
|
40
|
+
saveCroppedRegion() {
|
41
|
+
//On hitting "save changes", we need to copy over the value
|
42
|
+
//to the iiif thumbnail url input field as well as the image source itself
|
43
|
+
var context = this;
|
44
|
+
var dataCropperDiv = $('#blacklight-modal [data-behavior="iiif-cropper"]');
|
45
|
+
|
46
|
+
if(dataCropperDiv) {
|
47
|
+
var dataCropperKey = dataCropperDiv.data("cropper-key");
|
48
|
+
var itemIndex = dataCropperDiv.data("index-id");
|
49
|
+
// Get the element on the main edit page whose select image link opened up the modal
|
50
|
+
var itemElement = $('[data-cropper="' + dataCropperKey + '"]');
|
51
|
+
// Get the hidden input field on the main edit page corresponding to this item
|
52
|
+
var thumbnailSaveField = context.iiifInputField(itemIndex, 'thumbnail_image_url', itemElement);
|
53
|
+
var fullimageSaveField = context.iiifInputField(itemIndex, 'full_image_url', itemElement);
|
54
|
+
var iiifTilesource = context.iiifInputField(itemIndex, 'iiif_tilesource', itemElement).val();
|
55
|
+
var regionValue = context.iiifInputField(itemIndex, 'iiif_region', itemElement).val();
|
56
|
+
// Extract the region string to incorporate into the thumbnail URL
|
57
|
+
var urlPrefix = iiifTilesource.substring(0, iiifTilesource.lastIndexOf('/info.json'));
|
58
|
+
var thumbnailUrl = urlPrefix + '/' + regionValue + '/!400,400/0/default.jpg';
|
59
|
+
// Set the hidden input value to the thumbnail URL
|
60
|
+
// Also set the full image - which is used by widgets like carousel or slideshow
|
61
|
+
thumbnailSaveField.val(thumbnailUrl);
|
62
|
+
fullimageSaveField.val(urlPrefix + '/' + regionValue + '/!800,800/0/default.jpg');
|
63
|
+
// Also change img url for thumbnail image
|
64
|
+
var itemImage = $('img.img-thumbnail', itemElement);
|
65
|
+
itemImage.attr('src', thumbnailUrl);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
@@ -41,21 +41,26 @@ export default class {
|
|
41
41
|
$(inputContainer).insertAfter(contacts.last());
|
42
42
|
});
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
}
|
47
|
-
|
48
|
-
$('.contact-email-delete').on('ajax:error', function(event, _xhr, _status, error) {
|
49
|
-
var errSpan = $(this).closest('.contact').find('.contact-email-delete-error');
|
50
|
-
errSpan.show();
|
51
|
-
errSpan.find('.error-msg').first().text(error || event.detail[1]);
|
52
|
-
});
|
44
|
+
if (document.getElementById('another-email')) {
|
45
|
+
document.addEventListener('turbo:submit-end', this.contactToDeleteNotFoundHandler);
|
46
|
+
}
|
53
47
|
|
54
|
-
|
48
|
+
if ($.fn.tooltip) {
|
49
|
+
$('.btn-with-tooltip').tooltip();
|
50
|
+
}
|
55
51
|
|
56
52
|
// Put focus in saved search title input when Save this search modal is shown
|
57
53
|
$('#save-modal').on('shown.bs.modal', function () {
|
58
54
|
$('#search_title').focus();
|
59
55
|
});
|
60
56
|
}
|
57
|
+
|
58
|
+
contactToDeleteNotFoundHandler(e) {
|
59
|
+
const contact = e.detail.formSubmission?.delegate?.element?.querySelector('.contact')
|
60
|
+
if (contact && e.detail?.fetchResponse?.response?.status === 404) {
|
61
|
+
const error = contact.querySelector('.contact-email-delete-error');
|
62
|
+
error.style.display = 'block';
|
63
|
+
error.querySelector('.error-msg').textContent = 'Not Found';
|
64
|
+
}
|
65
|
+
}
|
61
66
|
}
|
@@ -68,7 +68,7 @@ export default class {
|
|
68
68
|
connect() {
|
69
69
|
// Instantiate the singleton SerializedForm plugin
|
70
70
|
var serializedForm = $.SerializedForm();
|
71
|
-
$(window).on('beforeunload page:before-change turbolinks:before-visit', function(event) {
|
71
|
+
$(window).on('beforeunload page:before-change turbolinks:before-visit turbo:before-visit', function(event) {
|
72
72
|
// Don't handle the same event twice #turbolinks
|
73
73
|
if (event.handled !== true) {
|
74
74
|
if ( serializedForm.observedFormsStatusHasChanged() ) {
|
@@ -1,18 +1,9 @@
|
|
1
|
-
// These scripts are in the vendor directory
|
2
|
-
import 'nestable'
|
3
|
-
import 'bootstrap-tagsinput'
|
4
|
-
import 'jquery.serializejson'
|
5
|
-
import 'leaflet-iiif'
|
6
|
-
import 'Leaflet.Editable'
|
7
|
-
import 'Path.Drag'
|
8
|
-
|
9
1
|
import AddAnother from 'spotlight/admin/add_another'
|
10
2
|
import AddNewButton from 'spotlight/admin/add_new_button'
|
11
3
|
import BlacklightConfiguration from 'spotlight/admin/blacklight_configuration'
|
12
4
|
import CopyEmailAddress from 'spotlight/admin/copy_email_addresses'
|
13
5
|
import Croppable from 'spotlight/admin/croppable'
|
14
6
|
import EditInPlace from 'spotlight/admin/edit_in_place'
|
15
|
-
import ExhibitTagAutocomplete from 'spotlight/admin/exhibit_tag_autocomplete'
|
16
7
|
import Exhibits from 'spotlight/admin/exhibits'
|
17
8
|
import FormObserver from 'spotlight/admin/form_observer'
|
18
9
|
import Locks from 'spotlight/admin/locks'
|
@@ -62,7 +53,6 @@ export default class {
|
|
62
53
|
new CopyEmailAddress().connect()
|
63
54
|
new Croppable().connect()
|
64
55
|
new EditInPlace().connect()
|
65
|
-
new ExhibitTagAutocomplete().connect()
|
66
56
|
new Exhibits().connect()
|
67
57
|
new FormObserver().connect()
|
68
58
|
new Locks().connect()
|
@@ -1,12 +1,22 @@
|
|
1
1
|
export default class {
|
2
2
|
delete_lock(el) {
|
3
|
-
|
4
|
-
|
3
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
|
4
|
+
|
5
|
+
fetch(el.dataset.lock, {
|
6
|
+
method: 'DELETE',
|
7
|
+
headers: {
|
8
|
+
'X-CSRF-Token': csrfToken
|
9
|
+
}
|
10
|
+
});
|
11
|
+
|
12
|
+
el.removeAttribute('data-lock');
|
5
13
|
}
|
6
14
|
|
7
15
|
connect() {
|
8
|
-
|
9
|
-
|
10
|
-
|
16
|
+
document.querySelectorAll('[data-lock]').forEach(element => {
|
17
|
+
element.addEventListener('click', (e) => {
|
18
|
+
this.delete_lock(e.target);
|
19
|
+
});
|
20
|
+
});
|
11
21
|
}
|
12
22
|
}
|
@@ -5,7 +5,7 @@ import Core from 'spotlight/core'
|
|
5
5
|
export default class {
|
6
6
|
connect(){
|
7
7
|
SirTrevor.setDefaults({
|
8
|
-
iconUrl: Spotlight.sirTrevorIcon
|
8
|
+
iconUrl: Spotlight.sirTrevorIcon,
|
9
9
|
uploadUrl: $('[data-attachment-endpoint]').data('attachment-endpoint'),
|
10
10
|
ajaxOptions: {
|
11
11
|
headers: {
|