diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f3d9ac6..801fba4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -70,5 +70,41 @@ + + <% + constants_json = { + PASSWORD_MIN_LENGTH: 8, + PASSWORD_MAX_LENGTH: 128, + MAX_NUMBER_ORG_URLS: 3, + MAX_NUMBER_GUIDANCE_SELECTIONS: 6, + + VALIDATION_MESSAGE_DEFAULT: _('Please enter a valid value.'), + VALIDATION_MESSAGE_EMAIL: _('You must enter a valid email address.'), + VALIDATION_MESSAGE_URL: _('You must enter a valid URL (e.g. https://organisation.org).'), + VALIDATION_MESSAGE_NUMBER: _('Please enter a valid number.'), + VALIDATION_MESSAGE_PASSWORD: _('The password must be between 8 and 128 characters.'), + VALIDATION_MESSAGE_PASSWORDS_MATCH: _('The passwords must match.'), + VALIDATION_MESSAGE_RADIO: _('Please choose one of the options.'), + VALIDATION_MESSAGE_CHECKBOX: _('Please check the box to continue.'), + VALIDATION_MESSAGE_SELECT: _('Please select a value from the list.'), + VALIDATION_MESSAGE_TEXT: _('This field is required.'), + + SHOW_PASSWORD_MESSAGE: _('Show password'), + SHOW_SELECT_ORG_MESSAGE: _('Select an organisation from the list.'), + SHOW_OTHER_ORG_MESSAGE: _('My organisation isn\'t listed'), + + PLAN_VISIBILITY_WHEN_TEST: _('N/A'), + PLAN_VISIBILITY_WHEN_NOT_TEST: _('Private'), + PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP: _('Private: restricted to me and people I invite.'), + + SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST: _('Hide list.'), + SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST: _('See the full list of partner institutions.'), + + NO_TEMPLATE_FOUND_ERROR: _('Unable to find a suitable template for the research organisation and funder you selected.'), + NEW_PLAN_DISABLED_TOOLTIP: _('Please select a research organisation and funder to continue.') + }.to_json + %> + + diff --git a/lib/assets/javascripts/constants.js b/lib/assets/javascripts/constants.js index 82109c3..9a953c6 100644 --- a/lib/assets/javascripts/constants.js +++ b/lib/assets/javascripts/constants.js @@ -1,33 +1,11 @@ -export const PASSWORD_MIN_LENGTH = 8; -export const PASSWORD_MAX_LENGTH = 128; +import { isObject, isString } from './utils/isType'; -// Maximum number of URLs allowed on the Org details page. These links appear at the -// top of the screen in the lower navigation row next to the Org Logo -export const MAX_NUMBER_ORG_URLS = 3; - -export const MAX_NUMBER_GUIDANCE_SELECTIONS = 6; - -export const VALIDATION_MESSAGE_DEFAULT = 'Please enter a valid value.'; -export const VALIDATION_MESSAGE_EMAIL = 'You must enter a valid email address.'; -export const VALIDATION_MESSAGE_URL = 'You must enter a valid URL (e.g. https://organisation.org).'; -export const VALIDATION_MESSAGE_NUMBER = 'Please enter a valid number.'; -export const VALIDATION_MESSAGE_PASSWORD = 'The password must be between 8 and 128 characters.'; -export const VALIDATION_MESSAGE_PASSWORDS_MATCH = 'The passwords must match.'; -export const VALIDATION_MESSAGE_RADIO = 'Please choose one of the options.'; -export const VALIDATION_MESSAGE_CHECKBOX = 'Please check the box to continue.'; -export const VALIDATION_MESSAGE_SELECT = 'Please select a value from the list.'; -export const VALIDATION_MESSAGE_TEXT = 'This field is required.'; - -export const SHOW_PASSWORD_MESSAGE = 'Show password'; -export const SHOW_SELECT_ORG_MESSAGE = 'Select an organisation from the list.'; -export const SHOW_OTHER_ORG_MESSAGE = 'My organisation isn\'t listed'; - -export const PLAN_VISIBILITY_WHEN_TEST = 'N/A'; -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 SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST = 'Hide list.'; -export const SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST = 'See the full list of partner institutions.'; - -export const NO_TEMPLATE_FOUND_ERROR = 'Unable to find a suitable template for the research organisation and funder you selected.'; -export const NEW_PLAN_DISABLED_TOOLTIP = 'Please select a research organisation and funder to continue.'; +let constants = {}; +export default key => constants[key]; +$(() => { + // js-constants is defined in views/layouts/application.html.erb + const target = $('#js-constants'); + if (isObject(target) && isString(target.val())) { + constants = JSON.parse(target.val()); + } +}); diff --git a/lib/assets/javascripts/utils/ariatiseForm.js b/lib/assets/javascripts/utils/ariatiseForm.js index fda3c8f..0264863 100644 --- a/lib/assets/javascripts/utils/ariatiseForm.js +++ b/lib/assets/javascripts/utils/ariatiseForm.js @@ -32,7 +32,7 @@ */ import { Tinymce } from './tinymce'; import { isObject, isString, isBoolean } from './isType'; -import * as constants from '../constants'; +import getConstant from '../constants'; import * as validator from './isValidInputType'; const validatableFields = (selector) => { @@ -135,23 +135,23 @@ const getDefaultValidationMessage = (type) => { switch (type) { case 'text': - return constants.VALIDATION_MESSAGE_TEXT; + return getConstant('VALIDATION_MESSAGE_TEXT'); case 'textarea': - return constants.VALIDATION_MESSAGE_TEXT; + return getConstant('VALIDATION_MESSAGE_TEXT'); case 'number': - return constants.VALIDATION_MESSAGE_NUMBER; + return getConstant('VALIDATION_MESSAGE_NUMBER'); case 'email': - return constants.VALIDATION_MESSAGE_EMAIL; + return getConstant('VALIDATION_MESSAGE_EMAIL'); case 'password': - return constants.VALIDATION_MESSAGE_PASSWORD; + return getConstant('VALIDATION_MESSAGE_PASSWORD'); case 'radio': - return constants.VALIDATION_MESSAGE_RADIO; + return getConstant('VALIDATION_MESSAGE_RADIO'); case 'checkbox': - return constants.VALIDATION_MESSAGE_CHECKBOX; + return getConstant('VALIDATION_MESSAGE_CHECKBOX'); case 'js-combobox': - return constants.VALIDATION_MESSAGE_SELECT; + return getConstant('VALIDATION_MESSAGE_SELECT'); default: - return constants.VALIDATION_MESSAGE_DEFAULT; + return getConstant('VALIDATION_MESSAGE_DEFAULT'); } }; diff --git a/lib/assets/javascripts/utils/validation.js b/lib/assets/javascripts/utils/validation.js index 480517e..09ff999 100644 --- a/lib/assets/javascripts/utils/validation.js +++ b/lib/assets/javascripts/utils/validation.js @@ -1,6 +1,6 @@ import { Tinymce } from './tinymce'; import { isObject, isString, isBoolean } from './isType'; -import * as constants from '../constants'; +import getConstant from '../constants'; import * as validator from './isValidInputType'; const isValidatableField = ctx => $(ctx).attr('data-validatable') === 'true'; @@ -100,25 +100,25 @@ const getDefaultValidationMessage = (type) => { switch (type) { case 'text': - return constants.VALIDATION_MESSAGE_TEXT; + return getConstant('VALIDATION_MESSAGE_TEXT'); case 'textarea': - return constants.VALIDATION_MESSAGE_TEXT; + return getConstant('VALIDATION_MESSAGE_TEXT'); case 'number': - return constants.VALIDATION_MESSAGE_NUMBER; + return getConstant('VALIDATION_MESSAGE_NUMBER'); case 'email': - return constants.VALIDATION_MESSAGE_EMAIL; + return getConstant('VALIDATION_MESSAGE_EMAIL'); case 'url': - return constants.VALIDATION_MESSAGE_URL; + return getConstant('VALIDATION_MESSAGE_URL'); case 'password': - return constants.VALIDATION_MESSAGE_PASSWORD; + return getConstant('VALIDATION_MESSAGE_PASSWORD'); case 'radio': - return constants.VALIDATION_MESSAGE_RADIO; + return getConstant('VALIDATION_MESSAGE_RADIO'); case 'checkbox': - return constants.VALIDATION_MESSAGE_CHECKBOX; + return getConstant('VALIDATION_MESSAGE_CHECKBOX'); case 'js-combobox': - return constants.VALIDATION_MESSAGE_SELECT; + return getConstant('VALIDATION_MESSAGE_SELECT'); default: - return constants.VALIDATION_MESSAGE_DEFAULT; + return getConstant('VALIDATION_MESSAGE_DEFAULT'); } }; const getValidationMessage = (el) => { diff --git a/lib/assets/javascripts/views/orgs/shibboleth_ds.js b/lib/assets/javascripts/views/orgs/shibboleth_ds.js index f186b93..d1c7f56 100644 --- a/lib/assets/javascripts/views/orgs/shibboleth_ds.js +++ b/lib/assets/javascripts/views/orgs/shibboleth_ds.js @@ -1,9 +1,6 @@ import ariatiseForm from '../../utils/ariatiseForm'; import initAutoComplete from '../../utils/autoComplete'; -import { - SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST, - SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST, -} from '../../constants'; +import getConstant from '../../constants'; $(() => { initAutoComplete(); @@ -13,10 +10,10 @@ e.preventDefault(); if ($('#full_list').is('.hidden')) { $('#full_list').removeClass('hidden').attr('aria-hidden', 'false'); - $(e.currentTarget).html(SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST); + $(e.currentTarget).html(getConstant('SHIBBOLETH_DISCOVERY_SERVICE_HIDE_LIST')); } else { $('#full_list').addClass('hidden').attr('aria-hidden', 'true'); - $(e.currentTarget).html(SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST); + $(e.currentTarget).html(getConstant('SHIBBOLETH_DISCOVERY_SERVICE_SHOW_LIST')); } }); }); diff --git a/lib/assets/javascripts/views/plans/edit_details.js b/lib/assets/javascripts/views/plans/edit_details.js index 1e79030..3b6865e 100644 --- a/lib/assets/javascripts/views/plans/edit_details.js +++ b/lib/assets/javascripts/views/plans/edit_details.js @@ -1,6 +1,6 @@ import { Tinymce } from '../../utils/tinymce'; import ariatiseForm from '../../utils/ariatiseForm'; -import { MAX_NUMBER_GUIDANCE_SELECTIONS } from '../../constants'; +import getConstant from '../../constants'; $(() => { Tinymce.init(); @@ -26,7 +26,7 @@ const toggleCheckboxes = (selections) => { $('#priority-guidance-orgs, #other-guidance-orgs').find('input[type="checkbox"]').each((i, el) => { const checkbox = $(el); - if (selections.length >= MAX_NUMBER_GUIDANCE_SELECTIONS) { + if (selections.length >= getConstant('MAX_NUMBER_GUIDANCE_SELECTIONS')) { if (checkbox.is(':checked')) { checkbox.removeAttr('disabled'); } else { diff --git a/lib/assets/javascripts/views/plans/index.js b/lib/assets/javascripts/views/plans/index.js index b408954..b030b67 100644 --- a/lib/assets/javascripts/views/plans/index.js +++ b/lib/assets/javascripts/views/plans/index.js @@ -1,10 +1,5 @@ import * as notifier from '../../utils/notificationHelper'; - -import { - PLAN_VISIBILITY_WHEN_TEST, - PLAN_VISIBILITY_WHEN_NOT_TEST, - PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP, -} from '../../constants'; +import getConstant from '../../constants'; import { paginableSelector } from '../../utils/paginable'; $(() => { @@ -21,11 +16,11 @@ } if (form.find('input[type="checkbox"]').is(':checked')) { - form.parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_TEST) + form.parent().siblings('.plan-visibility').html(getConstant('PLAN_VISIBILITY_WHEN_TEST')) .attr('title', ''); } else { - form.parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_NOT_TEST) - .attr('title', PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP); + form.parent().siblings('.plan-visibility').html(getConstant('PLAN_VISIBILITY_WHEN_NOT_TEST')) + .attr('title', getConstant('PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP')); } }); $(paginableSelector).on('ajax:error', '.set_test_plan', () => { diff --git a/lib/assets/javascripts/views/plans/new.js b/lib/assets/javascripts/views/plans/new.js index 6c2d066..39e1518 100644 --- a/lib/assets/javascripts/views/plans/new.js +++ b/lib/assets/javascripts/views/plans/new.js @@ -1,9 +1,9 @@ import debounce from '../../utils/debounce'; import ariatiseForm from '../../utils/ariatiseForm'; import initAutoComplete from '../../utils/autoComplete'; +import getConstant from '../../constants'; import { isObject, isArray, isString } from '../../utils/isType'; import { isValidText } from '../../utils/isValidInputType'; -import { NO_TEMPLATE_FOUND_ERROR, NEW_PLAN_DISABLED_TOOLTIP } from '../../constants'; import { renderAlert, hideNotifications } from '../../utils/notificationHelper'; $(() => { @@ -14,13 +14,13 @@ .removeAttr('data-toggle').removeAttr('title'); } else { $('#new_plan button[type="submit"]').attr('disabled', true) - .attr('data-toggle', 'tooltip').attr('title', NEW_PLAN_DISABLED_TOOLTIP); + .attr('data-toggle', 'tooltip').attr('title', getConstant('NEW_PLAN_DISABLED_TOOLTIP')); } }; // AJAX error function for available template search const error = () => { - renderAlert(NO_TEMPLATE_FOUND_ERROR); + renderAlert(getConstant('NO_TEMPLATE_FOUND_ERROR')); }; // AJAX success function for available template search