diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index 6f671f8f51..f2cfe41c25 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -522,15 +522,15 @@ class ViewsTestCase(ModuleStoreTestCase):
effort = "I'm done, okay? You just give me my money, and you and I, we're done."
data = {
'username': username,
- 'course_id': course,
- 'legal_name': legal_name,
+ 'course': course,
+ 'name': legal_name,
'email': self.user.email,
'country': country,
'income': income,
'reason_for_applying': reason_for_applying,
'goals': goals,
'effort': effort,
- 'marketing_permission': False,
+ 'mktg-permission': False,
}
response = self._submit_financial_assistance_form(data)
self.assertEqual(response.status_code, 204)
@@ -560,15 +560,15 @@ class ViewsTestCase(ModuleStoreTestCase):
def test_zendesk_submission_failed(self, _mock_record_feedback):
response = self._submit_financial_assistance_form({
'username': self.user.username,
- 'course_id': '',
- 'legal_name': '',
+ 'course': '',
+ 'name': '',
'email': '',
'country': '',
'income': '',
'reason_for_applying': '',
'goals': '',
'effort': '',
- 'marketing_permission': False,
+ 'mktg-permission': False,
})
self.assertEqual(response.status_code, 500)
diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py
index 6c2ecf1ce3..72f15070c5 100644
--- a/lms/djangoapps/courseware/views.py
+++ b/lms/djangoapps/courseware/views.py
@@ -1460,15 +1460,15 @@ def financial_assistance_request(request):
if request.user.username != username:
return HttpResponseForbidden()
- course_id = data['course_id']
- legal_name = data['legal_name']
+ course_id = data['course']
+ legal_name = data['name']
email = data['email']
country = data['country']
income = data['income']
reason_for_applying = data['reason_for_applying']
goals = data['goals']
effort = data['effort']
- marketing_permission = data['marketing_permission']
+ marketing_permission = data['mktg-permission']
ip_address = get_ip(request)
except ValueError:
# Thrown if JSON parsing fails
diff --git a/lms/static/js/financial-assistance/financial_assistance_form_factory.js b/lms/static/js/financial-assistance/financial_assistance_form_factory.js
new file mode 100644
index 0000000000..0cc77a7617
--- /dev/null
+++ b/lms/static/js/financial-assistance/financial_assistance_form_factory.js
@@ -0,0 +1,17 @@
+;(function (define) {
+ 'use strict';
+
+ define([
+ 'js/financial-assistance/views/financial_assistance_form_view'
+ ],
+ function (FinancialAssistanceFormView) {
+ return function (options) {
+ var formView = new FinancialAssistanceFormView({
+ el: '.financial-assistance-wrapper',
+ context: options
+ });
+
+ return formView;
+ };
+ });
+}).call(this, define || RequireJS.define);
diff --git a/lms/static/js/financial-assistance/models/financial_assistance_model.js b/lms/static/js/financial-assistance/models/financial_assistance_model.js
new file mode 100644
index 0000000000..3039059158
--- /dev/null
+++ b/lms/static/js/financial-assistance/models/financial_assistance_model.js
@@ -0,0 +1,14 @@
+/**
+ * Model for Financial Assistance.
+ */
+(function (define) {
+ 'use strict';
+ define(['backbone'], function (Backbone) {
+ var FinancialAssistance = Backbone.Model.extend({
+ initialize: function(options) {
+ this.url = options.url;
+ }
+ });
+ return FinancialAssistance;
+ });
+}).call(this, define || RequireJS.define);
diff --git a/lms/static/js/financial-assistance/templates/financial_assessment_form.underscore b/lms/static/js/financial-assistance/templates/financial_assessment_form.underscore
new file mode 100644
index 0000000000..7efe95c9c0
--- /dev/null
+++ b/lms/static/js/financial-assistance/templates/financial_assessment_form.underscore
@@ -0,0 +1,48 @@
+
<%- gettext('Financial Assistance Application') %>
+
+
+ <% _.each(header_text, function(copy) { %>
+
<%- copy %>
+ <% }); %>
+
+
+
diff --git a/lms/static/js/financial-assistance/templates/financial_assessment_submitted.underscore b/lms/static/js/financial-assistance/templates/financial_assessment_submitted.underscore
new file mode 100644
index 0000000000..88897f0cfb
--- /dev/null
+++ b/lms/static/js/financial-assistance/templates/financial_assessment_submitted.underscore
@@ -0,0 +1,8 @@
+<%- gettext('Financial Assistance Application') %>
+<%- interpolate_text(
+ gettext('Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.'), {course_name: course}
+ ) %>
+
+
diff --git a/lms/static/js/financial-assistance/views/financial_assistance_form_view.js b/lms/static/js/financial-assistance/views/financial_assistance_form_view.js
new file mode 100644
index 0000000000..1cecdb4db7
--- /dev/null
+++ b/lms/static/js/financial-assistance/views/financial_assistance_form_view.js
@@ -0,0 +1,107 @@
+;(function (define) {
+ 'use strict';
+
+ define(['backbone',
+ 'jquery',
+ 'underscore',
+ 'gettext',
+ 'js/financial-assistance/models/financial_assistance_model',
+ 'text!js/financial-assistance/templates/financial_assessment_form.underscore',
+ 'text!js/financial-assistance/templates/financial_assessment_submitted.underscore',
+ 'js/student_account/views/FormView',
+ 'text!templates/student_account/form_field.underscore'
+ ],
+ function(Backbone, $, _, gettext, FinancialAssistanceModel, formViewTpl, successTpl, FormView, formFieldTpl) {
+ return FormView.extend({
+ el: '.financial-assistance-wrapper',
+ events: {
+ 'click .js-submit-form': 'submitForm'
+ },
+ tpl: formViewTpl,
+ fieldTpl: formFieldTpl,
+ formType: 'financial-assistance',
+ requiredStr: '',
+ submitButton: '.js-submit-form',
+
+ initialize: function(data) {
+ var context = data.context,
+ fields = context.fields;
+
+ // Add default option to array
+ if ( fields[0].options.length > 1 ) {
+ fields[0].options.unshift({
+ name: '- ' + gettext('Choose one') + ' -',
+ value: '',
+ default: true
+ });
+ }
+
+ // Set non-form data needed to render the View
+ this.context = {
+ dashboard_url: context.dashboard_url,
+ header_text: context.header_text,
+ platform_name: context.platform_name,
+ student_faq_url: context.student_faq_url
+ };
+
+ // Make the value accessible to this View
+ this.user_details = context.user_details;
+
+ // Initialize the model and set user details
+ this.model = new FinancialAssistanceModel({
+ url: context.submit_url
+ });
+ this.model.set( context.user_details );
+ this.listenTo( this.model, 'error', this.saveError );
+ this.model.on('sync', this.renderSuccess, this);
+
+ // Build the form
+ this.buildForm( fields );
+ },
+
+ render: function(html) {
+ var data = _.extend( this.model.toJSON(), this.context, {
+ fields: html || '',
+ });
+
+ this.$el.html(_.template(this.tpl, data));
+
+ this.postRender();
+
+ return this;
+ },
+
+ renderSuccess: function() {
+ this.$el.html(_.template(successTpl, {
+ course: this.model.get('course'),
+ dashboard_url: this.context.dashboard_url
+ }));
+
+ $('.js-success-message').focus();
+ },
+
+ saveError: function(error) {
+ /*jslint maxlen: 500 */
+ var txt = [
+ 'An error has occurred. Wait a few minutes and then try to submit the application again.',
+ 'If you continue to have issues please contact support.'
+ ],
+ msg = gettext(txt.join(' '));
+
+ if (error.status === 0) {
+ msg = gettext('An error has occurred. Check your Internet connection and try again.');
+ }
+
+ this.errors = ['' + msg + ' '];
+ this.setErrors();
+ this.element.hide( this.$resetSuccess );
+ this.toggleDisableButton(false);
+ },
+
+ setExtraData: function(data) {
+ return _.extend(data, this.user_details);
+ }
+ });
+ }
+ );
+}).call(this, define || RequireJS.define);
diff --git a/lms/static/js/spec/financial-assistance/financial_assistance_form_view_spec.js b/lms/static/js/spec/financial-assistance/financial_assistance_form_view_spec.js
new file mode 100644
index 0000000000..9ec688e934
--- /dev/null
+++ b/lms/static/js/spec/financial-assistance/financial_assistance_form_view_spec.js
@@ -0,0 +1,59 @@
+define([
+ 'backbone',
+ 'jquery',
+ 'js/financial-assistance/views/financial_assistance_form_view'
+ ], function (Backbone, $, FinancialAssistanceFormView) {
+
+ 'use strict';
+
+ describe('Financial Assistance View', function () {
+ var view = null,
+ context = {
+ fields: [{
+ defaultValue: '',
+ form: 'financial-assistance',
+ instructions: 'select a course',
+ label: 'Course',
+ name: 'course',
+ options: [
+ {'name': 'Verified with Audit', 'value': 'course-v1:HCFA+VA101+2015'},
+ {'name': 'Something Else', 'value': 'course-v1:SomethingX+SE101+215'},
+ {'name': 'Test Course', 'value': 'course-v1:TestX+T101+2015'}
+ ],
+ placeholder: '',
+ required: true,
+ requiredStr: '',
+ type: 'select'
+ }],
+ user_details: {
+ country: 'UK',
+ email: 'xsy@edx.org',
+ name: 'xsy',
+ username: 'xsy4ever'
+ },
+ header_text: ['Line one.', 'Line two.'],
+ student_faq_url: '/faqs',
+ dashboard_url: '/dashboard',
+ platform_name: 'edx',
+ submit_url: '/api/financial/v1/assistance'
+ };
+
+ beforeEach(function() {
+ setFixtures('
');
+ view = new FinancialAssistanceFormView({
+ el: '.financial-assistance-wrapper',
+ context: context
+ });
+ });
+
+ afterEach(function() {
+ view.undelegateEvents();
+ view.remove();
+ });
+
+ it('should exist', function() {
+ expect(view).toBeDefined();
+ });
+ });
+ }
+);
diff --git a/lms/static/js/student_account/views/FormView.js b/lms/static/js/student_account/views/FormView.js
index 75f7c56f1c..42fb614a76 100644
--- a/lms/static/js/student_account/views/FormView.js
+++ b/lms/static/js/student_account/views/FormView.js
@@ -213,6 +213,13 @@
this.focusFirstError();
},
+ /* Allows extended views to add non-form attributes
+ * to the data before saving it to model
+ */
+ setExtraData: function( data ) {
+ return data;
+ },
+
submitForm: function( event ) {
var data = this.getFormData();
@@ -223,6 +230,7 @@
this.toggleDisableButton(true);
if ( !_.compact(this.errors).length ) {
+ data = this.setExtraData( data );
this.model.set( data );
this.model.save();
this.toggleErrorMsg( false );
diff --git a/lms/static/sass/views/_financial-assistance.scss b/lms/static/sass/views/_financial-assistance.scss
index 4fc5bc69bd..e8415e6da9 100644
--- a/lms/static/sass/views/_financial-assistance.scss
+++ b/lms/static/sass/views/_financial-assistance.scss
@@ -1,33 +1,39 @@
+%fa-copy {
+ @extend %t-copy-base;
+ padding: ($baseline/2) 0;
+ margin: 0;
+ color: $m-gray-d2;
+};
+
.financial-assistance-wrapper {
margin: auto;
- padding: $baseline 0;
+ padding: $baseline ($baseline/2);
max-width: 1180px;
- .financial-assistance {
+ h1 {
+ @extend %t-title4;
+ @include text-align(left);
+ margin: 0;
+ padding: ($baseline/2) 0;
border-bottom: 4px solid $gray-l5;
+ color: $m-gray-d3;
+ }
- h1 {
- @extend %t-title4;
- @include text-align(left);
- margin: 0;
- padding: ($baseline/2) 0;
- border-bottom: 4px solid $gray-l5;
- color: $m-gray-d3;
- }
+ h2 {
+ @extend %t-title6;
+ @extend %t-strong;
+ margin-top: ($baseline/2);
+ text-transform: none;
+ }
- h2 {
- @extend %t-title6;
- @extend %t-strong;
- margin-top: ($baseline/2);
- text-transform: none;
- }
+ p {
+ @extend %fa-copy;
+ font-size: 0.875em;
+ }
- p {
- @extend %t-copy-base;
- padding: ($baseline/2) 0;
- margin: 0;
- color: $m-gray-d2;
- }
+ .financial-assistance {
+ padding-bottom: ($baseline/2);
+ border-bottom: 4px solid $gray-l5;
.apply-form-list {
padding: 0;
@@ -73,4 +79,165 @@
border-radius: 2px;
}
}
+
+ // Application form View
+ .intro {
+ border-bottom: 4px solid $gray-l5;
+
+ p {
+ margin: 10px 0;
+ }
+ }
+
+ .success-message {
+ p {
+ margin: 10px 0;
+ }
+ }
+
+ .btn-dashboard {
+ @include float(right);
+ color: $white;
+
+ &:hover,
+ &:active,
+ &:focus {
+ color: $white;
+ }
+ }
+
+ .user-info {
+ @include clearfix();
+ border-bottom: 2px solid $gray-l5;
+ padding: 20px 0;
+ margin-bottom: 20px;
+
+ .info-column {
+ @include float(left);
+ width: 100%;
+ margin: 10px 0;
+ }
+
+ .title {
+ @extend %fa-copy;
+ padding: 0;
+ }
+
+ .data {
+ @extend %fa-copy;
+ padding: 0;
+ color: $black;
+ font-size: 1.125em;
+ }
+ }
+
+ .financial-assistance-form {
+ @extend .login-register;
+
+ .action-primary {
+ @include float(left);
+ width: auto;
+ margin-top: 0;
+ }
+
+ .nav-link {
+ margin: 15px 0;
+ display: block;
+ }
+
+ form {
+ border: none;
+ }
+
+ .form-field {
+ select,
+ input {
+ width: 320px;
+ }
+
+ input {
+ border: {
+ top: none;
+ right: none;
+ bottom: 3px solid $gray-l1;
+ left: none;
+ };
+ box-shadow: none;
+ }
+
+ textarea {
+ height: 125px;
+ }
+
+ .checkbox {
+ height: auto;
+ position: absolute;
+ top: 5px;
+
+ & + label {
+ @include margin-left(30px);
+ display: inline-block;
+ }
+ }
+ }
+ }
+
+ .cta-wrapper {
+ border-top: 4px solid $gray-l5;
+ padding: 20px 0;
+ }
+
+ @include media($bp-medium) {
+ .user-info {
+ .info-column {
+ width: 50%;
+ }
+ }
+
+ .financial-assistance-form {
+ .action-primary {
+ @include float(right);
+ }
+
+ .nav-link {
+ display: inline-block;
+ }
+ }
+ }
+
+ @include media($bp-large) {
+ .user-info {
+ .info-column {
+ width: 25%;
+ }
+ }
+
+ .financial-assistance-form {
+ .action-primary {
+ @include float(right);
+ }
+
+ .nav-link {
+ display: inline-block;
+ }
+ }
+ }
+
+ @include media($bp-huge) {
+ .user-info {
+ .info-column {
+ width: 25%;
+ }
+ }
+
+ .financial-assistance-form {
+ .action-primary {
+ @include float(right);
+ }
+
+ .nav-link {
+ display: inline-block;
+ }
+ }
+ }
}
diff --git a/lms/templates/student_account/form_field.underscore b/lms/templates/student_account/form_field.underscore
index 943b070940..898a59b5e6 100644
--- a/lms/templates/student_account/form_field.underscore
+++ b/lms/templates/student_account/form_field.underscore
@@ -21,6 +21,7 @@
data-isdefault="true"<% } %>><%= el.name %>
<% }); %>
+ <% if ( instructions ) { %> <%= instructions %> <% } %>
<% } else if ( type === 'textarea' ) { %>
+ <% if ( instructions ) { %> <%= instructions %> <% } %>
<% } else { %>
placeholder="<%= placeholder %>"<% } %>
value="<%- defaultValue %>"
/>
+ <% if ( type === 'checkbox' ) { %>
+
+ <%= label %>
+ <% if ( required && requiredStr ) { %> <%= requiredStr %><% } %>
+
+ <% } %>
<% if ( instructions ) { %> <%= instructions %> <% } %>
<% } %>
- <% if ( type === 'checkbox' ) { %>
-
- <%= label %>
- <% if ( required && requiredStr ) { %> <%= requiredStr %><% } %>
-
- <% } %>
-
<% if( form === 'login' && name === 'password' ) { %>
<%- gettext("Forgot password?") %>
<% } %>