Skip to content

Commit 90ef0aa

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

File tree

15 files changed

+272
-10
lines changed

15 files changed

+272
-10
lines changed

app/schemas/org.fossasia.openevent.general.OpenEventDatabase/1.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"formatVersion": 1,
33
"database": {
44
"version": 1,
5-
"identityHash": "0b3cd25764884626e03f56b0600d1c76",
5+
"identityHash": "2eccdc20f2068430bba84bf884a2ec02",
66
"entities": [
77
{
88
"tableName": "Event",
@@ -836,7 +836,7 @@
836836
},
837837
{
838838
"tableName": "Order",
839-
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `paymentMode` TEXT, `country` TEXT, `status` TEXT, `amount` REAL, `identifier` TEXT, `orderNotes` TEXT, `completedAt` TEXT, `city` TEXT, `address` TEXT, `createdAt` TEXT, `zipcode` TEXT, `paidVia` TEXT, `discountCodeId` TEXT, `ticketsPdfUrl` TEXT, `transactionId` TEXT, `event` INTEGER, `attendees` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`event`) REFERENCES `Event`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`attendees`) REFERENCES `Attendee`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
839+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `paymentMode` TEXT, `country` TEXT, `status` TEXT, `amount` REAL, `identifier` TEXT, `orderNotes` TEXT, `completedAt` TEXT, `city` TEXT, `address` TEXT, `createdAt` TEXT, `zipcode` TEXT, `paidVia` TEXT, `discountCodeId` TEXT, `ticketsPdfUrl` TEXT, `transactionId` TEXT, `event` INTEGER, `attendees` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`event`) REFERENCES `Event`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`attendees`) REFERENCES `Attendee`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
840840
"fields": [
841841
{
842842
"fieldPath": "id",
@@ -944,7 +944,7 @@
944944
"fieldPath": "attendees",
945945
"columnName": "attendees",
946946
"affinity": "TEXT",
947-
"notNull": false
947+
"notNull": true
948948
}
949949
],
950950
"primaryKey": {
@@ -1069,9 +1069,10 @@
10691069
]
10701070
}
10711071
],
1072+
"views": [],
10721073
"setupQueries": [
10731074
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
1074-
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"0b3cd25764884626e03f56b0600d1c76\")"
1075+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"2eccdc20f2068430bba84bf884a2ec02\")"
10751076
]
10761077
}
1077-
}
1078+
}

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import org.fossasia.openevent.general.event.EventsListAdapter
4242
import org.fossasia.openevent.general.event.EventsViewModel
4343
import org.fossasia.openevent.general.event.topic.EventTopic
4444
import org.fossasia.openevent.general.event.topic.EventTopicApi
45+
import org.fossasia.openevent.general.event.types.EventType
46+
import org.fossasia.openevent.general.event.types.EventTypesApi
4547
import org.fossasia.openevent.general.event.topic.SimilarEventsViewModel
4648
import org.fossasia.openevent.general.favorite.FavoriteEventsRecyclerAdapter
4749
import org.fossasia.openevent.general.favorite.FavoriteEventsViewModel
@@ -59,6 +61,7 @@ import org.fossasia.openevent.general.search.GeoLocationViewModel
5961
import org.fossasia.openevent.general.search.SearchLocationViewModel
6062
import org.fossasia.openevent.general.search.SearchViewModel
6163
import org.fossasia.openevent.general.search.SmartAuthViewModel
64+
import org.fossasia.openevent.general.search.SearchTypeViewModel
6265
import org.fossasia.openevent.general.search.LocationService
6366
import org.fossasia.openevent.general.search.LocationServiceImpl
6467
import org.fossasia.openevent.general.settings.SettingsViewModel
@@ -119,11 +122,15 @@ val apiModule = module {
119122
val retrofit: Retrofit = get()
120123
retrofit.create(PaypalApi::class.java)
121124
}
125+
single {
126+
val retrofit: Retrofit = get()
127+
retrofit.create(EventTypesApi::class.java)
128+
}
122129

123130
factory { AuthHolder(get()) }
124131
factory { AuthService(get(), get(), get()) }
125132

