SlideShare a Scribd company logo
1 of 36
Download to read offline
THE FAMILYSEARCH 
REFERENCE CLIENT 
Open-source implementation of the Family Tree UI 
Written as a Single-Page Application in Javascript 
using the REST API 
DALLAN QUASS 
LYNN MONSON 
DOVY PAUKSTYS
TOUR
SELECT PERSON
PERSON
PERSON (SCROLL DOWN)
EDIT NAME
CHINESE
ADD EVENT
ADD SOURCE
SOURCE BOX
WHY WAS IT 
DEVELOPED? 
1. Make it easy for partners to allow their customers to access 
the FamilySearch tree using an easily-extensible framework 
2. Provide a set of re-usable components for use by partners 
3. A real-world example of accessing the FamilySearch Tree 
using the FamilySearch Javascript SDK
DISCLAIMERS 
Not official - not an official FamilySearch project 
Not supported - code is provided as-is 
Not maintained - everything currently works...
WHAT CAN I DO WITH IT? 
1. Have you ever thought you could improve upon the 
FamilySearch UI? 
Fork this project and extend it 
2. Do you want to allow people to edit names and are intimidated 
by the complexity? 
Use the name edit component from this project 
3. Would you like to understand better how to use the 
FamilySearch REST API? 
Review the source for this project
HOW CAN I GET 
STARTED? 
Install pre-requisites 
Install node.js (nodejs.org) 
npm install -g bower install bower 
npm install -g grunt-cli install grunt 
Install PhantomJS (phantomjs.org)
HOW CAN I GET 
STARTED? 
Get an App Key 
Contact FamilySearch developer support if you don't already 
have one 
Ask FamilySearch developer support to add 
as an http://localhost:9000/#!/auth OAuth redirect URL
HOW CAN I GET 
STARTED? 
Run the code 
clone github.com/rootsdev/familysearch-reference-client 
npm install install build dependencies 
bower install install client dependencies 
grunt watch launch a server and watch for changes 
Visit 
http://localhost:9000 
Sign in using your sandbox username and password
ANGULARJS
ANGULARJS FRAMEWORK 
Models 
Views 
Controllers 
Directives (components) 
Filters 
Services 
dependency injection 
easy unit tests
index.html 
head> 
<!-- include stylesheets, fonts, and javascripts --> 
</head> 
body> 
<div class="navbar navbar-default navbar-static-top"> 
<div class="container"> 
<div class="navbar-header"> 
<a class="navbar-brand" href="/">FamilySearch Reference Client</a> 
<span ng-show="busy" style="float: left; line-height: 50px"><i class="fa fa-</div> 
<div class="collapse navbar-collapse header-collapse"> 
</div> 
</div> 
</div> 
<div id="themeContainer" class="familysearch_theme"> 
<div fs-growl=""></div> 
<div fs-re-authenticate=""></div> 
<div class="container" ui-view=""></div> 
</div> 
</body>
app.js 
angular.module('fsReferenceClient', [ 'fsReferenceClientShared', 'templates-app', 'templates-.config(function($stateProvider, $urlRouterProvider) { 
$urlRouterProvider.otherwise('/'); 
}) 
.config(function(fsApiProvider) { 
fsApiProvider 
.setClientId('WCQY-7J1Q-GKVV-7DNM-SQ5M-9Q5H-JX3H-CMJK') 
.setEnvironmentName('sandbox') 
.setRedirectUri('http://localhost:9000/#!/auth'); 
}) 
.config(function(fsLocationProvider) { 
var prefix = '/#'; 
fsLocationProvider.configure({ 
getPersonLocation: function(personId) { 
return { 
prefix: prefix, 
path: '/person/'+personId 
}; 
}, 
... 
}); 
})
app.js (continued) 
.controller('AppController', function ($scope) { 
$scope.environment = 'Sandbox'; 
$scope.$on('$stateChangeStart', function(event, toState) { 
if (toState.resolve) { 
$scope.busy = true; 
} 
}); 
$scope.$on('$stateChangeSuccess', function() { 
$scope.busy = false; 
}); 
$scope.$on('$stateChangeError', function() { 
$scope.busy = false; 
}); 
});
person.js 
angular.module('fsReferenceClient') 
.config(function ($stateProvider) { 
$stateProvider.state('person', { 
url: '/person/:personId', 
controller: 'PersonController', 
templateUrl: 'person/person.tpl.html', 
data: { pageTitle: 'Person' }, 
resolve: { 
person: ['$stateParams','fsApi',function($stateParams, fsApi) { 
return fsApi.getPerson($stateParams.personId).then(function (response) { 
return response.getPerson(); 
}); 
}], 
sources: ['_','$q','$stateParams','fsApi',function(_, $q, $stateParams, fsApi) 
return fsApi.getPersonSourcesQuery($stateParams.personId).then(function(response) 
return _.map(response.getSourceRefs(), function(sourceRef) { 
return { 
ref: sourceRef, 
description: response.getSourceDescription(sourceRef.$sourceDescriptionId 
id: sourceRef.id 
}; 
}); 
}); 
}] 
} 
});
person.js (continued) 
.controller('PersonController', function ($scope, $state, $rootScope, person, sources, var sections = ['vitalFacts', 'otherInfo', 'familyMembers', 'sources', 'discussions' 
$scope.states = {}; 
sections.forEach(function(section) { 
$scope.states[section] = {value: 'open'}; 
}); 
$scope.person = person; 
$scope.sources = sources; 
sources.forEach(function(source) { 
fsUtils.mixinStateFunctions($scope, source); 
}); 
var unbindRestored = $rootScope.$on('restored', function() { 
fsApi.getPerson($scope.person.id).then(function (response) { 
fsUtils.refresh($scope.person, response.getPerson()); 
}); 
}); 
$scope.$on('$destroy', unbindRestored); 
$scope.$on('delete', function(event, person, changeMessage) { 
event.stopPropagation(); 
person._busy = true; 
person.$delete(changeMessage).then(function() { 
person._busy = false; 
fsCurrentUserCache.getUser().then(function(user) { 
$state.go('person', { personId: user.personId });
person.tpl.html 
div fs-person-profile="" person="person"></div> 
div class="mainContent"> 
<div class="row"> 
<div class="col-md-9"> 
<div fs-vital-facts-section="" person="person" sources="sources" state="states 
<div fs-other-info-section="" person="person" state="states['otherInfo']"></div 
<div fs-family-members-section="" person="person" state="states['familyMembers 
<div fs-sources-section="" person="person" sources="sources" state="states['sources 
<div fs-discussions-section="" person="person" state="states['discussions']"></ 
<div fs-notes-section="" person="person" state="states['notes']"></div> 
</div> 
<div class="col-md-3 sidebar"> 
<div fs-changes-section="" person="person"></div> 
<div fs-tools-section="" person="person"></div> 
</div> 
</div> 
</div>
fsPersonProfile.js 
angular.module('fsReferenceClientShared') 
.directive('fsPersonProfile', function (fsLocation) { 
return { 
templateUrl: 'fsReferenceClientShared/fsPersonProfile/fsPersonProfile.tpl.html' 
scope: { 
person: '=' 
}, 
link: function(scope) { 
scope.treeHref = fsLocation.getTreeUrl(scope.person.id); 
} 
}; 
});
fsPersonProfile.tpl.html 
div class="profileHeaderContainer"> 
<div class="tree-family jumbotron"> 
<div class="personWrapper"> 
<div class="nameWrapper"> 
<div class="row"> 
<div class="col-lg-2 col-md-2"> 
<i class="icon-rounded hidden-xs" ng-class="{'fs-icon-male': person._isMale(), 
'fs-icon-female': !person._isMale()}"> </i> 
</div> 
<div class="col-lg-10 col-md-10"> 
<div class="pull-right"><span ng-show="person._busy"> 
<i class="fa fa-spinner fa-spin"></i></span></div> 
<h1>{{person.$getDisplayName()}}</h1> 
<span class="lifeSpan">{{person.$getDisplayBirthDate()}} - 
{{person.$getDisplayDeathDate()}}</span> 
<span class="pid">{{person.id}}</span> 
<div class="personActions"> 
<ul class="list-collapsed"> 
<li class="pull-left"><a ng-href="{{treeHref}}"> 
<i class="fs-icon-male fs-icon-pedigree"> </i>View Tree</a></li> 
</ul> 
</div> 
</div> 
</div> 
</div> 
</div>
EXTENDING
RESULT
RE-USE COMPONENTS
FORK 
Fork 
https://github.com/rootsdev/familysearch-reference-client 
create a directory for your components; e.g., 
src/common/dqComponents
dqPedigreeMini.js 
angular.module('dqPedigreeMini', ['loDash', 'fsReferenceClientShared', 'dqPersonMini' 
.directive('dqPedigreeMini', function (_, fsApi) { 
return { 
templateUrl: 'dqComponents/dqPedigreeMini.tpl.html', 
scope: { 
personId: '@' 
}, 
controller: function($scope) { 
fsApi.getAncestry($scope.personId, {generations: 2}).then(function(response) 
$scope.persons = _.filter(response.getPersons(), function(person) { 
return person.$getAscendancyNumber() >= 1 && 
person.$getAscendancyNumber() <= 7; 
}); 
}); 
} 
}; 
});
dqPedigreeMini.tpl.html 
<div class="panel panel-info"> 
<div class="panel-heading"> 
<h4 class="panel-title">Mini Pedigree</h4> 
</div> 
<div class="panel-body dq-pedigree-mini-outer"> 
<div ng-repeat="person in persons"> 
<div dq-person-mini person="person" 
is-focus="{{person.$getAscendancyNumber() == 1}}" 
class="dq-pedigree-mini-person" 
ng-class="'dq-pedigree-mini-pos'+person.$getAscendancyNumber()"> 
</div> 
</div> 
</div> 
</div>
dqPersonMini.js 
angular.module('dqPersonMini', []) 
.directive('dqPersonMini', function () { 
return { 
templateUrl: 'dqComponents/dqPersonMini.tpl.html', 
scope: { 
person: '=', 
isFocus: '@' 
} 
}; 
});
dqPersonMini.tpl.html 
div class="dq-person-mini"> 
<a href="" fs-person-popover="" person="person" popover-placement="left"> 
<span class="dq-person-mini-name" 
ng-style="{'font-weight': isFocus === 'true' ? 'bold' : 'normal', 
'color': isFocus === 'true' ? '#333' : '#0051c4'}"> 
{{person.$getDisplayName()}} 
</span> 
</a> 
</div>
INJECT INTO PERSON 
<div class="col-md-3 sidebar"> 
<div fs-changes-section="" person="person"></div> 
<div fs-tools-section="" person="person"></div> 
<div dq-pedigree-mini="" person-id="{{person.id}}"></div> 
</div>
THE END 
Slides are at https://github.com/DallanQ/fs-reference-client- 
2014-slides

More Related Content

What's hot

Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)Jeff Eaton
 
Country State City Dropdown in PHP
Country State City Dropdown in PHPCountry State City Dropdown in PHP
Country State City Dropdown in PHPVineet Kumar Saini
 
Web::Machine - Simpl{e,y} HTTP
Web::Machine - Simpl{e,y} HTTPWeb::Machine - Simpl{e,y} HTTP
Web::Machine - Simpl{e,y} HTTPMichael Francis
 
Building scalable products with WordPress - WordCamp London 2018
Building scalable products with WordPress - WordCamp London 2018Building scalable products with WordPress - WordCamp London 2018
Building scalable products with WordPress - WordCamp London 2018Elliot Taylor
 
Add edit delete in Codeigniter in PHP
Add edit delete in Codeigniter in PHPAdd edit delete in Codeigniter in PHP
Add edit delete in Codeigniter in PHPVineet Kumar Saini
 
Dethroning Grunt: Simple and Effective Builds with gulp.js
Dethroning Grunt: Simple and Effective Builds with gulp.jsDethroning Grunt: Simple and Effective Builds with gulp.js
Dethroning Grunt: Simple and Effective Builds with gulp.jsJay Harris
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created itPaul Bearne
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkDirk Haun
 
Gem christmas calendar
Gem christmas calendarGem christmas calendar
Gem christmas calendarerichsen
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
17. CodeIgniter login simplu cu sesiuni
17. CodeIgniter login simplu cu sesiuni17. CodeIgniter login simplu cu sesiuni
17. CodeIgniter login simplu cu sesiuniRazvan Raducanu, PhD
 
Perl调用微博API实现自动查询应答
Perl调用微博API实现自动查询应答Perl调用微博API实现自动查询应答
Perl调用微博API实现自动查询应答琛琳 饶
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Acquia
 

What's hot (20)

Pagination in PHP
Pagination in PHPPagination in PHP
Pagination in PHP
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 
logic321
logic321logic321
logic321
 
Country State City Dropdown in PHP
Country State City Dropdown in PHPCountry State City Dropdown in PHP
Country State City Dropdown in PHP
 
Web::Machine - Simpl{e,y} HTTP
Web::Machine - Simpl{e,y} HTTPWeb::Machine - Simpl{e,y} HTTP
Web::Machine - Simpl{e,y} HTTP
 
Building scalable products with WordPress - WordCamp London 2018
Building scalable products with WordPress - WordCamp London 2018Building scalable products with WordPress - WordCamp London 2018
Building scalable products with WordPress - WordCamp London 2018
 
Add edit delete in Codeigniter in PHP
Add edit delete in Codeigniter in PHPAdd edit delete in Codeigniter in PHP
Add edit delete in Codeigniter in PHP
 
Dethroning Grunt: Simple and Effective Builds with gulp.js
Dethroning Grunt: Simple and Effective Builds with gulp.jsDethroning Grunt: Simple and Effective Builds with gulp.js
Dethroning Grunt: Simple and Effective Builds with gulp.js
 
YAP / Open Mail Overview
YAP / Open Mail OverviewYAP / Open Mail Overview
YAP / Open Mail Overview
 
Daily notes
Daily notesDaily notes
Daily notes
 
The Benefits of Juicing
The Benefits of JuicingThe Benefits of Juicing
The Benefits of Juicing
 
Keeping It Simple
Keeping It SimpleKeeping It Simple
Keeping It Simple
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created it
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
 
Gem christmas calendar
Gem christmas calendarGem christmas calendar
Gem christmas calendar
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
17. CodeIgniter login simplu cu sesiuni
17. CodeIgniter login simplu cu sesiuni17. CodeIgniter login simplu cu sesiuni
17. CodeIgniter login simplu cu sesiuni
 
Perl调用微博API实现自动查询应答
Perl调用微博API实现自动查询应答Perl调用微博API实现自动查询应答
Perl调用微博API实现自动查询应答
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1
 

Similar to FamilySearch Reference Client

Opencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSOpencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSbuttyx
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From IusethisMarcus Ramberg
 
Scaling Complexity in WordPress Enterprise Apps
Scaling Complexity in WordPress Enterprise AppsScaling Complexity in WordPress Enterprise Apps
Scaling Complexity in WordPress Enterprise AppsMike Schinkel
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformanceJonas De Smet
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive Kuo
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Joao Lucas Santana
 
The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015Matt Raible
 
How to CASifying PeopleSoft and Integrating CAS and ADFS
How to CASifying PeopleSoft and Integrating CAS and ADFSHow to CASifying PeopleSoft and Integrating CAS and ADFS
How to CASifying PeopleSoft and Integrating CAS and ADFSJohn Gasper
 
WordPress Theme Design and Development Workshop - Day 3
WordPress Theme Design and Development Workshop - Day 3WordPress Theme Design and Development Workshop - Day 3
WordPress Theme Design and Development Workshop - Day 3Mizanur Rahaman Mizan
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of DjangoJacob Kaplan-Moss
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2James Pearce
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 

Similar to FamilySearch Reference Client (20)

Opencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSOpencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJS
 
JS-05-Handlebars.ppt
JS-05-Handlebars.pptJS-05-Handlebars.ppt
JS-05-Handlebars.ppt
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Scaling Complexity in WordPress Enterprise Apps
Scaling Complexity in WordPress Enterprise AppsScaling Complexity in WordPress Enterprise Apps
Scaling Complexity in WordPress Enterprise Apps
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and Performance
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
 
The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015
 
How to CASifying PeopleSoft and Integrating CAS and ADFS
How to CASifying PeopleSoft and Integrating CAS and ADFSHow to CASifying PeopleSoft and Integrating CAS and ADFS
How to CASifying PeopleSoft and Integrating CAS and ADFS
 
WordPress Theme Design and Development Workshop - Day 3
WordPress Theme Design and Development Workshop - Day 3WordPress Theme Design and Development Workshop - Day 3
WordPress Theme Design and Development Workshop - Day 3
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Test upload
Test uploadTest upload
Test upload
 
One Size Fits All
One Size Fits AllOne Size Fits All
One Size Fits All
 

More from Dallan Quass

FamilySearch Javascript SDK
FamilySearch Javascript SDKFamilySearch Javascript SDK
FamilySearch Javascript SDKDallan Quass
 
Using WeRelate.org (2009)
Using WeRelate.org (2009)Using WeRelate.org (2009)
Using WeRelate.org (2009)Dallan Quass
 
WeRelate.org flyer (2010)
WeRelate.org flyer (2010)WeRelate.org flyer (2010)
WeRelate.org flyer (2010)Dallan Quass
 
Why share your genealogy content on WeRelate.org (2009)
Why share your genealogy content on WeRelate.org (2009)Why share your genealogy content on WeRelate.org (2009)
Why share your genealogy content on WeRelate.org (2009)Dallan Quass
 
An Open-source Similar-name Finder
An Open-source Similar-name FinderAn Open-source Similar-name Finder
An Open-source Similar-name FinderDallan Quass
 
An Open-source Place-finder for Genealogy
An Open-source Place-finder for GenealogyAn Open-source Place-finder for Genealogy
An Open-source Place-finder for GenealogyDallan Quass
 
A Robust Open-source GEDCOM Parser
A Robust Open-source GEDCOM ParserA Robust Open-source GEDCOM Parser
A Robust Open-source GEDCOM ParserDallan Quass
 

More from Dallan Quass (7)

FamilySearch Javascript SDK
FamilySearch Javascript SDKFamilySearch Javascript SDK
FamilySearch Javascript SDK
 
Using WeRelate.org (2009)
Using WeRelate.org (2009)Using WeRelate.org (2009)
Using WeRelate.org (2009)
 
WeRelate.org flyer (2010)
WeRelate.org flyer (2010)WeRelate.org flyer (2010)
WeRelate.org flyer (2010)
 
Why share your genealogy content on WeRelate.org (2009)
Why share your genealogy content on WeRelate.org (2009)Why share your genealogy content on WeRelate.org (2009)
Why share your genealogy content on WeRelate.org (2009)
 
An Open-source Similar-name Finder
An Open-source Similar-name FinderAn Open-source Similar-name Finder
An Open-source Similar-name Finder
 
An Open-source Place-finder for Genealogy
An Open-source Place-finder for GenealogyAn Open-source Place-finder for Genealogy
An Open-source Place-finder for Genealogy
 
A Robust Open-source GEDCOM Parser
A Robust Open-source GEDCOM ParserA Robust Open-source GEDCOM Parser
A Robust Open-source GEDCOM Parser
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 

Recently uploaded (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

FamilySearch Reference Client

  • 1. THE FAMILYSEARCH REFERENCE CLIENT Open-source implementation of the Family Tree UI Written as a Single-Page Application in Javascript using the REST API DALLAN QUASS LYNN MONSON DOVY PAUKSTYS
  • 11. WHY WAS IT DEVELOPED? 1. Make it easy for partners to allow their customers to access the FamilySearch tree using an easily-extensible framework 2. Provide a set of re-usable components for use by partners 3. A real-world example of accessing the FamilySearch Tree using the FamilySearch Javascript SDK
  • 12. DISCLAIMERS Not official - not an official FamilySearch project Not supported - code is provided as-is Not maintained - everything currently works...
  • 13. WHAT CAN I DO WITH IT? 1. Have you ever thought you could improve upon the FamilySearch UI? Fork this project and extend it 2. Do you want to allow people to edit names and are intimidated by the complexity? Use the name edit component from this project 3. Would you like to understand better how to use the FamilySearch REST API? Review the source for this project
  • 14. HOW CAN I GET STARTED? Install pre-requisites Install node.js (nodejs.org) npm install -g bower install bower npm install -g grunt-cli install grunt Install PhantomJS (phantomjs.org)
  • 15. HOW CAN I GET STARTED? Get an App Key Contact FamilySearch developer support if you don't already have one Ask FamilySearch developer support to add as an http://localhost:9000/#!/auth OAuth redirect URL
  • 16. HOW CAN I GET STARTED? Run the code clone github.com/rootsdev/familysearch-reference-client npm install install build dependencies bower install install client dependencies grunt watch launch a server and watch for changes Visit http://localhost:9000 Sign in using your sandbox username and password
  • 18. ANGULARJS FRAMEWORK Models Views Controllers Directives (components) Filters Services dependency injection easy unit tests
  • 19. index.html head> <!-- include stylesheets, fonts, and javascripts --> </head> body> <div class="navbar navbar-default navbar-static-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="/">FamilySearch Reference Client</a> <span ng-show="busy" style="float: left; line-height: 50px"><i class="fa fa-</div> <div class="collapse navbar-collapse header-collapse"> </div> </div> </div> <div id="themeContainer" class="familysearch_theme"> <div fs-growl=""></div> <div fs-re-authenticate=""></div> <div class="container" ui-view=""></div> </div> </body>
  • 20. app.js angular.module('fsReferenceClient', [ 'fsReferenceClientShared', 'templates-app', 'templates-.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/'); }) .config(function(fsApiProvider) { fsApiProvider .setClientId('WCQY-7J1Q-GKVV-7DNM-SQ5M-9Q5H-JX3H-CMJK') .setEnvironmentName('sandbox') .setRedirectUri('http://localhost:9000/#!/auth'); }) .config(function(fsLocationProvider) { var prefix = '/#'; fsLocationProvider.configure({ getPersonLocation: function(personId) { return { prefix: prefix, path: '/person/'+personId }; }, ... }); })
  • 21. app.js (continued) .controller('AppController', function ($scope) { $scope.environment = 'Sandbox'; $scope.$on('$stateChangeStart', function(event, toState) { if (toState.resolve) { $scope.busy = true; } }); $scope.$on('$stateChangeSuccess', function() { $scope.busy = false; }); $scope.$on('$stateChangeError', function() { $scope.busy = false; }); });
  • 22. person.js angular.module('fsReferenceClient') .config(function ($stateProvider) { $stateProvider.state('person', { url: '/person/:personId', controller: 'PersonController', templateUrl: 'person/person.tpl.html', data: { pageTitle: 'Person' }, resolve: { person: ['$stateParams','fsApi',function($stateParams, fsApi) { return fsApi.getPerson($stateParams.personId).then(function (response) { return response.getPerson(); }); }], sources: ['_','$q','$stateParams','fsApi',function(_, $q, $stateParams, fsApi) return fsApi.getPersonSourcesQuery($stateParams.personId).then(function(response) return _.map(response.getSourceRefs(), function(sourceRef) { return { ref: sourceRef, description: response.getSourceDescription(sourceRef.$sourceDescriptionId id: sourceRef.id }; }); }); }] } });
  • 23. person.js (continued) .controller('PersonController', function ($scope, $state, $rootScope, person, sources, var sections = ['vitalFacts', 'otherInfo', 'familyMembers', 'sources', 'discussions' $scope.states = {}; sections.forEach(function(section) { $scope.states[section] = {value: 'open'}; }); $scope.person = person; $scope.sources = sources; sources.forEach(function(source) { fsUtils.mixinStateFunctions($scope, source); }); var unbindRestored = $rootScope.$on('restored', function() { fsApi.getPerson($scope.person.id).then(function (response) { fsUtils.refresh($scope.person, response.getPerson()); }); }); $scope.$on('$destroy', unbindRestored); $scope.$on('delete', function(event, person, changeMessage) { event.stopPropagation(); person._busy = true; person.$delete(changeMessage).then(function() { person._busy = false; fsCurrentUserCache.getUser().then(function(user) { $state.go('person', { personId: user.personId });
  • 24. person.tpl.html div fs-person-profile="" person="person"></div> div class="mainContent"> <div class="row"> <div class="col-md-9"> <div fs-vital-facts-section="" person="person" sources="sources" state="states <div fs-other-info-section="" person="person" state="states['otherInfo']"></div <div fs-family-members-section="" person="person" state="states['familyMembers <div fs-sources-section="" person="person" sources="sources" state="states['sources <div fs-discussions-section="" person="person" state="states['discussions']"></ <div fs-notes-section="" person="person" state="states['notes']"></div> </div> <div class="col-md-3 sidebar"> <div fs-changes-section="" person="person"></div> <div fs-tools-section="" person="person"></div> </div> </div> </div>
  • 25. fsPersonProfile.js angular.module('fsReferenceClientShared') .directive('fsPersonProfile', function (fsLocation) { return { templateUrl: 'fsReferenceClientShared/fsPersonProfile/fsPersonProfile.tpl.html' scope: { person: '=' }, link: function(scope) { scope.treeHref = fsLocation.getTreeUrl(scope.person.id); } }; });
  • 26. fsPersonProfile.tpl.html div class="profileHeaderContainer"> <div class="tree-family jumbotron"> <div class="personWrapper"> <div class="nameWrapper"> <div class="row"> <div class="col-lg-2 col-md-2"> <i class="icon-rounded hidden-xs" ng-class="{'fs-icon-male': person._isMale(), 'fs-icon-female': !person._isMale()}"> </i> </div> <div class="col-lg-10 col-md-10"> <div class="pull-right"><span ng-show="person._busy"> <i class="fa fa-spinner fa-spin"></i></span></div> <h1>{{person.$getDisplayName()}}</h1> <span class="lifeSpan">{{person.$getDisplayBirthDate()}} - {{person.$getDisplayDeathDate()}}</span> <span class="pid">{{person.id}}</span> <div class="personActions"> <ul class="list-collapsed"> <li class="pull-left"><a ng-href="{{treeHref}}"> <i class="fs-icon-male fs-icon-pedigree"> </i>View Tree</a></li> </ul> </div> </div> </div> </div> </div>
  • 30. FORK Fork https://github.com/rootsdev/familysearch-reference-client create a directory for your components; e.g., src/common/dqComponents
  • 31. dqPedigreeMini.js angular.module('dqPedigreeMini', ['loDash', 'fsReferenceClientShared', 'dqPersonMini' .directive('dqPedigreeMini', function (_, fsApi) { return { templateUrl: 'dqComponents/dqPedigreeMini.tpl.html', scope: { personId: '@' }, controller: function($scope) { fsApi.getAncestry($scope.personId, {generations: 2}).then(function(response) $scope.persons = _.filter(response.getPersons(), function(person) { return person.$getAscendancyNumber() >= 1 && person.$getAscendancyNumber() <= 7; }); }); } }; });
  • 32. dqPedigreeMini.tpl.html <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title">Mini Pedigree</h4> </div> <div class="panel-body dq-pedigree-mini-outer"> <div ng-repeat="person in persons"> <div dq-person-mini person="person" is-focus="{{person.$getAscendancyNumber() == 1}}" class="dq-pedigree-mini-person" ng-class="'dq-pedigree-mini-pos'+person.$getAscendancyNumber()"> </div> </div> </div> </div>
  • 33. dqPersonMini.js angular.module('dqPersonMini', []) .directive('dqPersonMini', function () { return { templateUrl: 'dqComponents/dqPersonMini.tpl.html', scope: { person: '=', isFocus: '@' } }; });
  • 34. dqPersonMini.tpl.html div class="dq-person-mini"> <a href="" fs-person-popover="" person="person" popover-placement="left"> <span class="dq-person-mini-name" ng-style="{'font-weight': isFocus === 'true' ? 'bold' : 'normal', 'color': isFocus === 'true' ? '#333' : '#0051c4'}"> {{person.$getDisplayName()}} </span> </a> </div>
  • 35. INJECT INTO PERSON <div class="col-md-3 sidebar"> <div fs-changes-section="" person="person"></div> <div fs-tools-section="" person="person"></div> <div dq-pedigree-mini="" person-id="{{person.id}}"></div> </div>
  • 36. THE END Slides are at https://github.com/DallanQ/fs-reference-client- 2014-slides