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
3 changes: 2 additions & 1 deletion app/src/main/java/org/openedx/app/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.openedx.app.BuildConfig
import org.openedx.app.PluginManager
import org.openedx.app.data.storage.PreferencesManager
import org.openedx.app.deeplink.DeepLinkRouter
import org.openedx.app.room.ALL_MIGRATIONS
import org.openedx.app.room.AppDatabase
import org.openedx.app.room.DATABASE_NAME
import org.openedx.app.room.DatabaseManager
Expand Down Expand Up @@ -139,7 +140,7 @@ val appModule = module {
androidApplication(),
AppDatabase::class.java,
DATABASE_NAME
).fallbackToDestructiveMigration()
).addMigrations(*ALL_MIGRATIONS)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/openedx/app/room/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.openedx.discovery.data.converter.DiscoveryConverter
import org.openedx.discovery.data.model.room.CourseEntity
import org.openedx.discovery.data.storage.DiscoveryDao

const val DATABASE_VERSION = 1
const val DATABASE_VERSION = 2
const val DATABASE_NAME = "OpenEdX_db"

@Database(
Expand Down
56 changes: 56 additions & 0 deletions app/src/main/java/org/openedx/app/room/DatabaseMigrations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.openedx.app.room

import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

/**
* Database Migrations
*
* This file contains all database migrations for the app.
* When adding new migrations:
* 1. Create a new MIGRATION_X_Y object
* 2. Add it to the ALL_MIGRATIONS array
* 3. Update DATABASE_VERSION in AppDatabase.kt
*
* Best Practices:
* - Never remove migrations that have been released
* - Keep migrations in chronological order
* - Use descriptive comments
* - Test migrations thoroughly before release
*/

/**
* Migration from version 1 to version 2
*
* Changes:
* - Adds new fields to course_discovery_table:
* - courseRequirement: Course prerequisites/requirements
* - description: Detailed course description
* - learningOutcomes: Expected learning outcomes
* - instructors: JSON string of instructor information
*/
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
// Add new columns to course_discovery_table with default empty string values
db.execSQL("ALTER TABLE course_discovery_table ADD COLUMN courseRequirement TEXT NOT NULL DEFAULT ''")
db.execSQL("ALTER TABLE course_discovery_table ADD COLUMN description TEXT NOT NULL DEFAULT ''")
db.execSQL("ALTER TABLE course_discovery_table ADD COLUMN learningOutcomes TEXT NOT NULL DEFAULT ''")
db.execSQL("ALTER TABLE course_discovery_table ADD COLUMN instructors TEXT NOT NULL DEFAULT ''")
}
}

/**
* All migrations in chronological order.
* This array is used by the database builder to apply migrations automatically.
*
* To add a new migration:
* - Create a new MIGRATION_X_Y object above
* - Add it to this array: arrayOf(MIGRATION_1_2, MIGRATION_2_3, ...)
*/
val ALL_MIGRATIONS = arrayOf(
MIGRATION_1_2
// Add future migrations here, e.g.:
// MIGRATION_2_3,
// MIGRATION_3_4,
)

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ data class CourseDetails(
val isEnrolled: Boolean?,
@SerializedName("duration")
val duration: String?,
@SerializedName("course_requirement")
val courseRequirement: String?,
@SerializedName("description")
val description: String?,
@SerializedName("learning_outcomes")
val learningOutcomes: List<String>?,
@SerializedName("instructors")
val instructors: List<Instructor>?,
) {

fun mapToDomain(): Course {
Expand All @@ -76,6 +84,10 @@ data class CourseDetails(
isEnrolled = isEnrolled ?: false,
media = mapMediaToDomain(),
duration = duration.orEmpty(),
courseRequirement = courseRequirement.orEmpty(),
description = description.orEmpty(),
learningOutcomes = learningOutcomes?.joinToString(", ") ?: "",
instructorsList = instructors ?: emptyList()
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.openedx.discovery.data.model

import com.google.gson.annotations.SerializedName

data class Instructor(
@SerializedName("name")
val name: String?,
@SerializedName("title")
val title: String?,
@SerializedName("organization")
val organization: String?,
@SerializedName("bio")
val bio: String?,
@SerializedName("image")
val image: String?
)

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ data class CourseEntity(
val isEnrolled: Boolean,
@ColumnInfo("duration")
val duration: String,
@ColumnInfo("courseRequirement")
val courseRequirement: String,
@ColumnInfo("description")
val description: String,
@ColumnInfo("learningOutcomes")
val learningOutcomes: String,
@ColumnInfo("instructors")
val instructors: String,
) {

fun mapToDomain(): Course {
Expand All @@ -82,6 +90,10 @@ data class CourseEntity(
overview = overview,
isEnrolled = isEnrolled,
duration = duration,
courseRequirement = courseRequirement,
description = description,
learningOutcomes = learningOutcomes,
instructorsList = emptyList()
)
}

Expand Down Expand Up @@ -110,6 +122,10 @@ data class CourseEntity(
media = MediaDb.createFrom(model.media),
isEnrolled = model.isEnrolled ?: false,
duration = model.duration.orEmpty(),
courseRequirement = model.courseRequirement.orEmpty(),
description = model.description.orEmpty(),
learningOutcomes = model.learningOutcomes?.joinToString(", ") ?: "",
instructors = model.instructors?.mapNotNull { it.name }?.joinToString(", ") ?: "",
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,9 @@ data class Course(
val startType: String,
val overview: String,
val isEnrolled: Boolean,
val duration: String
val duration: String,
val courseRequirement: String,
val description: String,
val learningOutcomes: String,
val instructorsList: List<org.openedx.discovery.data.model.Instructor> = emptyList()
)
Loading
Loading