Skip to content

Commit be4a014

Browse files
feat: add Event Types for search
1 parent d4e8f8c commit be4a014

File tree

10 files changed

+164
-16
lines changed

10 files changed

+164
-16
lines changed

app/src/main/java/org/fossasia/openevent/general/OpenEventDatabase.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import org.fossasia.openevent.general.auth.UserDao
1313
import org.fossasia.openevent.general.event.Event
1414
import org.fossasia.openevent.general.event.EventDao
1515
import org.fossasia.openevent.general.event.EventIdConverter
16+
import org.fossasia.openevent.general.event.location.EventLocation
17+
import org.fossasia.openevent.general.event.location.EventLocationDao
1618
import org.fossasia.openevent.general.event.topic.EventTopic
1719
import org.fossasia.openevent.general.event.topic.EventTopicIdConverter
1820
import org.fossasia.openevent.general.event.topic.EventTopicsDao
@@ -25,7 +27,7 @@ import org.fossasia.openevent.general.ticket.TicketDao
2527
import org.fossasia.openevent.general.ticket.TicketIdConverter
2628

2729
@Database(entities = [Event::class, User::class, SocialLink::class, Ticket::class, Attendee::class,
28-
EventTopic::class, Order::class, CustomForm::class], version = 1)
30+
EventTopic::class, Order::class, CustomForm::class, EventLocation::class], version = 1)
2931
@TypeConverters(EventIdConverter::class, EventTopicIdConverter::class, TicketIdConverter::class,
3032
AttendeeIdConverter::class, ListAttendeeIdConverter::class)
3133
abstract class OpenEventDatabase : RoomDatabase() {
@@ -42,5 +44,7 @@ abstract class OpenEventDatabase : RoomDatabase() {
4244

4345
abstract fun eventTopicsDao(): EventTopicsDao
4446

47+
abstract fun eventLocationsDao(): EventLocationDao
48+
4549
abstract fun orderDao(): OrderDao
4650
}

app/src/main/java/org/fossasia/openevent/general/di/Modules.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import org.fossasia.openevent.general.common.EventsDiffCallback
4040
import org.fossasia.openevent.general.data.Resource
4141
import org.fossasia.openevent.general.event.EventsListAdapter
4242
import org.fossasia.openevent.general.event.EventsViewModel
43+
import org.fossasia.openevent.general.event.location.EventLocation
44+
import org.fossasia.openevent.general.event.location.EventLocationApi
4345
import org.fossasia.openevent.general.event.topic.EventTopic
4446
import org.fossasia.openevent.general.event.topic.EventTopicApi
4547
import org.fossasia.openevent.general.event.topic.SimilarEventsViewModel
@@ -119,11 +121,15 @@ val apiModule = module {
119121
val retrofit: Retrofit = get()
120122
retrofit.create(PaypalApi::class.java)
121123
}
124+
single {
125+
val retrofit: Retrofit = get()
126+
retrofit.create(EventLocationApi::class.java)
127+
}
122128

123129
factory { AuthHolder(get()) }
124130
factory { AuthService(get(), get(), get()) }
125131

126-
factory { EventService(get(), get(), get(), get()) }
132+
factory { EventService(get(), get(), get(), get(), get(), get()) }
127133
factory { TicketService(get(), get()) }
128134
factory { SocialLinksService(get(), get()) }
129135
factory { AttendeeService(get(), get(), get()) }
@@ -139,7 +145,7 @@ val viewModelModule = module {
139145
viewModel { EventDetailsViewModel(get(), get()) }
140146
viewModel { SearchViewModel(get(), get(), get(), get()) }
141147
viewModel { AttendeeViewModel(get(), get(), get(), get(), get(), get(), get()) }
142-
viewModel { SearchLocationViewModel(get()) }
148+
viewModel { SearchLocationViewModel(get(), get()) }
143149
viewModel { TicketsViewModel(get(), get(), get(), get()) }
144150
viewModel { AboutEventViewModel(get(), get()) }
145151
viewModel { SocialLinksViewModel(get(), get()) }
@@ -190,7 +196,7 @@ val networkModule = module {
190196
SignUp::class.java, Ticket::class.java, SocialLink::class.java, EventId::class.java,
191197
EventTopic::class.java, Attendee::class.java, TicketId::class.java, Order::class.java,
192198
AttendeeId::class.java, Charge::class.java, Paypal::class.java, ConfirmOrder::class.java,
193-
CustomForm::class.java))
199+
CustomForm::class.java, EventLocation::class.java))
194200
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
195201
.baseUrl(baseUrl)
196202
.build()
@@ -240,6 +246,11 @@ val databaseModule = module {
240246
val database: OpenEventDatabase = get()
241247
database.orderDao()
242248
}
249+
250+
factory {
251+
val database: OpenEventDatabase = get()
252+
database.eventLocationsDao()
253+
}
243254
}
244255

