Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d8cede2
Merge pull request #74 from DMPRoadmap/development
briri Aug 16, 2017
2071019
Merge pull request #78 from DMPRoadmap/development
briri Aug 23, 2017
26015b9
Updated seeds.rb token_permission_types and question_formats and adde…
briri Aug 23, 2017
71e96b7
Merge branch 'development' of https://github.com/CDLUC3/roadmap into …
briri Aug 23, 2017
fced606
Merge pull request #604 from CDLUC3/development
jollopre Aug 24, 2017
558b2d4
updated db migration for mysql drop and then readd fkeys DMPRoadmap/r…
briri Aug 25, 2017
508aba6
Merge pull request #608 from CDLUC3/development
jollopre Aug 29, 2017
96f5248
moved view specific es6 js to top level views dir. added validation f…
briri Aug 30, 2017
43bd5b4
finished up bootstrapping of share page
briri Aug 30, 2017
c6f8f94
Merge pull request #82 from DMPRoadmap/CDL-MVP
briri Aug 31, 2017
8a76614
removed data-validation from aria-required passwords
briri Aug 31, 2017
9088f18
Moved views js back into separate files per view
briri Aug 31, 2017
4f56149
moved view js back into individual views files
briri Aug 31, 2017
56e31c8
added karma-fixtures, html and json preprocessors
briri Aug 31, 2017
7817f3a
created ariatiseTest and fixture
briri Aug 31, 2017
4aed933
updated plan sharing to be case-insensitive
xsrust Sep 1, 2017
d7a8968
updated controller and test to reflect each other's behaviors
xsrust Sep 5, 2017
758acd9
added karma-jasmine-jquery, created fixture and tests for ariatiseFor…
briri Sep 5, 2017
90a737e
fixed linter issue in share.js
briri Sep 5, 2017
792804c
removed if ($) check
briri Sep 5, 2017
dca128a
changes default pdf settings
xsrust Sep 6, 2017
503c444
Merge pull request #618 from DigitalCurationCentre/xsrust/bugfixes
briri Sep 6, 2017
804fb44
fixed merge conflicts
briri Sep 6, 2017
1a462f4
Merge branch 'DMPRoadmap-CDL-MVP' into CDL-MVP
briri Sep 6, 2017
8bfb0c6
Merge pull request #84 from DMPRoadmap/development
briri Sep 6, 2017
58c8088
fixed merge conflicts from pulling in latest bug fixes from development
briri Sep 6, 2017
4391907
fixed merge conflicts
briri Sep 6, 2017
054b104
1. click ariatiseForm preventDefault only once now
Sep 7, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions app/controllers/roles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ def create

access_level = params[:role][:access_level].to_i
set_access_level(access_level)
message = ''
if params[:user].present?
if @role.plan.owner.present? && @role.plan.owner.email == params[:user]
flash[:notice] = _('Cannot share plan with %{email} since that email matches with the owner of the plan.') % {email: params[:user]}
else
if Role.find_by(plan: @role.plan, user: User.find_by(email: params[:user])) # role already exists
user = User.where_case_insensitive('email',params[:user]).first
if Role.find_by(plan: @role.plan, user: user) # role already exists
flash[:notice] = _('Plan is already shared with %{email}.') % {email: params[:user]}
else
message = _('Plan shared with %{email}.') % {email: params[:user]}
user = User.find_by(email: params[:user])
else
if user.nil?
registered = false
User.invite!(email: params[:user])
message = _('Invitation to %{email} issued successfully.') % {email: params[:user]}
message = _('Invitation to %{email} issued successfully. \n') % {email: params[:user]}
user = User.find_by(email: params[:user])
end
message += _('Plan shared with %{email}.') % {email: user.email}
@role.user = user
if @role.save
if registered then UserMailer.sharing_notification(@role, current_user).deliver_now end
Expand Down
16 changes: 8 additions & 8 deletions app/models/settings/template.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module Settings
class Template < RailsSettings::SettingObject

#attr_accessible :var, :target, :target_id, :target_type

VALID_FONT_FACES = [
'Arial, Helvetica, Sans-Serif',
'"Times New Roman", Times, Serif'
'"Times New Roman", Times, Serif',
'Arial, Helvetica, Sans-Serif'
]

