Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ repos:
- ".*/generated/"
additional_dependencies: ["gibberish-detector"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.6.5"
rev: "v0.6.6"
hooks:
- id: ruff-format
- id: ruff
Expand Down
152 changes: 152 additions & 0 deletions frontends/api/src/generated/v1/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,18 @@ export interface CourseResource {
* @memberof CourseResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof CourseResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof CourseResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {CourseResourceResourceTypeEnum}
Expand Down Expand Up @@ -844,6 +856,62 @@ export const CourseResourceDeliveryInnerCodeEnum = {
export type CourseResourceDeliveryInnerCodeEnum =
(typeof CourseResourceDeliveryInnerCodeEnum)[keyof typeof CourseResourceDeliveryInnerCodeEnum]

/**
*
* @export
* @interface CourseResourceFormatInner
*/
export interface CourseResourceFormatInner {
/**
*
* @type {string}
* @memberof CourseResourceFormatInner
*/
code: CourseResourceFormatInnerCodeEnum
/**
*
* @type {string}
* @memberof CourseResourceFormatInner
*/
name: string
}

export const CourseResourceFormatInnerCodeEnum = {
Synchronous: "synchronous",
Asynchronous: "asynchronous",
} as const

export type CourseResourceFormatInnerCodeEnum =
(typeof CourseResourceFormatInnerCodeEnum)[keyof typeof CourseResourceFormatInnerCodeEnum]

/**
*
* @export
* @interface CourseResourcePaceInner
*/
export interface CourseResourcePaceInner {
/**
*
* @type {string}
* @memberof CourseResourcePaceInner
*/
code: CourseResourcePaceInnerCodeEnum
/**
*
* @type {string}
* @memberof CourseResourcePaceInner
*/
name: string
}

export const CourseResourcePaceInnerCodeEnum = {
SelfPaced: "self_paced",
InstructorPaced: "instructor_paced",
} as const

export type CourseResourcePaceInnerCodeEnum =
(typeof CourseResourcePaceInnerCodeEnum)[keyof typeof CourseResourcePaceInnerCodeEnum]

/**
* Serializer for course resources
* @export
Expand Down Expand Up @@ -1376,6 +1444,18 @@ export interface LearningPathResource {
* @memberof LearningPathResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof LearningPathResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof LearningPathResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {LearningPathResourceResourceTypeEnum}
Expand Down Expand Up @@ -2100,6 +2180,18 @@ export interface LearningResourceRun {
* @memberof LearningResourceRun
*/
delivery: Array<CourseResourceDeliveryInner>
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof LearningResourceRun
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof LearningResourceRun
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {string}
Expand Down Expand Up @@ -4049,6 +4141,18 @@ export interface PodcastEpisodeResource {
* @memberof PodcastEpisodeResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof PodcastEpisodeResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof PodcastEpisodeResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {PodcastEpisodeResourceResourceTypeEnum}
Expand Down Expand Up @@ -4395,6 +4499,18 @@ export interface PodcastResource {
* @memberof PodcastResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof PodcastResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof PodcastResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {PodcastResourceResourceTypeEnum}
Expand Down Expand Up @@ -4961,6 +5077,18 @@ export interface ProgramResource {
* @memberof ProgramResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof ProgramResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof ProgramResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {ProgramResourceResourceTypeEnum}
Expand Down Expand Up @@ -5786,6 +5914,18 @@ export interface VideoPlaylistResource {
* @memberof VideoPlaylistResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof VideoPlaylistResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof VideoPlaylistResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {VideoPlaylistResourceResourceTypeEnum}
Expand Down Expand Up @@ -6120,6 +6260,18 @@ export interface VideoResource {
* @memberof VideoResource
*/
resource_category: string
/**
*
* @type {Array<CourseResourceFormatInner>}
* @memberof VideoResource
*/
format: Array<CourseResourceFormatInner>
/**
*
* @type {Array<CourseResourcePaceInner>}
* @memberof VideoResource
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {VideoResourceResourceTypeEnum}
Expand Down
18 changes: 18 additions & 0 deletions frontends/api/src/test-utils/factories/learningResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import type {
import {
AvailabilityEnum,
DeliveryEnum,
CourseResourcePaceInnerCodeEnum,
CourseResourceFormatInnerCodeEnum,
ResourceTypeEnum,
LearningResourceRunLevelInnerCodeEnum,
PlatformEnum,
Expand Down Expand Up @@ -186,6 +188,22 @@ const learningResourceRun: Factory<LearningResourceRun> = (overrides = {}) => {
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
pace: [
{
code: faker.helpers.arrayElement(
Object.values(CourseResourcePaceInnerCodeEnum),
),
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
format: [
{
code: faker.helpers.arrayElement(
Object.values(CourseResourceFormatInnerCodeEnum),
),
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
level: [
{
code: faker.helpers.arrayElement(
Expand Down
14 changes: 14 additions & 0 deletions learning_resources/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,17 @@ class CertificationType(ExtendedEnum):
professional = "Professional Certificate"
completion = "Certificate of Completion"
none = "No Certificate"


class Pace(ExtendedEnum):
"""Enum for resource pace types"""

self_paced = "Self-paced"
instructor_paced = "Instructor-paced"


class Format(ExtendedEnum):
"""Enum for resource format types"""

synchronous = "Synchronous"
asynchronous = "Asynchronous"
2 changes: 1 addition & 1 deletion learning_resources/etl/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
)


class ETLSource(Enum):
class ETLSource(ExtendedEnum):
"""Enum of ETL sources"""

micromasters = "micromasters"
Expand Down
78 changes: 57 additions & 21 deletions learning_resources/etl/micromasters.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
from learning_resources.constants import (
Availability,
CertificationType,
Format,
LearningResourceType,
OfferedBy,
PlatformType,
)
from learning_resources.etl.constants import COMMON_HEADERS, ETLSource
from learning_resources.models import LearningResource
from learning_resources.models import LearningResource, default_pace

OFFERED_BY = {"code": OfferedBy.mitx.name}
READABLE_ID_PREFIX = "micromasters-program-"
Expand Down Expand Up @@ -46,6 +47,27 @@ def _is_published(course_id: str) -> bool:
return False


def _get_course_pace(course_id: str) -> list[str]:
"""
Determine the pace of the course by id

Args:
course_id (str): the course id

Returns:
list[str]: the pace of the course as a list of strings

"""
existing_course = LearningResource.objects.filter(
readable_id=course_id,
resource_type=LearningResourceType.course.name,
published=True,
).first()
if existing_course:
return existing_course.pace
return default_pace()


def _transform_image(micromasters_data: dict) -> dict:
"""
Transform an image into our normalized data structure
Expand All @@ -65,7 +87,36 @@ def transform(programs_data):
programs = []
for program in programs_data:
url = program.get("programpage_url")
# need positioning of courses by course_id for course data
courses = [
{
"readable_id": course["edx_key"],
"platform": PlatformType.edx.name,
"offered_by": OFFERED_BY,
"published": _is_published(course["edx_key"]),
"pace": _get_course_pace(course["edx_key"]),
"runs": [
{
"run_id": run["edx_course_key"],
}
for run in course["course_runs"]
if run.get("edx_course_key", None)
],
}
for course in sorted(
program["courses"],
key=lambda course: course["position_in_program"],
)
]
if url and DEDP not in url:
pace = sorted(
{
pace
for course in courses
for pace in course["pace"]
if course["published"]
}
)
programs.append(
{
"readable_id": f"{READABLE_ID_PREFIX}{program['id']}",
Expand All @@ -91,30 +142,15 @@ def transform(programs_data):
"end_date": program["end_date"],
"enrollment_start": program["enrollment_start"],
"availability": Availability.dated.name,
"pace": pace,
"format": [Format.asynchronous.name],
}
],
"topics": program["topics"],
"availability": Availability.dated.name,
# only need positioning of courses by course_id for course data
"courses": [
{
"readable_id": course["edx_key"],
"platform": PlatformType.edx.name,
"offered_by": OFFERED_BY,
"published": _is_published(course["edx_key"]),
"runs": [
{
"run_id": run["edx_course_key"],
}
for run in course["course_runs"]
if run.get("edx_course_key", None)
],
}
for course in sorted(
program["courses"],
key=lambda course: course["position_in_program"],
)
],
"pace": pace,
"format": [Format.asynchronous.name],
"courses": courses,
}
)
return programs
Loading