-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Don't allow more than 1000 bookmarks
Co-authored-by: Kevin Reiss <kevinreiss@users.noreply.github.com> Co-authored-by: Max Kadel <maxkadel@users.noreply.github.com>
- Loading branch information
1 parent
11fe222
commit f426942
Showing
10 changed files
with
288 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Customize which blacklight javascripts are imported | ||
// See: https://github.com/projectblacklight/blacklight/wiki/Using-Sprockets-to-compile-javascript-assets | ||
|
||
|
||
//= require 'blacklight/core.js' | ||
|
||
//= import 'blacklight/autocomplete.js' | ||
//= require 'blacklight/bookmark_toggle.js' | ||
//= require 'blacklight/button_focus.js' | ||
//= require 'blacklight/facet_load.js' | ||
//= require 'blacklight/modal.js' | ||
//= require 'blacklight/search_context.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// From blacklight gem | ||
// The upstream file has changed substantially in Blacklight 8, | ||
// When we upgrade, we will need to update this file to match | ||
// the new API. | ||
|
||
/* A JQuery plugin (should this be implemented as a widget instead? not sure) | ||
that will convert a "toggle" form, with single submit button to add/remove | ||
something, like used for Bookmarks, into an AJAXy checkbox instead. | ||
Apply to a form. Does require certain assumption about the form: | ||
1) The same form 'action' href must be used for both ADD and REMOVE | ||
actions, with the different being the hidden input name="_method" | ||
being set to "put" or "delete" -- that's the Rails method to pretend | ||
to be doing a certain HTTP verb. So same URL, PUT to add, DELETE | ||
to remove. This plugin assumes that. | ||
Plus, the form this is applied to should provide a data-doc-id | ||
attribute (HTML5-style doc-*) that contains the id/primary key | ||
of the object in question -- used by plugin for a unique value for | ||
DOM id's. | ||
Uses HTML for a checkbox compatible with Bootstrap 3. | ||
Pass in options for your class name and labels: | ||
$("form.something").blCheckboxSubmit({ | ||
//cssClass is added to elements added, plus used for id base | ||
cssClass: "toggle_my_kinda_form", | ||
error: function() { | ||
#optional callback | ||
}, | ||
success: function(after_success_check_state) { | ||
#optional callback | ||
} | ||
}); | ||
*/ | ||
(function($) { | ||
$.fn.blCheckboxSubmit = function(argOpts) { | ||
this.each(function() { | ||
var options = $.extend({}, $.fn.blCheckboxSubmit.defaults, argOpts); | ||
|
||
|
||
var form = $(this); | ||
form.children().hide(); | ||
//We're going to use the existing form to actually send our add/removes | ||
//This works conveneintly because the exact same action href is used | ||
//for both bookmarks/$doc_id. But let's take out the irrelevant parts | ||
//of the form to avoid any future confusion. | ||
form.find('input[type=submit]').remove(); | ||
|
||
//View needs to set data-doc-id so we know a unique value | ||
//for making DOM id | ||
var uniqueId = form.attr('data-doc-id') || Math.random(); | ||
// if form is currently using method delete to change state, | ||
// then checkbox is currently checked | ||
var checked = (form.find('input[name=_method][value=delete]').length != 0); | ||
|
||
var checkbox = $('<input type="checkbox">') | ||
.addClass( options.cssClass ) | ||
.attr('id', options.cssClass + '_' + uniqueId); | ||
var label = $('<label>') | ||
.addClass( options.cssClass ) | ||
.attr('for', options.cssClass + '_' + uniqueId) | ||
.attr('title', form.attr('title') || ''); | ||
var span = $('<span>'); | ||
|
||
label.append(checkbox); | ||
label.append(' '); | ||
label.append(span); | ||
|
||
var checkboxDiv = $('<div class="checkbox" />') | ||
.addClass(options.cssClass) | ||
.append(label); | ||
|
||
function updateStateFor(state) { | ||
checkbox.prop('checked', state); | ||
label.toggleClass('checked', state); | ||
if (state) { | ||
//Set the Rails hidden field that fakes an HTTP verb | ||
//properly for current state action. | ||
form.find('input[name=_method]').val('delete'); | ||
span.html(form.attr('data-present')); | ||
} else { | ||
form.find('input[name=_method]').val('put'); | ||
span.html(form.attr('data-absent')); | ||
} | ||
} | ||
|
||
form.append(checkboxDiv); | ||
updateStateFor(checked); | ||
|
||
checkbox.click(function() { | ||
span.html(form.attr('data-inprogress')); | ||
label.attr('disabled', 'disabled'); | ||
checkbox.attr('disabled', 'disabled'); | ||
|
||
$.ajax({ | ||
url: form.attr('action'), | ||
dataType: 'json', | ||
type: form.attr('method').toUpperCase(), | ||
data: form.serialize(), | ||
error: function(data) { | ||
label.removeAttr('disabled'); | ||
checkbox.removeAttr('disabled'); | ||
options.error.call(form, data.responseJSON); | ||
updateStateFor(checked); | ||
}, | ||
success: function(data, status, xhr) { | ||
//if app isn't running at all, xhr annoyingly | ||
//reports success with status 0. | ||
if (xhr.status != 0) { | ||
checked = ! checked; | ||
updateStateFor(checked); | ||
label.removeAttr('disabled'); | ||
checkbox.removeAttr('disabled'); | ||
options.success.call(form, checked, xhr.responseJSON); | ||
} else { | ||
label.removeAttr('disabled'); | ||
checkbox.removeAttr('disabled'); | ||
options.error.call(form, xhr.responseJSON); | ||
} | ||
} | ||
}); | ||
|
||
return false; | ||
}); //checkbox.click | ||
|
||
|
||
}); //this.each | ||
return this; | ||
}; | ||
|
||
$.fn.blCheckboxSubmit.defaults = { | ||
//cssClass is added to elements added, plus used for id base | ||
cssClass: 'blCheckboxSubmit', | ||
error: function(json) { | ||
if (json && json.length && json[0]) { | ||
alert(json[0]); | ||
} else { | ||
alert("Error"); | ||
} | ||
}, | ||
success: function() {} //callback | ||
}; | ||
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
class Bookmark < ApplicationRecord | ||
belongs_to :user, polymorphic: true | ||
belongs_to :document, polymorphic: true | ||
validate :not_too_many_bookmarks, on: :create | ||
|
||
def document | ||
document_type.new document_type.unique_key => document_id | ||
end | ||
|
||
def document_type | ||
value = super if defined?(super) | ||
value &&= value.constantize | ||
value || default_document_type | ||
end | ||
|
||
def default_document_type | ||
SolrDocument | ||
end | ||
|
||
def not_too_many_bookmarks | ||
return if user.bookmarks.count < Orangelight.config['bookmarks']['maximum'] | ||
|
||
errors.add(:user, "You have exceeded the maximum number of bookmarks! You can only save up to #{Orangelight.config['bookmarks']['maximum']} bookmarks") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
require 'rails_helper' | ||
|
||
describe Bookmark do | ||
it 'does not allow user to create more than the maximum configured bookmarks' do | ||
user = FactoryBot.create(:user_with_many_bookmarks, | ||
bookmarks: Orangelight.config['bookmarks']['maximum']) | ||
expect do | ||
bookmark = described_class.new(user:, document_id: '123') | ||
bookmark.save! | ||
end.to raise_error(ActiveRecord::RecordInvalid) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters