blacklight-spotlight 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spotlight/check_user_existence.js +77 -0
  3. data/app/assets/javascripts/spotlight/users.js +7 -5
  4. data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +13 -3
  5. data/app/assets/stylesheets/spotlight/_header.scss +1 -0
  6. data/app/assets/stylesheets/spotlight/_variables.scss +2 -0
  7. data/app/controllers/spotlight/roles_controller.rb +29 -0
  8. data/app/models/concerns/spotlight/user.rb +5 -1
  9. data/app/models/spotlight/contact.rb +1 -1
  10. data/app/models/spotlight/custom_field.rb +1 -1
  11. data/app/models/spotlight/exhibit.rb +2 -0
  12. data/app/models/spotlight/page.rb +1 -1
  13. data/app/models/spotlight/search.rb +1 -1
  14. data/app/views/devise/mailer/invitation_instructions.html.erb +7 -0
  15. data/app/views/spotlight/roles/_edit_fields.html.erb +7 -1
  16. data/app/views/spotlight/roles/index.html.erb +8 -6
  17. data/config/locales/spotlight.en.yml +12 -1
  18. data/config/routes.rb +2 -0
  19. data/db/migrate/20151208085432_add_weight_to_exhibits.rb +5 -0
  20. data/lib/generators/spotlight/install_generator.rb +6 -0
  21. data/lib/spotlight/engine.rb +5 -1
  22. data/lib/spotlight/version.rb +1 -1
  23. data/spec/controllers/spotlight/exhibits_controller_spec.rb +4 -0
  24. data/spec/controllers/spotlight/roles_controller_spec.rb +51 -1
  25. data/spec/controllers/spotlight/searches_controller_spec.rb +4 -0
  26. data/spec/features/create_exhibit_spec.rb +1 -1
  27. data/spec/features/create_page_spec.rb +1 -4
  28. data/spec/features/curator_items.rb +2 -4
  29. data/spec/features/home_page_spec.rb +3 -9
  30. data/spec/features/import_exhibit_spec.rb +2 -12
  31. data/spec/features/javascript/about_page_admin_spec.rb +1 -7
  32. data/spec/features/javascript/block_controls_spec.rb +2 -5
  33. data/spec/features/javascript/blocks/uploaded_items_block_spec.rb +1 -1
  34. data/spec/features/javascript/feature_page_admin_spec.rb +6 -24
  35. data/spec/features/javascript/roles_admin_spec.rb +37 -0
  36. data/spec/features/javascript/search_config_admin_spec.rb +8 -20
  37. data/spec/features/javascript/search_context_spec.rb +12 -9
  38. data/spec/models/spotlight/page_spec.rb +21 -0
  39. data/spec/models/spotlight/search_spec.rb +21 -0
  40. data/spec/models/spotlight/user_spec.rb +25 -0
  41. data/spec/serializers/spotlight/exhibit_export_serializer_spec.rb +12 -0
  42. metadata +23 -4
  43. data/app/views/spotlight/catalog/_status_header.html.erb +0 -19
  44. data/db/migrate/20151204093112_add_reindexing_flag_to_spotlight_resources.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5017845fee1b7aec23f0ca3defacc0f32ad5ee02
4
- data.tar.gz: 0f84e6b1bac2250f6125a7d299718127b596ee40
3
+ metadata.gz: 04d55db45686c960c104b415057758f0f890225a
4
+ data.tar.gz: a5fe69056e63432730a864d937e56337f1fa679f
5
5
  SHA512:
