Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Average grade improvement #1439

Merged
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
c22fc50
Added ui to enter grade parameters
tobiasjungmann Apr 29, 2022
521b5aa
Added menu item to enter edit mode
tobiasjungmann Apr 29, 2022
eaa6f76
Added click listener to edit menu item to toggle edit mode
tobiasjungmann Apr 29, 2022
1590d7c
toggeling edit mode changes now all ui elements
tobiasjungmann May 4, 2022
e945497
Exam List is stored as a json object in shared preferences
tobiasjungmann May 6, 2022
6a1391e
connected ui to the model - exams are saved permanently in shared pre…
tobiasjungmann May 6, 2022
1fcb966
connected checkbox to the exam model
tobiasjungmann May 6, 2022
d671990
reordered ui elements for better visibility
tobiasjungmann May 6, 2022
d52dbba
extracted string ressources
tobiasjungmann May 6, 2022
9f1c940
downloading new grades update the existing grade list
tobiasjungmann May 6, 2022
1dbf340
hidden grades are o displayed correctly after initialization
tobiasjungmann May 6, 2022
f00f0c3
added ui to manually add exams
tobiasjungmann May 9, 2022
3076c27
added ui to delete manually added exams
tobiasjungmann May 9, 2022
1452b40
added logic to delete manually added exams
tobiasjungmann May 11, 2022
835b4c4
added logic to manually add exams
tobiasjungmann May 11, 2022
a542da0
reduced number of store operations, newly added exams are now directl…
tobiasjungmann May 11, 2022
57da62f
finished manually adding and deleting exams
tobiasjungmann May 11, 2022
603f0e8
started input sanitization, tried to fix recycler overwrites
tobiasjungmann May 11, 2022
ce218f0
improved input sanitization for remaining attributes
tobiasjungmann May 12, 2022
3a2c330
adapted computation of the average grade
tobiasjungmann May 12, 2022
f7b206e
prevented wrong updates of credits in the recycler view
tobiasjungmann May 12, 2022
a5be907
fixed ui inconsistencies, reduced method sizes
tobiasjungmann May 12, 2022
d337a3e
persistently stored exams in shared preferences
tobiasjungmann May 12, 2022
1e0ef3f
extracted string resources
tobiasjungmann May 12, 2022
0464fe5
linted small warnings
tobiasjungmann May 12, 2022
c775f3b
fixed styling issue with the add grade dialog, added option for weigh…
tobiasjungmann May 15, 2022
b0265cd
fixed unclickable checkbox
tobiasjungmann May 15, 2022
fb4a87e
fixed inconsistency in saving exams to the shared preferences
tobiasjungmann May 15, 2022
e2b73d9
changed stickyListHeaders import to a still maintained project to pre…
tobiasjungmann May 15, 2022
5758a1f
added translations, linted; show program spinner only if more than on…
tobiasjungmann May 15, 2022
9a83a50
Merge branch 'master' into 1426_Average_Grade_Improvement
tobiasjungmann May 15, 2022
a01fc20
added more intuitive icons, fixed translation
tobiasjungmann May 21, 2022
66cef3c
Added ui to enter grade parameters
tobiasjungmann Apr 29, 2022
22e80ad
Added menu item to enter edit mode
tobiasjungmann Apr 29, 2022
e16fec2
Added click listener to edit menu item to toggle edit mode
tobiasjungmann Apr 29, 2022
4995b02
toggeling edit mode changes now all ui elements
tobiasjungmann May 4, 2022
90a7fe5
Exam List is stored as a json object in shared preferences
tobiasjungmann May 6, 2022
7ed75ea
connected ui to the model - exams are saved permanently in shared pre…
tobiasjungmann May 6, 2022
d694ce2
connected checkbox to the exam model
tobiasjungmann May 6, 2022
f4abf2d
reordered ui elements for better visibility
tobiasjungmann May 6, 2022
34b89bd
extracted string ressources
tobiasjungmann May 6, 2022
9cf7c9e
downloading new grades update the existing grade list
tobiasjungmann May 6, 2022
e164104
hidden grades are o displayed correctly after initialization
tobiasjungmann May 6, 2022
95a929a
added ui to manually add exams
tobiasjungmann May 9, 2022
97cae1f
added ui to delete manually added exams
tobiasjungmann May 9, 2022
154df3e
added logic to delete manually added exams
tobiasjungmann May 11, 2022
3fcc939
added logic to manually add exams
tobiasjungmann May 11, 2022
4bf6c40
reduced number of store operations, newly added exams are now directl…
tobiasjungmann May 11, 2022
cd76337
finished manually adding and deleting exams
tobiasjungmann May 11, 2022
4830e78
started input sanitization, tried to fix recycler overwrites
tobiasjungmann May 11, 2022
971f4df
improved input sanitization for remaining attributes
tobiasjungmann May 12, 2022
8f8fa02
adapted computation of the average grade
tobiasjungmann May 12, 2022
d996f2f
prevented wrong updates of credits in the recycler view
tobiasjungmann May 12, 2022
5b9b1dd
fixed ui inconsistencies, reduced method sizes
tobiasjungmann May 12, 2022
e96855c
persistently stored exams in shared preferences
tobiasjungmann May 12, 2022
98612e9
extracted string resources
tobiasjungmann May 12, 2022
8027d37
linted small warnings
tobiasjungmann May 12, 2022
336d7d0
fixed styling issue with the add grade dialog, added option for weigh…
tobiasjungmann May 15, 2022
1b6a7b3
fixed unclickable checkbox
tobiasjungmann May 15, 2022
36159f5
fixed inconsistency in saving exams to the shared preferences
tobiasjungmann May 15, 2022
e2e30ff
added translations, linted; show program spinner only if more than on…
tobiasjungmann May 15, 2022
b49e51b
Fix Build (#1436)
ctsk May 12, 2022
9b7ac5a
Update appcompat, fragment libraries and fix findViewById() in Fragme…
jfoerste May 12, 2022
346da82
Release 3.18
kordianbruck May 12, 2022
1898b73
added more intuitive icons, fixed translation
tobiasjungmann May 21, 2022
9c9b16a
Merge remote-tracking branch 'origin/1426_Average_Grade_Improvement' …
tobiasjungmann Jul 13, 2022
9286b1b
Merge branch 'master' into 1426_Average_Grade_Improvement
tobiasjungmann Jul 14, 2022
fe89a5d
fixed errors from merging
tobiasjungmann Jul 14, 2022
6a688e6
added questionmark to text
tobiasjungmann Jul 20, 2022
e39fc48
Merge branch 'master' into 1426_Average_Grade_Improvement
tobiasjungmann Jul 21, 2022
4fa596a
Update app/src/main/java/de/tum/in/tumcampusapp/component/tumui/grade…
tobiasjungmann Jul 27, 2022
43e7127
Apply suggestions from code review
tobiasjungmann Jul 27, 2022
d524dae
Apply suggestions from code review in grades Fragment
tobiasjungmann Jul 28, 2022
8000555
implemented requested feedback
tobiasjungmann Jul 28, 2022
8b56125
linted grade files
tobiasjungmann Jul 28, 2022
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
18 changes: 14 additions & 4 deletions app/src/main/java/de/tum/in/tumcampusapp/api/app/DateSerializer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import java.util.*
*/
class DateSerializer : JsonDeserializer<DateTime>, JsonSerializer<DateTime> {
private val formatStrings = arrayOf(
"yyyy-MM-dd",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ss'Z'"
"dd.MM.yy",
"dd.MM.yyyy",
"yyyy.MM.dd",
"dd-MM-yy",
"dd-MM-yyyy",
"yyyy-MM-dd",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ss'Z'"
)

private val dateFormats = formatStrings.map {
Expand All @@ -35,9 +40,14 @@ class DateSerializer : JsonDeserializer<DateTime>, JsonSerializer<DateTime> {
}
}
throw JsonParseException("Unparseable date: \"${json?.asString.orEmpty()}\". Supported formats: ${formatStrings.contentToString()}")

}

override fun serialize(time: DateTime, typeOfT: Type, context: JsonSerializationContext): JsonElement {
override fun serialize(
time: DateTime,
typeOfT: Type,
context: JsonSerializationContext
): JsonElement {
return JsonPrimitive(DateTimeUtils.getDateString(time))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import org.joda.time.format.DateTimeFormat
class DateTimeConverter : TypeConverter<DateTime?> {

private val formats = arrayOf(
"yyyy-MM-dd",
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH:mm:ss"
"dd.MM.yy",
"dd.MM.yyyy",
"yyyy-MM-dd",
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH:mm:ss"
)

override fun read(value: String?): DateTime? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package de.tum.`in`.tumcampusapp.component.tumui.grades

import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.*
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import de.tum.`in`.tumcampusapp.R
import de.tum.`in`.tumcampusapp.component.other.generic.adapter.SimpleStickyListHeadersAdapter
import de.tum.`in`.tumcampusapp.component.tumui.grades.model.Exam
import org.joda.time.format.DateTimeFormat


/**
* Custom UI adapter for a list of exams.
*/
class ExamListAdapter(context: Context, results: List<Exam>) : SimpleStickyListHeadersAdapter<Exam>(context, results.toMutableList()) {
class ExamListAdapter(context: Context, results: List<Exam>, gradesFragment: GradesFragment) :
SimpleStickyListHeadersAdapter<Exam>(context, results.toMutableList()) {

val localGradesFragment: GradesFragment = gradesFragment

init {
itemList.sort()
Expand All @@ -32,26 +39,188 @@ class ExamListAdapter(context: Context, results: List<Exam>) : SimpleStickyListH
}

val exam = itemList[position]


initUIEditElements(holder, exam)
initUIDisplayElements(holder, exam)
return view
}

private fun initUIDisplayElements(holder: ViewHolder, exam: Exam) {
holder.nameTextView.text = exam.course
holder.gradeTextView.text = exam.grade

val gradeColor = exam.getGradeColor(context)
holder.gradeTextView.background.setTint(gradeColor)

adaptUIToCheckboxStatus(holder, exam)

val date: String = if (exam.date == null) {
context.getString(R.string.not_specified)
} else {
DATE_FORMAT.print(exam.date)
}
holder.examDateTextView.text = String.format("%s: %s", context.getString(R.string.date), date)
holder.examDateTextView.text =
String.format("%s: %s", context.getString(R.string.date), date)

holder.additionalInfoTextView.text = String.format("%s: %s, %s: %s",
context.getString(R.string.examiner), exam.examiner,
context.getString(R.string.mode), exam.modus)
holder.additionalInfoTextView.text = String.format(
"%s: %s, %s: %s",
context.getString(R.string.examiner), exam.examiner,
context.getString(R.string.mode), exam.modus
)
}

return view

/**
* Init the ui Elements to change the parameters of the grade
*/
private fun initUIEditElements(holder: ViewHolder, exam: Exam) {
if (localGradesFragment.getGlobalEdit()) {
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
holder.editGradesContainer.visibility = View.GONE
holder.gradeTextViewDeleteCustomGrade.visibility = View.GONE
} else {
holder.editGradesContainer.visibility = View.VISIBLE

initListenerDeleteCustomGrade(exam, holder)
initListenerEditTexts(exam, holder)
initListenerResetGradeParameters(exam, holder)
initCheckBoxUsedInAverage(exam, holder)
}
}


/**
* Adds a Clicklistener which will show confirmation dialog whether the exam should actually be deleted.
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
*/
private fun initListenerDeleteCustomGrade(exam: Exam, holder: ViewHolder) {
if (exam.manuallyAdded) {
holder.gradeTextViewDeleteCustomGrade.visibility = View.VISIBLE

holder.gradeTextViewDeleteCustomGrade.setOnClickListener {
val dialog = AlertDialog.Builder(localGradesFragment.requireContext())
.setTitle(context.getString(R.string.delete_exam))
.setMessage(
context.getString(R.string.delete_exam_dialog_message)
)
.setPositiveButton(R.string.delete) { _, _ ->

localGradesFragment.deleteExamFromList(exam)
}
.setNegativeButton(android.R.string.cancel, null)
.create()
.apply {
window?.setBackgroundDrawableResource(R.drawable.rounded_corners_background)
}
dialog.show()
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(
localGradesFragment.resources.getColor(R.color.text_primary)
)
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(
localGradesFragment.resources.getColor(R.color.text_primary)
)
}
} else {
holder.gradeTextViewDeleteCustomGrade.visibility = View.GONE
}

}


/**
* Adds on Focus change listeners which store the value to the exam object if and only if the
* user finished editing the exam.
*/
private fun initListenerEditTexts(exam: Exam, holder: ViewHolder) {
holder.editTextGradeWeights.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val helper = holder.editTextGradeWeights.text.toString().toDouble()
if (exam.weight != helper) {
exam.weight = helper
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
localGradesFragment.storeExamListInSharedPreferences()
notifyDataSetChanged()
}
}
}

holder.editTextGradeCredits.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val helper = holder.editTextGradeCredits.text.toString().toInt()
if (exam.credits_new != helper) {
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
exam.credits_new = helper
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
localGradesFragment.storeExamListInSharedPreferences()
notifyDataSetChanged()
}
}
}
holder.editTextGradeWeights.setText(exam.weight.toString())
holder.editTextGradeCredits.setText(exam.credits_new.toString())
}


/**
* Adds a ClickListener to reset one exam to the default values and adapts the UI accordingly
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
*/
private fun initListenerResetGradeParameters(exam: Exam, holder: ViewHolder) {
holder.buttonResetGradeParameters.setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
exam.gradeUsedInAverage = true
adaptUIToCheckboxStatus(holder, exam)
holder.checkBoxUseGradeForAverage.isChecked = true
exam.weight = 1.0
exam.credits_new = 6
holder.editTextGradeWeights.setText(exam.weight.toString())
holder.editTextGradeCredits.setText(exam.credits_new.toString())
localGradesFragment.storeExamListInSharedPreferences()
notifyDataSetChanged()
}

})
}

