learning-credentials 0.3.0rc3__py3-none-any.whl → 0.3.0rc10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,48 +0,0 @@
1
- <div class="credentials-block">
2
- {% if is_author_mode %}
3
- <p>The Studio view of this XBlock is not supported yet. Please preview the XBlock in the LMS.</p>
4
- {% else %}
5
- <h3>Check Your Certificate Eligibility Status</h3>
6
- <ul class="credentials-list">
7
- {% if credentials %}
8
- {% for credential_type, credential in credentials.items %}
9
- <li class="credential">
10
- <strong>Type:</strong> {{ credential_type }}
11
- {% if credential.download_url %}
12
- <p class="credential-status">Congratulations on finishing strong!</p>
13
- <strong>Download Link:</strong> <a href="{{ credential.download_url }}">Download Certificate</a>
14
- {% elif credential.status == credential.Status.ERROR %}
15
- <p class="credential-status">Something went wrong. Please contact us via the Help page for assistance.</p>
16
- {% endif %}
17
- <button class="btn-brand generate-credential" data-credential-type="{{ credential_type }}" disabled>
18
- Certificate Claimed
19
- </button>
20
- <div id="message-area-{{ credential_type }}"></div>
21
- </li>
22
- {% endfor %}
23
- {% endif %}
24
-
25
- {% if eligible_types %}
26
- {% for credential_type, is_eligible in eligible_types.items %}
27
- {% if not credentials or credential_type not in credentials %}
28
- <li class="credential">
29
- <strong>Type:</strong> {{ credential_type }}
30
- {% if is_eligible %}
31
- <p class="credential-status">Congratulations! You have earned this certificate. Please claim it below.</p>
32
- <button class="btn-brand generate-credential" data-credential-type="{{ credential_type }}">
33
- Claim Certificate
34
- </button>
35
- {% else %}
36
- <p class="certificate-status">You are not yet eligible for this certificate.</p>
37
- <button class="btn-brand generate-certificate" data-certificate-type="{{ credential_type }}" disabled>
38
- Claim Certificate
39
- </button>
40
- {% endif %}
41
- <div id="message-area-{{ credential_type }}"></div>
42
- </li>
43
- {% endif %}
44
- {% endfor %}
45
- {% endif %}
46
- </ul>
47
- {% endif %}
48
- </div>
@@ -1,23 +0,0 @@
1
- function CredentialsXBlock(runtime, element) {
2
- function generateCredential(event) {
3
- const button = event.target;
4
- const credentialType = $(button).data('credential-type');
5
- const handlerUrl = runtime.handlerUrl(element, 'generate_credential');
6
-
7
- $.post(handlerUrl, JSON.stringify({ credential_type: credentialType }))
8
- .done(function(data) {
9
- const messageArea = $(element).find('#message-area-' + credentialType);
10
- if (data.status === 'success') {
11
- messageArea.html('<p style="color:green;">Certificate generation initiated successfully.</p>');
12
- } else {
13
- messageArea.html('<p style="color:red;">' + data.message + '</p>');
14
- }
15
- })
16
- .fail(function() {
17
- const messageArea = $(element).find('#message-area-' + credentialType);
18
- messageArea.html('<p style="color:red;">An error occurred while processing your request.</p>');
19
- });
20
- }
21
-
22
- $(element).find('.generate-credential').on('click', generateCredential);
23
- }
@@ -1,85 +0,0 @@
1
- """XBlocks for Learning Credentials."""
2
-
3
- import logging
4
-
5
- from xblock.core import XBlock
6
- from xblock.fields import Scope, String
7
- from xblock.fragment import Fragment
8
- from xblock.utils.resources import ResourceLoader
9
- from xblock.utils.studio_editable import StudioEditableXBlockMixin
10
-
11
- from .core_api import generate_credential_for_user, get_eligible_users_by_credential_type, get_user_credentials_by_type
12
-
13
- loader = ResourceLoader(__name__)
14
- logger = logging.getLogger(__name__)
15
-
16
-
17
- class CredentialsXBlock(StudioEditableXBlockMixin, XBlock):
18
- """XBlock that displays the credential eligibility status and allows eligible users to generate credentials."""
19
-
20
- display_name = String(
21
- help='The display name for this component.',
22
- scope=Scope.content,
23
- display_name="Display name",
24
- default='Credentials',
25
- )
26
-
27
- def student_view(self, context) -> Fragment: # noqa: ANN001, ARG002
28
- """Main view for the student. Displays the credential eligibility or ineligibility status."""
29
- fragment = Fragment()
30
- eligible_types = False
31
- credentials = []
32
-
33
- if not (is_author_mode := getattr(self.runtime, 'is_author_mode', False)):
34
- credentials = self.get_credentials()
35
- eligible_types = self.get_eligible_credential_types()
36
-
37
- # Filter out the eligible types that already have a credential generated
38
- for cred_type in credentials:
39
- if cred_type in eligible_types:
40
- del eligible_types[cred_type]
41
-
42
- fragment.add_content(
43
- loader.render_django_template(
44
- 'public/html/credentials_xblock.html',
45
- {
46
- 'credentials': credentials,
47
- 'eligible_types': eligible_types,
48
- 'is_author_mode': is_author_mode,
49
- },
50
- )
51
- )
52
-
53
- fragment.add_css_url(self.runtime.local_resource_url(self, "public/css/credentials_xblock.css"))
54
- fragment.add_javascript_url(self.runtime.local_resource_url(self, "public/js/credentials_xblock.js"))
55
- fragment.initialize_js('CredentialsXBlock')
56
- return fragment
57
-
58
- def get_eligible_credential_types(self) -> dict[str, bool]:
59
- """Retrieve the eligibility status for each credential type."""
60
- eligible_users = get_eligible_users_by_credential_type(self.runtime.course_id, user_id=self.scope_ids.user_id)
61
-
62
- return {credential_type: bool(users) for credential_type, users in eligible_users.items()}
63
-
64
- def get_credentials(self) -> dict[str, dict[str, str]]:
65
- """Retrieve the credentials for the current user in the current course."""
66
- return get_user_credentials_by_type(self.runtime.course_id, self.scope_ids.user_id)
67
-
68
- @XBlock.json_handler
69
- def generate_credential(self, data: dict, suffix: str = '') -> dict[str, str]: # noqa: ARG002
70
- """Handler for generating a credential for a specific type."""
71
- credential_type = data.get('credential_type')
72
- if not credential_type:
73
- return {'status': 'error', 'message': 'No credential type specified.'}
74
-
75
- course_id = self.runtime.course_id
76
- user_id = self.scope_ids.user_id
77
- logger.info(
78
- 'Generating a credential for user %s in course %s with type %s.', user_id, course_id, credential_type
79
- )
80
-
81
- try:
82
- generate_credential_for_user(course_id, credential_type, user_id)
83
- except ValueError as e:
84
- return {'status': 'error', 'message': str(e)}
85
- return {'status': 'success'}