-
Notifications
You must be signed in to change notification settings - Fork 629
feat : Migrate Datatable to cmp #2382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
...ure/data-table/src/commonMain/kotlin/com/mifos/feature/dataTable/dataTableList/FormWidget.kt
Show resolved
Hide resolved
.../data-table/src/commonMain/kotlin/com/mifos/feature/dataTable/dataTableList/FormWidgetDto.kt
Outdated
Show resolved
Hide resolved
@itsPronay resolve merge conflicts |
@niyajali done |
@HekmatullahAmin @kapmaurya @Aditya3815 Despite repeated requests, why haven't you reviewed the PRs? |
@itsPronay ask one more team member to approve the PR |
@itsPronay i will review it |
feature/data-table/build.gradle.kts
Outdated
alias(libs.plugins.mifos.android.library.compose) | ||
alias(libs.plugins.mifos.android.library.jacoco) | ||
alias(libs.plugins.mifos.cmp.feature) | ||
alias(libs.plugins.mifos.kmp.koin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mifos.kmp.koin
is already added as plugin in CMPFeatureConventionPlugin
and KMPLibraryConventionPlugin
} else { | ||
_dataTableUiState.value = DataTableUiState.ShowDataTables(response) | ||
fun loadDataTable(tableName: String?) { | ||
viewModelScope.launch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Both the
refresh
andloadDataTable
independently call viewModelScope.launch, leading to Redundant coroutine launches. - make the
loadDataTable
suspend and removeviewModelScope.launch
).show() | ||
onBackPressed() | ||
MifosAlertDialog( | ||
dialogTitle = "Success", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a completed action you should use for it snackbar.
When to use which:
Use an AlertDialog only if:
- You want the user to acknowledge something critical.
- There's a decision to be made (Yes/No, Confirm/Cancel).
- It’s a destructive or risky operation before it's confirmed.
Use Snackbar if:
- Users don’t need to confirm a successful deletion just be informed.
- A Snackbar allows the user to continue using the app without interruption.
- Android Material guidelines encourage using snackbars for lightweight feedback.
_dataTableListUiState.value = | ||
DataTableListUiState.ShowMessage(R.string.feature_data_table_loan_creation_success) | ||
viewModelScope.launch { | ||
repository.createLoansAccount(loansPayload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could please look into these types of function these doesn't need to be flowable. They are one shot api calls like creating, deleting, editing .... these need to be taken care of
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
saw your response below, fixing it accordingly
override fun onNext(loans: Loan?) { | ||
_dataTableListUiState.value = | ||
DataTableListUiState.ShowMessage(R.string.feature_data_table_loan_creation_success) | ||
viewModelScope.launch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
Toast.LENGTH_SHORT, | ||
).show() | ||
onSuccess() | ||
MifosAlertDialog( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here use Snackbar instead of AlertDialog
payload: Map<String, String>, | ||
) { | ||
viewModelScope.launch { | ||
addDataTableEntryUseCase.invoke(table, entityId, payload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addDataTableEntry()
is a single network call it doesn't emit multiple values or benefit from reactive chaining.- Using Flow adds boilerplate: mapping to DataState, managing emissions, and collecting with lifecycle scope.
- For one-shot results, suspend functions with try/catch are simpler, faster, and easier to test.
Below is just an example change it accordingly and handle others like this:
class AddDataTableEntryUseCase(
private val repository: DataTableRowDialogRepository,
) {
suspend operator fun invoke(
table: String,
entityId: Int,
payload: Map<String, String>,
): DataState<GenericResponse> {
return try {
val response = repository.addDataTableEntry(table, entityId, payload)
DataState.Success(response)
} catch (e: Exception) {
DataState.Error(e)
}
}
}
fun addDataTableEntry(table: String, entityId: Int, payload: Map<String, String>) {
_dataTableRowDialogUiState.value = DataTableRowDialogUiState.Loading
viewModelScope.launch(Dispatchers.IO) {
val result = addDataTableEntryUseCase(table, entityId, payload)
_dataTableRowDialogUiState.value = when (result) {
is DataState.Success -> DataTableRowDialogUiState.DataTableEntrySuccessfully
is DataState.Error -> DataTableRowDialogUiState.Error(
R.string.feature_data_table_failed_to_add_data_table
)
else -> DataTableRowDialogUiState.Initial
}
}
}
@@ -35,6 +36,9 @@ interface DataTableService { | |||
@Path("entityId") entityId: Int, | |||
): JsonArray | |||
|
|||
@GET("datatables") | |||
fun getDatatables(@Query("apptable") apptable: String? = null): Flow<List<GetDataTablesResponse>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already in core -> network -> apis -> DataTablesApi.kt
is there any reason you created here otherwise delete it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HekmatullahAmin I am getting ResponseConverter error when i use baseApiManager instead of mBaseApiManager & that's why I used mBaseApiManager
instead of baseApiManager
Could not figure out exactly why this is happening. Any idea!?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsPronay I think adding a FlowConverterFactory
in FineractClient.kt
's ktofitBuilder (like we did it in NetworkModule.kt
) might resolve the ResponseConverter error for now:
val ktorfitBuilder = Ktorfit.Builder()
.httpClient(ktorClient)
.baseUrl(baseURL)
.converterFactories(FlowConverterFactory())
.build()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsPronay if you see that error it is completely obvious because the converter class is not added when doing DI.
@biplab1 brother i thought in previous PR's you took care of it and add it why it is missing or you forgot.
if (result.isEmpty()) { | ||
_dataTableUiState.value = DataTableUiState.ShowEmptyDataTables | ||
} else { | ||
_dataTableUiState.value = DataTableUiState.ShowDataTables(result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sometimes when you see a part of code is duplicated have a look if there is a way to avaoid duplication of code:
is DataState.Success -> {
val result = dataState.data
_dataTableUiState.value = if (result.isEmpty()) {
DataTableUiState.ShowEmptyDataTables
} else {
DataTableUiState.ShowDataTables(result)
}
}
} | ||
|
||
fun deleteDataTableEntry(table: String, entity: Int, rowId: Int) = | ||
viewModelScope.launch(Dispatchers.IO) { | ||
viewModelScope.launch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Why deleting a table should be flowable this is wrong properly handle it in
DeleteDataTableEntryUseCase
- also have a look at
GetDataTableInfoUseCase
and fix it accordingly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right now, there are few issues with the domain module as @biplab1 mentioned, there is a separate jira ticket as well for that. we will be working on it after this migration and fixing those issues in domain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsPronay i just looked at the repository in so many use cases although the api call is suspend the change it to flow and then call it as a one time api call these need to be take care of. If there is a seperate ticket no issue.
// fun getIdOfSelectedItem(key: String): Int { | ||
// return spinnerValueIdMap[key]!! | ||
// } | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this block of code is commented out — could you share why it's been left that way? Was it for debugging, future use, or is it safe to remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kept it for future reference since there are so many todos in datatable module. once we take care of todos these will be deleted
@itsPronay when you are done with the rest of changes that need to be made let me know i will approve. |
@HekmatullahAmin done, just left out the domain-related changes since we will be working on that in a separate ticket and fixing those accordingly in all viewmodel |
@itsPronay great, just do one thing for those you commented that needed to be done later like from XML to compose please add a TODO so in our studio we can see what things are in the TODO section. It will be easy to chase. |
@HekmatullahAmin There are no todos from my side since I have already migrated the XML to Compose. The existing todos in the DataTable module were already present before. also I noticed that the old XML code is still there along with those todos, so I kept the old code as well, as we might need it while implementing them |
onCreate = {}, | ||
) | ||
} | ||
|
||
// private fun createForm(table: DataTable?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsPronay by adding TODO
I mean for example this code is commented at above add why and when it will be taken care of.
for ex: this is commented because of X and we will fix it after doing Y
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh.okok. I'll add it. thanks for the clarification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsPronay when i say TODO
you should type it TODO
in capital letter and then it will be higlighted as yellow otherwise it will be the same as the rest of comments.
But no issue next time, have it in your mind.
@niyajali looks good to me |
Fixes - https://mifosforge.jira.com/browse/MIFOSAC-419

Didn't create a Jira ticket, click here to create new.
Please Add Screenshots If there are any UI changes.
Please make sure these boxes are checked before submitting your pull request - thanks!
Run the static analysis check
./gradlew check
orci-prepush.sh
to make sure you didn't break anythingIf you have multiple commits please combine them into one commit by squashing them.