Skip to content

Commit

Permalink
Release/2.1.0 (#82)
Browse files Browse the repository at this point in the history
* Dev/rc adapter (#79)

* remote command factory

* ios + tests

* pr updates (#80)

* pr updates

* fix

* Dev/callback (#81)

* Add a callback to the Tealium initialize method

* kotlin callback

Co-authored-by: christinasund <christina.sund@tealium.com>

Co-authored-by: christinasund <christina.sund@tealium.com>
  • Loading branch information
jameskeith and christinasund authored Apr 27, 2021
1 parent 7d9b883 commit 75994ef
Show file tree
Hide file tree
Showing 19 changed files with 7,539 additions and 51 deletions.
51 changes: 44 additions & 7 deletions example/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
import React, { Component } from 'react';
import { Platform, Button, StyleSheet, Text, TextInput, View, TouchableOpacity, Alert, ScrollView, SafeAreaView } from 'react-native';
import Tealium from 'tealium-react-native';
import { TealiumConfig, TealiumView, TealiumEvent, ConsentCategories, Dispatchers, Collectors, ConsentPolicy, Expiry, ConsentExpiry, TimeUnit, ConsentStatus, TealiumEnvironment } from 'tealium-react-native/common';
import { TealiumConfig, TealiumView, TealiumEvent, ConsentCategories, Dispatchers, Collectors, ConsentPolicy, Expiry, ConsentExpiry, TimeUnit, ConsentStatus, TealiumEnvironment, RemoteCommand } from 'tealium-react-native/common';

export default class App extends Component < {} > {

componentDidMount() {
let config: TealiumConfig = { account: 'tealiummobile', profile: 'demo', environment: TealiumEnvironment.dev, dispatchers: [Dispatchers.Collect, Dispatchers.TagManagement, Dispatchers.RemoteCommands], collectors: [Collectors.AppData, Collectors.DeviceData, Collectors.Lifecycle, Collectors.Connectivity], consentLoggingEnabled: true, consentExpiry: {'time': 10, 'unit': 'minutes' }, consentPolicy: ConsentPolicy.gdpr, batchingEnabled: false, visitorServiceEnabled: true, useRemoteLibrarySettings: false };
Tealium.initialize(config);
let config: TealiumConfig = {
account: 'tealiummobile',
profile: 'demo',
environment: TealiumEnvironment.dev,
dispatchers: [
Dispatchers.Collect,
Dispatchers.TagManagement,
Dispatchers.RemoteCommands
],
collectors: [
Collectors.AppData,
Collectors.DeviceData,
Collectors.Lifecycle,
Collectors.Connectivity
],
consentLoggingEnabled: true,
consentExpiry: {
'time': 10,
'unit': 'days'
},
consentPolicy: ConsentPolicy.gdpr,
batchingEnabled: false,
visitorServiceEnabled: true,
useRemoteLibrarySettings: false,
remoteCommands: [{
id: "hello-world",
callback: (payload) => {
console.log("hello-world: " + JSON.stringify(payload));
}
}]
};
Tealium.initialize(config, success => {
if (!success) {
console.log("Tealium not initialized")
return
}
console.log("Tealium initialized")
Tealium.setConsentStatus(ConsentStatus.consented)
Tealium.addRemoteCommand("hello", payload => {
console.log('hello remote command');
console.log(JSON.stringify(payload));
});
});
Tealium.setVisitorServiceListener(profile => {
console.log("audiences: ");
console.log(JSON.stringify(profile["audiences"]));
Expand Down Expand Up @@ -97,10 +138,6 @@ export default class App extends Component < {} > {
}

addRemoteCommand() {
Tealium.addRemoteCommand('hello', payload => {
console.log('hello remote command');
console.log(JSON.stringify(payload));
});
Tealium.addRemoteCommand('example', payload => {
console.log('example remote command');
console.log(JSON.stringify(payload));
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ PODS:
- React-Core (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- tealium-react-native (2.0.2):
- tealium-react-native (2.1.0):
- React
- tealium-swift/Collect (~> 2.2.2)
- tealium-swift/Core (~> 2.2.2)
Expand Down Expand Up @@ -478,7 +478,7 @@ SPEC CHECKSUMS:
React-RCTText: 5c51df3f08cb9dedc6e790161195d12bac06101c
React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d
ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b
tealium-react-native: f48425fee6daf49803b4c8cc38cfac6943a65b29
tealium-react-native: 0e4250c6f17a8a23ef8115d3599e822c3a7f55d8
tealium-swift: 3fed069f2066953da4b02491f5e9aadd87cc3845
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
7,167 changes: 7,167 additions & 0 deletions example/yarn.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ const val KEY_CONSENT_EXPIRY_UNIT = "unit"
const val KEY_LIFECYCLE_AUTO_TRACKING_ENABLED = "lifecycleAutotrackingEnabled"

const val KEY_VISITOR_SERVICE_ENABLED = "visitorServiceEnabled"

const val KEY_REMOTE_COMMANDS_CONFIG = "remoteCommands"
const val KEY_REMOTE_COMMANDS_ID = "id"
const val KEY_REMOTE_COMMANDS_PATH = "path"
const val KEY_REMOTE_COMMANDS_URL = "url"
const val KEY_REMOTE_COMMANDS_CALLBACK = "callback"
Original file line number Diff line number Diff line change
Expand Up @@ -163,27 +163,27 @@ fun ReadableMap.toTealiumConfig(application: Application): TealiumConfig? {
return config
}

private fun ReadableMap.safeGetString(key: String): String? {
internal fun ReadableMap.safeGetString(key: String): String? {
return if (hasValue(key, ReadableType.String)) getString(key) else null
}

private fun ReadableMap.safeGetBoolean(key: String): Boolean? {
internal fun ReadableMap.safeGetBoolean(key: String): Boolean? {
return if (hasValue(key, ReadableType.Boolean)) getBoolean(key) else null
}

private fun ReadableMap.safeGetInt(key: String): Int? {
internal fun ReadableMap.safeGetInt(key: String): Int? {
return if (hasValue(key, ReadableType.Number)) getInt(key) else null
}

private fun ReadableMap.safeGetDouble(key: String): Double? {
internal fun ReadableMap.safeGetDouble(key: String): Double? {
return if (hasValue(key, ReadableType.Number)) getDouble(key) else null
}

private fun ReadableMap.safeGetArray(key: String): ReadableArray? {
internal fun ReadableMap.safeGetArray(key: String): ReadableArray? {
return if (hasValue(key, ReadableType.Array)) getArray(key) else null
}

private fun ReadableMap.safeGetMap(key: String): ReadableMap? {
internal fun ReadableMap.safeGetMap(key: String): ReadableMap? {
return if (hasValue(key, ReadableType.Map)) getMap(key) else null
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.tealium.react

import com.tealium.remotecommands.RemoteCommand

interface RemoteCommandFactory {
val name: String
fun create(): RemoteCommand
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import android.util.Log
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.*
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
import com.tealium.core.*
import com.tealium.core.consent.*
import com.tealium.react.BuildConfig.TAG
import com.tealium.remotecommanddispatcher.remoteCommands
import com.tealium.remotecommands.RemoteCommand
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
Expand All @@ -26,22 +28,37 @@ class TealiumReactNative : ReactPackage {
}
}

@ReactModule(name = MODULE_NAME)
class TealiumReact(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

override fun getName(): String = MODULE_NAME
private var tealium: Tealium? = null
private val remoteCommandFactories: MutableMap<String, RemoteCommandFactory> = mutableMapOf()

fun registerRemoteCommandFactory(factory: RemoteCommandFactory) {
if (remoteCommandFactories.containsKey(factory.name)) {
Logger.qa(TAG, "RemoteCammand for name ${factory.name} already registered; overwriting.")
}
remoteCommandFactories[factory.name] = factory
}

@ReactMethod
fun initialize(configMap: ReadableMap) {
fun initialize(configMap: ReadableMap, callback: Callback?) {
getApplication()?.let { app ->
configMap.toTealiumConfig(app)?.let { config ->
tealium = Tealium.create(INSTANCE_NAME, config) {
Log.d(TAG, "Instance Initialized: ${this.key}")
events.subscribe(EmitterListeners(reactContext))

configMap.safeGetArray(KEY_REMOTE_COMMANDS_CONFIG)?.let {
createRemoteCommands(it)
}
callback?.invoke(true)
}
}
} ?: run {
Log.w(TAG, "Failed to initialize instance.")
callback?.invoke(false)
}
}

Expand All @@ -61,6 +78,28 @@ class TealiumReact(private val reactContext: ReactApplicationContext) : ReactCon
return app
}

private fun createRemoteCommands(commands: ReadableArray) {
for (i in 0 until commands.size()) {
val cmd = commands.getMap(i)
if (cmd is ReadableMap) {
val id = cmd.safeGetString(KEY_REMOTE_COMMANDS_ID)
if (id != null) {
val path = cmd.safeGetString(KEY_REMOTE_COMMANDS_PATH)
val url = cmd.safeGetString(KEY_REMOTE_COMMANDS_URL)
val command: RemoteCommand? = if (cmd.hasKey(KEY_REMOTE_COMMANDS_CALLBACK)) {
RemoteCommandListener(reactContext, id)
} else {
remoteCommandFactories[id]?.create()
}

if (command != null) {
tealium?.remoteCommands?.add(command, path, url)
}
}
}
}
}

@ReactMethod
fun terminateInstance() {
Tealium.destroy(INSTANCE_NAME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,27 +217,29 @@ class ExtensionsTests {

@Test
fun dispatchFromMap_Payload() {
val mockMap: ReadableMap = mockk(relaxed = true)
every { mockMap.getMap("dataLayer") } returns mockMap
every { mockMap.toHashMap() } returns hashMapOf("key" to "value")
val map: WritableMap = JavaOnlyMap()
map.putString(KEY_TRACK_EVENT_TYPE, "event")
map.putString(KEY_TRACK_EVENT_NAME, "test-event")

every { mockMap.getString(KEY_TRACK_EVENT_TYPE) } returns "event"
every { mockMap.getString(KEY_TRACK_EVENT_NAME) } returns "test-event"
val event = dispatchFromMap(mockMap) as TealiumEvent
val dataLayer: WritableMap = JavaOnlyMap()
dataLayer.putString("key", "value")
map.putMap(KEY_TRACK_DATALAYER, dataLayer)

val event = dispatchFromMap(map) as TealiumEvent
assertEquals("test-event", event.eventName)
assertEquals("value", event.payload()["key"])

every { mockMap.getString(KEY_TRACK_EVENT_TYPE) } returns "view"
every { mockMap.getString(KEY_TRACK_VIEW_NAME) } returns "test-view"
val view = dispatchFromMap(mockMap) as TealiumView
map.putString(KEY_TRACK_EVENT_TYPE, "view")
map.putString(KEY_TRACK_VIEW_NAME, "test-view")
val view = dispatchFromMap(map) as TealiumView
assertEquals("test-view", view.viewName)
assertEquals("value", view.payload()["key"])

// Defaults
every { mockMap.getString(KEY_TRACK_EVENT_TYPE) } returns "something-else"
every { mockMap.getString(KEY_TRACK_EVENT_NAME) } returns null
every { mockMap.getMap(KEY_TRACK_DATALAYER) } returns null
val default = dispatchFromMap(mockMap) as TealiumEvent
map.putString(KEY_TRACK_EVENT_TYPE, "something-else")
map.putString(KEY_TRACK_EVENT_NAME, null)
map.putMap(KEY_TRACK_DATALAYER, null)
val default = dispatchFromMap(map) as TealiumEvent
assertEquals(DispatchType.EVENT, default.eventName)
assertFalse(default.payload().containsKey("key"))
}
Expand Down
Loading

0 comments on commit 75994ef

Please sign in to comment.