diff --git a/app/src/main/java/org/openedx/app/MainViewModel.kt b/app/src/main/java/org/openedx/app/MainViewModel.kt index 3f90e1aa1..da681e8e1 100644 --- a/app/src/main/java/org/openedx/app/MainViewModel.kt +++ b/app/src/main/java/org/openedx/app/MainViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow @@ -31,13 +32,17 @@ class MainViewModel( val isDiscoveryTypeWebView get() = config.getDiscoveryConfig().isViewTypeWebView() + @OptIn(FlowPreview::class) override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) - notifier.notifier.onEach { - if (it is NavigationToDiscovery) { - _navigateToDiscovery.emit(true) + notifier.notifier + .onEach { + if (it is NavigationToDiscovery) { + _navigateToDiscovery.emit(true) + } } - }.distinctUntilChanged().launchIn(viewModelScope) + .distinctUntilChanged() + .launchIn(viewModelScope) } fun enableBottomBar(enable: Boolean) { diff --git a/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt index 63dce6272..46291af62 100644 --- a/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt @@ -134,6 +134,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -167,6 +168,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -200,6 +202,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -233,6 +236,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -267,6 +271,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -297,6 +302,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, @@ -327,6 +333,7 @@ class CourseContainerViewModelTest { "", "", "", + "", config, interactor, calendarManager, diff --git a/course/src/test/java/org/openedx/course/presentation/dates/CourseDatesViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/dates/CourseDatesViewModelTest.kt index 40a2d41c0..7d407de89 100644 --- a/course/src/test/java/org/openedx/course/presentation/dates/CourseDatesViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/dates/CourseDatesViewModelTest.kt @@ -44,6 +44,7 @@ import org.openedx.core.system.notifier.CourseLoading import org.openedx.core.system.notifier.CourseNotifier import org.openedx.course.domain.interactor.CourseInteractor import org.openedx.course.presentation.CourseAnalytics +import org.openedx.course.presentation.CourseRouter import org.openedx.course.presentation.calendarsync.CalendarManager import java.net.UnknownHostException import java.util.Date @@ -62,6 +63,7 @@ class CourseDatesViewModelTest { private val corePreferences = mockk() private val analytics = mockk() private val config = mockk() + private val courseRouter = mockk() private val openEdx = "OpenEdx" private val calendarTitle = "OpenEdx - Abc" @@ -169,7 +171,8 @@ class CourseDatesViewModelTest { resourceManager, corePreferences, analytics, - config + config, + courseRouter ) coEvery { interactor.getCourseDates(any()) } throws UnknownHostException() val message = async { @@ -195,7 +198,8 @@ class CourseDatesViewModelTest { resourceManager, corePreferences, analytics, - config + config, + courseRouter ) coEvery { interactor.getCourseDates(any()) } throws Exception() val message = async { @@ -221,7 +225,8 @@ class CourseDatesViewModelTest { resourceManager, corePreferences, analytics, - config + config, + courseRouter ) coEvery { interactor.getCourseDates(any()) } returns mockedCourseDatesResult val message = async { @@ -247,7 +252,8 @@ class CourseDatesViewModelTest { resourceManager, corePreferences, analytics, - config + config, + courseRouter ) coEvery { interactor.getCourseDates(any()) } returns CourseDatesResult( datesSection = linkedMapOf(), diff --git a/course/src/test/java/org/openedx/course/presentation/outline/CourseOutlineViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/outline/CourseOutlineViewModelTest.kt index 098960a2a..955b3a85a 100644 --- a/course/src/test/java/org/openedx/course/presentation/outline/CourseOutlineViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/outline/CourseOutlineViewModelTest.kt @@ -56,6 +56,7 @@ import org.openedx.core.system.notifier.CourseNotifier import org.openedx.core.system.notifier.CourseStructureUpdated import org.openedx.course.domain.interactor.CourseInteractor import org.openedx.course.presentation.CourseAnalytics +import org.openedx.course.presentation.CourseRouter import java.net.UnknownHostException import java.util.Date @@ -77,6 +78,7 @@ class CourseOutlineViewModelTest { private val workerController = mockk() private val analytics = mockk() private val coreAnalytics = mockk() + private val courseRouter = mockk() private val noInternet = "Slow or no internet connection" private val somethingWrong = "Something went wrong" @@ -233,6 +235,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController, @@ -267,6 +270,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -311,6 +315,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -357,6 +362,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -403,6 +409,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -437,6 +444,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -485,6 +493,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -528,6 +537,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -563,6 +573,7 @@ class CourseOutlineViewModelTest { networkConnection, preferencesManager, analytics, + courseRouter, coreAnalytics, downloadDao, workerController diff --git a/course/src/test/java/org/openedx/course/presentation/videos/CourseVideoViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/videos/CourseVideoViewModelTest.kt index 43d057a6c..78943d621 100644 --- a/course/src/test/java/org/openedx/course/presentation/videos/CourseVideoViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/videos/CourseVideoViewModelTest.kt @@ -53,6 +53,7 @@ import org.openedx.core.system.notifier.VideoNotifier import org.openedx.course.R import org.openedx.course.domain.interactor.CourseInteractor import org.openedx.course.presentation.CourseAnalytics +import org.openedx.course.presentation.CourseRouter import java.util.Date @OptIn(ExperimentalCoroutinesApi::class) @@ -73,6 +74,7 @@ class CourseVideoViewModelTest { private val networkConnection = mockk() private val downloadDao = mockk() private val workerController = mockk() + private val courseRouter = mockk() private val cantDownload = "You can download content only from Wi-fi" @@ -196,9 +198,10 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, - workerController + workerController, ) viewModel.getVideos() @@ -227,6 +230,7 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -267,6 +271,7 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -308,6 +313,7 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -344,6 +350,7 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, workerController @@ -384,6 +391,7 @@ class CourseVideoViewModelTest { courseNotifier, videoNotifier, analytics, + courseRouter, coreAnalytics, downloadDao, workerController diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesFragment.kt b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesFragment.kt index 635029919..7f0d67ff0 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesFragment.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesFragment.kt @@ -400,7 +400,9 @@ private fun AllEnrolledCoursesScreen( .fillMaxHeight() .then(emptyStatePaddings) ) { - EmptyState() + EmptyState( + currentCourseStatus = CourseStatusFilter.entries[tabPagerState.currentPage] + ) } } } @@ -560,28 +562,33 @@ private fun Header( } @Composable -private fun EmptyState() { +private fun EmptyState( + currentCourseStatus: CourseStatusFilter +) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( - Modifier.width(185.dp), + Modifier.width(200.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Icon( - painter = painterResource(id = R.drawable.dashboard_ic_empty), - contentDescription = null, - tint = MaterialTheme.appColors.textFieldBorder + painter = painterResource(id = R.drawable.dashboard_ic_book), + tint = MaterialTheme.appColors.textFieldBorder, + contentDescription = null ) - Spacer(Modifier.height(16.dp)) + Spacer(Modifier.height(4.dp)) Text( modifier = Modifier - .testTag("txt_empty_state_description") + .testTag("txt_empty_state_title") .fillMaxWidth(), - text = stringResource(id = R.string.dashboard_you_are_not_enrolled), - color = MaterialTheme.appColors.textPrimaryVariant, - style = MaterialTheme.appTypography.bodySmall, + text = stringResource( + id = R.string.dashboard_no_status_courses, + stringResource(currentCourseStatus.labelResId) + ), + color = MaterialTheme.appColors.textDark, + style = MaterialTheme.appTypography.titleMedium, textAlign = TextAlign.Center ) } @@ -616,6 +623,16 @@ private fun AllEnrolledCoursesPreview() { } } +@Preview +@Composable +private fun EmptyStatePreview() { + OpenEdXTheme { + EmptyState( + currentCourseStatus = CourseStatusFilter.COMPLETE + ) + } +} + private val mockCourseAssignments = CourseAssignments(null, emptyList()) private val mockCourseEnrolled = EnrolledCourse( auditAccessExpires = Date(), diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesUIState.kt b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesUIState.kt index 3ec4551f4..9c6166a9b 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesUIState.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesUIState.kt @@ -4,6 +4,6 @@ import org.openedx.core.domain.model.EnrolledCourse sealed class AllEnrolledCoursesUIState { data class Courses(val courses: List) : AllEnrolledCoursesUIState() - object Empty : AllEnrolledCoursesUIState() - object Loading : AllEnrolledCoursesUIState() + data object Empty : AllEnrolledCoursesUIState() + data object Loading : AllEnrolledCoursesUIState() } diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesViewModel.kt b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesViewModel.kt index 59368b04f..22e6914f8 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesViewModel.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesViewModel.kt @@ -1,6 +1,5 @@ package org.openedx.courses.presentation -import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -61,18 +60,8 @@ class AllEnrolledCoursesViewModel( private val currentFilter: MutableStateFlow = MutableStateFlow(CourseStatusFilter.ALL) - override fun onCreate(owner: LifecycleOwner) { - super.onCreate(owner) - viewModelScope.launch { - discoveryNotifier.notifier.collect { - if (it is CourseDashboardUpdate) { - updateCourses() - } - } - } - } - init { + collectDiscoveryNotifier() getCourses(currentFilter.value) } @@ -170,6 +159,15 @@ class AllEnrolledCoursesViewModel( analytics.dashboardCourseClickedEvent(courseId, courseName) } + private fun collectDiscoveryNotifier() { + viewModelScope.launch { + discoveryNotifier.notifier.collect { + if (it is CourseDashboardUpdate) { + updateCourses() + } + } + } + } } interface AllEnrolledCoursesAction { diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseScreen.kt b/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseScreen.kt index 1c4e102c9..14c332aa4 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseScreen.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseScreen.kt @@ -83,6 +83,7 @@ import org.openedx.core.domain.model.Progress import org.openedx.core.presentation.course.CourseContainerTab import org.openedx.core.ui.HandleUIMessage import org.openedx.core.ui.OfflineModeDialog +import org.openedx.core.ui.OpenEdXButton import org.openedx.core.ui.TextIcon import org.openedx.core.ui.rememberWindowSize import org.openedx.core.ui.theme.OpenEdXTheme @@ -124,6 +125,10 @@ fun PrimaryCourseScreen( viewModel.getCourses() } + PrimaryCourseScreenAction.NavigateToDiscovery -> { + viewModel.navigateToDiscovery() + } + is PrimaryCourseScreenAction.OpenCourse -> { viewModel.dashboardRouter.navigateToCourseOutline( fm = fragmentManager, @@ -181,6 +186,7 @@ private fun PrimaryCourseScreen( modifier = Modifier.fillMaxSize(), backgroundColor = MaterialTheme.appColors.background ) { paddingValues -> + HandleUIMessage(uiMessage = uiMessage, scaffoldState = scaffoldState) Surface( @@ -224,8 +230,16 @@ private fun PrimaryCourseScreen( } is PrimaryCourseUIState.Empty -> { - EmptyState( - modifier = Modifier.align(Alignment.Center) + NoCoursesInfo( + modifier = Modifier + .align(Alignment.Center) + ) + FindACourseButton( + modifier = Modifier + .align(Alignment.BottomCenter), + findACourseClick = { + onAction(PrimaryCourseScreenAction.NavigateToDiscovery) + } ) } } @@ -692,7 +706,27 @@ private fun PrimaryCourseTitle( } @Composable -private fun EmptyState( +private fun FindACourseButton( + modifier: Modifier = Modifier, + findACourseClick: () -> Unit +) { + OpenEdXButton( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 20.dp), + onClick = { + findACourseClick() + } + ) { + Text( + color = MaterialTheme.appColors.buttonText, + text = stringResource(id = R.string.dashboard_find_a_course) + ) + } +} + +@Composable +private fun NoCoursesInfo( modifier: Modifier = Modifier ) { Box( @@ -700,22 +734,32 @@ private fun EmptyState( contentAlignment = Alignment.Center ) { Column( - Modifier.width(185.dp), + modifier = Modifier.width(200.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Icon( - painter = painterResource(id = R.drawable.dashboard_ic_empty), - contentDescription = null, - tint = MaterialTheme.appColors.textFieldBorder + painter = painterResource(id = R.drawable.dashboard_ic_book), + tint = MaterialTheme.appColors.textFieldBorder, + contentDescription = null + ) + Spacer(Modifier.height(4.dp)) + Text( + modifier = Modifier + .testTag("txt_empty_state_title") + .fillMaxWidth(), + text = stringResource(id = R.string.dashboard_all_courses_empty_title), + color = MaterialTheme.appColors.textDark, + style = MaterialTheme.appTypography.titleMedium, + textAlign = TextAlign.Center ) - Spacer(Modifier.height(16.dp)) + Spacer(Modifier.height(12.dp)) Text( modifier = Modifier .testTag("txt_empty_state_description") .fillMaxWidth(), - text = stringResource(id = R.string.dashboard_you_are_not_enrolled), - color = MaterialTheme.appColors.textPrimaryVariant, - style = MaterialTheme.appTypography.bodySmall, + text = stringResource(id = R.string.dashboard_all_courses_empty_description), + color = MaterialTheme.appColors.textDark, + style = MaterialTheme.appTypography.labelMedium, textAlign = TextAlign.Center ) } @@ -807,3 +851,11 @@ private fun PrimaryCourseScreenPreview() { ) } } + +@Preview +@Composable +private fun NoCoursesInfoPreview() { + OpenEdXTheme { + NoCoursesInfo() + } +} diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseViewModel.kt b/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseViewModel.kt index 14b9b1db7..a1362a7ab 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseViewModel.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/PrimaryCourseViewModel.kt @@ -18,6 +18,7 @@ import org.openedx.core.system.ResourceManager import org.openedx.core.system.connection.NetworkConnection import org.openedx.core.system.notifier.CourseDashboardUpdate import org.openedx.core.system.notifier.DiscoveryNotifier +import org.openedx.core.system.notifier.NavigationToDiscovery import org.openedx.core.utils.FileUtil import org.openedx.courses.domain.model.UserCourses import org.openedx.dashboard.domain.interactor.DashboardInteractor @@ -90,6 +91,10 @@ class PrimaryCourseViewModel( getCourses() } + fun navigateToDiscovery() { + viewModelScope.launch { discoveryNotifier.send(NavigationToDiscovery()) } + } + private fun collectDiscoveryNotifier() { viewModelScope.launch { discoveryNotifier.notifier.collect { @@ -105,6 +110,7 @@ interface PrimaryCourseScreenAction { object SwipeRefresh : PrimaryCourseScreenAction object ViewAll : PrimaryCourseScreenAction object Reload : PrimaryCourseScreenAction + object NavigateToDiscovery : PrimaryCourseScreenAction data class OpenBlock(val enrolledCourse: EnrolledCourse, val blockId: String) : PrimaryCourseScreenAction data class OpenCourse(val enrolledCourse: EnrolledCourse) : PrimaryCourseScreenAction data class NavigateToDates(val enrolledCourse: EnrolledCourse) : PrimaryCourseScreenAction diff --git a/dashboard/src/main/java/org/openedx/learn/presentation/LearnFragment.kt b/dashboard/src/main/java/org/openedx/learn/presentation/LearnFragment.kt index af01e8253..f1b9d07f3 100644 --- a/dashboard/src/main/java/org/openedx/learn/presentation/LearnFragment.kt +++ b/dashboard/src/main/java/org/openedx/learn/presentation/LearnFragment.kt @@ -21,7 +21,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandMore -import androidx.compose.material.icons.filled.Search import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -32,6 +31,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp @@ -56,6 +56,7 @@ import org.openedx.dashboard.R import org.openedx.dashboard.databinding.FragmentLearnBinding import org.openedx.dashboard.presentation.DashboardRouter import org.openedx.learn.LearnType +import org.openedx.core.R as CoreR class LearnFragment : Fragment(R.layout.fragment_learn) { @@ -121,11 +122,9 @@ private fun Header( horizontalAlignment = Alignment.CenterHorizontally ) { Title( - modifier = Modifier - .padding(horizontal = 16.dp), label = stringResource(id = R.string.dashboard_learn), - onSearchClick = { - viewModel.onSearchClick(fragmentManager) + onSettingsClick = { + viewModel.onSettingsClick(fragmentManager) } ) @@ -144,13 +143,15 @@ private fun Header( private fun Title( modifier: Modifier = Modifier, label: String, - onSearchClick: () -> Unit + onSettingsClick: () -> Unit ) { Box( modifier = modifier.fillMaxWidth() ) { Text( - modifier = Modifier.align(Alignment.CenterStart), + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 16.dp), text = label, color = MaterialTheme.appColors.textDark, style = MaterialTheme.appTypography.headlineBolt @@ -158,15 +159,15 @@ private fun Title( IconButton( modifier = Modifier .align(Alignment.CenterEnd) - .padding(start = 16.dp), + .padding(end = 12.dp), onClick = { - onSearchClick() + onSettingsClick() } ) { Icon( - imageVector = Icons.Filled.Search, - contentDescription = null, - tint = MaterialTheme.appColors.textDark + painter = painterResource(id = CoreR.drawable.core_ic_settings), + tint = MaterialTheme.appColors.primary, + contentDescription = stringResource(id = CoreR.string.core_accessibility_settings) ) } } @@ -259,7 +260,7 @@ private fun HeaderPreview() { OpenEdXTheme { Title( label = stringResource(id = R.string.dashboard_learn), - onSearchClick = {} + onSettingsClick = {} ) } } diff --git a/dashboard/src/main/java/org/openedx/learn/presentation/LearnViewModel.kt b/dashboard/src/main/java/org/openedx/learn/presentation/LearnViewModel.kt index fe5136dff..d2300f652 100644 --- a/dashboard/src/main/java/org/openedx/learn/presentation/LearnViewModel.kt +++ b/dashboard/src/main/java/org/openedx/learn/presentation/LearnViewModel.kt @@ -12,7 +12,7 @@ class LearnViewModel( val isProgramTypeWebView get() = config.getProgramConfig().isViewTypeWebView() - fun onSearchClick(fragmentManager: FragmentManager) { - dashboardRouter.navigateToCourseSearch(fragmentManager, "") + fun onSettingsClick(fragmentManager: FragmentManager) { + dashboardRouter.navigateToSettings(fragmentManager) } } diff --git a/dashboard/src/main/res/values/strings.xml b/dashboard/src/main/res/values/strings.xml index fdcd630d9..662bc4f8e 100644 --- a/dashboard/src/main/res/values/strings.xml +++ b/dashboard/src/main/res/values/strings.xml @@ -19,4 +19,8 @@ Expired All Courses All + No Courses + You are not currently enrolled in any courses, would you like to explore the course catalog? + Find a Course + No %1$s Courses