Drupal on the Big Screen

Decoupled Drupal Powering an Interactive Touchscreen Kiosk

Brian Reese

brian.reese@gmail.com

github.com/darkcody

brian-reese.com

 

senior developer @ acquia

What we'll cover

  • A little background on headless & decoupled Drupal
  • A case study on a decoupled drupal implementation powering a kiosk
  • A quick demo showing how easy it can be to get started

A Little Background

1.

on decoupling drupal

Rendered Pages

CMS

Custom Front End

CMS

Content Creation Tools

Content Repository

Presentation Logic

(renders raw data into pages)

Content Creation Tools

Content Repository

Raw Data

Traditional

Headless/Decoupled

Rendered Page

CMS

Content Creation Tools

Content Repository

API

Progressively Decoupled

Component

Component

Presentation Logic

Custom Front End

CMS

(renders raw data into pages)

Content Creation Tools

Content Repository

Raw Data

Fully Decoupled

Why you might Choose a Decoupled architechture?

  • Flexibility in your presentation layer
  • Increased speed/responsiveness
  • More interactive interfaces
  • Front-end devs don't need to know Drupal

Some Possible Downsides

  • Introduces more complexity
  • Lose a lot of out-of-the-box drupal
  • Can be more difficult for small or single-person teams

A Case Study

2.

building a kiosk

Client Checklist:

  • User friendly

  • Touch screen

  • Various Social media integrations

  • Use whatever tech you want*

  • Concert details & Musician Bios

just make it cool

(Magical Unicorn)

(Two-headed monster)

Application + APIs

AngularJS

Drupal 7

Facebook

Youtube

Google Maps + Calendar

Why AngularJS?

  • Excellent DOM Manipulation framework
  • Flexibile Services
  • Modular components 
  • Familiarity

Why Drupal?

  • Excellent CMS
  • Easy REST services 
  • Familiarity

Drupal

Home Screen

Ensembles

Photo Gallery

Video Gallery

Calendar

Map

Ensemble Members

Ensemble Detail

Member Bios

Facebook Graph API

Youtube player API

Google Calendar / .ics

Google Maps 

Google Geocoding API

Drupal

Home Screen

Ensembles

Photo Gallery

Video Gallery

Calendar

Map

Ensemble Members

Ensemble Detail

Member Bios

Facebook Graph API

Youtube player API

Google Calendar / .ics

Google Maps 

Google Geocoding API

Drupal

Home Screen

Ensembles

Photo Gallery

Video Gallery

Calendar

Map

Ensemble Members

Ensemble Detail

Member Bios

Facebook Graph API

Youtube player API

Google Calendar / .ics

Google Maps 

Google Geocoding API

A Quick Demo

3.

Drupal Modules to Enable:

REST

REST UI (contrib)

Serialization

HTTP Basic Authentication

RESTful Web Services are available in d8 core

https://drupalize.me/blog/201401/introduction-restful-web-services-drupal-8

Great introduction to REST in d8:

Drupal

Home Screen

Ensembles

Photo Gallery

Video Gallery

Calendar

Map

Ensemble Members

Ensemble Detail

Member Bios

Facebook Graph API

Youtube player API

Google Calendar / .ics

Google Maps 

Google Geocoding API

angular.module('calendar.services', [])
.provider('CalendarConfiguration', function CalendarConfigurationProvider (){
  this.addGoogleCalendar = function(calendarLabel, calendarId, apiKey){
    // ...Store config details for a google calendar.
  };
  this.addIcalCalendar = function(calendarLabel, calendarId, apiKey){
    // ...Store config details for an Ical
  };
});

Creating an angular service for calendar config

separate methods for google & ical

angular.module( 'kiosk', [
  'calendar.services'
])
.config( function kioskConfig( CalendarConfigurationProvider ){
  CalendarConfigurationProvider.addIcalCalendar('Sessions', 'http://badcampdemo.local/sessions');
  CalendarConfigurationProvider.addGoogleCalendar('Bay Area Events', 'foo@group.calendar.google.com');
})

Allows one-line configuration for each calendar source

note both ical and google calendars used above

BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:web test events
X-WR-TIMEZONE:America/New_York
X-WR-CALDESC:A test calendar for importing and exporting events
BEGIN:VEVENT
DTSTART:20161024T223000Z
DTEND:20161025T015500Z
DTSTAMP:20161022T182226Z
UID:AEE7890B-17D0-4598-BDED-9C27A79E1901
URL:message://%3C119004230.1476213003399.JavaMail.dets%40ny-dets-002%3E?c=1
 476213006&k=%7CflightF9%5C%7CDEN%5C%7CDCA%5C%7C720%5C%7C
CREATED:20161012T184448Z
DESCRIPTION:Brian Reginald Reese
LAST-MODIFIED:20161012T184448Z
LOCATION:Denver International Airport
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Flight: F9 720 from DEN to DCA
TRANSP:OPAQUE
X-APPLE-STRUCTURED-LOCATION;VALUE=URI;X-APPLE-RADIUS=0;X-TITLE=Denver Inter
 national Airport:geo:39.861698,-104.672996
X-APPLE-SUGGESTION-INFO-CHANGED-FIELDS:0
X-APPLE-SUGGESTION-INFO-CHANGES-ACKNOWLEDGED:FALSE
X-APPLE-SUGGESTION-INFO-OPAQUE-KEY:|flightF9\\|DEN\\|DCA\\|720\\|
X-APPLE-SUGGESTION-INFO-UNIQUE-KEY:|2|\\|flightF9\\\\\\|DEN\\\\\\|DCA\\\\\\
 |720\\\\\\||\\|5\\|\\\\\\|4371109B-D5A3-47B0-953E-41271774D06A\\\\\\|<11900
 4230.1476213003399.JavaMail.dets@ny-dets-002>