6
- metadata.gz: fd56e28a84ec7f003693cce1c62252986002d850bad13745adc812e55faa288983f28c4cdc2bdcb2de3a1ba6d6f8f3b7ca31e161d54e55a621c8eb5faa86b611
7
- data.tar.gz: 43163422ed9ae1d38cd4a8b56786effebfc3d3e7a6e9f94a28ee99ef98b756efe5a87417f1d7c6ef0e02f86c8d790de0d4606678bde06034281164c6a548a698
6
+ metadata.gz: a4d9d682a2a7a8c4948ec1f92a7620019804fc5467bad97ad63b33c3e548e74845af3bb37e4a1b53b0fe6d475b00ffefc08b342b001ddb9ac5a992eaf4e49d92
7
+ data.tar.gz: f88c7ac71957e878187f799afd7f08bd54d7216bff08e7af74f05f7e1f9fc0624647e47cc1786f3c7bffa8225a407d80fe23061c3dded7ad2a722bfb30555803
@@ -0,0 +1,77 @@
1
+ (function($) {
2
+ $.fn.spotlightCheckUserExistence = function() {
3
+ var formElements = this;
4
+ var target;
5
+
6
+ $(formElements).each(function() {
7
+ $(this).on('blur', checkIfUserExists);
8
+ $(this).on('change', cleanUpBlankUserField);
9
+ });
10
+
11
+ function checkIfUserExists() {
12
+ target = $(this);
13
+ var form = target.closest('form');
14
+ if (target.val() !== '' && form[0].checkValidity()) {
15
+ $.ajax(userExistsUrl())
16
+ .success(userExists)
17
+ .fail(userDoesNotExist);
18
+ } else {
19
+ userExists();
20
+ }
21
+ }
22
+
23
+ function cleanUpBlankUserField() {
24
+ if ($(this).val() === '') {
25
+ userExists();
26
+ }
27
+ }
28
+
29
+ function userExists() {
30
+ noUserNote().hide();
31
+ submitButton().prop('disabled', false);
32
+ }
33
+
34
+ function userDoesNotExist() {
35
+ updateNoUserNoteLink();
36
+ noUserNote().show();
37
+ roleSelect().on('change', updateNoUserNoteLink);
38
+ submitButton().prop('disabled', true);
39
+ }
40
+
41
+ function updateNoUserNoteLink() {
42
+ var link = noUserNote().find('a');
43
+ var originalHref = link.data('inviteUrl');
44
+ var userName = target.val();
45
+ var role = roleSelect().val();
46
+ link.attr(
47
+ 'href',
48
+ originalHref + '?user=' + encodeURIComponent(userName) + '&role=' + encodeURIComponent(role)
49
+ );
50
+ }
51
+
52
+ function roleSelect() {
53
+ return target.closest('tr').find('select');
54
+ }
55
+
56
+ function noUserNote() {
57
+ return target.closest('td')
58
+ .find('[data-behavior="no-user-note"]');
59
+ }
60
+
61
+ function submitButton() {
62
+ return target.closest('tr')
63
+ .next('tr')
64
+ .find('input[type="submit"]');
65
+ }
66
+
67
+ function userExistsUrl() {
68
+ return $('[data-user-exists-url]').data('userExistsUrl') + '?user=' + target.val();
69
+ }
70
+
71
+ return this;
72
+ };
73
+ })(jQuery);
74
+
75
+ Spotlight.onLoad(function() {
76
+ $('[data-behavior="check-user-existence"]').spotlightCheckUserExistence();
77
+ });
@@ -1,6 +1,6 @@
1
1
  (function( $ ){
2
2
 
3
- $.fn.spotlight_users = function( options ) {
3
+ $.fn.spotlight_users = function( options ) {
4
4
 
5
5
  // Create some defaults, extending them with any options that were provided
6
6
  var settings = $.extend( { }, options);
@@ -27,13 +27,15 @@
27
27
  }
28
28
 
29
29
  function clear_errors(element) {
30
- element.find('.has-error').removeClass('has-error');
31
- element.find('.help-block').remove(); // Remove the error messages
30
+ element.find('.has-error')
31
+ .removeClass('has-error')
32
+ .find('.help-block')
33
+ .remove(); // Remove the error messages
32
34
  }
33
35
 
34
36
  function rollback_changes(element) {
35
37
  $.each(element.find('input[type="text"], select'), function() {
36
- $(this).val($(this).data('orig'));
38
+ $(this).val($(this).data('orig')).trigger('change');
37
39
  });
38
40
  }
39
41
 
@@ -58,7 +60,7 @@
58
60
  edit_row.next().show();
59
61
  }
60
62
 
61
- return this.each(function() {
63
+ return this.each(function() {
62
64
 
63
65
  container = $(this);
64
66
  $('[data-edit-for]', container).hide();
@@ -10,11 +10,11 @@
10
10
  margin-top: 10px;
11
11
  margin-left: 0;
12
12
  padding-left: 0;
13
-
13
+
14
14
  &.not-validated {
15
15
  margin-top: 0;
16
16
  }
17
-
17
+
18
18
  .confirmed {
19
19
  @extend .text-success;
20
20
  white-space: nowrap;
@@ -84,4 +84,14 @@
84
84
  }
85
85
 
86
86
  border-bottom: 1px solid $table-border-color;
87
- }
87
+ }
88
+
89
+ .pending-label {
90
+ display: none;
91
+ }
92
+
93
+ .invite-pending {
94
+ .pending-label {
95
+ display: inline;
96
+ }
97
+ }
@@ -41,6 +41,7 @@ $masthead-image-blur: 1px;
41
41
 
42
42
  &.page-masthead {
43
43
  @include transparent-masthead-navigation-menu();
44
+ background-color: $navbar-transparent-page-bg;
44
45
  border-bottom: 1px solid $navbar-transparent-border;
45
46
  margin-bottom: 0;
46
47
  margin-top: 0;
@@ -21,6 +21,8 @@ $navbar-transparent-link-active-bg: rgba(255, 255, 255, 0.3) !default;
21
21
  $navbar-transparent-link-disabled-color: #ccc !default;
22
22
  $navbar-transparent-link-disabled-bg: transparent !default;
23
23
 
24
+ $navbar-transparent-page-bg: rgba(0, 0, 0, 0.5) !default;
25
+
24
26
  // Navbar brand label
25
27
  $navbar-transparent-brand-color: $navbar-transparent-link-color !default;
26
28
  $navbar-transparent-brand-hover-color: darken($navbar-transparent-brand-color, 10%) !default;
@@ -30,12 +30,41 @@ module Spotlight
30
30
  end
31
31
  end
32
32
 
33
+ def exists
34
+ # note: the messages returned are not shown to users and really only useful for debug, hence no translation necessary
35
+ # app uses html status code to act on response
36
+ if ::User.where(email: exists_params).present?
37
+ render json: { message: 'User exists' }
38
+ else
39
+ render json: { message: 'User does not exist' }, status: :not_found
40
+ end
41
+ end
42
+
43
+ def invite
44
+ user = ::User.invite!(email: invite_params[:user], skip_invitation: true) # don't deliver the invitation yet
45
+ role = Spotlight::Role.create(exhibit: current_exhibit, user: user, role: invite_params[:role])
46
+ if role.save
47
+ user.deliver_invitation # now deliver it when we have saved the role
48
+ redirect_to :back, notice: t(:'helpers.submit.role.updated')
49
+ else
50
+ redirect_to :back, alert: t(:'helpers.submit.role.batch_error')
51
+ end
52
+ end
53
+
33
54
  protected
34
55
 
35
56
  def exhibit_params
36
57
  params.require(:exhibit).permit(roles_attributes: [:id, :user_key, :role, :_destroy])
37
58
  end
38
59
 
60
+ def invite_params
61
+ params.permit(:user, :role)
62
+ end
63
+
64
+ def exists_params
65
+ params.require(:user)
66
+ end
67
+
39
68
  # When nested attributes are passed in, ensure we have authorization to update each row.
40
69
  # @param attr [Hash,Array] the nested attributes
41
70
  # @param klass [Class] the class that is getting created
@@ -4,7 +4,7 @@ module Spotlight
4
4
  module User
5
5
  extend ActiveSupport::Concern
6
6
  included do
7
- has_many :roles, class_name: 'Spotlight::Role'
7
+ has_many :roles, class_name: 'Spotlight::Role', dependent: :destroy
8
8
 
9
9
  before_create :add_default_roles
10
10
  end
@@ -21,6 +21,10 @@ module Spotlight
21
21
  roles.build role: 'admin' unless self.class.any?
22
22
  end
23
23
 
24
+ def invite_pending?
25
+ invited_to_sign_up? && !invitation_accepted?
26
+ end
27
+
24
28
  alias_attribute :user_key, :email
25
29
 
26
30
  ##
@@ -42,7 +42,7 @@ module Spotlight
42
42
  protected
43
43
 
44
44
  def should_generate_new_friendly_id?
45
- name_changed?
45
+ super || (name_changed? && persisted?)
46
46
  end
47
47
  end
48
48
  end
@@ -102,7 +102,7 @@ module Spotlight
102
102
  end
103
103
 
104
104
  def should_generate_new_friendly_id?
105
- true
105
+ super || persisted?
106
106
  end
107
107
 
108
108
  # Try building a slug based on the following fields in
@@ -13,6 +13,8 @@ module Spotlight
13
13
  friendly_id :title, use: [:slugged, :finders]
14
14
  validates :title, presence: true
15
15
 
16
+ default_scope { order('weight ASC') }
17
+
16
18
  acts_as_tagger
17
19
  delegate :blacklight_config, to: :blacklight_configuration
18
20
  serialize :facets, Array
@@ -76,7 +76,7 @@ module Spotlight
76
76
  end
77
77
 
78
78
  def should_generate_new_friendly_id?
79
- title_changed?
79
+ super || (title_changed? && persisted?)
80
80
  end
81
81
 
82
82
  def should_display_title?
@@ -88,7 +88,7 @@ module Spotlight
88
88
  end
89
89
 
90
90
  def should_generate_new_friendly_id?
91
- title_changed?
91
+ super || (title_changed? && persisted?)
92
92
  end
93
93
 
94
94
  alias_method :current_exhibit, :exhibit
@@ -0,0 +1,7 @@
1
+ <p><%= t("spotlight.invitation_mailer.invitation_instructions.hello", email: @resource.email) %></p>
2
+
3
+ <p><%= t("spotlight.invitation_mailer.invitation_instructions.someone_invited_you", role: @resource.roles.first.role, exhibit_name: @resource.roles.first.exhibit.title, url: spotlight.exhibit_home_page_url(@resource.roles.first.exhibit)) %></p>
4
+
5
+ <p><%= link_to t("spotlight.invitation_mailer.invitation_instructions.accept"), accept_invitation_url(@resource, :invitation_token => @token) %></p>
6
+
7
+ <p><%= t("spotlight.invitation_mailer.invitation_instructions.ignore_html") %></p>
@@ -1,5 +1,11 @@
1
1
  <tr data-edit-for="<%= f.object.new_record? ? 'new' : f.object.id %>">
2
- <td><%= f.text_field :user_key, hide_label: true %></td>
2
+ <td>
3
+ <%= f.email_field :user_key, hide_label: true, disabled: f.object.persisted?, data: { behavior: 'check-user-existence' } %>
4
+ <span style='display:none' class='help-block' data-behavior='no-user-note'>
5
+ <%= t('.invite_html', link: link_to(t('.invite_link'), spotlight.invite_exhibit_roles_path(current_exhibit), data: { method: 'post', 'invite-url': spotlight.invite_exhibit_roles_path(current_exhibit) })) %>
6
+ <span class='label label-warning pending-label'><%= t('.pending') %></span>
7
+ </span>
8
+ </td>
3
9
  <td><%= f.select :role, roles_for_select, hide_label: true %></td>
4
10
  <td></td>
5
11
  </tr>
@@ -1,11 +1,10 @@
1
1
  <%= render 'spotlight/shared/exhibit_sidebar' %>
2
- <div id="content" class="col-md-9">
2
+ <div id="content" class="col-md-9" data-user-exists-url="<%= spotlight.exists_exhibit_roles_path(current_exhibit) %>">
3
3
  <%= configuration_page_title %>
4
- <%= bootstrap_form_for @exhibit, url: spotlight.update_all_exhibit_roles_path(@exhibit) do |f| %>
5
-
4
+ <%= bootstrap_form_for current_exhibit, url: spotlight.update_all_exhibit_roles_path(current_exhibit) do |f| %>
6
5
  <table class="table table-striped users">
7
6
  <thead>
8
- <th><%= t '.name' %></th>
7
+ <th><%= t '.email' %></th>
9
8
  <th><%= t '.role' %></th>
10
9
  <th><%= t '.actions' %></th>
11
10
  </thead>
@@ -25,8 +24,11 @@
25
24
  </td>
26
25
  </tr>
27
26
  <% else %>
28
- <tr data-show-for="<%= r.object.id %>">
29
- <td><%= r.object.user.to_s %></td>
27
+ <tr data-show-for="<%= r.object.id %>" class="<%= 'invite-pending' if r.object.user.invite_pending? %>">
28
+ <td>
29
+ <%= r.object.user.to_s %>
30
+ <span class='label label-warning pending-label'><%= t('.invite_pending') %></span>
31
+ </td>
30
32
  <td><%= r.object.role.humanize %></td>
31
33
  <td><%= link_to "#", data: {behavior: 'edit-user', target: r.object.id } do %>
32
34
  <span class="glyphicon glyphicon-edit"></span>
@@ -72,7 +72,7 @@ en:
72
72
  role:
73
73
  updated: "User has been updated."
74
74
  destroyed: "User has been removed."
75
- batch_error: "There was a problem saving the users."
75
+ batch_error: "There was a problem saving the user(s)."
76
76
  label:
77
77
  solr_document:
78
78
  exhibit_tag_list: "Tags"
@@ -261,6 +261,12 @@ en:
261
261
  non_repo_item: "Add non-repository item"
262
262
  new:
263
263
  header: Import items
264
+ invitation_mailer:
265
+ invitation_instructions:
266
+ hello: "Hello %{email}!"
267
+ someone_invited_you: "The Exhibits Administrator has invited to be a member of '%{exhibit_name}' at %{url}. You can accept it through the link below."
268
+ accept: "Accept invitation"
269
+ ignore_html: "If you don't want to accept the invitation, please ignore this email.<br />Your account won't be created until you access the link above."
264
270
  confirmation_mailer:
265
271
  confirmation_instructions:
266
272
  welcome: "Welcome %{email}!"
@@ -466,10 +472,15 @@ en:
466
472
  bookmarklet: "%{application_name} widget"
467
473
  reindexing_in_progress: "Reindexing all resources"
468
474
  roles:
475
+ edit_fields:
476
+ invite_html: "This user does not yet exist. Would you like to send them an %{link}?"
477
+ invite_link: invite
469
478
  index:
470
479
  title: Site Configuration - Users
480
+ invite_pending: pending
471
481
  header: Users
472
482
  name: Username
483
+ email: "Email Address"
473
484
  role: "Role"
474
485
  actions: "Actions"
475
486
  searches: &search
@@ -88,6 +88,8 @@ Spotlight::Engine.routes.draw do
88
88
 
89
89
  resources :roles, path: 'users', only: [:index, :create, :destroy] do
90
90
  collection do
91
+ get :exists
92
+ post :invite
91
93
  patch :update_all
92
94
  end
93
95
  end
@@ -0,0 +1,5 @@
1
+ class AddWeightToExhibits < ActiveRecord::Migration
2
+ def up
3
+ add_column :spotlight_exhibits, :weight, :integer, default: 50
4
+ end
5
+ end
@@ -121,5 +121,11 @@ module Spotlight
121
121
  copy_file 'jetty.rake', 'lib/tasks/jetty.rake'
122
122
  directory 'solr_conf'
123
123
  end
124
+
125
+ def generate_devise_invitable
126
+ gem 'devise_invitable'
127
+ generate 'devise_invitable:install'
128
+ generate 'devise_invitable', 'User'
129
+ end
124
130
  end
125
131
  end
@@ -1,9 +1,13 @@
1
1
  # Load blacklight which will give spotlight views a higher preference than those in blacklight
2
+
3
+ # devise must be required to first to ensure we can override devise and invitable views in spotlight correctly
4
+ require 'devise'
5
+ require 'devise_invitable'
6
+
2
7
  require 'blacklight'
3
8
  require 'blacklight/oembed'
4
9
  require 'autoprefixer-rails'
5
10
  require 'friendly_id'
6
- require 'devise'
7
11
  require 'tophat'
8
12
  require 'paper_trail'
9
13
 
@@ -1,4 +1,4 @@
1
1
  #
2
2
  module Spotlight
3
- VERSION = '0.11.0'
3
+ VERSION = '0.12.0'
4
4
  end
@@ -4,6 +4,10 @@ describe Spotlight::ExhibitsController, type: :controller do
4
4
  routes { Spotlight::Engine.routes }
5
5
  let(:exhibit) { FactoryGirl.create(:exhibit) }
6
6
 
7
+ before do
8
+ allow(Spotlight::DefaultThumbnailJob).to receive(:perform_later)
9
+ end
10
+
7
11
  describe 'when the user is not authorized' do
8
12
  before do
9
13
  sign_in FactoryGirl.create(:exhibit_visitor)
@@ -71,7 +71,57 @@ describe Spotlight::RolesController, type: :controller do
71
71
  }
72
72
  }
73
73
  expect(response).to be_successful
74
- expect(flash[:alert]).to eq 'There was a problem saving the users.'
74
+ expect(flash[:alert]).to eq 'There was a problem saving the user(s).'
75
+ end
76
+ end
77
+
78
+ describe 'GET exists' do
79
+ it 'requires a user parameter' do
80
+ expect do
81
+ get :exists, exhibit_id: exhibit
82
+ end.to raise_error(ActionController::ParameterMissing)
83
+ end
84
+
85
+ it 'returns a successful status when the requested user exists' do
86
+ user = FactoryGirl.create(:exhibit_curator)
87
+ get :exists, exhibit_id: exhibit, user: user.email
88
+ expect(response).to be_success
89
+ end
90
+
91
+ it 'returns an unsuccessful status when the user does not exist' do
92
+ get :exists, exhibit_id: exhibit, user: 'user@example.com'
93
+ expect(response).not_to be_success
94
+ expect(response.status).to eq 404
95
+ end
96
+ end
97
+
98
+ describe 'GET invite' do
99
+ before { request.env['HTTP_REFERER'] = 'http://example.com' }
100
+
101
+ it 'invites the selected user' do
102
+ expect do
103
+ post :invite, exhibit_id: exhibit, user: 'user@example.com', role: 'curator'
104
+ end.to change { ::User.count }.by(1)
105
+ expect(::User.last.roles.length).to eq 1
106
+ expect(::User.last.roles.first.exhibit).to eq exhibit
107
+ end
108
+
109
+ it 'adds the user to the exhibit via a role' do
110
+ expect do
111
+ post :invite, exhibit_id: exhibit, user: 'user@example.com', role: 'curator'
112
+ end.to change { Spotlight::Role.count }.by(1)
113
+ end
114
+
115
+ it 'redirects back with a flash notice upon success' do
116
+ post :invite, exhibit_id: exhibit, user: 'user@example.com', role: 'curator'
117
+ expect(flash[:notice]).to eq 'User has been updated.'
118
+ expect(response).to redirect_to(:back)
119
+ end
120
+
121
+ it 'redirects back with flash error upon failure' do
122
+ post :invite, exhibit_id: exhibit, user: 'user@example.com', role: 'not-a-real-role'
123
+ expect(flash[:alert]).to eq 'There was a problem saving the user(s).'
124
+ expect(response).to redirect_to(:back)
75
125
  end
76
126
  end
77
127
  end
@@ -4,6 +4,10 @@ describe Spotlight::SearchesController, type: :controller do
4
4
  routes { Spotlight::Engine.routes }
5
5
  let(:exhibit) { FactoryGirl.create(:exhibit) }
6
6
 
7
+ before do
8
+ allow(Spotlight::DefaultThumbnailJob).to receive(:perform_later)
9
+ end
10
+
7
11
  describe 'when the user is not authorized' do
8
12
  before do
9
13
  sign_in FactoryGirl.create(:exhibit_visitor)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe 'Create a new exhibit', type: :feature do
4
4
  let(:user) { FactoryGirl.create(:site_admin) }
5
5
  before do
6
- allow_any_instance_of(Spotlight::Search).to receive(:set_default_featured_image)
6
+ allow(Spotlight::DefaultThumbnailJob).to receive(:perform_later)
7
7
  login_as user
8
8
  end
9
9
 
@@ -10,10 +10,7 @@ describe 'Creating a page', type: :feature do
10
10
  let!(:page3) { FactoryGirl.create(:about_page, exhibit: exhibit, title: 'A new one') }
11
11
  it 'is able to show a list of About pages to be curated' do
12
12
  login_as exhibit_curator
13
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
14
- within '#user-util-collapse .dropdown' do
15
- click_link 'Dashboard'
16
- end
13
+ visit spotlight.exhibit_dashboard_path(exhibit)
17
14
  within '#sidebar' do
18
15
  click_link 'About pages'
19
16
  end
@@ -2,14 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe 'A curator can see the items page', type: :feature do
4
4
  let(:exhibit_curator) { FactoryGirl.create(:exhibit_curator) }
5
+ let(:exhibit) { FactoryGirl.create(:exhibit) }
5
6
 
6
7
  it 'works' do
7
8
  login_as exhibit_curator
9
+ visit spotlight.exhibit_dashboard_path(exhibit)
8
10
 
9
- visit '/'
10
- within '.dropdown-menu' do
11
- click_link 'Dashboard'
12
- end
13
11
  expect(page).to have_content 'Items'
14
12
  end
15
13
  end
@@ -4,20 +4,14 @@ describe 'Home page', type: :feature do
4
4
  let(:exhibit_curator) { FactoryGirl.create(:exhibit_curator, exhibit: exhibit) }
5
5
  before { login_as exhibit_curator }
6
6
  it 'exists by default on exhibits' do
7
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
8
- within '#user-util-collapse .dropdown-menu' do
9
- click_link 'Dashboard'
10
- end
7
+ visit spotlight.exhibit_dashboard_path(exhibit)
11
8
  click_link 'Feature pages'
12
9
  expect(page).to have_selector 'h3', text: 'Homepage'
13
10
  expect(page).to have_selector 'h3.panel-title', text: 'Exhibit Home'
14
11
  end
15
12
 
16
13
  it 'allows users to edit the home page title' do
17
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
18
- within '#user-util-collapse .dropdown-menu' do
19
- click_link 'Dashboard'
20
- end
14
+ visit spotlight.exhibit_dashboard_path(exhibit)
21
15
  click_link 'Feature pages'
22
16
  within('.home_page') do
23
17
  click_link 'Edit'
@@ -83,7 +77,7 @@ describe 'Home page', type: :feature do
83
77
  exhibit.home_page.save
84
78
  end
85
79
  it 'does not display the facet sidebar' do
86
- visit spotlight.exhibit_home_page_path(exhibit.home_page)
80
+ visit spotlight.exhibit_home_page_path(exhibit)
87
81
  expect(page).not_to have_css('#sidebar')
88
82
  end
89
83
  end
@@ -10,12 +10,7 @@ describe 'Allow exhibit admins to import and export content from an exhibit', ty
10
10
  pending(%(There's not really any good way to test the contents of a
11
11
  downloaded file with Poltergeist (which is now necessary since we've moved
12
12
  the export option behind a bootstrap tab)))
13
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
14
-
15
- click_link user.email
16
- within '#user-util-collapse .dropdown-menu' do
17
- click_link 'Dashboard'
18
- end
13
+ visit spotlight.exhibit_dashboard_path(exhibit)
19
14
 
20
15
  click_link 'General'
21
16
  within('.nav-tabs') do
@@ -31,12 +26,7 @@ the export option behind a bootstrap tab)))
31
26
  end
