Skip to content

Commit

Permalink
Merge pull request #47 from Trendyol/Feature/eventPlatformFilter
Browse files Browse the repository at this point in the history
Develop filter by event platform feature
  • Loading branch information
selimtoksal authored Oct 18, 2024
2 parents aee13f9 + f227940 commit 91fb7d3
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 30 deletions.
3 changes: 2 additions & 1 deletion libraries/analytics-logger/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ android {

ext {
PUBLISH_GROUP_ID = 'com.trendyol.android.devtools'
PUBLISH_VERSION = '0.2.0'
PUBLISH_VERSION = '0.3.0'
PUBLISH_ARTIFACT_ID = 'analytics-logger'
PUBLISH_DESCRIPTION = "Android Analytics Event Logger"
PUBLISH_URL = "https://github.com/Trendyol/android-dev-tools"
Expand All @@ -55,6 +55,7 @@ dependencies {
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
implementation "androidx.constraintlayout:constraintlayout:$constraint_layout_version"
implementation "com.google.android.material:material:$material_version"

implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ import com.trendyol.android.devtools.analyticslogger.internal.data.model.EventEn
@Dao
internal interface EventDao {

@Query("SELECT * FROM event_entities WHERE `key` LIKE :query ORDER BY uid DESC LIMIT :limit OFFSET :offset")
suspend fun find(query: String, limit: Int, offset: Int): List<EventEntity>
@Query("SELECT * FROM event_entities WHERE (`key` LIKE :query OR value LIKE :query) AND platform LIKE :platform ORDER BY uid DESC LIMIT :limit OFFSET :offset")
suspend fun find(query: String, platform: String, limit: Int, offset: Int): List<EventEntity>

@Insert
suspend fun insert(vararg eventEntities: EventEntity)

@Query("DELETE FROM event_entities")
suspend fun deleteAll()

@Query("SELECT DISTINCT platform FROM event_entities")
suspend fun getPlatforms(): List<String>

@Query("SELECT * FROM event_entities WHERE platform LIKE :platform ORDER BY uid DESC LIMIT :limit OFFSET :offset")
suspend fun filterByPlatform(platform: String, limit: Int, offset: Int): List<EventEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import com.trendyol.android.devtools.analyticslogger.internal.data.model.EventEn

internal interface EventRepository {

suspend fun find(query: String, limit: Int, offset: Int): List<EventEntity>
suspend fun find(query: String, platform: String, limit: Int, offset: Int): List<EventEntity>

suspend fun insert(eventEntity: EventEntity)

suspend fun deleteAll()

suspend fun getPlatforms(): List<String>

suspend fun filterByPlatform(platform: String, limit: Int, offset: Int): List<EventEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ internal class EventRepositoryImpl(
private val eventDatabase: EventDatabase,
) : EventRepository {

override suspend fun find(query: String, limit: Int, offset: Int): List<EventEntity> {
return eventDatabase.eventDao().find(query, limit, offset)
override suspend fun find(query: String, platform: String, limit: Int, offset: Int): List<EventEntity> {
return eventDatabase.eventDao().find(query, platform, limit, offset)
}

override suspend fun insert(eventEntity: EventEntity) {
Expand All @@ -18,4 +18,14 @@ internal class EventRepositoryImpl(
override suspend fun deleteAll() {
return eventDatabase.eventDao().deleteAll()
}

override suspend fun getPlatforms(): List<String> {
val platforms = mutableListOf("All")
platforms.addAll(eventDatabase.eventDao().getPlatforms())
return platforms
}

override suspend fun filterByPlatform(platform: String, limit: Int, offset: Int): List<EventEntity> {
return eventDatabase.eventDao().filterByPlatform(platform, limit, offset)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import com.trendyol.android.devtools.analyticslogger.internal.domain.model.Event

internal interface EventManager {

suspend fun find(query: String?, page: Int, pageSize: Int): List<Event>
suspend fun find(query: String?, platform: String, page: Int, pageSize: Int): List<Event>

suspend fun insert(key: String?, value: String?, platform: String?)

suspend fun deleteAll()

suspend fun getPlatforms(): List<String>

suspend fun filterByPlatform(platform: String, page: Int, pageSize: Int): List<Event>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,14 @@ internal class EventManagerImpl(
private val moshi: Moshi,
) : EventManager {

override suspend fun find(query: String?, page: Int, pageSize: Int): List<Event> {
val limit = 20
val offset = (page - 1) * limit

override suspend fun find(query: String?, platform: String, page: Int, pageSize: Int): List<Event> {
val events = eventRepository.find(
query = "%${query.orEmpty()}%",
limit = limit,
offset = offset,
platform = "%${platform}%",
limit = PAGE_LIMIT,
offset = calculateOffset(page),
)
return events.map { eventEntity ->
Event(
uid = eventEntity.uid,
key = eventEntity.key,
value = eventEntity.value,
json = eventEntity.value.beautify(moshi),
platform = eventEntity.platform,
date = eventEntity.date,
)
}
return mapEventData(events)
}

override suspend fun insert(
Expand All @@ -56,4 +45,35 @@ internal class EventManagerImpl(
override suspend fun deleteAll() {
return eventRepository.deleteAll()
}

override suspend fun getPlatforms(): List<String> {
return eventRepository.getPlatforms()
}

override suspend fun filterByPlatform(platform: String, page: Int, pageSize: Int): List<Event> {
val events = eventRepository.filterByPlatform(
platform = platform,
limit = PAGE_LIMIT,
offset = calculateOffset(page)
)
return mapEventData(events)
}

private fun calculateOffset(page: Int) = (page - 1) * PAGE_LIMIT

private fun mapEventData(eventEntities: List<EventEntity>): List<Event> =
eventEntities.map { eventEntity ->
Event(
uid = eventEntity.uid,
key = eventEntity.key,
value = eventEntity.value,
json = eventEntity.value.beautify(moshi),
platform = eventEntity.platform,
date = eventEntity.date,
)
}

companion object {
private const val PAGE_LIMIT = 20
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import com.trendyol.android.devtools.analyticslogger.internal.domain.model.Event
internal class EventPagingSource(
private val eventManager: EventManager,
private val query: String?,
private val platform: String,
) : PagingSource<Int, Event>() {

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Event> {
val nextPage = params.key ?: 1
val response = eventManager.find(
query = query,
platform = platform,
page = nextPage,
pageSize = params.loadSize,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,26 @@ internal class MainViewModel(
private val eventManager: EventManager,
) : ViewModel() {

init {
viewModelScope.launch {
_platformsState.value = eventManager.getPlatforms()
}
}

private val queryState = MutableStateFlow<String?>("")
private val platformState = MutableStateFlow("")

private val _detailState = MutableStateFlow<DetailState>(DetailState.Initial)
val detailState: StateFlow<DetailState> = _detailState

private val _platformsState = MutableStateFlow<List<String>>(emptyList())
val platformsState: StateFlow<List<String>> = _platformsState

val eventsFlow: Flow<PagingData<Event>> = Pager(PagingConfig(pageSize = PAGE_SIZE)) {
EventPagingSource(
eventManager = eventManager,
query = queryState.value,
platform = platformState.value
)
}
.flow
Expand All @@ -37,6 +48,10 @@ internal class MainViewModel(
queryState.value = query.orEmpty()
}

fun setFilterState(platform: String) {
platformState.value = if (platform == "All") "" else platform
}

fun deleteAll() = viewModelScope.launch {
eventManager.deleteAll()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.trendyol.android.devtools.analyticslogger.internal.ui.events

import android.content.res.ColorStateList
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.trendyol.android.devtools.analyticslogger.databinding.AnalyticsLoggerItemEventPlatformBinding
import com.trendyol.android.devtools.analyticslogger.internal.factory.ColorFactory

class EventPlatformAdapter(
): RecyclerView.Adapter<EventPlatformAdapter.EventPlatformViewHolder>() {

private val platforms: MutableList<String> = mutableListOf()
var onItemSelected: ((platform: String) -> Unit)? = null

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventPlatformViewHolder {
return EventPlatformViewHolder(
AnalyticsLoggerItemEventPlatformBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}

override fun onBindViewHolder(holder: EventPlatformViewHolder, position: Int) {
platforms[position].let { holder.bind(it) }
}

override fun getItemCount(): Int {
return platforms.size
}

fun submitData(data: List<String>) {
platforms.addAll(data)
notifyDataSetChanged()
}

inner class EventPlatformViewHolder(
private val binding: AnalyticsLoggerItemEventPlatformBinding
) : RecyclerView.ViewHolder(binding.root) {

fun bind(platform: String) = with(binding) {
chipPlatform.text = platform
chipPlatform.chipBackgroundColor = ColorStateList.valueOf(ColorFactory.getColor(platform))

chipPlatform.setOnClickListener {
onItemSelected?.invoke(platform)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ internal class EventsFragment : Fragment() {

private var eventAdapter: EventAdapter? = null

private lateinit var eventPlatformAdapter: EventPlatformAdapter

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = AnalyticsLoggerFragmentEventsBinding.inflate(inflater, container, false)
return binding.root
Expand All @@ -51,20 +53,38 @@ internal class EventsFragment : Fragment() {
}

private fun initView() {
eventPlatformAdapter = EventPlatformAdapter()
binding.platformsRecyclerView.adapter = eventPlatformAdapter

eventAdapter = EventAdapter()
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
binding.recyclerView.adapter = eventAdapter

eventAdapter?.onItemSelected = { event ->
navigateToEventDetail(event)
}

eventPlatformAdapter.onItemSelected = {
viewModel.setFilterState(it)
eventAdapter?.refresh()
}
}

private fun observeData() {
viewLifecycleOwner.lifecycleScope.launch {
viewModel.eventsFlow.collectLatest {
eventAdapter?.submitData(it)
with(viewLifecycleOwner.lifecycleScope) {

launch {
viewModel.eventsFlow.collectLatest {
eventAdapter?.submitData(it)
}
}

launch {
viewModel.platformsState.collectLatest {
eventPlatformAdapter.submitData(it)
}
}

}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/platformsRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>
</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">

<com.google.android.material.chip.Chip
android:id="@+id/chipPlatform"
app:chipBackgroundColor="@color/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textSize="12sp"
tools:text="Firebase" />

</FrameLayout>
1 change: 1 addition & 0 deletions libraries/analytics-logger/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<color name="colorPrimaryDark">#ffffff</color>
<color name="textColorPrimary">#000000</color>
<color name="textColorSecondary">#000000</color>
<color name="colorAccent">#9b59b6</color>

<color name="analyticGridBackgroundColor">#e3e3e3</color>
</resources>
13 changes: 12 additions & 1 deletion libraries/analytics-logger/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">

<style name="Theme.AnalyticsReporter" parent="Theme.AppCompat.DayNight">
<style name="Theme.AnalyticsReporter" parent="Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">?attr/isLightTheme</item>

<item name="materialButtonStyle">@style/Widget.App.Button</item>
</style>

<style name="Widget.App.Button" parent="Widget.MaterialComponents.Button">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Button</item>
</style>

<style name="ThemeOverlay.App.Button" parent="">
<item name="colorPrimary">@color/colorAccent</item>
<item name="colorOnPrimary">@color/colorPrimary</item>
</style>

</resources>

0 comments on commit 91fb7d3

Please sign in to comment.