diff --git a/cms/djangoapps/contentstore/views/certificates.py b/cms/djangoapps/contentstore/views/certificates.py index 6535e0a85718..0b3e1a8f85ed 100644 --- a/cms/djangoapps/contentstore/views/certificates.py +++ b/cms/djangoapps/contentstore/views/certificates.py @@ -225,7 +225,8 @@ def serialize_certificate(certificate): "description": certificate_data['description'], "is_active": certificate_data['is_active'], "version": CERTIFICATE_SCHEMA_VERSION, - "signatories": certificate_data['signatories'] + "signatories": certificate_data['signatories'], + "arabic_course_title": certificate_data['arabic_course_title'] } # Some keys are not required, such as the title override... diff --git a/cms/static/js/certificates/models/certificate.js b/cms/static/js/certificates/models/certificate.js index 97a2735d7159..b8b754c257d3 100644 --- a/cms/static/js/certificates/models/certificate.js +++ b/cms/static/js/certificates/models/certificate.js @@ -19,6 +19,8 @@ function(_, Backbone, BackboneRelational, BackboneAssociations, gettext, CoffeeS // Metadata fields currently displayed in web forms course_title: '', + arabic_course_title: '', + // Metadata fields not currently displayed in web forms name: 'Name of the certificate', description: 'Description of the certificate', @@ -78,6 +80,12 @@ function(_, Backbone, BackboneRelational, BackboneAssociations, gettext, CoffeeS attributes: {name: true} }; } + if (!attrs.arabic_course_title.trim()) { + return { + message: gettext('Arabic name is require for generating Certificate'), + attributes: {name: true} + }; + } var allSignatoriesValid = _.every(attrs.signatories.models, function(signatory) { return signatory.isValid(); }); diff --git a/cms/static/js/certificates/views/certificate_editor.js b/cms/static/js/certificates/views/certificate_editor.js index 6b0365ffbf65..ca7fef650e4c 100644 --- a/cms/static/js/certificates/views/certificate_editor.js +++ b/cms/static/js/certificates/views/certificate_editor.js @@ -24,6 +24,7 @@ function($, _, Backbone, gettext, 'change .collection-name-input': 'setName', 'change .certificate-description-input': 'setDescription', 'change .certificate-course-title-input': 'setCourseTitle', + 'change .certificate-arabic-course-title-input': 'setArabicCourseTitle', 'focus .input-text': 'onFocus', 'blur .input-text': 'onBlur', submit: 'setAndClose', @@ -103,6 +104,7 @@ function($, _, Backbone, gettext, name: this.model.get('name'), description: this.model.get('description'), course_title: this.model.get('course_title'), + arabic_course_title: this.model.get('arabic_course_title'), org_logo_path: this.model.get('org_logo_path'), is_active: this.model.get('is_active'), isNew: this.model.isNew() @@ -143,11 +145,22 @@ function($, _, Backbone, gettext, ); }, + setArabicCourseTitle: function(event) { + // Updates the indicated model field (still requires persistence on server) + if (event && event.preventDefault) { event.preventDefault(); } + this.model.set( + 'arabic_course_title', + this.$('.certificate-arabic-course-title-input').val(), + {silent: true} + ); + }, + setValues: function() { // Update the specified values in the local model instance this.setName(); this.setDescription(); this.setCourseTitle(); + this.setArabicCourseTitle(); return this; } }); diff --git a/cms/templates/js/certificate-details.underscore b/cms/templates/js/certificate-details.underscore index a09a3baf897c..8c4f02235352 100644 --- a/cms/templates/js/certificate-details.underscore +++ b/cms/templates/js/certificate-details.underscore @@ -29,6 +29,12 @@ <%- course_title %>

<% } %> + <% if (arabic_course_title) { %> +

+ <%- gettext('Arabic Course Title') %>: + <%- arabic_course_title %> +

+ <% } %>
@@ -46,15 +52,6 @@
- - -
-
-

<%- gettext("Certificate Signatories") %>

-
-

<%- gettext("It is strongly recommended that you include four or fewer signatories. If you include additional signatories, preview the certificate in Print View to ensure the certificate will print correctly on one page.") %>