32
27
 
33
28
  it 'allows admins to import content into an exhibit' do
34
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
35
-
36
- click_link user.email
37
- within '#user-util-collapse .dropdown-menu' do
38
- click_link 'Dashboard'
39
- end
29
+ visit spotlight.exhibit_dashboard_path(exhibit)
40
30
 
41
31
  click_link 'General'
42
32
 
@@ -7,13 +7,7 @@ feature 'About Pages Adminstration', js: true do
7
7
 
8
8
  it 'is able to create new pages' do
9
9
  login_as exhibit_curator
10
-
11
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
12
- click_link exhibit_curator.email
13
-
14
- within '#user-util-collapse .dropdown' do
15
- click_link 'Dashboard'
16
- end
10
+ visit spotlight.exhibit_dashboard_path(exhibit)
17
11
 
18
12
  click_link 'About pages'
19
13
 
@@ -7,11 +7,8 @@ feature 'Block controls' do
7
7
 
8
8
  scenario 'should be split into separate sections', js: true do
9
9
  # create page
10
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
11
- click_link exhibit_curator.email
12
- within '#user-util-collapse .dropdown' do
13
- click_link 'Dashboard'
14
- end
10
+ visit spotlight.exhibit_dashboard_path(exhibit)
11
+
15
12
  click_link 'Feature pages'
