Skip to content

Commit 3de8d4f

Browse files
feat: Add Content Groups API v2 endpoints for Instructor Dashboard
- Add GET /api/instructor/v2/courses/{course_id}/group_configurations - Add GET /api/instructor/v2/courses/{course_id}/group_configurations/{id} - Create shared constants module for course groups
1 parent 3a1d929 commit 3de8d4f

File tree

10 files changed

+632
-11
lines changed

10 files changed

+632
-11
lines changed

cms/djangoapps/contentstore/course_group_config.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,21 @@
1212
from cms.djangoapps.contentstore.utils import reverse_usage_url
1313
from common.djangoapps.util.db import MYSQL_MAX_INT, generate_int_id
1414
from lms.lib.utils import get_parent_unit
15+
# Re-exported for backward compatibility - other modules import these from here
16+
from openedx.core.djangoapps.course_groups.constants import ( # pylint: disable=unused-import
17+
COHORT_SCHEME,
18+
CONTENT_GROUP_CONFIGURATION_DESCRIPTION,
19+
CONTENT_GROUP_CONFIGURATION_NAME,
20+
ENROLLMENT_SCHEME,
21+
RANDOM_SCHEME,
22+
)
1523
from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition
1624
from xmodule.partitions.partitions import MINIMUM_UNUSED_PARTITION_ID, ReadOnlyUserPartitionError, UserPartition # lint-amnesty, pylint: disable=wrong-import-order
1725
from xmodule.partitions.partitions_service import get_all_partitions_for_course # lint-amnesty, pylint: disable=wrong-import-order
1826
from xmodule.split_test_block import get_split_user_partitions # lint-amnesty, pylint: disable=wrong-import-order
1927

2028
MINIMUM_GROUP_ID = MINIMUM_UNUSED_PARTITION_ID
2129

22-
RANDOM_SCHEME = "random"
23-
COHORT_SCHEME = "cohort"
24-
ENROLLMENT_SCHEME = "enrollment_track"
25-
26-
CONTENT_GROUP_CONFIGURATION_DESCRIPTION = _(
27-
'The groups in this configuration can be mapped to cohorts in the Instructor Dashboard.'
28-
)
29-
30-
CONTENT_GROUP_CONFIGURATION_NAME = _('Content Groups')
31-
3230
log = logging.getLogger(__name__)
3331

