Skip to content
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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'org.jacoco:org.jacoco.core:0.8.3'
classpath 'org.jacoco:org.jacoco.core:0.8.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
}
}
Expand Down
8 changes: 4 additions & 4 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ apply plugin: 'jacoco'
group='com.github.Constructor-io'

jacoco {
toolVersion = '0.8.3'
toolVersion = '0.8.1'
}

tasks.withType(Test) {
Expand Down Expand Up @@ -158,12 +158,12 @@ apply from: 'dependencies.gradle'
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.13'
implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0'
testImplementation 'io.mockk:mockk:1.9.kotlin12'
testImplementation 'org.robolectric:robolectric:3.6.1'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.11.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.14.1'
implementation supportLibs
implementation networkLibs
implementation otherLibs
Expand Down
2 changes: 1 addition & 1 deletion library/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ext {
versions = [
support : "28.0.0",
moshi : "1.5.0",
okHttp : "3.9.0",
okHttp : "3.14.1",
retrofit: '2.3.0',
dagger : '2.14.1',
junit : '4.12',
Expand Down
4 changes: 4 additions & 0 deletions library/src/main/java/io/constructor/core/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class Constants {
const val GROUP_DISPLAY_NAME = "group[display_name]"
const val USER_ID = "ui"
const val TERM_UNKNOWN = "TERM_UNKNOWN"
const val PAGE = "page"
const val PER_PAGE = "num_results_per_page"
const val FILTER_GROUP_ID = "filters[group_id]"
const val FILTER_FACET = "filters[%s]"
}

object QueryValues {
Expand Down
32 changes: 26 additions & 6 deletions library/src/main/java/io/constructor/core/ConstructorIo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.constructor.data.local.PreferencesHelper
import io.constructor.data.memory.ConfigMemoryHolder
import io.constructor.data.model.Group
import io.constructor.data.model.Suggestion
import io.constructor.data.model.search.SearchResponse
import io.constructor.injection.component.AppComponent
import io.constructor.injection.component.DaggerAppComponent
import io.constructor.injection.module.AppModule
Expand Down Expand Up @@ -105,6 +106,25 @@ object ConstructorIo {
return dataManager.getAutocompleteResults(query, params.toTypedArray())
}

fun getSearchResults(text: String, vararg facets: Pair<String, List<String>>, page: Int? = null, perPage: Int? = null, groupId: Int? = null): Observable<ConstructorData<SearchResponse>> {
val sessionId = preferenceHelper.getSessionId(sessionIncrementEventHandler)
val encodedParams: ArrayList<Pair<String, String>> = arrayListOf()
groupId?.let { encodedParams.add(Constants.QueryConstants.FILTER_GROUP_ID.urlEncode() to it.toString()) }
page?.let {
encodedParams.add(Constants.QueryConstants.PAGE.urlEncode() to page.toString().urlEncode())
}
perPage?.let {
encodedParams.add(Constants.QueryConstants.PER_PAGE.urlEncode() to perPage.toString().urlEncode())
}
encodedParams.add(Constants.QueryConstants.SESSION.urlEncode() to sessionId.toString().urlEncode())
facets.forEach { facet ->
facet.second.forEach {
encodedParams.add(Constants.QueryConstants.FILTER_FACET.format(facet.first).urlEncode() to it.urlEncode())
}
}
return dataManager.getSearchResults(text, encodedParams = encodedParams.toTypedArray())
}

fun trackAutocompleteSelect(searchTerm: String, originalQuery: String, sectionName: String, group: Group? = null, errorCallback: ConstructorError = null) {
val sessionId = preferenceHelper.getSessionId(sessionIncrementEventHandler)
val encodedParams: ArrayList<Pair<String, String>> = arrayListOf()
Expand All @@ -121,7 +141,7 @@ object ConstructorIo {
}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("trigger select error: ${t.message}") //To change body of created functions use File | Settings | File Templates.
e("Autocomplete Select event error: ${t.message}")
}))
}

Expand All @@ -139,7 +159,7 @@ object ConstructorIo {
}, {
it.printStackTrace()
errorCallback?.invoke(it)
e("trigger search error: ${it.message}")
e("Search Submit event error: ${it.message}")
}))
}

Expand All @@ -165,7 +185,7 @@ object ConstructorIo {
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Search result click event error: ${t.message}")
e("Search Result Click event error: ${t.message}")
}))
}

Expand All @@ -177,7 +197,7 @@ object ConstructorIo {
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Conversion event error: ${t.message}")
e("Search Results Loaded event error: ${t.message}")
}))
}

Expand All @@ -189,7 +209,7 @@ object ConstructorIo {
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Input focus event error: ${t.message}")
e("Input Focus event error: ${t.message}")
}))
}

Expand All @@ -203,7 +223,7 @@ object ConstructorIo {
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Input focus event error: ${t.message}")
e("Purchase event error: ${t.message}")
}))
}

Expand Down
32 changes: 30 additions & 2 deletions library/src/main/java/io/constructor/data/DataManager.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package io.constructor.data

import com.squareup.moshi.Moshi
import io.constructor.BuildConfig
import io.constructor.data.model.Suggestion
import io.constructor.data.model.search.SearchResponse
import io.constructor.data.remote.ApiPaths
import io.constructor.data.remote.ConstructorApi
import io.reactivex.Completable
import io.reactivex.Observable
Expand All @@ -9,9 +13,9 @@ import javax.inject.Singleton

