Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
70efd284
Commit
70efd284
authored
Feb 27, 2015
by
Muhammad Ammar
Committed by
Usman Khalid
Mar 23, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changes after Andy's Review
parent
3ce494f5
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
125 additions
and
67 deletions
+125
-67
common/test/acceptance/tests/discussion/test_cohort_management.py
+1
-1
lms/static/js/edxnotes/views/toggle_notes_factory.js
+2
-9
lms/static/js/groups/views/cohorts.js
+10
-1
lms/static/js/groups/views/course_cohort_settings_notification.js
+1
-5
lms/static/js/instructor_dashboard/cohort_management.js
+4
-14
lms/static/js/spec/groups/views/cohorts_spec.js
+27
-17
lms/static/js/utils/animation.js
+15
-0
lms/static/sass/course/instructor/_instructor_2.scss
+3
-2
lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
+1
-1
lms/templates/instructor/instructor_dashboard_2/cohort-state.underscore
+2
-2
lms/templates/instructor/instructor_dashboard_2/cohorts.underscore
+3
-3
lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html
+3
-2
openedx/core/djangoapps/course_groups/cohorts.py
+4
-1
openedx/core/djangoapps/course_groups/models.py
+2
-2
openedx/core/djangoapps/course_groups/tests/test_cohorts.py
+23
-0
openedx/core/djangoapps/course_groups/tests/test_views.py
+17
-6
openedx/core/djangoapps/course_groups/views.py
+7
-1
No files found.
common/test/acceptance/tests/discussion/test_cohort_management.py
View file @
70efd284
...
@@ -451,7 +451,7 @@ class CohortConfigurationTest(EventsTestMixin, UniqueCourseTest, CohortTestMixin
...
@@ -451,7 +451,7 @@ class CohortConfigurationTest(EventsTestMixin, UniqueCourseTest, CohortTestMixin
And I can see the `Enable Cohorts` checkbox is checked.
And I can see the `Enable Cohorts` checkbox is checked.
And cohort management controls are visible.
And cohort management controls are visible.
When I uncheck the `Enable Cohorts` checkbox.
When I uncheck the `Enable Cohorts` checkbox.
Then
I
cohort management controls are not visible.
Then cohort management controls are not visible.
And When I reload the page.
And When I reload the page.
Then I can see the `Enable Cohorts` checkbox is unchecked.
Then I can see the `Enable Cohorts` checkbox is unchecked.
And cohort management controls are not visible.
And cohort management controls are not visible.
...
...
lms/static/js/edxnotes/views/toggle_notes_factory.js
View file @
70efd284
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
'use strict'
;
'use strict'
;
define
([
define
([
'jquery'
,
'underscore'
,
'backbone'
,
'gettext'
,
'jquery'
,
'underscore'
,
'backbone'
,
'gettext'
,
'annotator_1.2.9'
,
'js/edxnotes/views/visibility_decorator'
'annotator_1.2.9'
,
'js/edxnotes/views/visibility_decorator'
,
'js/utils/animation'
],
function
(
$
,
_
,
Backbone
,
gettext
,
Annotator
,
EdxnotesVisibilityDecorator
)
{
],
function
(
$
,
_
,
Backbone
,
gettext
,
Annotator
,
EdxnotesVisibilityDecorator
)
{
var
ToggleNotesView
=
Backbone
.
View
.
extend
({
var
ToggleNotesView
=
Backbone
.
View
.
extend
({
events
:
{
events
:
{
...
@@ -31,7 +31,7 @@ define([
...
@@ -31,7 +31,7 @@ define([
toggleHandler
:
function
(
event
)
{
toggleHandler
:
function
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
this
.
visibility
=
!
this
.
visibility
;
this
.
visibility
=
!
this
.
visibility
;
this
.
showActionMessage
(
);
AnimationUtil
.
triggerAnimation
(
this
.
actionToggleMessage
);
this
.
toggleNotes
(
this
.
visibility
);
this
.
toggleNotes
(
this
.
visibility
);
},
},
...
@@ -51,13 +51,6 @@ define([
...
@@ -51,13 +51,6 @@ define([
this
.
sendRequest
();
this
.
sendRequest
();
},
},
showActionMessage
:
function
()
{
// The following lines are necessary to re-trigger the CSS animation on span.action-toggle-message
this
.
actionToggleMessage
.
removeClass
(
'is-fleeting'
);
this
.
actionToggleMessage
.
offset
().
width
=
this
.
actionToggleMessage
.
offset
().
width
;
this
.
actionToggleMessage
.
addClass
(
'is-fleeting'
);
},
enableNotes
:
function
()
{
enableNotes
:
function
()
{
_
.
each
(
$
(
'.edx-notes-wrapper'
),
EdxnotesVisibilityDecorator
.
enableNote
);
_
.
each
(
$
(
'.edx-notes-wrapper'
),
EdxnotesVisibilityDecorator
.
enableNote
);
this
.
actionLink
.
addClass
(
'is-active'
);
this
.
actionLink
.
addClass
(
'is-active'
);
...
...
lms/static/js/groups/views/cohorts.js
View file @
70efd284
...
@@ -57,7 +57,8 @@ var edx = edx || {};
...
@@ -57,7 +57,8 @@ var edx = edx || {};
renderCourseCohortSettingsNotificationView
:
function
()
{
renderCourseCohortSettingsNotificationView
:
function
()
{
var
cohortStateMessageNotificationView
=
new
CourseCohortSettingsNotificationView
({
var
cohortStateMessageNotificationView
=
new
CourseCohortSettingsNotificationView
({
el
:
$
(
'.cohort-state-message'
),
el
:
$
(
'.cohort-state-message'
),
cohortEnabled
:
this
.
getCohortsEnabled
()});
cohortEnabled
:
this
.
getCohortsEnabled
()
});
cohortStateMessageNotificationView
.
render
();
cohortStateMessageNotificationView
.
render
();
},
},
...
@@ -123,6 +124,12 @@ var edx = edx || {};
...
@@ -123,6 +124,12 @@ var edx = edx || {};
).
done
(
function
()
{
).
done
(
function
()
{
self
.
render
();
self
.
render
();
self
.
renderCourseCohortSettingsNotificationView
();
self
.
renderCourseCohortSettingsNotificationView
();
}).
fail
(
function
(
result
)
{
self
.
showNotification
({
type
:
'error'
,
title
:
gettext
(
"We've encountered an error. Refresh your browser and then try again."
)},
self
.
$
(
'.cohorts-state-section'
)
);
});
});
},
},
...
@@ -199,9 +206,11 @@ var edx = edx || {};
...
@@ -199,9 +206,11 @@ var edx = edx || {};
setCohortEditorVisibility
:
function
(
showEditor
)
{
setCohortEditorVisibility
:
function
(
showEditor
)
{
if
(
showEditor
)
{
if
(
showEditor
)
{
this
.
$
(
'.cohorts-state-section'
).
removeClass
(
disabledClass
).
attr
(
'aria-disabled'
,
false
);
this
.
$
(
'.cohort-management-group'
).
removeClass
(
hiddenClass
);
this
.
$
(
'.cohort-management-group'
).
removeClass
(
hiddenClass
);
this
.
$
(
'.cohort-management-nav'
).
removeClass
(
disabledClass
).
attr
(
'aria-disabled'
,
false
);
this
.
$
(
'.cohort-management-nav'
).
removeClass
(
disabledClass
).
attr
(
'aria-disabled'
,
false
);
}
else
{
}
else
{
this
.
$
(
'.cohorts-state-section'
).
addClass
(
disabledClass
).
attr
(
'aria-disabled'
,
true
);
this
.
$
(
'.cohort-management-group'
).
addClass
(
hiddenClass
);
this
.
$
(
'.cohort-management-group'
).
addClass
(
hiddenClass
);
this
.
$
(
'.cohort-management-nav'
).
addClass
(
disabledClass
).
attr
(
'aria-disabled'
,
true
);
this
.
$
(
'.cohort-management-nav'
).
addClass
(
disabledClass
).
attr
(
'aria-disabled'
,
true
);
}
}
...
...
lms/static/js/groups/views/course_cohort_settings_notification.js
View file @
70efd284
...
@@ -20,11 +20,7 @@ var edx = edx || {};
...
@@ -20,11 +20,7 @@ var edx = edx || {};
showCohortStateMessage
:
function
()
{
showCohortStateMessage
:
function
()
{
var
actionToggleMessage
=
this
.
$
(
'.action-toggle-message'
);
var
actionToggleMessage
=
this
.
$
(
'.action-toggle-message'
);
// The following lines are necessary to re-trigger the CSS animation on span.action-toggle-message
AnimationUtil
.
triggerAnimation
(
actionToggleMessage
);
actionToggleMessage
.
removeClass
(
'is-fleeting'
);
actionToggleMessage
.
offset
().
width
=
actionToggleMessage
.
offset
().
width
;
actionToggleMessage
.
addClass
(
'is-fleeting'
);
if
(
this
.
cohortEnabled
)
{
if
(
this
.
cohortEnabled
)
{
actionToggleMessage
.
text
(
gettext
(
'Cohorts Enabled'
));
actionToggleMessage
.
text
(
gettext
(
'Cohorts Enabled'
));
}
else
{
}
else
{
...
...
lms/static/js/instructor_dashboard/cohort_management.js
View file @
70efd284
(
function
()
{
(
function
()
{
var
CohortManagement
;
var
CohortManagement
;
CohortManagement
=
(
function
()
{
CohortManagement
=
(
function
()
{
function
CohortManagement
(
$section
)
{
function
CohortManagement
(
$section
)
{
this
.
$section
=
$section
;
this
.
$section
=
$section
;
...
@@ -12,18 +12,8 @@
...
@@ -12,18 +12,8 @@
return
CohortManagement
;
return
CohortManagement
;
})();
})();
_
.
defaults
(
window
,
{
window
.
InstructorDashboard
.
sections
.
CohortManagement
=
CohortManagement
;
InstructorDashboard
:
{}
});
_
.
defaults
(
window
.
InstructorDashboard
,
{
sections
:
{}
});
_
.
defaults
(
window
.
InstructorDashboard
.
sections
,
{
CohortManagement
:
CohortManagement
});
}).
call
(
this
);
}).
call
(
this
);
lms/static/js/spec/groups/views/cohorts_spec.js
View file @
70efd284
define
([
'backbone'
,
'jquery'
,
'js/common_helpers/ajax_helpers'
,
'js/common_helpers/template_helpers'
,
define
([
'backbone'
,
'jquery'
,
'js/common_helpers/ajax_helpers'
,
'js/common_helpers/template_helpers'
,
'js/groups/views/cohorts'
,
'js/groups/collections/cohort'
,
'js/groups/models/content_group'
,
'js/groups/views/cohorts'
,
'js/groups/collections/cohort'
,
'js/groups/models/content_group'
,
'js/groups/models/course_cohort_settings'
,
'js/groups/views/course_cohort_settings_notification'
],
'js/groups/models/course_cohort_settings'
,
'js/utils/animation'
,
'js/groups/views/course_cohort_settings_notification'
],
function
(
Backbone
,
$
,
AjaxHelpers
,
TemplateHelpers
,
CohortsView
,
CohortCollection
,
ContentGroupModel
,
function
(
Backbone
,
$
,
AjaxHelpers
,
TemplateHelpers
,
CohortsView
,
CohortCollection
,
ContentGroupModel
,
CourseCohortSettingsModel
,
CourseCohortSettingsNotificationView
)
{
CourseCohortSettingsModel
,
AnimationUtil
,
CourseCohortSettingsNotificationView
)
{
'use strict'
;
'use strict'
;
describe
(
"Cohorts View"
,
function
()
{
describe
(
"Cohorts View"
,
function
()
{
var
catLoversInitialCount
=
123
,
dogLoversInitialCount
=
456
,
unknownUserMessage
,
var
catLoversInitialCount
=
123
,
dogLoversInitialCount
=
456
,
unknownUserMessage
,
createMockCohort
,
createMockCohorts
,
createMockContentGroups
,
create
CohortSettings
,
createCohortsView
,
createMockCohort
,
createMockCohorts
,
createMockContentGroups
,
create
MockCohortSettingsJson
,
c
ohortsView
,
requests
,
respondToRefresh
,
verifyMessage
,
verifyNoMessage
,
verifyDetailed
Message
,
c
reateCohortsView
,
cohortsView
,
requests
,
respondToRefresh
,
verifyMessage
,
verifyNo
Message
,
verify
Header
,
expectCohortAddRequest
,
getAddModal
,
selectContentGroup
,
clear
ContentGroup
,
verify
DetailedMessage
,
verifyHeader
,
expectCohortAddRequest
,
getAddModal
,
select
ContentGroup
,
saveFormAndExpectErrors
,
createMockCohortSettings
,
MOCK_COHORTED_USER_PARTITION_ID
,
clearContentGroup
,
saveFormAndExpectErrors
,
createMockCohortSettings
,
MOCK_COHORTED_USER_PARTITION_ID
,
MOCK_UPLOAD_COHORTS_CSV_URL
,
MOCK_STUDIO_ADVANCED_SETTINGS_URL
,
MOCK_STUDIO_GROUP_CONFIGURATIONS_URL
,
MOCK_UPLOAD_COHORTS_CSV_URL
,
MOCK_STUDIO_ADVANCED_SETTINGS_URL
,
MOCK_STUDIO_GROUP_CONFIGURATIONS_URL
,
MOCK_MANUAL_ASSIGNMENT
,
MOCK_RANDOM_ASSIGNMENT
;
MOCK_MANUAL_ASSIGNMENT
,
MOCK_RANDOM_ASSIGNMENT
;
...
@@ -52,7 +54,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
...
@@ -52,7 +54,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
];
];
};
};
createMockCohortSettings
=
function
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
{
createMockCohortSettings
Json
=
function
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
{
return
{
return
{
id
:
0
,
id
:
0
,
is_cohorted
:
isCohorted
||
false
,
is_cohorted
:
isCohorted
||
false
,
...
@@ -61,9 +63,9 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
...
@@ -61,9 +63,9 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
};
};
};
};
createCohortSettings
=
function
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
{
create
Mock
CohortSettings
=
function
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
{
return
new
CourseCohortSettingsModel
(
return
new
CourseCohortSettingsModel
(
createMockCohortSettings
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
createMockCohortSettings
Json
(
isCohorted
,
cohortedDiscussions
,
alwaysCohortInlineDiscussions
)
);
);
};
};
...
@@ -73,7 +75,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
...
@@ -73,7 +75,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
cohortsJson
=
options
.
cohorts
?
{
cohorts
:
options
.
cohorts
}
:
createMockCohorts
();
cohortsJson
=
options
.
cohorts
?
{
cohorts
:
options
.
cohorts
}
:
createMockCohorts
();
cohorts
=
new
CohortCollection
(
cohortsJson
,
{
parse
:
true
});
cohorts
=
new
CohortCollection
(
cohortsJson
,
{
parse
:
true
});
contentGroups
=
options
.
contentGroups
||
createMockContentGroups
();
contentGroups
=
options
.
contentGroups
||
createMockContentGroups
();
cohortSettings
=
options
.
cohortSettings
||
createCohortSettings
(
true
);
cohortSettings
=
options
.
cohortSettings
||
create
Mock
CohortSettings
(
true
);
cohortSettings
.
url
=
'/mock_service/cohorts/settings'
;
cohortSettings
.
url
=
'/mock_service/cohorts/settings'
;
cohorts
.
url
=
'/mock_service/cohorts'
;
cohorts
.
url
=
'/mock_service/cohorts'
;
requests
=
AjaxHelpers
.
requests
(
test
);
requests
=
AjaxHelpers
.
requests
(
test
);
...
@@ -278,36 +280,36 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
...
@@ -278,36 +280,36 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
});
describe
(
"Course Cohort Settings"
,
function
()
{
describe
(
"Course Cohort Settings"
,
function
()
{
it
(
'
enable/disable working correctly
'
,
function
()
{
it
(
'
can enable and disable cohorting
'
,
function
()
{
createCohortsView
(
this
,
{
cohortSettings
:
createCohortSettings
(
false
)});
createCohortsView
(
this
,
{
cohortSettings
:
create
Mock
CohortSettings
(
false
)});
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeFalsy
();
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeFalsy
();
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
,
true
).
change
();
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
,
true
).
change
();
AjaxHelpers
.
expectJsonRequest
(
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/mock_service/cohorts/settings'
,
requests
,
'PUT'
,
'/mock_service/cohorts/settings'
,
createMockCohortSettings
(
true
,
[],
true
)
createMockCohortSettings
Json
(
true
,
[],
true
)
);
);
AjaxHelpers
.
respondWithJson
(
AjaxHelpers
.
respondWithJson
(
requests
,
requests
,
createMockCohortSettings
(
true
)
createMockCohortSettings
Json
(
true
)
);
);
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeTruthy
();
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeTruthy
();
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
,
false
).
change
();
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
,
false
).
change
();
AjaxHelpers
.
expectJsonRequest
(
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/mock_service/cohorts/settings'
,
requests
,
'PUT'
,
'/mock_service/cohorts/settings'
,
createMockCohortSettings
(
false
,
[],
true
)
createMockCohortSettings
Json
(
false
,
[],
true
)
);
);
AjaxHelpers
.
respondWithJson
(
AjaxHelpers
.
respondWithJson
(
requests
,
requests
,
createMockCohortSettings
(
false
)
createMockCohortSettings
Json
(
false
)
);
);
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeFalsy
();
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeFalsy
();
});
});
it
(
'
Course Cohort Settings Notification View renders correctly
'
,
function
()
{
it
(
'
shows an appropriate cohort status message
'
,
function
()
{
var
createCourseCohortSettingsNotificationView
=
function
(
is_cohorted
)
{
var
createCourseCohortSettingsNotificationView
=
function
(
is_cohorted
)
{
var
notificationView
=
new
CourseCohortSettingsNotificationView
({
var
notificationView
=
new
CourseCohortSettingsNotificationView
({
el
:
$
(
'.cohort-state-message'
),
el
:
$
(
'.cohort-state-message'
),
...
@@ -323,6 +325,14 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
...
@@ -323,6 +325,14 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
expect
(
notificationView
.
$
(
'.action-toggle-message'
).
text
().
trim
()).
toBe
(
'Cohorts Disabled'
);
expect
(
notificationView
.
$
(
'.action-toggle-message'
).
text
().
trim
()).
toBe
(
'Cohorts Disabled'
);
});
});
it
(
'shows an appropriate error message for HTTP500'
,
function
()
{
createCohortsView
(
this
,
{
cohortSettings
:
createMockCohortSettings
(
false
)});
expect
(
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
)).
toBeFalsy
();
cohortsView
.
$
(
'.cohorts-state'
).
prop
(
'checked'
,
true
).
change
();
AjaxHelpers
.
respondWithError
(
requests
,
500
);
var
expectedTitle
=
"We've encountered an error. Refresh your browser and then try again."
expect
(
cohortsView
.
$
(
'.message-title'
).
text
().
trim
()).
toBe
(
expectedTitle
);
});
});
});
describe
(
"Cohort Group Header"
,
function
()
{
describe
(
"Cohort Group Header"
,
function
()
{
...
...
lms/static/js/utils/animation.js
0 → 100644
View file @
70efd284
(
function
()
{
this
.
AnimationUtil
=
(
function
()
{
function
AnimationUtil
()
{}
AnimationUtil
.
triggerAnimation
=
function
(
messageElement
)
{
// The following lines are necessary to re-trigger the CSS animation on span.action-toggle-message
// To see how it works, please see `Another JavaScript Method to Restart a CSS Animation`
// at https://css-tricks.com/restart-css-animation/
messageElement
.
removeClass
(
'is-fleeting'
);
messageElement
.
offset
().
width
=
messageElement
.
offset
().
width
;
messageElement
.
addClass
(
'is-fleeting'
);
};
return
AnimationUtil
;
}).
call
(
this
);
}).
call
(
this
);
lms/static/sass/course/instructor/_instructor_2.scss
View file @
70efd284
...
@@ -809,9 +809,10 @@
...
@@ -809,9 +809,10 @@
}
}
}
}
.cohort-management-assignment-type-settings
{
.cohort-management-assignment-type-settings
,
.cohorts-state-section
{
&
.is-disabled
{
&
.is-disabled
{
opacity
:
0
.
50
;
opacity
:
0
.
25
;
}
}
}
}
...
...
lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore
View file @
70efd284
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
<div class="cohort-management-assignment-type-settings field field-radio">
<div class="cohort-management-assignment-type-settings field field-radio">
<% } %>
<% } %>
<h4 class="form-label">
<h4 class="form-label">
<%- gettext('Students in this cohort are
:
') %>
<%- gettext('Students in this cohort are') %>
</h4>
</h4>
<label>
<label>
<input type="radio" class="type-random" name="cohort-assignment-type" value="random" <%- assignment_type == 'random' ? 'checked="checked"' : '' %>/> <%- gettext("Automatically Assigned") %>
<input type="radio" class="type-random" name="cohort-assignment-type" value="random" <%- assignment_type == 'random' ? 'checked="checked"' : '' %>/> <%- gettext("Automatically Assigned") %>
...
...
lms/templates/instructor/instructor_dashboard_2/cohort-state.underscore
View file @
70efd284
<div class="nav-utilities">
<div class="nav-utilities">
<span class="action-toggle-message" aria-live="polite"></span>
<span class="action-toggle-message" aria-live="polite"></span>
</div>
</div>
\ No newline at end of file
lms/templates/instructor/instructor_dashboard_2/cohorts.underscore
View file @
70efd284
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
<form action="" method="post" name="" id="cohort-management-nav-form" class="cohort-management-nav-form">
<form action="" method="post" name="" id="cohort-management-nav-form" class="cohort-management-nav-form">
<div class="cohort-management-nav-form-select field field-select">
<div class="cohort-management-nav-form-select field field-select">
<label for="cohort-select" class="label sr"><%- gettext("Select a cohort
group
to manage") %></label>
<label for="cohort-select" class="label sr"><%- gettext("Select a cohort to manage") %></label>
<select class="input cohort-select" name="cohort-select" id="cohort-select"></select>
<select class="input cohort-select" name="cohort-select" id="cohort-select"></select>
</div>
</div>
...
@@ -17,10 +17,10 @@
...
@@ -17,10 +17,10 @@
</div>
</div>
</form>
</form>
<
a href="" class="
action-primary action-create">
<
button class="button
action-primary action-create">
<i class="icon fa fa-plus" aria-hidden="true"></i>
<i class="icon fa fa-plus" aria-hidden="true"></i>
<%- gettext('Add Cohort') %>
<%- gettext('Add Cohort') %>
</
a
>
</
button
>
</div>
</div>
<!-- Add modal -->
<!-- Add modal -->
...
...
lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html
View file @
70efd284
...
@@ -66,6 +66,7 @@
...
@@ -66,6 +66,7 @@
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohort_form.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohort_form.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohort_editor.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohort_editor.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohorts.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/groups/views/cohorts.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/utils/animation.js')}"
></script>
</
%
block>
</
%
block>
## Include Underscore templates
## Include Underscore templates
...
@@ -129,4 +130,5 @@
...
@@ -129,4 +130,5 @@
% endfor
% endfor
</section>
</section>
</div>
</div>
</section>
</section>
\ No newline at end of file
openedx/core/djangoapps/course_groups/cohorts.py
View file @
70efd284
...
@@ -456,9 +456,12 @@ def set_course_cohort_settings(course_key, **kwargs):
...
@@ -456,9 +456,12 @@ def set_course_cohort_settings(course_key, **kwargs):
Raises:
Raises:
ValueError if course_key is invalid.
ValueError if course_key is invalid.
"""
"""
fields
=
{
'is_cohorted'
:
bool
,
'always_cohort_inline_discussions'
:
bool
,
'cohorted_discussions'
:
list
}
course_cohort_settings
=
get_course_cohort_settings
(
course_key
)
course_cohort_settings
=
get_course_cohort_settings
(
course_key
)
for
field
in
(
'is_cohorted'
,
'always_cohort_inline_discussions'
,
'cohorted_discussions'
):
for
field
,
field_type
in
fields
.
items
(
):
if
field
in
kwargs
:
if
field
in
kwargs
:
if
not
isinstance
(
kwargs
[
field
],
field_type
):
raise
ValueError
(
"Incorrect field type for `{}`. Type must be `{}`"
.
format
(
field
,
field_type
.
__name__
))
setattr
(
course_cohort_settings
,
field
,
kwargs
[
field
])
setattr
(
course_cohort_settings
,
field
,
kwargs
[
field
])
course_cohort_settings
.
save
()
course_cohort_settings
.
save
()
return
course_cohort_settings
return
course_cohort_settings
...
...
openedx/core/djangoapps/course_groups/models.py
View file @
70efd284
...
@@ -93,12 +93,12 @@ class CourseCohortsSettings(models.Model):
...
@@ -93,12 +93,12 @@ class CourseCohortsSettings(models.Model):
@property
@property
def
cohorted_discussions
(
self
):
def
cohorted_discussions
(
self
):
"""Json
fi
y the cohorted_discussions"""
"""Json
if
y the cohorted_discussions"""
return
json
.
loads
(
self
.
_cohorted_discussions
)
return
json
.
loads
(
self
.
_cohorted_discussions
)
@cohorted_discussions.setter
@cohorted_discussions.setter
def
cohorted_discussions
(
self
,
value
):
def
cohorted_discussions
(
self
,
value
):
"""Un
Jsonfi
y the cohorted_discussions"""
"""Un
-Jsonif
y the cohorted_discussions"""
self
.
_cohorted_discussions
=
json
.
dumps
(
value
)
self
.
_cohorted_discussions
=
json
.
dumps
(
value
)
...
...
openedx/core/djangoapps/course_groups/tests/test_cohorts.py
View file @
70efd284
...
@@ -716,6 +716,29 @@ class TestCohorts(ModuleStoreTestCase):
...
@@ -716,6 +716,29 @@ class TestCohorts(ModuleStoreTestCase):
self
.
assertEqual
(
course_cohort_settings
.
cohorted_discussions
,
[
'topic a id'
,
'topic b id'
])
self
.
assertEqual
(
course_cohort_settings
.
cohorted_discussions
,
[
'topic a id'
,
'topic b id'
])
self
.
assertFalse
(
course_cohort_settings
.
always_cohort_inline_discussions
)
self
.
assertFalse
(
course_cohort_settings
.
always_cohort_inline_discussions
)
def
test_update_course_cohort_settings_with_invalid_data_type
(
self
):
"""
Test that cohorts.set_course_cohort_settings raises exception if fields have incorrect data type.
"""
course
=
modulestore
()
.
get_course
(
self
.
toy_course_key
)
CourseCohortSettingsFactory
(
course_id
=
course
.
id
)
exception_msg_tpl
=
"Incorrect field type for `{}`. Type must be `{}`"
fields
=
[
{
'name'
:
'is_cohorted'
,
'type'
:
bool
},
{
'name'
:
'always_cohort_inline_discussions'
,
'type'
:
bool
},
{
'name'
:
'cohorted_discussions'
,
'type'
:
list
}
]
for
field
in
fields
:
with
self
.
assertRaises
(
ValueError
)
as
value_error
:
cohorts
.
set_course_cohort_settings
(
course
.
id
,
**
{
field
[
'name'
]:
''
})
self
.
assertEqual
(
value_error
.
exception
.
message
,
exception_msg_tpl
.
format
(
field
[
'name'
],
field
[
'type'
]
.
__name__
)
)
class
TestCohortsAndPartitionGroups
(
ModuleStoreTestCase
):
class
TestCohortsAndPartitionGroups
(
ModuleStoreTestCase
):
"""
"""
...
...
openedx/core/djangoapps/course_groups/tests/test_views.py
View file @
70efd284
...
@@ -3,7 +3,6 @@ Tests for course group views
...
@@ -3,7 +3,6 @@ Tests for course group views
"""
"""
# pylint: disable=attribute-defined-outside-init
# pylint: disable=attribute-defined-outside-init
# pylint: disable=no-member
# pylint: disable=no-member
from
collections
import
namedtuple
import
json
import
json
from
collections
import
namedtuple
from
collections
import
namedtuple
...
@@ -15,7 +14,6 @@ from student.models import CourseEnrollment
...
@@ -15,7 +14,6 @@ from student.models import CourseEnrollment
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.django
import
modulestore
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
..models
import
CourseUserGroup
,
CourseCohort
from
..models
import
CourseUserGroup
,
CourseCohort
...
@@ -180,13 +178,26 @@ class CourseCohortSettingsHandlerTestCase(CohortViewsTestCase):
...
@@ -180,13 +178,26 @@ class CourseCohortSettingsHandlerTestCase(CohortViewsTestCase):
"""
"""
config_course_cohorts
(
self
.
course
,
[],
cohorted
=
True
)
config_course_cohorts
(
self
.
course
,
[],
cohorted
=
True
)
# Get the cohorts from the course. This will run the migrations.
# And due to migrations CourseCohortsSettings object will be created.
self
.
get_handler
(
self
.
course
)
response
=
self
.
put_handler
(
self
.
course
,
expected_response_code
=
400
,
handler
=
course_cohort_settings_handler
)
response
=
self
.
put_handler
(
self
.
course
,
expected_response_code
=
400
,
handler
=
course_cohort_settings_handler
)
self
.
assertEqual
(
"Bad Request"
,
response
.
get
(
"error"
))
self
.
assertEqual
(
"Bad Request"
,
response
.
get
(
"error"
))
def
test_update_settings_with_invalid_field_data_type
(
self
):
"""
Verify that course_cohort_settings_handler return HTTP 400 if field data type is incorrect.
"""
config_course_cohorts
(
self
.
course
,
[],
cohorted
=
True
)
response
=
self
.
put_handler
(
self
.
course
,
data
=
{
'is_cohorted'
:
''
},
expected_response_code
=
400
,
handler
=
course_cohort_settings_handler
)
self
.
assertEqual
(
"Incorrect field type for `{}`. Type must be `{}`"
.
format
(
'is_cohorted'
,
bool
.
__name__
),
response
.
get
(
"error"
)
)
class
CohortHandlerTestCase
(
CohortViewsTestCase
):
class
CohortHandlerTestCase
(
CohortViewsTestCase
):
"""
"""
...
...
openedx/core/djangoapps/course_groups/views.py
View file @
70efd284
...
@@ -112,7 +112,13 @@ def course_cohort_settings_handler(request, course_key_string):
...
@@ -112,7 +112,13 @@ def course_cohort_settings_handler(request, course_key_string):
if
is_cohorted
is
None
:
if
is_cohorted
is
None
:
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
return
JsonResponse
({
"error"
:
"Bad Request"
},
400
)
return
JsonResponse
({
"error"
:
"Bad Request"
},
400
)
cohort_settings
=
cohorts
.
set_course_cohort_settings
(
course_key
,
is_cohorted
=
is_cohorted
)
try
:
cohort_settings
=
cohorts
.
set_course_cohort_settings
(
course_key
,
is_cohorted
=
is_cohorted
)
except
ValueError
as
err
:
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
return
JsonResponse
({
"error"
:
unicode
(
err
)},
400
)
return
JsonResponse
(
_get_course_cohort_settings_representation
(
cohort_settings
))
return
JsonResponse
(
_get_course_cohort_settings_representation
(
cohort_settings
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment