Skip to content

Commit 2e13fde

Browse files
Okuro3499pavi38dogi
authored
teams: smoother courses handling (fixes #5747) (#11247)
Co-authored-by: Pavneet Singh Cheema <90737218+pavi38@users.noreply.github.com> Co-authored-by: dogi <dogi@users.noreply.github.com>
1 parent b2e84d5 commit 2e13fde

19 files changed

Lines changed: 324 additions & 40 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId "org.ole.planet.myplanet"
1212
minSdk = 26
1313
targetSdk = 36
14-
versionCode = 4602
15-
versionName = "0.46.2"
14+
versionCode = 4603
15+
versionName = "0.46.3"
1616
ndkVersion = '26.3.11579264'
1717
vectorDrawables.useSupportLibrary = true
1818
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.ole.planet.myplanet.callback
22

33
interface OnTeamPageListener {
4+
fun onAddCourse()
45
fun onAddDocument()
56
}

app/src/main/java/org/ole/planet/myplanet/model/RealmMyCourse.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,43 @@ open class RealmMyCourse : RealmObject() {
277277
}
278278
return ids
279279
}
280+
281+
@JvmStatic
282+
fun serialize(course: RealmMyCourse, realm: Realm): JsonObject {
283+
val obj = JsonObject()
284+
obj.addProperty("_id", course.courseId)
285+
obj.addProperty("_rev", course.courseRev)
286+
obj.addProperty("courseTitle", course.courseTitle)
287+
obj.addProperty("description", course.description)
288+
obj.addProperty("languageOfInstruction", course.languageOfInstruction)
289+
obj.addProperty("gradeLevel", course.gradeLevel)
290+
obj.addProperty("subjectLevel", course.subjectLevel)
291+
obj.addProperty("createdDate", course.createdDate)
292+
obj.addProperty("method", course.method)
293+
obj.addProperty("memberLimit", course.memberLimit)
294+
295+
val stepsArray = JsonArray()
296+
course.courseSteps?.forEach { step ->
297+
val stepObj = JsonObject()
298+
stepObj.addProperty("stepTitle", step.stepTitle)
299+
stepObj.addProperty("description", step.description)
300+
stepObj.addProperty("id", step.id)
301+
302+
val resourcesArray = JsonArray()
303+
val stepResources = realm.where(RealmMyLibrary::class.java)
304+
.equalTo("stepId", step.id)
305+
.equalTo("courseId", course.courseId)
306+
.findAll()
307+
308+
stepResources.forEach { resource ->
309+
resourcesArray.add(resource.serializeResource())
310+
}
311+
stepObj.add("resources", resourcesArray)
312+
stepsArray.add(stepObj)
313+
}
314+
obj.add("steps", stepsArray)
315+
obj.add("images", JsonArray())
316+
return obj
317+
}
280318
}
281319
}

app/src/main/java/org/ole/planet/myplanet/model/RealmMyTeam.kt

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.ole.planet.myplanet.model
22