-
-
<% } %> diff --git a/cms/templates/js/certificate-editor.underscore b/cms/templates/js/certificate-editor.underscore index 513113b80500..ea89595bad35 100644 --- a/cms/templates/js/certificate-editor.underscore +++ b/cms/templates/js/certificate-editor.underscore @@ -31,16 +31,12 @@ " value="<%- course_title %>" aria-describedby="certificate-course-title-<%-uniqueId %>-tip" /> <%- gettext("Specify an alternative to the official course title to display on certificates. Leave blank to use the official course title.") %> +
+ + " value="<%- arabic_course_title %>" aria-describedby="certificate-arabic-course-title-<%-uniqueId %>-tip" /> + <%- gettext("Specify the title in the Arabic for the certificate") %> +
-
-

<%- gettext("Certificate Signatories") %>

-
-

<%- gettext("It is strongly recommended that you include four or fewer signatories. If you include additional signatories, preview the certificate in Print View to ensure the certificate will print correctly on one page.") %>

-
- - - <%- gettext("(Add signatories for a certificate)") %> -
diff --git a/lms/djangoapps/certificates/views/webview.py b/lms/djangoapps/certificates/views/webview.py index e4585b98d5f4..69c8e7534de9 100644 --- a/lms/djangoapps/certificates/views/webview.py +++ b/lms/djangoapps/certificates/views/webview.py @@ -114,7 +114,6 @@ def _update_certificate_context(context, course, course_overview, user_certifica uuid=user_certificate.verify_uuid, suffix=context.get('certificate_verify_url_suffix') ) - # We prefer a CourseOverview for this function because it validates and corrects certificate_available_date # and certificates_display_behavior values. However, not all certificates are guaranteed to have a CourseOverview # associated with them, so we fall back on the course in that case. This shouldn't cause a problem because courses @@ -125,7 +124,9 @@ def _update_certificate_context(context, course, course_overview, user_certifica date = display_date_for_certificate(course, user_certificate) # Translators: The format of the date includes the full name of the month date = strftime_localized(date, "%B %-d, %Y") - context['certificate_date_issued'] = convert_date_to_arabic(date) + context['certificate_date_issued'] = date + # SDAIA: Adding Date in Arabic + context['arabic_certificate_date_issued'] = convert_date_to_arabic(date) # Translators: This text represents the verification of the certificate context['document_meta_description'] = _('This is a valid {platform_name} certificate for {user_name}, ' @@ -249,11 +250,18 @@ def _update_course_context(request, context, course, platform_name, course_overv Updates context dictionary with course info. """ effort = course_overview and course_overview.effort or '8' - context['course_duration'] = convert_date_to_arabic(effort) + context['course_duration'] = effort context['full_course_image_url'] = request.build_absolute_uri(course_image_url(course)) course_title_from_cert = context['certificate_data'].get('course_title', '') accomplishment_copy_course_name = course_title_from_cert if course_title_from_cert else course.display_name context['accomplishment_copy_course_name'] = accomplishment_copy_course_name + + # SDAIA: Adding Arabic name in the certificate context + context['arabic_course_duration'] = convert_date_to_arabic(effort) + arabic_course_title_from_cert = context['certificate_data'].get('arabic_course_title', '') + accomplishment_copy_arabic_course_name = arabic_course_title_from_cert if arabic_course_title_from_cert else course.display_name + context['accomplishment_copy_arabic_course_name'] = accomplishment_copy_arabic_course_name + course_number = course.display_coursenumber if course.display_coursenumber else course.number context['course_number'] = course_number context['idv_enabled_for_certificates'] = settings.FEATURES.get('ENABLE_CERTIFICATES_IDV_REQUIREMENT') @@ -326,6 +334,7 @@ def _update_context_with_user_info(context, user, user_certificate): context['accomplishment_user_id'] = user.id context['accomplishment_copy_name'] = user_fullname context['accomplishment_copy_username'] = user.username + context['accomplishment_copy_name_arabic'] = user.profile.arabic_name if user.profile.arabic_name else user_fullname context['accomplishment_more_title'] = _("More Information About {user_name}'s Certificate:").format( user_name=user_fullname @@ -603,7 +612,8 @@ def render_html_view(request, course_id, certificate=None): # pylint: disable=t certificate_language, course_key ) - + # import pdb; pdb.set_trace(); + # Generate the certificate context in the correct language, then render the template. with translation.override(certificate_language): context = {'user_language': user_language} @@ -643,6 +653,8 @@ def render_html_view(request, course_id, certificate=None): # pylint: disable=t # Append/Override the existing view context values with any course-specific static values from Advanced Settings context.update(course.cert_html_view_overrides) + # import pdb; pdb.set_trace(); + # Track certificate view events _track_certificate_events(request, course, user, user_certificate) diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Bold.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Bold.ttf new file mode 100755 index 000000000000..ecf3973bff35 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Bold.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Extralight.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Extralight.ttf new file mode 100755 index 000000000000..b13d5d85f55d Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Extralight.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Light.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Light.ttf new file mode 100755 index 000000000000..55e59c31dfec Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Light.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium (1).ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium (1).ttf new file mode 100755 index 000000000000..c7d17271ee91 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium (1).ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium.ttf new file mode 100755 index 000000000000..c7d17271ee91 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium_2.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium_2.ttf new file mode 100755 index 000000000000..c7d17271ee91 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Medium_2.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Regular.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Regular.ttf new file mode 100755 index 000000000000..370018100759 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Regular.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold.ttf new file mode 100755 index 000000000000..3538863b9791 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold.ttf differ diff --git a/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold_2.ttf b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold_2.ttf new file mode 100755 index 000000000000..3538863b9791 Binary files /dev/null and b/lms/static/certificates/fonts/Diodrum/DiodrumArabic-Semibold_2.ttf differ diff --git a/lms/static/certificates/images/certificate-bg.png b/lms/static/certificates/images/certificate-bg.png index 813fb72014ab..1eb74048fd47 100644 Binary files a/lms/static/certificates/images/certificate-bg.png and b/lms/static/certificates/images/certificate-bg.png differ diff --git a/lms/static/certificates/sass/_sdaia-template.scss b/lms/static/certificates/sass/_sdaia-template.scss index b1522e0ccda4..b32fd6a7e454 100644 --- a/lms/static/certificates/sass/_sdaia-template.scss +++ b/lms/static/certificates/sass/_sdaia-template.scss @@ -2,251 +2,275 @@ html { -webkit-text-size-adjust: 100%; /* 2 */ } -h1 { - font-size: 2em; - margin: 0.67em 0; +@font-face { + font-family: 'Diodrum'; + font-weight: 200; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Extralight.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Extralight.ttf') format('truetype'); } -a { - background-color: transparent; +@font-face { + font-family: 'Diodrum'; + font-weight: 300; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Light.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Light.ttf') format('truetype'); } -b, -strong { - font-weight: 500; +@font-face { + font-family: 'Diodrum'; + font-weight: 400; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Regular.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Regular.ttf') format('truetype'); } -img { - border-style: none; - max-width: 100%; - height: auto; +@font-face { + font-family: 'Diodrum'; + font-weight: 500; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Medium.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Medium.ttf') format('truetype'); } -.hidden, -[hidden] { - display: none; +@font-face { + font-family: 'Diodrum'; + font-weight: 600; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Semibold.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Semibold.ttf') format('truetype'); } -.text-primary { - color: $success; +@font-face { + font-family: 'Diodrum'; + font-weight: 700; + src: url('#{$font-path}/Diodrum/DiodrumArabic-Bold.ttf'); + src: + url('#{$font-path}/Diodrum/DiodrumArabic-Bold.ttf') format('truetype'); } -.text-secondary { - color: $secondary; +:root { + --primary-color: #32b994; + --secondary-color: #1c355e; } - - -.certificate-wrapper { - background: url(../images/certificate-bg.png) no-repeat; - background-size: 100% 100%; - padding: 174px 11.9% 179px; - color: $primary; +* { + margin: 0; + padding: 0; +} +.primary-color { + color: var(--primary-color); +} +.black-color { + color: var(--secondary-color); +} +.flex-small { + display: flex; + flex-shrink: 0; + gap: 4px; +} +.text-align{ + text-align: right; +} +.diodrumFontFamily{ + font-family: Diodrum; font-weight: 500; - margin: 0 auto; - line-height: 1.15; - - @include media-breakpoint-down(sm) { - padding: 100px 11.9%; - } - - * { - box-sizing: border-box; - } } - -.certificate-wrapper * { - box-sizing: border-box; +.stronger{ + font-weight: 700; } - -.certificate-header { - overflow: hidden; - padding: 0 0 66px; - - @include media-breakpoint-down(sm) { - padding: 0; - } - - img { - vertical-align: middle; - - @include media-breakpoint-down(sm) { - width: 120px; +.certificateWrapper { + background: url(../images/certificate-bg.png) no-repeat; + padding: 130px 12% 150px; + background-size: 100% 100%; + display: flex; + flex-direction: column; + gap: 60px; + + .sdaia-academy-logo { + width: 240px; } - - @include media-breakpoint-down(xs) { - display: block; - margin: 0 auto 10px; + .sdaia-logo { + width: 190px; } - - &.sdaia-academy-logo { - @include margin-right(19px); - - @include media-breakpoint-down(sm) { - width: 150px; - } - - @include media-breakpoint-down(xs) { - @include margin-right(auto); - } + + &__bodywraper { + width: 100%; + max-width: 1100px; + margin: 0 auto; + display: flex; + flex-direction: column; + gap: 30px; } - } -} - -.certificate-header-col { - float: right; - padding: 0 12px 0 0; - - @include media-breakpoint-down(sm) { - float: none; - padding: 0 0 10px; - text-align: center; - } - - &:first-child { - float: left; - padding: 2px 0 0 115px; - - @include media-breakpoint-down(md) { - padding: 2px 0 0 47px; + &__header { + display: flex; + justify-content: space-between; + gap: 10px; } - @include media-breakpoint-down(sm) { - float: none; - padding: 0 0 10px; - text-align: center; + &__mainTitleWrap { + text-align: center; + color: var(--primary-color); + display: flex; + flex-direction: column; + font-size: 45px; } - } -} - -.certificate-heading { - padding: 0 0 33px; - - @include media-breakpoint-down(sm) { - padding: 0; - } - - h1 { - font-size: 71px; - margin: 0 0 17px; - - @include media-breakpoint-down(sm) { - font-size: 40px; + &__titleAr { + font-weight: 100; } - } - - .subtitle { - display: block; - font-size: 27px; - margin: 0 0 30px; - - @include media-breakpoint-down(sm) { - font-size: 22px; - margin: 0 0 15px; + &__title { + font-weight: bold; } - @include media-breakpoint-down(xs) { - font-size: 18px; + &__subTitleWrap { + display: flex; + justify-content: space-between; + font-size: 22px; + color: var(--secondary-color); + font-weight: bold; + flex-direction: column; } - } -} - -.certificate-body { text-align: center; } - -.certificate-main { - overflow: hidden; - - p, - h2 { - margin: 0 0 30px; - font-size: 38px; - font-weight: 500; - - @include media-breakpoint-down(sm) { - margin: 0 0 15px; - font-size: 20px; + &__personName { + font-size: 22px; } - - @include media-breakpoint-down(xs) { - margin: 0 0 10px; - font-size: 18px; + &__subTitleBody, + &__personWrap, + &__innerDetailWrap { + display: flex; + justify-content: space-between; + gap: 10px; } - } - - .sub-title, - .main-title { - margin: 0 0 34px; - - @include media-breakpoint-down(sm) { - margin: 0 0 20px; + &__innerDetailWrap { + font-size: 18px; } - } - - .limited-text { - max-width: 900px; - margin: 0 auto 97px; - text-align: right; - - @include media-breakpoint-down(sm) { - margin: 0 0 40px; + &__topWrapper { + display: flex; + flex-direction: column; + gap: 50px; } - - @include media-breakpoint-down(xs) { - margin: 0 0 20px; + &__list { + display: flex; + gap: 10px; + justify-content: space-between; + font-size: 20px; + color: var(--secondary-color); } - - .text-secondary { - margin: 0 13px; - - @include media-breakpoint-down(sm) { - margin: 0 6px; - } + &__listWraper { + display: flex; + flex-direction: column; } - } -} - -@media print { - body { - margin: 0; - } - - .certificate-header-col { - &:first-child { - padding-left: 100px; + &__valueListWrap { + display: flex; + flex-direction: column; } - } - - .certificate-header { - padding: 0 0 40px; - } - - .certificate-heading { - padding: 0; - - h1 { - font-size: 50px; + @media only screen and (max-width: 1200px) { + gap: 20px; + .sdaia-academy-logo { + width: 200px; + } + .sdaia-logo { + width: 160px; + } + + &__list { + font-size: 18px; + } + + &__mainTitleWrap { + font-size: 25px; + } + &__bodywraper { + gap: 25px; + } + &__subTitleWrap { + font-size: 18px; + } + &__personName { + font-size: 20px; + } } - } - .certificate-main { - - p, - h2 { - margin: 0 0 25px; - font-size: 30px; - font-weight: 500; + @media only screen and (max-width: 992px) { + padding: 100px 11%; + .sdaia-academy-logo { + width: 1700px; + } + .sdaia-logo { + width: 150px; + } + &__topWrapper { + gap: 30px; + } + &__bodywraper { + gap: 20px; + } } - .main-title { - margin: 0 0 25px; + @media only screen and (max-width: 768px) { + padding: 70px 11%; + &__topWrapper { + gap: 20px; + } + .sdaia-academy-logo { + width: 150px; + } + .sdaia-logo { + width: 120px; + } + + &__list { + font-size: 14px; + } + + &__mainTitleWrap { + font-size: 20px; + } + &__bodywraper { + gap: 20px; + } + &__subTitleWrap, + &__innerDetailWrap { + font-size: 15px; + } } - .limited-text { - margin: 0 auto 50px; + @media only screen and (max-width: 556px) { + padding: 60px 13%; + gap: 15px; + + .sdaia-academy-logo { + width: 100px; + } + .sdaia-logo { + width: 80px; + } + &__bodywraper, + &__topWrapper { + gap: 10px; + } + + &__mainTitleWrap { + font-size: 18px; + } + &__subTitleWrap, + &__list, + &__innerDetailWrap { + font-size: 12px; + } + &__list{ + gap: 5px; + } + &__personName { + font-size: 18px; + } } - } +} - .certificate-wrapper { - padding: 120px 11.9%; - } +[dir="rtl"] { + .certificateWrapper { + .text-align{ + text-align: left; + } + } } diff --git a/lms/templates/certificates/_accomplishment-rendering.html b/lms/templates/certificates/_accomplishment-rendering.html index 1bdae34c8075..2231c61fa462 100644 --- a/lms/templates/certificates/_accomplishment-rendering.html +++ b/lms/templates/certificates/_accomplishment-rendering.html @@ -1,39 +1,93 @@ - - - - - - SDAIA Academy - Certificate of completion - - -
-
-
- - SDAIA Academy Main -
-
- SDAIA Logo -
-
-
-
-

