diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 4b79893..43e0c55 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -9,21 +9,22 @@ 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 diff --git a/app/models/settings/template.rb b/app/models/settings/template.rb index 59ac3de..a9fd6f8 100644 --- a/app/models/settings/template.rb +++ b/app/models/settings/template.rb @@ -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) @@ -17,13 +17,13 @@ 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: { diff --git a/app/models/user.rb b/app/models/user.rb index d4e0543..79f5be7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -276,5 +276,13 @@ 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 diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb index 92d1218..c61c99d 100644 --- a/app/views/devise/passwords/edit.html.erb +++ b/app/views/devise/passwords/edit.html.erb @@ -12,11 +12,11 @@
<%= 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 %>
<%= 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 %>
- <%= 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')}") %>
<%= f.button(_('Submit'), class: "btn btn-default", type: "submit") %> diff --git a/db/migrate/20170702012742_ensure_indexes_in_place.rb b/db/migrate/20170702012742_ensure_indexes_in_place.rb index 6bd9410..367ce5f 100644 --- a/db/migrate/20170702012742_ensure_indexes_in_place.rb +++ b/db/migrate/20170702012742_ensure_indexes_in_place.rb @@ -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 @@ -27,14 +31,22 @@ #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 diff --git a/db/seeds.rb b/db/seeds.rb index 6c4aded..fabb9a8 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -8,7 +8,7 @@ {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? } @@ -16,13 +16,13 @@ # 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? } @@ -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? } diff --git a/lib/assets/javascripts/application.js b/lib/assets/javascripts/application.js index 262a25d..9328f23 100644 --- a/lib/assets/javascripts/application.js +++ b/lib/assets/javascripts/application.js @@ -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'; diff --git a/lib/assets/javascripts/constants.js b/lib/assets/javascripts/constants.js index eabe1db..1ac6267 100644 --- a/lib/assets/javascripts/constants.js +++ b/lib/assets/javascripts/constants.js @@ -6,6 +6,7 @@ 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'; diff --git a/lib/assets/javascripts/spec/ariatiseFormSpec.js b/lib/assets/javascripts/spec/ariatiseFormSpec.js new file mode 100644 index 0000000..439753d --- /dev/null +++ b/lib/assets/javascripts/spec/ariatiseFormSpec.js @@ -0,0 +1,105 @@ +import ariatiseForm from '../utils/ariatiseForm'; + +describe('ariatiseForm test suite', () => { + beforeAll(() => fixture.setBase('javascripts/spec/fixtures')); + + beforeEach(() => { + this.submitButton = '[type="submit"]'; + this.form = 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(); + }); + + 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).click(); + + // TODO: For some reason the Spy does not catch the button 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(); + }); + }); +}); diff --git a/lib/assets/javascripts/spec/debounceSpec.js b/lib/assets/javascripts/spec/debounceSpec.js new file mode 100644 index 0000000..0aa8640 --- /dev/null +++ b/lib/assets/javascripts/spec/debounceSpec.js @@ -0,0 +1,68 @@ +import debounce from '../utils/debounce'; + +describe('debounce test suite', () => { + let functionToDebounce; + + beforeEach(() => { + functionToDebounce = jasmine.createSpy('My function to debounce'); + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('functionToDebounce gets called after the time specified', () => { + const debounced = debounce(functionToDebounce, 1000); + + debounced('foo', 'bar'); + + expect(functionToDebounce).not.toHaveBeenCalled(); + + jasmine.clock().tick(1001); + + expect(functionToDebounce).toHaveBeenCalled(); + expect(functionToDebounce.calls.first().args[0]).toBe('foo'); + expect(functionToDebounce.calls.first().args[1]).toBe('bar'); + }); + + it('functionToDebounce gets cancelled before time elapses', () => { + const debounced = debounce(functionToDebounce, 1000); + + debounced('foo', 'bar'); + + jasmine.clock().tick(999); + debounced.cancel(); + jasmine.clock().tick(2); + + expect(functionToDebounce).not.toHaveBeenCalled(); + }); + + it('functionToDebounce gets called once after the time specified', () => { + const debounced = debounce(functionToDebounce, 1000); + + debounced('foo', 'bar'); + jasmine.clock().tick(999); + debounced('foo', 'bar'); + jasmine.clock().tick(999); + debounced('foo', 'bar'); + jasmine.clock().tick(1001); + + expect(functionToDebounce.calls.count()).toBe(1); + }); + + it('functionToDebounce gets called once after the time specified with args of last invocation', () => { + const debounced = debounce(functionToDebounce, 1000); + + debounced('foo', 'bar'); + jasmine.clock().tick(999); + debounced('foo2', 'bar2'); + jasmine.clock().tick(999); + debounced('foo3', 'bar3'); + jasmine.clock().tick(1001); + + expect(functionToDebounce.calls.count()).toBe(1); + expect(functionToDebounce.calls.first().args[0]).toBe('foo3'); + expect(functionToDebounce.calls.first().args[1]).toBe('bar3'); + }); +}); diff --git a/lib/assets/javascripts/spec/fixtures/form.html b/lib/assets/javascripts/spec/fixtures/form.html new file mode 100644 index 0000000..bf06e68 --- /dev/null +++ b/lib/assets/javascripts/spec/fixtures/form.html @@ -0,0 +1,68 @@ +
+ +

Fields that are not required and have no validation specified

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +

Fields that are required

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +

Fields that are not required but have validation specified

+
+ + +
+
+ + +
+
+ + +
+ + +
\ No newline at end of file diff --git a/lib/assets/javascripts/spec/isTypeSpec.js b/lib/assets/javascripts/spec/isTypeSpec.js new file mode 100644 index 0000000..fbfe768 --- /dev/null +++ b/lib/assets/javascripts/spec/isTypeSpec.js @@ -0,0 +1,146 @@ +import { + isArray, + isBoolean, + isDate, + isFunction, + isNumber, + isNull, + isObject, + isRegExp, + isString, + isUndefined } from '../utils/isType'; + +describe('isArray test suite', () => { + it('expect true for []', () => expect(isArray([])).toBe(true)); + it('expect false for Boolean', () => expect(isArray(true)).toBe(false)); + it('expect false for Date', () => expect(isArray(new Date())).toBe(false)); + it('expect false for Function', () => expect(isArray(() => {})).toBe(false)); + it('expect false for Number', () => expect(isArray(1)).toBe(false)); + it('expect false for Null', () => expect(isArray(null)).toBe(false)); + it('expect false for Object', () => expect(isArray({})).toBe(false)); + it('expect false for RegExp', () => expect(isArray(/foo/)).toBe(false)); + it('expect false for String', () => expect(isArray('Hello World!')).toBe(false)); + it('expect false for Undefined', () => expect(isArray(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isArray()).toBe(false)); +}); + +describe('isBoolean test suite', () => { + it('expect true for true', () => expect(isBoolean(true)).toBe(true)); + it('expect true for false', () => expect(isBoolean(true)).toBe(true)); + it('expect false for []', () => expect(isBoolean([])).toBe(false)); + it('expect false for Date', () => expect(isBoolean(new Date())).toBe(false)); + it('expect false for Function', () => expect(isBoolean(() => {})).toBe(false)); + it('expect false for Number', () => expect(isBoolean(1)).toBe(false)); + it('expect false for Null', () => expect(isBoolean(null)).toBe(false)); + it('expect false for Object', () => expect(isBoolean({})).toBe(false)); + it('expect false for RegExp', () => expect(isBoolean(/foo/)).toBe(false)); + it('expect false for String', () => expect(isBoolean('Hello World!')).toBe(false)); + it('expect false for Undefined', () => expect(isBoolean(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isBoolean()).toBe(false)); +}); + +describe('isDate test suite', () => { + it('expect true for Date', () => expect(isDate(new Date())).toBe(true)); + it('expect fase for []', () => expect(isDate([])).toBe(false)); + it('expect fase for Boolean', () => expect(isDate(true)).toBe(false)); + it('expect fase for Function', () => expect(isDate(() => {})).toBe(false)); + it('expect fase for Number', () => expect(isDate(1)).toBe(false)); + it('expect fase for Null', () => expect(isDate(null)).toBe(false)); + it('expect fase for Object', () => expect(isDate({})).toBe(false)); + it('expect fase for RegExp', () => expect(isDate(/foo/)).toBe(false)); + it('expect fase for String', () => expect(isDate('Hello World!')).toBe(false)); + it('expect fase for zero args', () => expect(isDate(undefined)).toBe(false)); +}); + +describe('isFunction test suite', () => { + it('expect true for Function', () => expect(isFunction(() => {})).toBe(true)); + it('expect false for []', () => expect(isFunction([])).toBe(false)); + it('expect false for Boolean', () => expect(isFunction(true)).toBe(false)); + it('expect false for Date', () => expect(isFunction(new Date())).toBe(false)); + it('expect false for Number', () => expect(isFunction(1)).toBe(false)); + it('expect false for Null', () => expect(isFunction(null)).toBe(false)); + it('expect false for Object', () => expect(isFunction({})).toBe(false)); + it('expect false for RegExp', () => expect(isFunction(/foo/)).toBe(false)); + it('expect false for String', () => expect(isFunction('Hello World!')).toBe(false)); + it('expect false for undefined', () => expect(isFunction(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isFunction()).toBe(false)); +}); + +describe('isNumber test suite', () => { + it('expect true for 1', () => expect(isNumber(1)).toBe(true)); + it('expect true for NaN', () => expect(isNumber(NaN)).toBe(true)); + it('expect true for Infinity', () => expect(isNumber(Infinity)).toBe(true)); + it('expect false for []', () => expect(isNumber([])).toBe(false)); + it('expect false for Boolean', () => expect(isNumber(true)).toBe(false)); + it('expect false for Date', () => expect(isNumber(new Date())).toBe(false)); + it('expect false for Null', () => expect(isNumber(null)).toBe(false)); + it('expect false for Object', () => expect(isNumber({})).toBe(false)); + it('expect false for RegExp', () => expect(isNumber(/foo/)).toBe(false)); + it('expect false for String', () => expect(isNumber('Hello World!')).toBe(false)); + it('expect false for undefined', () => expect(isNumber(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isNumber()).toBe(false)); +}); + +describe('isNull test suite', () => { + it('expect true for Null', () => expect(isNull(null)).toBe(true)); + it('expect false for []', () => expect(isNull([])).toBe(false)); + it('expect false for Boolean', () => expect(isNull(true)).toBe(false)); + it('expect false for Date', () => expect(isNull(new Date())).toBe(false)); + it('expect false for Number', () => expect(isNull(1)).toBe(false)); + it('expect false for Object', () => expect(isNull(Object.create(null))).toBe(false)); + it('expect false for RegExp', () => expect(isNull(/foo/)).toBe(false)); + it('expect false for String', () => expect(isNull('null')).toBe(false)); + it('expect false for undefined', () => expect(isNull(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isNull()).toBe(false)); +}); + +describe('isObject test suite', () => { + it('expect true for {}', () => expect(isObject({})).toBe(true)); + it('expect true for []', () => expect(isObject([])).toBe(true)); + it('expect true for Date', () => expect(isObject(new Date())).toBe(true)); + it('expect true for RegExp', () => expect(isObject(/foo/)).toBe(true)); + it('expect false for Number', () => expect(isObject(1)).toBe(false)); + it('expect false for Null', () => expect(isObject(null)).toBe(false)); + it('expect false for String', () => expect(isObject('Hello World!')).toBe(false)); + it('expect false for undefined', () => expect(isObject(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isObject()).toBe(false)); +}); + +describe('isRegExp test suite', () => { + it('expect true for RegExp', () => expect(isRegExp(/foo/)).toBe(true)); + it('expect true for RegExp', () => expect(isRegExp(new RegExp('foo'))).toBe(true)); + it('expect false for []', () => expect(isRegExp([])).toBe(false)); + it('expect false for Boolean', () => expect(isRegExp(true)).toBe(false)); + it('expect false for Date', () => expect(isRegExp(new Date())).toBe(false)); + it('expect false for Number', () => expect(isRegExp(1)).toBe(false)); + it('expect false for Null', () => expect(isRegExp(null)).toBe(false)); + it('expect false for String', () => expect(isRegExp('Hello World!')).toBe(false)); + it('expect false for undefined', () => expect(isRegExp(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isRegExp()).toBe(false)); +}); + +describe('isString test suite', () => { + it('expect true for String', () => expect(isString('Hello World!')).toBe(true)); + it('expect false for []', () => expect(isString([])).toBe(false)); + it('expect false for Boolean', () => expect(isString(true)).toBe(false)); + it('expect false for Date', () => expect(isString(new Date())).toBe(false)); + it('expect false for Function', () => expect(isString(() => {})).toBe(false)); + it('expect false for Number', () => expect(isString(1)).toBe(false)); + it('expect false for Null', () => expect(isString(null)).toBe(false)); + it('expect false for RegExp', () => expect(isString(/foo/)).toBe(false)); + it('expect false for Undefined', () => expect(isString(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isString()).toBe(false)); +}); + +describe('isUndefined test suite', () => { + it('expect true for Undefined', () => expect(isUndefined(undefined)).toBe(true)); + it('expect false for zero args', () => expect(isUndefined()).toBe(true)); + it('expect false for []', () => expect(isUndefined([])).toBe(false)); + it('expect false for Boolean', () => expect(isUndefined(true)).toBe(false)); + it('expect false for Date', () => expect(isUndefined(new Date())).toBe(false)); + it('expect false for Function', () => expect(isUndefined(() => {})).toBe(false)); + it('expect false for Number', () => expect(isUndefined(1)).toBe(false)); + it('expect false for Null', () => expect(isUndefined(null)).toBe(false)); + it('expect false for RegExp', () => expect(isUndefined(/foo/)).toBe(false)); + it('expect false for String', () => expect(isUndefined('Hello World!')).toBe(false)); +}); diff --git a/lib/assets/javascripts/spec/isValidInputTypeSpec.js b/lib/assets/javascripts/spec/isValidInputTypeSpec.js new file mode 100644 index 0000000..c90235f --- /dev/null +++ b/lib/assets/javascripts/spec/isValidInputTypeSpec.js @@ -0,0 +1,43 @@ +import { + isValidEmail, + isValidNumber, + isValidPassword, + isValidText, +} from '../utils/isValidInputType'; + +describe('isValidEmail test suite', () => { + it('expect true for someone@somewhere.com', () => expect(isValidEmail('someone@somewhere.com')).toBe(true)); + it('expect true for s@somewhere.ac.uk', () => expect(isValidEmail('s@somewhere.ac.uk')).toBe(true)); + it('expect true for someone@somewhere.gov.ac.uk', () => expect(isValidEmail('someone@somewhere.gov.ac.uk')).toBe(true)); + it('expect false for @somewhere.com', () => expect(isValidEmail('@somewhere.com')).toBe(false)); + it('expect false for s@somewhere.ac.u', () => expect(isValidEmail('s@somewhere.ac.u')).toBe(false)); + it('expect false for someone@somewhere.gov.ac.u', () => expect(isValidEmail('someone@somewhere.gov.ac.u')).toBe(false)); +}); + +describe('isValidNumber test suite', () => { + it('expect true for 1', () => expect(isValidNumber(1)).toBe(true)); + it('expect true for \'1\'', () => expect(isValidNumber('1')).toBe(true)); + it('expect true for Infinity', () => expect(isValidNumber(Infinity)).toBe(true)); + it('expect false for Array', () => expect(isValidNumber([])).toBe(false)); + it('expect false for Boolean', () => expect(isValidNumber(true)).toBe(false)); + it('expect false for Date', () => expect(isValidNumber(new Date())).toBe(false)); + it('expect false for Function', () => expect(isValidNumber(() => {})).toBe(false)); + it('expect false for Object', () => expect(isValidNumber({})).toBe(false)); + it('expect false for RegExp', () => expect(isValidNumber(/foo/)).toBe(false)); + it('expect false for String', () => expect(isValidNumber('Hello World!')).toBe(false)); + it('expect false for Null', () => expect(isValidNumber(null)).toBe(false)); + it('expect false for Array', () => expect(isValidNumber(undefined)).toBe(false)); + it('expect false for zero args', () => expect(isValidNumber()).toBe(false)); +}); + +describe('isValidPassword test suite', () => { + it('expect true for hjkl7890', () => expect(isValidPassword('hjkl7890')).toBe(true)); + it('expect false for hjkl', () => expect(isValidPassword('hjkl')).toBe(false)); + it('expect false for \' abcd \'', () => expect(isValidPassword(' abcd ')).toBe(false)); + it('expect false for non-string', () => expect(isValidPassword(null)).toBe(false)); +}); + +describe('isValid test suite', () => { + it('expect true for h', () => expect(isValidText('h')).toBe(true)); + it('expect false for \' \'', () => expect(isValidText(' ')).toBe(false)); +}); diff --git a/lib/assets/javascripts/utils/ariatiseForm.js b/lib/assets/javascripts/utils/ariatiseForm.js index a1f9264..2471742 100644 --- a/lib/assets/javascripts/utils/ariatiseForm.js +++ b/lib/assets/javascripts/utils/ariatiseForm.js @@ -1,3 +1,29 @@ +/* + This module allows you to add the necessary aria tags to your form elements to + make them accessible and wire up client-side error handling. Usage: + + Required Fields + ------------------------ + To make a field required just add the `aria-required="true"` attribute to the + input element. The element's `type` attribute will be used to determine what + validation method will be used. + Example: `` + + Validation for fields that are not required + ------------------------ + To add validation to a field that is not required, just add the + `data-validation=""` to the input element. Validation checks will only + be run if the field has a value. + Example: `` + + Validation for radio buttons + ------------------------ + To add validation to a set of `radio` buttons, use the rules listed above, + but you should only attach them to the last `` in the set. + Example: ` + ` +*/ + import { isObject, isString, isBoolean } from './isType'; import * as constants from '../constants'; import * as validator from './isValidInputType'; @@ -51,6 +77,15 @@ return false; }; +const getValue = (type, el) => { + switch (type) { + case 'radio': + return $(el).closest('form').find(`input[name="${$(el).attr('name')}"]:checked`).val(); + default: + return $(el).val(); + } +}; + const isValid = (type, value) => { // TODO add more validation for each new type coming along by: // 1. defining a function at dmproadmap.utils.validate @@ -66,6 +101,8 @@ return validator.isValidEmail(value); case 'password': return validator.isValidPassword(value); + case 'radio': + return validator.isValidText(value); default: return false; } @@ -81,6 +118,8 @@ return constants.VALIDATION_MESSAGE_EMAIL; case 'password': return constants.VALIDATION_MESSAGE_PASSWORD; + case 'radio': + return constants.VALIDATION_MESSAGE_RADIO; default: return constants.VALIDATION_MESSAGE_DEFAULT; } @@ -116,7 +155,7 @@ // If the field is required OR its not empty if (required || $(el).val().trim() !== '') { - if (isValid(type, $(el).val())) { + if (isValid(type, getValue(type, el))) { valid(el); } else { e.preventDefault(); diff --git a/lib/assets/javascripts/utils/debounceSpec.js b/lib/assets/javascripts/utils/debounceSpec.js deleted file mode 100644 index c5803df..0000000 --- a/lib/assets/javascripts/utils/debounceSpec.js +++ /dev/null @@ -1,68 +0,0 @@ -import debounce from './debounce'; - -describe('debounce test suite', () => { - let functionToDebounce; - - beforeEach(() => { - functionToDebounce = jasmine.createSpy('My function to debounce'); - jasmine.clock().install(); - }); - - afterEach(() => { - jasmine.clock().uninstall(); - }); - - it('functionToDebounce gets called after the time specified', () => { - const debounced = debounce(functionToDebounce, 1000); - - debounced('foo', 'bar'); - - expect(functionToDebounce).not.toHaveBeenCalled(); - - jasmine.clock().tick(1001); - - expect(functionToDebounce).toHaveBeenCalled(); - expect(functionToDebounce.calls.first().args[0]).toBe('foo'); - expect(functionToDebounce.calls.first().args[1]).toBe('bar'); - }); - - it('functionToDebounce gets cancelled before time elapses', () => { - const debounced = debounce(functionToDebounce, 1000); - - debounced('foo', 'bar'); - - jasmine.clock().tick(999); - debounced.cancel(); - jasmine.clock().tick(2); - - expect(functionToDebounce).not.toHaveBeenCalled(); - }); - - it('functionToDebounce gets called once after the time specified', () => { - const debounced = debounce(functionToDebounce, 1000); - - debounced('foo', 'bar'); - jasmine.clock().tick(999); - debounced('foo', 'bar'); - jasmine.clock().tick(999); - debounced('foo', 'bar'); - jasmine.clock().tick(1001); - - expect(functionToDebounce.calls.count()).toBe(1); - }); - - it('functionToDebounce gets called once after the time specified with args of last invocation', () => { - const debounced = debounce(functionToDebounce, 1000); - - debounced('foo', 'bar'); - jasmine.clock().tick(999); - debounced('foo2', 'bar2'); - jasmine.clock().tick(999); - debounced('foo3', 'bar3'); - jasmine.clock().tick(1001); - - expect(functionToDebounce.calls.count()).toBe(1); - expect(functionToDebounce.calls.first().args[0]).toBe('foo3'); - expect(functionToDebounce.calls.first().args[1]).toBe('bar3'); - }); -}); diff --git a/lib/assets/javascripts/utils/isTypeSpec.js b/lib/assets/javascripts/utils/isTypeSpec.js deleted file mode 100644 index f85ef1a..0000000 --- a/lib/assets/javascripts/utils/isTypeSpec.js +++ /dev/null @@ -1,146 +0,0 @@ -import { - isArray, - isBoolean, - isDate, - isFunction, - isNumber, - isNull, - isObject, - isRegExp, - isString, - isUndefined } from './isType'; - -describe('isArray test suite', () => { - it('expect true for []', () => expect(isArray([])).toBe(true)); - it('expect false for Boolean', () => expect(isArray(true)).toBe(false)); - it('expect false for Date', () => expect(isArray(new Date())).toBe(false)); - it('expect false for Function', () => expect(isArray(() => {})).toBe(false)); - it('expect false for Number', () => expect(isArray(1)).toBe(false)); - it('expect false for Null', () => expect(isArray(null)).toBe(false)); - it('expect false for Object', () => expect(isArray({})).toBe(false)); - it('expect false for RegExp', () => expect(isArray(/foo/)).toBe(false)); - it('expect false for String', () => expect(isArray('Hello World!')).toBe(false)); - it('expect false for Undefined', () => expect(isArray(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isArray()).toBe(false)); -}); - -describe('isBoolean test suite', () => { - it('expect true for true', () => expect(isBoolean(true)).toBe(true)); - it('expect true for false', () => expect(isBoolean(true)).toBe(true)); - it('expect false for []', () => expect(isBoolean([])).toBe(false)); - it('expect false for Date', () => expect(isBoolean(new Date())).toBe(false)); - it('expect false for Function', () => expect(isBoolean(() => {})).toBe(false)); - it('expect false for Number', () => expect(isBoolean(1)).toBe(false)); - it('expect false for Null', () => expect(isBoolean(null)).toBe(false)); - it('expect false for Object', () => expect(isBoolean({})).toBe(false)); - it('expect false for RegExp', () => expect(isBoolean(/foo/)).toBe(false)); - it('expect false for String', () => expect(isBoolean('Hello World!')).toBe(false)); - it('expect false for Undefined', () => expect(isBoolean(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isBoolean()).toBe(false)); -}); - -describe('isDate test suite', () => { - it('expect true for Date', () => expect(isDate(new Date())).toBe(true)); - it('expect fase for []', () => expect(isDate([])).toBe(false)); - it('expect fase for Boolean', () => expect(isDate(true)).toBe(false)); - it('expect fase for Function', () => expect(isDate(() => {})).toBe(false)); - it('expect fase for Number', () => expect(isDate(1)).toBe(false)); - it('expect fase for Null', () => expect(isDate(null)).toBe(false)); - it('expect fase for Object', () => expect(isDate({})).toBe(false)); - it('expect fase for RegExp', () => expect(isDate(/foo/)).toBe(false)); - it('expect fase for String', () => expect(isDate('Hello World!')).toBe(false)); - it('expect fase for zero args', () => expect(isDate(undefined)).toBe(false)); -}); - -describe('isFunction test suite', () => { - it('expect true for Function', () => expect(isFunction(() => {})).toBe(true)); - it('expect false for []', () => expect(isFunction([])).toBe(false)); - it('expect false for Boolean', () => expect(isFunction(true)).toBe(false)); - it('expect false for Date', () => expect(isFunction(new Date())).toBe(false)); - it('expect false for Number', () => expect(isFunction(1)).toBe(false)); - it('expect false for Null', () => expect(isFunction(null)).toBe(false)); - it('expect false for Object', () => expect(isFunction({})).toBe(false)); - it('expect false for RegExp', () => expect(isFunction(/foo/)).toBe(false)); - it('expect false for String', () => expect(isFunction('Hello World!')).toBe(false)); - it('expect false for undefined', () => expect(isFunction(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isFunction()).toBe(false)); -}); - -describe('isNumber test suite', () => { - it('expect true for 1', () => expect(isNumber(1)).toBe(true)); - it('expect true for NaN', () => expect(isNumber(NaN)).toBe(true)); - it('expect true for Infinity', () => expect(isNumber(Infinity)).toBe(true)); - it('expect false for []', () => expect(isNumber([])).toBe(false)); - it('expect false for Boolean', () => expect(isNumber(true)).toBe(false)); - it('expect false for Date', () => expect(isNumber(new Date())).toBe(false)); - it('expect false for Null', () => expect(isNumber(null)).toBe(false)); - it('expect false for Object', () => expect(isNumber({})).toBe(false)); - it('expect false for RegExp', () => expect(isNumber(/foo/)).toBe(false)); - it('expect false for String', () => expect(isNumber('Hello World!')).toBe(false)); - it('expect false for undefined', () => expect(isNumber(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isNumber()).toBe(false)); -}); - -describe('isNull test suite', () => { - it('expect true for Null', () => expect(isNull(null)).toBe(true)); - it('expect false for []', () => expect(isNull([])).toBe(false)); - it('expect false for Boolean', () => expect(isNull(true)).toBe(false)); - it('expect false for Date', () => expect(isNull(new Date())).toBe(false)); - it('expect false for Number', () => expect(isNull(1)).toBe(false)); - it('expect false for Object', () => expect(isNull(Object.create(null))).toBe(false)); - it('expect false for RegExp', () => expect(isNull(/foo/)).toBe(false)); - it('expect false for String', () => expect(isNull('null')).toBe(false)); - it('expect false for undefined', () => expect(isNull(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isNull()).toBe(false)); -}); - -describe('isObject test suite', () => { - it('expect true for {}', () => expect(isObject({})).toBe(true)); - it('expect true for []', () => expect(isObject([])).toBe(true)); - it('expect true for Date', () => expect(isObject(new Date())).toBe(true)); - it('expect true for RegExp', () => expect(isObject(/foo/)).toBe(true)); - it('expect false for Number', () => expect(isObject(1)).toBe(false)); - it('expect false for Null', () => expect(isObject(null)).toBe(false)); - it('expect false for String', () => expect(isObject('Hello World!')).toBe(false)); - it('expect false for undefined', () => expect(isObject(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isObject()).toBe(false)); -}); - -describe('isRegExp test suite', () => { - it('expect true for RegExp', () => expect(isRegExp(/foo/)).toBe(true)); - it('expect true for RegExp', () => expect(isRegExp(new RegExp('foo'))).toBe(true)); - it('expect false for []', () => expect(isRegExp([])).toBe(false)); - it('expect false for Boolean', () => expect(isRegExp(true)).toBe(false)); - it('expect false for Date', () => expect(isRegExp(new Date())).toBe(false)); - it('expect false for Number', () => expect(isRegExp(1)).toBe(false)); - it('expect false for Null', () => expect(isRegExp(null)).toBe(false)); - it('expect false for String', () => expect(isRegExp('Hello World!')).toBe(false)); - it('expect false for undefined', () => expect(isRegExp(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isRegExp()).toBe(false)); -}); - -describe('isString test suite', () => { - it('expect true for String', () => expect(isString('Hello World!')).toBe(true)); - it('expect false for []', () => expect(isString([])).toBe(false)); - it('expect false for Boolean', () => expect(isString(true)).toBe(false)); - it('expect false for Date', () => expect(isString(new Date())).toBe(false)); - it('expect false for Function', () => expect(isString(() => {})).toBe(false)); - it('expect false for Number', () => expect(isString(1)).toBe(false)); - it('expect false for Null', () => expect(isString(null)).toBe(false)); - it('expect false for RegExp', () => expect(isString(/foo/)).toBe(false)); - it('expect false for Undefined', () => expect(isString(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isString()).toBe(false)); -}); - -describe('isUndefined test suite', () => { - it('expect true for Undefined', () => expect(isUndefined(undefined)).toBe(true)); - it('expect false for zero args', () => expect(isUndefined()).toBe(true)); - it('expect false for []', () => expect(isUndefined([])).toBe(false)); - it('expect false for Boolean', () => expect(isUndefined(true)).toBe(false)); - it('expect false for Date', () => expect(isUndefined(new Date())).toBe(false)); - it('expect false for Function', () => expect(isUndefined(() => {})).toBe(false)); - it('expect false for Number', () => expect(isUndefined(1)).toBe(false)); - it('expect false for Null', () => expect(isUndefined(null)).toBe(false)); - it('expect false for RegExp', () => expect(isUndefined(/foo/)).toBe(false)); - it('expect false for String', () => expect(isUndefined('Hello World!')).toBe(false)); -}); diff --git a/lib/assets/javascripts/utils/isValidInputType.js b/lib/assets/javascripts/utils/isValidInputType.js index 6073730..5fcfc94 100644 --- a/lib/assets/javascripts/utils/isValidInputType.js +++ b/lib/assets/javascripts/utils/isValidInputType.js @@ -53,4 +53,3 @@ } return false; }; - diff --git a/lib/assets/javascripts/utils/isValidInputTypeSpec.js b/lib/assets/javascripts/utils/isValidInputTypeSpec.js deleted file mode 100644 index 6eaf31f..0000000 --- a/lib/assets/javascripts/utils/isValidInputTypeSpec.js +++ /dev/null @@ -1,43 +0,0 @@ -import { - isValidEmail, - isValidNumber, - isValidPassword, - isValidText, -} from './isValidInputType'; - -describe('isValidEmail test suite', () => { - it('expect true for someone@somewhere.com', () => expect(isValidEmail('someone@somewhere.com')).toBe(true)); - it('expect true for s@somewhere.ac.uk', () => expect(isValidEmail('s@somewhere.ac.uk')).toBe(true)); - it('expect true for someone@somewhere.gov.ac.uk', () => expect(isValidEmail('someone@somewhere.gov.ac.uk')).toBe(true)); - it('expect false for @somewhere.com', () => expect(isValidEmail('@somewhere.com')).toBe(false)); - it('expect false for s@somewhere.ac.u', () => expect(isValidEmail('s@somewhere.ac.u')).toBe(false)); - it('expect false for someone@somewhere.gov.ac.u', () => expect(isValidEmail('someone@somewhere.gov.ac.u')).toBe(false)); -}); - -describe('isValidNumber test suite', () => { - it('expect true for 1', () => expect(isValidNumber(1)).toBe(true)); - it('expect true for \'1\'', () => expect(isValidNumber('1')).toBe(true)); - it('expect true for Infinity', () => expect(isValidNumber(Infinity)).toBe(true)); - it('expect false for Array', () => expect(isValidNumber([])).toBe(false)); - it('expect false for Boolean', () => expect(isValidNumber(true)).toBe(false)); - it('expect false for Date', () => expect(isValidNumber(new Date())).toBe(false)); - it('expect false for Function', () => expect(isValidNumber(() => {})).toBe(false)); - it('expect false for Object', () => expect(isValidNumber({})).toBe(false)); - it('expect false for RegExp', () => expect(isValidNumber(/foo/)).toBe(false)); - it('expect false for String', () => expect(isValidNumber('Hello World!')).toBe(false)); - it('expect false for Null', () => expect(isValidNumber(null)).toBe(false)); - it('expect false for Array', () => expect(isValidNumber(undefined)).toBe(false)); - it('expect false for zero args', () => expect(isValidNumber()).toBe(false)); -}); - -describe('isValidPassword test suite', () => { - it('expect true for hjkl7890', () => expect(isValidPassword('hjkl7890')).toBe(true)); - it('expect false for hjkl', () => expect(isValidPassword('hjkl')).toBe(false)); - it('expect false for \' abcd \'', () => expect(isValidPassword(' abcd ')).toBe(false)); - it('expect false for non-string', () => expect(isValidPassword(null)).toBe(false)); -}); - -describe('isValid test suite', () => { - it('expect true for h', () => expect(isValidText('h')).toBe(true)); - it('expect false for \' \'', () => expect(isValidText(' ')).toBe(false)); -}); diff --git a/lib/assets/javascripts/views/devise/devise.js b/lib/assets/javascripts/views/devise/devise.js deleted file mode 100644 index 695b5ba..0000000 --- a/lib/assets/javascripts/views/devise/devise.js +++ /dev/null @@ -1,36 +0,0 @@ -import ariatiseForm from '../../utils/ariatiseForm'; -import { addMatchingPasswordValidator, togglisePasswords } from '../../utils/passwordHelper'; -import { SHOW_SELECT_ORG_MESSAGE, SHOW_OTHER_ORG_MESSAGE } from '../../constants'; - -/* - Ariatise all of the devise forms -*/ -$(() => { - ariatiseForm({ selector: '#sign_in_form' }); - ariatiseForm({ selector: '#create_account_form' }); - ariatiseForm({ selector: '#user_request_reset_password_form' }); - ariatiseForm({ selector: '#user_reset_password_form' }); - ariatiseForm({ selector: '#invitation_create_account_form' }); - - addMatchingPasswordValidator({ selector: '#user_reset_password_form' }); - - togglisePasswords({ selector: '#sign_in_form' }); - togglisePasswords({ selector: '#create_account_form' }); - togglisePasswords({ selector: '#user_reset_password_form' }); - - $('#other_org_link').click((e) => { - e.preventDefault(); - const other = $('#user_other_organisation'); - const selector = $('.combobox-container'); - if ($(other).css('display') === 'none') { - $('#other_org_link').text(SHOW_SELECT_ORG_MESSAGE); - $(selector).hide(); - $(other).show(); - } else { - $('#other_org_link').text(SHOW_OTHER_ORG_MESSAGE); - $(selector).show(); - $(other).val('').hide(); - } - }); -}); - diff --git a/lib/assets/javascripts/views/devise/invitations/edit.js b/lib/assets/javascripts/views/devise/invitations/edit.js new file mode 100644 index 0000000..3ad30db --- /dev/null +++ b/lib/assets/javascripts/views/devise/invitations/edit.js @@ -0,0 +1,5 @@ +import ariatiseForm from '../../../utils/ariatiseForm'; + +$(() => { + ariatiseForm({ selector: '#invitation_create_account_form' }); +}); diff --git a/lib/assets/javascripts/views/devise/passwords/edit.js b/lib/assets/javascripts/views/devise/passwords/edit.js new file mode 100644 index 0000000..b4b91a5 --- /dev/null +++ b/lib/assets/javascripts/views/devise/passwords/edit.js @@ -0,0 +1,8 @@ +import ariatiseForm from '../../../utils/ariatiseForm'; +import { addMatchingPasswordValidator, togglisePasswords } from '../../../utils/passwordHelper'; + +$(() => { + ariatiseForm({ selector: '#user_reset_password_form' }); + addMatchingPasswordValidator({ selector: '#user_reset_password_form' }); + togglisePasswords({ selector: '#user_reset_password_form' }); +}); diff --git a/lib/assets/javascripts/views/devise/passwords/new.js b/lib/assets/javascripts/views/devise/passwords/new.js new file mode 100644 index 0000000..0abfa4b --- /dev/null +++ b/lib/assets/javascripts/views/devise/passwords/new.js @@ -0,0 +1,5 @@ +import ariatiseForm from '../../../utils/ariatiseForm'; + +$(() => { + ariatiseForm({ selector: '#user_request_reset_password_form' }); +}); diff --git a/lib/assets/javascripts/views/plans/share.js b/lib/assets/javascripts/views/plans/share.js index b221b47..7b54f68 100644 --- a/lib/assets/javascripts/views/plans/share.js +++ b/lib/assets/javascripts/views/plans/share.js @@ -1,43 +1,6 @@ -$(document).ready(function(){ - /*---------------- - Listener for changes in access-level for a plan shared with a user - TODO partial update instead of forcing a page reload - ------------------*/ - $(".toggle-existing-user-access").change(function(){ - var params = {role: {access_level: $(this).find("option:checked").val()}}; - asyncRequest({ - url: "/roles/" + $(this).closest("form").find("#role_id").val(), - type: 'PUT', - data: JSON.stringify(params) - }); - }); - - // Run the input validations when the focus changes - $("#role_user_email").on('blur', function(){ - toggleFormElementError(this, validateEmail($(this).val().trim())); - }); - - // See if we should enable the add collaborator button - $("#role_user_email").on('change keyup', function(){ - toggleAddCollaboratorSubmit(); - }); - $("input[name='role[access_level]']").on('click', function(){ - toggleAddCollaboratorSubmit(); - }); - - $("input[name='plan[visibility]']").on('click, change', function(e){ - var params = {plan: {visibility: $("input[name='plan[visibility]']:checked").val()}}; - asyncRequest({ - url: "/plans/" + $("#plan_id").val() + "/visibility", - type: 'POST', - data: JSON.stringify(params) - }); - }); - - // Display the submit button only if there is a valid email and password - function toggleAddCollaboratorSubmit(){ - var disabled = (validateEmail($("#role_user_email").val()) != '' || - $("input[name='role[access_level]']:checked").val() == undefined); - $("#add-collaborator-button").attr('aria-disabled', disabled); - } +import ariatiseForm from '../../utils/ariatiseForm'; + +$().ready(() => { + // Invite Collaborators form on the Share page + ariatiseForm({ selector: '#new_role' }); }); diff --git a/lib/assets/javascripts/views/shared/create_account_form.js b/lib/assets/javascripts/views/shared/create_account_form.js new file mode 100644 index 0000000..da63fd1 --- /dev/null +++ b/lib/assets/javascripts/views/shared/create_account_form.js @@ -0,0 +1,23 @@ +import ariatiseForm from '../../utils/ariatiseForm'; +import togglisePasswords from '../../utils/passwordHelper'; +import { SHOW_SELECT_ORG_MESSAGE, SHOW_OTHER_ORG_MESSAGE } from '../../constants'; + +$(() => { + ariatiseForm({ selector: '#create_account_form' }); + togglisePasswords({ selector: '#create_account_form' }); + + $('#other_org_link').click((e) => { + e.preventDefault(); + const other = $('#user_other_organisation'); + const selector = $('.combobox-container'); + if ($(other).css('display') === 'none') { + $('#other_org_link').text(SHOW_SELECT_ORG_MESSAGE); + $(selector).hide(); + $(other).show(); + } else { + $('#other_org_link').text(SHOW_OTHER_ORG_MESSAGE); + $(selector).show(); + $(other).val('').hide(); + } + }); +}); diff --git a/lib/assets/javascripts/views/shared/login_form.js b/lib/assets/javascripts/views/shared/login_form.js deleted file mode 100644 index c081110..0000000 --- a/lib/assets/javascripts/views/shared/login_form.js +++ /dev/null @@ -1,52 +0,0 @@ -$(document).ready(function(){ - if($("form.login-form").length > 0){ - // If the hidden valid-form field is set to true then enable the submit button - $("form.login-form #valid-form").change(function(){ - $(this).siblings(".form-submit").attr('aria-disabled', $(this).val() != "true"); - }); - - // See if we should enable the submit button when a required input changes - $("form.login-form input[class*='required']").on('change keyup', function(){ - toggleLogInSubmit(); - }); - - // Run the input validations when the focus changes - $("form.login-form #user_email").on('blur', function(){ - toggleFormElementError(this, validateEmail($(this).val().trim())); - }); - $("form.login-form #user_password").on('blur', function(){ - toggleFormElementError(this, validatePassword($(this).val().trim())); - }); - - // Toggle the password field so that its visible/masked - $("form.login-form #password_show").click(function(){ - var typ = $("form.login-form #user_password").attr('type'); - $("form.login-form #user_password").attr('type', (typ === 'password' ? 'text' : 'password')); - }); - - // Run the validations in case the page was refreshed - toggleFormElementError($("form.login-form #user_email"), - validateEmail($("form.login-form #user_email").val().trim())); - toggleFormElementError($("form.login-form #user_password"), - validatePassword($("form.login-form #user_password").val().trim())); - - // Make sure the show password checkbox is unchecked on load - $("form.login-form #password_show").attr("checked", false); - - // Pressing enter should submit the login form NOT the omniauth buttons! - $("form.login-form").keypress(function(e){ - if(e.keyCode == 13){ - $("#sign-in-button").click(); - return false; - } - }); - - // Display the submit button only if there is a valid email and password - function toggleLogInSubmit(){ - var disabled = (validateEmail($("form.login-form #user_email").val()) != '' || - validatePassword($("form.login-form #user_password").val()) != ''); - $("form.login-form #sign-in-button").attr('aria-disabled', disabled); - } - } -}); - diff --git a/lib/assets/javascripts/views/shared/register_form.js b/lib/assets/javascripts/views/shared/register_form.js deleted file mode 100644 index f3e9824..0000000 --- a/lib/assets/javascripts/views/shared/register_form.js +++ /dev/null @@ -1,79 +0,0 @@ -$(document).ready(function(){ - if($("form.register-form").length > 0){ - // If the hidden valid-form field is set to true then enable the submit button - $("form.register-form #valid-form").change(function(){ - $(this).siblings(".form-submit").attr('aria-disabled', $(this).val() != "true"); - }); - - // See if we should enable the submit button when a required input changes - $("form.register-form input[class*='required'], #other-org-name, #user_org_name").on('change keyup', function(){ - toggleRegisterSubmit(); - }); - - // Run the input validations when the focus changes - $("form.register-form #user_email, form.register-form #user_recovery_email").on('blur change', function(){ - var msg = validateEmail($(this).val().trim()); - // If the standard email validation was successful validate that they do not match - toggleFormElementError(this, (msg != '' ? msg : validateEmailsDoNotMatch())); - }); - $("form.register-form #user_password").on('blur change', function(){ - toggleFormElementError(this, validatePassword($(this).val().trim())); - }); - - // Toggle the password field so that its visible/masked - $("form.register-form #password_show").click(function(){ - var typ = $("form.register-form #user_password").attr('type'); - $("form.register-form #user_password").attr('type', (typ === 'password' ? 'text' : 'password')); - }); - - $('#user_org_name').on("change", function(e) { - e.preventDefault(); - var selected_org = $(this).val(); - var other_orgs = $("#other-org-name").attr("data-orgs").split(","); - var index = $.inArray(selected_org, other_orgs); - if (index > -1) { - $("#other-org-name").show(); - $("#user_other_organisation").focus(); - } - else { - $("#other-org-name").hide(); - $("#user_other_organisation").val(""); - } - }); - $("#other-org-link > a").click(function(e){ - e.preventDefault(); - var other_org = $("#other-org-name").attr("data-orgs").split(","); - $("#user_org_name").val(""); - $("#user_org_id").val(""); - $("#user_org_name").change(); - }); - - // Run the validations in case the page was refreshed - toggleFormElementError($("form.register-form #user_email"), - validateEmail($("form.register-form #user_email").val().trim())); - toggleFormElementError($("form.register-form #user_recovery_email"), - validateEmail($("form.register-form #user_recovery_email").val().trim())); - toggleFormElementError($("form.register-form #user_password"), - validatePassword($("form.register-form #user_password").val().trim())); - - // Make sure the show password checkbox is unchecked on load - $("form.register-form #password_show").attr("checked", false); - - function validateEmailsDoNotMatch(){ - var email = $("form.register-form #user_email").val().trim(); - var recovery = $("form.register-form #user_recovery_email").val().trim(); - return (email === recovery ? (email != '' ? __('Emails must be different') : '') : ''); - } - - function toggleRegisterSubmit(){ - var disabled = ($("form.register-form #user_firstname").val().trim().length <= 0 || - $("form.register-form #user_surname").val().trim().length <= 0 || - validateEmail($("form.register-form #user_email").val()) != '' || - validateEmail($("form.register-form #user_recovery_email").val()) != '' || - !$("form.register-form #user_accept_terms").prop('checked') || - $("form.register-form #user_email").val() === $("form.register-form #user_recovery_email").val() || - ($("form.register-form #user_org_name").val().trim().length <=0 && $("form.register-form #user_other_organisation").val().trim().length <= 0)); - $("form.register-form #register-button").attr('aria-disabled', disabled); - } - } -}); diff --git a/lib/assets/javascripts/views/shared/sign_in_form.js b/lib/assets/javascripts/views/shared/sign_in_form.js new file mode 100644 index 0000000..c906dd3 --- /dev/null +++ b/lib/assets/javascripts/views/shared/sign_in_form.js @@ -0,0 +1,7 @@ +import ariatiseForm from '../../utils/ariatiseForm'; +import togglisePasswords from '../../utils/passwordHelper'; + +$(() => { + ariatiseForm({ selector: '#sign_in_form' }); + togglisePasswords({ selector: '#sign_in_form' }); +}); diff --git a/lib/assets/karma.conf.js b/lib/assets/karma.conf.js index 6e5f5d4..a48ab6e 100644 --- a/lib/assets/karma.conf.js +++ b/lib/assets/karma.conf.js @@ -7,15 +7,15 @@ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', - // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['jasmine', 'jquery-3.2.1'], + frameworks: ['fixture', 'jquery-3.2.1', 'jasmine-jquery', 'jasmine'], // list of files / patterns to load in the browser files: [ './node_modules/phantomjs-polyfill/bind-polyfill.js', './javascripts/**/*Spec.js', + 'javascripts/spec/fixtures/**/*', ], @@ -28,6 +28,8 @@ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { './javascripts/**/*Spec.js': ['webpack'], + '**/*.html': ['html2js'], + '**/*.json': ['json_fixtures'], }, webpack: webpackConfig, @@ -67,5 +69,9 @@ // Concurrency level // how many browser should be started simultaneous concurrency: Infinity, + + jsonFixturesPreprocessor: { + variableName: '__json__', + }, }); }; diff --git a/lib/assets/package-lock.json b/lib/assets/package-lock.json index baa18ec..8c8ace3 100644 --- a/lib/assets/package-lock.json +++ b/lib/assets/package-lock.json @@ -141,6 +141,12 @@ "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", "dev": true }, + "archy": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/archy/-/archy-0.0.2.tgz", + "integrity": "sha1-kQ9Dv2YUH8M1VkWXq8GJ30Sz014=", + "dev": true + }, "are-we-there-yet": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", @@ -175,12 +181,30 @@ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, "array-slice": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", @@ -922,12 +946,57 @@ "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=", "dev": true }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "chainsaw": "0.1.0" + } + }, "binary-extensions": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", "dev": true }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "blob": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", @@ -1004,6 +1073,806 @@ "resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.3.7.tgz", "integrity": "sha1-ZZbHq0D2Y3OTMjqwvIDQZPxjBJg=" }, + "bower": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.0.tgz", + "integrity": "sha1-Vdvr7wrZFVOC2enT5JfBNyNFtEo=", + "dev": true + }, + "bower-config": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-0.5.2.tgz", + "integrity": "sha1-H30uiZ6ZtwwpphPnDUxkWQQUsi4=", + "dev": true, + "requires": { + "graceful-fs": "2.0.3", + "mout": "0.9.1", + "optimist": "0.6.1", + "osenv": "0.0.3" + }, + "dependencies": { + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "osenv": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz", + "integrity": "sha1-zWrY3bKQkVrZ4idlV2Al1BHynLY=", + "dev": true + } + } + }, + "bower-endpoint-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz", + "integrity": "sha1-ALVlrb+rby01rd3pd+l5Yqy8s/Y=", + "dev": true + }, + "bower-installer": { + "version": "git://github.com/bessdsv/bower-installer.git#7f9cece1e6fada50f44dc0851e1d85815cd1b4a7", + "dev": true, + "requires": { + "async": "0.2.10", + "bower": "1.3.12", + "colors": "0.6.2", + "glob": "3.2.11", + "lodash": "0.9.2", + "mkdirp": "0.3.5", + "node-fs": "0.1.7", + "nopt": "2.1.2" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true, + "optional": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true, + "optional": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "bower": { + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.3.12.tgz", + "integrity": "sha1-N94O2zkEuvkK7hM4Sho3mgXuIUw=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "archy": "0.0.2", + "bower-config": "0.5.2", + "bower-endpoint-parser": "0.2.2", + "bower-json": "0.4.0", + "bower-logger": "0.2.2", + "bower-registry-client": "0.2.4", + "cardinal": "0.4.0", + "chalk": "0.5.0", + "chmodr": "0.1.0", + "decompress-zip": "0.0.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "glob": "4.0.6", + "graceful-fs": "3.0.11", + "handlebars": "2.0.0", + "inquirer": "0.7.1", + "insight": "0.4.3", + "is-root": "1.0.0", + "junk": "1.0.3", + "lockfile": "1.0.3", + "lru-cache": "2.5.2", + "mkdirp": "0.5.0", + "mout": "0.9.1", + "nopt": "3.0.6", + "opn": "1.0.2", + "osenv": "0.1.0", + "p-throttler": "0.1.0", + "promptly": "0.2.0", + "q": "1.0.1", + "request": "2.42.0", + "request-progress": "0.3.0", + "retry": "0.6.0", + "rimraf": "2.2.8", + "semver": "2.3.2", + "shell-quote": "1.4.3", + "stringify-object": "1.0.1", + "tar-fs": "0.5.2", + "tmp": "0.0.23", + "update-notifier": "0.2.0", + "which": "1.0.9" + }, + "dependencies": { + "glob": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "integrity": "sha1-aVxQvdTi+1xdNwsJHziNNwfikac=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "inherits": "2.0.3", + "minimatch": "1.0.0", + "once": "1.4.0" + } + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + } + } + }, + "caseless": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", + "integrity": "sha1-gWfBq4OX+1u5X5bSjlqBxQ8kesQ=", + "dev": true + }, + "chalk": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.0.tgz", + "integrity": "sha1-N138y8IcCmCothvFt489wqVcIS8=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "optional": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true, + "optional": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true, + "optional": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.5.2", + "sigmund": "1.0.1" + } + } + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": true, + "optional": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "inquirer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.7.1.tgz", + "integrity": "sha1-uKzxQBZb1YGGLtEZj7bSZDAJH6w=", + "dev": true, + "requires": { + "chalk": "0.5.0", + "cli-color": "0.3.3", + "figures": "1.7.0", + "lodash": "2.4.2", + "mute-stream": "0.0.4", + "readline2": "0.1.1", + "rx": "2.5.3", + "through": "2.3.8" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + } + } + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "lru-cache": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz", + "integrity": "sha1-H92tk4quEmPOE4aAvhs/WRwKtBw=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true, + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "minimatch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=", + "dev": true, + "requires": { + "lru-cache": "2.5.2", + "sigmund": "1.0.1" + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "oauth-sign": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", + "integrity": "sha1-8ilW8x6nFRqCHl8vsywRPK2Ln2k=", + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.0.tgz", + "integrity": "sha1-YWaBIe7FhJVQMLn0cLHSMJUEv8s=", + "dev": true + }, + "q": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "integrity": "sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=", + "dev": true + }, + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=", + "dev": true + }, + "request": { + "version": "2.42.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.42.0.tgz", + "integrity": "sha1-VyvQFIk4VkBArHqxSLlkI6BjMEo=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.6.0", + "forever-agent": "0.5.2", + "form-data": "0.1.4", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.4.0", + "qs": "1.2.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.4.3" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "semver": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=", + "dev": true + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "optional": true, + "requires": { + "hoek": "0.9.1" + } + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "tmp": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.23.tgz", + "integrity": "sha1-3odKpel0qF8KMs39vXRmPLO9nHQ=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + } + } + }, + "bower-json": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/bower-json/-/bower-json-0.4.0.tgz", + "integrity": "sha1-qZw8z0Fu8FkO0N7SUsdg8cbZN2Y=", + "dev": true, + "requires": { + "deep-extend": "0.2.11", + "graceful-fs": "2.0.3", + "intersect": "0.0.3" + }, + "dependencies": { + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + } + } + }, + "bower-logger": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/bower-logger/-/bower-logger-0.2.2.tgz", + "integrity": "sha1-Ob4H6Xmy/I4DqUY0IF7ZQiNz04E=", + "dev": true + }, + "bower-registry-client": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/bower-registry-client/-/bower-registry-client-0.2.4.tgz", + "integrity": "sha1-Jp/H6Ji2J/uTnRFEpZMlTX+77rw=", + "dev": true, + "requires": { + "async": "0.2.10", + "bower-config": "0.5.2", + "graceful-fs": "2.0.3", + "lru-cache": "2.3.1", + "mkdirp": "0.3.5", + "request": "2.51.0", + "request-replay": "0.2.0", + "rimraf": "2.2.8" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "caseless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "dev": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime-types": "2.0.14" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "mime-types": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "dev": true, + "requires": { + "mime-db": "1.12.0" + } + } + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "lru-cache": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.3.1.tgz", + "integrity": "sha1-s632s9hW6VTiw5DmzvIggSRaU9Y=", + "dev": true + }, + "mime-db": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", + "dev": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "oauth-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "request": { + "version": "2.51.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.51.0.tgz", + "integrity": "sha1-NdALvswBLlX5B7G9ng29V3v+8m4=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.8.0", + "combined-stream": "0.0.7", + "forever-agent": "0.5.2", + "form-data": "0.2.0", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.5.0", + "qs": "2.3.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.4.3" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + } + } + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -1127,6 +1996,12 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1200,6 +2075,15 @@ "integrity": "sha1-J931/szdM4yZpiyXiMJpT5n2ftc=", "dev": true }, + "cardinal": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.0.tgz", + "integrity": "sha1-fRCq+yCDe94EPEXkOgyMKM2q5F4=", + "dev": true, + "requires": { + "redeyed": "0.4.4" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1224,6 +2108,15 @@ } } }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": "0.3.9" + } + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1237,6 +2130,12 @@ "supports-color": "2.0.0" } }, + "chmodr": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chmodr/-/chmodr-0.1.0.tgz", + "integrity": "sha1-4JIVodUVQtsqJXaWl2W89hJVg+s=", + "dev": true + }, "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", @@ -1296,6 +2195,29 @@ "chalk": "1.1.3" } }, + "cli-color": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.3.tgz", + "integrity": "sha1-EtW90Vj/igsNtAEZiRPAPfBp9vU=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.29", + "memoizee": "0.3.10", + "timers-ext": "0.1.2" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "0.10.29" + } + } + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1494,6 +2416,55 @@ "typedarray": "0.0.6" } }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "dev": true, + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-0.3.2.tgz", + "integrity": "sha1-JeTBbDdoq/dcWmW8YXYfSVBVtFk=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "object-assign": "2.1.1", + "osenv": "0.1.4", + "user-home": "1.1.1", + "uuid": "2.0.3", + "xdg-basedir": "1.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, "connect": { "version": "3.6.3", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.3.tgz", @@ -1775,6 +2746,12 @@ "source-map": "0.5.7" } }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1837,6 +2814,77 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decompress-zip": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.0.8.tgz", + "integrity": "sha1-SiZbIseyCdeyT6ZvKy37ztWQRPM=", + "dev": true, + "requires": { + "binary": "0.3.0", + "graceful-fs": "3.0.11", + "mkpath": "0.1.0", + "nopt": "2.2.1", + "q": "1.0.1", + "readable-stream": "1.1.14", + "touch": "0.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "q": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "integrity": "sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "deep-extend": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz", + "integrity": "sha1-eha6aXKRMjQFBhcElLyD9wdv4I8=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1995,6 +3043,26 @@ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", "dev": true }, + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, "engine.io": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", @@ -3629,14 +4697,6 @@ } } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "string-width": { "version": "1.0.2", "bundled": true, @@ -3647,6 +4707,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -3771,6 +4839,17 @@ "rimraf": "2.6.1" } }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, "function-bind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", @@ -3994,12 +5073,85 @@ } } }, + "got": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/got/-/got-0.3.0.tgz", + "integrity": "sha1-iI7GbKS8c1qwidvpWUltD3lIVJM=", + "dev": true, + "requires": { + "object-assign": "0.3.1" + }, + "dependencies": { + "object-assign": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-0.3.1.tgz", + "integrity": "sha1-Bg4qKifXwNd+x3t48Rqkf9iACNI=", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, + "handlebars": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-2.0.0.tgz", + "integrity": "sha1-bp1/hRSjRn+l6fgswVjs/B1ax28=", + "dev": true, + "requires": { + "optimist": "0.3.7", + "uglify-js": "2.3.6" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true, + "optional": true + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "0.0.3" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "uglify-js": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", + "integrity": "sha1-+gmEdwtCi3qbKoBY9GNV0U/vIRo=", + "dev": true, + "optional": true, + "requires": { + "async": "0.2.10", + "optimist": "0.3.7", + "source-map": "0.1.43" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, "har-schema": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", @@ -4320,6 +5472,12 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, "inquirer": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.2.tgz", @@ -4394,12 +5552,134 @@ } } }, + "insight": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/insight/-/insight-0.4.3.tgz", + "integrity": "sha1-dtZTxcDYBIsDzbpjhaaUj3RhSvA=", + "dev": true, + "requires": { + "async": "0.9.2", + "chalk": "0.5.1", + "configstore": "0.3.2", + "inquirer": "0.6.0", + "lodash.debounce": "2.4.1", + "object-assign": "1.0.0", + "os-name": "1.0.3", + "request": "2.81.0", + "tough-cookie": "0.12.1" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "inquirer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.6.0.tgz", + "integrity": "sha1-YU17s+SPnmqAKOlKDDjyPvKYI9M=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "cli-color": "0.3.3", + "lodash": "2.4.2", + "mute-stream": "0.0.4", + "readline2": "0.1.1", + "rx": "2.5.3", + "through": "2.3.8" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "object-assign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz", + "integrity": "sha1-5l3Idm07R7S4MHRlyDEdoDCwcKY=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "tough-cookie": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "integrity": "sha1-giDH4hq9WxPZaAQlS9WoHr8sfWI=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + } + } + }, "interpret": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", "dev": true }, + "intersect": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/intersect/-/intersect-0.0.3.tgz", + "integrity": "sha1-waSl5erG7eSvdQTMB+Ctp7yfSSA=", + "dev": true + }, "invariant": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", @@ -4577,6 +5857,12 @@ "tryit": "1.0.3" } }, + "is-root": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz", + "integrity": "sha1-B7bCM7w5TNnQK6FclmvWZg1jQtU=", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -4787,6 +6073,12 @@ } } }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", + "dev": true + }, "karma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.0.tgz", @@ -4860,12 +6152,46 @@ "which": "1.3.0" } }, + "karma-fixture": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/karma-fixture/-/karma-fixture-0.2.6.tgz", + "integrity": "sha1-lxzqjCFtc/BwQ5ZMtz8Q4IMAGO8=", + "dev": true + }, + "karma-html2js-preprocessor": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-html2js-preprocessor/-/karma-html2js-preprocessor-1.1.0.tgz", + "integrity": "sha1-/Ant8Eu+K7bu6boZaPgmtziAIL0=", + "dev": true + }, "karma-jasmine": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.0.tgz", "integrity": "sha1-IuTAa/mhguUpTR9wXjczgRuBCs8=", "dev": true }, + "karma-jasmine-jquery": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/karma-jasmine-jquery/-/karma-jasmine-jquery-0.1.1.tgz", + "integrity": "sha1-icG3VP6kElsfiTghOSwRuc5ddFY=", + "dev": true, + "requires": { + "bower": "1.8.0", + "bower-installer": "git://github.com/bessdsv/bower-installer.git#7f9cece1e6fada50f44dc0851e1d85815cd1b4a7" + } + }, + "karma-jquery": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/karma-jquery/-/karma-jquery-0.2.2.tgz", + "integrity": "sha1-a+6TRU2LCWvMeBVXCoHnP93bXW8=", + "dev": true + }, + "karma-json-fixtures-preprocessor": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/karma-json-fixtures-preprocessor/-/karma-json-fixtures-preprocessor-0.0.6.tgz", + "integrity": "sha1-T3ii6800OH+OVaur/2NGVRZMTHY=", + "dev": true + }, "karma-webpack": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.4.tgz", @@ -4932,6 +6258,15 @@ "graceful-fs": "4.1.11" } }, + "latest-version": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-0.2.0.tgz", + "integrity": "sha1-ra+JjV8iOA0/nEU4bv3/ChtbdQE=", + "dev": true, + "requires": { + "package-json": "0.2.0" + } + }, "lazy-cache": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", @@ -5047,12 +6382,30 @@ "path-exists": "3.0.0" } }, + "lockfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.3.tgz", + "integrity": "sha1-Jjj8OaAzHpysGgS3F5mTHJxQ33k=", + "dev": true + }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", @@ -5077,6 +6430,32 @@ "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", "dev": true }, + "lodash.debounce": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-2.4.1.tgz", + "integrity": "sha1-2M6tJG7EuSbouFZ4/Dlr/rqMxvw=", + "dev": true, + "requires": { + "lodash.isfunction": "2.4.1", + "lodash.isobject": "2.4.1", + "lodash.now": "2.4.1" + } + }, + "lodash.isfunction": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", + "integrity": "sha1-LP1XXHPkmKtX4xm3f6Aq3vE6lNE=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5089,6 +6468,15 @@ "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=", "dev": true }, + "lodash.now": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.now/-/lodash.now-2.4.1.tgz", + "integrity": "sha1-aHIVZQBSUYX6+WeFu3/n/hW1YsY=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1" + } + }, "lodash.tail": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", @@ -5178,6 +6566,15 @@ "yallist": "2.1.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "0.10.29" + } + }, "macaddress": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", @@ -5242,6 +6639,65 @@ "mimic-fn": "1.1.0" } }, + "memoizee": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", + "integrity": "sha1-TsoNiu057J0Bf0xcLy9kMvQuXI8=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.29", + "es6-weak-map": "0.1.4", + "event-emitter": "0.3.5", + "lru-queue": "0.1.0", + "next-tick": "0.2.2", + "timers-ext": "0.1.2" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "0.10.29" + } + }, + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.29", + "es6-symbol": "2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.29" + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.29", + "es6-iterator": "0.1.3", + "es6-symbol": "2.0.1" + } + } + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -5480,6 +6936,18 @@ "minimist": "0.0.8" } }, + "mkpath": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", + "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=", + "dev": true + }, + "mout": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.9.1.tgz", + "integrity": "sha1-hPDz/WrMcxf2PeKv/cwM7gCbBHc=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5498,6 +6966,12 @@ "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", "dev": true }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5510,6 +6984,12 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, + "next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=", + "dev": true + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -5519,6 +6999,12 @@ "minimatch": "3.0.4" } }, + "node-fs": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", + "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=", + "dev": true + }, "node-gyp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", @@ -5710,6 +7196,40 @@ "path-key": "2.0.1" } }, + "npmconf": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/npmconf/-/npmconf-2.1.2.tgz", + "integrity": "sha1-ZmBqSnNvHnegWaoHGnnJSreBhTo=", + "dev": true, + "requires": { + "config-chain": "1.1.11", + "inherits": "2.0.3", + "ini": "1.3.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.3.3", + "osenv": "0.1.4", + "semver": "4.3.6", + "uid-number": "0.0.5" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + } + } + }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -5812,6 +7332,12 @@ "mimic-fn": "1.1.0" } }, + "opn": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-1.0.2.tgz", + "integrity": "sha1-uQlkM0bQChq8l3qLlvPOPFPVz18=", + "dev": true + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -5871,6 +7397,16 @@ "lcid": "1.0.0" } }, + "os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "dev": true, + "requires": { + "osx-release": "1.1.0", + "win-release": "1.1.1" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -5887,6 +7423,23 @@ "os-tmpdir": "1.0.2" } }, + "osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -5908,6 +7461,33 @@ "p-limit": "1.1.0" } }, + "p-throttler": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/p-throttler/-/p-throttler-0.1.0.tgz", + "integrity": "sha1-GxaQeULDM+bx3eq8s0eSBLjEF8Q=", + "dev": true, + "requires": { + "q": "0.9.7" + }, + "dependencies": { + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=", + "dev": true + } + } + }, + "package-json": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-0.2.0.tgz", + "integrity": "sha1-Axbhd7jrFJmF009wa0pVQ7J0vsU=", + "dev": true, + "requires": { + "got": "0.3.0", + "registry-url": "0.1.1" + } + }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -6683,6 +8263,21 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, + "promptly": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-0.2.0.tgz", + "integrity": "sha1-c+8gD6gynV06jfQXmJULhkbKRtk=", + "dev": true, + "requires": { + "read": "1.0.7" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "prr": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", @@ -6708,6 +8303,24 @@ "randombytes": "2.0.5" } }, + "pump": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/pump/-/pump-0.3.5.tgz", + "integrity": "sha1-rl/4wfk+2HrcZTCpdWWxJvWFRUs=", + "dev": true, + "requires": { + "end-of-stream": "1.0.0", + "once": "1.2.0" + }, + "dependencies": { + "once": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.2.0.tgz", + "integrity": "sha1-3hkFxjavh0qPuoYtmqvd0fkgRhw=", + "dev": true + } + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -6829,6 +8442,15 @@ } } }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "0.0.7" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -6877,6 +8499,39 @@ "set-immediate-shim": "1.0.1" } }, + "readline2": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", + "dev": true, + "requires": { + "mute-stream": "0.0.4", + "strip-ansi": "2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true, + "requires": { + "ansi-regex": "1.1.1" + } + } + } + }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -6887,6 +8542,23 @@ "strip-indent": "1.0.1" } }, + "redeyed": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz", + "integrity": "sha1-N+mQpvKyGyoRwuakj9QTVpjLqX8=", + "dev": true, + "requires": { + "esprima": "1.0.4" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + } + } + }, "reduce-css-calc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", @@ -6967,6 +8639,15 @@ "regjsparser": "0.1.5" } }, + "registry-url": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-0.1.1.tgz", + "integrity": "sha1-FzlCe4GxELMCSCocfNcn/8yC1b4=", + "dev": true, + "requires": { + "npmconf": "2.1.2" + } + }, "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", @@ -7047,6 +8728,24 @@ "uuid": "3.1.0" } }, + "request-progress": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.0.tgz", + "integrity": "sha1-vfIGK/wZfF1JJQDUTLOv94ZbSS4=", + "dev": true, + "requires": { + "throttleit": "0.0.2" + } + }, + "request-replay": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/request-replay/-/request-replay-0.2.0.tgz", + "integrity": "sha1-m2k6XRGLOfXFlurV7ZGiZEQFf2A=", + "dev": true, + "requires": { + "retry": "0.6.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7100,6 +8799,12 @@ "signal-exit": "3.0.2" } }, + "retry": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.0.tgz", + "integrity": "sha1-HAEHEyeab9Ho3vKK8MP/GHHKpTc=", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -7153,6 +8858,12 @@ "is-promise": "2.1.0" } }, + "rx": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", + "dev": true + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -7265,6 +8976,23 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "semver-diff": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-0.1.0.tgz", + "integrity": "sha1-T2BXyj66I8xIS1H2Sq+IsTGjhV0=", + "dev": true, + "requires": { + "semver": "2.3.2" + }, + "dependencies": { + "semver": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=", + "dev": true + } + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -7336,6 +9064,24 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shell-quote": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.4.3.tgz", + "integrity": "sha1-lSxE4LHtkBPvU5WBecxkPod3Rms=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -7630,13 +9376,30 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "string-length": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-0.1.2.tgz", + "integrity": "sha1-qwS7M4Z+50vu1/uJu38InTkngPI=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "strip-ansi": "0.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.1.0.tgz", + "integrity": "sha1-Vcpg22kAhXxCOukpeYACb5Qe2QM=", + "dev": true + }, + "strip-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.2.2.tgz", + "integrity": "sha1-hU0pDJgVJfyMOXqRCwJa4tVP/Ag=", + "dev": true, + "requires": { + "ansi-regex": "0.1.0" + } + } } }, "string-width": { @@ -7666,6 +9429,21 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringify-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-1.0.1.tgz", + "integrity": "sha1-htNefb+86apFY31+zdeEfhWduKI=", + "dev": true + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -7790,12 +9568,67 @@ "inherits": "2.0.3" } }, + "tar-fs": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-0.5.2.tgz", + "integrity": "sha1-D1lCS+fu7kUjIxbjAvZtP26m2z4=", + "dev": true, + "requires": { + "mkdirp": "0.5.1", + "pump": "0.3.5", + "tar-stream": "0.4.7" + } + }, + "tar-stream": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.4.7.tgz", + "integrity": "sha1-Hx0s6evHtCdlJDyg6PG3v9oKrc0=", + "dev": true, + "requires": { + "bl": "0.9.5", + "end-of-stream": "1.0.0", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -7825,6 +9658,24 @@ "setimmediate": "1.0.5" } }, + "timers-ext": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", + "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", + "dev": true, + "requires": { + "es5-ext": "0.10.29", + "next-tick": "1.0.0" + }, + "dependencies": { + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + } + } + }, "tinymce": { "version": "4.6.5", "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.6.5.tgz", @@ -7857,6 +9708,26 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, + "touch": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.2.tgz", + "integrity": "sha1-plp3d5Xly74SmUmb3EIoH/shtfQ=", + "dev": true, + "requires": { + "nopt": "1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + } + } + }, "tough-cookie": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", @@ -7866,6 +9737,12 @@ "punycode": "1.4.1" } }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -7997,6 +9874,12 @@ "webpack-sources": "1.0.1" } }, + "uid-number": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.5.tgz", + "integrity": "sha1-Wj2yPvXb1VuB/ODsmirG/M3ruB4=", + "dev": true + }, "ultron": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", @@ -8030,6 +9913,70 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "update-notifier": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.2.0.tgz", + "integrity": "sha1-oBDJKK3PAgkLjgzn/vb7Cnysw0o=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "configstore": "0.3.2", + "latest-version": "0.2.0", + "semver-diff": "0.1.0", + "string-length": "0.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + } + } + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -8048,6 +9995,12 @@ } } }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "useragent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", @@ -8343,6 +10296,15 @@ } } }, + "win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -8418,6 +10380,15 @@ "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", "dev": true }, + "xdg-basedir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-1.0.1.tgz", + "integrity": "sha1-FP+PY6T9vLBdW27qIrNvMDO58E4=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, "xmlhttprequest-ssl": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", diff --git a/lib/assets/package.json b/lib/assets/package.json index 9324098..2d0a2b5 100644 --- a/lib/assets/package.json +++ b/lib/assets/package.json @@ -45,8 +45,12 @@ "jasmine-core": "^2.7.0", "karma": "^1.7.0", "karma-chrome-launcher": "^2.2.0", + "karma-fixture": "^0.2.6", + "karma-html2js-preprocessor": "^1.1.0", "karma-jasmine": "^1.1.0", + "karma-jasmine-jquery": "^0.1.1", "karma-jquery": "^0.2.2", + "karma-json-fixtures-preprocessor": "0.0.6", "karma-webpack": "^2.0.4", "node-sass": "^4.5.3", "sass-loader": "^6.0.6", diff --git a/lib/tasks/bugfix.rake b/lib/tasks/bugfix.rake new file mode 100644 index 0000000..5fc6bf1 --- /dev/null +++ b/lib/tasks/bugfix.rake @@ -0,0 +1,49 @@ +namespace :bugfix do + + desc "Bug fixes for version v0.3.3" + task v0_3_3: :environment do + Rake::Task['bugfix:fix_question_formats'].execute + Rake::Task['bugfix:add_missing_token_permission_types'].execute + end + + desc "Add the missing formattype to the question_formats table" + task fix_question_formats: :environment do + QuestionFormat.all.each do |qf| + case qf.title.downcase + when 'text area' + qf.formattype = :textarea + when 'text field' + qf.formattype = :textfield + when 'radio buttons' + qf.formattype = :radiobuttons + when 'check box' + qf.formattype = :checkbox + when 'dropdown' + qf.formattype = :dropdown + when 'multi select box' + qf.formattype = :multiselectbox + when 'date' + qf.formattype = :date + end + + qf.save! + end + + if QuestionFormat.find_by(formattype: :date).nil? + QuestionFormat.create!({title: "Date", option_based: true, formattype: 6}) + end + end + + desc "Add the missing token_permission_types" + task add_missing_token_permission_types: :environment do + if TokenPermissionType.find_by(token_type: 'templates').nil? + TokenPermissionType.create!({token_type: 'templates', + text_description: 'allows a user access to the templates api endpoint'}) + end + if TokenPermissionType.find_by(token_type: 'statistics').nil? + TokenPermissionType.create!({token_type: 'statistics', + text_description: 'allows a user access to the statistics api endpoint'}) + end + end + +end \ No newline at end of file diff --git a/test/functional/roles_controller_test.rb b/test/functional/roles_controller_test.rb index 6a61b79..7d2f9f0 100644 --- a/test/functional/roles_controller_test.rb +++ b/test/functional/roles_controller_test.rb @@ -7,10 +7,10 @@ setup do scaffold_plan scaffold_org_admin(@plan.template.org) - + # This should NOT be unnecessary! Owner should have full access @plan.roles << Role.create(user: @user, plan: @plan, access: 15) - + end # TODO: Cleanup routes for this one. The controller currently only responds to create, update, destroy @@ -21,19 +21,19 @@ # role PATCH /roles/:id roles#update # PUT /roles/:id roles#update # DELETE /roles/:id roles#destroy - + # POST /roles (roles_path) # ---------------------------------------------------------- test "create a new role" do params = {plan_id: @plan.id, access_level: 4} - + # Should redirect user to the root path if they are not logged in! post roles_path, {role: params} assert_unauthorized_redirect_to_root_path sign_in @user - + # Known user @invitee = User.where.not(id: [@plan.owner.id, @user.id]).first post roles_path, {user: @invitee.email, role: params} @@ -50,15 +50,15 @@ assert_redirected_to share_plan_path(@plan) assert_equal @invitee.id, Role.last.user_id, "expected no record to have been created!" assert assigns(:role) - + # Unknown user post roles_path, {user: 'unknown_user@org.org', role: params} - assert_equal _('Invitation to unknown_user@org.org issued successfully.'), flash[:notice] + assert_equal _('Invitation to unknown_user@org.org issued successfully. \nPlan shared with unknown_user@org.org.'), flash[:notice] assert_response :redirect assert_redirected_to share_plan_path(@plan) assert_equal User.find_by(email:'unknown_user@org.org').id, Role.last.user_id, "expected the record to have been created!" assert assigns(:role) - + # Invite owner @invitee = User.find_by(id: @plan.owner.id) post roles_path, {user: @invitee.email, role: params} @@ -67,32 +67,32 @@ assert_redirected_to share_plan_path(@plan) assert_not_equal @invitee.id, Role.last.user_id, "expected no record to have been created!" assert assigns(:role) - + # Missing email post roles_path, {role: {plan_id: @plan.id, access_level: 4}} assert_equal _('Please enter an email address'), flash[:notice] assert_response :redirect assert_redirected_to share_plan_path(@plan) assert assigns(:role) - end - + end + # PUT /role/:id (role_path) # ---------------------------------------------------------- test "update the role" do @invitee = User.last role = Role.create(user: @invitee, plan: @plan, access: 1) params = {access_level: 2} - + # Should redirect user to the root path if they are not logged in! put role_path(role), {role: params} assert_unauthorized_redirect_to_root_path - + sign_in @user # Valid save put role_path(role, format: :json), {role: params} assert_equal 13, role.reload.access, "expected the record to have been updated" - + # TODO: Role should require a user, plan and an access level :/ # Invalid save # put role_path(role), {role: {user: nil}} @@ -101,26 +101,26 @@ # assert_redirected_to share_plan_path(@plan) # assert assigns(:role) end - + # DELETE /role/:id (role_path) # ---------------------------------------------------------- test "delete the section" do @invitee = User.last role = Role.create(user: @invitee, plan: @plan, access: 1) - + # Should redirect user to the root path if they are not logged in! delete role_path(role) assert_unauthorized_redirect_to_root_path - + sign_in @user - + delete role_path(role) assert_equal _('Access removed'), flash[:notice] assert_response :redirect assert_redirected_to share_plan_path(@plan) - assert_raise ActiveRecord::RecordNotFound do + assert_raise ActiveRecord::RecordNotFound do Role.find(role.id).nil? end end - + end