Skip to content
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

Mobileapps 1731 #237

Merged
merged 6 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.alfresco.content.DATE_FORMAT_4
import com.alfresco.content.DATE_FORMAT_5
import com.alfresco.content.actions.ActionUpdateNameDescription
import com.alfresco.content.browse.R
import com.alfresco.content.common.isEllipsized
import com.alfresco.content.component.ComponentData
import com.alfresco.content.component.ComponentType
import com.alfresco.content.component.DatePickerBuilder
Expand All @@ -23,7 +24,6 @@ internal fun ProcessDetailFragment.showStartFormView() {
binding.clStatus.isVisible = false
binding.clIdentifier.isVisible = false
binding.clComment.isVisible = false

binding.iconTitleEdit.isVisible = true
binding.iconDueDateEdit.isVisible = true
binding.iconPriorityEdit.isVisible = true
Expand All @@ -40,10 +40,19 @@ internal fun ProcessDetailFragment.setListeners() {
viewModel.execute(ActionUpdateNameDescription(requireNotNull(state.entry)))
}
}
binding.tvTitle.setSafeOnClickListener {
if (binding.tvTitle.isEllipsized())
showTitleDescriptionComponent()
}
binding.tvDueDateValue.setSafeOnClickListener {
formatDateAndShowCalendar()
}
binding.iconDueDateEdit.setSafeOnClickListener {
formatDateAndShowCalendar()
}

binding.iconDueDateClear.setSafeOnClickListener {
viewModel.updateDate(null, true)
}
binding.iconPriorityEdit.setSafeOnClickListener {
withState(viewModel) { state ->
val dataObj = state.entry
Expand All @@ -62,6 +71,19 @@ internal fun ProcessDetailFragment.setListeners() {
}
}
}
binding.iconAssignedEdit.setSafeOnClickListener {
withState(viewModel) { state ->
requireNotNull(state.entry)
viewLifecycleOwner.lifecycleScope.launch {
val result = showSearchUserGroupComponentDialog(
requireContext(), state.entry
)
if (result != null) {
viewModel.updateAssignee(result)
}
}
}
}
}

private fun ProcessDetailFragment.showCalendar(fromDate: String) {
Expand All @@ -85,9 +107,32 @@ private fun ProcessDetailFragment.showCalendar(fromDate: String) {
}
}

internal fun ProcessDetailFragment.updateUI(state: ProcessDetailViewState) {
if (state.entry.formattedDueDate.isNullOrEmpty()) {
binding.iconDueDateClear.isVisible = false
binding.iconDueDateEdit.isVisible = true
} else {
binding.iconDueDateEdit.isVisible = false
binding.iconDueDateClear.isVisible = true
}
}

private fun ProcessDetailFragment.formatDateAndShowCalendar() {
withState(viewModel) { state ->
val parseDate = state.entry.formattedDueDate?.parseDate(DATE_FORMAT_1)
showCalendar(parseDate?.formatDate(DATE_FORMAT_4, parseDate) ?: "")
}
}