شهادة إتمام

- CERTIFICATE OF COMPLETION -
-
-

: الهيئة السعودية للبيانات والذكاء الاصطناعي ( سدايا ) تمنح

-

${accomplishment_copy_name}

-

هذه الشهادة وذلك لإتمام البرنامج التدريبي

-

${accomplishment_copy_course_name}

-

ومدته${course_duration} ساعات تدريبية بتاريخ ${certificate_date_issued}

-

مع تمنياتنا بدوام التوفيق والنجاح

-

أكاديمية سدايا

-
-
-
- + + + + + SDAIA Academy - Certificate of completion + + + +
+
+ + +
+
+
+

+
شهادة إتمام
+
CERTIFICATE OF COMPLETION
+

+ +
+
+
+ Saudi Data and AI Authority (SDAIA) Certifies that +
+
+ :الهيئة السعودية للبيانات والذكاء الاصطناعي ( سدايا ) تمنح +
+
+
+ + +
+
+
+
+
+
+
+ has succsessfully completed the + شهادة إتمام ا لدورة التدريبية +
+
+ + +
+
+
+
+ + Consisting of + (${course_duration}) + hours + ساعة تدريبية(${arabic_course_duration})بمعدل + +
+
+ + +
+
+
+
+
+
+ diff --git a/xmodule/course_block.py b/xmodule/course_block.py index 3cf3a1af3563..1fbda9047feb 100644 --- a/xmodule/course_block.py +++ b/xmodule/course_block.py @@ -681,6 +681,13 @@ class CourseFields: # lint-amnesty, pylint: disable=missing-class-docstring scope=Scope.settings, ) + cert_english_name = Dict( + # Translators: This field is the container for course-specific certificate configuration values + display_name=_("Certificate Web/HTML View Overrides"), + # Translators: These overrides allow for an alternative configuration of the certificate web view + help=_("Enter course-specific overrides for the Web/HTML template parameters here (JSON format)"), + scope=Scope.settings, + ) # An extra property is used rather than the wiki_slug/number because # there are courses that change the number for different runs. This allows # courses to share the same css_class across runs even if they have