16
13
 
17
14
  add_new_page_via_button('My New Feature Page')
@@ -45,7 +45,7 @@ feature 'Uploaded Items Block', feature: true, js: true do
45
45
  end
46
46
  end
47
47
 
48
- scenario 'users can to toggle individual images to not display' do
48
+ scenario 'users can toggle individual images to not display' do
49
49
  attach_file('uploaded_item_url', fixture_file1)
50
50
  attach_file('uploaded_item_url', fixture_file2)
51
51
 
@@ -18,16 +18,11 @@ feature 'Feature Pages Adminstration', js: true do
18
18
  display_sidebar: true
19
19
  )
20
20
  end
21
- before { login_as exhibit_curator }
22
- it 'is able to create new pages' do
23
- login_as exhibit_curator
24
21
 
25
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
26
- click_link exhibit_curator.email
22
+ before { login_as exhibit_curator }
27
23
 
28
- within '#user-util-collapse .dropdown' do
29
- click_link 'Dashboard'
30
- end
24
+ it 'is able to create new pages' do
25
+ visit spotlight.exhibit_dashboard_path(exhibit)
31
26
 
32
27
  click_link 'Feature pages'
33
28
 
@@ -39,12 +34,7 @@ feature 'Feature Pages Adminstration', js: true do
39
34
  end
