/**
* Make routes
* @namespace routerService
*/
'use strict';
app.provider('routerService', [
'$routeProvider', 'routeData',
function ($routeProvider, controllers) {
function encodeUri(val) {
return encodeURIComponent(val).
replace(/%40/g, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, '+');
}
/* Add the query params to the url. */
function urlParams(url, params) {
if (!params) {
return url;
}
var q = url.includes('?');
_.each(params, function (value, key) {
if (value == null)
return;
var add = function (v) {
if (angular.isObject(v))
v = angular.toJson(v);
url += (q ? '&' : '?') + encodeUri(key);
if (v !== true)
url += '=' + encodeUri(v);
q = true;
};
if (Array.isArray(value))
value.forEach(add);
else
add(value);
});
return url;
}
/* Apply a jsroute (from play's routeData) given the names of its arguments and optional data (or placeholders). */
function getRoute(route, argNames, data) {
var args;
var params = {};
if (!argNames)
argNames = [];
var ph = arguments.length < 3;
if (ph)
args = argNames.map(function (a) { return ':' + a; });
else if (data == null)
args = [];
else if (Array.isArray(data))
args = data;
else if (typeof data === 'object') {
args = argNames.map(function (k) {
if (k in data) {
var r = data[k];
delete data[k];
return r;
}
return null;
});
params = data;
} else
args = [data];
var url = route.route.apply(null, args);
if (ph)
return url;
for (var i = route.route.length; i < argNames.length && i < args.length; i++) {
params[argNames[i]] = args[i];
}
var q;
for (var p in params) {
if (!q) {
url += '?';
q = true;
}
url += p;
if (params[p] != null)
url += '=' + encodeUri(params[p]);
}
return url;
}
/* Add a route to $routeProvider and return a function to get a url given parameters. */
function makeRoute(route, argNames, handler) {
if (handler) {
var path = getRoute(route, argNames);
$routeProvider.when(path, handler);
if (path.includes('id/:segment'))
$routeProvider.when(path.replace('id/:segment', 'id'), handler);
}
return function (data, params) {
return urlParams(getRoute(route, argNames, data), params);
};
}
function checkPermission($q, f, perm) {
return f.then(function (obj) {
return obj.checkPermission(perm) ? obj :
$q.reject({status: 403});
});
}
var routes = {};
routes.index = makeRoute(controllers.viewRoot, [], {
controller: 'site/home',
templateUrl: 'site/home.html',
resolve: {
volume: [
'modelService', 'constantService',
function (models, constants) {
if (constants.sandbox) return; else
return models.Volume.get(9)
.catch(function() {
return {};
});
}
],
tags: [
'modelService',
function (models) {
return models.Tag.top();
}
],
activity: [
'modelService',
function (models) {
return models.siteActivity();
}
]
},
reloadOnSearch: false,
});
//
routes.login = makeRoute(controllers.viewLogin, [], {
controller: 'party/login',
templateUrl: 'party/login.html',
reloadOnSearch: false
});
//
routes.register = makeRoute(controllers.viewRegister, [], {
controller: 'party/register',
templateUrl: 'party/register.html',
resolve: {
user: [
'modelService',
function (models) {
if (models.Login.isLoggedIn())
return models.Login.user.get(['parents']);
else
return models.Login.user;
}
],
token: function () {},
},
reloadOnSearch: false
});
//
routes.password = makeRoute(controllers.viewPasswordReset, [], {
controller: 'party/reset',
templateUrl: 'party/reset.html',
reloadOnSearch: false
});
//
makeRoute(controllers.viewLoginToken, ['id'], {
controller: 'party/register',
templateUrl: 'party/register.html',
resolve: {
token: [
'modelService', '$route',
function (models, $route) {
return models.Login.getToken($route.current.params.id, $route.current.params.auth);
}
],
user: [
'modelService', function (models) {
return models.Login.user;
}
],
},
reloadOnSearch: false
});
//
routes.volumeSearch = makeRoute(controllers.viewVolumeSearch, [], {
controller: 'volume/search',
templateUrl: 'volume/search.html',
resolve: {
volumes: [
'pageService', function (page) {
return page.models.Volume.search(page.$route.current.params);
}
]
},
});
// Solr search
routes.search = makeRoute(controllers.viewSearch, [], {
controller: 'site/search',
templateUrl: "site/search.html",
resolve: {
parties: [
'$route', 'searchService',
function ($route, search) {
return search.Party.search($route.current.params);
}
],
volumes: [
'$route', 'searchService',
function ($route, search) {
return search.Volume.search($route.current.params);
}
]
},
reloadOnSearch: true
});
routes.profile = makeRoute(controllers.viewProfile, [], {
controller: 'party/profile',
templateUrl: 'party/profile.html',
resolve: {
party: [
'modelService', function (models) {
return models.Login.user.get({parents:true, children:true, volumes:'access'});
}
]
},
reloadOnSearch: false,
});
routes.party = makeRoute(controllers.viewParty, ['id'], {
controller: 'party/view',
templateUrl: 'party/view.html',
resolve: {
party: [
'pageService', function (page) {
return page.models.Party.get(page.$route.current.params.id, ['parents', 'children', 'access']);
}
],
},
reloadOnSearch: false,
});
//
routes.partyEdit = makeRoute(controllers.viewPartyEdit, ['id'], {
controller: 'party/edit',
templateUrl: 'party/edit.html',
resolve: {
party: [
'pageService', function (page) {
return checkPermission(page.$q,
page.models.Party.get(page.$route.current.params.id, ['parents', 'children']),
page.permission.EDIT);
}
],
},
reloadOnSearch: false,
});
routes.profileEdit = makeRoute(controllers.viewProfileEdit, [], {
controller: 'party/edit',
templateUrl: 'party/edit.html',
resolve: {
party: [
'modelService', function (models) {
return models.Login.user.get(['parents', 'children']);
}
],
},
reloadOnSearch: false,
});
routes.partyActivity = makeRoute(controllers.viewPartyActivity, ['id'], {
controller: 'party/activity',
templateUrl: 'party/activity.html',
resolve: {
activity: [
'pageService', function (page) {
return page.models.Party.get(page.$route.current.params.id).then(function (p) {
return p.getActivity().then(function (a) {
a.party = p;
return a;
});
});
}
],
}
});
routes.partySearch = makeRoute(controllers.viewPartySearch, [], {
controller: 'party/search',
templateUrl: 'party/search.html',
resolve: {
parties: [
'pageService', function (page) {
return page.models.Party.search(page.$route.current.params);
}
]
},
});
var volumeEdit = {
controller: 'volume/edit',
templateUrl: 'volume/edit.html',
resolve: {
volume: [
'pageService', function (page) {
if (!('id' in page.$route.current.params)) {
return page.models.Login.user.get({parents:'authorization'})
.then(function () {
return undefined;
});
}
return checkPermission(page.$q,
page.models.Volume.get(page.$route.current.params.id,
{access:true, citation:true, links:true, top:true, funding:true, records:true, containers:'all', tags:'keyword', metrics:true, excerpts:true}),
page.permission.EDIT)
.then(function (volume) {
return volume.top.getSlot(volume.top.segment, ['assets'])
.then(function () {
return volume;
});
});
}
],
},
reloadOnSearch: false,
};
routes.volumeCreate = makeRoute(controllers.viewVolumeCreate, ['owner'], volumeEdit);
routes.volumeEdit = makeRoute(controllers.viewVolumeEdit, ['id'], volumeEdit);
routes.volume = makeRoute(controllers.viewVolume, ['id'], {
controller: 'volume/view',
templateUrl: 'volume/view.html',
resolve: {
volume: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.id,
{access:true, citation:true, links:true, funding:true, top:true, tags:true, excerpts:true, comments:true, records:true, containers:'all', metrics:true, state:true});
}
]
},
reloadOnSearch: false,
});
routes.volumeDescription = makeRoute(controllers.viewVolumeDescription, ['id'], {
controller: 'volume/zip',
templateUrl: 'volume/zip.html',
resolve: {
volume: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.id, {containers:'assets',top:true});
}
],
slot: function() {
},
}
});
routes.volumeCSV = makeRoute(controllers.csvVolume, ['id'], {
controller: 'volume/csv',
templateUrl: 'volume/csv.html',
resolve: {
volume: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.id);
}
],
}
});
routes.volumeActivity = makeRoute(controllers.viewVolumeActivity, ['id'], {
controller: 'volume/activity',
templateUrl: 'volume/activity.html',
resolve: {
activity: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.id).then(function (v) {
return v.getActivity().then(function (a) {
a.volume = v;
return a;
});
});
}
],
}
});
routes.slotZip = makeRoute(controllers.zipSlot, ['vid', 'id'], {
controller: 'volume/zip',
templateUrl: 'volume/zip.html',
resolve: {
slot: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.vid).then(function(v) {
return v.getSlot(page.$route.current.params.id, page.$route.current.params.segment, ['assets']);
});
}
],
volume: function () {
},
}
});
routes.slotOrigZip = makeRoute(controllers.zipOrigSlot, ['vid', 'id'], {
controller: 'volume/zip',
templateUrl: 'volume/zip.html',
resolve: {
slot: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.vid).then(function(v) {
return v.getSlot(page.$route.current.params.id, page.$route.current.params.segment, ['assets']);
});
}
],
volume: function () {
},
}
});
routes.slotActivity = makeRoute(controllers.viewSlotActivity, ['vid', 'id'], {
controller: 'volume/slotActivity',
templateUrl: 'volume/slotActivity.html',
resolve: {
activity: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.vid).then(function (v) {
return v.getSlot(page.$route.current.params.id).then(function (s) {
return s.getActivity().then(function (a) {
a.slot = s;
return a;
});
});
});
}
],
}
});
function slotRoute(edit) { return {
controller: 'volume/slot',
templateUrl: 'volume/slot.html',
resolve: {
slot: [
'pageService', function (page) {
var r = page.models.Volume.get(page.$route.current.params.vid, edit ? ['records', 'metrics'] : ['metrics']);
return (edit ? checkPermission(page.$q, r, page.permission.EDIT) : r)
.then(function (volume) {
return volume.getSlot(page.$route.current.params.id, edit ? '-' : page.$route.current.params.segment,
['records', 'assets', 'excerpts', 'tags', 'comments']);
});
},
],
edit: function () {
return edit;
}
},
reloadOnSearch: false,
}; }
routes.slotEdit = makeRoute(controllers.viewSlotEdit, ['vid', 'id'], slotRoute(true));
routes.slot = makeRoute(controllers.viewSlot, ['vid', 'id', 'segment'], slotRoute(false));
routes.slotAsset = makeRoute(controllers.viewAssetSegment, ['vid', 'cid', 'segment', 'id'], {
controller: 'asset/view',
templateUrl: 'asset/view.html',
resolve: {
asset: [
'pageService', function (page) {
return page.models.Volume.get(page.$route.current.params.vid)
.then(function (volume) {
return volume.getAsset(page.$route.current.params.id, page.$route.current.params.cid, page.$route.current.params.segment, ['container', 'asset']);
});
},
]
},
reloadOnSearch: false,
});
routes.helpFormats = makeRoute(controllers.viewFormats, [], {
controller: 'asset/formats',
templateUrl: 'asset/formats.html',
reloadOnSearch: false,
});
routes.partyAvatar = makeRoute(controllers.partyAvatar, ['id', 'size']);
routes.volumeThumb = makeRoute(controllers.thumbVolume, ['id', 'size']);
routes.assetThumb = makeRoute(controllers.thumbAssetSegment, ['cid', 'segment', 'id', 'size']);
routes.slotThumb = makeRoute(controllers.thumbSlot, ['id','cid','segment', 'size']);
routes.assetDownload = makeRoute(controllers.downloadAssetSegment, ['cid', 'segment', 'id', 'inline']);
routes.rawAssetDownload = makeRoute(controllers.downloadAsset, ['id', 'inline']);
routes.rawAssetThumb = makeRoute(controllers.thumbAsset, ['id', 'size']);
routes.volumeZip = makeRoute(controllers.zipVolume, ['id']);
routes.volumeZipOrig = makeRoute(controllers.zipOrigVolume, ['id']);
$routeProvider.otherwise('/');
//
this.$get = [
'$rootScope', '$location', '$http', '$cacheFactory', 'constantService', 'analyticService',
function ($rootScope, $location, $http, $cacheFactory, constants, analytics) {
var router = angular.extend({
controllers: controllers,
prev: '/'
}, routes);
/* Simple wrapper to $http(route(...)).
* Non-object arguments (or an initial array) are passed to route.
* The next argument is passed as data (POST) or params.
* An additional argument is passed as extra config to $http.
*/
router.http = function (route, args/*...*/) {
var i;
if (Array.isArray(args))
i = 2;
else {
for (i = 1; i < arguments.length; i ++)
if (angular.isObject(arguments[i]))
break;
args = Array.prototype.slice.call(arguments, 1, i);
}
var r = {
method: route.method,
url: route.route.apply(null, args),
headers: {}
};
if (i < arguments.length) {
if (r.method === 'POST' || r.method === 'PUT')
r.data = arguments[i];
else
r.url = urlParams(r.url, arguments[i]); // Workaround for ; escaping
if (++i < arguments.length)
angular.extend(r, arguments[i]);
}
if (r.data instanceof FormData) {
if (!('transformRequest' in r))
r.transformRequest = angular.identity;
// Not sure why we do this but it seems to be necessary:
if (!('Content-Type' in r.headers))
r.headers['Content-Type'] = undefined;
}
var cache;
/* try to guess (conservatively) if this request is cached: */
if (r.method === 'GET' || r.method === 'JSONP') {
cache = r.cache || $http.defaults.cache && $cacheFactory('$http');
if (cache && !r.params)
cache = cache.get(r.url);
} else if (router.http.csverf)
r.headers['x-csverf'] = router.http.csverf;
if (!cache) {
var a = analytics.dump();
if (a)
r.headers.Analytics = a;
}
return $http(r);
};
var prev;
$rootScope.$on('$locationChangeStart', function (event, to, from) {
router.prev = prev;
prev = from;
});
$rootScope.$on('$routeChangeStart', function () {
router.prev = prev;
});
router.back = function () {
if (!router.prev || router.prev === $location.absUrl())
$location.url('/');
else
$location.$$parse(router.prev);
};
return router;
}
];
}
]);