/**
* Initialises the state of the checkbox and adapts the ui accordingly
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
*/
private fun initCheckBoxUsedInAverage(exam: Exam, holder: ViewHolder) {
holder.checkBoxUseGradeForAverage.isChecked = exam.gradeUsedInAverage
adaptUIToCheckboxStatus(holder, exam)
holder.checkBoxUseGradeForAverage.setOnClickListener() {
exam.gradeUsedInAverage = holder.checkBoxUseGradeForAverage.isChecked
adaptUIToCheckboxStatus(holder, exam)
localGradesFragment.storeExamListInSharedPreferences()
notifyDataSetChanged()
}
}

/**
* Enables/disables Edittexts, and adapts the color of the grade bar on the right side
tobiasjungmann marked this conversation as resolved.
Show resolved Hide resolved
*/
private fun adaptUIToCheckboxStatus(
holder: ViewHolder,
exam: Exam
) {
if (exam.gradeUsedInAverage) {
holder.editTextGradeCredits.isEnabled = true
holder.editTextGradeWeights.isEnabled = true
val gradeColor = exam.getGradeColor(context)
holder.gradeTextView.background.setTint(gradeColor)
holder.gradeTextView.setTextColor(ContextCompat.getColor(context, R.color.white))
} else {
holder.editTextGradeCredits.isEnabled = false
holder.editTextGradeWeights.isEnabled = false
holder.gradeTextView.background.setTint(
ContextCompat.getColor(
context,
R.color.transparent
)
)
holder.gradeTextView.setTextColor(
ContextCompat.getColor(
context,
R.color.grade_default
)
)
}
}


override fun generateHeaderName(item: Exam): String {
val headerText = super.generateHeaderName(item)
val year = Integer.parseInt(headerText.substring(0, 2))
Expand All @@ -71,6 +240,16 @@ class ExamListAdapter(context: Context, results: List<Exam>) : SimpleStickyListH
var gradeTextView: TextView = itemView.findViewById(R.id.gradeTextView)
var examDateTextView: TextView = itemView.findViewById(R.id.examDateTextView)
var additionalInfoTextView: TextView = itemView.findViewById(R.id.additionalInfoTextView)

var editTextGradeWeights: EditText = itemView.findViewById(R.id.editTextGradeWeight)
var editTextGradeCredits: EditText = itemView.findViewById(R.id.editTextCreditsOfSubject)
var editGradesContainer: LinearLayout = itemView.findViewById(R.id.editGradesContainer)
var checkBoxUseGradeForAverage: CheckBox =
itemView.findViewById(R.id.checkBoxUseGradeForAverage)
val buttonResetGradeParameters: Button =
itemView.findViewById(R.id.buttonResetGradeParameters)
val gradeTextViewDeleteCustomGrade: ImageView =
itemView.findViewById(R.id.gradeTextViewDeleteCustomGrade)
}

companion object {
Expand Down
Loading