40
35
 
41
36
  it 'updates the page titles' do
42
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
43
- click_link exhibit_curator.email
44
-
45
- within '#user-util-collapse .dropdown' do
46
- click_link 'Dashboard'
47
- end
37
+ visit spotlight.exhibit_dashboard_path(exhibit)
48
38
 
49
39
  click_link 'Feature pages'
50
40
  within("[data-id='#{page1.id}']") do
@@ -84,11 +74,7 @@ feature 'Feature Pages Adminstration', js: true do
84
74
  end
85
75
 
86
76
  it 'does not update the pages list when the user has unsaved changes' do
87
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
88
- click_link exhibit_curator.email
89
- within '#user-util-collapse .dropdown' do
90
- click_link 'Dashboard'
91
- end
77
+ visit spotlight.exhibit_dashboard_path(exhibit)
92
78
 
93
79
  click_link 'Feature pages'
94
80
  within("[data-id='#{page1.id}']") do
@@ -122,11 +108,7 @@ feature 'Feature Pages Adminstration', js: true do
122
108
  end
123
109
 
124
110
  it 'is able to update home page titles' do
125
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
126
- click_link exhibit_curator.email
127
- within '#user-util-collapse .dropdown' do
128
- click_link 'Dashboard'
129
- end
111
+ visit spotlight.exhibit_dashboard_path(exhibit)
130
112
 