245256
val fragmentsModule = module {

app/src/main/java/org/fossasia/openevent/general/event/EventService.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package org.fossasia.openevent.general.event
33
import io.reactivex.Completable
44
import io.reactivex.Flowable
55
import io.reactivex.Single
6+
import org.fossasia.openevent.general.event.location.EventLocation
7+
import org.fossasia.openevent.general.event.location.EventLocationApi
8+
import org.fossasia.openevent.general.event.location.EventLocationDao
69
import org.fossasia.openevent.general.event.topic.EventTopic
710
import org.fossasia.openevent.general.event.topic.EventTopicApi
811
import org.fossasia.openevent.general.event.topic.EventTopicsDao
@@ -12,7 +15,9 @@ class EventService(
1215
private val eventApi: EventApi,
1316
private val eventDao: EventDao,
1417
private val eventTopicApi: EventTopicApi,
15-
private val eventTopicsDao: EventTopicsDao
18+
private val eventTopicsDao: EventTopicsDao,
19+
private val eventLocationApi: EventLocationApi,
20+
private val eventLocationDao: EventLocationDao
1621
) {
1722

1823
fun getEvents(): Flowable<List<Event>> {
@@ -33,6 +38,23 @@ class EventService(
3338
}
3439
}
3540

41+
fun getEventLocations(): Flowable<List<EventLocation>> {
42+
val eventsLocationFlowable = eventLocationDao.getAllEventLocation()
43+
return eventsLocationFlowable.switchMap {
44+
if (it.isNotEmpty())
45+
eventsLocationFlowable
46+
else
47+
eventLocationApi.getEventLocation()
48+
.map {
49+
eventLocationDao.insertEventLocations(it)
50+
}
51+
.toFlowable()
52+
.flatMap {
53+
eventsLocationFlowable
54+
}
55+
}
56+
}
57+
3658
private fun getEventTopicList(eventsList: List<Event>): List<EventTopic?> {
3759
return eventsList
3860
.filter { it.eventTopic != null }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.fossasia.openevent.general.event.location
2+
3+
import androidx.room.Entity
4+
import androidx.room.PrimaryKey
5+
import com.github.jasminb.jsonapi.LongIdHandler
6+
import com.github.jasminb.jsonapi.annotations.Id
7+
import com.github.jasminb.jsonapi.annotations.Type
8+
9+
@Type("event-location")
10+
@Entity
11+
data class EventLocation(
12+
@Id(LongIdHandler::class)
13+
@PrimaryKey
14+
val id: Long?,
15+
val name: String?,
16+
val slug: String?
17+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fossasia.openevent.general.event.location
2+
3+
import io.reactivex.Single
4+
import retrofit2.http.GET
5+
6+
interface EventLocationApi {
7+
8+
@GET("event-locations?sort=name")
9+
fun getEventLocation(): Single<List<EventLocation>>
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.fossasia.openevent.general.event.location
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.OnConflictStrategy
6+
import androidx.room.Query
7+
import io.reactivex.Flowable
8+
9+
@Dao
10+
interface EventLocationDao {
11+
12+
@Insert(onConflict = OnConflictStrategy.REPLACE)
13+
fun insertEventLocations(eventLocation: List<EventLocation?>)
14+
15+
@Query("SELECT * from EventLocation")
16+
fun getAllEventLocation(): Flowable<List<EventLocation>>
17+
18+
@Query("DELETE FROM EventLocation")
19+
fun deleteAll()
20+
}

app/src/main/java/org/fossasia/openevent/general/search/SearchLocationFragment.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.view.LayoutInflater
77
import android.view.MenuItem
88
import android.view.View
99
import android.view.ViewGroup
10+
import android.widget.ArrayAdapter
1011
import androidx.appcompat.widget.SearchView
1112
import androidx.core.content.ContextCompat
1213
import androidx.fragment.app.Fragment
@@ -17,8 +18,10 @@ import com.google.android.material.snackbar.Snackbar
1718
import kotlinx.android.synthetic.main.fragment_search_location.view.currentLocationLinearLayout
1819
import kotlinx.android.synthetic.main.fragment_search_location.view.locationProgressBar
1920
import kotlinx.android.synthetic.main.fragment_search_location.view.locationSearchView
21+
import kotlinx.android.synthetic.main.fragment_search_location.view.eventLocationLv
2022
import org.fossasia.openevent.general.R
2123
import org.fossasia.openevent.general.utils.Utils
24+
import org.fossasia.openevent.general.utils.extensions.nonNull
2225
import org.koin.androidx.viewmodel.ext.android.viewModel
2326
import org.fossasia.openevent.general.utils.Utils.setToolbar
2427

@@ -29,11 +32,28 @@ class SearchLocationFragment : Fragment() {
2932
private val searchLocationViewModel by viewModel<SearchLocationViewModel>()
3033
private val geoLocationViewModel by viewModel<GeoLocationViewModel>()
3134
private val safeArgs: SearchLocationFragmentArgs by navArgs()
35+
private val eventLocationList: MutableList<String> = ArrayList()
3236

3337
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
3438
rootView = inflater.inflate(R.layout.fragment_search_location, container, false)
3539
setToolbar(activity, hasUpEnabled = true, show = true)
3640
setHasOptionsMenu(true)
41+
searchLocationViewModel.loadEventsLocation()
42+
val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, eventLocationList)
43+
rootView.eventLocationLv.adapter = adapter
44+
45+
searchLocationViewModel.eventLocations
46+
.nonNull()
47+
.observe(this, Observer { list ->
48+
list.forEach {
49+
eventLocationList.add(it.name ?: "")
50+
}
51+
adapter.notifyDataSetChanged()
52+
})
53+
rootView.eventLocationLv.setOnItemClickListener { parent, view, position, id ->
54+
searchLocationViewModel.saveSearch(eventLocationList[position])
55+
redirectToMain()
56+
}
3757

3858
geoLocationViewModel.currentLocationVisibility.observe(viewLifecycleOwner, Observer {
3959
rootView.currentLocationLinearLayout.visibility = View.GONE
Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
package org.fossasia.openevent.general.search
22

3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
35
import androidx.lifecycle.ViewModel
6+
import io.reactivex.android.schedulers.AndroidSchedulers
7+
import io.reactivex.disposables.CompositeDisposable
8+
import io.reactivex.schedulers.Schedulers
49
import org.fossasia.openevent.general.data.Preference
10+
import org.fossasia.openevent.general.event.EventService
11+
import org.fossasia.openevent.general.event.location.EventLocation
12+
import timber.log.Timber
513

614
const val SAVED_LOCATION = "LOCATION"
715

8-
class SearchLocationViewModel(private val preference: Preference) : ViewModel() {
16+
class SearchLocationViewModel(
17+
private val eventService: EventService,
18+
private val preference: Preference
19+
) : ViewModel() {
20+
21+
private val compositeDisposable = CompositeDisposable()
22+
private val mutableEventLocations = MutableLiveData<List<EventLocation>>()
23+
val eventLocations: LiveData<List<EventLocation>> = mutableEventLocations
924

1025
fun saveSearch(query: String) {
1126
preference.putString(SAVED_LOCATION, query)
1227
}
28+
29+
fun loadEventsLocation() {
30+
compositeDisposable.add(eventService.getEventLocations()
31+
.subscribeOn(Schedulers.io())
32+
.observeOn(AndroidSchedulers.mainThread())
33+
.subscribe({
34+
mutableEventLocations.value = it
35+
}, {
36+
Timber.e(it, "Error fetching events")
37+
})
38+
)
39+
}
1340
}

app/src/main/res/layout/fragment_search_location.xml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<androidx.constraintlayout.widget.ConstraintLayout
3-
xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
43
xmlns:app="http://schemas.android.com/apk/res-auto"
54
android:layout_width="match_parent"
65
android:layout_height="match_parent"
@@ -17,12 +16,32 @@
1716
android:layout_marginRight="@dimen/layout_margin_medium"
1817
android:inputType="textCapWords"
1918
app:iconifiedByDefault="false"
20-
app:layout_constraintEnd_toEndOf="parent"
21-
app:layout_constraintStart_toStartOf="parent"
22-
app:layout_constraintTop_toTopOf="parent"
2319
app:queryHint="@string/location_hint"
2420
app:searchIcon="@null" />
2521

22+
<TextView
23+
android:id="@+id/titleTv"
24+
android:layout_width="wrap_content"
25+
android:layout_height="wrap_content"
26+
android:layout_marginStart="@dimen/layout_margin_large"
27+
android:layout_marginLeft="@dimen/layout_margin_large"
28+
android:layout_marginTop="@dimen/layout_margin_medium"
29+
android:text="@string/popular_locations"
30+
android:textColor="@android:color/black"
31+
android:textSize="@dimen/heading_text_size" />
32+
33+
<ListView
34+
android:id="@+id/eventLocationLv"
35+
android:layout_width="match_parent"
36+
android:layout_height="wrap_content"
37+
android:layout_marginTop="@dimen/layout_margin_medium"
38+
android:layout_marginBottom="8dp"
39+
android:layout_marginStart="@dimen/layout_margin_large"
40+
android:layout_marginLeft="@dimen/layout_margin_large"
41+
android:layout_marginEnd="@dimen/layout_margin_large"
42+
android:layout_marginRight="@dimen/layout_margin_large" />
43+
44+
2645
<LinearLayout
2746
android:id="@+id/currentLocationLinearLayout"
2847
android:layout_width="wrap_content"
@@ -34,10 +53,7 @@
3453
android:layout_marginBottom="@dimen/layout_margin_extra_large"
3554
android:background="@drawable/round_background"
3655
android:orientation="horizontal"
37-
android:padding="@dimen/padding_medium"
38-
app:layout_constraintBottom_toBottomOf="parent"
39-
app:layout_constraintEnd_toEndOf="parent"
40-
app:layout_constraintStart_toStartOf="parent">
56+
android:padding="@dimen/padding_medium">
4157

4258
<TextView
4359
android:layout_width="wrap_content"
@@ -58,4 +74,4 @@
5874
android:layout_marginLeft="@dimen/layout_margin_large"
5975
android:visibility="gone" />
6076
</LinearLayout>
61-
</androidx.constraintlayout.widget.ConstraintLayout>
77+
</LinearLayout>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,5 +292,6 @@
292292

293293
<!--social link fragment-->
294294
<string name="social_link_check_internet_message">Information is not loaded! Please check your internet connection</string>
295+
<string name="popular_locations">Popular Locations</string>
295296

296297
</resources>

0 commit comments

Comments
 (0)