33
import android.content.SharedPreferences
4+
import com.google.gson.JsonArray
45
import com.google.gson.JsonObject
56
import com.google.gson.JsonParser
67
import io.realm.Realm
@@ -94,18 +95,36 @@ open class RealmMyTeam : RealmObject() {
9495
team.startDate = JsonUtils.getLong("startDate", doc)
9596
team.endDate = JsonUtils.getLong("endDate", doc)
9697
team.updatedDate = JsonUtils.getLong("updatedDate", doc)
97-
team.updated = JsonUtils.getBoolean("updated", doc)
9898

99-
if (includeCourses) {
100-
val coursesArray = JsonUtils.getJsonArray("courses", doc)
101-
team.courses = RealmList()
102-
for (e in coursesArray) {
99+
val hadLocalChanges = team.updated
100+
val localCourses = team.courses?.toList() ?: emptyList()
101+
102+
if (!hadLocalChanges) {
103+
team.updated = JsonUtils.getBoolean("updated", doc)
104+
}
105+
106+
val coursesArray = JsonUtils.getJsonArray("courses", doc)
107+
val serverCourseIds = mutableListOf<String>()
108+
for (e in coursesArray) {
109+
try {
103110
val id = e.asJsonObject["_id"].asString
104-
if (!team.courses!!.contains(id)) {
105-
team.courses!!.add(id)
111+
serverCourseIds.add(id)
112+
} catch (ex: Exception) {
113+
if (e.isJsonPrimitive) {
114+
serverCourseIds.add(e.asString)
106115
}
107116
}
108117
}
118+
119+
if (hadLocalChanges) {
120+
val mergedCourses = serverCourseIds.toMutableSet()
121+
mergedCourses.addAll(localCourses)
122+
team.courses = RealmList()
123+
team.courses?.addAll(mergedCourses)
124+
} else {
125+
team.courses = RealmList()
126+
team.courses?.addAll(serverCourseIds)
127+
}
109128
}
110129

111130
private fun processDescription(description: String?) {
@@ -305,6 +324,28 @@ open class RealmMyTeam : RealmObject() {
305324
return JsonParser.parseString(JsonUtils.gson.toJson(`object`)).asJsonObject
306325
}
307326

327+
@JvmStatic
328+
fun serialize(team: RealmMyTeam, realm: Realm): JsonObject {
329+
val `object` = serialize(team)
330+
331+
if (!team.courses.isNullOrEmpty()) {
332+
val coursesArray = JsonArray()
333+
334+
team.courses?.forEach { courseId ->
335+
val course = realm.where(RealmMyCourse::class.java)
336+
.equalTo("courseId", courseId)
337+
.findFirst()
338+
339+
if (course != null) {
340+
val courseJson = RealmMyCourse.serialize(course, realm)
341+
coursesArray.add(courseJson)
342+
}
343+
}
344+
`object`.add("courses", coursesArray)
345+
}
346+
return `object`
347+
}
348+
308349
fun getMyTeamsByUserId(mRealm: Realm, settings: SharedPreferences?): RealmResults<RealmMyTeam> {
309350
val userId = settings?.getString("userId", "--") ?: "--"
310351
val list = mRealm.where(RealmMyTeam::class.java)

app/src/main/java/org/ole/planet/myplanet/repository/CoursesRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.ole.planet.myplanet.model.RealmMyCourse
99
import org.ole.planet.myplanet.model.RealmMyLibrary
1010

1111
interface CoursesRepository {
12+
suspend fun getAllCourses(): List<RealmMyCourse>
1213
fun getMyCourses(userId: String?, courses: List<RealmMyCourse>): List<RealmMyCourse>
1314
suspend fun getMyCourses(userId: String): List<RealmMyCourse>
1415
suspend fun getMyCoursesFlow(userId: String): Flow<List<RealmMyCourse>>

app/src/main/java/org/ole/planet/myplanet/repository/CoursesRepositoryImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class CoursesRepositoryImpl @Inject constructor(
3030
private val progressRepository: ProgressRepository
3131
) : RealmRepository(databaseService), CoursesRepository {
3232

33+
override suspend fun getAllCourses(): List<RealmMyCourse> {
34+
return queryList(RealmMyCourse::class.java) {}
35+
}
36+
3337
override fun getMyCourses(userId: String?, courses: List<RealmMyCourse>): List<RealmMyCourse> {
3438
val myCourses: MutableList<RealmMyCourse> = ArrayList()
3539
if (userId == null) return myCourses

app/src/main/java/org/ole/planet/myplanet/repository/TeamsRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.ole.planet.myplanet.repository
22

33
import com.google.gson.JsonObject
44
import kotlinx.coroutines.flow.Flow
5+
import org.ole.planet.myplanet.model.RealmMyCourse
56
import org.ole.planet.myplanet.model.RealmMyLibrary
67
import org.ole.planet.myplanet.model.RealmMyTeam
78
import org.ole.planet.myplanet.model.RealmTeamTask
@@ -35,6 +36,8 @@ interface TeamsRepository {
3536
suspend fun getShareableTeams(): List<RealmMyTeam>
3637
suspend fun getShareableEnterprises(): List<RealmMyTeam>
3738
suspend fun getTeamResources(teamId: String): List<RealmMyLibrary>
39+
suspend fun getTeamCourses(teamId: String): List<RealmMyCourse>
40+
suspend fun addCoursesToTeam(teamId: String, courseIds: List<String>)
3841
suspend fun getTeamByDocumentIdOrTeamId(id: String): RealmMyTeam?
3942
suspend fun getTeamByIdOrTeamId(id: String): RealmMyTeam?
4043
suspend fun getTeamLinks(): List<RealmMyTeam>

app/src/main/java/org/ole/planet/myplanet/repository/TeamsRepositoryImpl.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.ole.planet.myplanet.data.DatabaseService
2424
import org.ole.planet.myplanet.data.api.ApiClient.client
2525
import org.ole.planet.myplanet.data.api.ApiInterface
2626
import org.ole.planet.myplanet.di.AppPreferences
27+
import org.ole.planet.myplanet.model.RealmMyCourse
2728
import org.ole.planet.myplanet.model.RealmMyLibrary
2829
import org.ole.planet.myplanet.model.RealmMyTeam
2930
import org.ole.planet.myplanet.model.RealmTeamLog
@@ -162,6 +163,37 @@ class TeamsRepositoryImpl @Inject constructor(
162163
return (linkedResources + privateResources).distinctBy { it.id }
163164
}
164165

166+
override suspend fun getTeamCourses(teamId: String): List<RealmMyCourse> {
167+
val team = findByField(RealmMyTeam::class.java, "_id", teamId) ?: return emptyList()
168+
val courseIds = team.courses?.toList() ?: return emptyList()
169+
170+
if (courseIds.isEmpty()) return emptyList()
171+
val courses = queryList(RealmMyCourse::class.java) {
172+
`in`("courseId", courseIds.toTypedArray())
173+
}
174+
return courses
175+
}
176+
177+
override suspend fun addCoursesToTeam(teamId: String, courseIds: List<String>) {
178+
if (courseIds.isEmpty()) {
179+
return
180+
}
181+
executeTransaction { realm ->
182+
val team = realm.where(RealmMyTeam::class.java)
183+
.equalTo("_id", teamId)
184+
.findFirst()
185+
if (team == null) {
186+
return@executeTransaction
187+
}
188+
courseIds.forEach { courseId ->
189+
if (team.courses?.contains(courseId) != true) {
190+
team.courses?.add(courseId)
191+
}
192+
}
193+
team.updated = true
194+
}
195+
}
196+
165197
override suspend fun getTeamByDocumentIdOrTeamId(id: String): RealmMyTeam? {
166198
if (id.isBlank()) return null
167199
return findByField(RealmMyTeam::class.java, "_id", id)

app/src/main/java/org/ole/planet/myplanet/services/UploadManager.kt

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ class UploadManager @Inject constructor(
452452

453453
data class TeamData(
454454
val teamId: String?,
455+
val teamName: String?,
456+
val coursesCount: Int,
455457
val serialized: JsonObject
456458
)
457459

@@ -461,8 +463,9 @@ class UploadManager @Inject constructor(
461463

462464
teams.map { team ->
463465
TeamData(
464-
teamId = team._id,
465-
serialized = RealmMyTeam.serialize(team)
466+
teamId = team._id, teamName = team.name,
467+
coursesCount = team.courses?.size ?: 0,
468+
serialized = RealmMyTeam.serialize(team, realm)
466469
)
467470
}
468471
}
@@ -471,10 +474,12 @@ class UploadManager @Inject constructor(
471474
teamsToUpload.chunked(BATCH_SIZE).forEach { batch ->
472475
batch.forEach { teamData ->
473476
try {
474-
val `object` = apiInterface.postDoc(
477+
val response = apiInterface.postDoc(
475478
UrlUtils.header, "application/json",
476479
"${UrlUtils.getUrl()}/teams", teamData.serialized
477-
).body()
480+
)
481+
482+
val `object` = response.body()
478483

479484
if (`object` != null) {
480485
val rev = getString("rev", `object`)
@@ -552,7 +557,6 @@ class UploadManager @Inject constructor(
552557
}
553558

554559
uploadTeamActivitiesRefactored()
555-
556560
listener.onSuccess("User activities sync completed successfully")
557561
} catch (e: Exception) {
558562
e.printStackTrace()
@@ -587,10 +591,8 @@ class UploadManager @Inject constructor(
587591
logsData.forEach { logData ->
588592
try {
589593
val `object` = apiInterface.postDoc(
590-
UrlUtils.header,
591-
"application/json",
592-
"${UrlUtils.getUrl()}/team_activities",
593-
logData.serialized
594+
UrlUtils.header, "application/json",
595+
"${UrlUtils.getUrl()}/team_activities", logData.serialized
594596
).body()
595597

596598
if (`object` != null) {

app/src/main/java/org/ole/planet/myplanet/ui/teams/TeamDetailFragment.kt

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import androidx.viewpager2.widget.ViewPager2
1111
import com.google.android.material.snackbar.Snackbar
1212
import com.google.android.material.tabs.TabLayoutMediator
1313
import dagger.hilt.android.AndroidEntryPoint
14-
import javax.inject.Inject
15-
import kotlinx.coroutines.Dispatchers
1614
import kotlinx.coroutines.Job
1715
import kotlinx.coroutines.launch
1816
import kotlinx.coroutines.withContext
@@ -23,6 +21,7 @@ import org.ole.planet.myplanet.base.BaseTeamFragment
2321
import org.ole.planet.myplanet.callback.OnBaseRealtimeSyncListener
2422
import org.ole.planet.myplanet.callback.OnMemberChangeListener
2523
import org.ole.planet.myplanet.callback.OnSyncListener
24+
import org.ole.planet.myplanet.callback.OnTeamPageListener
2625
import org.ole.planet.myplanet.callback.OnTeamUpdateListener
2726
import org.ole.planet.myplanet.databinding.FragmentTeamDetailBinding
2827
import org.ole.planet.myplanet.model.RealmNews
@@ -48,8 +47,10 @@ import org.ole.planet.myplanet.ui.teams.TeamPageConfig.ResourcesPage
4847
import org.ole.planet.myplanet.ui.teams.TeamPageConfig.SurveyPage
4948
import org.ole.planet.myplanet.ui.teams.TeamPageConfig.TasksPage
5049
import org.ole.planet.myplanet.ui.teams.TeamPageConfig.TeamPage
50+
import org.ole.planet.myplanet.ui.teams.courses.TeamCoursesFragment
5151
import org.ole.planet.myplanet.utils.DialogUtils
5252
import org.ole.planet.myplanet.utils.Utilities
53+
import javax.inject.Inject
5354

5455
@AndroidEntryPoint
5556
class TeamDetailFragment : BaseTeamFragment(), OnMemberChangeListener, OnTeamUpdateListener {
@@ -294,18 +295,13 @@ class TeamDetailFragment : BaseTeamFragment(), OnMemberChangeListener, OnTeamUpd
294295

295296
binding.viewPager2.adapter = null
296297
binding.viewPager2.adapter = TeamPagerAdapter(
297-
requireActivity(),
298-
pageConfigs,
299-
team?._id,
300-
this,
301-
this
298+
this, pageConfigs, team?._id, this, this
302299
)
303300
binding.tabLayout.tabMode = com.google.android.material.tabs.TabLayout.MODE_SCROLLABLE
304301
binding.tabLayout.isInlineLabel = true
305302

306303
TabLayoutMediator(binding.tabLayout, binding.viewPager2) { tab, position ->
307304
val title = (binding.viewPager2.adapter as TeamPagerAdapter).getPageTitle(position)
308-
val pageConfig = pageConfigs.getOrNull(position)
309305
tab.text = title
310306
}.attach()
311307

@@ -321,6 +317,12 @@ class TeamDetailFragment : BaseTeamFragment(), OnMemberChangeListener, OnTeamUpd
321317
teamLastPage[teamId] = it
322318
}
323319
}
320+
321+
val fragmentTag = "f$position"
322+
val fragment = childFragmentManager.findFragmentByTag(fragmentTag)
323+
if (fragment is OnTeamPageListener) {
324+
MainApplication.listener = fragment
325+
}
324326
}
325327
}
326328
)
@@ -388,9 +390,27 @@ class TeamDetailFragment : BaseTeamFragment(), OnMemberChangeListener, OnTeamUpd
388390

389391
binding.btnAddDoc.setOnClickListener {
390392
MainApplication.showDownload = true
391-
selectPage(DocumentsPage.id)
393+
val coursesPageIndex = pageIndexById(CoursesPage.id)
394+
val isAlreadyOnCoursesPage = coursesPageIndex != null && binding.viewPager2.currentItem == coursesPageIndex
395+
396+
selectPage(CoursesPage.id)
392397
MainApplication.showDownload = false
393-
MainApplication.listener?.onAddDocument()
398+
399+
val delay = if (isAlreadyOnCoursesPage) 50L else 300L
400+
401+
binding.root.postDelayed({
402+
val allFragments = childFragmentManager.fragments
403+
val coursesFragment = allFragments.filterIsInstance<TeamCoursesFragment>().firstOrNull()
404+
405+
when {
406+
coursesFragment != null -> {
407+
coursesFragment.onAddCourse()
408+
}
409+
MainApplication.listener is TeamCoursesFragment -> {
410+
MainApplication.listener?.onAddCourse()
411+
}
412+
}
413+
}, delay)
394414
}
395415
}
396416

0 commit comments

Comments
 (0)