131
113
  click_link 'Feature pages'
132
114
 
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Roles Admin', type: :feature, js: true do
4
+ let(:exhibit) { FactoryGirl.create(:exhibit) }
5
+ let(:exhibit_admin) { FactoryGirl.create(:exhibit_admin, exhibit: exhibit) }
6
+ before do
7
+ login_as exhibit_admin
8
+
9
+ visit spotlight.exhibit_dashboard_path(exhibit)
10
+ click_link 'Users'
11
+ end
12
+
13
+ it 'informs the admin that a user they are trying to add does not yet exist' do
14
+ expect(page).to have_css('.help-block[data-behavior="no-user-note"]', visible: false)
15
+ expect(page).not_to have_css('input[disabled]')
16
+
17
+ click_link 'Add a new user'
18
+ fill_in 'User key', with: 'user@example.com'
19
+
20
+ expect(page).to have_css('.help-block[data-behavior="no-user-note"]', visible: true)
21
+ expect(page).to have_link('invite', visible: true)
22
+ expect(page).to have_css('input[disabled]')
23
+ end
24
+
25
+ it 'persists invited users to the exhibits user list' do
26
+ expect(page).not_to have_css('.label-warning pending-label', text: 'pending', visible: true)
27
+
28
+ click_link 'Add a new user'
29
+ fill_in 'User key', with: 'user@example.com'
30
+ click_link 'invite'
31
+
32
+ within('tr.invite-pending') do
33
+ expect(page).to have_css('td', text: 'user@example.com')
34
+ expect(page).to have_css('.label-warning.pending-label', text: 'pending', visible: true)
35
+ end
36
+ end
37
+ end
@@ -27,11 +27,8 @@ feature 'Search Configuration Administration', js: true do
27
27
  end
28
28
 
29
29
  it 'allows the curator to update search field options' do
30
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
31
- click_link user.email
32
- within '#user-util-collapse .dropdown' do
33
- click_link 'Dashboard'
34
- end
30
+ visit spotlight.exhibit_dashboard_path(exhibit)
31
+
35
32
  click_link 'Search'
36
33
 
37
34
  click_link 'Options'
@@ -55,11 +52,8 @@ feature 'Search Configuration Administration', js: true do
55
52
  describe 'facets' do
56
53
  it 'allows us to update the label with edit-in-place' do
57
54
  input_id = 'blacklight_configuration_facet_fields_genre_ssim_label'
58
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
59
- click_link user.email
60
- within '#user-util-collapse .dropdown' do
61
- click_link 'Dashboard'
62
- end
55
+ visit spotlight.exhibit_dashboard_path(exhibit)
56
+
63
57
  click_link 'Search'
64
58
 
65
59
  click_link 'Facets'
@@ -105,11 +99,8 @@ feature 'Search Configuration Administration', js: true do
105
99
 
106
100
  describe 'results' do
107
101
  it 'updates search result options' do
108
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
109
- click_link user.email
110
- within '#user-util-collapse .dropdown' do
111
- click_link 'Dashboard'
112
- end
102
+ visit spotlight.exhibit_dashboard_path(exhibit)
103
+
113
104
  click_link 'Search'
114
105
 
115
106
  click_link 'Results'
@@ -131,11 +122,8 @@ feature 'Search Configuration Administration', js: true do
131
122
  expect(field_labeled('10')).to_not be_checked
132
123
  end
133
124
  it 'updates Sort field result options' do
134
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
135
- click_link user.email
136
- within '#user-util-collapse .dropdown' do
137
- click_link 'Dashboard'
138
- end
125
+ visit spotlight.exhibit_dashboard_path(exhibit)
126
+
139
127
  click_link 'Search'
140
128
 
141
129
  click_link 'Results'
@@ -71,14 +71,17 @@ feature 'Search contexts' do
71
71
  expect(page).to have_link 'FeaturePage1', href: spotlight.exhibit_feature_page_path(exhibit, feature_page)
72
72
  end
73
73
 
