Source:route.config.js

(function () {
	'use strict';
	// Configuration for the mohistory app.
	angular.module('mohistory').config(uiRouterConfig);
	uiRouterConfig.$inject = ['$stateProvider', '$urlRouterProvider', '$urlMatcherFactoryProvider',
		'$uiViewScrollProvider', '$locationProvider', '$sceProvider', '$httpProvider'
	];
	/**
	 * Define and configure UI-Router in order to provide navigation for the app.
	 * @memberof mohistory
	 * @name uiRouterConfig
	 * @ngdoc config
	 * @param {object} $stateProvider UI-Router service which registers states for each route.
	 * @param {object} $urlRouterProvider UI-Router service which watches $location and applies defined
	 * 	rules when the route changes.
	 * @param {object} $urlMatcherFactoryProvider UI-Router service when dictates how URLs are matched to routes
	 * @param {object} $uiViewScrollProvider UI-Router service which configures scroll behavior on route change.
	 * @param {object} $locationProvider Service effects how the app stores deep linking paths.
	 */
	function uiRouterConfig($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider,
		$uiViewScrollProvider, $locationProvider, $sceProvider, $httpProvider) {
		// HTTP headers added to API requests
		$httpProvider.defaults.headers
			.common['Accept'] = 'application/json, text/plain, */*';
		// Provide clean URLs
		$locationProvider.html5Mode(true);
		// Make URLs less strict, e.g. '/Exhibits' is considered the same as '/exhibits/'.
		$urlMatcherFactoryProvider.strictMode(false);
		$urlMatcherFactoryProvider.caseInsensitive(true);
		// Default back to AngularJS's $anchorScroll service
		$uiViewScrollProvider.useAnchorScroll();
		// Special route rules
		$urlRouterProvider.when('/', '/society');
		$urlRouterProvider.otherwise(function ($injector) {
			$injector.invoke(function ($window, $timeout) {
				$timeout(function () {
					console.log('redirecting ...');
					location.reload(false);
				});
			});
			return true;
		});
		// Route state definitions
		var states = [{
				name: 'main',
				component: 'mohistoryApp',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					menus: ['dataLoader', function (dataLoader) {
						return dataLoader.getMenus();
					}]
				}
			},
			{
				name: 'main.exhibits',
				url: '/exhibits/{id}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						var exhibitID = $transition$.params().id;
						// If exhibitID is an empty string, then this must be a page.
						// Reject the current resolve and redirect to the pages route.
						if (!exhibitID) {
							return $q.reject().catch(function () {
								$state.go('main.firstID', {
									firstID: 'exhibits'
								});
								return $q.reject('Removing trailing slash.');
							});
						} else {
							return dataLoader.getPartsContext(exhibitID, 'exhibits')
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.events',
				url: '/events?redirect&layout&size&page&text&sort&date&icon&type&series&exhibit&location',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', function (dataLoader) {
						return dataLoader.getPartsContext('events', 'pages');
					}],
					calendar: ['dataLoader', function (dataLoader) {
						return dataLoader.getCalendar();
					}],
					searchResults: ['keywordSearcher', '$transition$', function (keywordSearcher, $transition$) {
						return keywordSearcher.getResultsForPage('search-events', $transition$.params());
					}],
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
				params: {
					redirect: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					layout: {
						value: 'detail',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					size: {
						value: 20,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					text: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					sort: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					date: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
						squash: true,
					},
					icon: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					type: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					series: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					exhibit: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					location: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
				},
			},
			{
				name: 'main.eventsid',
				url: '/events/{id}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						var eventID = $transition$.params().id;
						// If eventID is an empty string, then this must be the hub.
						// Reject the current resolve and redirect to the main.events state.
						if (!eventID) {
							return $q.reject().catch(function () {
								$state.go('main.events');
								return $q.reject('Removing trailing slash.');
							});
						} else {
							return dataLoader.getPartsContext(eventID, 'events')
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], 'MHS');
				}],
			},
			{
				name: 'main.blog',
				url: '/blog?redirect&layout&size&page&text&sort&date&author&category&subject&exhibit',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', function (dataLoader) {
						return dataLoader.getPartsContext('blog', 'pages');
					}],
					searchResults: ['keywordSearcher', '$transition$', function (keywordSearcher, $transition$) {
						return keywordSearcher.getResultsForPage('search-blog', $transition$.params());
					}],
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
				params: {
					redirect: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					layout: {
						value: 'grid',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					size: {
						value: 20,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					text: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					sort: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					date: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					author: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					category: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					subject: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					exhibit: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
				},
			},
			{
				name: 'main.post',
				url: '/blog/{id}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						var postID = $transition$.params().id;
						// If postID is an empty string, then this must be the hub page.
						// Reject the current resolve and redirect to the main.blog state.
						if (!postID) {
							return $q.reject().catch(function () {
								$state.go('main.blog');
								return $q.reject('Removing trailing slash.');
							});
						} else {
							return dataLoader.getPartsContext(postID, 'posts')
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.presskits',
				url: '/presskits',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', function (dataLoader, $transition$) {
						return dataLoader.getPartsContext('', 'mediaroom')
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.presskitsid',
				url: '/presskits/{id}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						var pressID = $transition$.params().id;
						// If pressID is an empty string, then this must be a page.
						// Reject the current resolve and redirect to the pages route.
						if (!pressID) {
							return $q.reject().catch(function () {
								$state.go('main.presskits');
								return $q.reject('Removing trailing slash.');
							});
						} else {
							return dataLoader.getPartsContext(pressID, 'presskits')
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.mediaroom',
				url: '/mediaroom',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', function (dataLoader, $transition$) {
						return dataLoader.getPartsContext('', 'mediaroom');
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.mediaroomid',
				url: '/mediaroom/{id}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						var mediaID = $transition$.params().id;
						// If mediaID is an empty string, then this must be a page.
						// Reject the current resolve and redirect to the pages route.
						if (!mediaID) {
							return $q.reject().catch(function () {
								$state.go('main.mediaroom');
								return $q.reject('Removing trailing slash.');
							});
						} else {
							return dataLoader.getPartsContext(mediaID, 'mediaroom')
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.search',
				url: '/search?redirect&layout&size&page&text&sort&author&location&type&subject&category&audience',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', function (dataLoader) {
						return dataLoader.getPartsContext('search', 'pages');
					}],
					searchResults: ['keywordSearcher', '$transition$', function (keywordSearcher, $transition$) {
						return keywordSearcher.getResultsForPage('search-all', $transition$.params());
					}],
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
				params: {
					redirect: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					layout: {
						value: 'detail',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					size: {
						value: 20,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					text: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					sort: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					author: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					location: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					type: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					subject: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					category: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					audience: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
				}
			},
			{
				name: 'main.collections',
				url: '/collections?redirect&layout&size&page&text&department&collection&decade&creator&type&subject&place&images',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', function (dataLoader) {
						return dataLoader.getPartsContext('collections', 'pages');
					}],
					searchResults: ['keywordSearcher', '$transition$', function (keywordSearcher, $transition$) {
						return keywordSearcher.getResultsForPage('search-collections', $transition$.params());
					}],
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
				params: {
					redirect: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					layout: {
						value: 'detail',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					size: {
						value: 20,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					text: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					department: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					collection: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					decade: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					creator: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					type: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					subject: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					place: {
						value: [],
						type: 'string',
						array: true,
						dynamic: true,
					},
					images: {
						value: false,
						type: 'bool',
						dynamic: true,
					},
				},
			},
			{
				name: 'main.searchguide',
				url: '/collections/search-guide',
				templateUrl: 'app/search-guide.html'
			},
			{
				name: 'main.item',
				url: '/collections/item/{itemID}?page&fullscreen&view',
				component: 'collectionsItem',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					item: ['keywordSearcher', '$transition$', function (keywordSearcher, $transition$) {
						var itemID = $transition$.params().itemID;
						return keywordSearcher.getCollectionItem(itemID);
					}],
					/* Uncomment Below to get EAD data for item */
					// ead: ['keywordSearcher', 'item', function (keywordSearcher, item) {
					// 	var collectionId = item.ids[0];
					// 	return keywordSearcher.getItemEADFromSearch(collectionId);
					// }]
				},
				onEnter: ['$rootScope', 'item', function ($rootScope, item) {
					// Edge case item title
					if (/<I>/.test(item.label)) {
						item.label = String(item.label).replace('<I>', '').replace('</I>', '');
					}
					setPageTitleAndTheme($rootScope, item.label, 'MHS');
				}],
				params: {
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					fullscreen: {
						value: false,
						type: 'bool',
						dynamic: true,
						squash: true,
					},
					view: {
						value: 'default',
						type: 'string',
						dynamic: true,
						squash: true,
					},
				},
			},
			{
				name: 'main.firstID',
				url: '/{firstID}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', function (dataLoader, $transition$) {
						var routeID = $transition$.params().firstID;
						return dataLoader.getPartsContext(routeID, 'pages');
					}]
				},
				onEnter: ['$rootScope', 'data', '$transition$', function ($rootScope, data, $transition$) {
					var routeID = $transition$.params().firstID;
					// Four main pages do not have a pipe, but everything else does
					if (routeID === 'society') {
						$rootScope.pageTheme = data['mhs:owner'];
						$rootScope.pageTitle = data['og:title'] + ' | Find Yourself Here.';
					} else if (routeID === 'museum') {
						$rootScope.pageTheme = data['mhs:owner'];
						$rootScope.pageTitle = data['og:title'] + ' | Find Yourself Here.';
					} else if (routeID === 'library') {
						$rootScope.pageTheme = data['mhs:owner'];
						$rootScope.pageTitle = data['og:title'] + ' | Find Yourself Here.';
					} else if (routeID === 'memorial') {
						$rootScope.pageTheme = data['mhs:owner'];
						$rootScope.pageTitle = data['og:title'] + ' | Find Yourself Here.';
					} else {
						setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
					}
				}],
			},
			{
				name: 'main.firstIDsecondID',
				url: '/{firstID}/{secondID}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						// If secondID is an empty string, then this must be a parent page.
						// Reject the current resolve and redirect to the parent route.
						if (!$transition$.params().secondID) {
							return $q.reject().catch(function () {
								$state.go('main.firstID', {
									firstID: $transition$.params().firstID,
								});
								return $q.reject('Removing trailing slash.');
							});
						} else {
							var routeID = $transition$.params().firstID + '/' + $transition$.params().secondID;
							return dataLoader.getPartsContext(routeID, 'pages');
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
			{
				name: 'main.firstIDsecondIDthirdID',
				url: '/{firstID}/{secondID}/{thirdID}?size&page&text&filter&sort',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						// If thirdID is an empty string, then this must be a two level deep page.
						// Reject the current resolve and redirect to the main.firstIDsecondID route.
						if (!$transition$.params().thirdID) {
							return $q.reject().catch(function () {
								$state.go('main.firstIDsecondID', {
									firstID: $transition$.params().firstID,
									secondID: $transition$.params().secondID,
								});
								return $q.reject('Removing trailing slash.');
							});
						} else {
							var routeID = $transition$.params().firstID + '/' + $transition$.params().secondID +
								'/' + $transition$.params().thirdID;
							return dataLoader.getPartsContext(routeID, 'pages');
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
				params: {
					size: {
						value: 20,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					page: {
						value: 1,
						type: 'int',
						dynamic: true,
						squash: true,
					},
					text: {
						value: '',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					filter: {
						value: 'all',
						type: 'string',
						dynamic: true,
						squash: true,
					},
					sort: {
						value: 'identifier',
						type: 'string',
						dynamic: true,
					},
				},
			},
			{
				name: 'main.firstIDsecondIDthirdIDforthID',
				url: '/{firstID}/{secondID}/{thirdID}/{forthID}',
				component: 'part',
				resolve: {
					// These properties represent promises that must be successfully resolved
					// for the transition to succeed
					data: ['dataLoader', '$transition$', '$state', '$q', function (dataLoader, $transition$, $state, $q) {
						// If forthID is an empty string, then this must be a three level deep page.
						// Reject the current resolve and redirect to the main.firstIDsecondIDthirdTD route.
						if (!$transition$.params().thirdID) {
							return $q.reject().catch(function () {
								$state.go('main.firstIDsecondIDthirdID', {
									firstID: $transition$.params().firstID,
									secondID: $transition$.params().secondID,
									thirdID: $transition$.params().thirdID,
								});
								return $q.reject('Removing trailing slash.');
							});
						} else {
							var routeID = $transition$.params().firstID + '/' + $transition$.params().secondID +
								'/' + $transition$.params().thirdID + '/' + $transition$.params().forthID;
							return dataLoader.getPartsContext(routeID, 'pages');
						}
					}]
				},
				onEnter: ['$rootScope', 'data', function ($rootScope, data) {
					setPageTitleAndTheme($rootScope, data['og:title'], data['mhs:owner']);
				}],
			},
		];
		// Register each of the states with the $stateProvider service.
		states.forEach(function (state) {
			$stateProvider.state(state);
		});
		/**
		 * Helper function that is run every time a main route is entered. It updates the pageTitle and theme
		 * from the data retrieved from the server.
		 * @memberof uiRouterConfig
		 * @function setPageTitleAndTheme
		 * @param {object} $rootScope AngularJS root scope
		 * @param {string} title The new title of the page, default 'Missouri Historical Society'
		 * @param {string} theme The new theme for the page, default 'MHS'
		 */
		function setPageTitleAndTheme($rootScope, title, theme) {
			switch (theme) {
				case 'MHS':
					$rootScope.pageTheme = theme;
					$rootScope.pageTitle = title + ' | Missouri Historical Society';
					break;
				case 'LRC':
					$rootScope.pageTheme = theme;
					$rootScope.pageTitle = title + ' | Library and Research Center';
					break;
				case 'MHM':
					$rootScope.pageTheme = theme;
					$rootScope.pageTitle = title + ' | Missouri History Museum';
					break;
				case 'SM':
					$rootScope.pageTheme = theme;
					$rootScope.pageTitle = title + ' | Soldiers Memorial';
					break;
				case 'Off-Site':
					$rootScope.pageTheme = 'MHS';
					$rootScope.pageTitle = title + ' | Missouri Historical Society';
					break;
				case 'TBD':
					$rootScope.pageTheme = 'MHS';
					$rootScope.pageTitle = title + ' | Missouri Historical Society';
					break;
				default:
					$rootScope.pageTheme = 'MHS';
					$rootScope.pageTitle = 'Missouri Historical Society';
			}
		}
	}
})();