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
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
buildscript {
ext.kotlin_version = '1.2.41'
ext.kotlin_version = '1.3.21'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.1'
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.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
}
}
Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon May 07 20:12:54 CEST 2018
#Thu Feb 28 08:10:16 CET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
91 changes: 82 additions & 9 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'jacoco'

group='com.github.Constructor-io'

jacoco {
toolVersion = '0.8.1'
}

tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}

android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
compileSdkVersion 28

dexOptions {
maxProcessCount 4
Expand All @@ -17,7 +25,7 @@ android {

defaultConfig {
minSdkVersion 19
targetSdkVersion 27
targetSdkVersion 28
testInstrumentationRunner "${applicationId}.runner.RxAndroidJUnitRunner"
versionCode 1
versionName '1.2.0'
Expand Down Expand Up @@ -78,24 +86,89 @@ android {
androidExtensions {
experimental = true
}

libraryVariants.all { variant ->
variant.outputs.each { output ->
def lintTask = tasks["lint${variant.name.capitalize()}"]
output.assemble.dependsOn lintTask
}
}

}

task jacocoUnitTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {

def buildDir = "build/"

def coverageSourceDirs = [
"src/main/java"
]

def excludedClasses = [
'**/databinding/**/*.*',
'**/android/databinding/*Binding.*',
'**/BR.*',
'**/R.*',
'**/R$*.*',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*_MembersInjector.*',
'**/Dagger*Component.*',
'**/Dagger*Component$Builder.*',
'**/*Module_*Factory.*',
'**/*Fragment*.*',
'**/*Activity*.*',
'**/*Adapter*.*',
'**/*ViewPager*.*',
'**/*ViewHolder*.*',
'**/*Module*.*'
]

def javaClasses = fileTree(
dir: "$buildDir/intermediates/classes/debug",
excludes: excludedClasses
)

def kotlinClasses = fileTree(
dir: "$buildDir/tmp/kotlin-classes/debug",
excludes: excludedClasses
)

classDirectories = files([ javaClasses ], [ kotlinClasses ])
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = fileTree(dir: "$buildDir/jacoco", includes: [
"testDebugUnitTest.exec"
])

reports {
xml.enabled = true
html.enabled = true
}
}

task getCoverage(type: Exec, dependsOn: 'jacocoUnitTestReport') {
group = "Reporting"
commandLine "open", "$buildDir/reports/jacoco/jacocoUnitTestReport/html/index.html"
}


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.7.14'
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
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
kapt annotationProcessorLibs
kaptTest daggerCompiler
kaptAndroidTest daggerCompiler
Expand Down
4 changes: 2 additions & 2 deletions library/dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ext {
versions = [
support : "27.1.1",
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
47 changes: 41 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,13 +159,14 @@ object ConstructorIo {
}, {
it.printStackTrace()
errorCallback?.invoke(it)
e("trigger search error: ${it.message}")
e("Search Submit event error: ${it.message}")
}))
}

fun trackConversion(itemName: String, customerId: String, revenue: Double?, searchTerm: String = Constants.QueryConstants.TERM_UNKNOWN, sectionName: String? = null, errorCallback: ConstructorError = null) {
val sessionId = preferenceHelper.getSessionId(sessionIncrementEventHandler)
disposable.add(dataManager.trackConversion(searchTerm, itemName, customerId, "%.2f".format(revenue),
val revenueString = revenue?.let { "%.2f".format(revenue) }
disposable.add(dataManager.trackConversion(searchTerm, itemName, customerId, revenueString,
arrayOf(Constants.QueryConstants.SESSION to sessionId.toString(),
Constants.QueryConstants.AUTOCOMPLETE_SECTION to (sectionName ?: preferenceHelper.defaultItemSection))).subscribeOn(Schedulers.io())
.subscribe({}, { t ->
Expand All @@ -164,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 @@ -176,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 @@ -188,7 +209,21 @@ object ConstructorIo {
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Input focus event error: ${t.message}")
e("Input Focus event error: ${t.message}")
}))
}

fun trackPurchase(clientIds: Array<String>, revenue: Double?, sectionName: String? = null, errorCallback: ConstructorError = null) {
val sessionId = preferenceHelper.getSessionId(sessionIncrementEventHandler)
val sectionNameParam = sectionName ?: preferenceHelper.defaultItemSection
val revenueString = revenue?.let { "%.2f".format(revenue) }
val params = mutableListOf(Constants.QueryConstants.SESSION to sessionId.toString(),
Constants.QueryConstants.AUTOCOMPLETE_SECTION to sectionNameParam)
disposable.add(dataManager.trackPurchase(clientIds.toList(), revenueString, params.toTypedArray()).subscribeOn(Schedulers.io())
.subscribe({}, { t ->
t.printStackTrace()
errorCallback?.invoke(t)
e("Purchase event error: ${t.message}")
}))
}

Expand Down
38 changes: 33 additions & 5 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 All @@ -42,7 +70,7 @@ constructor(private val constructorApi: ConstructorApi) {
}

fun trackSearchResultClick(itemName: String, customerId: String, term: String, params: Array<Pair<String, String>> = arrayOf()): Completable {
return constructorApi.trackSearchResultTerm(term, itemName, customerId, params.toMap())
return constructorApi.trackSearchResultClick(term, itemName, customerId, params.toMap())
}

fun trackSearchResultsLoaded(term: String, resultCount: Int, params: Array<Pair<String, String>>): Completable {
Expand All @@ -53,8 +81,8 @@ constructor(private val constructorApi: ConstructorApi) {
return constructorApi.trackInputFocus(term, params.toMap())
}

fun trackPurchase(params: Array<Pair<String, String>>): Completable {
return constructorApi.trackPurchase(params.toMap())
fun trackPurchase(customerIds: List<String>, revenue: String? = null, params: Array<Pair<String, String>>): Completable {
return constructorApi.trackPurchase(customerIds, revenue, params.toMap())
}

}
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>?)
Loading