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
c6b54aa6
Commit
c6b54aa6
authored
Sep 15, 2015
by
Bill DeRusha
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Readonly for enrollment end date/time on edX (for non-global-staff)
TNL-2694 Add accessibility aria-readonly attributes
parent
ac0d9264
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
164 additions
and
19 deletions
+164
-19
cms/djangoapps/contentstore/tests/test_course_settings.py
+116
-0
cms/djangoapps/contentstore/views/course.py
+5
-1
cms/static/sass/views/_settings.scss
+29
-12
cms/templates/settings.html
+14
-6
No files found.
cms/djangoapps/contentstore/tests/test_course_settings.py
View file @
c6b54aa6
...
@@ -16,6 +16,9 @@ from models.settings.course_details import (CourseDetails, CourseSettingsEncoder
...
@@ -16,6 +16,9 @@ from models.settings.course_details import (CourseDetails, CourseSettingsEncoder
from
models.settings.course_grading
import
CourseGradingModel
from
models.settings.course_grading
import
CourseGradingModel
from
contentstore.utils
import
reverse_course_url
,
reverse_usage_url
from
contentstore.utils
import
reverse_course_url
,
reverse_usage_url
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
student.roles
import
CourseInstructorRole
from
student.tests.factories
import
UserFactory
from
models.settings.course_metadata
import
CourseMetadata
from
models.settings.course_metadata
import
CourseMetadata
from
xmodule.fields
import
Date
from
xmodule.fields
import
Date
...
@@ -1106,3 +1109,116 @@ class CourseGraderUpdatesTest(CourseTestCase):
...
@@ -1106,3 +1109,116 @@ class CourseGraderUpdatesTest(CourseTestCase):
self
.
assertEqual
(
obj
,
grader
)
self
.
assertEqual
(
obj
,
grader
)
current_graders
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
.
graders
current_graders
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
.
graders
self
.
assertEqual
(
len
(
self
.
starting_graders
)
+
1
,
len
(
current_graders
))
self
.
assertEqual
(
len
(
self
.
starting_graders
)
+
1
,
len
(
current_graders
))
class
CourseEnrollmentEndFieldTest
(
CourseTestCase
):
"""
Base class to test the enrollment end fields in the course settings details view in Studio
when using marketing site flag and global vs non-global staff to access the page.
"""
NOT_EDITABLE_HELPER_MESSAGE
=
"Contact your edX Partner Manager to update these settings."
NOT_EDITABLE_DATE_WRAPPER
=
"<div class=
\"
field date is-not-editable
\"
id=
\"
field-enrollment-end-date
\"
>"
NOT_EDITABLE_TIME_WRAPPER
=
"<div class=
\"
field time is-not-editable
\"
id=
\"
field-enrollment-end-time
\"
>"
NOT_EDITABLE_DATE_FIELD
=
"<input type=
\"
text
\"
class=
\"
end-date date end
\"
\
id=
\"
course-enrollment-end-date
\"
placeholder=
\"
MM/DD/YYYY
\"
autocomplete=
\"
off
\"
readonly aria-readonly=
\"
true
\"
/>"
NOT_EDITABLE_TIME_FIELD
=
"<input type=
\"
text
\"
class=
\"
time end
\"
id=
\"
course-enrollment-end-time
\"
\
value=
\"\"
placeholder=
\"
HH:MM
\"
autocomplete=
\"
off
\"
readonly aria-readonly=
\"
true
\"
/>"
EDITABLE_DATE_WRAPPER
=
"<div class=
\"
field date
\"
id=
\"
field-enrollment-end-date
\"
>"
EDITABLE_TIME_WRAPPER
=
"<div class=
\"
field time
\"
id=
\"
field-enrollment-end-time
\"
>"
EDITABLE_DATE_FIELD
=
"<input type=
\"
text
\"
class=
\"
end-date date end
\"
\
id=
\"
course-enrollment-end-date
\"
placeholder=
\"
MM/DD/YYYY
\"
autocomplete=
\"
off
\"
/>"
EDITABLE_TIME_FIELD
=
"<input type=
\"
text
\"
class=
\"
time end
\"
\
id=
\"
course-enrollment-end-time
\"
value=
\"\"
placeholder=
\"
HH:MM
\"
autocomplete=
\"
off
\"
/>"
EDITABLE_ELEMENTS
=
[
EDITABLE_DATE_WRAPPER
,
EDITABLE_TIME_WRAPPER
,
EDITABLE_DATE_FIELD
,
EDITABLE_TIME_FIELD
,
]
NOT_EDITABLE_ELEMENTS
=
[
NOT_EDITABLE_HELPER_MESSAGE
,
NOT_EDITABLE_DATE_WRAPPER
,
NOT_EDITABLE_TIME_WRAPPER
,
NOT_EDITABLE_DATE_FIELD
,
NOT_EDITABLE_TIME_FIELD
,
]
def
setUp
(
self
):
""" Initialize course used to test enrollment fields. """
super
(
CourseEnrollmentEndFieldTest
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
(
org
=
'edX'
,
number
=
'dummy'
,
display_name
=
'Marketing Site Course'
)
self
.
course_details_url
=
reverse_course_url
(
'settings_handler'
,
unicode
(
self
.
course
.
id
))
def
_get_course_details_response
(
self
,
global_staff
):
""" Return the course details page as either global or non-global staff"""
user
=
UserFactory
(
is_staff
=
global_staff
)
CourseInstructorRole
(
self
.
course
.
id
)
.
add_users
(
user
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
'test'
)
return
self
.
client
.
get_html
(
self
.
course_details_url
)
def
_verify_editable
(
self
,
response
):
""" Verify that the response has expected editable fields.
Assert that all editable field content exists and no
uneditable field content exists for enrollment end fields.
"""
self
.
assertEqual
(
response
.
status_code
,
200
)
for
element
in
self
.
NOT_EDITABLE_ELEMENTS
:
self
.
assertNotContains
(
response
,
element
)
for
element
in
self
.
EDITABLE_ELEMENTS
:
self
.
assertContains
(
response
,
element
)
def
_verify_not_editable
(
self
,
response
):
""" Verify that the response has expected non-editable fields.
Assert that all uneditable field content exists and no
editable field content exists for enrollment end fields.
"""
self
.
assertEqual
(
response
.
status_code
,
200
)
for
element
in
self
.
NOT_EDITABLE_ELEMENTS
:
self
.
assertContains
(
response
,
element
)
for
element
in
self
.
EDITABLE_ELEMENTS
:
self
.
assertNotContains
(
response
,
element
)
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_MKTG_SITE'
:
False
})
def
test_course_details_with_disabled_setting_global_staff
(
self
):
""" Test that user enrollment end date is editable in response.
Feature flag 'ENABLE_MKTG_SITE' is not enabled.
User is global staff.
"""
self
.
_verify_editable
(
self
.
_get_course_details_response
(
True
))
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_MKTG_SITE'
:
False
})
def
test_course_details_with_disabled_setting_non_global_staff
(
self
):
""" Test that user enrollment end date is editable in response.
Feature flag 'ENABLE_MKTG_SITE' is not enabled.
User is non-global staff.
"""
self
.
_verify_editable
(
self
.
_get_course_details_response
(
False
))
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_MKTG_SITE'
:
True
})
def
test_course_details_with_enabled_setting_global_staff
(
self
):
""" Test that user enrollment end date is editable in response.
Feature flag 'ENABLE_MKTG_SITE' is enabled.
User is global staff.
"""
self
.
_verify_editable
(
self
.
_get_course_details_response
(
True
))
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_MKTG_SITE'
:
True
})
def
test_course_details_with_enabled_setting_non_global_staff
(
self
):
""" Test that user enrollment end date is not editable in response.
Feature flag 'ENABLE_MKTG_SITE' is enabled.
User is non-global staff.
"""
self
.
_verify_not_editable
(
self
.
_get_course_details_response
(
False
))
cms/djangoapps/contentstore/views/course.py
View file @
c6b54aa6
...
@@ -903,12 +903,15 @@ def settings_handler(request, course_key_string):
...
@@ -903,12 +903,15 @@ def settings_handler(request, course_key_string):
# see if the ORG of this course can be attributed to a 'Microsite'. In that case, the
# see if the ORG of this course can be attributed to a 'Microsite'. In that case, the
# course about page should be editable in Studio
# course about page should be editable in Studio
about_page_editable
=
not
microsite
.
get_value_for_org
(
marketing_site_enabled
=
microsite
.
get_value_for_org
(
course_module
.
location
.
org
,
course_module
.
location
.
org
,
'ENABLE_MKTG_SITE'
,
'ENABLE_MKTG_SITE'
,
settings
.
FEATURES
.
get
(
'ENABLE_MKTG_SITE'
,
False
)
settings
.
FEATURES
.
get
(
'ENABLE_MKTG_SITE'
,
False
)
)
)
about_page_editable
=
not
marketing_site_enabled
enrollment_end_editable
=
GlobalStaff
()
.
has_user
(
request
.
user
)
or
not
marketing_site_enabled
short_description_editable
=
settings
.
FEATURES
.
get
(
'EDITABLE_SHORT_DESCRIPTION'
,
True
)
short_description_editable
=
settings
.
FEATURES
.
get
(
'EDITABLE_SHORT_DESCRIPTION'
,
True
)
settings_context
=
{
settings_context
=
{
'context_course'
:
course_module
,
'context_course'
:
course_module
,
...
@@ -924,6 +927,7 @@ def settings_handler(request, course_key_string):
...
@@ -924,6 +927,7 @@ def settings_handler(request, course_key_string):
'credit_eligibility_enabled'
:
credit_eligibility_enabled
,
'credit_eligibility_enabled'
:
credit_eligibility_enabled
,
'is_credit_course'
:
False
,
'is_credit_course'
:
False
,
'show_min_grade_warning'
:
False
,
'show_min_grade_warning'
:
False
,
'enrollment_end_editable'
:
enrollment_end_editable
,
}
}
if
prerequisite_course_enabled
:
if
prerequisite_course_enabled
:
courses
,
in_process_course_actions
=
get_courses_accessible_to_user
(
request
)
courses
,
in_process_course_actions
=
get_courses_accessible_to_user
(
request
)
...
...
cms/static/sass/views/_settings.scss
View file @
c6b54aa6
...
@@ -62,6 +62,27 @@
...
@@ -62,6 +62,27 @@
margin-top
:
(
$baseline
);
margin-top
:
(
$baseline
);
}
}
// specific fields - settings details
.settings-details
{
// course details that should appear more like content than elements to change
.is-not-editable
{
label
{
}
input
,
textarea
{
@extend
%t-copy-lead1
;
@extend
%t-strong
;
box-shadow
:
none
;
border
:
none
;
background
:
none
;
margin
:
0
;
}
}
}
// in form - elements
// in form - elements
.group-settings
{
.group-settings
{
...
@@ -305,21 +326,10 @@
...
@@ -305,21 +326,10 @@
}
}
}
}
// course details that should appear more like content than elements to change
.is-not-editable
{
.field.is-not-editable
{
label
{
}
input
,
textarea
{
input
,
textarea
{
@extend
%t-copy-lead1
;
@extend
%t-strong
;
box-shadow
:
none
;
border
:
none
;
background
:
none
;
padding
:
0
;
padding
:
0
;
margin
:
0
;
}
}
}
}
...
@@ -438,6 +448,13 @@
...
@@ -438,6 +448,13 @@
padding-bottom
:
0
;
padding-bottom
:
0
;
}
}
.is-not-editable
{
input
,
textarea
{
padding
:
10px
;
}
}
.field
{
.field
{
@include
float
(
left
);
@include
float
(
left
);
width
:
flex-grid
(
3
,
9
);
width
:
flex-grid
(
3
,
9
);
...
...
cms/templates/settings.html
View file @
c6b54aa6
...
@@ -220,17 +220,25 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
...
@@ -220,17 +220,25 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
<span
class=
"tip tip-stacked timezone"
>
${_("(UTC)")}
</span>
<span
class=
"tip tip-stacked timezone"
>
${_("(UTC)")}
</span>
</div>
</div>
</li>
</li>
<
%
enrollment_end_readonly =
"readonly aria-readonly=\"
true
\""
if
not
enrollment_end_editable
else
""
enrollment_end_editable_class =
"is-not-editable"
if
not
enrollment_end_editable
else
""
%
>
<li
class=
"field-group field-group-enrollment-end"
id=
"enrollment-end"
>
<li
class=
"field-group field-group-enrollment-end"
id=
"enrollment-end"
>
<div
class=
"field date"
id=
"field-enrollment-end-date"
>
<div
class=
"field date
${enrollment_end_editable_class}
"
id=
"field-enrollment-end-date"
>
<label
for=
"course-enrollment-end-date"
>
${_("Enrollment End Date")}
</label>
<label
for=
"course-enrollment-end-date"
>
${_("Enrollment End Date")}
</label>
<input
type=
"text"
class=
"end-date date end"
id=
"course-enrollment-end-date"
placeholder=
"MM/DD/YYYY"
autocomplete=
"off"
/>
<input
type=
"text"
class=
"end-date date end"
id=
"course-enrollment-end-date"
placeholder=
"MM/DD/YYYY"
autocomplete=
"off"
${
enrollment_end_readonly
}
/>
<span
class=
"tip tip-stacked"
>
${_("Last day students can enroll")}
</span>
<span
class=
"tip tip-stacked"
>
${_("Last day students can enroll.")}
% if not enrollment_end_editable:
${_("Contact your edX Partner Manager to update these settings.")}
% endif
</span>
</div>
</div>
<div
class=
"field time"
id=
"field-enrollment-end-time"
>
<div
class=
"field time
${enrollment_end_editable_class}
"
id=
"field-enrollment-end-time"
>
<label
for=
"course-enrollment-end-time"
>
${_("Enrollment End Time")}
</label>
<label
for=
"course-enrollment-end-time"
>
${_("Enrollment End Time")}
</label>
<input
type=
"text"
class=
"time end"
id=
"course-enrollment-end-time"
value=
""
placeholder=
"HH:MM"
autocomplete=
"off"
/>
<input
type=
"text"
class=
"time end"
id=
"course-enrollment-end-time"
value=
""
placeholder=
"HH:MM"
autocomplete=
"off"
${
enrollment_end_readonly
}
/>
<span
class=
"tip tip-stacked timezone"
>
${_("(UTC)")}
</span>
<span
class=
"tip tip-stacked timezone"
>
${_("(UTC)")}
</span>
</div>
</div>
</li>
</li>
...
...
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