Skip to content

Commit

Permalink
Merge community with enterprise (#32)
Browse files Browse the repository at this point in the history
* Mobileapps 830 (#30)

* adjusted margins as per figma design

* Mobileapps 832 (#31)

* downloaded config from server, also mimic config json app bundle

* Preview screen enhancement, fixed crash… (#32)

Preview screen changes.

* Mobileapps 835 (#33)

* added drop down for the advance search filters

* Mobileapps 868 (#34)

* fixed string localisation

* fixed localisation default

* Mobileapps 871 (#35)

* fixed retain selected value

* Mobileapps 837 (#36)

* created epoxy recyclerview for advance chips

* added epoxy controller

* inflate categories on the view

* select and unselect chips while changing the filter

* created chip for relative filters

* added text component dialog for chips

* merged community with enterprise

* merged community with enterprise and resolved conflicts
  • Loading branch information
aman-alfresco authored Oct 19, 2021
1 parent ef26410 commit 68976e8
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 77 deletions.
17 changes: 17 additions & 0 deletions data/src/main/kotlin/com/alfresco/content/data/SearchFilters.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,26 @@ enum class SearchFilter {
Libraries;
}

/**
* This class pointing the selected filter chips data.
* @property query
* @property name
*/
data class AdvanceSearchFilter(val query: String, val name: String)

typealias SearchFilters = EnumSet<SearchFilter>

/**
* creating the alias for mutable list of type AdvanceSearchFilter
*/
typealias AdvanceSearchFilters = MutableList<AdvanceSearchFilter>

infix fun SearchFilter.and(other: SearchFilter): SearchFilters = SearchFilters.of(this, other)
infix fun SearchFilters.allOf(other: SearchFilters) = this.containsAll(other)
infix fun SearchFilters.and(other: SearchFilter): SearchFilters = SearchFilters.of(other, *this.toTypedArray())
fun emptyFilters(): SearchFilters = SearchFilters.noneOf(SearchFilter::class.java)

/**
* empty the mutable list of type AdvanceSearchFilter
*/
fun emptyAdvanceFilters(): AdvanceSearchFilters = mutableListOf()
36 changes: 21 additions & 15 deletions data/src/main/kotlin/com/alfresco/content/data/SearchRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,23 @@ class SearchRepository(val session: Session = SessionManager.requireSession) {
skipCount: Int,
maxItems: Int
) = if (filters.contains(SearchFilter.Libraries)) {
ResponsePaging.with(queryService.findSites(
terms,
skipCount,
maxItems
))
} else {
ResponsePaging.with(searchService.simpleSearch(
terms,
if (filters.contains(SearchFilter.Contextual)) nodeId else null,
skipCount,
maxItems,
includeFrom(filters)
))
ResponsePaging.with(
queryService.findSites(
terms,
skipCount,
maxItems
)
)
} else {
ResponsePaging.with(
searchService.simpleSearch(
terms,
if (filters.contains(SearchFilter.Contextual)) nodeId else null,
skipCount,
maxItems,
includeFrom(filters)
)
)
}

private fun includeFrom(filters: SearchFilters) =
Expand All @@ -61,12 +65,14 @@ class SearchRepository(val session: Session = SessionManager.requireSession) {
}

suspend fun getRecents(skipCount: Int, maxItems: Int) =
ResponsePaging.with(searchService.recentFiles(
ResponsePaging.with(
searchService.recentFiles(
SessionManager.requireSession.account.id,
MAX_RECENT_FILES_AGE,
skipCount,
maxItems
))
)
)

/**
* Get AppConfigModel from the internal storage or from assets
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.alfresco.content.search

/**
* This is chip component of various types
*/
enum class ChipComponentType(val component: String) {

TEXT("text"),
CHECK_LIST("check-list"),
SLIDER("slider"),
NUMBER_RANGE("number-range"),
DATE_RANGE("date-range"),
RADIO("radio"),
None("none")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.alfresco.content.search

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.CompoundButton
import android.widget.FrameLayout
import com.airbnb.epoxy.CallbackProp
import com.airbnb.epoxy.ModelProp
import com.airbnb.epoxy.ModelView
import com.alfresco.content.data.SearchFilter
import com.alfresco.content.search.databinding.ViewListFilterChipsBinding
import java.lang.StringBuilder

/**
* Generated Model View for the Advance Filter Chips
*/
@ModelView(autoLayout = ModelView.Size.WRAP_WIDTH_WRAP_HEIGHT)
class ListViewFilterChips @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

private val binding = ViewListFilterChipsBinding.inflate(LayoutInflater.from(context), this)

/**
* Bind the capture item data to the view
*/
@ModelProp
fun setData(dataObj: SearchChipCategory) {
println("ListViewFilterChips.setData ${dataObj.category.name}")
binding.chip.uncheck(false)

binding.chip.text = getChipName(dataObj)

if (dataObj.category.id == SearchFilter.Contextual.toString()) {
binding.chip.isChecked = true
}

binding.chip.isChecked = dataObj.isSelected
}

private fun getChipName(dataObj: SearchChipCategory): StringBuilder {

val nameBuilder = StringBuilder()

val chipTitle: String? = if (dataObj.selectedName.isNotEmpty())
"${dataObj.category.name}: "
else dataObj.category.name

nameBuilder.append(chipTitle)
nameBuilder.append(dataObj.selectedName)

return nameBuilder
}

/**
* set clickListener to the list item
*/
@CallbackProp
fun setCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener?) {
binding.chip.setOnCheckedChangeListener(listener)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.alfresco.content.search

import com.alfresco.content.models.CategoriesItem

/**
* SearchChipCategory type is used for listSearchChips
*/
data class SearchChipCategory(
var category: CategoriesItem,
var isSelected: Boolean,
var selectedName: String = "",
var selectedQuery: String = ""
)
103 changes: 80 additions & 23 deletions search/src/main/kotlin/com/alfresco/content/search/SearchFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.airbnb.epoxy.AsyncEpoxyController
import com.airbnb.mvrx.MavericksView
import com.airbnb.mvrx.withState
import com.alfresco.content.data.SearchFilter
import com.alfresco.content.data.and
import com.alfresco.content.data.emptyFilters
import com.alfresco.content.fragmentViewModelWithArgs
import com.alfresco.content.hideSoftInput
import com.alfresco.content.models.CategoriesItem
import com.alfresco.content.search.databinding.FragmentSearchBinding
import com.alfresco.content.simpleController
import kotlinx.parcelize.Parcelize

@Parcelize
Expand Down Expand Up @@ -54,6 +57,7 @@ class SearchFragment : Fragment(), MavericksView {

private lateinit var searchView: SearchView

private val epoxyController: AsyncEpoxyController by lazy { epoxyController() }
private val recentsFragment by lazy {
childFragmentManager.findFragmentById(R.id.recents_fragment) as RecentSearchFragment
}
Expand All @@ -79,9 +83,9 @@ class SearchFragment : Fragment(), MavericksView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setAdvanceSearchFiltersData()
binding.recyclerViewChips.setController(epoxyController)

setupChips()
setAdvanceSearchFiltersData()

resultsFragment.topLoadingIndicator = view.findViewById(R.id.loading)
recentsFragment.onEntrySelected = { searchView.setQuery(it, false) }
Expand All @@ -91,19 +95,21 @@ class SearchFragment : Fragment(), MavericksView {
withState(viewModel) {
if (viewModel.isShowAdvanceFilterView(it.listSearchFilters)) {
binding.rlDropDownSearch.visibility = View.VISIBLE
binding.chipFolders.visibility = View.GONE
binding.chipGroup.visibility = View.GONE
setupDropDown()
} else {
binding.rlDropDownSearch.visibility = View.GONE
binding.chipFolders.visibility = View.VISIBLE
binding.chipGroup.visibility = View.VISIBLE
setupChips()
}
}
}

override fun invalidate() {
// No-op.
// State is read only once on screen setup.
// This does not include results which are updated in their fragment.
override fun invalidate() = withState(viewModel) { state ->

setSearchFilterLocalizedName(state)

epoxyController.requestModelBuild()
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
Expand Down Expand Up @@ -178,39 +184,55 @@ class SearchFragment : Fragment(), MavericksView {
val items = mutableListOf<String?>()
val searchFilters = viewModel.getSearchFilterList()
searchFilters?.forEach { item ->
items.add(item.name)
item.name?.let { name ->
items.add(getLocalizedName(name))
}
}
val adapter = ArrayAdapter(requireContext(), R.layout.list_search_filter_pop_up, items)
searchFilterPopup.setAdapter(adapter)

withState(viewModel) {
viewModel.getDefaultSearchFilterName(it.listSearchFilters)?.let { name ->
val stringResource = requireContext().resources.getIdentifier(name.lowercase(), "string", requireActivity().packageName)
if (stringResource != 0)
binding.textSearchFilterTitle.text = getString(stringResource)
else
binding.textSearchFilterTitle.text = name
}
withState(viewModel) { state ->
if (state.selectedFilterIndex == -1)
viewModel.copyFilterIndex(viewModel.getDefaultSearchFilterIndex(state.listSearchFilters))
}

searchFilterPopup.setOnItemClickListener { _: AdapterView<*>?, _: View?, position: Int, _: Long ->
setSelectedFilterData(position)
viewModel.copyFilterIndex(position)
viewModel.updateSearchChipCategoryList(position)
setSelectedFilterData()
searchFilterPopup.dismiss()
}

binding.rlDropDownSearch.setOnClickListener { _: View? -> searchFilterPopup.show() }
binding.rlDropDownSearch.setOnClickListener { searchFilterPopup.show() }
}

private fun setSearchFilterLocalizedName(state: SearchResultsState) {
if (state.selectedFilterIndex != -1)
viewModel.getDefaultSearchFilterName(state)?.let { name ->
binding.textSearchFilterTitle.text = getLocalizedName(name)
}
}

private fun setSelectedFilterData(position: Int) {
private fun getLocalizedName(name: String): String {
val stringResource = requireContext().resources.getIdentifier(name.lowercase(), "string", requireActivity().packageName)
return if (stringResource != 0)
getString(stringResource)
else
name
}

private fun setSelectedFilterData() {
withState(viewModel) {
viewModel.getSelectedFilter(position, it)?.let { searchItem ->
binding.textSearchFilterTitle.text = searchItem.name
viewModel.getSelectedFilter(it.selectedFilterIndex, it)?.let { searchItem ->
searchItem.name?.let { name ->
binding.textSearchFilterTitle.text = getLocalizedName(name)
}
}
}
}

private fun setupChips() {
filterContextual = requireView().findViewById(R.id.chip_contextual)
filterContextual = requireView().findViewById(R.id.chip)
filterFiles = requireView().findViewById(R.id.chip_files)
filterFolders = requireView().findViewById(R.id.chip_folders)
filterLibraries = requireView().findViewById(R.id.chip_libraries)
Expand Down Expand Up @@ -260,6 +282,41 @@ class SearchFragment : Fragment(), MavericksView {
}
}

private fun epoxyController() = simpleController(viewModel) { state ->

val filterIndex = state.selectedFilterIndex

if (filterIndex != -1) {
val searchChipCategory = state.listSearchCategoryChips?.toMutableList()
var contextualSearchChipCategory: SearchChipCategory? = null
if (state.filters.contains(SearchFilter.Contextual)) {

contextualSearchChipCategory = SearchChipCategory(
CategoriesItem(
name = getString(R.string.search_chip_contextual, state.contextTitle), expanded = null,
component = null, enabled = null, id = SearchFilter.Contextual.toString()
), true
)
}
if (!searchChipCategory.isNullOrEmpty()) {

contextualSearchChipCategory?.let {
searchChipCategory.add(0, it)
}

searchChipCategory.forEach { model ->
val modelID = filterIndex.toString() + model.category.id
listViewFilterChips {
id(modelID)
data(model)
checkedChangeListener { _, _ ->
}
}
}
}
}
}

private fun applyFilters() {
var filter = emptyFilters()
if (filterContextual.isChecked) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.parentFragmentViewModel
import com.airbnb.mvrx.withState
import com.alfresco.content.HideSoftInputOnScrollListener
import com.alfresco.content.data.AdvanceSearchFilters
import com.alfresco.content.data.Entry
import com.alfresco.content.data.SearchFilters
import com.alfresco.content.listview.ListFragment
Expand Down Expand Up @@ -36,6 +37,14 @@ class SearchResultsFragment : ListFragment<SearchViewModel, SearchResultsState>(
viewModel.setFilters(filters)
}

/**
* set the advance filters on the viewModel
*/
fun setFilters(filters: AdvanceSearchFilters) {
scrollToTop()
viewModel.setFilters(filters)
}

private fun scrollToTop() {
if (isResumed) {
recyclerView.layoutManager?.scrollToPosition(0)
Expand Down
Loading

0 comments on commit 68976e8

Please sign in to comment.