Tech Blog

How We Built the Appointment Scheduler Primo Add-On

The Appointment Scheduler Cloud App has been used by institutions to schedule thousands of appointments in their libraries. It’s a great way to leverage the Alma platform to provide library-related functionality, and has been especially useful as many libraries are providing service remotely or by-appointment only. The Cloud App supports defining locations and capacity, scheduling appointments of configurable length and notifying users of their library appointment via email or SMS.

Some institutions have asked for patrons to have self-service access to their appointments made via the Appointment Scheduler. Cloud Apps are only supported in the Ex Libris platform (e.g. Alma), but Primo can be customized by building an add-on and using the UI customization framework. So we decided to build a new add-on which would provide self-service functionality. The add-on should support:

  • Viewing or cancelling existing appointments
  • Scheduling a new appointment for configured locations
  • Providing time slots based on location capacity and availability

In this blog post, we’ll describe how we build the add-on, leveraging the AWS public cloud.

Overview

The Cloud App stores its data in a hosted mongoDB instance in the Frankfurt AWS region. The database is fronted by a serverless service which consists of an API Gateway endpoint and a Lambda function. The code includes a template.yml file which defines all of the resources needed to run the service.

The topology is represented in the diagram below:

Building the Add-On

Authentication

The first challenge is how we can authenticate patrons from their session in Primo. Access to the service for Cloud App users is managed by the authentication token provided in the Cloud App framework. Thankfully, Primo also provides a JWT authentication token. We discussed working with JWTs in last month’s post. There are two ways to retrieve the public key to verify the Primo authentication token:

  • an API which can be used to retrieve the institution’s public key using an API Key which is configured for read-0nly access to the public key API
  • a publicly available JWK set which contains the public key for Alma and for the institution’s Primo instance

The add-on uses the JWKS to retrieve the public key and validate the token.

So we seem to have everything we need to verify the user and allow them access to their appointments.

Configuration

Configuration for the Appointment Scheduler is stored using the Cloud App Configuration Service and includes locations, opening and closing times, and appointment duration. Data stored in this service is not available outside of the Cloud App context, so we need to store the configuration in the mongoDB as well. For this purpose, we created a new “config” collection in the database and a new PUT /config/{instCode}¬†endpoint in our service. Now in the Cloud App, whenever we save the configuration to the Configuration Service, we call our service endpoint as well so it’s available in both places.

Service

To support accessing the service for patrons, we added a number of end points:

  • GET /patron/events– retrieve a patron’s appointments
  • POST /patron/events– create a new appointment for the patron
  • DELETE /patron/events/{id}– delete a patron’s appointment
  • GET /patron/slots– retrieve an anonymized list of appointments for a specified date to build the available slots
  • GET /patron/config– retrieve the configuration for a patron’s institution

We then change our service to check the “route key”- if it includes /patron, we authenticate the user with the Primo token, otherwise we validate as a Cloud App token. This ensures that patrons only have access to their own appointments.

handler.jsView on Github

Now our service supports all of the functionality required to build our add-on.

Add-On

To build our add-on, we followed the instructions in the Primo Dev Env Github repository. We first built the functionality locally as a part of the customization package (in the custom.js file). Once it was working, we separated out the module into an NPM package so that it can be installed and used by others in their customization packages.

Primo customizations are built using AngularJS. Our code includes the following AngularJS elements:

AppointmentSchedulerService: Handles the communication with the back-end appointment scheduler service, including retrieving/creating/deleting appointments and retrieving configuration

AppointmentSchedulerController: Interacts with the service and provides the functionality of the component. The most complex logic in the controller is the building of the available slots, which takes into consideration the configuration of the selected location and removes filled slots based on the location’s capacity and the appointments already scheduled.

AppointmentSchedulerComponent: Provides the HTML user interface

AppointmentSchedulerHttpInterceptor  Adds the Primo token and the supplied API key (for token validation) to each request to the backend service

All of these elements are added to an appointmentScheduler module which is then exposed for inclusion in a Primo customization package.

The widget as it appears in the account overview screen:

The widget in “Add new appointment” mode:

Wrapping Up

In this post we saw how we built a Primo add-on to expose self-service functionality to patrons for appointments scheduled with the Appointment Scheduler Cloud App, leveraging the AWS public cloud.

If you’re interested in using the add-on, detailed installation and configuration instructions are available on the add-on’s home page. If you’d like to look more closely at the code it’s available in this Github repository. The repository includes the Cloud App, the back-end service, and the add-on.

Leave a Reply