VALID_FONT_SIZE_RANGE = (8..14)
Expand All @@ -17,13 +17,13 @@ class Template < RailsSettings::SettingObject
DEFAULT_SETTINGS = {
formatting: {
margin: { # in millimeters
top: 20,
bottom: 20,
left: 20,
right: 20
top: 10,
bottom: 10,
left: 10,
right: 10
},
font_face: VALID_FONT_FACES.first,
font_size: 12 # pt
font_size: 10 # pt
},
max_pages: 3,
fields: {
Expand Down
8 changes: 8 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -276,5 +276,13 @@ def get_preferences(key)
def deliver_invitation(options = {})
super(options.merge(subject: _('A Data Management Plan in %{application_name} has been shared with you') % {application_name: Rails.configuration.branding[:application][:name]}))
end
##
# Case insensitive search over User model
# @param field [string] The name of the field being queried
# @param val [string] The string to search for, case insensitive
# @return [ActiveRecord::Relation] The result of the search
def self.where_case_insensitive(field, val)
User.where("lower(#{field}) = ?", val.downcase)
end

end
4 changes: 2 additions & 2 deletions app/views/devise/passwords/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

<div class="form-group">
<%= f.label(:password, _('New password'), class: 'control-label') %>
<%= f.password_field(:password, class: 'form-control', "aria-required": true) %>
<%= f.password_field(:password, class: 'form-control', "aria-required": true %>
</div>
<div class="form-group">
<%= f.label(:password_confirmation, _('Password confirmation'), class: 'control-label') %>
<%= f.password_field(:password_confirmation, class: 'form-control', "aria-required": true) %>
<%= f.password_field(:password_confirmation, class: 'form-control', "aria-required": true %>
</div>
<div class="checkbox">
<label for="passwords_toggle">
Expand Down
1 change: 0 additions & 1 deletion app/views/layouts/_es5_scripts.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
<%= javascript_include_tag 'views/plans/export_configure.js' %> <!-- (app/views/plans/show_export.html.erb) -->
<%= javascript_include_tag 'views/plans/index.js' %> <!-- -->
<%= javascript_include_tag 'views/plans/new.js' %> <!-- (app/views/plans/new.html.erb) -->
<%= javascript_include_tag 'views/plans/share.js' %> <!-- (app/views/plans/share.html.erb) -->
<%= javascript_include_tag 'views/registrations/sign_in_sign_up.js' %> <!-- -->
<%#= javascript_include_tag 'views/shared/accessible_combobox.js' %> <!-- (app/views/shared/_accessible_combobox.html.erb) BROKEN since uses rails templating for setting values for JS variables -->
<%#= javascript_include_tag 'views/shared/accessible_submit_button.js' %> <!-- (app/views/shared/_accessible_submit_button.html.erb) BROKEN since uses rails templating for setting values for JS variables -->
Expand Down
6 changes: 3 additions & 3 deletions app/views/plans/_share_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
<div class="form-group">
<%= f.hidden_field :plan_id %>
<%= f.fields_for :user do |user| %>
<%= user.label :email, _('Email') %>
<%= user.email_field :email, for: :user, name: "user", class: "input-medium" %>
<%= user.label :email, _('Email'), class: 'control-label' %>
<%= user.email_field :email, for: :user, name: "user", class: "form-control", "aria-required": true %>
<% end %>
</div>

Expand All @@ -77,7 +77,7 @@
<%= f.label :access_level, raw("#{f.radio_button :access_level, 2} #{_('Editor: can comment and make changes')}") %>
</div>
<div class="radio">
<%= f.label :access_level, raw("#{f.radio_button :access_level, 3} #{_('Co-owner: can edit project details, change visibility, and add collaborators')}") %>
<%= f.label :access_level, raw("#{f.radio_button :access_level, 3, "aria-required": true} #{_('Co-owner: can edit project details, change visibility, and add collaborators')}") %>
</div>

<%= f.button(_('Submit'), class: "btn btn-default", type: "submit") %>
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20170702012742_ensure_indexes_in_place.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
class EnsureIndexesInPlace < ActiveRecord::Migration
def change
#users_perms
remove_foreign_key :users_perms, :perms
remove_foreign_key :users_perms, :users
remove_index :users_perms, name: 'index_users_perms_on_user_id_and_perm_id'
add_index :users_perms, :user_id
add_foreign_key :users_perms, :perms
add_foreign_key :users_perms, :users
#user_identifiers
add_index :user_identifiers, :user_id
#roles
Expand All @@ -27,14 +31,22 @@ def change
#annotations
add_index :annotations, :question_id
#question_themes
remove_foreign_key :questions_themes, :questions
remove_foreign_key :questions_themes, :themes
remove_index :questions_themes, name: 'question_theme_index'
remove_index :questions_themes, name: 'theme_question_index'
add_index :questions_themes, :question_id
add_foreign_key :questions_themes, :questions
add_foreign_key :questions_themes, :themes
#question_options
add_index :question_options, :question_id
#answers_question_options
remove_foreign_key :answers_question_options, :answers
remove_foreign_key :answers_question_options, :question_options
remove_index :answers_question_options, name: 'answer_question_option_index'
remove_index :answers_question_options, name: 'question_option_answer_index'
add_index :answers_question_options, :answer_id
add_foreign_key :answers_question_options, :answers
add_foreign_key :answers_question_options, :question_options
end
end
20 changes: 11 additions & 9 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
{name: 'orcid', description: 'ORCID', active: true,
logo_url:'http://orcid.org/sites/default/files/images/orcid_16x16.png',
user_landing_url:'https://orcid.org' },
{name: 'shibboleth', description: 'your institutional credentials', active: true,
{name: 'shibboleth', description: 'Your institutional credentials', active: true,
},
]
identifier_schemes.map{ |is| IdentifierScheme.create!(is) if IdentifierScheme.find_by(name: is[:name]).nil? }

# Question Formats
# -------------------------------------------------------
question_formats = [
{title: "Text area", option_based: false},
{title: "Text field", option_based: false},
{title: "Radio buttons", option_based: true},
{title: "Check box", option_based: true},
{title: "Dropdown", option_based: true},
{title: "Multi select box", option_based: true},
{title: "Date", option_based: false}
{title: "Text area", option_based: false, formattype: 0},
{title: "Text field", option_based: false, formattype: 1},
{title: "Radio buttons", option_based: true, formattype: 2},
{title: "Check box", option_based: true, formattype: 3},
{title: "Dropdown", option_based: true, formattype: 4},
{title: "Multi select box", option_based: true, formattype: 5},
{title: "Date", option_based: true, formattype: 6}
]
question_formats.map{ |qf| QuestionFormat.create!(qf) if QuestionFormat.find_by(title: qf[:title]).nil? }

Expand Down Expand Up @@ -154,7 +154,9 @@
# -------------------------------------------------------
token_permission_types = [
{token_type: 'guidances', text_description: 'allows a user access to the guidances api endpoint'},
{token_type: 'plans', text_description: 'allows a user access to the plans api endpoint'}
{token_type: 'plans', text_description: 'allows a user access to the plans api endpoint'},
{token_type: 'templates', text_description: 'allows a user access to the templates api endpoint'},
{token_type: 'statistics', text_description: 'allows a user access to the statistics api endpoint'}
]
token_permission_types.map{ |tpt| TokenPermissionType.create!(tpt) if TokenPermissionType.find_by(token_type: tpt[:token_type]).nil? }

Expand Down
5 changes: 4 additions & 1 deletion lib/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import './views/devise/devise';
import './views/contacts/new';
import './views/devise/invitations/edit';
import './views/devise/passwords/edit';
import './views/devise/passwords/new';
import './views/plans/edit_details';
import './views/plans/share';
1 change: 1 addition & 0 deletions lib/assets/javascripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const VALIDATION_MESSAGE_EMAIL = 'You must enter a valid email address.';
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_TEXT = 'This field is required.';

export const SHOW_PASSWORD_MESSAGE = 'Show password';
Expand Down
101 changes: 101 additions & 0 deletions lib/assets/javascripts/spec/ariatiseFormSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import ariatiseForm from '../utils/ariatiseForm';

describe('ariatiseForm test suite', () => {
beforeAll(() => fixture.setBase('javascripts/spec/fixtures'));

beforeEach(() => {
this.submitButton = '[type="submit"]';
$('body').html(fixture.load('form.html'));
ariatiseForm({ selector: `#${$('form').attr('id')}` });
// Override the form submission, we are just going to validate the ariatisation of the form
$('form').submit((e) => { e.preventDefault(); });
});

afterEach(() => {
fixture.cleanup();
$('body').html('');
});
it('adds an error message section to fields with `aria-required="true"` or `data-validation="[type]"`', () => {
$.each($('input'), (idx, el) => {
const block = $(`#${$(el).attr('aria-describedby')}`);
if ($(el).attr('aria-required') === 'true' || $(el).attr('data-validation')) {
// The error message should be present but not visible yet
expect(block.length).toEqual(1);
expect($(block)).not.toBeVisible();
} else {
expect(block.length).toEqual(0);
}
});
});
it('invalid data causes errors to appear', () => {
const spyEvent = spyOnEvent(this.submitButton, 'click');
$(this.submitButton).trigger('click');
expect('click').toHaveBeenPreventedOn(this.submitButton);
expect(spyEvent).toHaveBeenPrevented();

// Only the aria-required="true" errors should be visible
$.each($('input[aria-required="true"]'), (idx, el) => {
const block = $(`#${$(el).attr('aria-describedby')}`);
// The error message should be present but not visible yet
expect($(block)).toBeVisible();
});

// Inputs without aria-required="true" errors should not be visible
$.each($('input').not('[aria-required="true"]').not('[type="radio"]'), (idx, el) => {
const block = $(`#${$(el).attr('aria-describedby')}`);
// The error message should be present but not visible yet
expect($(block)).not.toBeVisible();
});
});
it('text validation is working', () => {
['#text-required'].forEach((selector) => {
const block = $(`#${$(selector).attr('aria-describedby')}`);
$(selector).val('');
$(this.submitButton).click();
expect(block).toBeVisible();

$(selector).val('testing');
$(this.submitButton).click();
expect(block).not.toBeVisible();
});
});

it('email validation is working', () => {
['#email-required', '#email-not-required-with-validation'].forEach((selector) => {
const block = $(`#${$(selector).attr('aria-describedby')}`);
$(selector).val('abcd1234');
$(this.submitButton).click();
expect(block).toBeVisible();

$(selector).val('abcd1234@test.org');
$(this.submitButton).click();
expect(block).not.toBeVisible();
});
});

it('password validation is working', () => {
['#password-required', '#password-not-required-with-validation'].forEach((selector) => {
const block = $(`#${$(selector).attr('aria-describedby')}`);
$(selector).val('abc');
$(this.submitButton).click();
expect(block).toBeVisible();

$(selector).val('abcd1234');
$(this.submitButton).click();
expect(block).not.toBeVisible();
});
});

it('radio validation is working', () => {
['[name="radio-required"][aria-required="true"]'].forEach((selector) => {
const block = $(`#${$(selector).attr('aria-describedby')}`);
$(`[name="${$(selector).attr('name')}"][value="a"]`).removeAttr('checked');
$(this.submitButton).click();
expect(block).toBeVisible();

$(`[name="${$(selector).attr('name')}"][value="a"]`).attr('checked', true);
$(this.submitButton).click();
expect(block).not.toBeVisible();
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import debounce from './debounce';
import debounce from '../utils/debounce';

describe('debounce test suite', () => {
let functionToDebounce;
Expand Down
68 changes: 68 additions & 0 deletions lib/assets/javascripts/spec/fixtures/form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<form id="test-form">
<!-- Fields that are not required and have no validation specified -->
<h2>Fields that are not required and have no validation specified</h2>
<div class="form-group">
<label for="text-not-required-no-validation" class="control-label">Text Field (not required)</label>
<input id="text-not-required-no-validation" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="email-not-required-no-validation" class="control-label">Email Field (not required)</label>
<input id="email-not-required-no-validation" type="email" class="form-control" />
</div>
<div class="form-group">
<label for="password-not-required-no-validation" class="control-label">Password Field (not required)</label>
<input id="password-not-required-no-validation" type="password" class="form-control" />
</div>
<div class="radio">
<label for="radioA-not-required-no-validation">
<input id="radioA-not-required-no-validation" name="Radio-not-required-no-validation" type="radio" value="a" />Radio A (not required)
</label>
<label for="radioB-not-required-no-validation">
<input id="radioB-not-required-no-validation" name="Radio-not-required-no-validation" type="radio" value="b" />Radio B (not required)
</label>
</div>

<!-- Fields that are required -->
<h2>Fields that are required</h2>
<div class="form-group">
<label for="text-required" class="control-label">Text Field</label>
<input id="text-required" type="text" aria-required="true" class="form-control" />
</div>
<div class="form-group">
<label for="email-required" class="control-label">Email Field</label>
<input id="email-required" type="email" aria-required="true" class="form-control" />
</div>
<div class="form-group">
<label for="password-required" class="control-label">Password Field</label>
<input id="password-required" type="password" aria-required="true" class="form-control" />
</div>
<div class="radio">
<label for="radioA-required">
<input id="radioA-required" type="radio" name="radio-required" value="a" />Radio A
</label>
<label for="radioB-required">
<input id="radioB-required" type="radio" name="radio-required" value="b" aria-required="true" />Radio B
</label>
</div>

<!-- Fields that are not required but have validation specified -->
<h2>Fields that are not required but have validation specified</h2>
<div class="form-group">
<label for="email-not-required-with-validation" class="control-label">Email Field</label>
<input id="email-not-required-with-validation" type="email" data-validation="email" class="form-control" />
</div>
<div class="form-group">
<label for="password-not-required-with-validation" class="control-label">Password Field</label>
<input id="password-not-required-with-validation" type="password" data-validation="password" class="form-control" />
</div>
<div class="radio">
<label for="radioA-not-required-with-validation">
<input id="radioA-not-required-with-validation" name="radio-not-required-with-validation" type="radio" value="a" />Radio A (not required)
</label>
<label for="radioB-not-required-with-validation">
<input id="radioB-not-required-with-validation" name="radio-not-required-with-validation" type="radio" value="b" data-validation="radio" />Radio B (not required)
</label>
</div>

<button id="form-submit" type="submit" class="btn btn-default">Save</button>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
isObject,
isRegExp,
isString,
isUndefined } from './isType';
isUndefined } from '../utils/isType';

describe('isArray test suite', () => {
it('expect true for []', () => expect(isArray([])).toBe(true));
Expand Down
Loading