From 16dc91f18d21dba187ed61410c3fcacaff7bd638 Mon Sep 17 00:00:00 2001 From: Joe Hoag Date: Mon, 26 Aug 2019 10:04:56 -0600 Subject: [PATCH] [Student][NewRelic][MBL-13108]: USE_REMOTE_CONFIG -> USE_NEW_RELIC (#267) * [RC6.6.1] Change cancel text to red (#263) * [Teacher][MBL-13105] Post Policy skeleton (#257) Added the feature flag, necessary strings, and the view pager layout for the base screen. Now just the two individual screens need their loops/views done. * MBL-13108: USE_REMOTE_CONFIG -> USE_NEW_RELIC --- .../student/activity/LoginActivity.kt | 2 +- .../postpolicies/PostPolicyFragment.kt | 88 +++++++++++++++++++ .../postpolicies/ui/HideGradeFragment.kt | 46 ++++++++++ .../postpolicies/ui/PostGradeFragment.kt | 46 ++++++++++ .../AssignmentSubmissionListFragment.kt | 8 ++ .../teacher/router/RouteMatcher.kt | 7 +- .../teacher/router/RouteResolver.kt | 4 + .../instructure/teacher/utils/FeatureFlags.kt | 3 +- .../fragment_assignment_submission_list.xml | 3 +- .../layout/fragment_post_policy_settings.xml | 65 ++++++++++++++ .../main/res/menu/menu_filter_submissions.xml | 6 ++ .../canvasapi2/utils/RemoteConfigUtils.kt | 2 +- .../src/main/res/drawable/ic_eye_filled.xml | 26 ++++++ .../src/main/res/drawable/ic_mail_filled.xml | 26 ++++++ libs/pandares/src/main/res/values/strings.xml | 17 ++++ 15 files changed, 341 insertions(+), 8 deletions(-) create mode 100644 apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/PostPolicyFragment.kt create mode 100644 apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/HideGradeFragment.kt create mode 100644 apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/PostGradeFragment.kt create mode 100644 apps/teacher/src/main/res/layout/fragment_post_policy_settings.xml create mode 100644 libs/pandares/src/main/res/drawable/ic_eye_filled.xml create mode 100644 libs/pandares/src/main/res/drawable/ic_mail_filled.xml diff --git a/apps/student/src/main/java/com/instructure/student/activity/LoginActivity.kt b/apps/student/src/main/java/com/instructure/student/activity/LoginActivity.kt index 348438d77a..d51be7941c 100644 --- a/apps/student/src/main/java/com/instructure/student/activity/LoginActivity.kt +++ b/apps/student/src/main/java/com/instructure/student/activity/LoginActivity.kt @@ -76,7 +76,7 @@ class LoginActivity : BaseLoginInitActivity() { override fun onCreate(savedInstanceState: Bundle?) { val startNewRelic = - RemoteConfigUtils.getString(RemoteConfigParam.USE_REMOTE_CONFIG)?.equals("true",ignoreCase = true) ?: false + RemoteConfigUtils.getString(RemoteConfigParam.USE_NEW_RELIC)?.equals("true",ignoreCase = true) ?: false Log.v("LoginActivity","startNewRelic=$startNewRelic") diff --git a/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/PostPolicyFragment.kt b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/PostPolicyFragment.kt new file mode 100644 index 0000000000..27c0802de5 --- /dev/null +++ b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/PostPolicyFragment.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 - present Instructure, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.instructure.teacher.features.postpolicies + +import android.graphics.Color +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentPagerAdapter +import com.instructure.canvasapi2.models.Assignment +import com.instructure.canvasapi2.models.Course +import com.instructure.interactions.router.Route +import com.instructure.pandautils.utils.* +import com.instructure.teacher.R +import com.instructure.teacher.features.postpolicies.ui.HideGradeFragment +import com.instructure.teacher.features.postpolicies.ui.PostGradeFragment +import com.instructure.teacher.utils.setupBackButtonAsBackPressedOnly +import kotlinx.android.synthetic.main.fragment_post_policy_settings.* +import kotlinx.android.synthetic.main.fragment_post_policy_settings.view.* + +class PostPolicyFragment : Fragment() { + + private var assignment: Assignment by ParcelableArg(Assignment(), Const.ASSIGNMENT) + private var course: Course by ParcelableArg(Course(), Const.CANVAS_CONTEXT) + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.fragment_post_policy_settings, container, false) + + val titles = listOf(getString(R.string.postGradesTab), getString(R.string.hideGradesTab)) + view.postPolicyPager.adapter = PostPolicyPagerAdapter(course, assignment, childFragmentManager, titles) + view.postPolicyTabLayout.setupWithViewPager(view.postPolicyPager, true) + + return view + } + + override fun onResume() { + super.onResume() + applyTheme() + } + + private fun applyTheme() { + postPolicyToolbar.setupBackButtonAsBackPressedOnly(this) + + ViewStyler.themeToolbar(requireActivity(), postPolicyToolbar, Color.WHITE, Color.BLACK) + + val courseColor = ColorKeeper.getOrGenerateColor(course) + postPolicyTabLayout.setSelectedTabIndicatorColor(courseColor) + postPolicyTabLayout.setTabTextColors(ContextCompat.getColor(requireContext(), R.color.gray), courseColor) + } + + companion object { + fun makeRoute(course: Course, assignment: Assignment) = + Route(PostPolicyFragment::class.java, course, Bundle().apply { putParcelable(Const.ASSIGNMENT, assignment) }) + + fun newInstance(args: Bundle) = PostPolicyFragment().withArgs(args) + } +} + +private class PostPolicyPagerAdapter(val course: Course, val assignment: Assignment, fragmentManager: FragmentManager, val titles: List) : FragmentPagerAdapter(fragmentManager) { + override fun getCount() = 2 + override fun getPageTitle(position: Int) = titles[position] + + override fun getItem(position: Int): Fragment { + return when (position) { + 0 -> PostGradeFragment.newInstance(course, assignment) + 1 -> HideGradeFragment.newInstance(course, assignment) + else -> throw IndexOutOfBoundsException("No post policy adapter item at position $position") + } + } +} \ No newline at end of file diff --git a/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/HideGradeFragment.kt b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/HideGradeFragment.kt new file mode 100644 index 0000000000..17a1638c9d --- /dev/null +++ b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/HideGradeFragment.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 - present Instructure, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.instructure.teacher.features.postpolicies.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import com.instructure.canvasapi2.models.Assignment +import com.instructure.canvasapi2.models.Course +import com.instructure.pandautils.utils.Const +import com.instructure.pandautils.utils.ParcelableArg +import com.instructure.pandautils.utils.makeBundle +import com.instructure.pandautils.utils.withArgs +import com.instructure.teacher.R + +class HideGradeFragment : Fragment() { + private var assignment: Assignment by ParcelableArg(Assignment(), Const.ASSIGNMENT) + private var course: Course by ParcelableArg(Course(), Const.CANVAS_CONTEXT) + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return TextView(requireContext()).apply { setText(R.string.hideGradesTab) } + } + + companion object { + fun newInstance(course: Course, assignment: Assignment) = HideGradeFragment().withArgs(course.makeBundle { + putParcelable(Const.ASSIGNMENT, assignment) + }) + } +} diff --git a/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/PostGradeFragment.kt b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/PostGradeFragment.kt new file mode 100644 index 0000000000..f81b46dbfc --- /dev/null +++ b/apps/teacher/src/main/java/com/instructure/teacher/features/postpolicies/ui/PostGradeFragment.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 - present Instructure, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.instructure.teacher.features.postpolicies.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import com.instructure.canvasapi2.models.Assignment +import com.instructure.canvasapi2.models.Course +import com.instructure.pandautils.utils.Const +import com.instructure.pandautils.utils.ParcelableArg +import com.instructure.pandautils.utils.makeBundle +import com.instructure.pandautils.utils.withArgs +import com.instructure.teacher.R + +class PostGradeFragment : Fragment() { + private var assignment: Assignment by ParcelableArg(Assignment(), Const.ASSIGNMENT) + private var course: Course by ParcelableArg(Course(), Const.CANVAS_CONTEXT) + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return TextView(requireContext()).apply { setText(R.string.postGradesTab) } + } + + companion object { + fun newInstance(course: Course, assignment: Assignment) = PostGradeFragment().withArgs(course.makeBundle { + putParcelable(Const.ASSIGNMENT, assignment) + }) + } +} diff --git a/apps/teacher/src/main/java/com/instructure/teacher/fragments/AssignmentSubmissionListFragment.kt b/apps/teacher/src/main/java/com/instructure/teacher/fragments/AssignmentSubmissionListFragment.kt index 7b1a26d979..735aca7481 100644 --- a/apps/teacher/src/main/java/com/instructure/teacher/fragments/AssignmentSubmissionListFragment.kt +++ b/apps/teacher/src/main/java/com/instructure/teacher/fragments/AssignmentSubmissionListFragment.kt @@ -40,6 +40,7 @@ import com.instructure.teacher.events.AssignmentGradedEvent import com.instructure.teacher.events.SubmissionCommentsUpdated import com.instructure.teacher.events.SubmissionFilterChangedEvent import com.instructure.teacher.factory.AssignmentSubmissionListPresenterFactory +import com.instructure.teacher.features.postpolicies.PostPolicyFragment import com.instructure.teacher.holders.GradeableStudentSubmissionViewHolder import com.instructure.teacher.presenters.AssignmentSubmissionListPresenter import com.instructure.teacher.presenters.AssignmentSubmissionListPresenter.SubmissionListFilter @@ -286,14 +287,21 @@ class AssignmentSubmissionListFragment : BaseSyncFragment< EventBus.getDefault().post(SubmissionFilterChangedEvent(canvasContext = canvasContexts)) }.show(requireActivity().supportFragmentManager, PeopleListFilterDialog::class.java.simpleName) } + R.id.menuPostPolicies -> { + RouteMatcher.route(requireContext(), PostPolicyFragment.makeRoute(mCourse, mAssignment)) + } } } private fun updateStatuses() { val isMuted = presenter.mAssignment.muted assignmentSubmissionListToolbar.menu.findItem(R.id.menuMuteGrades)?.let { + it.isVisible = !FeatureFlags.postPolicies it.title = getString(if (isMuted) R.string.unmuteGrades else R.string.muteGrades) } + assignmentSubmissionListToolbar.menu.findItem(R.id.menuPostPolicies)?.let { + it.isVisible = FeatureFlags.postPolicies + } val statuses = mutableListOf() if (presenter.mAssignment.anonymousGrading) statuses += getString(R.string.anonymousGradingLabel) diff --git a/apps/teacher/src/main/java/com/instructure/teacher/router/RouteMatcher.kt b/apps/teacher/src/main/java/com/instructure/teacher/router/RouteMatcher.kt index 890849967e..16f075c41b 100644 --- a/apps/teacher/src/main/java/com/instructure/teacher/router/RouteMatcher.kt +++ b/apps/teacher/src/main/java/com/instructure/teacher/router/RouteMatcher.kt @@ -42,14 +42,12 @@ import com.instructure.interactions.router.RouteContext import com.instructure.interactions.router.RouterParams import com.instructure.pandautils.activities.BaseViewMediaActivity import com.instructure.pandautils.loaders.OpenMediaAsyncTaskLoader -import com.instructure.pandautils.utils.Const -import com.instructure.pandautils.utils.LoaderUtils -import com.instructure.pandautils.utils.RouteUtils -import com.instructure.pandautils.utils.nonNullArgs +import com.instructure.pandautils.utils.* import com.instructure.teacher.PSPDFKit.AnnotationComments.AnnotationCommentListFragment import com.instructure.teacher.R import com.instructure.teacher.activities.* import com.instructure.teacher.adapters.StudentContextFragment +import com.instructure.teacher.features.postpolicies.PostPolicyFragment import com.instructure.teacher.fragments.* import com.instructure.teacher.fragments.FileListFragment import instructure.rceditor.RCEFragment @@ -332,6 +330,7 @@ object RouteMatcher : BaseRouteMatcher() { AssignmentDetailsFragment::class.java.isAssignableFrom(cls) -> fragment = getAssignmentDetailsFragment(canvasContext, route) DueDatesFragment::class.java.isAssignableFrom(cls) -> fragment = DueDatesFragment.getInstance((canvasContext as Course?)!!, route.arguments) AssignmentSubmissionListFragment::class.java.isAssignableFrom(cls) -> fragment = AssignmentSubmissionListFragment.newInstance((canvasContext as Course?)!!, route.arguments) + PostPolicyFragment::class.java.isAssignableFrom(cls) -> fragment = PostPolicyFragment.newInstance(route.argsWithContext) EditAssignmentDetailsFragment::class.java.isAssignableFrom(cls) -> fragment = EditAssignmentDetailsFragment.newInstance((canvasContext as Course?)!!, route.arguments) AssigneeListFragment::class.java.isAssignableFrom(cls) -> fragment = AssigneeListFragment.newInstance(route.arguments) EditFavoritesFragment::class.java.isAssignableFrom(cls) -> fragment = EditFavoritesFragment.newInstance(route.arguments) diff --git a/apps/teacher/src/main/java/com/instructure/teacher/router/RouteResolver.kt b/apps/teacher/src/main/java/com/instructure/teacher/router/RouteResolver.kt index 54a7f111f9..e1893ee32c 100644 --- a/apps/teacher/src/main/java/com/instructure/teacher/router/RouteResolver.kt +++ b/apps/teacher/src/main/java/com/instructure/teacher/router/RouteResolver.kt @@ -6,10 +6,12 @@ import com.instructure.canvasapi2.models.Course import com.instructure.interactions.router.Route import com.instructure.interactions.router.RouterParams import com.instructure.pandautils.utils.Const +import com.instructure.pandautils.utils.argsWithContext import com.instructure.teacher.PSPDFKit.AnnotationComments.AnnotationCommentListFragment import com.instructure.teacher.adapters.StudentContextFragment import com.instructure.teacher.features.files.search.FileSearchFragment import com.instructure.teacher.features.modules.list.ui.ModuleListFragment +import com.instructure.teacher.features.postpolicies.PostPolicyFragment import com.instructure.teacher.fragments.* import instructure.rceditor.RCEFragment @@ -76,6 +78,8 @@ object RouteResolver { fragment = DueDatesFragment.getInstance((canvasContext as Course?)!!, route.arguments) } else if (AssignmentSubmissionListFragment::class.java.isAssignableFrom(cls)) { fragment = AssignmentSubmissionListFragment.newInstance((canvasContext as Course?)!!, route.arguments) + } else if (PostPolicyFragment::class.java.isAssignableFrom(cls)) { + fragment = PostPolicyFragment.newInstance(route.argsWithContext) } else if (EditAssignmentDetailsFragment::class.java.isAssignableFrom(cls)) { fragment = EditAssignmentDetailsFragment.newInstance((canvasContext as Course?)!!, route.arguments) } else if (AssigneeListFragment::class.java.isAssignableFrom(cls)) { diff --git a/apps/teacher/src/main/java/com/instructure/teacher/utils/FeatureFlags.kt b/apps/teacher/src/main/java/com/instructure/teacher/utils/FeatureFlags.kt index 7277d07212..7fd55e7944 100644 --- a/apps/teacher/src/main/java/com/instructure/teacher/utils/FeatureFlags.kt +++ b/apps/teacher/src/main/java/com/instructure/teacher/utils/FeatureFlags.kt @@ -15,8 +15,9 @@ */ package com.instructure.teacher.utils +import com.instructure.canvasapi2.utils.FeatureFlagPref import com.instructure.canvasapi2.utils.PrefManager object FeatureFlags : PrefManager("feature_flags") { - + var postPolicies by FeatureFlagPref("Post Policies") } diff --git a/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml b/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml index 6aee9c7d9f..93942c4052 100644 --- a/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml +++ b/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml @@ -122,7 +122,8 @@ android:layout_margin="16dp" app:fabSize="normal" app:elevation="4dp" - app:srcCompat="@drawable/vd_mail" + app:srcCompat="@drawable/ic_mail_filled" + android:tint="@color/white" android:contentDescription="@string/sendMessage"/> diff --git a/apps/teacher/src/main/res/layout/fragment_post_policy_settings.xml b/apps/teacher/src/main/res/layout/fragment_post_policy_settings.xml new file mode 100644 index 0000000000..75eac3c78a --- /dev/null +++ b/apps/teacher/src/main/res/layout/fragment_post_policy_settings.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + diff --git a/apps/teacher/src/main/res/menu/menu_filter_submissions.xml b/apps/teacher/src/main/res/menu/menu_filter_submissions.xml index 92b689dcb0..059be842f4 100644 --- a/apps/teacher/src/main/res/menu/menu_filter_submissions.xml +++ b/apps/teacher/src/main/res/menu/menu_filter_submissions.xml @@ -16,6 +16,12 @@ --> + + + + diff --git a/libs/pandares/src/main/res/drawable/ic_mail_filled.xml b/libs/pandares/src/main/res/drawable/ic_mail_filled.xml new file mode 100644 index 0000000000..de2bca9820 --- /dev/null +++ b/libs/pandares/src/main/res/drawable/ic_mail_filled.xml @@ -0,0 +1,26 @@ + + + + diff --git a/libs/pandares/src/main/res/values/strings.xml b/libs/pandares/src/main/res/values/strings.xml index f7c24fbc60..51fdc21780 100644 --- a/libs/pandares/src/main/res/values/strings.xml +++ b/libs/pandares/src/main/res/values/strings.xml @@ -1031,6 +1031,23 @@ Complete Incomplete + + Post Settings + Post Grades + Hide Grades + %d grades currently posted + %d grades currently hidden + Post to… + Specific Sections + Everyone + Grades will be made visible to all students + Graded + Grades will be made visible to students with graded submissions + All Hidden + All grades are currently hidden. + All Posted + All grades are currently posted. + 00:00:00 %1$d hours, %2$d minutes, and %3$d seconds