@Singleton
class DataManager @Inject
constructor(private val constructorApi: ConstructorApi) {
constructor(private val constructorApi: ConstructorApi, private val moshi: Moshi) {

fun getAutocompleteResults(text: String, params: Array<Pair<String, String>> = arrayOf()): Observable<ConstructorData<List<Suggestion>?>> = constructorApi.getSuggestions(text, params.toMap()).map {
fun getAutocompleteResults(text: String, params: Array<Pair<String, String>> = arrayOf()): Observable<ConstructorData<List<Suggestion>?>> = constructorApi.getAutocompleteResults(text, params.toMap()).map {
if (!it.isError) {
it.response()?.let {
if (it.isSuccessful) {
Expand All @@ -25,6 +29,30 @@ constructor(private val constructorApi: ConstructorApi) {
}
}.toObservable()

fun getSearchResults(text: String, encodedParams: Array<Pair<String, String>> = arrayOf()): Observable<ConstructorData<SearchResponse>> {
var dynamicUrl = BuildConfig.BASE_API_URL + "/${ApiPaths.URL_SEARCH.format(text)}"
encodedParams.forEachIndexed { index, pair ->
dynamicUrl += "${if (index != 0) "&" else "?" }${pair.first}=${pair.second}"
}
return constructorApi.getSearchResults(dynamicUrl).map { result ->
if (!result.isError) {
result.response()?.let {
if (it.isSuccessful){
val adapter = moshi.adapter(SearchResponse::class.java)
val response = it.body()?.string()
val result = response?.let { adapter.fromJson(it) }
result?.rawData = response
ConstructorData.of(result!!)
} else {
ConstructorData.networkError(it.errorBody()?.string())
}
} ?: ConstructorData.error(result.error())
} else {
ConstructorData.error(result.error())
}
}.toObservable()
}

fun trackAutocompleteSelect(term: String, params: Array<Pair<String, String>> = arrayOf(), encodedParams: Array<Pair<String, String>> = arrayOf()): Completable {
return constructorApi.trackAutocompleteSelect(term, params.toMap(), encodedParams.toMap())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.constructor.data.model.search

data class FacetOption(val count: Int, val value: String?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json

data class Result(@Json(name = "data") val result: ResultData, @Json(name = "matched_terms") val matchedTerms: List<String>?, val value: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json
import io.constructor.data.model.Group

data class ResultData(val description: String?,
val id: String,
@Json(name = "image_url") val imageUrl: String?,
val url: String?,
val facets: List<ResultFacet>?,
val groups: List<Group>?,
var metadata: Map<String, Any>?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.constructor.data.model.search

data class ResultFacet(val name: String, val values: List<FacetOption>?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json


data class SearchData(val facets: List<SearchFacet>?, val groups: List<SearchGroup>?, val results: List<Result>?, @Json(name = "total_num_results") val resultCount: Int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json

data class SearchFacet(val name: String,
@Json(name = "display_name") val displayName: String?,
val status: Map<String, Any>?,
val type: String?,
val min: Int?,
val max: Int?,
val options: List<FacetOption>?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json

data class SearchGroup(@Json(name = "children") val children: List<SearchGroup>?,
@Json(name = "parents") val parents: List<SearchGroup>?,
val count: Int,
@Json(name = "display_name") val displayName: String,
@Json(name = "group_id") val groupId: Long)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.constructor.data.model.search

import com.squareup.moshi.Json

data class SearchResponse(@Json(name = "response") val searchData: SearchData, @Json(name = "result_id") val resultId: String, var rawData: String?)
3 changes: 2 additions & 1 deletion library/src/main/java/io/constructor/data/remote/ApiPaths.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package io.constructor.data.remote

object ApiPaths {
const val URL_GET_SUGGESTIONS = "autocomplete/{value}"
const val URL_AUTOCOMPLETE = "autocomplete/{value}"
const val URL_AUTOCOMPLETE_SELECT_EVENT = "autocomplete/{term}/select"
const val URL_SEARCH_SUBMIT_EVENT = "autocomplete/{term}/search"
const val URL_SESSION_START_EVENT = "behavior"
const val URL_CONVERSION_EVENT = "autocomplete/{term}/conversion"
const val URL_SEARCH_RESULT_CLICK_EVENT = "autocomplete/{term}/click_through"
const val URL_BEHAVIOR = "behavior"
const val URL_PURCHASE = "autocomplete/TERM_UNKNOWN/purchase"
const val URL_SEARCH = "search/%s"

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import io.constructor.core.Constants
import io.constructor.data.model.AutocompleteResult
import io.reactivex.Completable
import io.reactivex.Single
import okhttp3.ResponseBody
import retrofit2.adapter.rxjava2.Result
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
import retrofit2.http.QueryMap
import retrofit2.http.*

interface ConstructorApi {

@GET(ApiPaths.URL_GET_SUGGESTIONS)
fun getSuggestions(@Path("value") value: String, @QueryMap data: Map<String, String>): Single<Result<AutocompleteResult>>
@GET(ApiPaths.URL_AUTOCOMPLETE)
fun getAutocompleteResults(@Path("value") value: String, @QueryMap data: Map<String, String>): Single<Result<AutocompleteResult>>

@GET(ApiPaths.URL_AUTOCOMPLETE_SELECT_EVENT)
fun trackAutocompleteSelect(@Path("term") term: String, @QueryMap data: Map<String, String>, @QueryMap(encoded = true) encodedData: Map<String, String>): Completable
Expand All @@ -40,4 +38,8 @@ interface ConstructorApi {
fun trackPurchase(@Query(Constants.QueryConstants.CUSTOMER_ID) customerIds: List<String>,
@Query("revenue") revenue: String?,
@QueryMap params: Map<String, String>): Completable

@GET
fun getSearchResults(@Url searchUrl: String): Single<Result<ResponseBody>>

}
Loading