Commit 0aa87b8a by clrux Committed by GitHub

Merge pull request #12452 from edx/clrux/ac-414

AC-414 adding headings as first child to sections
parents b4d330bc 257903fe
......@@ -23,7 +23,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the membership tab and returns the MembershipSection
"""
self.q(css='a[data-section=membership]').first.click()
self.q(css='[data-section=membership]').first.click()
membership_section = MembershipPage(self.browser)
membership_section.wait_for_page()
return membership_section
......@@ -32,7 +32,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the cohort management tab and returns the CohortManagementSection
"""
self.q(css='a[data-section=cohort_management]').first.click()
self.q(css='[data-section=cohort_management]').first.click()
cohort_management_section = CohortManagementSection(self.browser)
# The first time cohort management is selected, an ajax call is made.
cohort_management_section.wait_for_ajax()
......@@ -43,7 +43,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the data download tab and returns a DataDownloadPage.
"""
self.q(css='a[data-section=data_download]').first.click()
self.q(css='[data-section=data_download]').first.click()
data_download_section = DataDownloadPage(self.browser)
data_download_section.wait_for_page()
return data_download_section
......@@ -52,7 +52,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the student admin tab and returns the MembershipSection
"""
self.q(css='a[data-section=student_admin]').first.click()
self.q(css='[data-section=student_admin]').first.click()
student_admin_section = StudentAdminPage(self.browser)
student_admin_section.wait_for_page()
return student_admin_section
......@@ -61,7 +61,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the certificates tab and returns the CertificatesSection
"""
self.q(css='a[data-section=certificates]').first.click()
self.q(css='[data-section=certificates]').first.click()
certificates_section = CertificatesPage(self.browser)
certificates_section.wait_for_page()
return certificates_section
......@@ -70,7 +70,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the timed exam tab and returns the Special Exams Section
"""
self.q(css='a[data-section=special_exams]').first.click()
self.q(css='[data-section=special_exams]').first.click()
timed_exam_section = SpecialExamsPage(self.browser)
timed_exam_section.wait_for_page()
return timed_exam_section
......@@ -79,7 +79,7 @@ class InstructorDashboardPage(CoursePage):
"""
Selects the email tab and returns the bulk email section
"""
self.q(css='a[data-section=send_email]').first.click()
self.q(css='[data-section=send_email]').first.click()
email_section = BulkEmailPage(self.browser)
email_section.wait_for_page()
return email_section
......@@ -115,7 +115,7 @@ class BulkEmailPage(PageObject):
url = None
def is_browser_on_page(self):
return self.q(css='a[data-section=send_email].active-section').present
return self.q(css='[data-section=send_email].active-section').present
def _bounded_selector(self, selector):
"""
......@@ -169,7 +169,7 @@ class MembershipPage(PageObject):
url = None
def is_browser_on_page(self):
return self.q(css='a[data-section=membership].active-section').present
return self.q(css='[data-section=membership].active-section').present
def select_auto_enroll_section(self):
"""
......@@ -185,7 +185,7 @@ class SpecialExamsPage(PageObject):
url = None
def is_browser_on_page(self):
return self.q(css='a[data-section=special_exams].active-section').present
return self.q(css='[data-section=special_exams].active-section').present
def select_allowance_section(self):
"""
......@@ -954,7 +954,7 @@ class DataDownloadPage(PageObject):
url = None
def is_browser_on_page(self):
return self.q(css='a[data-section=data_download].active-section').present
return self.q(css='[data-section=data_download].active-section').present
@property
def generate_student_report_button(self):
......@@ -1017,7 +1017,7 @@ class StudentAdminPage(PageObject):
"""
Confirms student admin section is present
"""
return self.q(css='a[data-section=student_admin].active-section').present
return self.q(css='[data-section=student_admin].active-section').present
@property
def student_email_input(self):
......@@ -1177,7 +1177,7 @@ class CertificatesPage(PageObject):
self.wait_for_page()
def is_browser_on_page(self):
return self.q(css='a[data-section=certificates].active-section').present
return self.q(css='[data-section=certificates].active-section').present
def get_selector(self, css_selector):
"""
......
......@@ -208,7 +208,7 @@ class DiscussionHomePageTest(UniqueCourseTest):
def test_page_accessibility(self):
self.page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'color-contrast', # TNL-4635
'link-href', # TNL-4636
'icon-aria-hidden', # TNL-4637
......@@ -348,7 +348,7 @@ class DiscussionTabMultipleThreadTest(BaseDiscussionTestCase):
def test_page_accessibility(self):
self.thread_page_1.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4638
'color-contrast', # TNL-4639
'link-href', # TNL-4640
......@@ -360,7 +360,7 @@ class DiscussionTabMultipleThreadTest(BaseDiscussionTestCase):
self.thread_page_2.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4638
'color-contrast', # TNL-4639
'link-href', # TNL-4640
......@@ -424,7 +424,7 @@ class DiscussionOpenClosedThreadTest(BaseDiscussionTestCase):
page = self.setup_openclosed_thread_page()
page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4643
'color-contrast', # TNL-4644
'link-href', # TNL-4640
......@@ -436,7 +436,7 @@ class DiscussionOpenClosedThreadTest(BaseDiscussionTestCase):
page = self.setup_openclosed_thread_page(True)
page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4643
'color-contrast', # TNL-4644
'link-href', # TNL-4640
......@@ -725,7 +725,7 @@ class DiscussionResponseEditTest(BaseDiscussionTestCase):
page = self.create_single_thread_page("response_edit_test_thread")
page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4638
'color-contrast', # TNL-4644
'link-href', # TNL-4640
......@@ -827,7 +827,7 @@ class DiscussionCommentEditTest(BaseDiscussionTestCase):
page.visit()
page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr-value', # TNL-4643
'color-contrast', # TNL-4644
'link-href', # TNL-4640
......@@ -1202,7 +1202,7 @@ class DiscussionSearchAlertTest(UniqueCourseTest):
def test_page_accessibility(self):
self.page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'color-contrast', # TNL-4639
'link-href', # TNL-4640
'icon-aria-hidden', # TNL-4641
......
......@@ -481,7 +481,7 @@ class AccountSettingsA11yTest(AccountSettingsTestMixin, WebAppTest):
self.visit_account_settings_page()
self.account_settings_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'link-href', # TODO: AC-233
],
})
......
......@@ -779,7 +779,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest):
profile_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'link-href', # TODO: AC-231
],
})
......@@ -807,7 +807,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest):
profile_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'link-href', # TODO: AC-231
],
})
......@@ -824,7 +824,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest):
profile_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'link-href', # TODO: AC-231
],
})
......
......@@ -1349,7 +1349,7 @@ class CourseInfoA11yTest(UniqueCourseTest):
self.course_info_page.visit()
self.course_info_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.course_info_page.a11y_audit.check_for_accessibility_errors()
......@@ -621,7 +621,7 @@ class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin):
include=['div.sequence-nav'])
self.courseware_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
],
})
self.courseware_page.a11y_audit.check_for_accessibility_errors()
......
......@@ -234,7 +234,7 @@ class LmsDashboardA11yTest(BaseLmsDashboardTest):
self.assertEqual(len(course_listings), 1)
self.dashboard_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.dashboard_page.a11y_audit.check_for_accessibility_errors()
......@@ -46,6 +46,27 @@ class BaseInstructorDashboardTest(EventsTestMixin, UniqueCourseTest):
return instructor_dashboard_page
@attr('a11y')
class LMSInstructorDashboardA11yTest(BaseInstructorDashboardTest):
"""
Instructor dashboard base accessibility test.
"""
def setUp(self):
super(LMSInstructorDashboardA11yTest, self).setUp()
self.course_fixture = CourseFixture(**self.course_info).install()
self.log_in_as_instructor()
self.instructor_dashboard_page = self.visit_instructor_dashboard()
def test_instructor_dashboard_a11y(self):
self.instructor_dashboard_page.a11y_audit.config.set_rules({
"ignore": [
'link-href', # TODO: AC-491
'data-table', # TODO: AC-491
]
})
self.instructor_dashboard_page.a11y_audit.check_for_accessibility_errors()
@ddt.ddt
class BulkEmailTest(BaseInstructorDashboardTest):
"""
......@@ -64,6 +85,23 @@ class BulkEmailTest(BaseInstructorDashboardTest):
self.send_email_page.send_message(recipient)
self.send_email_page.verify_message_queued_successfully()
@attr('a11y')
def test_bulk_email_a11y(self):
"""
Bulk email accessibility tests
"""
self.send_email_page.a11y_audit.config.set_scope([
'#section-send-email'
])
self.send_email_page.a11y_audit.config.set_rules({
"ignore": [
'button-name', # TODO: AC-491
'list', # TODO: AC-491,
'color-contrast', # TODO: AC-491
]
})
self.send_email_page.a11y_audit.check_for_accessibility_errors()
@attr('shard_7')
class AutoEnrollmentWithCSVTest(BaseInstructorDashboardTest):
......@@ -172,6 +210,16 @@ class AutoEnrollmentWithCSVTest(BaseInstructorDashboardTest):
self.assertTrue(self.auto_enroll_section.is_notification_displayed(section_type=self.auto_enroll_section.NOTIFICATION_ERROR))
self.assertEqual(self.auto_enroll_section.first_notification_message(section_type=self.auto_enroll_section.NOTIFICATION_ERROR), "Make sure that the file you upload is in CSV format with no extraneous characters or rows.")
@attr('a11y')
def test_auto_enroll_csv_a11y(self):
"""
Auto-enrollment with CSV accessibility tests
"""
self.auto_enroll_section.a11y_audit.config.set_scope([
'#member-list-widget-template'
])
self.auto_enroll_section.a11y_audit.check_for_accessibility_errors()
@attr('shard_7')
class ProctoredExamsTest(BaseInstructorDashboardTest):
......@@ -668,6 +716,16 @@ class DataDownloadsTest(BaseInstructorDashboardTest):
self.data_download_section.wait_for_available_report()
self.verify_report_download(report_name)
@attr('a11y')
def test_data_download_a11y(self):
"""
Data download page accessibility tests
"""
self.data_download_section.a11y_audit.config.set_scope([
'.data-download-container'
])
self.data_download_section.a11y_audit.check_for_accessibility_errors()
@attr('shard_7')
@ddt.ddt
......@@ -956,6 +1014,26 @@ class CertificatesTest(BaseInstructorDashboardTest):
self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertIn(expected_notes, self.certificates_section.last_certificate_exception.text)
@attr('a11y')
def test_certificates_a11y(self):
"""
Certificates page accessibility tests
"""
self.certificates_section.a11y_audit.config.set_scope([
'.certificates-wrapper'
])
self.certificates_section.a11y_audit.config.set_rules({
"ignore": [
'aria-valid-attr-value', # TODO: AC-491
'checkboxgroup', # TODO: AC-491
'color-contrast', # TODO: AC-491
'duplicate-id', # TODO: AC-491
'label', # TODO: AC-491
'radiogroup', # TODO: AC-491
]
})
self.certificates_section.a11y_audit.check_for_accessibility_errors()
@attr('shard_7')
class CertificateInvalidationTest(BaseInstructorDashboardTest):
......@@ -1154,3 +1232,24 @@ class CertificateInvalidationTest(BaseInstructorDashboardTest):
u"{user} is not enrolled in this course. Please check your spelling and retry.".format(user=new_user),
self.certificates_section.certificate_invalidation_message.text
)
@attr('a11y')
def test_invalidate_certificates_a11y(self):
"""
Certificate invalidation accessibility tests
"""
self.certificates_section.a11y_audit.config.set_scope([
'.certificates-wrapper'
])
self.certificates_section.a11y_audit.config.set_rules({
"ignore": [
'data-table', # TODO: AC-491
'aria-valid-attr-value', # TODO: AC-491
'checkboxgroup', # TODO: AC-491
'color-contrast', # TODO: AC-491
'duplicate-id', # TODO: AC-491
'label', # TODO: AC-491
'radiogroup', # TODO: AC-491
]
})
self.certificates_section.a11y_audit.check_for_accessibility_errors()
......@@ -247,14 +247,14 @@ class ProblemTypeTestMixin(object):
self.problem_page.a11y_audit.config.set_rules({
"ignore": [
'aria-allowed-attr', # TODO: wcag2aa
'aria-valid-attr', # TODO: wcag2aa
'aria-roles', # TODO: wcag2aa
'checkboxgroup', # TODO: wcag2aa
'radiogroup', # TODO: wcag2aa
'color-contrast', # TODO: wcag2aa
'section', # TODO: wcag2aa
'label', # TODO: wcag2aa
'aria-allowed-attr', # TODO: AC-491
'aria-valid-attr', # TODO: AC-491
'aria-roles', # TODO: AC-491
'checkboxgroup', # TODO: AC-491
'radiogroup', # TODO: AC-491
'color-contrast', # TODO: AC-491
'section', # TODO: AC-491
'label', # TODO: AC-491
]
})
......@@ -335,7 +335,7 @@ class CheckboxProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(CheckboxProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-allowed-attr', # TODO: AC-251
'aria-valid-attr', # TODO: AC-251
'aria-roles', # TODO: AC-251
......@@ -381,7 +381,7 @@ class MultipleChoiceProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(MultipleChoiceProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr', # TODO: AC-251
'radiogroup', # TODO: AC-251
]
......@@ -425,7 +425,7 @@ class RadioProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(RadioProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'aria-valid-attr', # TODO: AC-292
'radiogroup', # TODO: AC-292
]
......@@ -463,7 +463,7 @@ class DropDownProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(DropDownProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-291
]
})
......@@ -506,7 +506,7 @@ class StringProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(StringProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-290
]
})
......@@ -548,7 +548,7 @@ class NumericalProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(NumericalProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-289
]
})
......@@ -592,7 +592,7 @@ class FormulaProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(FormulaProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-288
]
})
......@@ -643,7 +643,7 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(ScriptProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-287
]
})
......@@ -693,7 +693,7 @@ class CodeProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(CodeProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'color-contrast', # TODO: AC-286
'label', # TODO: AC-286
]
......@@ -802,7 +802,7 @@ class RadioTextProblemTypeTest(ChoiceTextProbelmTypeTestBase, ProblemTypeTestMix
super(RadioTextProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-285
'radiogroup', # TODO: AC-285
]
......@@ -835,7 +835,7 @@ class CheckboxTextProblemTypeTest(ChoiceTextProbelmTypeTestBase, ProblemTypeTest
super(CheckboxTextProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-284
'checkboxgroup', # TODO: AC-284
]
......@@ -899,7 +899,7 @@ class SymbolicProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
super(SymbolicProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'label', # TODO: AC-294
]
})
......
......@@ -125,7 +125,7 @@ class ProgramListingPageA11yTest(ProgramPageBase):
self.listing_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.listing_page.a11y_audit.check_for_accessibility_errors()
......@@ -140,7 +140,7 @@ class ProgramListingPageA11yTest(ProgramPageBase):
self.listing_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.listing_page.a11y_audit.check_for_accessibility_errors()
......@@ -164,7 +164,7 @@ class ProgramDetailsPageA11yTest(ProgramPageBase):
self.details_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.details_page.a11y_audit.check_for_accessibility_errors()
......@@ -656,7 +656,7 @@ class StudioLibraryA11yTest(StudioLibraryTest):
# we will ignore this error in the test until we fix them.
lib_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'color-contrast', # TODO: AC-225
'link-href', # TODO: AC-226
'nav-aria-label', # TODO: AC-227
......
......@@ -503,7 +503,7 @@ class StudioSettingsA11yTest(StudioCourseTest):
# we will ignore this error in the test until we fix them.
self.settings_page.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
'color-contrast', # TODO: AC-225
'link-href', # TODO: AC-226
'nav-aria-label', # TODO: AC-227
......@@ -582,7 +582,7 @@ class StudioSubsectionSettingsA11yTest(StudioCourseTest):
)
self.course_outline.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.course_outline.a11y_audit.check_for_accessibility_errors()
......
......@@ -360,7 +360,7 @@ class CMSVideoA11yTest(CMSVideoBaseTest):
)
self.outline.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.outline.a11y_audit.check_for_accessibility_errors()
......@@ -1274,7 +1274,7 @@ class LMSVideoModuleA11yTest(VideoBaseTest):
)
self.video.a11y_audit.config.set_rules({
"ignore": [
'section', # TODO: wcag2aa
'section', # TODO: AC-491
]
})
self.video.a11y_audit.check_for_accessibility_errors()
......@@ -137,7 +137,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
"""
response = self.client.get(self.url)
# no enrollment information should be visible
self.assertFalse('<h2>Enrollment Information</h2>' in response.content)
self.assertNotIn('<h3 class="hd hd-3">Enrollment Information</h3>', response.content)
@patch.dict(settings.FEATURES, {'DISPLAY_ANALYTICS_ENROLLMENTS': True})
@override_settings(ANALYTICS_DASHBOARD_URL='')
......@@ -148,7 +148,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
response = self.client.get(self.url)
# enrollment information visible
self.assertTrue('<h2>Enrollment Information</h2>' in response.content)
self.assertIn('<h3 class="hd hd-3">Enrollment Information</h3>', response.content)
self.assertTrue('<td>Verified</td>' in response.content)
self.assertTrue('<td>Audit</td>' in response.content)
self.assertTrue('<td>Honor</td>' in response.content)
......
......@@ -422,8 +422,10 @@ def _section_course_info(course, access):
section_data['enrollment_count'] = CourseEnrollment.objects.enrollment_counts(course_key)
if settings.ANALYTICS_DASHBOARD_URL:
# dashboard_link is already made safe in _get_dashboard_link
dashboard_link = _get_dashboard_link(course_key)
message = _("Enrollment data is now available in {dashboard_link}.").format(dashboard_link=dashboard_link)
# so we can use Text() here so it's not double-escaped and rendering HTML on the front-end
message = Text(_("Enrollment data is now available in {dashboard_link}.")).format(dashboard_link=dashboard_link)
section_data['enrollment_message'] = message
if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'):
......
......@@ -13,10 +13,10 @@ $(function() {
$.cookie('saved_index', active);
},
animate: 400,
header: "> div.wrap >h2",
header: "> .wrap > .hd",
icons: icons,
active: isNaN(parseInt($.cookie('saved_index'))) ? 0 : parseInt($.cookie('saved_index')),
collapsible: true
}
);
});
\ No newline at end of file
});
......@@ -4,6 +4,7 @@
// About: Sass compile for the LMS Courseware Elements that are shared between LTR and RTL UI. Configuration and vendor specific imports happen before this shared set of imports are compiled in the lms-course-*.scss files.
@import 'base/base';
@import 'base/headings';
@import 'base/extends';
@import 'base/animations';
@import 'shared/tooltips';
......@@ -66,6 +67,3 @@
// responsive
@import 'base/layouts'; // temporary spot for responsive course
// xmodule
@import 'xmodule/headings';
......@@ -3,9 +3,9 @@
* The UXPL isn't available retroactively, so this shims
* the headings from the UXPL with what we're using in
* the platform to better sync things up in the meantime.
* It is scoped to #seq_content, specifically for xblock.
* These are available to entire LMS.
*
* Once the UXPl is fitted retroactively, this can be removed.
* Once the UXPL is fitted retroactively (if ever then), this can be removed.
*/
$headings-count: 8;
......@@ -88,29 +88,33 @@ $headings-base-color: $gray-d2;
letter-spacing: 1px;
}
.xblock .xblock {
// let's make these classnames available to the entire LMS!
.hd-1,
.hd-2,
.hd-3,
.hd-4,
.hd-5,
.hd-6,
.hd-7,
.hd-8 {
@extend %reset-headings;
}
.hd-1,
.hd-2,
.hd-3,
.hd-4,
.hd-5,
.hd-6,
.hd-7,
.hd-8 {
@extend %reset-headings;
// ----------------------------
// #CANNED
// ----------------------------
// canned heading classes
@for $i from 1 through $headings-count {
.hd-#{$i} {
@extend %hd-#{$i};
}
}
// H3 was problematic in xblocks, we so we'll keep it as it was
// ----------------------------
// #CANNED
// ----------------------------
// canned heading classes
@for $i from 1 through $headings-count {
.hd-#{$i} {
@extend %hd-#{$i};
}
}
.xblock .xblock {
h3 {
@extend %hd-2;
......
......@@ -406,11 +406,6 @@
// view - bulk email
// --------------------
.instructor-dashboard-wrapper-2 section.idash-section#send_email {
h2 {
// override forced uppercase
text-transform: none;
}
// form fields
.list-fields {
list-style: none;
......
......@@ -23,8 +23,8 @@ from openedx.core.djangolib.js_utils import (
<section class="container">
<div class="instructor-dashboard-wrapper-2">
<main id="main" aria-label="Content" tabindex="-1">
<section class="instructor-dashboard-content-2" id="ccx-coach-dashboard-content">
<h1>${_("CCX Coach Dashboard")}</h1>
<section class="instructor-dashboard-content-2" id="ccx-coach-dashboard-content" aria-labelledby="header-ccx-dashboard">
<h2 class="hd hd-2" id="header-ccx-dashboard">${_("CCX Coach Dashboard")}</h2>
%if not ccx:
% if messages:
......@@ -38,7 +38,7 @@ from openedx.core.djangolib.js_utils import (
% endfor
</ul>
% endif
<section>
<div>
<p class="request-response-error" id="ccx-create-message"></p>
<form action="${create_ccx_url}" class="ccx-form" method="POST" onsubmit="return validateForm(this)">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"/>
......@@ -50,7 +50,7 @@ from openedx.core.djangolib.js_utils import (
<button id="create-ccx" type="submit">${_('Create a new Custom Course for edX')}</button>
</div>
</form>
</section>
</div>
%endif
%if ccx:
......@@ -68,16 +68,16 @@ from openedx.core.djangolib.js_utils import (
<a href="#" data-section="grading_policy">${_("Grading Policy")}</a>
</li>
</ul>
<section id="membership" class="idash-section">
<section id="membership" class="idash-section" aria-label="${_('Batch Enrollment')}">
<%include file="enrollment.html" args="" />
</section>
<section id="schedule" class="idash-section">
<section id="schedule" class="idash-section" aria-label="${_('Schedule')}">
<%include file="schedule.html" args="" />
</section>
<section id="student_admin" class="idash-section">
<section id="student_admin" class="idash-section" aria-label="${_('Student Grades')}">
<%include file="student_admin.html" args="" />
</section>
<section id="grading_policy" class="idash-section">
<section id="grading_policy" class="idash-section" aria-label="${_('Grading Policy')}">
<%include file="grading_policy.html" args="" />
</section>
%endif
......
......@@ -4,10 +4,10 @@ from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML, Text
%>
<h2 class="hd hd-2">${_("Batch Enrollment")}</h2>
<div class="batch-enrollment" style="float:left;width:50%">
<form method="POST" action="ccx_invite">
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
<h2> ${_("Batch Enrollment")} </h2>
<label for="student-ids" class="sr">${_("Email Addresses/Usernames")}</label>
<p id="label_student_ids" class="text-helper">
${_("Enter email addresses and/or usernames separated by new lines or commas.")}
......
<%page expression_filter="h"/>
<%! from django.utils.translation import ugettext as _ %>
<h2 class="hd hd-2">${_("Grading Policy")}</h2>
<div id="warn-coach" class="wrapper-msg urgency-high warning">
<div class="msg">
<span class="msg-icon fa fa-warning" aria-hidden="true"></span>
......@@ -14,8 +16,6 @@
</div>
</div>
<h2>${_("Grading Policy")}</h2>
<form action="${grading_policy_url}" method="POST">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"/>
<textarea cols="80" style="height: 500px;"
......
......@@ -30,12 +30,13 @@ from openedx.core.djangolib.js_utils import (
</script>
%endfor
<h2 class="hd hd-2">${_('Schedule')}</h2>
<div class="ccx-schedule-container">
<div id="ccx-schedule"></div>
<div id="new-ccx-schedule"></div>
</div>
<section id="enter-date-modal" class="modal"
<div id="enter-date-modal" class="modal"
tabindex="-1" role="dialog" aria-labelledby="ccx_schedule_set_date_heading">
<div class="inner-wrapper">
<button class="close-modal">
......@@ -59,12 +60,12 @@ from openedx.core.djangolib.js_utils import (
</div>
</form>
</div>
</section>
</div>
<div class="ccx-schedule-sidebar">
<div class="ccx-sidebar-panel" id="dirty-schedule" tabindex="-1" role="region"
aria-labelledby="ccx_schedule_save_changes_heading">
<h2 id="ccx_schedule_save_changes_heading">${_('Save changes')}</h2>
<h3 class="hd hd-3" id="ccx_schedule_save_changes_heading">${_('Save changes')}</h3>
<form>
<p id="message_save" class="text-helper">${_("You have unsaved changes.")}</p>
<div class="field">
......@@ -74,12 +75,12 @@ from openedx.core.djangolib.js_utils import (
</form>
</div>
<div class="ccx-sidebar-panel" id="ajax-error" tabindex="-1" role="region" aria-labelledby="ccx_schedule_error_message">
<h2>${_('Error')}</h2>
<h3 class="hd hd-2">${_('Error')}</h3>
<p id="ccx_schedule_error_message" class="text-helper">${_("There was an error saving changes.")}</p>
</div>
<div class="ccx-sidebar-panel" aria-labelledby="ccx_schedule_unit"
id="ccx_schedule_unit_panel" role="region">
<h2 id="ccx_schedule_unit">${_('Schedule a Unit')}</h2>
<h3 class="hd hd-3" id="ccx_schedule_unit">${_('Schedule a Unit')}</h3>
<form role="form" id="add-unit" name="add-unit" class="ccx-form">
<div class="field">
<label for="ccx_chapter" class="form-label"><b>${_('Section')}</b></label>
......
<%page expression_filter="h"/>
<%! from django.utils.translation import ugettext as _ %>
<section>
<h2>${_('Student Grades')}</h2>
<p>
<a href="${gradebook_url}">${_('View gradebook')}</a>
</p>
<p>
<a href="${grades_csv_url}">${_('Download student grades')}</a>
</p>
</section>
<h2 class="hd hd-2">${_('Student Grades')}</h2>
<p><a href="${gradebook_url}">${_('View gradebook')}</a></p>
<p><a href="${grades_csv_url}">${_('Download student grades')}</a></p>
<div class="wrapper-form">
<h3 class="form-title subsection-title"><%- title %></h3>
<h3 class="hd hd-3 form-title subsection-title"><%- title %></h3>
<div class="file-upload-form-result result"></div>
<form class="file-upload-form" id="file-upload-form" method="post" action="<%= url %>" enctype="multipart/form-data">
<form class="file-upload-form" id="file-upload-form" method="post" action="<%- url %>" enctype="multipart/form-data">
<div class="form-fields">
<div class="field field-file is-required">
......
......@@ -3,7 +3,8 @@
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
%>
<section id="add-coupon-modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Add Coupon Code')}">
<section id="add-coupon-modal" class="modal" role="dialog" tabindex="-1" aria-labelledby="header-coupon-code">
<h2 id="header-coupon-code" class="hd hd-2">${_("Add Coupon Code")}</h2>
<div class="inner-wrapper">
<button class="close-modal">
<span class="icon fa fa-remove" aria-hidden="true"></span>
......@@ -15,7 +16,7 @@ from django.core.urlresolvers import reverse
<div id="coupon-content">
<header>
<h2>${_("Add Coupon Code")}</h2>
<h3 class="hd hd-3">${_("Add Coupon Code")}</h3>
</header>
<div class="instructions">
......
<h3><%- gettext("Bulk Exceptions") %></h3>
<h3 class="hd hd-3"><%- gettext("Bulk Exceptions") %></h3>
<div class="white-list-csv">
<p class="under-heading">
<%- gettext("Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.") %>
......
<h3><%- gettext("Individual Exceptions") %></h3>
<h3 class="hd hd-3"><%- gettext("Individual Exceptions") %></h3>
<p class="under-heading"> <%- gettext("Enter the username or email address of each learner that you want to add as an exception.") %></p>
<div class='certificate-exception-inputs'>
<div class="">
......
<h3><%- gettext("Generate Exception Certificates") %></h3>
<h3 class="hd hd-3"><%- gettext("Generate Exception Certificates") %></h3>
<p class="under-heading">
<label>
<input type='radio' name='generate-exception-certificates-radio' checked="checked" value='new' aria-describedby='generate-exception-certificates-radio-new-tip'>
......
......@@ -4,7 +4,6 @@
<%!
from django.utils.translation import ugettext as _
from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
from openedx.core.djangolib.markup import HTML
%>
<%static:require_module_async module_name="js/certificates/factories/certificate_whitelist_factory" class_name="CertificateWhitelistFactory">
......@@ -19,7 +18,7 @@ from openedx.core.djangolib.markup import HTML
<div class="example-certificates">
% if not section_data['html_cert_enabled']:
<h2>${_('Example Certificates')}</h2>
<h3 class="hd hd-3">${_('Example Certificates')}</h3>
<div class="generate-example-certificates-wrapper">
<p>${_('Generate example certificates for the course.')}</p>
......@@ -55,7 +54,7 @@ from openedx.core.djangolib.markup import HTML
<hr />
<div class="enable-certificates">
<h2>${_("Student-Generated Certificates")}</h2>
<h3 class="hd hd-3">${_("Student-Generated Certificates")}</h3>
% if section_data['enabled_for_course']:
<form id="enable-certificates-form" method="post" action="${section_data['urls']['enable_certificate_generation']}">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}">
......@@ -79,14 +78,14 @@ from openedx.core.djangolib.markup import HTML
<hr class="section-divider" />
<div class="start-certificate-generation">
<h2>${_("Generate Certificates")}</h2>
<h3 class="hd hd-3">${_("Generate Certificates")}</h3>
<form id="certificates-generating-form" method="post" action="${section_data['urls']['start_certificate_generation']}">
% if section_data['html_cert_enabled'] and section_data['active_certificate'] is None:
<p>${_("Course certificate generation requires an activated web certificate configuration.")}</p>
<input type="button" id="disabled-btn-start-generating-certificates" class="is-disabled" aria-disabled="true" value="${_('Generate Certificates')}"/>
% else:
<p class="under-heading">
${HTML(_("When you are ready to generate certificates for your course, click Generate Certificates. You do not need to do this<br/>if you have set the certificate mode to on-demand generation."))}
${_("When you are ready to generate certificates for your course, click Generate Certificates. You do not need to do this if you have set the certificate mode to on-demand generation.")}
</p>
<input type="button" class="btn-blue" id="btn-start-generating-certificates" value="${_('Generate Certificates')}" data-endpoint="${section_data['urls']['start_certificate_generation']}"/>
%endif
......@@ -97,7 +96,7 @@ from openedx.core.djangolib.markup import HTML
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3"> ${_("Pending Tasks")} </h3>
<div class="running-tasks-section">
<p>${_("The status for any active tasks appears in a table below.")} </p>
<br />
......@@ -109,11 +108,11 @@ from openedx.core.djangolib.markup import HTML
% endif
<hr>
<p class="start-certificate-regeneration">
<h2>${_("Regenerate Certificates")}</h2>
<div class="start-certificate-regeneration">
<h3 class="hd hd-3">${_("Regenerate Certificates")}</h3>
<form id="certificate-regenerating-form" method="post" action="${section_data['urls']['start_certificate_regeneration']}">
<p class="under-heading">
${HTML(_('To regenerate certificates for your course, choose the learners who will receive regenerated certificates and click <br/> Regenerate Certificates.'))}
${_('To regenerate certificates for your course, choose the learners who will receive regenerated certificates and click Regenerate Certificates.')}
</p>
<label style="display: inline" for="certificate_status_${section_data['status'].downloadable}">
......@@ -139,7 +138,7 @@ from openedx.core.djangolib.markup import HTML
<hr>
<div class="certificate-generation-history">
<h2 class="title">${_("Certificate Generation History")}</h2>
<h3 class="hd hd-3 title">${_("Certificate Generation History")}</h3>
<div class="certificate-generation-history-content">
<table>
<thead>
......@@ -164,7 +163,7 @@ from openedx.core.djangolib.markup import HTML
<div class="certificate-exception-container">
<hr class="section-divider">
<h2> ${_("SET CERTIFICATE EXCEPTIONS")} </h2>
<h3 class="hd hd-3"> ${_("SET CERTIFICATE EXCEPTIONS")} </h3>
<p class="under-heading info">
${_("Set exceptions to generate certificates for learners who did not qualify for a certificate but have " \
"been given an exception by the course team. After you add learners to the exception list, click Generate " \
......@@ -186,7 +185,7 @@ from openedx.core.djangolib.markup import HTML
<hr class="section-divider" />
<div class="certificate-invalidation-container">
<h2> ${_("Invalidate Certificates")} </h2>
<h3 class="hd hd-3"> ${_("Invalidate Certificates")} </h3>
<div id="certificate-invalidation">
<div class="ui-loading">
<span class="spin"><span class="icon fa fa-refresh" aria-hidden="true"></span></span> <span class="copy">${_('Loading')}</span>
......
<h3 class="subsection-title"><%- gettext('Specify whether discussion topics are divided by cohort') %></h3>
<h3 class="hd hd-3 subsection-title"><%- gettext('Specify whether discussion topics are divided by cohort') %></h3>
<form action="" method="post" id="cohort-course-wide-discussions-form" class="cohort-course-wide-discussions-form">
<div class="wrapper cohort-management-supplemental">
<div class="form-fields">
<div class="form-field">
<div class="course-wide-discussion-topics">
<h3 class="subsection-title"><%- gettext('Course-Wide Discussion Topics') %></h3>
<h4 class="hd hd-4 subsection-title"><%- gettext('Course-Wide Discussion Topics') %></h4>
<p><%- gettext('Select the course-wide discussion topics that you want to divide by cohort.') %></p>
<div class="field">
<ul class="discussions-wrapper"><%= HtmlUtils.ensureHtml(courseWideTopicsHtml) %></ul>
......
......@@ -5,7 +5,7 @@
<div class="form-fields">
<div class="form-field">
<div class="inline-discussion-topics">
<h3 class="subsection-title"><%- gettext('Content-Specific Discussion Topics') %></h3>
<h4 class="hd hd-4 subsection-title"><%- gettext('Content-Specific Discussion Topics') %></h4>
<p><%- gettext('Specify whether content-specific discussion topics are divided by cohort.') %></p>
<div class="always_cohort_inline_discussions">
<label>
......
......@@ -9,7 +9,7 @@
<div class="cohort-management-group-add tab-content tab-content-manage_students" tabindex="-1">
<form action="" method="post" id="cohort-management-group-add-form" class="cohort-management-group-add-form">
<h4 class="form-title"><%- gettext('Add students to this cohort') %></h4>
<h4 class="hd hd-3 form-title"><%- gettext('Add students to this cohort') %></h4>
<div class="form-introduction">
<p><%- gettext('Note: Students can be in only one cohort. Adding students to this group overrides any previous group assignment.') %></p>
......
......@@ -2,7 +2,7 @@
<div class="cohort-management-settings">
<form action="" method="post" name="" id="cohort-management-settings-form" class="cohort-management-settings-form">
<% if (isNewCohort) { %>
<h3 class="form-title"><%- gettext('Add a New Cohort') %></h3>
<h3 class="hd hd-3 form-title"><%- gettext('Add a New Cohort') %></h3>
<div class="tab-content is-visible new-cohort-form">
<% } %>
<div class="form-fields">
......
<h3 class="group-header-title" tabindex="-1">
<h3 class="hd hd-3 group-header-title" tabindex="-1">
<span class="title-value"><%- cohort.get('name') %></span>
<span class="group-count"><%-
interpolate(
......
<%! from django.utils.translation import ugettext as _ %>
<%page args="section_data"/>
<%page args="section_data" expression_filter="h"/>
<%!
from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML, Text
%>
%if settings.FEATURES.get('DISPLAY_ANALYTICS_ENROLLMENTS') or section_data.get('enrollment_message'):
<h3 class="hd hd-3">${_("Enrollment Information")}</h3>
<div class="enrollment-wrapper">
<h2>${_("Enrollment Information")}</h2>
%if settings.FEATURES.get('DISPLAY_ANALYTICS_ENROLLMENTS'):
## Translators: 'track' refers to the enrollment type ('honor', 'verified', or 'audit')
<span class="tip">${_("Number of enrollees (admins, staff, and students) by track")}</span>
......@@ -35,27 +37,27 @@
%endif
<div class="basic-wrapper">
<h2>${_("Basic Course Information")}</h2>
<h3 class="hd hd-3">${_("Basic Course Information")}</h3>
<ul class="list-input">
<li class="field text is-not-editable" id="field-course-organization">
<label for="course-organization">${_("Organization:")}</label>
<b>${ section_data['course_id'].org | h}</b>
<b>${ section_data['course_id'].org}</b>
</li>
<li class="field text is-not-editable" id="field-course-number">
<label for="course-number">${_("Course Number:")}</label>
<b>${ section_data['course_id'].course | h}</b>
<b>${ section_data['course_id'].course}</b>
</li>
<li class="field text is-not-editable" id="field-course-name">
<label for="course-name">${_("Course Name:")}</label>
<b>${ section_data['course_id'].run | h}</b>
<b>${ section_data['course_id'].run}</b>
</li>
<li class="field text is-not-editable" id="field-course-display-name">
<label for="course-display-name">${_("Course Display Name:")}</label>
<b>${ section_data['course_display_name'] | h}</b>
<b>${ section_data['course_display_name']}</b>
</li>
<li class="field text is-not-editable" id="field-course-start-date">
......@@ -98,9 +100,9 @@
%if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD', ''):
<p>
## Translators: git is a version-control system; see http://git-scm.com/about
${_("View detailed Git import logs for this course {link_start}by clicking here{link_end}.").format(
link_start='<a href="{}">'.format(section_data['detailed_gitlogs_url']),
link_end='</a>'
${Text(_("View detailed Git import logs for this course {link_start}by clicking here{link_end}.")).format(
link_start=HTML('<a href="{}">').format(section_data['detailed_gitlogs_url']),
link_end=HTML('</a>')
)}
</p>
%endif
......@@ -110,7 +112,7 @@
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3"> ${_("Pending Tasks")} </h3>
<div class="running-tasks-section">
<p>${_("The status for any active tasks appears in a table below.")} </p>
<br />
......@@ -127,7 +129,7 @@
<hr>
<p>
<div class="toggle-wrapper">
<h2 class="title">${_("Course Warnings")}:</h2>
<h3 class="hd hd-3 title">${_("Course Warnings")}:</h3>
<div class="triangle"></div>
</div>
<div class="course-errors-visibility-wrapper">
......
<%! from django.utils.translation import ugettext as _ %>
<%page args="section_data"/>
<%page args="section_data" expression_filter="h"/>
<%!
from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML, Text
%>
<div class="data-download-container action-type-container">
<h2>${_("Data Download")}</h2>
<div class="request-response-error msg msg-error copy" id="data-request-response-error"></div>
......@@ -21,7 +22,7 @@
%if settings.FEATURES.get('ENABLE_S3_GRADE_DOWNLOADS'):
<div class="reports-download-container action-type-container">
<hr>
<h2> ${_("Reports")}</h2>
<h3 class="hd hd-3">${_("Reports")}</h3>
<p>${_("For large courses, generating some reports can take several hours. When report generation is complete, a link that includes the date and time of generation appears in the table below. These reports are generated in the background, meaning it is OK to navigate away from this page while your report is generating.")}</p>
......@@ -86,7 +87,7 @@
<div class="request-response-error msg msg-error copy" id="report-request-response-error"></div>
<br>
<p><b>${_("Reports Available for Download")}</b></p>
<h3 class="hd hd-3">${_("Reports Available for Download")}</h3>
<p>
${_("The reports listed below are available for download. A link to every report remains available on this page, identified by the UTC date and time of generation. Reports are not deleted, so you will always be able to access previously generated reports from this page.")}
</p>
......@@ -98,7 +99,12 @@
%endif
## Translators: a table of URL links to report files appears after this sentence.
<p>${_("<b>Note</b>: To keep student data secure, you cannot save or email these links for direct access. Copies of links expire within 5 minutes.")}</p><br>
<p>
${Text(_("{strong_start}Note{strong_end}: To keep student data secure, you cannot save or email these links for direct access. Copies of links expire within 5 minutes.")).format(
strong_start=HTML("<strong>"),
strong_end=HTML("</strong>"),
)}
</p><br>
<div class="report-downloads-table" id="report-downloads-table" data-endpoint="${ section_data['list_report_downloads_url'] }" ></div>
</div>
......@@ -107,7 +113,7 @@
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3">${_("Pending Tasks")}</h3>
<div class="running-tasks-section">
<p>${_("The status for any active tasks appears in a table below.")} </p>
<br />
......
......@@ -3,6 +3,7 @@
from django.utils.translation import ugettext as _
from datetime import datetime, timedelta
from openedx.core.djangolib.js_utils import js_escaped_string
from openedx.core.djangolib.markup import HTML, Text
import pytz
%>
<%include file="add_coupon_modal.html" args="section_data=section_data" />
......@@ -11,10 +12,10 @@ import pytz
<%include file="generate_registarion_codes_modal.html" args="section_data=section_data" />
<%include file="invalidate_registration_code_modal.html" args="section_data=section_data" />
<div class="ecommerce-wrapper">
<h3 class="error-msgs" id="error-msg"></h3>
<div class="error-msgs" id="error-msg"></div>
<div id = "accordion">
<div class="wrap">
<h2>${_('Enrollment Codes')}</h2>
<h3 class="hd hd-3">${_('Enrollment Codes')}</h3>
<div>
%if section_data['sales_admin']:
<span class="code_tip">
......@@ -55,7 +56,7 @@ import pytz
<!-- end wrap -->
%if section_data['coupons_enabled']:
<div class="wrap">
<h2>${_("Course Price")}</h2>
<h3 class="hd hd-3">${_("Course Price")}</h3>
<div>
<span class="tip">${_("Course price per seat: ")}<span>${section_data['currency_symbol']}${section_data['course_price']}</span>
%if section_data['access']['finance_admin'] is True:
......@@ -68,7 +69,7 @@ import pytz
<!-- end wrap -->
%if section_data['access']['finance_admin']:
<div class="wrap">
<h2>${_("Course Seat Purchases")}</h2>
<h3 class="hd hd-3">${_("Course Seat Purchases")}</h3>
<div>
%if section_data['total_amount'] is not None:
<span><strong>${_("Total Credit Card Purchases: ")}</strong></span><span>${section_data['currency_symbol']}${section_data['total_amount']}</span>
......@@ -93,7 +94,7 @@ import pytz
%endif
%if section_data['reports_enabled']:
<div class="reports wrap">
<h2>${_("Reports")}</h2>
<h3 class="hd hd-3">${_("Reports")}</h3>
<div>
<span class="csv_tip">
<div>
......@@ -118,7 +119,12 @@ import pytz
<p>${_("The following reports are available for download. Reports are not deleted. A link to every report remains available on this page, identified by the date and time (in UTC) that the report was generated.")}</p>
## Translators: a table of URL links to report files appears after this sentence.
<p>${_("<b>Note</b>: To help protect learner data, links to these reports that you save outside of this page or that you send or receive in email expire after five minutes.")}</p><br>
<p>
${Text(_("{strong_start}Note{strong_end}: To help protect learner data, links to these reports that you save outside of this page or that you send or receive in email expire after five minutes.")).format(
strong_start=HTML("<strong>"),
strong_end=HTML("</strong>"),
)}
</p><br>
<div class="report-downloads-table" id="report-downloads-table"
data-endpoint="${ section_data['list_financial_report_downloads_url'] }"></div>
......@@ -127,7 +133,7 @@ import pytz
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3">${_("Pending Tasks")}</h3>
<div class="running-tasks-section">
<p>${_("The status for any active tasks appears in a table below.")} </p>
<br/>
......@@ -141,7 +147,7 @@ import pytz
%endif
%if section_data['coupons_enabled']:
<div class="wrap">
<h2>${_("Coupon Code List")}</h2>
<h3 class="hd hd-3">${_("Coupon Code List")}</h3>
<div>
<span class="csv_tip">${_("Download a .csv file of all coupon codes for this course.")}
......@@ -256,7 +262,7 @@ import pytz
}
if($('#invoice_number').val() == "") {
$('#error-msg').attr('class','error-msgs')
$('#error-msg').html("${_('The Invoice Number field cannot be empty.') | n, h, js_escaped_string}").show();
$('#error-msg').text("${_('The Invoice Number field cannot be empty.') | n, js_escaped_string}").show();
return
}
$.ajax({
......@@ -265,12 +271,14 @@ import pytz
url: "${section_data['sale_validation_url'] | n, js_escaped_string}",
success: function (data) {
$('#error-msg').attr('class','success-msgs')
$('#error-msg').html(data.message).show();
edx.HtmlUtils.setHtml($('#error-msg'), data.message);
$('#error-msg').show();
$('#invoice_number').val('');
},
error: function(jqXHR, textStatus, errorThrown) {
$('#error-msg').attr('class','error-msgs')
$('#error-msg').html(jqXHR.responseText).show();
edx.HtmlUtils.setHtml($('#error-msg'), jqXHR.responseText);
$('#error-msg').show();
}
});
});
......@@ -307,7 +315,8 @@ import pytz
error: function(jqXHR, textStatus, errorThrown) {
var data = $.parseJSON(jqXHR.responseText);
$('#error-msg').attr('class','error-msgs')
$('#error-msg').html(data.message).show();
edx.HtmlUtils.setHtml($('#error-msg'), data.message);
$('#error-msg').show();
}
});
});
......@@ -332,7 +341,8 @@ import pytz
error: function(jqXHR, textStatus, errorThrown) {
var data = $.parseJSON(jqXHR.responseText);
$('#error-msg').attr('class','error-msgs')
$('#error-msg').html(data.message).show();
edx.HtmlUtils.setHtml($('#error-msg'), data.message);
$('#error-msg').show();
anchor.removeData("disabled");
}
});
......
......@@ -3,7 +3,8 @@
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
%>
<section id="edit-coupon-modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Edit Coupon Code')}">
<section id="edit-coupon-modal" class="modal" role="dialog" tabindex="-1" aria-labelledby="header-edit-coupon-code">
<h2 id="header-edit-coupon-code" class="hd hd-2">${_("Edit Coupon Code")}</h2>
<div class="inner-wrapper">
<button class="close-modal">
<span class="icon fa fa-remove" aria-hidden="true"></span>
......@@ -14,10 +15,6 @@ from django.core.urlresolvers import reverse
</button>
<div id="coupon-content">
<header>
<h2>${_("Edit Coupon Code")}</h2>
</header>
<div class="instructions">
<p>
${_("Edit Coupon Code Information")}</p>
......
<%! from django.utils.translation import ugettext as _ %>
<%page args="section_data"/>
<%page args="section_data" expression_filter="h"/>
<%!
from django.utils.translation import ugettext as _
%>
<div id="set-extension">
<h2>${_("Individual due date extensions")}</h2>
<h3 class="hd hd-3">${_("Individual due date extensions")}</h3>
<p>
${_("In this section, you have the ability to grant extensions on specific "
"units to individual students. Please note that the latest date is always "
......@@ -40,7 +42,7 @@
</div>
<hr/>
<div id="view-granted-extensions">
<h2>${_("Viewing granted extensions")}</h2>
<h3 class="hd hd-3">${_("Viewing granted extensions")}</h3>
<p>
${_("Here you can see what extensions have been granted on particular "
"units or for a particular student.")}
......@@ -81,7 +83,7 @@
</div>
<hr/>
<div id="reset-extension">
<h2>${_("Resetting extensions")}</h2>
<h3 class="hd hd-3">${_("Resetting extensions")}</h3>
<p>
${_("Resetting a problem's due date rescinds a due date extension for a "
"student on a particular unit. This will revert the due date for the "
......@@ -109,4 +111,3 @@
data-endpoint="${section_data['reset_due_date_url']}">
</p>
</div>
......@@ -3,7 +3,8 @@
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
%>
<section id="registration_code_generation_modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Generate Registration Code Modal')}">
<section id="registration_code_generation_modal" class="modal" role="dialog" tabindex="-1" aria-labelledby="header-registration-code">
<h2 id="header-registration-code" class="hd hd-2">${_("Generate Registration Code Modal")}</h2>
<div class="inner-wrapper">
<button class="close-modal">
<span class="icon fa fa-remove" aria-hidden="true"></span>
......@@ -15,7 +16,7 @@ from django.core.urlresolvers import reverse
<div id="registration-content">
<header>
<h2>${_("Create Enrollment Codes")}</h2>
<h3 class="hd hd-3">${_("Create Enrollment Codes")}</h3>
</header>
<div class="instructions">
......
<%page expression_filter="h"/>
<%inherit file="/main.html" />
<%namespace name='static' file='/static_content.html'/>
<%def name="online_help_token()"><% return "instructor" %></%def>
......@@ -84,18 +85,17 @@ from django.core.urlresolvers import reverse
<script language="JavaScript" type="text/javascript"></script>
<section class="container">
<div class="container">
<div class="instructor-dashboard-wrapper-2">
<main id="main" aria-label="Content" tabindex="-1">
<section class="instructor-dashboard-content-2" id="instructor-dashboard-content">
<h1 class="hd hd-1">${_("Instructor Dashboard")}</h1>
<div class="wrap-instructor-info studio-view">
%if studio_url:
<a class="instructor-info-action" href="${studio_url}">${_("View Course in Studio")}</a>
%endif
</div>
<h1>${_("Instructor Dashboard")}</h1>
%if analytics_dashboard_message:
<div class="wrapper-msg urgency-low is-shown">
<p>${analytics_dashboard_message}</p>
......@@ -117,11 +117,12 @@ from django.core.urlresolvers import reverse
## to keep this short, sections can be pulled out into their own files
% for section_data in sections:
<section id="${ section_data['section_key'] }" class="idash-section">
<%include file="${ section_data['section_key'] }.html" args="section_data=section_data" />
<section id="${ section_data['section_key'] }" class="idash-section" aria-labelledby="header-${section_data['section_key']}">
<h2 class="hd hd-2" id="header-${ section_data['section_key'] }">${ section_data['section_display_name'] }</h2>
<%include file="${ section_data['section_key'] }.html" args="section_data=section_data" />
</section>
% endfor
</section>
</main>
</div>
</section>
</div>
<%page args="section_data" expression_filter="h"/>
<%! from django.utils.translation import ugettext as _ %>
<%! from django.core.urlresolvers import reverse %>
<section id="invalidate_registration_code_modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Enrollment Code Status')}">
<section id="invalidate_registration_code_modal" class="modal" role="dialog" tabindex="-1" aria-labelledby="header-enrollment-code-status">
<h2 id="header-enrollment-code-status" class="hd hd-2">${_("Enrollment Code Status")}</h2>
<div class="inner-wrapper">
<button class="close-modal">
<span class="icon fa fa-remove" aria-hidden="true"></span>
......@@ -13,7 +14,7 @@
<div id="regcode-content">
<header>
<h2>${_("Enrollment Code Status")}</h2>
<h3 class="hd hd-3">${_("Enrollment Code Status")}</h3>
</header>
<div class="instructions">
......
......@@ -5,7 +5,6 @@ from django.utils.translation import ugettext as _
from courseware.courses import get_studio_url
from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition
%>
<script type="text/template" id="member-list-widget-template">
<div class="member-list-widget">
<div class="header">
......@@ -34,9 +33,8 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
</div>
</script>
<h2 class="hd hd-2">Enrollment</h2>
<fieldset class="batch-enrollment membership-section">
<legend id="heading-batch-enrollment" class="hd hd-2">${_("Batch Enrollment")}</legend>
<legend id="heading-batch-enrollment" class="hd hd-3">${_("Batch Enrollment")}</legend>
<label>
${_("Enter email addresses and/or usernames separated by new lines or commas.")}
${_("You will not get notification for emails that bounce, so please double-check spelling.")}
......@@ -45,11 +43,11 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
<input type="hidden" id="is_course_white_label" value="${section_data['is_white_label']}">
% if section_data['is_white_label']:
<label>
${_("Enter the reason why the students are to be manually enrolled or unenrolled.")}
${_("This cannot be left blank and will be recorded and presented in Enrollment Reports.")}
${_("Therefore, please give enough detail to account for this action.")}
<textarea rows="2" id="reason-field-id" name="reason-field" placeholder="${_('Reason')}" spellcheck="false"></textarea>
</label>
${_("Enter the reason why the students are to be manually enrolled or unenrolled.")}
${_("This cannot be left blank and will be recorded and presented in Enrollment Reports.")}
${_("Therefore, please give enough detail to account for this action.")}
<textarea rows="2" id="reason-field-id" name="reason-field" placeholder="${_('Reason')}" spellcheck="false"></textarea>
</label>
%endif
<div class="enroll-option">
<label class="has-hint">
......@@ -89,8 +87,8 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
%if static.get_value('ALLOW_AUTOMATED_SIGNUPS', settings.FEATURES.get('ALLOW_AUTOMATED_SIGNUPS', False)):
<hr class="divider" />
<div class="auto_enroll auto_enroll_csv">
<h2>${_("Register/Enroll Students")}</h2>
<div class="auto_enroll auto_enroll_csv">
<h3 class="hd hd-3">${_("Register/Enroll Students")}</h3>
<p>${_("To register and enroll a list of users in this course, choose a CSV file that contains the following columns in this exact order: email, username, name, and country. Please include one student per row and do not include any headers, footers, or blank lines.")}</p>
<form id="student-auto-enroll-form" method="post" action="${ section_data['upload_student_csv_button_url'] }" enctype="multipart/form-data">
<div class="customBrowseBtn">
......@@ -113,7 +111,7 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
%if section_data['access']['instructor']:
<fieldset class="batch-beta-testers membership-section">
<legend id="heading-batch-beta-testers" class="hd hd-2">${_("Batch Beta Tester Addition")}</legend>
<legend id="heading-batch-beta-testers" class="hd hd-3">${_("Batch Beta Tester Addition")}</legend>
<label>
${_("Enter email addresses and/or usernames separated by new lines or commas.")}<br/>
${_("Note: Users must have an activated {platform_name} account before they can be enrolled as beta testers.").format(platform_name=settings.PLATFORM_NAME)}
......@@ -158,7 +156,7 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
<div class="member-lists-management membership-section" aria-live="polite">
## Translators: an "Administration List" is a list, such as Course Staff, that users can be added to.
<h2> ${_("Course Team Management")} </h2>
<h3 class="hd hd-3">${_("Course Team Management")}</h3>
<div class="request-response-error"></div>
......
......@@ -20,14 +20,14 @@ from django.template.defaultfilters import escapejs
</div>
<div class="metrics-header-container">
<div class="metrics-left-header">
<h2>${_("Subsection Data")}</h2>
<h3 class="hd hd-3">${_("Subsection Data")}</h3>
<p>${_("Each bar shows the number of students that opened the subsection.")}</p>
<p>${_("You can click on any of the bars to list the students that opened the subsection.")}</p>
<p>${_("You can also download this data as a CSV file.")}</p>
<p><input type="button" id="download_subsection_data" value="${_("Download Subsection Data for all Subsections as a CSV")}" /></p>
</div>
<div class="metrics-right-header">
<h2>${_("Grade Distribution Data")}</h2>
<h3 class="hd hd-3">${_("Grade Distribution Data")}</h3>
<p>${_("Each bar shows the grade distribution for that problem.")}</p>
<p>${_("You can click on any of the bars to list the students that attempted the problem, along with the grades they received.")}</p>
<p>${_("You can also download this data as a CSV file.")}</p>
......
<div class="message message-<%= type %>" tabindex="-1">
<h3 class="message-title">
<div class="message message-<%- type %>" tabindex="-1">
<h3 class="hd hd-3 message-title">
<%- title %>
</h3>
......
......@@ -5,7 +5,6 @@ from openedx.core.djangolib.markup import HTML
%>
<div class="vert-left send-email" id="section-send-email">
<h2> ${_("Send Email")} </h2>
<div class="request-response msg msg-confirm copy" id="request-response"></div>
<ul class="list-fields">
<li class="field">
......@@ -85,7 +84,7 @@ from openedx.core.djangolib.markup import HTML
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3">${_("Pending Tasks")}</h3>
<div class="running-tasks-section">
<p>${_("Email actions run in the background. The status for any active tasks - including email tasks - appears in a table below.")} </p>
<br />
......@@ -99,7 +98,7 @@ from openedx.core.djangolib.markup import HTML
<hr>
<div class="vert-left email-background" id="section-task-history">
<h2> ${_("Email Task History")} </h2>
<h3 class="hd hd-3">${_("Email Task History")}</h3>
<div>
<p>${_("To see the content of previously sent emails, click this button:")}</p>
<br/>
......
......@@ -3,7 +3,8 @@
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
%>
<section id="set-course-mode-price-modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Set Course Mode Price')}">
<section id="set-course-mode-price-modal" class="modal" role="dialog" tabindex="-1" aria-labelledby="header-course-price">
<h2 id="header-course-price" class="hd hd-2">${_("Set Course Mode Price")}</h2>
<div class="inner-wrapper">
<button class="close-modal">
<span class="icon fa fa-remove" aria-hidden="true"></span>
......@@ -15,7 +16,7 @@ from django.core.urlresolvers import reverse
<div id="course-content">
<header>
<h2>${_("Set Course Mode Price")}</h2>
<h3 class="hd hd-3">${_("Set Course Mode Price")}</h3>
</header>
<div class="instructions">
......
......@@ -5,13 +5,13 @@ from datetime import datetime, timedelta
import pytz
%>
<div class="proctoring-wrapper">
<div id = "proctoring-accordion">
<div id="proctoring-accordion">
<div class="wrap">
<h2>${_('Allowance Section')}</h2>
<h3 class="hd hd-3">${_('Allowance Section')}</h3>
<div class="special-allowance-container" data-course-id="${ section_data['course_id'] }"></div>
</div>
<div class="wrap">
<h2>${_('Student Special Exam Attempts')}</h2>
<h3 class="hd hd-3">${_('Student Special Exam Attempts')}</h3>
<div class="student-proctored-exam-container" data-course-id="${ section_data['course_id'] }"></div>
</div>
</div>
......
<%page args="section_data" expression_filter="h"/>
<%! from django.utils.translation import ugettext as _ %>
<div>
%if section_data['is_small_course']:
## Show the gradebook for small courses
<h2>${_("Student Gradebook")}</h2>
<h3 class="hd hd-3">${_("Student Gradebook")}</h3>
<p>
${_("Click here to view the gradebook for enrolled students. This feature is only visible to courses with a small number of total enrolled students.")}
</p>
......@@ -17,7 +16,7 @@
</div>
<div class="student-specific-container action-type-container">
<h2>${_("Student-specific grade inspection")}</h2>
<h3 class="hd hd-3">${_("Student-specific grade inspection")}</h3>
<div class="request-response-error"></div>
<br />
<label>
......@@ -38,7 +37,7 @@
</div>
<div class="student-grade-container action-type-container">
<h2>${_("Student-specific grade adjustment")}</h2>
<h3 class="hd hd-3">${_("Student-specific grade adjustment")}</h3>
<div class="request-response-error"></div>
<p>
<label>
......@@ -90,7 +89,7 @@
% if course.entrance_exam_enabled:
<div class="entrance-exam-grade-container action-type-container">
<h2>${_("Entrance Exam Adjustment")}</h2>
<h3 class="hd hd-3">${_("Entrance Exam Adjustment")}</h3>
<div class="request-response-error"></div>
<label>
${_("Student's {platform_name} email address or username:").format(platform_name=settings.PLATFORM_NAME)}
......@@ -132,7 +131,7 @@
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS') and section_data['access']['instructor']:
<div class="course-specific-container action-type-container">
<h2>${_('Course-specific grade adjustment')}</h2>
<h3 class="hd hd-3">${_('Course-specific grade adjustment')}</h3>
<div class="request-response-error"></div>
<label>
......@@ -161,7 +160,7 @@
%if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<div class="running-tasks-container action-type-container">
<hr>
<h2> ${_("Pending Tasks")} </h2>
<h3 class="hd hd-3">${_("Pending Tasks")}</h3>
<div class="running-tasks-section">
<p>${_("The status for any active tasks appears in a table below.")} </p>
<br />
......
<%! from django.utils.translation import ugettext as _ %>
<div class="wrapper-comp-editor" id="editor-tab" data-editor="${editor}">
<section class="html-editor editor">
<div class="html-editor editor">
<div class="row">
% if editor == 'visual':
<textarea class="tiny-mce">${data | h}</textarea>
% endif
<textarea name="" class="edit-box">${data | h}</textarea>
</div>
</section>
</div>
\ No newline at end of file
</div>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment