Skip to content

Commit 19bb326

Browse files
feat: color coding, detekt fixes
1 parent 74c978c commit 19bb326

File tree

36 files changed

+1035
-102
lines changed

36 files changed

+1035
-102
lines changed

app/src/main/java/org/openedx/app/di/ScreenModule.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,9 @@ val screenModule = module {
532532
courseId = courseId,
533533
courseName = courseName,
534534
interactor = get(),
535-
courseRouter = get()
535+
courseRouter = get(),
536+
courseNotifier = get(),
537+
analytics = get()
536538
)
537539
}
538540
}

app/src/main/java/org/openedx/app/room/AppDatabase.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.room.TypeConverters
77
import org.openedx.core.data.model.room.CourseCalendarEventEntity
88
import org.openedx.core.data.model.room.CourseCalendarStateEntity
99
import org.openedx.core.data.model.room.CourseEnrollmentDetailsEntity
10+
import org.openedx.core.data.model.room.CourseProgressEntity
1011
import org.openedx.core.data.model.room.CourseStructureEntity
1112
import org.openedx.core.data.model.room.DownloadCoursePreview
1213
import org.openedx.core.data.model.room.OfflineXBlockProgress
@@ -37,6 +38,7 @@ const val DATABASE_NAME = "OpenEdX_db"
3738
DownloadCoursePreview::class,
3839
CourseEnrollmentDetailsEntity::class,
3940
VideoProgressEntity::class,
41+
CourseProgressEntity::class,
4042
],
4143
autoMigrations = [
4244
AutoMigration(1, DATABASE_VERSION)

app/src/main/java/org/openedx/app/room/DatabaseManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class DatabaseManager(
1919
CoroutineScope(Dispatchers.IO).launch {
2020
courseDao.clearCachedData()
2121
courseDao.clearEnrollmentCachedData()
22+
courseDao.clearCourseProgressData()
2223
dashboardDao.clearCachedData()
2324
downloadDao.clearOfflineProgress()
2425
discoveryDao.clearCachedData()

core/src/main/java/org/openedx/core/data/api/CourseApi.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.openedx.core.data.model.CourseDates
88
import org.openedx.core.data.model.CourseDatesBannerInfo
99
import org.openedx.core.data.model.CourseEnrollmentDetails
1010
import org.openedx.core.data.model.CourseEnrollments
11+
import org.openedx.core.data.model.CourseProgressResponse
1112
import org.openedx.core.data.model.CourseStructureModel
1213
import org.openedx.core.data.model.DownloadCoursePreview
1314
import org.openedx.core.data.model.EnrollmentStatus
@@ -106,4 +107,9 @@ interface CourseApi {
106107
suspend fun getDownloadCoursesPreview(
107108
@Path("username") username: String
108109
): List<DownloadCoursePreview>
110+
111+
@GET("/api/course_home/progress/{course_id}")
112+
suspend fun getCourseProgress(
113+
@Path("course_id") courseId: String,
114+
): CourseProgressResponse
109115
}

core/src/main/java/org/openedx/core/data/model/AssignmentProgress.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import com.google.gson.annotations.SerializedName
44
import org.openedx.core.data.model.room.AssignmentProgressDb
55
import org.openedx.core.domain.model.AssignmentProgress
66

7+
private const val DEFAULT_LABEL_LENGTH = 5
8+
79
data class AssignmentProgress(
810
@SerializedName("assignment_type")
911
val assignmentType: String?,
@@ -18,7 +20,7 @@ data class AssignmentProgress(
1820
assignmentType = assignmentType ?: "",
1921
numPointsEarned = numPointsEarned ?: 0f,
2022
numPointsPossible = numPointsPossible ?: 0f,
21-
label = label ?: displayName.take(5)
23+
label = label ?: displayName.take(DEFAULT_LABEL_LENGTH)
2224
)
2325

2426
fun mapToRoomEntity() = AssignmentProgressDb(
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
package org.openedx.core.data.model
2+
3+
import androidx.compose.ui.graphics.Color
4+
import androidx.core.graphics.toColorInt
5+
import com.google.gson.annotations.SerializedName
6+
import org.openedx.core.data.model.room.CertificateDataDb
7+
import org.openedx.core.data.model.room.CompletionSummaryDb
8+
import org.openedx.core.data.model.room.CourseGradeDb
9+
import org.openedx.core.data.model.room.CourseProgressEntity
10+
import org.openedx.core.data.model.room.GradingPolicyDb
11+
import org.openedx.core.data.model.room.SectionScoreDb
12+
import org.openedx.core.data.model.room.VerificationDataDb
13+
import org.openedx.core.domain.model.CourseProgress
14+
15+
data class CourseProgressResponse(
16+
@SerializedName("verified_mode") val verifiedMode: String?,
17+
@SerializedName("access_expiration") val accessExpiration: String?,
18+
@SerializedName("certificate_data") val certificateData: CertificateData?,
19+
@SerializedName("completion_summary") val completionSummary: CompletionSummary?,
20+
@SerializedName("course_grade") val courseGrade: CourseGrade?,
21+
@SerializedName("credit_course_requirements") val creditCourseRequirements: String?,
22+
@SerializedName("end") val end: String?,
23+
@SerializedName("enrollment_mode") val enrollmentMode: String?,
24+
@SerializedName("grading_policy") val gradingPolicy: GradingPolicy?,
25+
@SerializedName("has_scheduled_content") val hasScheduledContent: Boolean?,
26+
@SerializedName("section_scores") val sectionScores: List<SectionScore>?,
27+
@SerializedName("studio_url") val studioUrl: String?,
28+
@SerializedName("username") val username: String?,
29+
@SerializedName("user_has_passing_grade") val userHasPassingGrade: Boolean?,
30+
@SerializedName("verification_data") val verificationData: VerificationData?,
31+
@SerializedName("disable_progress_graph") val disableProgressGraph: Boolean?,
32+
) {
33+
data class CertificateData(
34+
@SerializedName("cert_status") val certStatus: String?,
35+
@SerializedName("cert_web_view_url") val certWebViewUrl: String?,
36+
@SerializedName("download_url") val downloadUrl: String?,
37+
@SerializedName("certificate_available_date") val certificateAvailableDate: String?
38+
) {
39+
fun mapToRoomEntity() = CertificateDataDb(
40+
certStatus = certStatus.orEmpty(),
41+
certWebViewUrl = certWebViewUrl.orEmpty(),
42+
downloadUrl = downloadUrl.orEmpty(),
43+
certificateAvailableDate = certificateAvailableDate.orEmpty()
44+
)
45+
46+
fun mapToDomain() = CourseProgress.CertificateData(
47+
certStatus = certStatus ?: "",
48+
certWebViewUrl = certWebViewUrl ?: "",
49+
downloadUrl = downloadUrl ?: "",
50+
certificateAvailableDate = certificateAvailableDate ?: ""
51+
)
52+
}
53+
54+
data class CompletionSummary(
55+
@SerializedName("complete_count") val completeCount: Int?,
56+
@SerializedName("incomplete_count") val incompleteCount: Int?,
57+
@SerializedName("locked_count") val lockedCount: Int?
58+
) {
59+
fun mapToRoomEntity() = CompletionSummaryDb(
60+
completeCount = completeCount ?: 0,
61+
incompleteCount = incompleteCount ?: 0,
62+
lockedCount = lockedCount ?: 0
63+
)
64+
65+
fun mapToDomain() = CourseProgress.CompletionSummary(
66+
completeCount = completeCount ?: 0,
67+
incompleteCount = incompleteCount ?: 0,
68+
lockedCount = lockedCount ?: 0
69+
)
70+
}
71+
72+
data class CourseGrade(
73+
@SerializedName("letter_grade") val letterGrade: String?,
74+
@SerializedName("percent") val percent: Double?,
75+
@SerializedName("is_passing") val isPassing: Boolean?
76+
) {
77+
fun mapToRoomEntity() = CourseGradeDb(
78+
letterGrade = letterGrade.orEmpty(),
79+
percent = percent ?: 0.0,
80+
isPassing = isPassing ?: false
81+
)
82+
83+
fun mapToDomain() = CourseProgress.CourseGrade(
84+
letterGrade = letterGrade ?: "",
85+
percent = percent ?: 0.0,
86+
isPassing = isPassing ?: false
87+
)
88+
}
89+
90+
data class GradingPolicy(
91+
@SerializedName("assignment_policies") val assignmentPolicies: List<AssignmentPolicy>?,
92+
@SerializedName("grade_range") val gradeRange: Map<String, Float>?,
93+
@SerializedName("assignment_colors") val assignmentColors: List<String>?
94+
) {
95+
fun mapToRoomEntity() = GradingPolicyDb(
96+
assignmentPolicies = assignmentPolicies?.map { it.mapToRoomEntity() } ?: emptyList(),
97+
gradeRange = gradeRange ?: emptyMap(),
98+
assignmentColors = assignmentColors ?: emptyList()
99+
)
100+
101+
fun mapToDomain() = CourseProgress.GradingPolicy(
102+
assignmentPolicies = assignmentPolicies?.map { it.mapToDomain() } ?: emptyList(),
103+
gradeRange = gradeRange ?: emptyMap(),
104+
assignmentColors = assignmentColors?.map { colorString ->
105+
Color(colorString.toColorInt())
106+
} ?: emptyList()
107+
)
108+
109+
data class AssignmentPolicy(
110+
@SerializedName("num_droppable") val numDroppable: Int?,
111+
@SerializedName("num_total") val numTotal: Int?,
112+
@SerializedName("short_label") val shortLabel: String?,
113+
@SerializedName("type") val type: String?,
114+
@SerializedName("weight") val weight: Double?
115+
) {
116+
fun mapToRoomEntity() = GradingPolicyDb.AssignmentPolicyDb(
117+
numDroppable = numDroppable ?: 0,
118+
numTotal = numTotal ?: 0,
119+
shortLabel = shortLabel.orEmpty(),
120+
type = type.orEmpty(),
121+
weight = weight ?: 0.0
122+
)
123+
124+
fun mapToDomain() = CourseProgress.GradingPolicy.AssignmentPolicy(
125+
numDroppable = numDroppable ?: 0,
126+
numTotal = numTotal ?: 0,
127+
shortLabel = shortLabel ?: "",
128+
type = type ?: "",
129+
weight = weight ?: 0.0
130+
)
131+
}
132+
}
133+
134+
data class SectionScore(
135+
@SerializedName("display_name") val displayName: String?,
136+
@SerializedName("subsections") val subsections: List<Subsection>?
137+
) {
138+
fun mapToRoomEntity() = SectionScoreDb(
139+
displayName = displayName.orEmpty(),
140+
subsections = subsections?.map { it.mapToRoomEntity() } ?: emptyList()
141+
)
142+
143+
fun mapToDomain() = CourseProgress.SectionScore(
144+
displayName = displayName ?: "",
145+
subsections = subsections?.map { it.mapToDomain() } ?: emptyList()
146+
)
147+
148+
data class Subsection(
149+
@SerializedName("assignment_type") val assignmentType: String?,
150+
@SerializedName("block_key") val blockKey: String?,
151+
@SerializedName("display_name") val displayName: String?,
152+
@SerializedName("has_graded_assignment") val hasGradedAssignment: Boolean?,
153+
@SerializedName("override") val override: String?,
154+
@SerializedName("learner_has_access") val learnerHasAccess: Boolean?,
155+
@SerializedName("num_points_earned") val numPointsEarned: Float?,
156+
@SerializedName("num_points_possible") val numPointsPossible: Float?,
157+
@SerializedName("percent_graded") val percentGraded: Double?,
158+
@SerializedName("problem_scores") val problemScores: List<ProblemScore>?,
159+
@SerializedName("show_correctness") val showCorrectness: String?,
160+
@SerializedName("show_grades") val showGrades: Boolean?,
161+
@SerializedName("url") val url: String?
162+
) {
163+
fun mapToRoomEntity() = SectionScoreDb.SubsectionDb(
164+
assignmentType = assignmentType.orEmpty(),
165+
blockKey = blockKey.orEmpty(),
166+
displayName = displayName.orEmpty(),
167+
hasGradedAssignment = hasGradedAssignment ?: false,
168+
override = override.orEmpty(),
169+
learnerHasAccess = learnerHasAccess ?: false,
170+
numPointsEarned = numPointsEarned ?: 0f,
171+
numPointsPossible = numPointsPossible ?: 0f,
172+
percentGraded = percentGraded ?: 0.0,
173+
problemScores = problemScores?.map { it.mapToRoomEntity() } ?: emptyList(),
174+
showCorrectness = showCorrectness.orEmpty(),
175+
showGrades = showGrades ?: false,
176+
url = url.orEmpty()
177+
)
178+
179+
fun mapToDomain() = CourseProgress.SectionScore.Subsection(
180+
assignmentType = assignmentType ?: "",
181+
blockKey = blockKey ?: "",
182+
displayName = displayName ?: "",
183+
hasGradedAssignment = hasGradedAssignment ?: false,
184+
override = override ?: "",
185+
learnerHasAccess = learnerHasAccess ?: false,
186+
numPointsEarned = numPointsEarned ?: 0f,
187+
numPointsPossible = numPointsPossible ?: 0f,
188+
percentGraded = percentGraded ?: 0.0,
189+
problemScores = problemScores?.map { it.mapToDomain() } ?: emptyList(),
190+
showCorrectness = showCorrectness ?: "",
191+
showGrades = showGrades ?: false,
192+
url = url ?: ""
193+
)
194+
195+
data class ProblemScore(
196+
@SerializedName("earned") val earned: Double?,
197+
@SerializedName("possible") val possible: Double?
198+
) {
199+
fun mapToRoomEntity() = SectionScoreDb.SubsectionDb.ProblemScoreDb(
200+
earned = earned ?: 0.0,
201+
possible = possible ?: 0.0
202+
)
203+
204+
fun mapToDomain() = CourseProgress.SectionScore.Subsection.ProblemScore(
205+
earned = earned ?: 0.0,
206+
possible = possible ?: 0.0
207+
)
208+
}
209+
}
210+
}
211+
212+
data class VerificationData(
213+
@SerializedName("link") val link: String?,
214+
@SerializedName("status") val status: String?,
215+
@SerializedName("status_date") val statusDate: String?
216+
) {
217+
fun mapToRoomEntity() = VerificationDataDb(
218+
link = link.orEmpty(),
219+
status = status.orEmpty(),
220+
statusDate = statusDate.orEmpty()
221+
)
222+
223+
fun mapToDomain() = CourseProgress.VerificationData(
224+
link = link ?: "",
225+
status = status ?: "",
226+
statusDate = statusDate ?: ""
227+
)
228+
}
229+
230+
fun mapToDomain(): CourseProgress {
231+
return CourseProgress(
232+
verifiedMode = verifiedMode ?: "",
233+
accessExpiration = accessExpiration ?: "",
234+
certificateData = certificateData?.mapToDomain(),
235+
completionSummary = completionSummary?.mapToDomain(),
236+
courseGrade = courseGrade?.mapToDomain(),
237+
creditCourseRequirements = creditCourseRequirements ?: "",
238+
end = end ?: "",
239+
enrollmentMode = enrollmentMode ?: "",
240+
gradingPolicy = gradingPolicy?.mapToDomain(),
241+
hasScheduledContent = hasScheduledContent ?: false,
242+
sectionScores = sectionScores?.map { it.mapToDomain() } ?: emptyList(),
243+
studioUrl = studioUrl ?: "",
244+
username = username ?: "",
245+
userHasPassingGrade = userHasPassingGrade ?: false,
246+
verificationData = verificationData?.mapToDomain(),
247+
disableProgressGraph = disableProgressGraph ?: false,
248+
)
249+
}
250+
251+
fun mapToRoomEntity(courseId: String): CourseProgressEntity {
252+
return CourseProgressEntity(
253+
courseId = courseId,
254+
verifiedMode = verifiedMode.orEmpty(),
255+
accessExpiration = accessExpiration.orEmpty(),
256+
certificateData = certificateData?.mapToRoomEntity(),
257+
completionSummary = completionSummary?.mapToRoomEntity(),
258+
courseGrade = courseGrade?.mapToRoomEntity(),
259+
creditCourseRequirements = creditCourseRequirements.orEmpty(),
260+
end = end.orEmpty(),
261+
enrollmentMode = enrollmentMode.orEmpty(),
262+
gradingPolicy = gradingPolicy?.mapToRoomEntity(),
263+
hasScheduledContent = hasScheduledContent ?: false,
264+
sectionScores = sectionScores?.map { it.mapToRoomEntity() } ?: emptyList(),
265+
studioUrl = studioUrl.orEmpty(),
266+
username = username.orEmpty(),
267+
userHasPassingGrade = userHasPassingGrade ?: false,
268+
verificationData = verificationData?.mapToRoomEntity(),
269+
disableProgressGraph = disableProgressGraph ?: false,
270+
)
271+
}
272+
}

0 commit comments

Comments
 (0)