126-
factory { EventService(get(), get(), get(), get()) }
133+
factory { EventService(get(), get(), get(), get(),get()) }
127134
factory { TicketService(get(), get()) }
128135
factory { SocialLinksService(get(), get()) }
129136
factory { AttendeeService(get(), get(), get()) }
@@ -140,6 +147,7 @@ val viewModelModule = module {
140147
viewModel { SearchViewModel(get(), get(), get(), get()) }
141148
viewModel { AttendeeViewModel(get(), get(), get(), get(), get(), get(), get()) }
142149
viewModel { SearchLocationViewModel(get()) }
150+
viewModel { SearchTypeViewModel(get()) }
143151
viewModel { TicketsViewModel(get(), get(), get(), get()) }
144152
viewModel { AboutEventViewModel(get(), get()) }
145153
viewModel { SocialLinksViewModel(get(), get()) }
@@ -190,7 +198,7 @@ val networkModule = module {
190198
SignUp::class.java, Ticket::class.java, SocialLink::class.java, EventId::class.java,
191199
EventTopic::class.java, Attendee::class.java, TicketId::class.java, Order::class.java,
192200
AttendeeId::class.java, Charge::class.java, Paypal::class.java, ConfirmOrder::class.java,
193-
CustomForm::class.java))
201+
CustomForm::class.java,EventType::class.java))
194202
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
195203
.baseUrl(baseUrl)
196204
.build()

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ import io.reactivex.Single
66
import org.fossasia.openevent.general.event.topic.EventTopic
77
import org.fossasia.openevent.general.event.topic.EventTopicApi
88
import org.fossasia.openevent.general.event.topic.EventTopicsDao
9+
import org.fossasia.openevent.general.event.types.EventType
10+
import org.fossasia.openevent.general.event.types.EventTypesApi
11+
912
import java.util.Locale.filter
1013