74
- scenario 'should add context breadcrumbs back to the browse page when navigating to an item from a browse page', js: true do
75
- search = Spotlight::Search.create! exhibit_id: exhibit.id, title: 'Some Saved Search', published: true
76
- visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
77
- click_link 'Browse'
78
- click_link 'Some Saved Search'
79
- click_link 'A MAP of AMERICA from the latest and best Observations'
80
- expect(page).to have_link 'Home'
81
- expect(page).to have_link 'Browse'
82
- expect(page).to have_link 'Some Saved Search', href: spotlight.exhibit_browse_path(exhibit, search)
74
+ context 'from a browse page' do
75
+ let!(:search) { FactoryGirl.create(:search, title: 'Some Saved Search', exhibit: exhibit, published: true) }
76
+
77
+ scenario 'should add context breadcrumbs back to the browse page when navigating to an item', js: true do
78
+ visit spotlight.exhibit_home_page_path(exhibit, exhibit.home_page)
79
+ click_link 'Browse'
80
+ click_link 'Some Saved Search'
81
+ click_link 'A MAP of AMERICA from the latest and best Observations'
82
+ expect(page).to have_link 'Home'
83
+ expect(page).to have_link 'Browse'
84
+ expect(page).to have_link 'Some Saved Search', href: spotlight.exhibit_browse_path(exhibit, search)
85
+ end
83
86
  end
84
87
  end
@@ -74,4 +74,25 @@ describe Spotlight::Page, type: :model do
74
74
  expect(page).to have_content
75
75
  end
76
76
  end
77
+
78
+ describe '#slug' do
79
+ let(:page) { FactoryGirl.create(:feature_page) }
80
+
81
+ it 'gets a default slug' do
82
+ expect(page.slug).not_to be_blank
83
+ end
84
+
85
+ it 'is updated when the title changes' do
86
+ page.update(title: 'abc')
87
+ expect(page.slug).to eq 'abc'
88
+ end
89
+
90
+ context 'with a custom slug' do
91
+ let(:page) { FactoryGirl.create(:feature_page, slug: 'xyz') }
92
+
93
+ it 'gets a default slug' do
94
+ expect(page.slug).to eq 'xyz'
95
+ end
96
+ end
97
+ end
77
98
  end
@@ -58,4 +58,25 @@ describe Spotlight::Search, type: :model do
58
58
  expect(described_class.published.map(&:weight)).to eq [1, 5, 10]
59
59
  end
60
60
  end
61
+
62
+ describe '#slug' do
63
+ let(:search) { FactoryGirl.create(:search) }
64
+
65
+ it 'gets a default slug' do
66
+ expect(search.slug).not_to be_blank
67
+ end
68
+
69
+ it 'is updated when the title changes' do
70
+ search.update(title: 'abc')
71
+ expect(search.slug).to eq 'abc'
72
+ end
73
+
74
+ context 'with a custom slug' do
75
+ let(:search) { FactoryGirl.create(:search, slug: 'xyz') }
76
+
77
+ it 'gets a default slug' do
78
+ expect(search.slug).to eq 'xyz'
79
+ end
80
+ end
81
+ end
61
82
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spotlight::User do
4
+ subject { Class.new }
5
+ before { subject.extend described_class }
6
+
7
+ describe '#invite_pending?' do
8
+ it 'is false if the user was never invited in the first place' do
9
+ expect(subject).to receive_messages(invited_to_sign_up?: false)
10
+ expect(subject.invite_pending?).to be false
11
+ end
12
+
13
+ it 'is true if the user was invited but has not accepted' do
14
+ expect(subject).to receive_messages(invited_to_sign_up?: true)
15
+ expect(subject).to receive_messages(invitation_accepted?: false)
16
+ expect(subject.invite_pending?).to be true
17
+ end
18
+
19
+ it 'is false if the user was invited and has accpeted the invite' do
20
+ expect(subject).to receive_messages(invited_to_sign_up?: true)
21
+ expect(subject).to receive_messages(invitation_accepted?: true)
22
+ expect(subject.invite_pending?).to be false
23
+ end
24
+ end
25
+ end
@@ -176,6 +176,14 @@ describe Spotlight::ExhibitExportSerializer do
176
176
  expect(subject.feature_pages.first.child_pages.length).to eq 1
177
177
  end
178
178
 
179
+ context 'page slugs' do
180
+ let!(:feature_page) { FactoryGirl.create(:feature_page, exhibit: source_exhibit, slug: 'xyz') }
181
+
182
+ it 'uses the existing slug for the page' do
183
+ expect(subject.feature_pages.find('xyz')).to be_persisted
184
+ end
185
+ end
186
+
179
187
  context 'with a feature page' do
180
188
  let(:feature_page) { FactoryGirl.create(:feature_page, exhibit: source_exhibit) }
181
189
  let(:thumbnail) { FactoryGirl.create(:featured_image) }
@@ -341,6 +349,10 @@ describe Spotlight::ExhibitExportSerializer do
341
349
  source_exhibit.searches.create title: 'custom query', slug: 'xyz', published: true
342
350
  end
343
351
 
352
+ before do
353
+ allow(Spotlight::DefaultThumbnailJob).to receive(:perform_later)
354
+ end
355
+
344
356
  it 'creates a search within the exhibit' do
345
357
  expect(subject.feature_pages.first.content.first.search.exhibit).to eq subject
346
358
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacklight-spotlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Beer
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-12-07 00:00:00.000000000 Z
14
+ date: 2015-12-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -263,6 +263,20 @@ dependencies:
263
263
  - - "~>"
264
264
  - !ruby/object:Gem::Version
265
265
  version: '3.0'
266
+ - !ruby/object:Gem::Dependency
267
+ name: devise_invitable
268
+ requirement: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - "~>"
271
+ - !ruby/object:Gem::Version
272
+ version: '1.5'
273
+ type: :runtime
274
+ prerelease: false
275
+ version_requirements: !ruby/object:Gem::Requirement
276
+ requirements:
277
+ - - "~>"
278
+ - !ruby/object:Gem::Version
279
+ version: '1.5'
266
280
  - !ruby/object:Gem::Dependency