X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:DISABLED
END:VEVENT
END:VCALENDAR

A google calendar feed

BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-WR-CALNAME;VALUE=TEXT:
PRODID:-//Drupal iCal API//EN
BEGIN:VEVENT
SUMMARY: Brian demos a kiosk
DTSTART:20161023T143907Z
CREATED:20161021T233907Z
LOCATION: UC Berkeley, Berkeley CA
DESCRIPTION: Lorem ipsum dolor sit amet, consectetur adipiscing elit...
END:VEVENT
END:VCALENDAR

My drupal ical feed

BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:web test events
X-WR-TIMEZONE:America/New_York
X-WR-CALDESC:A test calendar for importing and exporting events
BEGIN:VEVENT
DTSTART:20161024T223000Z
DTEND:20161025T015500Z
DTSTAMP:20161022T182226Z
UID:AEE7890B-17D0-4598-BDED-9C27A79E1901
URL:message://%3C119004230.1476213003399.JavaMail.dets%40ny-dets-002%3E?c=1
 476213006&k=%7CflightF9%5C%7CDEN%5C%7CDCA%5C%7C720%5C%7C
CREATED:20161012T184448Z
DESCRIPTION:Brian Reginald Reese
LAST-MODIFIED:20161012T184448Z
LOCATION:Denver International Airport
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Flight: F9 720 from DEN to DCA
TRANSP:OPAQUE
X-APPLE-STRUCTURED-LOCATION;VALUE=URI;X-APPLE-RADIUS=0;X-TITLE=Denver Inter
 national Airport:geo:39.861698,-104.672996
X-APPLE-SUGGESTION-INFO-CHANGED-FIELDS:0
X-APPLE-SUGGESTION-INFO-CHANGES-ACKNOWLEDGED:FALSE
X-APPLE-SUGGESTION-INFO-OPAQUE-KEY:|flightF9\\|DEN\\|DCA\\|720\\|
X-APPLE-SUGGESTION-INFO-UNIQUE-KEY:|2|\\|flightF9\\\\\\|DEN\\\\\\|DCA\\\\\\
 |720\\\\\\||\\|5\\|\\\\\\|4371109B-D5A3-47B0-953E-41271774D06A\\\\\\|<11900
 4230.1476213003399.JavaMail.dets@ny-dets-002>
X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:DISABLED
END:VEVENT
END:VCALENDAR

A google calendar feed

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//AFWebCMS//Omnitech Inc.//EN
BEGIN:VEVENT
DTSTART:20160504T120000Z
DEND:20160504T090000Z
SUMMARY:12:10-12:45 p.m.

St. John's Church at Lafayette Square
1525 H St. NW
Washington, DC 20005

Join us for an afternoon of music for string orchestra and soloists.  We will be performing J.S. Bach's Brandenburg Concerto No. 5 in D Major, BWV 1050 and Friedrich Robert Volkmann's Serenade No. 2 in F Major, Op. 63.  Soloist for the Brandenburg concerto are Chief Master Sergeant Stacy Ascione, flute; Master Sergeant Cleveland Chandler, violin; and Brandon Straub, harpsichord.

END:VEVENT
END:VCALENDAR

calendar from legacy cms

angular.module('calendar.services', [])
.provider('CalendarConfiguration', function CalendarConfigurationProvider (){
  // ...
})
.service( 'calendarService', ['$http', '$q', 'CalendarConfiguration'],
  function($http, $q, CalendarConfiguration) {
    
    var fetchGcalEvents = function() {
      // Fetch calendar data using $http and parse relevant details
      // Return a promise.
    }

    var fetchIcalEvents = function() {
      // Fetch calendar data using $http and parse relevant details
      // Return a promise.
    };

  });

In our angular calendar services module, we define methods to fetch each type of feed



    // ...

    var fetchEvents = function(){
      CalendarConfiguration.getGoogleCalendars().forEach(function(){
        calendarEvents.push(fetchGcalEvents());
      });
      CalendarConfiguration.getIcalCalendars().forEach(function(){
        calendarEvents.push(fetchIcalEvents());
      });

      $q.all(calendarEvents).then(function(promiseResolves){
        // Combine our resolves.
        var data = [];
        promiseResolves.forEach(function(promiseResolve){
          data.concat(promiseResolve);
        });

        // resolve the original promise.
        promiseObj.resolve(data);
      });
    };

And then we write a wrapper to resolve all the data at the same time

angular.module( 'kiosk', [
  'calendar.services'
])

.config( function kioskConfig( CalendarConfigurationProvider ){
  CalendarConfigurationProvider.addIcalCalendar('Sessions', 'http://badcampdemo.local/sessions');
  CalendarConfigurationProvider.addIcalCalendar('Bay Area Events', 'foo@group.calendar.google.com');
})

.controller( 'KioskCtrl', function KioskCtrl($scope, calendarService) {
  calendarService.fetchEvents().then(function(events){
    $scope.events = events;
  })
});

Allows us to populate $scope with a an array of all our events

Questions?

Brian Reese

brian.reese@gmail.com

github.com/darkcody

brian-reese.com

 

senior developer @ acquia

Drupal on the big screen

By Brian Reese

Drupal on the big screen

A look at decoupled drupal powering an interactive touchscreen kiosk

  • 1,272