diff --git a/apps/src/code-studio/pd/application_dashboard/application_dashboard.jsx b/apps/src/code-studio/pd/application_dashboard/application_dashboard.jsx
index d6a432d173d8e..9184f93615058 100644
--- a/apps/src/code-studio/pd/application_dashboard/application_dashboard.jsx
+++ b/apps/src/code-studio/pd/application_dashboard/application_dashboard.jsx
@@ -118,6 +118,7 @@ export default class ApplicationDashboard extends React.Component {
breadcrumbs={cohort_path_name}
component={CohortView}
applicationType={cohort_path_name}
+ viewType={paths[path].type}
/>
)
];
diff --git a/apps/src/code-studio/pd/application_dashboard/cohort_view.jsx b/apps/src/code-studio/pd/application_dashboard/cohort_view.jsx
index fca235ba0d37d..f0ea37c07ff9a 100644
--- a/apps/src/code-studio/pd/application_dashboard/cohort_view.jsx
+++ b/apps/src/code-studio/pd/application_dashboard/cohort_view.jsx
@@ -12,10 +12,15 @@ class CohortView extends React.Component{
regionalPartnerName: PropTypes.string.isRequired,
route: PropTypes.shape({
path: PropTypes.string.isRequired,
- applicationType: PropTypes.string.isRequired
+ applicationType: PropTypes.string.isRequired,
+ viewType: PropTypes.oneOf(['teacher', 'facilitator']).isRequired
})
}
+ static contextTypes = {
+ router: PropTypes.object.isRequired
+ }
+
state = {
loading: true,
applications: null
@@ -47,6 +52,8 @@ class CohortView extends React.Component{
{this.props.route.applicationType}
);
diff --git a/apps/src/code-studio/pd/application_dashboard/cohort_view_table.jsx b/apps/src/code-studio/pd/application_dashboard/cohort_view_table.jsx
index 7b4a94d2b515d..498de8c73291a 100644
--- a/apps/src/code-studio/pd/application_dashboard/cohort_view_table.jsx
+++ b/apps/src/code-studio/pd/application_dashboard/cohort_view_table.jsx
@@ -1,5 +1,6 @@
import React, {PropTypes} from 'react';
import {Table} from 'reactabular';
+import {Button} from 'react-bootstrap';
const styles = {
table: {
@@ -10,19 +11,20 @@ const styles = {
export default class CohortViewTable extends React.Component {
static propTypes = {
data: PropTypes.array.isRequired,
+ path: PropTypes.string.isRequired,
+ viewType: PropTypes.oneOf(['facilitator', 'teacher']).isRequired
+ }
+
+ static contextTypes = {
+ router: PropTypes.object
}
constructColumns() {
- return [
+ let columns = [
{
- property: 'date_accepted',
+ property: 'accepted_at',
header: {
label: 'Date Accepted'
- },
- cell: {
- format: (date_accepted) => {
- return new Date(date_accepted).toLocaleDateString('en-us', {month: 'long', day: 'numeric'});
- }
}
}, {
property: 'applicant_name',
@@ -45,14 +47,73 @@ export default class CohortViewTable extends React.Component {
label: 'Email'
}
}, {
- property: 'registered_for_summer_workshop',
+ property: 'notified',
header: {
- label: 'Registered Summer Workshop'
+ label: 'Notified'
}
}
];
+
+ if (this.props.viewType === 'facilitator') {
+ columns.push({
+ property: 'assigned_fit',
+ header: {
+ label: 'Assigned FIT'
+ }
+ }, {
+ property: 'registered_fit',
+ header: {
+ label: 'Registered FIT'
+ }
+ }
+ );
+ } else {
+ columns.push(
+ {
+ property: 'assigned_workshop',
+ header: {
+ label: 'Assigned Workshop'
+ }
+ }, {
+ property: 'registered_workshop',
+ header: {
+ label: 'Registered Workshop'
+ }
+ }
+ );
+ }
+
+ columns.push({
+ property: 'id',
+ header: {
+ label: 'View Application'
+ },
+ cell: {
+ format: this.formatViewButton
+ }
+ });
+
+ return columns;
}
+ formatViewButton = (id) => {
+ return (
+
+ );
+ };
+
+ handleViewClick = (id, event) => {
+ event.preventDefault();
+ this.context.router.push(`/${this.props.path.replace('_cohort', '')}/${id}`);
+ };
+
render() {
return (
-
+
);
}
diff --git a/apps/src/code-studio/pd/application_dashboard/cohort_view_table.story.jsx b/apps/src/code-studio/pd/application_dashboard/cohort_view_table.story.jsx
index 7138e5e9f3886..b3a301d98feb6 100644
--- a/apps/src/code-studio/pd/application_dashboard/cohort_view_table.story.jsx
+++ b/apps/src/code-studio/pd/application_dashboard/cohort_view_table.story.jsx
@@ -8,27 +8,71 @@ export default storybook => {
.addDecorator(reactBootstrapStoryDecorator)
.addStoryTable([
{
- name: 'Cohort view for application',
+ name: 'Cohort view for teacher application',
story: () => (
+ )
+ }, {
+ name: 'Cohort view for facilitator application',
+ story: () => (
+
)
}
diff --git a/dashboard/app/controllers/api/v1/pd/applications_controller.rb b/dashboard/app/controllers/api/v1/pd/applications_controller.rb
index 9dbf26da4fb50..d3eec0bd00d0b 100644
--- a/dashboard/app/controllers/api/v1/pd/applications_controller.rb
+++ b/dashboard/app/controllers/api/v1/pd/applications_controller.rb
@@ -61,7 +61,14 @@ def quick_view
def cohort_view
applications = get_applications_by_role(params[:role].to_sym).where(status: 'accepted').where.not(locked_at: nil)
- render json: applications, each_serializer: Api::V1::Pd::ApplicationCohortViewSerializer
+ serializer =
+ if TYPES_BY_ROLE[params[:role].to_sym] == Pd::Application::Facilitator1819Application
+ Api::V1::Pd::FacilitatorApplicationCohortViewSerializer
+ elsif TYPES_BY_ROLE[params[:role].to_sym] == Pd::Application::Teacher1819Application
+ Api::V1::Pd::TeacherApplicationCohortViewSerializer
+ end
+
+ render json: applications, each_serializer: serializer
end
# PATCH /api/v1/pd/applications/1
diff --git a/dashboard/app/models/pd/application/application_base.rb b/dashboard/app/models/pd/application/application_base.rb
index f206e402d4711..0e0c235aa1c35 100644
--- a/dashboard/app/models/pd/application/application_base.rb
+++ b/dashboard/app/models/pd/application/application_base.rb
@@ -97,6 +97,7 @@ class ApplicationBase < ActiveRecord::Base
before_create -> {self.status = :unreviewed}
after_initialize :set_type_and_year
before_validation :set_type_and_year
+ before_save :update_accepted_date, if: :status_changed?
def set_type_and_year
# Override in derived classes and set to valid values.
@@ -105,6 +106,10 @@ def set_type_and_year
self.application_type = nil
end
+ def update_accepted_date
+ self.accepted_at = status == 'accepted' ? Time.now : nil
+ end
+
self.table_name = 'pd_applications'
enum status: %w(
diff --git a/dashboard/app/serializers/api/v1/pd/application_cohort_view_serializer.rb b/dashboard/app/serializers/api/v1/pd/application_cohort_view_serializer.rb
deleted file mode 100644
index 5554916d68ae8..0000000000000
--- a/dashboard/app/serializers/api/v1/pd/application_cohort_view_serializer.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-class Api::V1::Pd::ApplicationCohortViewSerializer < ActiveModel::Serializer
- attributes :date_accepted, :applicant_name, :district_name, :school_name, :email,
- :registered_for_summer_workshop
-
- def email
- object.user.email
- end
-
- def date_accepted
- # TODO: mehal - Implement this
- 'Not implemented yet'
- end
-
- def registered_for_summer_workshop
- # TODO: mehal - Implement this
- 'Not implemented yet'
- end
-end
diff --git a/dashboard/app/serializers/api/v1/pd/facilitator_application_cohort_view_serializer.rb b/dashboard/app/serializers/api/v1/pd/facilitator_application_cohort_view_serializer.rb
new file mode 100644
index 0000000000000..2608102f4fb18
--- /dev/null
+++ b/dashboard/app/serializers/api/v1/pd/facilitator_application_cohort_view_serializer.rb
@@ -0,0 +1,27 @@
+class Api::V1::Pd::FacilitatorApplicationCohortViewSerializer < ActiveModel::Serializer
+ attributes :id, :date_accepted, :applicant_name, :district_name, :school_name, :email,
+ :notified, :assigned_fit, :registered_fit
+
+ def date_accepted
+ object.accepted_at.try(:strftime, '%b %e')
+ end
+
+ def email
+ object.user.email
+ end
+
+ def notified
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+
+ def assigned_fit
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+
+ def registered_fit
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+end
diff --git a/dashboard/app/serializers/api/v1/pd/teacher_application_cohort_view_serializer.rb b/dashboard/app/serializers/api/v1/pd/teacher_application_cohort_view_serializer.rb
new file mode 100644
index 0000000000000..a57d0f736f10b
--- /dev/null
+++ b/dashboard/app/serializers/api/v1/pd/teacher_application_cohort_view_serializer.rb
@@ -0,0 +1,31 @@
+class Api::V1::Pd::TeacherApplicationCohortViewSerializer < ActiveModel::Serializer
+ attributes :id, :date_accepted, :applicant_name, :district_name, :school_name, :email,
+ :notified, :assigned_workshop, :registered_workshop, :accepted_teachercon
+
+ def date_accepted
+ object.accepted_at.try(:strftime, '%b %e')
+ end
+
+ def email
+ object.user.email
+ end
+
+ def notified
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+
+ def assigned_workshop
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+
+ def registered_workshop
+ # TODO: (mehal) implement this
+ 'Not implemented'
+ end
+
+ def accepted_teachercon
+ 'Not implemented'
+ end
+end
diff --git a/dashboard/test/controllers/api/v1/pd/applications_controller_test.rb b/dashboard/test/controllers/api/v1/pd/applications_controller_test.rb
index 4ff3695aea183..111b46cad9657 100644
--- a/dashboard/test/controllers/api/v1/pd/applications_controller_test.rb
+++ b/dashboard/test/controllers/api/v1/pd/applications_controller_test.rb
@@ -34,6 +34,17 @@ class ApplicationsControllerTest < ::ActionController::TestCase
@csd_teacher_application = create :pd_teacher1819_application, course: 'csd'
@csp_teacher_application = create :pd_teacher1819_application, course: 'csp'
@csp_facilitator_application = create :pd_facilitator1819_application, course: 'csp'
+
+ @serializing_teacher = create(:teacher,
+ email: 'minerva@hogwarts.edu',
+ school_info: create(
+ :school_info,
+ school: create(
+ :school,
+ name: 'Hogwarts'
+ )
+ )
+ )
end
test_redirect_to_sign_in_for :index
@@ -238,49 +249,77 @@ class ApplicationsControllerTest < ::ActionController::TestCase
).values.any? {|x| response_csv.first.exclude?(x + "\n")}
end
- test 'cohort view returns expected columns' do
- application = create(
- :pd_teacher1819_application,
- course: 'csp',
- regional_partner: @regional_partner,
- user: (
- create(
- :teacher,
+ test 'cohort view returns expected columns for a teacher' do
+ time = Date.new(2017, 3, 15)
+
+ Timecop.freeze(time) do
+ application = create(
+ :pd_teacher1819_application,
+ course: 'csp',
+ regional_partner: @regional_partner,
+ user: @serializing_teacher
+ )
+
+ application.update_form_data_hash({first_name: 'Minerva', last_name: 'McGonagall'})
+ application.save
+ application.update(status: 'accepted')
+ application.lock!
+
+ sign_in @workshop_organizer
+ get :cohort_view, params: {role: 'csp_teachers'}
+ assert :success
+
+ assert_equal(
+ {
+ id: application.id,
+ date_accepted: 'Mar 15',
+ applicant_name: 'Minerva McGonagall',
+ district_name: 'A School District',
+ school_name: 'Hogwarts',
email: 'minerva@hogwarts.edu',
- school_info: (
- create(
- :school_info,
- school: (
- create(
- :school,
- name: 'Hogwarts'
- )
- )
- )
- )
- )
+ notified: 'Not implemented',
+ assigned_workshop: 'Not implemented',
+ registered_workshop: 'Not implemented',
+ accepted_teachercon: 'Not implemented',
+ }.stringify_keys, JSON.parse(@response.body).first
)
- )
+ end
+ end
- application.update_form_data_hash({first_name: 'Minerva', last_name: 'McGonagall'})
- application.save
- application.update(status: 'accepted')
- application.lock!
+ test 'cohort view returns expected columns for a facilitator' do
+ time = Date.new(2017, 3, 15)
- sign_in @workshop_organizer
- get :cohort_view, params: {role: 'csp_teachers'}
- assert :success
-
- assert_equal(
- {
- date_accepted: 'Not implemented yet',
- applicant_name: 'Minerva McGonagall',
- district_name: 'A School District',
- school_name: 'Hogwarts',
- email: 'minerva@hogwarts.edu',
- registered_for_summer_workshop: 'Not implemented yet'
- }.stringify_keys, JSON.parse(@response.body).first
- )
+ Timecop.freeze(time) do
+ application = create(
+ :pd_facilitator1819_application,
+ course: 'csp',
+ regional_partner: @regional_partner,
+ user: @serializing_teacher
+ )
+
+ application.update_form_data_hash({first_name: 'Minerva', last_name: 'McGonagall'})
+ application.save
+ application.update(status: 'accepted')
+ application.lock!
+
+ sign_in @workshop_organizer
+ get :cohort_view, params: {role: 'csp_facilitators'}
+ assert :success
+
+ assert_equal(
+ {
+ id: application.id,
+ date_accepted: 'Mar 15',
+ applicant_name: 'Minerva McGonagall',
+ district_name: 'A School District',
+ school_name: 'Hogwarts',
+ email: 'minerva@hogwarts.edu',
+ notified: 'Not implemented',
+ assigned_fit: 'Not implemented',
+ registered_fit: 'Not implemented'
+ }.stringify_keys, JSON.parse(@response.body).first
+ )
+ end
end
end
end
diff --git a/dashboard/test/models/pd/application/teacher1819_application_test.rb b/dashboard/test/models/pd/application/teacher1819_application_test.rb
index 78f9e4bc4aa15..e3719128f1130 100644
--- a/dashboard/test/models/pd/application/teacher1819_application_test.rb
+++ b/dashboard/test/models/pd/application/teacher1819_application_test.rb
@@ -6,6 +6,8 @@ class Teacher1819ApplicationTest < ActiveSupport::TestCase
include Teacher1819ApplicationConstants
include ApplicationConstants
+ freeze_time
+
test 'application guid is generated on create' do
teacher_application = build :pd_teacher1819_application
assert_nil teacher_application.application_guid
@@ -349,5 +351,28 @@ class Teacher1819ApplicationTest < ActiveSupport::TestCase
application.send_decision_notification_email
end
end
+
+ test 'accepted_at updates times' do
+ today = Date.today.to_time
+ tomorrow = Date.tomorrow.to_time
+ application = create :pd_teacher1819_application
+ assert_nil application.accepted_at
+
+ Timecop.freeze(today) do
+ application.update(status: 'accepted')
+ application.reload
+ assert_equal today, application.accepted_at.to_time
+
+ application.update(status: 'declined')
+ application.reload
+ assert_nil application.accepted_at
+ end
+
+ Timecop.freeze(tomorrow) do
+ application.update(status: 'accepted')
+ application.reload
+ assert_equal tomorrow, application.accepted_at.to_time
+ end
+ end
end
end