learning-paths-plugin 0.3.0__tar.gz → 0.3.1__tar.gz
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.
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/CHANGELOG.rst +18 -0
- {learning_paths_plugin-0.3.0/learning_paths_plugin.egg-info → learning_paths_plugin-0.3.1}/PKG-INFO +19 -1
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/__init__.py +1 -1
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/serializers.py +100 -1
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/urls.py +2 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/views.py +27 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/compat.py +17 -0
- learning_paths_plugin-0.3.1/learning_paths/migrations/0008_remove_learningpathstep_relative_due_date_in_days.py +17 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/models.py +15 -10
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1/learning_paths_plugin.egg-info}/PKG-INFO +19 -1
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/SOURCES.txt +1 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/tests/test_models.py +8 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/LICENSE.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/MANIFEST.in +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/README.rst +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/admin.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/__init__.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/urls.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/__init__.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/filters.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/permissions.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/utils.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/apps.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/keys.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0001_initial.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0002_learningpath_uuid.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0003_learningpath_subtitle.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0004_auto_20240207_1633.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0005_learningpathstep_weight_learningpathgradingcriteria.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0006_enrollment_models.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/0007_replace_uuid_with_learningpathkey.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/__init__.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/receivers.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/settings.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/templates/learning_paths/base.html +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/urls.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/dependency_links.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/entry_points.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/not-zip-safe +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/requires.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths_plugin.egg-info/top_level.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/pyproject.toml +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/requirements/base.in +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/requirements/constraints.txt +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/setup.cfg +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/setup.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/tests/test_keys.py +0 -0
- {learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/tests/test_receivers.py +0 -0
|
@@ -16,6 +16,24 @@ Unreleased
|
|
|
16
16
|
|
|
17
17
|
*
|
|
18
18
|
|
|
19
|
+
0.3.1 - 2025-04-14
|
|
20
|
+
******************
|
|
21
|
+
|
|
22
|
+
Added
|
|
23
|
+
=====
|
|
24
|
+
|
|
25
|
+
* API for listing and retrieving Learning Paths.
|
|
26
|
+
|
|
27
|
+
Fixed
|
|
28
|
+
=====
|
|
29
|
+
|
|
30
|
+
* Automatically create grading criteria for Learning Paths.
|
|
31
|
+
|
|
32
|
+
Changed
|
|
33
|
+
=======
|
|
34
|
+
|
|
35
|
+
* Replaced relative due dates with actual due dates from course runs.
|
|
36
|
+
|
|
19
37
|
0.3.0 - 2025-04-03
|
|
20
38
|
******************
|
|
21
39
|
|
{learning_paths_plugin-0.3.0/learning_paths_plugin.egg-info → learning_paths_plugin-0.3.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: learning-paths-plugin
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Learning Paths plugin
|
|
5
5
|
Home-page: https://github.com/open-craft/learning-paths-plugin
|
|
6
6
|
Author: OpenCraft
|
|
@@ -120,6 +120,24 @@ Unreleased
|
|
|
120
120
|
|
|
121
121
|
*
|
|
122
122
|
|
|
123
|
+
0.3.1 - 2025-04-14
|
|
124
|
+
******************
|
|
125
|
+
|
|
126
|
+
Added
|
|
127
|
+
=====
|
|
128
|
+
|
|
129
|
+
* API for listing and retrieving Learning Paths.
|
|
130
|
+
|
|
131
|
+
Fixed
|
|
132
|
+
=====
|
|
133
|
+
|
|
134
|
+
* Automatically create grading criteria for Learning Paths.
|
|
135
|
+
|
|
136
|
+
Changed
|
|
137
|
+
=======
|
|
138
|
+
|
|
139
|
+
* Replaced relative due dates with actual due dates from course runs.
|
|
140
|
+
|
|
123
141
|
0.3.0 - 2025-04-03
|
|
124
142
|
******************
|
|
125
143
|
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/serializers.py
RENAMED
|
@@ -4,7 +4,14 @@ Serializer for LearningPath.
|
|
|
4
4
|
|
|
5
5
|
from rest_framework import serializers
|
|
6
6
|
|
|
7
|
-
from learning_paths.models import
|
|
7
|
+
from learning_paths.models import (
|
|
8
|
+
AcquiredSkill,
|
|
9
|
+
LearningPath,
|
|
10
|
+
LearningPathEnrollment,
|
|
11
|
+
LearningPathStep,
|
|
12
|
+
RequiredSkill,
|
|
13
|
+
Skill,
|
|
14
|
+
)
|
|
8
15
|
|
|
9
16
|
DEFAULT_STATUS = "active"
|
|
10
17
|
IMAGE_WIDTH = 1440
|
|
@@ -87,6 +94,98 @@ class LearningPathGradeSerializer(serializers.Serializer):
|
|
|
87
94
|
required_grade = serializers.FloatField()
|
|
88
95
|
|
|
89
96
|
|
|
97
|
+
class LearningPathStepSerializer(serializers.ModelSerializer):
|
|
98
|
+
class Meta:
|
|
99
|
+
model = LearningPathStep
|
|
100
|
+
fields = ["order", "course_key", "due_date", "weight"]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class LearningPathListSerializer(serializers.ModelSerializer):
|
|
104
|
+
"""Serializer for the learning path list."""
|
|
105
|
+
|
|
106
|
+
steps = LearningPathStepSerializer(many=True, read_only=True)
|
|
107
|
+
required_completion = serializers.FloatField(
|
|
108
|
+
source="grading_criteria.required_completion", read_only=True
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
class Meta:
|
|
112
|
+
model = LearningPath
|
|
113
|
+
fields = [
|
|
114
|
+
"key",
|
|
115
|
+
"slug",
|
|
116
|
+
"display_name",
|
|
117
|
+
"image_url",
|
|
118
|
+
"sequential",
|
|
119
|
+
"steps",
|
|
120
|
+
"required_completion",
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class SkillSerializer(serializers.ModelSerializer):
|
|
125
|
+
class Meta:
|
|
126
|
+
model = Skill
|
|
127
|
+
fields = ["id", "display_name"]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class RequiredSkillSerializer(serializers.ModelSerializer):
|
|
131
|
+
"""
|
|
132
|
+
Serializer for required skill.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
skill = SkillSerializer()
|
|
136
|
+
|
|
137
|
+
class Meta:
|
|
138
|
+
model = RequiredSkill
|
|
139
|
+
fields = ["skill", "level"]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class AcquiredSkillSerializer(serializers.ModelSerializer):
|
|
143
|
+
"""
|
|
144
|
+
Serializer for acquired skill.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
skill = SkillSerializer()
|
|
148
|
+
|
|
149
|
+
class Meta:
|
|
150
|
+
model = AcquiredSkill
|
|
151
|
+
fields = ["skill", "level"]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class LearningPathDetailSerializer(serializers.ModelSerializer):
|
|
155
|
+
"""
|
|
156
|
+
Serializer for learning path details.
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
steps = LearningPathStepSerializer(many=True, read_only=True)
|
|
160
|
+
required_skills = RequiredSkillSerializer(
|
|
161
|
+
source="requiredskill_set", many=True, read_only=True
|
|
162
|
+
)
|
|
163
|
+
acquired_skills = AcquiredSkillSerializer(
|
|
164
|
+
source="acquiredskill_set", many=True, read_only=True
|
|
165
|
+
)
|
|
166
|
+
required_completion = serializers.FloatField(
|
|
167
|
+
source="grading_criteria.required_completion", read_only=True
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
class Meta:
|
|
171
|
+
model = LearningPath
|
|
172
|
+
fields = [
|
|
173
|
+
"key",
|
|
174
|
+
"slug",
|
|
175
|
+
"display_name",
|
|
176
|
+
"subtitle",
|
|
177
|
+
"description",
|
|
178
|
+
"image_url",
|
|
179
|
+
"level",
|
|
180
|
+
"duration_in_days",
|
|
181
|
+
"sequential",
|
|
182
|
+
"steps",
|
|
183
|
+
"required_skills",
|
|
184
|
+
"acquired_skills",
|
|
185
|
+
"required_completion",
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
|
|
90
189
|
class LearningPathEnrollmentSerializer(serializers.ModelSerializer):
|
|
91
190
|
class Meta:
|
|
92
191
|
model = LearningPathEnrollment
|
|
@@ -9,6 +9,7 @@ from learning_paths.api.v1.views import (
|
|
|
9
9
|
LearningPathEnrollmentView,
|
|
10
10
|
LearningPathUserGradeView,
|
|
11
11
|
LearningPathUserProgressView,
|
|
12
|
+
LearningPathViewSet,
|
|
12
13
|
ListEnrollmentsView,
|
|
13
14
|
)
|
|
14
15
|
from learning_paths.keys import LEARNING_PATH_URL_PATTERN
|
|
@@ -17,6 +18,7 @@ router = routers.SimpleRouter()
|
|
|
17
18
|
router.register(
|
|
18
19
|
r"programs", LearningPathAsProgramViewSet, basename="learning-path-as-program"
|
|
19
20
|
)
|
|
21
|
+
router.register(r"learning-paths", LearningPathViewSet, basename="learning-path")
|
|
20
22
|
|
|
21
23
|
urlpatterns = router.urls + [
|
|
22
24
|
re_path(
|
|
@@ -12,6 +12,7 @@ from django.core.validators import validate_email
|
|
|
12
12
|
from django.shortcuts import get_object_or_404
|
|
13
13
|
from opaque_keys import InvalidKeyError
|
|
14
14
|
from rest_framework import generics, status, viewsets
|
|
15
|
+
from rest_framework.exceptions import NotFound
|
|
15
16
|
from rest_framework.pagination import PageNumberPagination
|
|
16
17
|
from rest_framework.permissions import IsAdminUser, IsAuthenticated
|
|
17
18
|
from rest_framework.response import Response
|
|
@@ -19,8 +20,10 @@ from rest_framework.views import APIView
|
|
|
19
20
|
|
|
20
21
|
from learning_paths.api.v1.serializers import (
|
|
21
22
|
LearningPathAsProgramSerializer,
|
|
23
|
+
LearningPathDetailSerializer,
|
|
22
24
|
LearningPathEnrollmentSerializer,
|
|
23
25
|
LearningPathGradeSerializer,
|
|
26
|
+
LearningPathListSerializer,
|
|
24
27
|
LearningPathProgressSerializer,
|
|
25
28
|
)
|
|
26
29
|
from learning_paths.keys import LearningPathKey
|
|
@@ -125,6 +128,30 @@ class LearningPathUserGradeView(APIView):
|
|
|
125
128
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
126
129
|
|
|
127
130
|
|
|
131
|
+
class LearningPathViewSet(viewsets.ReadOnlyModelViewSet):
|
|
132
|
+
"""
|
|
133
|
+
ViewSet for listing all learning paths and retrieving a specific learning path's details,
|
|
134
|
+
including steps and associated skills.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
queryset = LearningPath.objects.prefetch_related("steps", "grading_criteria")
|
|
138
|
+
permission_classes = (IsAuthenticated,)
|
|
139
|
+
pagination_class = PageNumberPagination
|
|
140
|
+
lookup_field = "key"
|
|
141
|
+
|
|
142
|
+
def get_serializer_class(self):
|
|
143
|
+
if self.action == "list":
|
|
144
|
+
return LearningPathListSerializer
|
|
145
|
+
return LearningPathDetailSerializer
|
|
146
|
+
|
|
147
|
+
def get_object(self):
|
|
148
|
+
"""Gracefully handle an invalid learning path key format."""
|
|
149
|
+
try:
|
|
150
|
+
return super().get_object()
|
|
151
|
+
except InvalidKeyError as exc:
|
|
152
|
+
raise NotFound("Invalid learning path key format.") from exc
|
|
153
|
+
|
|
154
|
+
|
|
128
155
|
class LearningPathEnrollmentView(APIView):
|
|
129
156
|
"""
|
|
130
157
|
API View to handle changes to LearningPathEnrollment model
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Compatibility layer for testing without Open edX.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
5
7
|
from django.contrib.auth.models import AbstractBaseUser
|
|
6
8
|
from opaque_keys.edx.keys import CourseKey
|
|
7
9
|
|
|
@@ -41,8 +43,23 @@ def get_course_keys_with_outlines():
|
|
|
41
43
|
return course_keys_with_outlines()
|
|
42
44
|
|
|
43
45
|
|
|
46
|
+
def get_course_due_date(course_key: CourseKey) -> datetime | None:
|
|
47
|
+
"""
|
|
48
|
+
Retrieve course end date.
|
|
49
|
+
"""
|
|
50
|
+
# pylint: disable=import-outside-toplevel, import-error
|
|
51
|
+
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
overview = CourseOverview.objects.get(id=course_key)
|
|
55
|
+
return overview.end
|
|
56
|
+
except CourseOverview.DoesNotExist:
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
44
60
|
__all__ = [
|
|
45
61
|
"get_course_keys_with_outlines",
|
|
46
62
|
"get_catalog_api_client",
|
|
47
63
|
"get_user_course_grade",
|
|
64
|
+
"get_course_due_date",
|
|
48
65
|
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Generated by Django 4.2.16 on 2025-03-24 10:37
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('learning_paths', '0007_replace_uuid_with_learningpathkey'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.RemoveField(
|
|
14
|
+
model_name='learningpathstep',
|
|
15
|
+
name='relative_due_date_in_days',
|
|
16
|
+
),
|
|
17
|
+
]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Database models for learning_paths.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from datetime import timedelta
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
6
|
from uuid import uuid4
|
|
7
7
|
|
|
8
8
|
from django.contrib import auth
|
|
@@ -13,7 +13,7 @@ from model_utils.models import TimeStampedModel
|
|
|
13
13
|
from opaque_keys.edx.django.models import CourseKeyField
|
|
14
14
|
from simple_history.models import HistoricalRecords
|
|
15
15
|
|
|
16
|
-
from .compat import get_user_course_grade
|
|
16
|
+
from .compat import get_course_due_date, get_user_course_grade
|
|
17
17
|
from .keys import LearningPathKeyField
|
|
18
18
|
|
|
19
19
|
User = auth.get_user_model()
|
|
@@ -88,6 +88,14 @@ class LearningPath(TimeStampedModel):
|
|
|
88
88
|
"""User-friendly string representation of this model."""
|
|
89
89
|
return self.display_name
|
|
90
90
|
|
|
91
|
+
def save(self, *args, **kwargs):
|
|
92
|
+
"""Create default grading criteria when a new learning path is created."""
|
|
93
|
+
is_new = self._state.adding
|
|
94
|
+
super().save(*args, **kwargs)
|
|
95
|
+
|
|
96
|
+
if is_new and not hasattr(self, "grading_criteria"):
|
|
97
|
+
LearningPathGradingCriteria.objects.get_or_create(learning_path=self)
|
|
98
|
+
|
|
91
99
|
|
|
92
100
|
class LearningPathStep(TimeStampedModel):
|
|
93
101
|
"""
|
|
@@ -105,14 +113,6 @@ class LearningPathStep(TimeStampedModel):
|
|
|
105
113
|
learning_path = models.ForeignKey(
|
|
106
114
|
LearningPath, related_name="steps", on_delete=models.CASCADE
|
|
107
115
|
)
|
|
108
|
-
relative_due_date_in_days = models.PositiveIntegerField(
|
|
109
|
-
blank=True,
|
|
110
|
-
null=True,
|
|
111
|
-
verbose_name=_("Due date (days)"),
|
|
112
|
-
help_text=_(
|
|
113
|
-
"Used to calculate the due date from the starting date of the course."
|
|
114
|
-
),
|
|
115
|
-
)
|
|
116
116
|
order = models.PositiveIntegerField(
|
|
117
117
|
blank=True,
|
|
118
118
|
null=True,
|
|
@@ -130,6 +130,11 @@ class LearningPathStep(TimeStampedModel):
|
|
|
130
130
|
),
|
|
131
131
|
)
|
|
132
132
|
|
|
133
|
+
@property
|
|
134
|
+
def due_date(self) -> datetime | None:
|
|
135
|
+
"""Retrieve the due date for this course."""
|
|
136
|
+
return get_course_due_date(self.course_key)
|
|
137
|
+
|
|
133
138
|
def __str__(self):
|
|
134
139
|
"""User-friendly string representation of this model."""
|
|
135
140
|
return "{}: {}".format(self.order, self.course_key)
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1/learning_paths_plugin.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: learning-paths-plugin
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Learning Paths plugin
|
|
5
5
|
Home-page: https://github.com/open-craft/learning-paths-plugin
|
|
6
6
|
Author: OpenCraft
|
|
@@ -120,6 +120,24 @@ Unreleased
|
|
|
120
120
|
|
|
121
121
|
*
|
|
122
122
|
|
|
123
|
+
0.3.1 - 2025-04-14
|
|
124
|
+
******************
|
|
125
|
+
|
|
126
|
+
Added
|
|
127
|
+
=====
|
|
128
|
+
|
|
129
|
+
* API for listing and retrieving Learning Paths.
|
|
130
|
+
|
|
131
|
+
Fixed
|
|
132
|
+
=====
|
|
133
|
+
|
|
134
|
+
* Automatically create grading criteria for Learning Paths.
|
|
135
|
+
|
|
136
|
+
Changed
|
|
137
|
+
=======
|
|
138
|
+
|
|
139
|
+
* Replaced relative due dates with actual due dates from course runs.
|
|
140
|
+
|
|
123
141
|
0.3.0 - 2025-04-03
|
|
124
142
|
******************
|
|
125
143
|
|
|
@@ -30,6 +30,7 @@ learning_paths/migrations/0004_auto_20240207_1633.py
|
|
|
30
30
|
learning_paths/migrations/0005_learningpathstep_weight_learningpathgradingcriteria.py
|
|
31
31
|
learning_paths/migrations/0006_enrollment_models.py
|
|
32
32
|
learning_paths/migrations/0007_replace_uuid_with_learningpathkey.py
|
|
33
|
+
learning_paths/migrations/0008_remove_learningpathstep_relative_due_date_in_days.py
|
|
33
34
|
learning_paths/migrations/__init__.py
|
|
34
35
|
learning_paths/templates/learning_paths/base.html
|
|
35
36
|
learning_paths_plugin.egg-info/PKG-INFO
|
|
@@ -77,3 +77,11 @@ class TestLearningPath:
|
|
|
77
77
|
key=LearningPathKey("org2", "number2", "run2", "group2"),
|
|
78
78
|
slug=learning_path.slug,
|
|
79
79
|
)
|
|
80
|
+
|
|
81
|
+
def test_grading_criteria_auto_creation(self, learning_path):
|
|
82
|
+
"""Test that grading criteria is automatically created with a learning path."""
|
|
83
|
+
|
|
84
|
+
criteria = learning_path.grading_criteria
|
|
85
|
+
assert criteria is not None
|
|
86
|
+
assert criteria.required_completion == 0.80
|
|
87
|
+
assert criteria.required_grade == 0.75
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/__init__.py
RENAMED
|
File without changes
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/filters.py
RENAMED
|
File without changes
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/api/v1/permissions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{learning_paths_plugin-0.3.0 → learning_paths_plugin-0.3.1}/learning_paths/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|