267
281
  name: roar-rails
268
282
  requirement: !ruby/object:Gem::Requirement
@@ -724,6 +738,7 @@ files:
724
738
  - app/assets/javascripts/spotlight/blocks/solr_documents_grid_block.js
725
739
  - app/assets/javascripts/spotlight/blocks/uploaded_items_block.js
726
740
  - app/assets/javascripts/spotlight/catalog_edit.js
741
+ - app/assets/javascripts/spotlight/check_user_existence.js
727
742
  - app/assets/javascripts/spotlight/compat.js
728
743
  - app/assets/javascripts/spotlight/croppable.js
729
744
  - app/assets/javascripts/spotlight/edit_in_place.js
@@ -891,6 +906,7 @@ files:
891
906
  - app/views/catalog/_save_search.html.erb
892
907
  - app/views/catalog/_search_form.html.erb
893
908
  - app/views/devise/confirmations/new.html.erb
909
+ - app/views/devise/mailer/invitation_instructions.html.erb
894
910
  - app/views/layouts/spotlight/home.html.erb
895
911
  - app/views/layouts/spotlight/popup.html.erb
896
912
  - app/views/layouts/spotlight/spotlight.html.erb
@@ -937,7 +953,6 @@ files:
937
953
  - app/views/spotlight/catalog/_document_visibility_control.html.erb
938
954
  - app/views/spotlight/catalog/_edit_default.html.erb
939
955
  - app/views/spotlight/catalog/_index_compact_default.html.erb
940
- - app/views/spotlight/catalog/_status_header.html.erb
941
956
  - app/views/spotlight/catalog/admin.html.erb
942
957
  - app/views/spotlight/catalog/edit.html.erb
943
958
  - app/views/spotlight/catalog/new.html.erb
@@ -1081,7 +1096,7 @@ files:
1081
1096
  - db/migrate/20151117153210_change_spotlight_exhibit_published_default.rb
1082
1097
  - db/migrate/20151124101123_remove_default_from_spotlight_exhibit.rb
1083
1098
  - db/migrate/20151124105543_update_custom_field_names.rb
1084
- - db/migrate/20151204093112_add_reindexing_flag_to_spotlight_resources.rb
1099
+ - db/migrate/20151208085432_add_weight_to_exhibits.rb
1085
1100
  - lib/blacklight/spotlight.rb
1086
1101
  - lib/generators/spotlight/install_generator.rb
1087
1102
  - lib/generators/spotlight/templates/catalog_controller.rb
@@ -1172,6 +1187,7 @@ files:
1172
1187
  - spec/features/javascript/metadata_admin_spec.rb
1173
1188
  - spec/features/javascript/multi_image_select_spec.rb
1174
1189
  - spec/features/javascript/preview_block_spec.rb
1190
+ - spec/features/javascript/roles_admin_spec.rb
1175
1191
  - spec/features/javascript/rule_block_spec.rb
1176
1192
  - spec/features/javascript/search_config_admin_spec.rb
1177
1193
  - spec/features/javascript/search_context_spec.rb
@@ -1236,6 +1252,7 @@ files:
1236
1252
  - spec/models/spotlight/solr_document/spotlight_images_spec.rb
1237
1253
  - spec/models/spotlight/solr_document/uploaded_resource_spec.rb
1238
1254
  - spec/models/spotlight/solr_document_sidecar_spec.rb
1255
+ - spec/models/spotlight/user_spec.rb
1239
1256
  - spec/routing/spotlight/exhibit_catalog_spec.rb
1240
1257
  - spec/routing/spotlight/pages_routing_spec.rb
1241
1258
  - spec/serializers/spotlight/exhibit_export_serializer_spec.rb
@@ -1403,6 +1420,7 @@ test_files:
1403
1420
  - spec/features/javascript/metadata_admin_spec.rb
1404
1421
  - spec/features/javascript/multi_image_select_spec.rb
1405
1422
  - spec/features/javascript/preview_block_spec.rb
1423
+ - spec/features/javascript/roles_admin_spec.rb
1406
1424
  - spec/features/javascript/rule_block_spec.rb
1407
1425
  - spec/features/javascript/search_config_admin_spec.rb
1408
1426
  - spec/features/javascript/search_context_spec.rb
@@ -1467,6 +1485,7 @@ test_files:
1467
1485
  - spec/models/spotlight/solr_document/spotlight_images_spec.rb
1468
1486
  - spec/models/spotlight/solr_document/uploaded_resource_spec.rb
1469
1487
  - spec/models/spotlight/solr_document_sidecar_spec.rb
1488
+ - spec/models/spotlight/user_spec.rb
1470
1489
  - spec/routing/spotlight/exhibit_catalog_spec.rb
1471
1490
  - spec/routing/spotlight/pages_routing_spec.rb
1472
1491
  - spec/serializers/spotlight/exhibit_export_serializer_spec.rb
@@ -1,19 +0,0 @@
1
- <div class="panel panel-info index-status">
2
- <div class="panel-heading">
3
- <h3 class="panel-title">Reindexing status</h3>
4
- </div>
5
- <div class="panel-body">
6
- <p>
7
- <span class="text-muted">2015-11-24 at 10:53 am:</span> Began reindexing a total of 55 items.
8
- </p>
9
- <p>
10
- <span class="text-muted">2015-11-24 at 11:04 am:</span> Reindexed 32 of 55 items.
11
- </p>
12
-
13
- <div class="progress">
14
- <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="58" aria-valuemin="0" aria-valuemax="100" style="width: 58%">58%
15
- <span class="sr-only">Reindexing 58% complete</span>
16
- </div>
17
- </div>
18
- </div>
19
- </div>
@@ -1,5 +0,0 @@
1
- class AddReindexingFlagToSpotlightResources < ActiveRecord::Migration
2
- def up
3
- add_column :spotlight_resources, :reindexing, :boolean
4
- end
5
- end