1114
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 eventTypesApi: EventTypesApi
1620
) {
1721

1822
fun getEvents(): Flowable<List<Event>> {
@@ -44,6 +48,11 @@ class EventService(
4448
return eventTopicsDao.getAllEventTopics()
4549
}
4650

51+
fun getEventTypes(): Single<List<EventType>> {
52+
return eventTypesApi.getEventTypes()
53+
}
54+
55+
4756
fun getSearchEvents(eventName: String): Single<List<Event>> {
4857
return eventApi.searchEvents("name", eventName).flatMap { apiList ->
4958
var eventIds = apiList.map { it.id }.toList()
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.types
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-type")
10+
@Entity
11+
data class EventType(
12+
@Id(LongIdHandler::class)
13+
@PrimaryKey
14+
val id: Long?,
15+
val name: String?,
16+
val slug: String?
17+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.fossasia.openevent.general.event.types
2+
3+
import io.reactivex.Single
4+
import retrofit2.http.GET
5+
6+
interface EventTypesApi {
7+
8+
@GET("event-types?sort=name")
9+
fun getEventTypes(): Single<List<EventType>>
10+
11+
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.navigation.Navigation.findNavController
1313
import kotlinx.android.synthetic.main.fragment_search.view.fabSearch
1414
import kotlinx.android.synthetic.main.fragment_search.view.locationTextView
1515
import kotlinx.android.synthetic.main.fragment_search.view.timeTextView
16+
import kotlinx.android.synthetic.main.fragment_search.view.eventTypeTextView
1617
import org.fossasia.openevent.general.R
1718
import org.fossasia.openevent.general.utils.nullToEmpty
1819
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -73,6 +74,9 @@ class SearchFragment : Fragment() {
7374
rootView.timeTextView.text = time
7475
}
7576
}
77+
val type = safeArgs?.stringSavedType
78+
if (type.isNullOrBlank()) rootView.eventTypeTextView.text = getString(R.string.anything)
79+
else rootView.eventTypeTextView.text = type
7680

7781
searchViewModel.loadSavedLocation()
7882
rootView.locationTextView.text = searchViewModel.savedLocation
@@ -87,6 +91,16 @@ class SearchFragment : Fragment() {
8791
}
8892
}
8993

94+
rootView.eventTypeTextView.setOnClickListener {
95+
SearchLocationFragmentArgs.Builder()
96+
.setFromSearchFragment(true)
97+
.build()
98+
.toBundle()
99+
.also { bundle ->
100+
Navigation.findNavController(rootView).navigate(R.id.searchTypeFragment, bundle, getAnimSlide())
101+
}
102+
}
103+
90104
return rootView
91105
}
92106

@@ -117,6 +131,7 @@ class SearchFragment : Fragment() {
117131
.setQuery(query)
118132
.setLocation(rootView.locationTextView.text.toString().nullToEmpty())
119133
.setDate((safeArgs?.stringSavedDate ?: getString(R.string.anytime)).nullToEmpty())
134+
.setType((safeArgs?.stringSavedType ?: getString(R.string.anything)).nullToEmpty())
120135
.build()
121136
.toBundle()
122137
.also { bundle ->

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,10 @@ class SearchResultsFragment : Fragment() {
180180
private fun performSearch(args: SearchResultsFragmentArgs, eventDate: String = "") {
181181
val query = args.query
182182
val location = args.location
183+
val type = args.type
183184
val date = if (eventDate.isNotEmpty()) eventDate else args.date
184185
searchViewModel.searchEvent = query
185-
searchViewModel.loadEvents(location, date)
186+
searchViewModel.loadEvents(location, date,type)
186187
}
187188

188189
private fun showNoSearchResults(events: List<Event>) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.fossasia.openevent.general.search
2+
3+
4+
import android.os.Bundle
5+
import android.view.LayoutInflater
6+
import android.view.View
7+
import android.view.ViewGroup
8+
import android.widget.ArrayAdapter
9+
import androidx.appcompat.app.AppCompatActivity
10+
import androidx.fragment.app.Fragment
11+
import androidx.lifecycle.Observer
12+
import androidx.navigation.NavOptions
13+
import androidx.navigation.Navigation
14+
import androidx.navigation.fragment.navArgs
15+
import kotlinx.android.synthetic.main.fragment_search_type.view.eventTypesLv
16+
import org.fossasia.openevent.general.R
17+
import org.fossasia.openevent.general.utils.extensions.nonNull
18+
import org.koin.androidx.viewmodel.ext.android.viewModel
19+
20+
21+
class SearchTypeFragment : Fragment() {
22+
private val searchTypeViewModel by viewModel<SearchTypeViewModel>()
23+
private val safeArgs: SearchTypeFragmentArgs by navArgs()
24+
private lateinit var rootView: View
25+
private val eventTypesList: MutableList<String> = ArrayList()
26+
27+
28+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
29+
savedInstanceState: Bundle?): View? {
30+
// Inflate the layout for this fragment
31+
rootView = inflater.inflate(R.layout.fragment_search_type, container, false)
32+
val thisActivity = activity
33+
if (thisActivity is AppCompatActivity) {
34+
thisActivity.supportActionBar?.title = ""
35+
thisActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
36+
}
37+
setHasOptionsMenu(true)
38+
searchTypeViewModel.loadEventTypes()
39+
val adapter = ArrayAdapter(context, R.layout.event_type_list, eventTypesList)
40+
rootView.eventTypesLv.adapter = adapter
41+
42+
searchTypeViewModel.eventLocations
43+
.nonNull()
44+
.observe(this, Observer { list ->
45+
list.forEach {
46+
eventTypesList.add(it.name ?: "")
47+
}
48+
adapter.notifyDataSetChanged()
49+
})
50+
rootView.eventTypesLv.setOnItemClickListener { parent, view, position, id ->
51+
redirectToSearch(eventTypesList[position])
52+
}
53+
return rootView
54+
}
55+
56+
private fun redirectToSearch(type: String) {
57+
val args = SearchFragmentArgs.Builder().setStringSavedType(type).build().toBundle()
58+
val navOptions = NavOptions.Builder().setPopUpTo(R.id.eventsFragment, false).build()
59+
Navigation.findNavController(rootView).navigate(R.id.searchFragment, args, navOptions)
60+
}
61+
62+
63+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.fossasia.openevent.general.search
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
5+
import androidx.lifecycle.ViewModel
6+
import io.reactivex.android.schedulers.AndroidSchedulers
7+
import io.reactivex.disposables.CompositeDisposable
8+
import io.reactivex.schedulers.Schedulers
9+
import org.fossasia.openevent.general.event.EventService
10+
import org.fossasia.openevent.general.event.types.EventType
11+
import timber.log.Timber
12+
13+
class SearchTypeViewModel(
14+
private val eventService: EventService
15+
) : ViewModel() {
16+
17+
private val compositeDisposable = CompositeDisposable()
18+
private val mutableEventLocations = MutableLiveData<List<EventType>>()
19+
val eventLocations: LiveData<List<EventType>> = mutableEventLocations
20+
21+
22+
fun loadEventTypes() {
23+
compositeDisposable.add(eventService.getEventTypes()
24+
.subscribeOn(Schedulers.io())
25+
.observeOn(AndroidSchedulers.mainThread())
26+
.subscribe({
27+
mutableEventLocations.value = it
28+
}, {
29+
Timber.e(it, "Error fetching events types")
30+
})
31+
)
32+
}
33+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class SearchViewModel(
5252
savedLocation = preference.getString(SAVED_LOCATION)
5353
}
5454

55-
fun loadEvents(location: String, time: String) {
55+
fun loadEvents(location: String, time: String, type: String) {
5656
if (mutableEvents.value != null) {
5757
mutableShowShimmerResults.value = false
5858
mutableShowNoInternetError.value = false
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<CheckedTextView
3+
android:id="@+id/text1"
4+
android:layout_width="match_parent"
5+
android:layout_height="wrap_content"
6+
android:paddingStart="@dimen/layout_margin_large"
7+
android:paddingTop="@dimen/layout_margin_large"
8+
android:paddingBottom="@dimen/layout_margin_large"
9+
android:gravity="center_vertical"
10+
android:text="@string/anytime"
11+
android:background="?attr/selectableItemBackground"
12+
android:textColor="@color/black"
13+
android:textSize="@dimen/text_size_expanded_title"
14+
android:paddingLeft="@dimen/layout_margin_large"
15+
xmlns:android="http://schemas.android.com/apk/res/android" />

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,39 @@
8282
android:layout_gravity="center_horizontal"
8383
android:background="@color/grey" />
8484
</RelativeLayout>
85+
<TextView
86+
android:layout_width="wrap_content"
87+
android:layout_height="wrap_content"
88+
android:layout_marginTop="@dimen/layout_margin_large"
89+
android:text="@string/and_i_m_up_for"
90+
android:textSize="@dimen/text_size_large" />
91+
92+
93+
<RelativeLayout
94+
android:layout_width="wrap_content"
95+
android:layout_height="wrap_content">
96+
97+
<TextView
98+
android:id="@+id/eventTypeTextView"
99+
android:layout_width="wrap_content"
100+
android:layout_height="wrap_content"
101+
android:layout_centerHorizontal="true"
102+
android:text="@string/anything"
103+
android:textColor="@color/black"
104+
android:textSize="@dimen/text_size_expanded_title_large"
105+
tools:text="@string/where" />
106+
107+
<View
108+
android:layout_width="@dimen/layout_margin_none"
109+
android:layout_height="@dimen/event_name_divider_height"
110+
android:layout_alignEnd="@id/eventTypeTextView"
111+
android:layout_alignLeft="@+id/eventTypeTextView"
112+
android:layout_alignRight="@id/eventTypeTextView"
113+
android:layout_alignStart="@+id/eventTypeTextView"
114+
android:layout_below="@id/eventTypeTextView"
115+
android:layout_gravity="center_horizontal"
116+
android:background="@color/grey" />
117+
</RelativeLayout>
85118

86119
</LinearLayout>
87120

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
android:layout_marginLeft="@dimen/layout_margin_large"
7+
android:layout_marginTop="@dimen/layout_margin_large"
8+
android:layout_marginRight="@dimen/layout_margin_large"
9+
android:background="@android:color/white"
10+
android:orientation="vertical"
11+
tools:context="org.fossasia.openevent.general.search.SearchTypeFragment">
12+
13+
<TextView
14+
android:layout_width="wrap_content"
15+
android:layout_height="wrap_content"
16+
android:layout_gravity="center_horizontal"
17+
android:layout_marginBottom="@dimen/layout_margin_extra_large"
18+
android:text="@string/what_type"
19+
android:textColor="@color/black"
20+
android:textSize="@dimen/text_size_extra_large"
21+
android:textStyle="bold" />
22+
23+
<ListView
24+
android:id="@+id/eventTypesLv"
25+
android:layout_width="match_parent"
26+
android:layout_height="wrap_content" />
27+
</LinearLayout>
28+

0 commit comments

Comments
 (0)