En este tutorial veremos como crear una aplicación que mostrará todos los eventos registrados en la red social Eventbrite cercanos a nuestra ubicación actual, utilizando la API de EventBrite. Para esto mostraremos como crear una aplicación, con sus experiencias, modelos, layouts y su lógica; asi como también veremos cómo autenticarnos usando el servicio broker.oauth.authenticate() y cómo importar una librería (la cual también ha sido creada en Mat|r) que contiene dos servicios que proporciona la API de EventBrite para obtener datos del perfil de usuario y de eventos cercanos.

Contenido

Obtención de apikey y apisecret para Eventbrite API

Para poder comunicarse con la API de eventos de Eventbrite, primero necesitarás crear una app eventbrite siguiendo los siguientes pasos:

  1. Registrarse en la red social de eventos www.eventbrite.com e iniciar sesión.
  2. Acceder al menu ‘Account Settings’
  3. Acceder al menu ‘Developer > App Management’
  4. Presionar botón ‘CREATE NEW APP’
  5. Completar la información de contacto y los detalles de la información de tu aplicación.  El campo redirect URI se utiliza en el protocolo como re-dirección de la vista web de Eventbrite luego del login exitoso. Aquí debes ingresar un sitio web accesible para completar en los campos de URL y URI (sin importar si la URI existe). Si no cuentas con un sitio web propio simplemente puedes ingresar el de matr, por ejemplo: (http://matrproject.com/ y http://matrproject.com/redirect_oauth). De todos modos, puedes volver a editar esta información en cualquier momento.
  6. Aceptar términos y condiciones, presionar ‘CREATE APP’ , y eso es todo!

Ahora puede visualizar en tu lista de aplicaciones los campos que necesitas para el proceso de OAuth. Cópiate y guarda los valores de los campos ‘client key’ y ‘client secret’ (recuadrados de la siguiente imagen), junto con la ‘OAuth Redirect URI’ ingresada en el paso 5, estos serán necesarios para iniciar el proceso y tendrás que agregarlos en tu código en la LoginExperience.ms.

Creación de proyecto y de aplicación

Si todavía no cuentas con ningún proyecto, puedes acceder a la sección Projects y crear un nuevo proyecto presionando el botón con el signo ‘+’ y completando los datos como se observa en la siguientes imagenes:

Luego creamos una nueva aplicación presionando el botón con el signo ‘+’ y completamos los datos como se observa a continuación:

Estructura de la aplicación

Una vez creada nuestra aplicación, procedemos a darle forma. La misma estará compuesta de 3 archivos:

  • main.ms: en donde se definirán variables globales, constantes, modelos, librerías importadas y la lógica de inicio de la aplicación.
  • LoginExperience.ms: aquí crearemos un experiencia para la autenticación del usuario.
  • EventsExperience.ms: el archivo que contendrá la experiencia que será responsable de la carga y visualización de los eventos.

Para crear los archivos, procedemos a hacer click en el icono ‘+’ ubicado en la barra de tareas por debajo de los diferentes tabs que posee nuestro IDE. A continuación podemos observar los archivos creados:

Observa que el archivo main.ms ya fue creado por defecto, te aconsejamos borrar su contenido y editarlo como explica la siguiente sección del tutorial.

Lógica de inicio de aplicación: main.ms

En nuestro primer archivo llamado main.ms, realizamos lo siguiente:

  • Crearemos un Modelo llamado User, el cual contendrá toda la información del usuario logueado.
 Model User {
    String name
    String email
    String eventbriteId
}
  • Definiremos todas las variables globales que usaremos en la aplicación, dentro del bloque Aplication.
 Application {

    //Constants
    String ebUserTokenKey    
    String loggedUserNameKey
    String loggedUserEventbriteIDKey
    
    //Global App Models
    User loggedUser
    String token
  • Inicializamos las variables dentro del bloque OnInit, el cuál es el primer bloque de código que se ejecutará al cargar la aplicación. Observar que las primeras 2 variables serán utilizadas como claves de los métodos de persistencia.
    OnInit {    
        ebUserTokenKey = "ebUserTokenKey"
        loggedUserNameKey  = "loggedUserNameKey"
        loggedUserEventbriteIDKey  = "loggedUserEventbriteIDKey"
  • Dentro del mismo bloque, escribiremos toda la lógica de inicio de la aplicación. Aquí haremos uso de los servicios de acceso y control del gps y activaremos el GPS del dispositivo:
   
    try {
        if (broker.location.hasGPS()) {
            broker.location.start()
        }
    } catch (e) {
       //handle exception e.reason()
    }

Luego, utilizando las funciones de acceso al almacenamiento local del dispositivo consultamos si el usuario ya se encuentra logueado (de una sesión anterior). En caso afirmativo, recuperamos el usuario logueado y lo asignamos en la variable loggedUser; hacemos algo similar con la variable token recuperando el valor por medio del almacenamiento local encriptado, sentencia broker.localKeychain.get(); y por ultimos mostramos la experiencia EventsExperience que mostrará la lista de eventos, por medio de la sentencia de navegacion broker.ui.push().
En caso contrario, mostramos la experiencia de login: LoginExperience.

    
        if (broker.localPersistence.hasKey(loggedUserNameKey)) {  
            //already logged user      
            loggedUser = User(name: broker.localPersistence.get(loggedUserNameKey), eventbriteId: broker.localPersistence.get(loggedUserEventbriteIDKey) )
            token = broker.localKeychain.get(ebUserTokenKey)            
            broker.ui.push("EventsExperience")
        } else {
            //must show login 
            broker.ui.push("LoginExperience")
        }
  • Importamos la librería EventBriteLibrary que contiene los servicios que se comunican con la API de Eventbrite, de donde la aplicación consultará los datos de los eventos a mostrar. Librerias como esta y muchas otras podrás encontrar en el mat|r hub e importarlas para acelerar tu desarrollo. La guia completa para crear e importar librerias puedes verla aqui.
    La expresión para importar la librería es la siguiente, y debes agregarla al inicio del archivo main.ms:
    Import EventBriteLibrary as EventBriteLib

Una vez hecho esto, podremos observar todos los modelos y servicios importados. En nuestro ejemplo utilizaremos dos servicios: uno para obtener los datos del usuario logueado, llamado eb_getProfile; y otro para obtener los eventos cercanos llamado eb_getEventsByLocation.

Si colocamos el puntero sobre el nombre de cada servicio, podemos observar los parámetros necesarios para poder hacer uso de ese servicio, como se muestra a continuación:

El código completo de nuestro archivo main.ms puedes visualizarlo aqui.

Experiencia de login LoginExperience.ms

En este archivo, vamos a definir:

  • Una experiencia llamada LoginExperience que contendrá un botón, y que al presionar el mismo ejecutará una regla llamada ruleSingInEventbrite, para esto agregamos una Experience y un Decision, de la siguiente forma:
Experience LoginExperience {
    Decision ruleSingInEventbrite action("LoginContext.ruleSingInEventbrite") label("Signin with Eventbrite")
}

  • Luego definiremos la regla ruleSingInEventbrite, que contendrá la configuración de un modelo OAuth con los valores necesarios para la autenticación y la llamada al servicio broker para que realice dicha autenticación. Es importante observar que aqui debes completar los atributos clientID, secret y redirectURL, por los campos correspondientes obtenidos en la creación de la app eventbrite al inicio del tutorial, estos son ‘client key’ y ‘client secret’ y ‘OAuth Redirect URI’.
    OAuth oauth = OAuth()
    oauth.clientID = "...COMPLETE..."
    oauth.secret   = "...COMPLETE..."
    oauth.redirectURL = "...COMPLETE..."
    oauth.accountName = oauth.clientID + oauth.secret
    oauth.authorizationURL = "https://www.eventbrite.com/oauth/authorize?response_type=token&client_id=" + oauth.clientID
    oauth.tokenURL =  "https://www.eventbrite.com/oauth/token"
    
    token = broker.oauth.authenticate(oauth)

La llamada broker.oauth.authenticate(oauth) abrirá una vista web donde el usuario debe ingresar sus credenciales de acceso de la red social Eventbrite. Al término de este proceso el usuario se encuentra logueado y autenticado, con lo cuál obtendremos el token necesario para llamar a los servicios definidos en la librería que importamos anteriormente.

Primero haremos la llamada para obtener los datos del usuario logueado, invocando el servicio EventBriteLib::eb_getProfile:

La llamada recibe como argumento el token y retorna un nuevo modelo EventBriteLib::EBProfileResponse:

    EventBriteLib::EBProfileResponse profileRsp = service.EventBriteLib::eb_getProfile.call(token)

Posteriormente, crearemos una instancia del modelo User con dichos datos:

 loggedUser = User(name:profileRsp.name, eventbriteId:profileRsp.eventbriteId) 

y guardaremos en el almacenamiento local los atributos del modeloUser y el token, para poder validar en un posterior acceso a la aplicación si el usuario ya había iniciado sesión y obtenido un token válido (esta lógica es la que habíamos definido anteriormente en el archivo main.ms).

 broker.localPersistence.save(loggedUserNameKey, loggedUser.name)
 broker.localPersistence.save(loggedUserEventbriteIDKey, loggedUser.eventbriteId)
 broker.localKeychain.save(ebUserTokenKey, token)

El código completo de nuestro archivo LoginExperience.ms puedes verlo aqui.

Experiencia lista de eventos EventsExperience.ms

Por último, en este archivo definiremos:

  • Una experiencia en la que se mostrará una lista con los eventos obtenidos a través de un servicio (importado por nuestra librería) y se mostrará el nombre del usuario logueado. Para esto agregamos a la experiencia un String que se mostrará en su layout como un componente Label y un Array de los modelos (importados de la librería) EventBriteLib::EBEvent, que se mostrarán en un componente de UI de tipo List.
Experience EventsExperience {
    String name as Label
    Array<EventBriteLib::EBEvent> events as List
}
  • Dentro de la experiencia, el método OnCreate, se ejecuta cada vez que la experiencia es creada. En este lugar, obtenemos el datasource asociado al layout de la experiencia mediante la llamada broker.ui.getDataSource() que asignamos a la variable local exp, para luego asignar sobre el atributo name el nombre del usuario logueado que tenemos referenciado desde la variable global loggedUser.
    OnCreate {    
        EventsExperience exp = broker.ui.getDataSource()
        exp.name = loggedUser.name
    }
  • Dentro de la experiencia, realizaremos la carga de los eventos a partir de la ubicación actual del dispositivo, en el método OnResume, que se ejecuta cada vez que la experiencia vuelve a ser visible.

Para esto, realizamos una llamada al servicio EventBriteLib::eb_getEventsByLocation, con los parámetros requeridos que podemos ver en la siguiente imagen:

Primero debemos configurar el formato que utiliza la API de eventbrite para parsear las fechas y esto lo logramos con la siguiente sentencia:

    service.EventBriteLib::eb_getEventsByLocation.setDateFormatter(DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ssZ", utcTimeZoneOffset: 0))

Luego efectuamos la llamada, con lo siguientes parámetros (en el orden de la llamada):

  1. ‘token’: obtenido desde el login
  2. ‘latitud’ y ‘longitud’ (obtenidos del servicio broker.location.getLocation())
  3. ‘within’: que establece el rango en kilometros para filtrar los eventos resultantes en la consulta.
  4. ‘pageNumber’: el número de página a consultar, puesto que el servicio soporta paginación.
   Location userLoc = broker.location.getLocation()
   EventBriteLib::EBEventResponse response = service.EventBriteLib::eb_getEventsByLocation.call(token, userLoc.latitude, userLoc.longitude,  25, 1)

asignamos los eventos recuperados en la lista de nuestra experiencia para que sean mostrados, y por último en caso de que no encontremos eventos mostramos un mensaje:

   experiencia.events = response.events

   if (response.events.size() == 0) {
        broker.ui.showAlert("Oops","No events found!")
   }

El código completo del archivo EventsExperience.ms puedes verlo aqui.

Edicion de Layouts – Creación de Templates

Una vez que tenemos listo el codigo de la aplicación, podemos pasar a ver cuales son los layouts que se van a auto-generar correspondientes a las experiencias que han sido creadas anteriormente, en el tab Build UI de nuestro IDE. En nuestro ejemplo, se autogeneran dos layouts: LoginExperience y EventsExperience, como podemos observar a continuación:

En esta vista de edición de UI, que llamamos UI Builder podrás customizar a gusto todos los elementos visuales. Haciendo click en el componente o en el panel izquierdo en la jerarquía de vistas, podrás observar en el panel derecho, sección Properties todas las propiedades visuales editables para el mismo.

Si intentamos ejecutar la aplicación en estas condiciones, obtendremos un error ya que en la experiencia EventsExperience estamos asociando una lista de modelos (en este caso EBEvent) a un componente visual List. Para que esto funcione, necesitamos crear un layout específico para mostrar cada uno de estos eventos en la lista, a estos layouts especiales los llamamos templates.

Por lo tanto procederemos a crear un template, desde el tab Build UI, clickeando sobre el segundo botón ‘+’, y nombrando al archivo ‘template_event_cell’ como observamos a continuación:

El nuevo template creado traerá un label por defecto. Agregamos 2 nuevos componentes: uno de tipo label y otro de tipo image. Asi tendremos en total 2 labels y una imagen donde mostraremos el nombre, fecha e imagen del evento. Esto lo hacemos haciendo click sobre el componente visual ubicado en el lado izquierdo del IDE, el mismo será agregado a la vista y obtenemos lo que podemos ver a continuación:

Luego, para cada elemento visual del template debemos establecer cuál será la clave a utilizar para el bindeo de datos. Para esto hacemos click sobre el componente mismo (o en la estructura de árbol del lado izquierdo de la pantalla). En el componente de tipo image podemos observar la propiedad llamada Data binding en donde seteamos valor eventImage:

Hacemos lo mismo con los otros componentes de tipo label, al primero le pondremos ‘eventStart’ y al segundo ‘eventName’.

Ya estamos listos para bindear los datos a mostrar de la lista de eventos en la experiencia EventsExperience. Primero seleccionamos el layout EventsExperience asociado a la experiencia desde el menú lateral izquierdo, luego seleccionando de la lista y por último, sobre el panel derecho la propiedad Template and data binding.

Desde allí seleccionamos el template a utilizar: ‘template_event_cell’ y establecemos para cada clave definida anteriormente (‘eventStart’, ‘eventName’ y ‘eventImage’) un atributo o cadena de atributos del modelo a bindear, de la siguiente manera:

{{item.atributo}}

donde ‘item’ hace referencia a un modelo del tipo definido en la lista, y ‘atributo’ al nombre de un atributo de un modelo. Notar que se pueden encadenar en caso de que los atributos sean a la vez modelos.

En nuestro ejemplo, sabemos que la lista que estamos configurando:

    Array<EventBriteLib::EBEvent> events as List

esta compuesta por modelos de tipo EventBriteLib::EBEvent. Si observamos el atributo start:

es a la vez un modelo de tipo EventBriteLib::EBDate

que tiene un atributo utc de tipo Date que indica la fecha de inicio del evento y contendrá el valor a mostrar, por lo cual en el binding para ese campo debemos ingresar: “{{item.start.utc}}”.

Con un razonamiento similar, el binding a configurar sobre la clave ‘eventName’ es “{{item.name.text}}” y el de la clave ‘eventImage’ es “{{item.logo.url}}”.

Y asi tenemos la primera versión de nuestra aplicación lista!!

Ejecutando la aplicación podrás ver las siguientes pantallas, con layouts autogenerados:

Por supuesto, con ayuda del UI Builder puedes embellecer tus layouts a gusto y así mejorar la apariencia visual de tu aplicación. Si quieres que tus pantallas queden igual que las
que se muestran al inicio del tutorial puedes hacer lo siguiente:

  • Accede a la edición por XML del layout LoginExperience en la sección Build UI:

Reemplaza el XML autogenerado (que representa la definición del layout) por el XML de aquí.

  • Selecciona el template ‘template_event_cell’, accede a la edición por XML y reemplaza el XML autogenerado por el XML de aquí.

Salva los cambios y listo! Cuando vuelves a correr la aplicación verás tu aplicación con la misma UI que te mostramos al inicio, con un aspecto profesional!