internal fun ProcessDetailFragment.showTitleDescriptionComponent() = withState(viewModel) {
viewLifecycleOwner.lifecycleScope.launch {
showComponentSheetDialog(
requireContext(), ComponentData(
name = requireContext().getString(R.string.title_start_workflow),
query = it.entry.name,
value = it.entry.description,
selector = ComponentType.VIEW_TEXT.value
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ import com.alfresco.content.common.updatePriorityView
import com.alfresco.content.component.ComponentBuilder
import com.alfresco.content.component.ComponentData
import com.alfresco.content.component.ComponentMetaData
import com.alfresco.content.component.SearchUserGroupComponentBuilder
import com.alfresco.content.data.AnalyticsManager
import com.alfresco.content.data.PageView
import com.alfresco.content.data.ProcessEntry
import com.alfresco.content.data.UserGroupDetails
import com.alfresco.content.getFormattedDate
import com.alfresco.content.getLocalizedName
import com.alfresco.ui.getDrawableForAttribute
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
Expand Down Expand Up @@ -70,6 +74,7 @@ class ProcessDetailFragment : Fragment(), MavericksView {
override fun invalidate() = withState(viewModel) { state ->
binding.loading.isVisible = false
setData(state)
updateUI(state)
}

private fun setData(state: ProcessDetailViewState) {
Expand All @@ -82,6 +87,13 @@ class ProcessDetailFragment : Fragment(), MavericksView {
binding.tvNoAttachedFilesError.text = getString(R.string.no_attached_files)
binding.completeButton.text = getString(R.string.title_start_workflow)
binding.tvPriorityValue.updatePriorityView(state.entry.priority)
binding.tvAssignedValue.apply {
text = if (dataEntry.startedBy?.groupName?.isEmpty() == true && viewModel.getAPSUser().id == dataEntry.startedBy?.id) {
requireContext().getLocalizedName(dataEntry.startedBy?.let { UserGroupDetails.with(it).name } ?: "")
} else if (dataEntry.startedBy?.groupName?.isNotEmpty() == true)
requireContext().getLocalizedName(dataEntry.startedBy?.groupName ?: "")
else requireContext().getLocalizedName(dataEntry.startedBy?.name ?: "")
}
}

internal suspend fun showComponentSheetDialog(
Expand All @@ -107,4 +119,21 @@ class ProcessDetailFragment : Fragment(), MavericksView {
private fun executeContinuation(continuation: Continuation<ComponentMetaData?>, name: String, query: String) {
continuation.resume(ComponentMetaData(name = name, query = query))
}

internal suspend fun showSearchUserGroupComponentDialog(
context: Context,
processEntry: ProcessEntry
) = withContext(dispatcher) {
suspendCoroutine {

SearchUserGroupComponentBuilder(context, processEntry)
.onApply { userDetails ->
it.resume(userDetails)
}
.onCancel {
it.resume(null)
}
.show()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.alfresco.content.actions.ActionUpdateNameDescription
import com.alfresco.content.component.ComponentMetaData
import com.alfresco.content.data.ProcessEntry
import com.alfresco.content.data.TaskRepository
import com.alfresco.content.data.UserGroupDetails
import com.alfresco.events.on
import kotlinx.coroutines.GlobalScope

Expand Down Expand Up @@ -39,10 +40,20 @@ class ProcessDetailViewModel(
/**
* update the formatted date in the existing ProcessEntry obj and update the UI.
*/
fun updateDate(formattedDate: String?) {
fun updateDate(formattedDate: String?, isClearDueDate: Boolean = false) {
setState {
requireNotNull(this.entry)
copy(entry = ProcessEntry.updateDueDate(this.entry, formattedDate))
copy(entry = ProcessEntry.updateDueDate(this.entry, formattedDate, isClearDueDate))
}
}

/**
* update the assignee in the existing ProcessEntry obj and update the UI.
*/
fun updateAssignee(result: UserGroupDetails) {
setState {
requireNotNull(this.entry)
copy(entry = ProcessEntry.updateAssignee(this.entry, result))
}
}

Expand All @@ -51,6 +62,11 @@ class ProcessDetailViewModel(
*/
fun execute(action: Action) = action.execute(context, GlobalScope)

/**
* returns the current logged in APS user profile data
*/
fun getAPSUser() = repository.getAPSUser()

companion object : MavericksViewModelFactory<ProcessDetailViewModel, ProcessDetailViewState> {

override fun create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class ListViewCommentRow @JvmOverloads constructor(
*/
@ModelProp
fun setData(data: CommentEntry) {
binding.tvName.text = context.getLocalizedName(data.userDetails?.name ?: "")
binding.tvUserInitial.text = context.getLocalizedName(data.userDetails?.nameInitial ?: "")
binding.tvName.text = context.getLocalizedName(data.userGroupDetails?.name ?: "")
binding.tvUserInitial.text = context.getLocalizedName(data.userGroupDetails?.nameInitial ?: "")
binding.tvComment.text = data.message
binding.tvDate.text = if (data.created != null) data.created?.toLocalDate().toString().getFormattedDate(DATE_FORMAT_1, DATE_FORMAT_4) else ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ import com.alfresco.content.common.updatePriorityView
import com.alfresco.content.component.ComponentBuilder
import com.alfresco.content.component.ComponentData
import com.alfresco.content.component.ComponentMetaData
import com.alfresco.content.component.SearchUserComponentBuilder
import com.alfresco.content.component.SearchUserGroupComponentBuilder
import com.alfresco.content.data.AnalyticsManager
import com.alfresco.content.data.CommentEntry
import com.alfresco.content.data.Entry
import com.alfresco.content.data.EventName
import com.alfresco.content.data.PageView
import com.alfresco.content.data.ParentEntry
import com.alfresco.content.data.TaskEntry
import com.alfresco.content.data.UserDetails
import com.alfresco.content.data.UserGroupDetails
import com.alfresco.content.getFormattedDate
import com.alfresco.content.getLocalizedName
import com.alfresco.content.listview.EntryListener
Expand Down Expand Up @@ -226,8 +226,8 @@ class TaskDetailFragment : BaseDetailFragment(), MavericksView, EntryListener {
binding.tvNoOfComments.visibility = View.GONE
}

commentViewBinding.tvUserInitial.text = requireContext().getLocalizedName(commentObj.userDetails?.nameInitial ?: "")
commentViewBinding.tvName.text = requireContext().getLocalizedName(commentObj.userDetails?.name ?: "")
commentViewBinding.tvUserInitial.text = requireContext().getLocalizedName(commentObj.userGroupDetails?.nameInitial ?: "")
commentViewBinding.tvName.text = requireContext().getLocalizedName(commentObj.userGroupDetails?.name ?: "")
commentViewBinding.tvDate.text = if (commentObj.created != null) commentObj.created?.toLocalDate().toString().getFormattedDate(DATE_FORMAT_1, DATE_FORMAT_4) else ""
commentViewBinding.tvComment.text = commentObj.message
} else {
Expand All @@ -252,7 +252,7 @@ class TaskDetailFragment : BaseDetailFragment(), MavericksView, EntryListener {
binding.tvPriorityValue.updatePriorityView(dataObj.priority)
binding.tvAssignedValue.apply {
text = if (viewModel.getAPSUser().id == dataObj.assignee?.id) {
requireContext().getLocalizedName(dataObj.assignee?.let { UserDetails.with(it).name } ?: "")
requireContext().getLocalizedName(dataObj.assignee?.let { UserGroupDetails.with(it).name } ?: "")
} else requireContext().getLocalizedName(dataObj.assignee?.name ?: "")
}
binding.tvIdentifierValue.text = dataObj.id
Expand Down Expand Up @@ -412,7 +412,7 @@ class TaskDetailFragment : BaseDetailFragment(), MavericksView, EntryListener {
) = withContext(dispatcher) {
suspendCoroutine {

SearchUserComponentBuilder(context, taskEntry)
SearchUserGroupComponentBuilder(context, taskEntry)
.onApply { userDetails ->
it.resume(userDetails)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.alfresco.content.data.AnalyticsManager
import com.alfresco.content.data.OfflineRepository
import com.alfresco.content.data.TaskEntry
import com.alfresco.content.data.TaskRepository
import com.alfresco.content.data.UserDetails
import com.alfresco.content.data.UserGroupDetails
import com.alfresco.content.data.payloads.CommentPayload
import com.alfresco.content.getFormattedDate
import com.alfresco.content.listview.EntryListener
Expand Down Expand Up @@ -258,7 +258,7 @@ class TaskDetailViewModel(
/**
* update the assignee in the existing TaskEntry obj and update the UI.
*/
fun updateAssignee(result: UserDetails) {
fun updateAssignee(result: UserGroupDetails) {
setState {
requireNotNull(this.parent)
copy(parent = TaskEntry.updateAssignee(this.parent, result))
Expand Down
16 changes: 16 additions & 0 deletions component/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,20 @@ dependencies {

implementation libs.epoxy.core
kapt libs.epoxy.processor

// Testing
testImplementation "junit:junit:4.13.2"
androidTestImplementation libs.androidx.test.core
androidTestImplementation libs.androidx.test.espresso.core

testImplementation("com.airbnb.android:mavericks-testing:3.0.0")

implementation("com.airbnb.android:mavericks-mocking:3.0.1")

testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")

// Optional -- Mockito framework
testImplementation "org.mockito:mockito-core:5.1.1"
// Optional -- Mockk framework
testImplementation "io.mockk:mockk:1.13.4"
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ComponentViewModel(
stateChipCreate: ComponentState
) : MavericksViewModel<ComponentState>(stateChipCreate) {

private var listOptionsData: MutableList<ComponentMetaData> = mutableListOf()
var listOptionsData: MutableList<ComponentMetaData> = mutableListOf()
private var isFacetComponent: Boolean = false
var onSearchComplete: ((List<ComponentOptions>) -> Unit)? = null
var searchComponentList: List<ComponentOptions> = emptyList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.airbnb.epoxy.CallbackProp
import com.airbnb.epoxy.ModelProp
import com.airbnb.epoxy.ModelView
import com.alfresco.content.component.databinding.ViewListUserRowBinding
import com.alfresco.content.data.UserDetails
import com.alfresco.content.data.UserGroupDetails
import com.alfresco.content.getLocalizedName

@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
Expand All @@ -20,9 +20,9 @@ internal class ListViewUserRow @JvmOverloads constructor(
private val binding = ViewListUserRowBinding.inflate(LayoutInflater.from(context), this)

@ModelProp
fun setData(dataObj: UserDetails) {
fun setData(dataObj: UserGroupDetails) {
binding.tvUserInitial.text = context.getLocalizedName(dataObj.nameInitial)
binding.tvName.text = context.getLocalizedName(dataObj.name ?: "")
binding.tvName.text = dataObj.groupName.ifEmpty { context.getLocalizedName(dataObj.name ?: "") }
}

/**
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import com.airbnb.mvrx.Mavericks
import com.alfresco.content.data.TaskEntry
import com.alfresco.content.data.UserDetails
import com.alfresco.content.data.ParentEntry
import com.alfresco.content.data.UserGroupDetails

internal typealias SearchUserComponentApplyCallback = (UserDetails) -> Unit
internal typealias SearchUserComponentApplyCallback = (UserGroupDetails) -> Unit
internal typealias SearchUserComponentCancelCallback = () -> Unit

/**
* Builder for build the search user component sheet
*/
data class SearchUserComponentBuilder(
data class SearchUserGroupComponentBuilder(
val context: Context,
val taskEntry: TaskEntry,
val parentEntry: ParentEntry,
var onApply: SearchUserComponentApplyCallback? = null,
var onCancel: SearchUserComponentCancelCallback? = null
) {
Expand Down Expand Up @@ -44,10 +44,10 @@ data class SearchUserComponentBuilder(
else -> throw IllegalArgumentException()
}

SearchUserComponentSheet().apply {
arguments = bundleOf(Mavericks.KEY_ARG to taskEntry)
onApply = this@SearchUserComponentBuilder.onApply
onCancel = this@SearchUserComponentBuilder.onCancel
}.show(fragmentManager, SearchUserComponentSheet::class.java.simpleName)
SearchUserGroupComponentSheet().apply {
arguments = bundleOf(Mavericks.KEY_ARG to parentEntry)
onApply = this@SearchUserGroupComponentBuilder.onApply
onCancel = this@SearchUserGroupComponentBuilder.onCancel
}.show(fragmentManager, SearchUserGroupComponentSheet::class.java.simpleName)
}
}
Loading