diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt index 223b1af4..0d1960d9 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -11,7 +11,6 @@ import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.filter import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.Filter -import net.pokeranalytics.android.model.realm.ReportSetup import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.util.extensions.startOfDay @@ -35,7 +34,8 @@ class Calculator { query: Query = Query(), filter: Filter? = null, var aggregationType: AggregationType? = null, - var userGenerated: Boolean = false + var userGenerated: Boolean = false, + var reportSetupId: String? = null ) { var evolutionValues: EvolutionValues = evolutionValues @@ -47,17 +47,17 @@ class Calculator { } private var _query: Query = query - private var _filter: Filter? = filter + var filter: Filter? = filter init { - if (!this._query.conditions.isEmpty() && this._filter != null) { + if (!this._query.conditions.isEmpty() && this.filter != null) { throw IllegalStateException("Can't specify a query with conditions AND a filter") } } val query: Query get() { - this._filter?.let { + this.filter?.let { return it.query } return this._query @@ -134,21 +134,21 @@ class Calculator { } } - fun reportSetup(name: String): ReportSetup { - - val rs = ReportSetup() - rs.name = name - rs.display = this.display.ordinal - this.stats.forEach { - rs.statIds.add(it.uniqueIdentifier) - } - this.criterias.forEach { - rs.criteriaIds.add(it.uniqueIdentifier) - } - rs.filter = this._filter - - return rs - } +// fun reportSetup(name: String): ReportSetup { +// +// val rs = ReportSetup() +// rs.name = name +// rs.display = this.display.ordinal +// this.stats.forEach { +// rs.statIds.add(it.uniqueIdentifier) +// } +// this.criterias.forEach { +// rs.criteriaIds.add(it.uniqueIdentifier) +// } +// rs.filter = this.filter +// +// return rs +// } /** * Returns some default name diff --git a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt index 5a556290..8209cd7c 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt @@ -24,7 +24,8 @@ enum class LiveData : Localizable { TRANSACTION, TRANSACTION_TYPE, FILTER, - CUSTOM_FIELD; + CUSTOM_FIELD, + REPORT_SETUP; fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> { val results = realm.where(this.relatedEntity).findAll().sort(fieldName ?: this.sortingFieldName, sortOrder ?: this.sorting) @@ -105,6 +106,7 @@ enum class LiveData : Localizable { TRANSACTION_TYPE -> TransactionType::class.java FILTER -> Filter::class.java CUSTOM_FIELD -> CustomField::class.java + REPORT_SETUP -> ReportSetup::class.java } } @@ -148,6 +150,7 @@ enum class LiveData : Localizable { TRANSACTION_TYPE -> R.string.operation_types FILTER -> R.string.filter CUSTOM_FIELD -> R.string.custom_fields + REPORT_SETUP -> R.string.custom } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt index b63a205c..82b996e8 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.model.realm import android.content.Context +import io.realm.Realm import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.Ignore @@ -8,15 +9,17 @@ import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.Criteria +import net.pokeranalytics.android.model.interfaces.Deletable +import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import java.util.* -open class ReportSetup : RealmObject(), RowRepresentable { +open class ReportSetup : RealmObject(), RowRepresentable, Deletable { @PrimaryKey - var id = UUID.randomUUID().toString() + override var id = UUID.randomUUID().toString() // The name of the report var name: String = "" @@ -60,8 +63,19 @@ open class ReportSetup : RealmObject(), RowRepresentable { stats = stats, criterias = criteria, filter = this.filter, - userGenerated = true + userGenerated = true, + reportSetupId = this.id ) } + // Deletable + + override fun isValidForDelete(realm: Realm): Boolean { + return true + } + + override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonReportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonReportActivity.kt index 8d776327..d99ec3b4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonReportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonReportActivity.kt @@ -1,35 +1,32 @@ package net.pokeranalytics.android.ui.activity -import android.content.Context -import android.content.Intent import android.os.Bundle import net.pokeranalytics.android.R -import net.pokeranalytics.android.calculus.Report -import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.fragment.report.ComparisonReportFragment -class ComparisonReportActivity : PokerAnalyticsActivity() { - - companion object { - - // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects - private var report: Report? = null - private var reportTitle: String = "" - - /** - * Default constructor - */ - fun newInstance(context: Context, report: Report, reportTitle: String) { - //parameters = GraphParameters(stat, group, report) - this.report = report - this.reportTitle = reportTitle - val intent = Intent(context, ComparisonReportActivity::class.java) - context.startActivity(intent) - } - - } +class ComparisonReportActivity : ReportActivity() { + +// companion object { +// +// // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects +// private var report: Report? = null +// private var reportTitle: String = "" +// +// /** +// * Default constructor +// */ +// fun newInstance(context: Context, report: Report, reportTitle: String) { +// //parameters = GraphParameters(stat, group, report) +// this.report = report +// this.reportTitle = reportTitle +// val intent = Intent(context, ComparisonReportActivity::class.java) +// context.startActivity(intent) +// } +// +// } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ProgressReportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ProgressReportActivity.kt index dd61d2fe..edbee7d5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ProgressReportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ProgressReportActivity.kt @@ -3,10 +3,12 @@ package net.pokeranalytics.android.ui.activity import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.fragment.app.Fragment import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.fragment.report.ProgressReportFragment @@ -24,12 +26,19 @@ class ProgressReportActivity : PokerAnalyticsActivity() { * Default constructor */ fun newInstance(context: Context, stat: Stat, report: Report, displayAggregationChoices: Boolean = true, title: String? = null) { - parameters = StatisticsDetailsParameters(stat, report, title) + this.parameters = StatisticsDetailsParameters(stat, report, title) this.displayAggregationChoices = displayAggregationChoices val intent = Intent(context, ProgressReportActivity::class.java) context.startActivity(intent) } + fun newInstanceForResult(fragment: Fragment, stat: Stat, report: Report, displayAggregationChoices: Boolean = true, title: String? = null) { + this.parameters = StatisticsDetailsParameters(stat, report, title) + this.displayAggregationChoices = displayAggregationChoices + val intent = Intent(fragment.context, ProgressReportActivity::class.java) + fragment.startActivityForResult(intent, ReportActivity.DEFAULT_REQUEST_CODE) + } + } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/TableReportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/TableReportActivity.kt index adc357a7..4f0153d0 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/TableReportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/TableReportActivity.kt @@ -1,32 +1,38 @@ package net.pokeranalytics.android.ui.activity -import android.content.Context -import android.content.Intent import android.os.Bundle import net.pokeranalytics.android.R -import net.pokeranalytics.android.calculus.Report -import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.fragment.report.TableReportFragment -class TableReportActivity : PokerAnalyticsActivity() { - - companion object { - - // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects - private var report: Report? = null - private var reportTitle: String = "" - - /** - * Default constructor - */ - fun newInstance(context: Context, report: Report, reportTitle: String) { - this.report = report - this.reportTitle = reportTitle - val intent = Intent(context, TableReportActivity::class.java) - context.startActivity(intent) - } - - } +class TableReportActivity : ReportActivity() { + +// companion object { +// const val DEFAULT_REQUEST_CODE = 1000 +// +// // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects +// private var report: Report? = null +// private var reportTitle: String = "" +// +// /** +// * Default constructor +// */ +// fun newInstance(context: Context, report: Report, reportTitle: String) { +// this.report = report +// this.reportTitle = reportTitle +// val intent = Intent(context, TableReportActivity::class.java) +// context.startActivity(intent) +// } +// +// fun newInstanceForResult(fragment: Fragment, report: Report, reportTitle: String) { +// this.report = report +// this.reportTitle = reportTitle +// +// val intent = Intent(fragment.requireContext(), TableReportActivity::class.java) +// fragment.startActivityForResult(intent, DEFAULT_REQUEST_CODE) +// } +// +// } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/ReportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/ReportActivity.kt new file mode 100644 index 00000000..c2f30e16 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/ReportActivity.kt @@ -0,0 +1,38 @@ +package net.pokeranalytics.android.ui.activity.components + +import android.content.Context +import android.content.Intent +import androidx.fragment.app.Fragment +import net.pokeranalytics.android.calculus.Report + +abstract class ReportActivity : PokerAnalyticsActivity() { + + companion object { + + const val DEFAULT_REQUEST_CODE = 999 + + // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects + var report: Report? = null + var reportTitle: String = "" + + /** + * Default constructor + */ + fun newInstance(context: Context, report: Report, reportTitle: String) { + this.report = report + this.reportTitle = reportTitle + val intent = Intent(context, this::class.java) + context.startActivity(intent) + } + + fun newInstanceForResult(fragment: Fragment, clazz: Class<*>, report: Report, reportTitle: String) { + this.report = report + this.reportTitle = reportTitle + + val intent = Intent(fragment.requireContext(), clazz) + fragment.startActivityForResult(intent, DEFAULT_REQUEST_CODE) + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 6ca073e9..b68674d7 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -85,13 +85,14 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_DETAILS && resultCode == Activity.RESULT_OK) { - val needToDeleteItem = data?.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false) ?: false - if (needToDeleteItem) { + val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) + itemToDeleteId?.let { id -> GlobalScope.launch(Dispatchers.Main) { delay(300) - deleteItem(bankrollAdapter, LiveData.BANKROLL.items(getRealm()), lastItemClickedId) + deleteItem(bankrollAdapter, LiveData.BANKROLL.items(getRealm()), id) } } + } else if (requestCode == REQUEST_CODE_CREATE && resultCode == Activity.RESULT_OK) { //TODO: Refresh bankrolls initData() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt index 4c537216..8e713078 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt @@ -108,14 +108,15 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_DETAILS && resultCode == Activity.RESULT_OK) { - val needToDeleteItem = - data?.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false) ?: false - if (needToDeleteItem) { + + val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) + itemToDeleteId?.let { id -> GlobalScope.launch(Dispatchers.Main) { delay(300) - deleteItem(dataListAdapter, items, lastItemClickedId) + deleteItem(dataListAdapter, LiveData.BANKROLL.items(getRealm()), id) } } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt index 8ad564ff..aa757a5c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt @@ -13,21 +13,21 @@ import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_data_list.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.Criteria +import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.realm.ReportSetup -import net.pokeranalytics.android.ui.activity.ComparisonReportActivity -import net.pokeranalytics.android.ui.activity.ProgressReportActivity -import net.pokeranalytics.android.ui.activity.ReportCreationActivity -import net.pokeranalytics.android.ui.activity.TableReportActivity +import net.pokeranalytics.android.ui.activity.* +import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource -import net.pokeranalytics.android.ui.fragment.components.RealmFragment +import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable @@ -35,7 +35,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.ReportRow import timber.log.Timber import java.util.* -class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { +class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { private lateinit var reportsAdapter: RowRepresentableAdapter private lateinit var reportSetups: RealmResults @@ -77,9 +77,17 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe this.launchReportWithOptions(options, options.getName(requireContext())) } ReportCreationActivity.options = null + } else if (requestCode == ReportActivity.DEFAULT_REQUEST_CODE && resultCode == Activity.RESULT_OK) { + val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) + itemToDeleteId?.let { id -> + GlobalScope.launch(Dispatchers.Main) { + delay(300) + deleteItem(reportsAdapter, LiveData.REPORT_SETUP.items(getRealm()), id) + } + } } - } + } // Business @@ -188,13 +196,16 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe when (options.display) { Calculator.Options.Display.TABLE -> { - TableReportActivity.newInstance(requireContext(), report, reportName) + ReportActivity.newInstanceForResult(this@ReportsFragment, TableReportActivity::class.java, report, reportName) +// TableReportActivity.newInstanceForResult(this@ReportsFragment, report, reportName) +// TableReportActivity.newInstance(requireContext(), report, reportName) } Calculator.Options.Display.PROGRESS -> { - ProgressReportActivity.newInstance(requireContext(), options.stats.first(), report) + ProgressReportActivity.newInstanceForResult(this@ReportsFragment, options.stats.first(), report) } Calculator.Options.Display.COMPARISON -> { - ComparisonReportActivity.newInstance(requireContext(), report, reportName) +// ComparisonReportActivity.newInstance(requireContext(), report, reportName) + ReportActivity.newInstanceForResult(this@ReportsFragment, ComparisonReportActivity::class.java, report, reportName) } else -> { Timber.d("Report type not handled at the moment") diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt index f824b3d1..50bff679 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt @@ -2,8 +2,8 @@ package net.pokeranalytics.android.ui.fragment.components import android.os.Bundle import android.view.View +import android.view.ViewGroup import androidx.appcompat.app.AlertDialog -import androidx.coordinatorlayout.widget.CoordinatorLayout import com.google.android.material.snackbar.Snackbar import io.realm.RealmObject import net.pokeranalytics.android.R @@ -20,12 +20,12 @@ open class DeletableItemFragment : RealmFragment() { private var deletedItem: RealmObject? = null private var lastDeletedItemPosition: Int = 0 private var dataListAdapter: RowRepresentableAdapter? = null - private var coordinatorLayout: CoordinatorLayout? = null + private var mainLayout: ViewGroup? = null private var snackBar: Snackbar? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - this.coordinatorLayout = view.findViewById(R.id.coordinatorLayout) + this.mainLayout = view.findViewById(R.id.mainLayout) } override fun onPause() { @@ -82,7 +82,7 @@ open class DeletableItemFragment : RealmFragment() { */ private fun showUndoSnackBar() { val message = String.format(getString(R.string.data_deleted)) - this.coordinatorLayout?.let { view -> + this.mainLayout?.let { view -> snackBar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE) snackBar?.setAction(R.string.cancel) { getRealm().executeTransaction { realm -> @@ -93,6 +93,8 @@ open class DeletableItemFragment : RealmFragment() { } } snackBar?.show() + } ?: run { + throw IllegalStateException("mainLayout is not defined") } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt index fc1735fe..ee3d7b51 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt @@ -157,11 +157,11 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS /** * Init data */ - private fun initData() { + override fun initData() { defaultCurrency = UserDefaults.currency - if (!isUpdating) { + if (!deleteButtonShouldAppear) { bankroll.currency = net.pokeranalytics.android.model.realm.Currency() bankroll.currency?.code = defaultCurrency.currencyCode bankroll.currency?.rate = 1.0 diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt new file mode 100644 index 00000000..645112b9 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt @@ -0,0 +1,154 @@ +package net.pokeranalytics.android.ui.fragment.data + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import androidx.appcompat.app.AlertDialog +import io.realm.RealmObject +import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.ConfigurationException +import net.pokeranalytics.android.model.LiveData +import net.pokeranalytics.android.model.interfaces.Deletable +import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.SaveValidityStatus +import net.pokeranalytics.android.ui.activity.DataListActivity +import net.pokeranalytics.android.ui.activity.EditableDataActivity +import net.pokeranalytics.android.ui.fragment.components.RealmFragment + +open class DataManagerFragment : RealmFragment() { + + lateinit var item: RealmObject + + lateinit var liveDataType: LiveData + protected var primaryKey: String? = null + + var deleteButtonShouldAppear = false + set(value) { + field = value + this.updateMenuUI() + } + + var saveButtonShouldAppear = true + set(value) { + field = value + this.updateMenuUI() + } + + protected var dataType: Int? = null + + private var editableMenu: Menu? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initData() + } + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() + inflater?.inflate(R.menu.toolbar_editable_data, menu) + this.editableMenu = menu + updateMenuUI() + super.onCreateOptionsMenu(menu, inflater) + } + + /** + * Update menu UI + */ + private fun updateMenuUI() { + editableMenu?.findItem(R.id.delete)?.isVisible = this.deleteButtonShouldAppear + editableMenu?.findItem(R.id.save)?.isVisible = this.saveButtonShouldAppear + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + when (item!!.itemId) { + R.id.save -> saveData() + R.id.delete -> deleteData() + } + return true + } + + /** + * Init data + */ + protected open fun initData() { + + this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey) + + } + + /** + * Save data + */ + protected open fun saveData() { + + val savable = this.item + when (savable) { + is Savable -> { + val status = savable.getSaveValidityStatus(realm = this.getRealm()) + when (status) { + SaveValidityStatus.VALID -> { + this.getRealm().executeTransaction { + val managedItem = it.copyToRealmOrUpdate(this.item) + if (managedItem is Savable) { + val uniqueIdentifier = (managedItem as Savable).id + finishActivityWithResult(uniqueIdentifier) + } + + } + } + else -> { + val message = savable.getFailedSaveMessage(status) + val builder = AlertDialog.Builder(requireContext()) + .setMessage(message) + .setNegativeButton(R.string.ok, null) + builder.show() + } + } + + } else -> { + throw ConfigurationException("Save action called on un-Savable object") + } + } + + } + + /** + * Delete data + */ + protected open fun deleteData() { + + val deletable = this.item as Deletable + val realm = this.getRealm() + + if (deletable.isValidForDelete(realm)) { + val intent = Intent() + intent.putExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, deletable.id) + activity?.setResult(Activity.RESULT_OK, intent) + activity?.finish() + } else { + val status = deletable.getDeleteStatus(realm) + val message = deletable.getFailedDeleteMessage(status) + val builder = AlertDialog.Builder(requireContext()) + .setMessage(message) + .setNegativeButton(R.string.ok, null) + builder.show() + } + } + + /** + * Finish the activity with a result + */ + private fun finishActivityWithResult(uniqueIdentifier: String) { + val intent = Intent() + intent.putExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, dataType) + intent.putExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName, uniqueIdentifier) + activity?.setResult(Activity.RESULT_OK, intent) + activity?.finish() + } + + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt index 5d3d6148..fe285215 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt @@ -1,44 +1,29 @@ package net.pokeranalytics.android.ui.fragment.data -import android.app.Activity.RESULT_OK -import android.content.Intent import android.os.Bundle -import android.view.* -import androidx.appcompat.app.AlertDialog +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import io.realm.RealmObject import kotlinx.android.synthetic.main.fragment_editable_data.* import kotlinx.android.synthetic.main.fragment_editable_data.view.* import net.pokeranalytics.android.R -import net.pokeranalytics.android.exceptions.ConfigurationException import net.pokeranalytics.android.model.LiveData -import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Editable -import net.pokeranalytics.android.model.interfaces.Savable -import net.pokeranalytics.android.model.interfaces.SaveValidityStatus -import net.pokeranalytics.android.ui.activity.DataListActivity -import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate -import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.view.RowRepresentable -open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { +open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegate { lateinit var parentActivity: PokerAnalyticsActivity - lateinit var item: RealmObject - lateinit var liveDataType: LiveData lateinit var rowRepresentableAdapter: RowRepresentableAdapter - private var editableMenu: Menu? = null - private var dataType: Int? = null - private var primaryKey: String? = null - - var isUpdating = false var shouldOpenKeyboard = true override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -49,24 +34,15 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() - initData() - } - - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - menu?.clear() - inflater?.inflate(R.menu.toolbar_editable_data, menu) - this.editableMenu = menu - updateMenuUI() - super.onCreateOptionsMenu(menu, inflater) } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when (item!!.itemId) { - R.id.save -> saveData() - R.id.delete -> deleteData() - } - return true + /** + * Set fragment data + */ + fun setData(dataType: Int, primaryKey: String?) { + this.dataType = dataType + this.liveDataType = LiveData.values()[dataType] + this.primaryKey = primaryKey } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { @@ -90,6 +66,16 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) setHasOptionsMenu(true) + val proxyItem: RealmObject? = this.liveDataType.getData(this.getRealm(), primaryKey) + proxyItem?.let { + //TODO: Localize + this.appBar.toolbar.title = "Update ${this.liveDataType.localizedTitle(requireContext()).toLowerCase().capitalize()}" + deleteButtonShouldAppear = true + } ?: run { + //TODO: Localize + this.appBar.toolbar.title = this.liveDataType.newEntityLocalizedTitle(requireContext()) + } + val viewManager = LinearLayoutManager(requireContext()) recyclerView.apply { @@ -105,121 +91,21 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { return this.item as RowRepresentableDataSource } - /** - * Init data - */ - private fun initData() { - if (this.dataType != null) { - val proxyItem: RealmObject? = this.liveDataType.getData(this.getRealm(), primaryKey) - proxyItem?.let { - //TODO: Localize - this.appBar.toolbar.title = "Update ${this.liveDataType.localizedTitle(this.parentActivity).toLowerCase().capitalize()}" - isUpdating = true - } ?: run { - //TODO: Localize - this.appBar.toolbar.title = this.liveDataType.newEntityLocalizedTitle(requireContext()) - } - this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey) - - val dataSource = getDataSource() - this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this) - this.recyclerView.adapter = rowRepresentableAdapter - - // When creating an object, open automatically the keyboard for the first row - if (!isUpdating && shouldOpenKeyboard) { - val row = dataSource.adapterRows()?.firstOrNull() - row?.let { - onRowSelected(0, it) - } - } - } - } + override fun initData() { + super.initData() - /** - * Update menu UI - */ - private fun updateMenuUI() { - editableMenu?.findItem(R.id.delete)?.isVisible = isUpdating - editableMenu?.findItem(R.id.save)?.isVisible = true - } + val dataSource = getDataSource() + this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this) + this.recyclerView.adapter = rowRepresentableAdapter - /** - * Save data - */ - fun saveData() { - - val savable = this.item - when (savable) { - is Savable -> { - val status = savable.getSaveValidityStatus(realm = this.getRealm()) - when (status) { - SaveValidityStatus.VALID -> { - this.getRealm().executeTransaction { - val managedItem = it.copyToRealmOrUpdate(this.item) - if (managedItem is Savable) { - val uniqueIdentifier = (managedItem as Savable).id - finishActivityWithResult(uniqueIdentifier) - } - - } - } - else -> { - val message = savable.getFailedSaveMessage(status) - val builder = AlertDialog.Builder(requireContext()) - .setMessage(message) - .setNegativeButton(R.string.ok, null) - builder.show() - } - } - - } else -> { - throw ConfigurationException("Save action called on un-Savable object") + // When creating an object, open automatically the keyboard for the first row + if (!deleteButtonShouldAppear && shouldOpenKeyboard) { + val row = dataSource.adapterRows()?.firstOrNull() + row?.let { + onRowSelected(0, it) } } } - /** - * Delete data - */ - private fun deleteData() { - - val deletable = this.item as Deletable - val realm = this.getRealm() - - if (deletable.isValidForDelete(realm)) { - val intent = Intent() - intent.putExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, true) - activity?.setResult(RESULT_OK, intent) - activity?.finish() - } else { - val status = deletable.getDeleteStatus(realm) - val message = deletable.getFailedDeleteMessage(status) - val builder = AlertDialog.Builder(requireContext()) - .setMessage(message) - .setNegativeButton(R.string.ok, null) - builder.show() - } - } - - /** - * Finish the activity with a result - */ - private fun finishActivityWithResult(uniqueIdentifier: String) { - val intent = Intent() - intent.putExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, dataType) - intent.putExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName, uniqueIdentifier) - activity?.setResult(RESULT_OK, intent) - activity?.finish() - } - - /** - * Set fragment data - */ - fun setData(dataType: Int, primaryKey: String?) { - this.dataType = dataType - this.liveDataType = LiveData.values()[dataType] - this.primaryKey = primaryKey - } - } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt index 61679a7c..5622c30e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt @@ -40,7 +40,7 @@ class LocationDataFragment : EditableDataFragment(), StaticRowRepresentableDataS shouldOpenKeyboard = false locationActivated = parentActivity.hasLocationPermissionGranted() - if (isUpdating) { + if (deleteButtonShouldAppear) { // If we update a location, we set the switch to the correct value locationActivated = location.latitude != null && location.longitude != null diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt index ce526f85..024a8aba 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt @@ -1,37 +1,41 @@ package net.pokeranalytics.android.ui.fragment.report import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem import android.view.View +import android.widget.EditText +import androidx.appcompat.app.AlertDialog +import kotlinx.android.synthetic.main.fragment_progress_report.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Report +import net.pokeranalytics.android.model.LiveData +import net.pokeranalytics.android.model.realm.ReportSetup import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity -import net.pokeranalytics.android.ui.fragment.components.RealmFragment +import net.pokeranalytics.android.ui.fragment.data.DataManagerFragment -abstract class AbstractReportFragment : RealmFragment() { +abstract class AbstractReportFragment : DataManagerFragment() { - protected lateinit var selectedReport: Report + private lateinit var _selectedReport: Report + + val selectedReport: Report + get() { + return this._selectedReport + } + + fun setReport(report: Report) { + this._selectedReport = report + this.primaryKey = report.options.reportSetupId + } protected var reportTitle: String? = null - private var editableMenu: Menu? = null protected lateinit var parentActivity: PokerAnalyticsActivity - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - menu?.clear() - inflater?.inflate(R.menu.toolbar_report, menu) - this.editableMenu = menu - updateMenuUI() - super.onCreateOptionsMenu(menu, inflater) - } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when (item!!.itemId) { - R.id.save -> this.saveReportRequest() - } - return true + this.liveDataType = LiveData.REPORT_SETUP + this.saveButtonShouldAppear = this._selectedReport.options.userGenerated + this.deleteButtonShouldAppear = (this.primaryKey != null) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -39,25 +43,57 @@ abstract class AbstractReportFragment : RealmFragment() { parentActivity = activity as PokerAnalyticsActivity } - /** - * Update menu UI - */ - private fun updateMenuUI() { - editableMenu?.findItem(R.id.save)?.let { - it.isVisible = this.selectedReport.options.userGenerated - it.icon.setTint(requireContext().getColor(R.color.white)) - } - } + override fun saveData() { - private fun saveReportRequest() { + activity?.let { + val builder = AlertDialog.Builder(it) + // Get the layout inflater + val inflater = requireActivity().layoutInflater; + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + val view = inflater.inflate(R.layout.dialog_edit_text, null) + val nameEditText = view.findViewById(R.id.reportName) + builder.setView(view) + // Add action buttons + .setPositiveButton(R.string.save) { dialog, id -> + saveReport(nameEditText.text.toString()) + dialog.dismiss() + } + .setNegativeButton(R.string.cancel) { dialog, id -> + dialog.cancel() + } + + val dialog = builder.create() + dialog.show() + + } ?: throw IllegalStateException("Activity cannot be null") } private fun saveReport(name: String) { - getRealm().executeTransaction { - val report = this.selectedReport.options.reportSetup(name) - it.insert(report) + getRealm().executeTransaction { realm -> + + val rs = this.item as ReportSetup + + val options = this._selectedReport.options + rs.name = name + rs.display = options.display.ordinal + options.stats.forEach { + rs.statIds.add(it.uniqueIdentifier) + } + options.criterias.forEach { + rs.criteriaIds.add(it.uniqueIdentifier) + } + rs.filter = options.filter + + this.item = rs + + this.deleteButtonShouldAppear = true + toolbar.title = name + realm.copyToRealmOrUpdate(rs) } + } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt index ab4bc327..c8d85401 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt @@ -18,7 +18,7 @@ class ComparisonReportFragment : AbstractReportFragment() { val fragment = ComparisonReportFragment() fragment.reportTitle = reportTitle report?.let { - fragment.selectedReport = it + fragment.setReport(it) } val bundle = Bundle() fragment.arguments = bundle @@ -27,15 +27,11 @@ class ComparisonReportFragment : AbstractReportFragment() { } } -// private var reports: MutableMap = hashMapOf() -// private var stat: Stat = Stat.NET_RESULT -// private var displayAggregationChoices: Boolean = true - /** * Set data */ fun setData(report: Report) { - this.selectedReport = report + this.setReport(report) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt index 2ac17009..40c3f66b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt @@ -66,7 +66,7 @@ class ProgressReportFragment : AbstractReportFragment() { */ fun setData(stat: Stat, report: Report, displayAggregationChoices: Boolean, title: String? = null) { this.stat = stat - this.selectedReport = report + this.setReport(report) this.displayAggregationChoices = displayAggregationChoices this.reportTitle = title diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt index 1e55c8a4..80eb7595 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt @@ -14,14 +14,11 @@ class TableReportFragment : AbstractReportFragment() { companion object { - /** - * Create new instance - */ fun newInstance(report: Report? = null, title: String? = null): TableReportFragment { val fragment = TableReportFragment() fragment.reportTitle = title report?.let { - fragment.selectedReport = it + fragment.setReport(it) } val bundle = Bundle() fragment.arguments = bundle diff --git a/app/src/main/res/layout/dialog_edit_text.xml b/app/src/main/res/layout/dialog_edit_text.xml new file mode 100644 index 00000000..3c1b82ec --- /dev/null +++ b/app/src/main/res/layout/dialog_edit_text.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_bankroll.xml b/app/src/main/res/layout/fragment_bankroll.xml index 6c8114a4..b4340482 100644 --- a/app/src/main/res/layout/fragment_bankroll.xml +++ b/app/src/main/res/layout/fragment_bankroll.xml @@ -1,7 +1,7 @@ diff --git a/app/src/main/res/layout/fragment_data_list.xml b/app/src/main/res/layout/fragment_data_list.xml index 03650077..034a120d 100644 --- a/app/src/main/res/layout/fragment_data_list.xml +++ b/app/src/main/res/layout/fragment_data_list.xml @@ -2,7 +2,7 @@ diff --git a/app/src/main/res/layout/fragment_reports.xml b/app/src/main/res/layout/fragment_reports.xml index 461dce4c..751d27b1 100644 --- a/app/src/main/res/layout/fragment_reports.xml +++ b/app/src/main/res/layout/fragment_reports.xml @@ -2,7 +2,7 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a66bc65f..294ae6ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,6 +30,7 @@ Select a filter or launch report Launch Report Progress + Save Report Address Naming suggestions diff --git a/build.gradle b/build.gradle index 8a1c4fe4..0340e807 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'io.realm:realm-gradle-plugin:5.8.0' classpath 'com.google.gms:google-services:4.2.0'