diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 023d573..3fce5a9 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -119,7 +119,7 @@
mandatory_params &&= false
end
if params[:user][:org_id].blank? && params[:user][:other_organisation].blank?
- message += _('Please select an organisation, or select Other.')
+ message += _('Please select an organisation from the list, or enter your organisation\'s name.')
mandatory_params &&= false
end
if mandatory_params # has the user entered all the details
diff --git a/app/views/devise/registrations/_external_identifier_shibboleth.html.erb b/app/views/devise/registrations/_external_identifier_shibboleth.html.erb
index 8e7283b..0d09d9e 100644
--- a/app/views/devise/registrations/_external_identifier_shibboleth.html.erb
+++ b/app/views/devise/registrations/_external_identifier_shibboleth.html.erb
@@ -1,19 +1,19 @@
<% if id.nil? || id.identifier == '' %>
- <%= link_to "#{_("Link account with #{scheme.description} ID")}",
+ <%= link_to "#{_("Link your institutional credentials")}",
Rails.application.routes.url_helpers.send(
"user_#{scheme.name.downcase}_omniauth_authorize_path"
), 'data-toggle': "tooltip",
- title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip", default: "")
+ title: _('Link your institutional credentials to access your account with them.')
%>
<% else %>
<% if scheme.user_landing_url.nil? %>
<%= _("Your account has been linked to #{scheme.description}.") %>
<% else %>
- <%= link_to "#{_("Your account has been linked to #{scheme.description}.")}", "#{scheme.user_landing_url}/#{id.identifier}", target: '_blank', 'data-toggle': "tooltip",
- title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip", default: "") %>
+ <%= link_to "#{_("Your account has been linked to your institution.")}", "#{scheme.user_landing_url}/#{id.identifier}", target: '_blank', 'data-toggle': "tooltip",
+ title: _('Your account has been linked to your institution. You can now login with that method.') %>
<% end %>
- <% title = _("Unlink your account from #{scheme.description}. You can link again at any time.") %>
+ <% title = _("Unlink your account from your institution. You can link again at any time.") %>
<%= link_to ' '.html_safe,
destroy_user_identifier_path(id), method: :delete, title: title, 'aria-label': title, 'data-toggle': "tooltip",
- data: {confirm: _("Are you sure you want to unlink #{scheme.description} ID?")} %>
+ id: 'unlink-shibboleth', data: {confirm: _("Are you sure you want to unlink your institutional credentials?")} %>
<% end %>
diff --git a/app/views/devise/registrations/_personal_details.html.erb b/app/views/devise/registrations/_personal_details.html.erb
index c928f7f..842d2e9 100644
--- a/app/views/devise/registrations/_personal_details.html.erb
+++ b/app/views/devise/registrations/_personal_details.html.erb
@@ -28,7 +28,10 @@
<%= f.password_field(:password, class: "form-control", "aria-required": true) %>
- <%= render partial: "shared/org_dropdown", locals: {f: f, default_org: @default_org, orgs: @orgs, allow_other_orgs: true} %>
+ <% org_admin = (current_user.can_org_admin? && !current_user.can_super_admin?) %>
+
>
+ <%= render partial: "shared/my_org", locals: {f: f, default_org: @default_org, orgs: @orgs, allow_other_orgs: true} %>
+
<% if MANY_LANGUAGES %>
-
+
<%= f.label(:password, _('Password'), class: "control-label") %>
<%= f.password_field(:password, class: "form-control", "aria-required": true) %>
diff --git a/app/views/shared/_my_org.html.erb b/app/views/shared/_my_org.html.erb
new file mode 100644
index 0000000..83acbac
--- /dev/null
+++ b/app/views/shared/_my_org.html.erb
@@ -0,0 +1,18 @@
+<%= f.label :org_name, _('Organisation'), class: 'control-label' %>
+<%= render partial: "shared/accessible_combobox",
+ locals: {name: "user[org_name]",
+ id: "user_org_name",
+ default_selection: default_org,
+ models: orgs,
+ attribute: 'name'} %>
+
+<% if allow_other_orgs %>
+ <%= f.text_field :other_organisation, autocomplete: "off", class: "form-control",
+ placeholder: _('Please enter the name of your organisation') %>
+<% end %>
+
+<% if allow_other_orgs %>
+
+<% end %>
diff --git a/app/views/shared/_org_dropdown.html.erb b/app/views/shared/_org_dropdown.html.erb
deleted file mode 100644
index f186af4..0000000
--- a/app/views/shared/_org_dropdown.html.erb
+++ /dev/null
@@ -1,25 +0,0 @@
-<% others = allow_other_orgs ||= false %>
-<% left_size = (others ? 5 : 8) %>
-
-
- <%= f.label :org_name, _('Organisation'), class: 'control-label' %>
- <%= render partial: "shared/accessible_combobox",
- locals: {name: "user[org_name]",
- id: "user_org_name",
- default_selection: default_org,
- models: orgs,
- attribute: 'name'} %>
-
- <% if others %>
- <%= f.text_field :other_organisation, autocomplete: "off", class: "form-control hide",
- placeholder: _('Please enter the name of your organisation') %>
- <% end %>
-
-
-<% if others %>
-
-
- <%= _('My organisation isn\'t listed') %>
-
-
-<% end %>
diff --git a/lib/assets/javascripts/application.js b/lib/assets/javascripts/application.js
index bb948af..de9dba9 100644
--- a/lib/assets/javascripts/application.js
+++ b/lib/assets/javascripts/application.js
@@ -33,6 +33,7 @@
import './views/questions/show';
import './views/question_options/index';
import './views/shared/create_account_form';
+import './views/shared/my_org';
import './views/shared/sign_in_form';
import './views/templates/edit';
import './views/templates/show';
diff --git a/lib/assets/javascripts/constants.js b/lib/assets/javascripts/constants.js
index 376f2e5..f2d030d 100644
--- a/lib/assets/javascripts/constants.js
+++ b/lib/assets/javascripts/constants.js
@@ -20,5 +20,9 @@
export const PLAN_VISIBILITY_WHEN_NOT_TEST = 'Private';
export const PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP = 'Private: restricted to me and people I invite.';
+export const DISABLE_ORG_COMBO_MESSAGE = 'You must unlink your account before changing your organisation.';
+export const OTHER_ORG_HIDE_COMBO_MESSAGE = 'My organisation isn\'t listed.';
+export const OTHER_ORG_SHOW_COMBO_MESSAGE = 'Select the organisation from a list.';
+
export const SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST = 'Hide list.';
export const SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST = 'See the full list of partner institutions.';
diff --git a/lib/assets/javascripts/utils/autoComplete.js b/lib/assets/javascripts/utils/autoComplete.js
index 50c3658..9391f7b 100644
--- a/lib/assets/javascripts/utils/autoComplete.js
+++ b/lib/assets/javascripts/utils/autoComplete.js
@@ -1,4 +1,6 @@
import debounce from '../utils/debounce';
+import { isObject } from '../utils/isType';
+import { isValidText } from '../utils/isValidInputType';
/*
* Looks up the id for the text selected by the user in the jquery autocomplete combobox and
@@ -10,10 +12,10 @@
const crosswalk = $(`#${$(el).attr('id')}_crosswalk`);
const idField = $(el).attr('id').replace(/_name/, '_id');
- if (crosswalk && idField) {
+ if (isObject(crosswalk) && isObject($(idField))) {
const json = JSON.parse(`${$(crosswalk).val().replace(/\\"/g, '"').replace(/\\'/g, '\'')}`);
- const selection = json[$(el).val()];
- $(`#${idField}`).val(selection === undefined ? '' : selection).change();
+ const selection = (json[$(el).val()] === undefined ? '' : json[$(el).val()]);
+ $(el).parent().siblings(`#${idField}`).val(selection);
}
};
@@ -23,10 +25,12 @@
*/
const toggleClearButton = (el) => {
const clearButton = $(el).parent().find('.combobox-clear-button');
- if ($(el).val().trim().length <= 0) {
- $(clearButton).addClass('hidden');
- } else {
- $(clearButton).removeClass('hidden');
+ if (isObject(clearButton)) {
+ if (isValidText($(el).val())) {
+ $(clearButton).removeClass('hidden');
+ } else {
+ $(clearButton).addClass('hidden');
+ }
}
};
@@ -36,20 +40,25 @@
*/
export default () => {
$('.js-combobox').each((idx, el) => {
+ // Swap out the 'X' with a fontawesome icon
+ $(el).siblings('.combobox-clear-button').text('')
+ .addClass('fa')
+ .addClass('fa-times-circle');
+
const debounced = debounce((e) => {
toggleClearButton(e);
updateIdField(e);
- }, 300);
+ }, 100);
// When the value in the combobox changes update the hidden id field
- $(el).on('keyup, blur', (e) => {
+ $(el).on('keyup blur', (e) => {
debounced($(e.currentTarget));
});
// Clear the text and hide the button when the user clicks the clear button
$(el).parent().find('.combobox-clear-button').on('click', () => {
- $(el).val('').focus();
- debounced($(el));
+ $(el).val('');
+ debounced(el);
});
// add a Bootstrap 'hide' class to the invisible help text
@@ -57,8 +66,5 @@
// Show/hide the clear button on page load
toggleClearButton(el);
-
- // Update the hidden ID field on initialize
- updateIdField(el);
});
};
diff --git a/lib/assets/javascripts/views/devise/registrations/edit.js b/lib/assets/javascripts/views/devise/registrations/edit.js
index a03e07e..3b6b122 100644
--- a/lib/assets/javascripts/views/devise/registrations/edit.js
+++ b/lib/assets/javascripts/views/devise/registrations/edit.js
@@ -1,5 +1,5 @@
import ariatiseForm from '../../../utils/ariatiseForm';
-
+import { DISABLE_ORG_COMBO_MESSAGE } from '../../../constants';
import { addMatchingPasswordValidator, togglisePasswords } from '../../../utils/passwordHelper';
$(() => {
@@ -8,4 +8,13 @@
ariatiseForm({ selector: '#preferences_registration_form' });
addMatchingPasswordValidator({ selector: '#password_details_registration_form' });
togglisePasswords({ selector: '#password_details_registration_form' });
+
+ // Disable organisation autocomplete if the user has linked their account to Shibboleth
+ if ($('.identifier-scheme #unlink-shibboleth').length > 0) {
+ $('#org-controls #user_org_name').attr('disabled', true)
+ .attr('data-toggle', 'tooltip')
+ .attr('title', DISABLE_ORG_COMBO_MESSAGE);
+ $('#org-controls .combobox-clear-button').hide();
+ $('#other_org_toggle a').hide();
+ }
});
diff --git a/lib/assets/javascripts/views/shared/my_org.js b/lib/assets/javascripts/views/shared/my_org.js
new file mode 100644
index 0000000..30d745a
--- /dev/null
+++ b/lib/assets/javascripts/views/shared/my_org.js
@@ -0,0 +1,39 @@
+import { OTHER_ORG_HIDE_COMBO_MESSAGE, OTHER_ORG_SHOW_COMBO_MESSAGE } from '../../constants';
+import { isValidNumber, isValidText } from '../../utils/isValidInputType';
+
+$(() => {
+ const combo = $('.combobox-container');
+ const id = $('input#user_org_id');
+ const text = $('input#user_other_organisation');
+ const link = $('#other_org_toggle a');
+
+ // Toggle between the autocomplete dropdown box and the other org textbox
+ const toggleCombobox = (show) => {
+ if (show) {
+ $(text).hide();
+ $(combo).fadeIn();
+ $(link).text(OTHER_ORG_HIDE_COMBO_MESSAGE);
+ } else {
+ $(combo).hide();
+ $(text).fadeIn();
+ $(link).text(OTHER_ORG_SHOW_COMBO_MESSAGE);
+ }
+ };
+
+ // Toggle between the combobox and textbox when the link is clicked
+ $(link).click((e) => {
+ e.preventDefault();
+ if ($(combo).css('display') === 'none') {
+ $(text).val('').hide();
+ toggleCombobox(true);
+ } else {
+ $(combo).find('.combobox-clear-button').click();
+ toggleCombobox(false);
+ }
+ });
+
+ // Display the appropriate input type on page load
+ if ($(id).length > 0 && $(text).length > 0) {
+ toggleCombobox(isValidNumber($(id).val()) || !isValidText($(text).val()));
+ }
+});
diff --git a/lib/assets/package-lock.json b/lib/assets/package-lock.json
index fdd4011..b95b6c5 100644
--- a/lib/assets/package-lock.json
+++ b/lib/assets/package-lock.json
@@ -7845,9 +7845,9 @@
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/timeago/-/timeago-1.6.1.tgz",
"integrity": "sha512-mvXlF+JKeclH6AxvBDcwLvDFJyfpjC9Qs3zs6O97u4WBoHYlnnx/QyE7h5INRkGnT53rS8BGUTRhIr661VqTZA==",
- "requires": {
+ "requires": {
"jquery": "3.2.1"
- }
+ }
},
"timers-browserify": {
"version": "2.0.4",
diff --git a/lib/assets/stylesheets/overrides.scss b/lib/assets/stylesheets/overrides.scss
index 4773088..d113fe5 100644
--- a/lib/assets/stylesheets/overrides.scss
+++ b/lib/assets/stylesheets/overrides.scss
@@ -218,3 +218,64 @@
}
}
+/* JQuery Autocomplete Styling */
+/* ---------------------------------------------------- */
+.invisible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+
+.combobox-container {
+ position: relative;
+}
+
+.combobox-suggestions {
+ position: absolute;
+ left: 0;
+ width: 100%;
+ background: $white;
+ z-index: 99;
+}
+.combobox-suggestion {
+ color: #grey;
+ border-bottom: 1px solid $grey;
+ border-left: 1px solid $grey;
+ border-right: 1px solid $grey;
+ padding: 5px 10px 5px 10px;
+ cursor: pointer;
+ text-align: left;
+}
+.combobox-suggestion:first-child {
+ border-top: 1px solid $grey;
+}
+.combobox-suggestion:hover,
+.combobox-suggestion:focus {
+ color: $white;
+ background-color: $grey;
+}
+
+.combobox-clear-button, .combobox-clear-button:hover, .combobox-clear-button:focus {
+ cursor: pointer;
+ display: inline;
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin-top: 2px;
+ margin-right: -35px;
+ border: none;
+ background: transparent;
+ color: $grey;
+ padding-top: 3px;
+ font-size: 16pt;
+}
+
+/* http://geektnt.com/how-to-remove-x-from-search-input-field-on-chrome-and-ie.html */
+.js-combobox[type=text]::-ms-clear { display: none; width: 0; height: 0; }
+.js-combobox[type=text]::-ms-reveal { display: none; width: 0; height: 0; }
+