3432

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
Constants for course groups.
3+
"""
4+
from django.utils.translation import gettext_lazy as _
5+
6+
COHORT_SCHEME = 'cohort'
7+
RANDOM_SCHEME = 'random'
8+
ENROLLMENT_SCHEME = 'enrollment_track'
9+
10+
CONTENT_GROUP_CONFIGURATION_NAME = _('Content Groups')
11+
CONTENT_GROUP_CONFIGURATION_DESCRIPTION = _(
12+
'Use this group configuration to control access to content.'
13+
)

openedx/core/djangoapps/course_groups/rest_api/__init__.py

Whitespace-only changes.
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
swagger: '2.0'
2+
info:
3+
title: Content Groups API v2
4+
version: 2.0.0
5+
description: |
6+
REST API for managing content group configurations.
7+
8+
Content groups allow course authors to restrict access to specific
9+
course content based on cohort membership.
10+
11+
host: courses.example.com
12+
basePath: /
13+
schemes:
14+
- https
15+
16+
securityDefinitions:
17+
JWTAuth:
18+
type: apiKey
19+
in: header
20+
name: Authorization
21+
description: JWT token authentication.
22+
23+
security:
24+
- JWTAuth: []
25+
26+
tags:
27+
- name: Content Groups
28+
description: Content group configuration management
29+
30+
parameters:
31+
CourseId:
32+
name: course_id
33+
in: path
34+
required: true
35+
type: string
36+
description: The course key (e.g., course-v1:org+course+run)
37+
ConfigurationId:
38+
name: configuration_id
39+
in: path
40+
required: true
41+
type: integer
42+
description: The ID of the content group configuration
43+
44+
paths:
45+
/api/cohorts/v2/courses/{course_id}/group_configurations:
46+
get:
47+
tags:
48+
- Content Groups
49+
summary: List content group configurations
50+
description: |
51+
Returns all content group configurations (scheme='cohort') for a course.
52+
If no content group exists, an empty one is automatically created.
53+
operationId: listGroupConfigurations
54+
produces:
55+
- application/json
56+
parameters:
57+
- $ref: '#/parameters/CourseId'
58+
responses:
59+
200:
60+
description: Content groups retrieved successfully
61+
schema:
62+
$ref: '#/definitions/ContentGroupsListResponse'
63+
400:
64+
description: Invalid course key
65+
401:
66+
description: Authentication required
67+
403:
68+
description: User lacks instructor permission
69+
404:
70+
description: Course not found
71+
72+
/api/cohorts/v2/courses/{course_id}/group_configurations/{configuration_id}:
73+
get:
74+
tags:
75+
- Content Groups
76+
summary: Get content group configuration details
77+
description: |
78+
Retrieve a specific content group configuration by ID.
79+
Only returns configurations with scheme='cohort'.
80+
operationId: getGroupConfiguration
81+
produces:
82+
- application/json
83+
parameters:
84+
- $ref: '#/parameters/CourseId'
85+
- $ref: '#/parameters/ConfigurationId'
86+
responses:
87+
200:
88+
description: Configuration retrieved successfully
89+
schema:
90+
$ref: '#/definitions/ContentGroupConfiguration'
91+
400:
92+
description: Invalid course key
93+
401:
94+
description: Authentication required
95+
403:
96+
description: User lacks instructor permission
97+
404:
98+
description: Configuration not found
99+
100+
definitions:
101+
Group:
102+
type: object
103+
properties:
104+
id:
105+
type: integer
106+
description: Unique identifier for the group
107+
name:
108+
type: string
109+
description: Display name of the group
110+
version:
111+
type: integer
112+
description: Version number of the group
113+
usage:
114+
type: array
115+
items:
116+
type: object
117+
description: List of content blocks using this group
118+
119+
ContentGroupConfiguration:
120+
type: object
121+
properties:
122+
id:
123+
type: integer
124+
description: Unique identifier for the configuration
125+
name:
126+
type: string
127+
description: Display name (typically "Content Groups")
128+
scheme:
129+
type: string
130+
enum: [cohort]
131+
description: Partition scheme type
132+
description:
133+
type: string
134+
description: Human-readable description
135+
parameters:
136+
type: object
137+
description: Additional configuration parameters
138+
groups:
139+
type: array
140+
items:
141+
$ref: '#/definitions/Group'
142+
description: List of groups in this configuration
143+
active:
144+
type: boolean
145+
description: Whether this configuration is active
146+
version:
147+
type: integer
148+
description: Version number of the configuration
149+
read_only:
150+
type: boolean
151+
description: Whether this configuration is system-managed
152+
153+
ContentGroupsListResponse:
154+
type: object
155+
properties:
156+
all_group_configurations:
157+
type: array
158+
items:
159+
$ref: '#/definitions/ContentGroupConfiguration'
160+
description: List of content group configurations
161+
should_show_enrollment_track:
162+
type: boolean
163+
description: Whether enrollment track groups should be displayed
164+
should_show_experiment_groups:
165+
type: boolean
166+
description: Whether experiment groups should be displayed
167+
group_configuration_url:
168+
type: string
169+
description: Base URL for accessing individual configurations
170+
course_outline_url:
171+
type: string
172+
description: URL to the course outline
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
Serializers for content group configurations REST API.
3+
"""
4+
from rest_framework import serializers
5+
6+
7+
class GroupSerializer(serializers.Serializer):
8+
"""
9+
Serializer for a single group within a content group configuration.
10+
"""
11+
id = serializers.IntegerField()
12+
name = serializers.CharField(max_length=255)
13+
version = serializers.IntegerField()
14+
usage = serializers.ListField(
15+
child=serializers.DictField(),
16+
required=False,
17+
default=list
18+
)
19+
20+
21+
class ContentGroupConfigurationSerializer(serializers.Serializer):
22+
"""
23+
Serializer for a content group configuration (UserPartition with scheme='cohort').
24+
"""
25+
id = serializers.IntegerField()
26+
name = serializers.CharField(max_length=255)
27+
scheme = serializers.CharField()
28+
description = serializers.CharField(allow_blank=True)
29+
parameters = serializers.DictField()
30+
groups = GroupSerializer(many=True)
31+
active = serializers.BooleanField()
32+
version = serializers.IntegerField()
33+
is_read_only = serializers.BooleanField(required=False, default=False)
34+
35+
36+
class ContentGroupsListResponseSerializer(serializers.Serializer):
37+
"""
38+
Response serializer for listing all content groups.
39+
"""
40+
all_group_configurations = ContentGroupConfigurationSerializer(many=True)
41+
should_show_enrollment_track = serializers.BooleanField()
42+
should_show_experiment_groups = serializers.BooleanField()
43+
context_course = serializers.JSONField(required=False, allow_null=True)
44+
group_configuration_url = serializers.CharField()
45+
course_outline_url = serializers.CharField()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Tests for Content Groups REST API v2.
3+
"""

0 commit comments

Comments
 (0)