Created
December 15, 2017 15:40
-
-
Save scottlepp/d27b274845f321b38a8ef8f24d71d3f4 to your computer and use it in GitHub Desktop.
Track Login Event
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getBrowser() { | |
"use strict"; | |
var tem, ua = navigator.userAgent, | |
M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; | |
return /trident/i.test(M[1]) ? (tem = /\brv[ :]+(\d+)/g.exec(ua) || [], "IE " + (tem[1] || "")) : "Chrome" === M[1] && (tem = ua.match(/\bOPR\/(\d+)/), null !== tem) ? "Opera " + tem[1] : (M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, "-?"], null !== (tem = ua.match(/version\/(\d+)/i)) && M.splice(1, 1, tem[1]), { | |
name: M[0], | |
version: M[1] | |
}) | |
} | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
var n = function() { | |
function t(t) { | |
t.debugEnabled(!0) | |
} | |
return t.$inject = ["$logProvider"], t | |
}(); | |
t.Config = n | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
var n = function() { | |
function t(t) { | |
t.debug("runBlock end") | |
} | |
return t.$inject = ["$log"], t | |
}(); | |
t.RunBlock = n | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools", []).config(t.Config).run(t.RunBlock).constant("config", config) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.appearance", []) | |
}(n = t.appearance || (t.appearance = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})), angular.module("vs.tools.appearance").factory("appearanceResource", ["$http", "$q", function(t, n) { | |
"use strict"; | |
function r() { | |
return t.get(e).then(function(t) { | |
return t.data | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
function o(n) { | |
return t.post(s, { | |
docActions: n | |
}).then(function(t) { | |
return t | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
var e = config.root + "api/rest/appearance", | |
s = config.root + "api/rest/appearance/actions"; | |
return { | |
fetch: function() { | |
return r() | |
}, | |
saveActions: function(t) { | |
return o(t) | |
} | |
} | |
}]); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.catalog", []) | |
}(n = t.catalog || (t.catalog = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})), angular.module("vs.tools.catalog").factory("catalogResource", ["$http", "$q", function(t, n) { | |
"use strict"; | |
function r() { | |
return t.get(e).then(function(t) { | |
return t.data.servers | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
function o(o) { | |
return r().then(function(r) { | |
var o = []; | |
return r.forEach(function(n) { | |
if (angular.isDefined(n.url)) { | |
var r = n.url + s, | |
e = t.get(r, { | |
withCredentials: !1 | |
}).then(function(t) { | |
return t | |
}); | |
o.push(e) | |
} | |
}), n.all(o).then(function(t) { | |
return t | |
}, function(t) { | |
return t | |
}) | |
}) | |
} | |
var e = config.root + "api/rest/index/config/federation.json", | |
s = "api/rest/i18n/field/location.json"; | |
return { | |
fetch: r, | |
loadRemoteLocations: o | |
} | |
}]); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.displayConfig", []) | |
}(n = t.displayConfig || (t.displayConfig = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})), angular.module("vs.tools.displayConfig").factory("displayConfigResource", ["$http", function(t) { | |
"use strict"; | |
function n() { | |
var t = i + "list"; | |
return t += "?rand=" + Math.random() | |
} | |
function r(t) { | |
var n = i + t; | |
return n += "?rand=" + Math.random() | |
} | |
function o() { | |
return t.get(n()).then(function(t) { | |
return t | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
function e(n) { | |
return t.get(r(n)).then(function(t) { | |
return t | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
function s(n) { | |
return t.delete(r(n)).then(function(t) { | |
return t | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
function a(n) { | |
return t.post(i, n).then(function(t) { | |
return t | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
var i = config.root + "api/rest/display/config/"; | |
return { | |
getDisplayConfigs: function() { | |
return o() | |
}, | |
getDisplayConfig: function(t) { | |
return e(t) | |
}, | |
deleteDisplayConfig: function(t) { | |
return s(t) | |
}, | |
saveDisplayConfig: function(t) { | |
return a(t) | |
} | |
} | |
}]); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
var n = function() { | |
function t(t, n) { | |
this.config = t, this.$http = n | |
} | |
return t.isString = function(t) { | |
return "string" == typeof t || t instanceof String | |
}, t.getInstance = function(n, r) { | |
return new t(n, r) | |
}, t.prototype.toMap = function(t, n) { | |
var r = {}; | |
return n.forEach(function(n) { | |
r[n[t]] = n | |
}), r | |
}, t.prototype.toStringMap = function(t) { | |
var n = {}; | |
return t.forEach(function(t) { | |
n[t] = t | |
}), n | |
}, t.prototype.pluck = function(t, n, r) { | |
var o = []; | |
return t.forEach(function(t) { | |
r && r(t) ? o.push(t[n]) : angular.isUndefined(r) && o.push(t[n]) | |
}), o | |
}, t.prototype.postForm = function(t, n) { | |
var r = this.config.root + t; | |
return this.$http({ | |
method: "POST", | |
url: r, | |
data: n, | |
withCredentials: !0, | |
headers: { | |
"Content-Type": "application/x-www-form-urlencoded" | |
} | |
}) | |
}, t.prototype.parseQueryString = function(t) { | |
var n, r = t.slice(1).split("&"), | |
o = {}; | |
return r.forEach(function(t) { | |
n = t.split("="), o[n[0]] = decodeURIComponent(n[1] || "") | |
}), JSON.parse(JSON.stringify(o)) | |
}, t.prototype.postJson = function(t, n, r) { | |
return this.$http({ | |
method: "POST", | |
url: config.root + "api/rest/" + n + "/" + r + ".json", | |
data: t, | |
headers: { | |
"Content-Type": "application/json" | |
} | |
}) | |
}, t | |
}(); | |
t.Sugar = n | |
}(n = t.util || (t.util = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
var n = function() { | |
function t(t) { | |
var n = this; | |
this.sugar = t, this.fetch = function(r) { | |
var o = r || "name,stype,category,docs,disp_en,sortable,filterable,tableable,displayable,editable"; | |
return t.postForm("solr/fields/select?rand=" + Math.random(), n.getFieldsParams(o)).then(function(t) { | |
return n.ensureTagsFieldExist(t.data.response.docs), t.data.response.docs | |
}) | |
}, this.ensureTagsFieldExist = function(t) { | |
for (var n = !1, r = t.length - 1; r >= 0; r--) | |
if ("tag_tags" === t[r].name) { | |
n = !0; | |
break | |
} | |
n || t.push({ | |
category: "TEXT", | |
disp_en: "Tags", | |
displayable: !0, | |
docs: 0, | |
filterable: !0, | |
name: "tag_tags", | |
sortable: !1, | |
stype: "string", | |
tableable: !1 | |
}) | |
}, this.fetchHydrationStats = function(r) { | |
return n.fetch().then(function(o) { | |
var e = t.pluck(o, "name", function(t) { | |
return 0 !== t.name.indexOf("_") && t.docs > 0 | |
}); | |
return t.postForm("solr/v0/select?" + r, n.getStatsParams(e)).then(function(t) { | |
var r = t.data.facet_counts.facet_fields, | |
e = t.data.response.numFound; | |
return n.applyHydration(r, o, e), o | |
}) | |
}) | |
} | |
} | |
return t.$inject = ["sugar"], t.prototype.getFieldsParams = function(t) { | |
return "q=*:*&fl=" + t + "&rows=100000&sort=name%20asc&wt=json&rand=" + Math.random() | |
}, t.prototype.getStatsParams = function(t) { | |
return "facet=true&facet.limit=100000&facet.mincount=100&rows=0&wt=json&facet.field=" + t.join("&facet.field=") + "&rand=" + Math.random() | |
}, t.prototype.applyHydration = function(t, n, r) { | |
for (var o, e, s = 0; s < n.length; s++) o = t[n[s].name], o && o.length > 0 && (n[s].id = n[s].name, e = this.getCount(o), n[s].hydration = e / r * 100); | |
return s | |
}, t.prototype.getCount = function(t) { | |
for (var n = 0, r = 1; r < t.length; r += 2) n += t[r]; | |
return n | |
}, t.refName = "fieldsResource", t | |
}(); | |
t.FieldsResource = n | |
}(n = t.fields || (t.fields = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.fields", ["vs.tools.util"]).service(t.FieldsResource.refName, t.FieldsResource) | |
}(n = t.fields || (t.fields = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.filters", []).filter("replaceString", function() { | |
return function(t, n, r) { | |
return t.replace(new RegExp(n, "g"), r) | |
} | |
}) | |
}(n = t.filters || (t.filters = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.savedSearch", ["vs.tools.util"]) | |
}(n = t.savedSearch || (t.savedSearch = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})), angular.module("vs.tools.savedSearch").factory("savedSearchResource", ["$http", "sugar", function(t, n) { | |
"use strict"; | |
function r(t) { | |
return n.postJson(t, "display", "ssearch") | |
} | |
function o(t) { | |
var n = 150, | |
r = config.root + "solr/ssearch/select?"; | |
return r += "rows=" + n + "&rand=" + Math.random(), r += "&fl=id,title,description,owner,path,share,query,config,order,saved,private,view,_version_,config_title:[configTitle],param*,labels,display_override", r += "&wt=json&json.wrf=JSON_CALLBACK", angular.isDefined(t) && (r += "&fq=id:" + t), r | |
} | |
function e(n) { | |
return t.jsonp(o(n)).then(function(t) { | |
return t.data.response.docs | |
}, function(t) { | |
return console.log(t), t | |
}) | |
} | |
return { | |
getSavedSearches: function() { | |
return e() | |
}, | |
fetch: function(t) { | |
return e(t).then(function(t) { | |
return t[0] | |
}) | |
}, | |
saveSearch: function(t, n) { | |
return r(t) | |
}, | |
deleteSearch: function(n) { | |
return t.delete(config.root + "api/rest/display/ssearch/" + n).then(function() {}) | |
}, | |
wipe: function() { | |
return t.delete(config.root + "api/rest/display/ssearch/wipe") | |
}, | |
restore: function() { | |
return n.postForm("api/rest/display/restore", "") | |
}, | |
order: function(t, n, r) { | |
var o = ""; | |
null !== n && (o += "before=" + n), "" !== o && (o += "&"), null !== r && (o += "after=" + r) | |
}, | |
fetchLabels: function() { | |
var n = config.root + "solr/ssearch/select?rows=0&facet=true&facet.field=labels&wt=json&r=" + (new Date).getTime(); | |
return t.get(n).then(function(t) { | |
return t.data.facet_counts.facet_fields.labels | |
}, function() { | |
return [] | |
}) | |
} | |
} | |
}]); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
var n = function() { | |
function t(t, n, r) { | |
var o = this; | |
this.config = t, this.$http = n, this.$q = r, this.fields = null, this.removePrefixHash = {}; | |
var e = ["fs_", "ft_", "fh_", "fi_", "fl_", "fd_", "ff_", "fu_", "fp_", "fy_", "fm_", "fb_", "tag_", "meta_", "fss_", "grp_"]; | |
e.forEach(function(t) { | |
o.removePrefixHash[t] = !0; | |
var n = t.substring(1, 2), | |
r = t.replace("_", n + "_"); | |
o.removePrefixHash[r] = !0 | |
}) | |
} | |
return t.$inject = ["config", "$http", "$q"], t.prototype.load = function() { | |
var t = this, | |
n = this.config.root + "api/rest/i18n/fields/standard.json"; | |
return this.fields ? this.$q.when() : this.$http.get(n).then(function(n) { | |
return t.fields = n.data, n.data | |
}) | |
}, t.prototype.translateField = function(t) { | |
var n = t.indexOf("_"); | |
if (n > -1) { | |
var r = t.substring(0, n + 1); | |
this.removePrefixHash[r] && (t = t.replace(r, "")) | |
} | |
var o = this.fields.FIELD[t]; | |
return angular.isDefined(o) ? o : this.classify(t) | |
}, t.prototype.classify = function(t) { | |
return t = t.replace(/_/g, " "), t.replace(/\w\S*/g, function(t) { | |
return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase() | |
}) | |
}, t | |
}(); | |
t.Translator = n | |
}(n = t.translate || (t.translate = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.translate", []).factory("translator", ["config", "$http", "$q", function(n, r, o) { | |
return new t.Translator(n, r, o) | |
}]).constant("config", config) | |
}(n = t.translate || (t.translate = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var vs; | |
! function(t) { | |
var n; | |
! function(t) { | |
var n; | |
! function(t) { | |
"use strict"; | |
angular.module("vs.tools.util", []).factory("sugar", ["config", "$http", function(n, r) { | |
return t.Sugar.getInstance(n, r) | |
}]) | |
}(n = t.util || (t.util = {})) | |
}(n = t.tools || (t.tools = {})) | |
}(vs || (vs = {})); | |
var browser = getBrowser(); | |
if ("IE" === browser.name || "MSIE" === browser.name) { | |
var globalHtml = $("html"), | |
version = parseInt(browser.version); | |
version < 9 && globalHtml.addClass("lt-ie9"), version < 8 && globalHtml.addClass("lt-ie8"), version < 7 && globalHtml.addClass("lt-ie7") | |
} | |
angular.element(document).ready(function() { | |
"use strict"; | |
var slash = config.root.charAt(config.root.length - 1); | |
if ("/" !== slash) return void alert(NaN) | |
}), angular.module("portalApp", ["ngResource", "ngSanitize", "ngTable", "ngTableResizableColumns", "ngAria", "angularSpinner", "ui.router", "ui.bootstrap", "ui.slider", "ui.select2", "ui.sortable", "LocalStorageModule", "cart", "taskRunner", "voyager.config", "voyager.security", "voyager.filters", "voyager.map", "voyager.util", "voyager.modal", "voyager.layout", "voyager.home", "voyager.search", "voyager.results", "voyager.details", "voyager.tagging", "voyager.component", "tree.directive", "angulartics", "angulartics.google.analytics", "voyager.common.featured"]).factory("httpRequestInterceptor", function($analytics, $injector, $q, $log) { | |
"use strict"; | |
return { | |
response: function(response) { | |
var err = response.headers("x-access-token-error"); | |
if (!_.isEmpty(err)) { | |
$log.error("Error with JWT Token", err); | |
var $state = $injector.get("$state"); | |
$state.go("login") | |
} | |
return response | |
}, | |
responseError: function(response) { | |
if (419 === response.status) { | |
$log.error("token timed out"); | |
var $state = $injector.get("$state"); | |
$state.go("login") | |
} else { | |
var url = "unknown"; | |
response.config && (url = response.config.url), $analytics.eventTrack("error", { | |
category: "http", | |
label: url, | |
value: response.status | |
}) | |
} | |
return $q.reject(response) | |
} | |
} | |
}), angular.module("portalApp").config(function($stateProvider, $httpProvider, $urlRouterProvider, $analyticsProvider, $locationProvider, $logProvider, toastrConfig) { | |
"use strict"; | |
function _loadIfAllowed(authService, $q, configLoader, $location) { | |
return authService.getPrivileges().then(function() { | |
return authService.hasPermission("view") ? configLoader.load($location.search().disp, $location.search().all) : $q.reject("Not Authorized") | |
}) | |
} | |
function _canProcess(authService, $q) { | |
return authService.getPrivileges().then(function() { | |
return authService.hasPermission("process") ? $q.when({}) : $q.reject("Not Authorized") | |
}) | |
} | |
$locationProvider.html5Mode(!0), $logProvider.debugEnabled(!1), $stateProvider.state("search", { | |
url: "/search?fq&q&vw&place", | |
reloadOnSearch: !1, | |
views: { | |
"": { | |
templateUrl: "src/search/search.html" | |
}, | |
"filters@search": { | |
templateUrl: "src/filters/filters.html", | |
controller: "FiltersCtrl" | |
}, | |
"card-results@search": { | |
templateUrl: "src/results/card-results.html" | |
}, | |
"table-results@search": { | |
templateUrl: "src/results/table-results.html" | |
}, | |
"grid-results@search": { | |
templateUrl: "src/results/grid-results.html" | |
}, | |
"selected-filters@search": { | |
templateUrl: "src/filters/selected-filters.html", | |
controller: "SelectedFiltersCtrl" | |
} | |
}, | |
resolve: { | |
load: function(configLoader, $location, $q, authService) { | |
return _loadIfAllowed(authService, $q, configLoader, $location) | |
} | |
} | |
}).state("home", { | |
url: "/home", | |
templateUrl: "src/home/home.html", | |
resolve: { | |
load: function(configLoader, $location, $q, authService) { | |
return config.homepage.showHomepage === !0 ? _loadIfAllowed(authService, $q, configLoader, $location) : $q.reject("Not Visible") | |
} | |
} | |
}).state("details", { | |
reloadOnSearch: !0, | |
url: "/show?id&disp&shard", | |
views: { | |
"": { | |
templateUrl: "src/details/details.html" | |
}, | |
"preview@details": { | |
templateUrl: "src/details/preview.html" | |
} | |
}, | |
resolve: { | |
load: function(detailConfig, $location, $q, authService) { | |
return _loadIfAllowed(authService, $q, detailConfig, $location) | |
} | |
} | |
}).state("login", { | |
url: "/login", | |
templateUrl: "common/security/login.html", | |
controller: "AuthPageCtrl", | |
resolve: { | |
load: function($q, authService) { | |
return authService.loadPrivileges() | |
} | |
} | |
}).state("queue", { | |
url: "/queue", | |
templateUrl: "src/cart/cart.html", | |
resolve: { | |
load: function($q, authService) { | |
return _canProcess(authService, $q) | |
} | |
} | |
}).state("tasks", { | |
url: "/tasks", | |
templateUrl: "src/taskrunner/tasks.html", | |
resolve: { | |
load: function($q, authService) { | |
return _canProcess(authService, $q) | |
} | |
} | |
}).state("task", { | |
url: "/task?type", | |
templateUrl: "src/taskrunner/task.html", | |
params: { | |
task: {}, | |
type: "" | |
}, | |
resolve: { | |
load: function($q, authService, configLoader, $location, translateService) { | |
return _canProcess(authService, $q).then(function() { | |
return configLoader.prepare().then(function() { | |
translateService.init() | |
}) | |
}) | |
} | |
} | |
}).state("history", { | |
url: "/history", | |
templateUrl: "src/jobs/view-jobs.html", | |
resolve: { | |
load: function($q, authService) { | |
return _canProcess(authService, $q) | |
} | |
} | |
}).state("status", { | |
url: "/status?id", | |
templateUrl: "src/taskrunner/status.html", | |
resolve: { | |
load: function($q, authService) { | |
return _canProcess(authService, $q) | |
} | |
} | |
}).state("chart", { | |
url: "/chart", | |
templateUrl: "src/chart/chart.html" | |
}).state("links", { | |
url: "/links?page", | |
templateUrl: "src/bot/bot-page.html" | |
}), $urlRouterProvider.otherwise(function($injector) { | |
$injector.invoke(function($state, config) { | |
config.homepage.showHomepage === !0 ? $state.go("home") : $state.go("search") | |
}) | |
}), $httpProvider.defaults.withCredentials = !0, $httpProvider.interceptors.push("httpRequestInterceptor"), $analyticsProvider.registerPageTrack(function() { | |
window.piTracker && window.piTracker() | |
}), $analyticsProvider.registerEventTrack(function(action, properties) { | |
if (config.trackAnalytics) { | |
properties.action = action; | |
var analyticsUrl = config.root + "api/rest/analytics/track"; | |
$.ajax({ | |
type: "POST", | |
url: analyticsUrl, | |
data: JSON.stringify(properties), | |
success: function() {}, | |
contentType: "application/json", | |
dataType: "json" | |
}) | |
} | |
}), angular.extend(toastrConfig, { | |
closeButton: !0, | |
positionClass: "toast-top-center", | |
allowHtml: !0 | |
}) | |
}).constant("config", config), angular.module("portalApp").run(function($rootScope, $location, authService, $state, config, $timeout) { | |
"use strict"; | |
_.mixin(_.str.exports()), _.isEmpty(config.homepage.bannerHTML) || ($rootScope.hasBanner = !0, $rootScope.banner = config.homepage.bannerHTML, $timeout(function() { | |
var $topBanner = $("#top-banner"); | |
$topBanner.height($topBanner.children(":first").height()) | |
})), "true" === $location.search().widget && ($rootScope.isWidget = !0), $rootScope.title = config.title, $rootScope.footer = config.homepage.footerHTML, 0 !== $rootScope.footer.indexOf("<li>") && ($rootScope.footer = "<li>" + $rootScope.footer + "</li>"), $rootScope.$on("searchEvent", function(event, args) { | |
$rootScope.$broadcast("doSearch", args) | |
}), $rootScope.$on("bboxChangeEvent", function(event, args) { | |
$rootScope.$broadcast("updateBBox", args) | |
}), $rootScope.$on("saveSearchSuccess", function(event, args) { | |
$rootScope.$broadcast("updateSearchSaveStatus", args) | |
}), $rootScope.$on("filterEvent", function(event, args) { | |
$rootScope.$broadcast("filterChanged", args) | |
}), $rootScope.$on("removeFilterEvent", function(event, args) { | |
$rootScope.$broadcast("removeFilter", args) | |
}), $rootScope.$on("clearSearchEvent", function(event, args) { | |
$rootScope.$broadcast("clearSearch", args) | |
}), $rootScope.$on("clearBboxEvent", function(event, args) { | |
$rootScope.$broadcast("clearBbox", args) | |
}), $rootScope.$on("changeViewEvent", function(event, args) { | |
$rootScope.$broadcast("changeView", args) | |
}), $rootScope.$on("searchComplete", function(event, args) { | |
$rootScope.$broadcast("searchResults", args) | |
}), $rootScope.$on("addAllToCartEvent", function(event, args) { | |
$rootScope.$broadcast("addAllToCart", args) | |
}), $rootScope.$on("removeAllCartEvent", function(event, args) { | |
$rootScope.$broadcast("removeAllCart", args) | |
}), $rootScope.$on("resultHoverEvent", function(event, args) { | |
$rootScope.$broadcast("resultHover", args) | |
}), $rootScope.$on("searchDrawingTypeChanged", function(event, args) { | |
$rootScope.$broadcast("updateDrawingTool", args) | |
}), $rootScope.$on("drawingToolChanged", function(event, args) { | |
$rootScope.$broadcast("updateSearchDrawingType", args) | |
}), $rootScope.$on("searchTypeChanged", function(event, args) { | |
$rootScope.$broadcast("updateSearchType", args) | |
}), $rootScope.$on("selectedDrawingTypeChanged", function(event, args) { | |
$rootScope.$broadcast("drawingTypeChanged", args) | |
}), $rootScope.$on("$stateChangeError", function(e, toState, toParams, fromState, fromParams, error) { | |
"Not Authorized" === error ? $state.go("login") : "Not Visible" === error ? $state.go("search") : "bot" === error && $state.go("bot") | |
}), $rootScope.$on("taskStatusEvent", function(event, args) { | |
$rootScope.$broadcast("taskStatusChanged", args) | |
}), $rootScope.$on("expandedQueryToggle", function(event, args) { | |
$rootScope.$broadcast("expandedQueryToggled", args) | |
}), L.Icon.Default.imagePath = "assets/img" | |
}), angular.module("voyager.util", []), angular.module("voyager.util").factory("loading", function($timeout) { | |
"use strict"; | |
var spinner, isLoading = !1, | |
delayedShow = function(element) { | |
if (isLoading && !spinner) { | |
spinner = new Spinner({ | |
radius: 3 | |
}).spin(); | |
var indicatorDiv = $(element); | |
indicatorDiv.append(spinner.el) | |
} | |
}; | |
return { | |
show: function(element) { | |
isLoading = !0, $timeout(function() { | |
delayedShow(element) | |
}, 250) | |
}, | |
done: function() { | |
isLoading = !1, spinner && (spinner.stop(), spinner = null) | |
} | |
} | |
}), angular.module("voyager.util").factory("sugar", function($http) { | |
"use strict"; | |
function _convertExtent(val) { | |
if (val.indexOf("bbox") >= 0) { | |
val = val.replace(/["\)]/g, ""); | |
var bboxInfo = val.split("("), | |
mode = bboxInfo[0].replace("Is", "").toUpperCase(); | |
mode = mode.replace("BBOX:", ""); | |
var bbox = bboxInfo[1]; | |
return "bbox=" + bbox + "/bbox.mode=" + mode | |
} | |
return val | |
} | |
function _cleanSlash(val) { | |
var newVal = val.replace(/\\/g, ""); | |
return newVal = newVal.replace(/\//g, "\\/"), newVal = _convertExtent(newVal) | |
} | |
function _removeFunk(params) { | |
angular.isDefined(params.fq) && (angular.isArray(params.fq) ? $.each(params.fq, function(index, value) { | |
params.fq[index] = _cleanSlash(value) | |
}) : params.fq = _cleanSlash(params.fq)) | |
} | |
function _separateOr(value) { | |
var separated = value.substring(value.indexOf("}") + 1), | |
sep = "", | |
parenStart = separated.indexOf("("); | |
if (parenStart !== -1) { | |
var filter = separated.substring(0, parenStart), | |
facets = separated.substring(parenStart + 1, separated.indexOf(")")); | |
facets = facets.split(" "), separated = "", _.each(facets, function(val) { | |
separated += sep + filter + val, sep = "&fq=" | |
}) | |
} | |
return separated | |
} | |
function _loadMapItem(mapList, key, item) { | |
var mapItem = mapList[key]; | |
void 0 === mapItem && (mapItem = { | |
key: key, | |
list: [] | |
}), mapItem.list.push(item), mapList[key] = mapItem | |
} | |
function _safeUrlEncode(string) { | |
return string.indexOf("%") === -1 ? encodeURIComponent(string) : string | |
} | |
var DATE_REGEX = new RegExp("^\\d{4}(-\\d{2}){2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,3})?)?Z$", "i"); | |
return { | |
retroParams: function(params) { | |
_removeFunk(params); | |
var retro = $.param(params, !0); | |
return retro = retro.replace(/\+/g, " "), retro = retro.replace(/ /g, "%20"), retro = retro.replace(/\\/g, ""), retro = retro.replace(/&/g, "/"), retro = retro.replace(/%3A/g, ":"), retro = retro.replace(/%5C%2F/g, "%252F"), retro = retro.replace(/fq=/g, "f."), retro = retro.replace(/path_path/g, "path"), retro = retro.replace("f.path", "path"), retro = retro.replace("f.bbox", "bbox"), retro = retro.replace("shard", "catalog"), retro = retro.replace(/:/g, "="), retro = retro.replace("*=*", "*:*") | |
}, | |
bytesToSize: function(bytes) { | |
var sizes = ["Bytes", "KB", "MB", "GB", "TB"]; | |
if (0 === bytes) return "0 Bytes"; | |
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); | |
return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i] | |
}, | |
isDate: function(input) { | |
return !isNaN(new Date(input).getDate()) && DATE_REGEX.test(input) | |
}, | |
toArray: function(val) { | |
return "string" == typeof val ? [val] : _.isUndefined(val) ? [] : val.slice() | |
}, | |
toMap: function(key, array) { | |
var map = {}; | |
return $.each(array, function(index, value) { | |
map[value[key]] = value | |
}), map | |
}, | |
toMapList: function(key, sourceList) { | |
var listItem, mapList = {}; | |
return sourceList.forEach(function(item) { | |
listItem = item[key], void 0 !== listItem && (Array.isArray(listItem) ? item[key].forEach(function(sub) { | |
_loadMapItem(mapList, sub, item) | |
}) : _loadMapItem(mapList, listItem, item)) | |
}), mapList | |
}, | |
hasField: function(list, field) { | |
var has = !1; | |
return $.each(list, function(index, item) { | |
return has = angular.isDefined(item[field]), !has | |
}), has | |
}, | |
trim: function(val, toTrim) { | |
return val.lastIndexOf(toTrim) === val.length - 1 && (val = val.substring(0, val.length - 1)), 0 === val.indexOf(toTrim) && (val = val.substring(1)), val | |
}, | |
getIndex: function(array, val) { | |
var i = 0; | |
for (i; i < array.length; i++) | |
if (array[i].indexOf(val) > -1) return i; | |
return -1 | |
}, | |
toQueryString: function(params) { | |
var queryString = "", | |
sep = ""; | |
return $.each(params, function(key, value) { | |
$.isArray(value) ? $.each(value, function(index, val) { | |
queryString += sep + key + "=" + val, sep = "&" | |
}) : ("q" === key && value.indexOf("id:") === -1 && (value = _safeUrlEncode(value)), queryString += sep + key + "=" + value, sep = "&") | |
}), queryString | |
}, | |
toQueryStringEncoded: function(params) { | |
var queryString = "", | |
sep = ""; | |
return $.each(params, function(key, value) { | |
$.isArray(value) ? $.each(value, function(index, val) { | |
queryString += sep + key + "=" + _safeUrlEncode(val), sep = "&" | |
}) : (queryString += sep + key + "=" + _safeUrlEncode(value), sep = "&") | |
}), queryString | |
}, | |
toNavigoQueryString: function(params) { | |
var filterValue, queryString = "", | |
sep = ""; | |
return $.each(params, function(key, value) { | |
$.isArray(value) ? $.each(value, function(index, val) { | |
queryString += sep + key + "=" + val, sep = "&" | |
}) : (filterValue = value, filterValue.indexOf("{!tag=") !== -1 && (filterValue = _separateOr(filterValue)), queryString += sep + key + "=" + filterValue, sep = "&") | |
}), queryString | |
}, | |
copy: function(value) { | |
return JSON.parse(JSON.stringify(value)) | |
}, | |
decodeParams: function(params) { | |
$.each(params, function(index, param) { | |
"string" == typeof param ? params[index] = decodeURIComponent(param) : $.each(param, function(index, value) { | |
param[index] = decodeURIComponent(value) | |
}) | |
}) | |
}, | |
formatBBox: function(bbox) { | |
var bboxRange = bbox.split(" "); | |
return _.each(bboxRange, function(item, index) { | |
bboxRange[index] = Number(item).toFixed(2) | |
}), bboxRange.join(" ") | |
}, | |
postJson: function(request, api, action) { | |
return $http({ | |
method: "POST", | |
url: config.root + "api/rest/" + api + "/" + action + ".json", | |
data: request, | |
headers: { | |
"Content-Type": "application/json" | |
} | |
}) | |
}, | |
postForm: function(url, data) { | |
var service = config.root + url, | |
headerConfig = { | |
headers: { | |
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" | |
} | |
}; | |
return $http.post(service, data, headerConfig) | |
}, | |
canOpen: function(doc) { | |
return 0 === doc.download.indexOf("file:") || "Service" === doc.format_type || "Server" === doc.format_type || "Map" === doc.format_type || "Application" === doc.format_type | |
}, | |
paramDelimiter: function(url) { | |
var sep = "?"; | |
return url.indexOf("?") !== -1 && (sep = "&"), sep | |
}, | |
isValidDate: function(dateString) { | |
var regEx = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d)/; | |
return null !== dateString.match(regEx) | |
}, | |
contains: function(check, value) { | |
return check.indexOf(value) > -1 | |
}, | |
containsAny: function(check, values) { | |
for (var contains = !1, i = 0; i < values.length && !(contains = check.indexOf(values[i]) > -1); i++); | |
return contains | |
}, | |
mapToList: function(map) { | |
var list = []; | |
return Object.keys(map).forEach(function(key) { | |
list.push(map[key]) | |
}), list | |
}, | |
toGroupedList: function(key, list) { | |
var categoryMap = this.toMapList(key, list); | |
return this.mapToList(categoryMap) | |
}, | |
isUrl: function(string) { | |
var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; | |
return regexp.test(string) | |
}, | |
safeUrlEncode: function(string) { | |
return _safeUrlEncode(string) | |
}, | |
removeDoubleQuotes: function(query) { | |
angular.isDefined(query.fq) && (_.isArray(query.fq) ? _.each(query.fq, function(value, index) { | |
query.fq[index] = value.replace(/"/g, "") | |
}) : query.fq = query.fq.replace(/"/g, "")) | |
} | |
} | |
}), angular.module("voyager.util").factory("converter", function($q, config, sugar) { | |
"use strict"; | |
function getPolygon(west, north, east, south) { | |
var wkt = "POLYGON ((" + west + " " + north + ", " + east + " " + north + ", " + east + " " + south + ", " + west + " " + south + ", " + west + " " + north + "))"; | |
return wkt | |
} | |
function toPolygon(bbox) { | |
var coords = bbox.split(" "); | |
return getPolygon(coords[0], coords[3], coords[2], coords[1]) | |
} | |
function _mercatorToLatLon(mercX, mercY) { | |
var rMajor = 6378137, | |
shift = Math.PI * rMajor, | |
lon = mercX / shift * 180, | |
lat = mercY / shift * 180; | |
return lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2), [lat, lon] | |
} | |
function _getGeometries(extent) { | |
var geometries = []; | |
return geometries.push({ | |
x: extent.xmin, | |
y: extent.ymin | |
}), geometries.push({ | |
x: extent.xmax, | |
y: extent.ymax | |
}), geometries | |
} | |
function _solrReady(name) { | |
if (0 === name.indexOf("(") && name.indexOf(")") === name.length - 1) { | |
name = name.replace(" )", ")").replace(")", "").replace("(", ""); | |
var facets = name.split(" "); | |
name = "(", facets.forEach(function(facet) { | |
name += _solrReady(facet) + " " | |
}), name += ")", name = name.replace(" )", ")") | |
} else name.indexOf("\\") === -1 && (name = name.replace(/[\s\/\+\-!\(\){}\^"~*?:]|&&|\|\|/g, "\\$&")); | |
return name | |
} | |
function _toClassic(params, from, to) { | |
var converted = ""; | |
if (angular.isDefined(params[from])) { | |
var f, filter, filterValue, pArr = sugar.toArray(params[from]); | |
"shards" === from && (pArr = params[from].split(",")), $.each(pArr, function(index, value) { | |
to.indexOf("links.") > -1 ? converted += "/" + to + "=" + encodeURIComponent(encodeURIComponent(value)) : value.indexOf(":") !== -1 ? (f = value.split(":"), filter = f[0], filterValue = f[1], f.length > 2 && (f.splice(0, 1), filterValue = f.join(":")), filterValue = filterValue.replace(/\\/g, ""), converted += "/" + to + "." + filter + "=" + encodeURIComponent(encodeURIComponent(filterValue))) : ("bbox.mode" === to && (value = "w" === value ? "WITHIN" : "INTERSECTS"), converted += "/" + to + "=" + value) | |
}) | |
} | |
return converted | |
} | |
return { | |
toPolygon: function(bbox) { | |
return toPolygon(bbox) | |
}, | |
toWebMercator: function(extent, spatialReference) { | |
var geometries = _getGeometries(extent), | |
svc = config.arcGisRoot + "rest/services/Geometry/GeometryServer/project?"; | |
svc += "inSR=" + spatialReference.wkid, svc += "&outSR=102100", svc += '&geometries={"geometryType":"esriGeometryPoint","geometries":' + JSON.stringify(geometries) + "}"; | |
var deferred = $q.defer(); | |
if (102100 !== spatialReference.wkid && 102113 !== spatialReference.wkid) $.getJSON(svc + "&f=json&callback=?", function(data) { | |
var bounds = [_mercatorToLatLon(data.geometries[0].x, data.geometries[0].y), _mercatorToLatLon(data.geometries[1].x, data.geometries[1].y)]; | |
deferred.resolve(bounds) | |
}); | |
else { | |
var bounds = [_mercatorToLatLon(geometries[0].x, geometries[0].y), _mercatorToLatLon(geometries[1].x, geometries[1].y)]; | |
deferred.resolve(bounds) | |
} | |
return deferred.promise | |
}, | |
toLatLng: function(extent, spatialReference) { | |
var geometries = _getGeometries(extent), | |
svc = config.arcGisRoot + "rest/services/Geometry/GeometryServer/project?"; | |
svc += "inSR=" + spatialReference.wkid, svc += "&outSR=4326", svc += '&geometries={"geometryType":"esriGeometryPoint","geometries":' + JSON.stringify(geometries) + "}"; | |
var deferred = $q.defer(); | |
if (4326 !== spatialReference.wkid && 4269 !== spatialReference.wkid) $.getJSON(svc + "&f=json&callback=?", function(data) { | |
var bounds = [ | |
[data.geometries[0].x, data.geometries[0].y], | |
[data.geometries[1].x, data.geometries[1].y] | |
]; | |
deferred.resolve(bounds) | |
}); | |
else { | |
var bounds = [ | |
[geometries[0].x, geometries[0].y], | |
[geometries[1].x, geometries[1].y] | |
]; | |
deferred.resolve(bounds) | |
} | |
return deferred.promise | |
}, | |
solrReady: function(value) { | |
return _solrReady(value) | |
}, | |
toSolrParams: function(filters) { | |
var name, fq = [], | |
orFilters = {}; | |
return $.each(filters, function(index, facet) { | |
if (name = "" !== facet.filter ? _solrReady(facet.name) : facet.name, "CHECK" === facet.style) orFilters[facet.filter] ? orFilters[facet.filter].push(name) : orFilters[facet.filter] = [name]; | |
else if ("RANGE" === facet.style || "STATS" === facet.style || "DATE" === facet.style) | |
if (facet.filter !== facet.name) fq.push(facet.filter + ":" + _solrReady(facet.name)); | |
else if (facet.model) fq.push(facet.filter + ":[" + facet.model[0] + " TO " + facet.model[1] + "]"); | |
else { | |
var filterValue = facet.humanized.substring(facet.humanized.indexOf(":") + 1); | |
fq.push(facet.filter + ":" + _solrReady(filterValue)) | |
} else "" === facet.filter ? fq.push(name) : fq.push(facet.filter + ":" + _solrReady(name)) | |
}), $.each(orFilters, function(name, orFilter) { | |
fq.push("{!tag=" + name + "}" + name + ":(" + orFilter.join(" ") + ")") | |
}), "&" + sugar.toQueryStringEncoded({ | |
fq: fq | |
}) | |
}, | |
toSolrQueryList: function(filters) { | |
var name, filterQuery = [], | |
orFilters = {}; | |
return $.each(filters, function(index, facet) { | |
name = "" !== facet.filter ? _solrReady(facet.name) : facet.name, "CHECK" === facet.style ? orFilters[facet.filter] ? orFilters[facet.filter].push(name) : orFilters[facet.filter] = [name] : "RANGE" === facet.style || "STATS" === facet.style ? filterQuery.push(facet.filter + ":" + facet.name) : "" === facet.filter ? filterQuery.push(name) : filterQuery.push(facet.filter + ":" + name) | |
}), $.each(orFilters, function(name, orFilter) { | |
filterQuery.push("{!tag=" + name + "}" + name + ":(" + orFilter.join(" ") + ")") | |
}), filterQuery | |
}, | |
toClassicParams: function(params, savedSearch) { | |
var voyagerParams = ""; | |
return angular.isDefined(params.q) && (voyagerParams += savedSearch ? "/q=" + sugar.safeUrlEncode(params.q) : _toClassic(params, "q", "q")), voyagerParams += _toClassic(params, "fq", "f"), voyagerParams += _toClassic(params, "place", "place"), voyagerParams += _toClassic(params, "place.op", "place.op"), voyagerParams += _toClassic(params, "voyager.list", "voyager.list"), voyagerParams += _toClassic(params, "links.to", "links.to"), voyagerParams += _toClassic(params, "links.from", "links.from"), voyagerParams += _toClassic(params, "shards", "catalog"), angular.isDefined(params.view) && "card" !== params.view && (voyagerParams += "/view=" + params.view), angular.isDefined(params.sort) && (voyagerParams += "/sort=" + params.sort), angular.isDefined(params.sortdir) && "desc" === params.sortdir && (voyagerParams += "/sort.reverse=true"), voyagerParams | |
}, | |
toIdTextArray: function(source) { | |
return source = source.replace(/ /g, "").split(","), _.transform(source, function(arr, val, idx) { | |
arr[idx] = { | |
id: val, | |
text: val | |
} | |
}) | |
}, | |
toPlaceFilter: function(params) { | |
var placeFq = ""; | |
return angular.isDefined(params["place.op"]) && (placeFq += " place.op=" + params["place.op"], delete params["place.op"]), angular.isDefined(params["place.id"]) && (placeFq += " place.id=" + params["place.id"], delete params["place.id"]), placeFq = "{!" + placeFq + '}place:"' + params.place + '"', delete params.place, placeFq | |
} | |
} | |
}), angular.module("voyager.util").factory("queryBuilder", function(config, filterService, configService, sugar, catalogService, converter) { | |
function getActionFields() { | |
if (null !== actionFields) return actionFields; | |
var fields = [], | |
actions = config.docActions, | |
pos = -1, | |
fieldArr = []; | |
return actions.forEach(function(action) { | |
_.isString(action.visible) && (pos = action.visible.indexOf("doc."), pos > -1 && (fieldArr = action.visible.split("doc."), fieldArr.forEach(function(field) { | |
"" === field || sugar.containsAny(field, ["canCart", "isService", "hasDownload", "isEsriLayer"]) || fields.push(field.substring(0, field.indexOf(" "))) | |
}))) | |
}), actionFields = fields.join(",") | |
} | |
function _convertPlaceFilter(params) { | |
var placeFilter = ""; | |
return angular.isDefined(params.place) && (placeFilter = "&fq=" + converter.toPlaceFilter(params)), placeFilter | |
} | |
function _getRequestFields() { | |
var fields = STATIC_FIELDS; | |
return fields += configService.getSolrFields(), fields += getActionFields(), | |
configService.getTableFieldNames().length && (fields += "," + configService.getTableFieldNames().join(",")), fields = fields.replace(/, /g, ","), fields = _.indexBy(fields.split(",")), _.values(fields).join(",") | |
} | |
function _getFilters(placeFilter) { | |
var queryString = ""; | |
return queryString += filterService.getFilterParams(), queryString += placeFilter | |
} | |
function build2(solrParams, page, itemsPerPage, sortDirection, sortField, disableJSONP) { | |
var placeFilter = ""; | |
solrParams ? (delete solrParams.fq, placeFilter = _convertPlaceFilter(solrParams)) : solrParams = {}, angular.isDefined(solrParams.shards) && (solrParams.shards = catalogService.removeInvalid(solrParams.shards)); | |
var queryString = config.root + selectPath; | |
queryString += "?" + sugar.toQueryString(solrParams); | |
var rows = 0; | |
if (page) { | |
var start = (page - 1) * itemsPerPage; | |
rows = itemsPerPage, queryString += "&start=" + start, queryString += "&fl=" + _getRequestFields() | |
} | |
return queryString += "&rows=" + rows, queryString += "&extent.bbox=true&block=false", queryString += _getFilters(placeFilter), angular.isDefined(configService.getConfigId()) && angular.isUndefined(solrParams["voyager.config.id"]) && (queryString += "&voyager.config.id=" + configService.getConfigId()), angular.isDefined(sortField) && (angular.isUndefined(sortDirection) && (sortDirection = angular.isDefined(config.defaultSortDirection) ? config.defaultSortDirection : "desc"), queryString += "&sort=" + sortField + " " + sortDirection), queryString += "&rand=" + Math.random(), queryString += "&wt=json", disableJSONP || (queryString += "&json.wrf=JSON_CALLBACK"), queryString | |
} | |
function buildByIds(ids) { | |
var queryString = config.root + selectPath + "?q="; | |
return queryString += "id:(", $.each(ids, function(index, id) { | |
queryString += " " + id | |
}), queryString += ")", queryString += "&fl=id,name:[name],thumb:[thumbURL],format:[format]&extent.bbox=true&rows=999999", queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _buildIdList(solrParams) { | |
var placeFilter = _convertPlaceFilter(solrParams); | |
delete solrParams.fq, angular.isDefined(solrParams.shards) && (solrParams.shards = catalogService.removeInvalid(solrParams.shards)), solrParams.q = getInput(solrParams.q); | |
var queryString = config.root + selectPath; | |
return queryString += "?" + sugar.toQueryString(solrParams), queryString += "&fl=id&rows=999999", queryString += _getFilters(placeFilter), queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _buildBboxList(solrParams) { | |
var placeFilter = _convertPlaceFilter(solrParams); | |
delete solrParams.fq, angular.isDefined(solrParams.shards) && (solrParams.shards = catalogService.removeInvalid(solrParams.shards)), solrParams.q = getInput(solrParams.q); | |
var queryString = config.root + selectPath; | |
return queryString += "?" + sugar.toQueryString(solrParams), queryString += "&fl=bbox,name,id&rows=" + config.markerLimit + "&fq=bbox:[-90,-180 TO 90,180]", queryString += _getFilters(placeFilter), queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
var actionFields = null, | |
selectPath = "solr/v0/select", | |
customFields = ["shards", "discoveryStatus"], | |
STATIC_FIELDS = "id,title, name:[name],format,abstract,fullpath:[absolute],absolute_path:[absolute],thumb:[thumbURL], path_to_thumb, subject,download:[downloadURL],format_type,bytes,modified,shard:[shard],bbox,geo:[geo],format_category, component_files, ags_fused_cache, linkcount__children, contains_name, wms_layer_name,tag_flags,hasMissingData,layerURL:[lyrURL]", | |
getFacetParams = function(field) { | |
var facetParams = ""; | |
if (field && !($.inArray(field, customFields) >= 0)) { | |
var fieldConfig = _.find(config.settings.data.filters, function(filter) { | |
return filter.field === field | |
}); | |
return angular.isDefined(fieldConfig.minCount) && (facetParams += "&f." + fieldConfig.field + ".facet.mincount=" + fieldConfig.minCount), angular.isDefined(fieldConfig.sort) && (facetParams += "&f." + fieldConfig.field + ".facet.sort=" + fieldConfig.sort), facetParams += "CHECK" === fieldConfig.style ? "&facet.field={!ex=" + field + "}" + field : "&facet.field=" + field | |
} | |
var filters = config.settings.data.filters; | |
return $.each(filters, function(index, filter) { | |
$.inArray(filter.field, customFields) >= 0 || (facetParams += "CHECK" === filter.style ? "&facet.field={!ex=" + filter.field + "}" + filter.field : "STATS" === filter.style ? "&facet.field=" + filter.field : "&facet.field=" + filter.field, angular.isDefined(filter.minCount) && (facetParams += "&f." + filter.field + ".facet.mincount=" + filter.minCount), angular.isDefined(filter.sort) && (facetParams += "&f." + filter.field + ".facet.sort=" + filter.sort)) | |
}), facetParams | |
}, | |
getInput = function(query) { | |
var input = "*:*"; | |
return angular.isDefined(query) && (input = query), input | |
}; | |
return { | |
doBuild2: function(params, page, itemsPerPage, sortDirection, sortField, disableJSONP) { | |
return build2(params, page, itemsPerPage, sortDirection, sortField, disableJSONP) | |
}, | |
doByIds: function(ids) { | |
return buildByIds(ids) | |
}, | |
buildAllFacets: function(params, field) { | |
var placeFilter = _convertPlaceFilter(params); | |
delete params.fq, delete params.sort, angular.isDefined(params.shards) && (params.shards = catalogService.removeInvalid(params.shards)), params.q = getInput(params.q); | |
var queryString = config.root + selectPath, | |
facetLimit = -1, | |
rows = 0; | |
queryString += "?" + sugar.toQueryString(params), queryString += "&rows=" + rows, queryString += "&facet=true&facet.mincount=1&facet.limit=" + facetLimit + getFacetParams(field); | |
var fieldConfig = _.find(config.settings.data.filters, function(filter) { | |
return filter.field === field | |
}); | |
return "shards" !== field && (queryString += "CHECK" === fieldConfig.style ? "&facet.field={!ex=" + field + "}" + field : "&facet.field=" + field), queryString += _getFilters(placeFilter), queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
}, | |
buildAllIds: function(params) { | |
return _buildIdList(params) | |
}, | |
buildAllBboxes: function(params) { | |
return _buildBboxList(params) | |
}, | |
buildBulkUpdaterUrl: function(url, params) { | |
var placeFilter = _convertPlaceFilter(params); | |
delete params.fq, delete params.sort, delete params.view, angular.isDefined(params.shards) && (params.shards = catalogService.removeInvalid(params.shards)), params.q = getInput(params.q); | |
var queryString = config.root + url, | |
rows = 999999; | |
return queryString += "?" + sugar.toQueryString(params), queryString += "&rows=" + rows, queryString += _getFilters(placeFilter), queryString += "&rand=" + Math.random(), queryString += "&wt=json" | |
}, | |
buildEsriGeocodeServiceTestQuery: function() { | |
return config.root + selectPath + "?" + $.param({ | |
wt: "json", | |
"json.wrf": "JSON_CALLBACK", | |
rows: 0, | |
place: "california", | |
"place.finder": "esri" | |
}) | |
}, | |
buildFacetParams: function(field) { | |
return getFacetParams(field) | |
} | |
} | |
}), angular.module("voyager.util").factory("translateService", function($log) { | |
"use strict"; | |
function _init() { | |
try { | |
field_names = config.fields.data.FIELD, field_descriptions = config.fields.data.FIELD_DESCR, file_formats = config.fileFormats.data.VALUE.format, locations = config.locations.data.VALUE.location, $.each(removePrefixList, function(index, item) { | |
removePrefixHash[item] = !0; | |
var c = item.substring(1, 2), | |
key = item.replace("_", c + "_"); | |
removePrefixHash[key] = !0 | |
}) | |
} catch (err) { | |
$log.error(err) | |
} | |
} | |
var locations, file_formats = { | |
"text/calendar": "iCalendar", | |
"text/x-tcl": "Tcl script", | |
"text/x-prolog": "Prolog source code", | |
"application/vnd.ms-excel.template.macroenabled.12": "Office Open XML Workbook Template (macro-enabled)", | |
"image/x-vnd.vrt": "VRT", | |
"text/x-lex": "Lex/Flex source code", | |
"video/x-ms-wmv": "Windows Media Video", | |
"application/x-tika-java-web-archive": "Java Web Archive", | |
"image/x-rpf-combatc_50": "Combat Chart (1:50,000)", | |
"application/vnd.esri.connection.wms": "WMS Connection File", | |
"application/x-sharedlib": "Shared Library", | |
"application/vnd.esri.e00": "ESRI ArcInfo interchange file (E00)", | |
"application/x-arcgis-search-server": "ArcGIS Search Service (SearchServer)", | |
"application/x-tika-msoffice-embedded; format=ole10_native": "OLE10 Native Embedded Document", | |
"image/nitf": "National Imagery Transmission Format (NITF)", | |
"application/vnd.visio": "Microsoft Visio Diagram", | |
"application/fgdc+xml": "FGDC XML", | |
"image/x-vnd.kap": "BSB Charts", | |
"application/x-object": "X-Object", | |
"text/vnd.wap.wmlscript": "WML Script", | |
"text/x-haml": "HAML source code", | |
"application/vnd.ogc.wms_layer_xml": "WMS Layer", | |
"application/x-webservice-json": "JSON REST Web Service", | |
"application/javascript": "JavaScript Source Code", | |
"audio/x-aiff": "Audio Interchange File Format (AIFF)", | |
"image/x-rpf-tlm-50": "Topographic Line Map (1:50,000) (TLM_50)", | |
"image/x-rpf-cityg_15_500": "City Graphics (1:15,500)", | |
"application/xquery": "XQuery source code", | |
"application/x-arcgis-na-server": "ArcGIS Network Analysis Service (NASerice)", | |
"application/vnd.esri.connection.sde": "SDE Connection File", | |
"image/x-vnd.gsat": "GSat", | |
"application/x-font-adobe-metric": "Adobe Font Metric", | |
"application/xml+xsd": "XML Schema (XSD)", | |
"application/vnd.oasis.opendocument.spreadsheet-template": "OpenDocument v1.0: Spreadsheet document used as template", | |
"text/x-vbscript": "VBScript source code", | |
"image/x-ms-bmp": "Windows bitmap (BMP)", | |
"application/x-geocortex-server": "Geocortex Server", | |
"application/zip": "Compressed Archive File (ZIP)", | |
"image/x-rpf-cib10x": "CIB >10m (CIB10X)", | |
"application/vnd.esri.lyr": "ESRI Layer File", | |
"text/x-php": "PHP script", | |
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "Office Open XML Document", | |
"image/x-rpf-joga": "Joint Operations Graphic - Air (JOGA)", | |
"text/x-awk": "AWK script", | |
"application/rdf+xml": "XML syntax for RDF graphs (RDF/XML)", | |
"application/vnd.oasis.opendocument.text-web": "OpenDocument v1.0: Text document used as template for HTML documents", | |
"image/x-rpf-jogr": "Joint Operations Graphic - Radar (JOGR)", | |
"application/vnd.apple.iwork": "Apple IWork", | |
"application/x-tika-unix-dump": "Tika Coredump", | |
"image/x-rpf-tlm-25": "Topographic Line Map (1:25,000) (TLM_25)", | |
"image/x-rpf-tlm-24": "Topographic Line Map (1:24,000) (TLM_24)", | |
"text/css": "Cascading Style Sheet", | |
"text/csv": "Comma Separated Values (CSV)", | |
"application/x-sas": "SAS Program", | |
"application/x-gtar": "GNU tar Compressed File Archive (GNU Tape Archive)", | |
"image/jp2": "JPEG 2000 Part 1 (JP2)", | |
"image/x-rpf-tlm_other": "Topographic Line Map (other 1:50,000) (TLM_OTHER)", | |
"image/x-vnd.erdas_gis": "ERDAS 7.5 GIS", | |
"image/x-vnd.blx": "BLX", | |
"application/vnd.esri.gdb.file.data": "Data in a File Geodatabase (FileGDB Data)", | |
"audio/ogg": "Ogg Vorbis Codec Compressed WAV File", | |
"application/x-webservice": "Web Services", | |
"application/vnd.esri.gdb.personal": "Personal Geodatabase", | |
"application/xhtml+xml": "XHTML", | |
"image/x-vnd.bsq": "Arc/Info & Space Imaging BSQ", | |
"image/png": "Portable Network Graphics (PNG)", | |
"application/vnd.esri.diinfo": "Derived Image Info (DIInfo)", | |
"application/dita+xml; format=topic": "DITA Topic", | |
"text/x-pascal": "Pascal source code", | |
"model/iges": "Initial Graphics Exchange Specification Format (IGES)", | |
"text/x-objcsrc": "Objective-C source code", | |
"image/x-xbitmap": "X11 Bitmap Graphic", | |
"application/x-tika-msoffice-embedded; format=comp_obj": "CompObj OLE2 Embedded Document", | |
"video/mpeg": "MPEG Movie Clip", | |
"application/vnd.oasis.opendocument.image-template": "OpenDocument v1.0: Image document used as template", | |
"model/vnd.parasolid.transmit.binary": "Parasolid (Binary)", | |
"text/x-actionscript": "ActionScript source code", | |
"application/vnd.oasis.opendocument.image": "OpenDocument v1.0: Image document", | |
"application/dita+xml; format=concept": "DITA Concept Topic", | |
"application/bizagi-modeler": "BizAgi Process Modeler", | |
"application/x-tika-ooxml-protected": "Password Protected OOXML File", | |
"text/uri-list": "URI List", | |
"image/x-dted-level-1": "DTED Level 1", | |
"image/x-dted-level-0": "DTED Level 0", | |
"image/x-dted-level-3": "DTED Level 3", | |
"image/x-dted-level-2": "DTED Level 2", | |
"image/x-vnd.ndf": "NDF", | |
"image/x-xcf": "GIMP Image File", | |
"image/x-rpf-combatc_25": "Combat Chart (1:25,000)", | |
"application/vnd.esri.isdef": "Image Service Definition (ISDef)", | |
"application/vnd.voyager.testsuite": "Voyager test suite", | |
"image/x-vnd.bil": "ESRI binary interleaved format (BIL)", | |
"image/x-rpf-cityg_12_800": "City Graphics (1:12,800)", | |
"image/x-vnd.bip": "Arc/Info & Space Imaging BIP", | |
"application/x-msdownload": "Dynamic Link Library", | |
"text/x-scala": "Scala source code", | |
"image/x-rpf-tlm_200": "Topographic Line Map (1:200,000) (TLM_200)", | |
"image/x-rpf-cityg_10_560": "City Graphics (1:10,560)", | |
"image/x-rpf-combatc_10": "Combat Chart (1:10,000)", | |
"image/jpx": "JPEG 2000 Part 2 (JPX) (JP2)", | |
"text/x-vbdotnet": "VB.NET source code", | |
"image/x-vnd.ter": "Terragen Heightfield (TER)", | |
"application/vnd.esri.connection": "ESRI Connection File", | |
"application/x-dosexec": "DOS/Windows executable (EXE)", | |
"application/vnd.ms-xpsdocument": "XML Paper Specification (XPS)", | |
"application/rtf": "Rich Text Format File (RTF)", | |
"image/x-rpf": "Raster Product (RPF)", | |
"application/vnd.esri.gdb.personal.data": "Data in a Personal Geodatabase (Access Data)", | |
"application/vnd.esri.gp.toolbox": "GP Toolbox (TBX)", | |
"application/x-executable": "Executable", | |
"image/x-rpf-rm_50": "Riverine Map (1:50,000)", | |
"application/vnd.ms-powerpoint.presentation.macroenabled.12": "Office Open XML Presentation (macro-enabled)", | |
"image/x-rpf-tfc-day": "Transit Flying Chart (Day) (TFC_day)", | |
"video/quicktime": "Apple QuickTime Movie", | |
"application/x-arcgis-feature-server-layer": "ArcGIS FeatureService Layer", | |
"application/x-font-ttf": "TrueType Font (TTF)", | |
"application/x-netcdf": "Mastercam Numerical Control File", | |
"application/vnd.ogc.se_xml": "OGC Webservice Error", | |
"application/x-staroffice-template": "StarOffice Template", | |
"text/x-ocaml": "Ocaml source code", | |
"image/x-vnd.srtm_hgt": "SRTM HGT", | |
"text/x-modula": "Modula source code", | |
"text/x-vcard": "vCard", | |
"image/x-xpixmap": "X11 Pixmap Graphic", | |
"image/x-rpf-cityg_17_500": "City Graphics (1:17,500)", | |
"application/vnd.oasis.opendocument.text": "OpenDocument v1.0: Text document", | |
"application/ddms3.1+xml": "DDMS 3.1", | |
"image/x-rpf-hac": "Harbor and Approach Charts", | |
"application/vnd.microsoft.url": "Windows URL Shortcut", | |
"text/x-less": "LESS source code", | |
"application/vnd.esri.mxd": "ArcMap Document (MXD)", | |
"image/x-vnd.ers": "ER Mapper", | |
"application/vnd.ms-works": "Microsoft Works", | |
"image/x-vnd.pci.pix": "PCI Geomatics Database File", | |
"image/x-rpf-lfc-1": "Low Flying Chart 1 (LFC_1)", | |
"text/x-jsp": "Java Server Page (JSP)", | |
"application/x-fictionbook+xml": "FictionBook document", | |
"text/x-fortran": "Fortran source code", | |
"image/x-rpf-cib10": "CIB 10m (CIB10)", | |
"image/x-rpf-hfc": "High Flying Chart (HFC)", | |
"application/gpx+xml": "GPS eXchange Format (GPX)", | |
"image/x-rpf-lfc-4": "Low Flying Chart 4 (LFC_4)", | |
"image/x-rpf-lfc-5": "Low Flying Chart 5 (LFC_5)", | |
"model/vnd.collada+xml": "COLLADA", | |
"image/x-rpf-lfc-2": "Low Flying Chart 2 (LFC_2)", | |
"video/mp4": "MP4", | |
"image/x-rpf-lfc-3": "Low Flying Chart 3 (LFC_3)", | |
"application/x-gzip": "Gzip Compressed Archive", | |
"application/x-cpio": "UNIX CPIO Archive", | |
"model/x-sat": "Standard ACIS Text (SAT)", | |
"application/x-tika-ooxml": "Open Office XML Format", | |
"text/x-rst": "reStructuredText source code", | |
"application/dita+xml": "Darwin Information Typing Architecture", | |
"image/tiff": "Tagged Image File Format (TIFF)", | |
"image/x-rpf-lfc-night": "Low Flying Chart (night) (LFC_night)", | |
"application/dita+xml; format=map": "DITA Map", | |
"image/x-vnd.grib": "GRIB", | |
"application/mbox": "MBox - Mailbox Text Archive", | |
"image/vnd.dxf": "AutoCAD DXF", | |
"application/x-tika-msworks-spreadsheet": "MSWorks Spreadsheet", | |
"application/mathml+xml": "Math Markup Language", | |
"audio/x-wav": "WAVE Audio", | |
"image/x-vnd.intergraphcit": "Intergraph CIT", | |
"image/vnd.dwg": "AutoCad Drawing (DWG)", | |
"application/vnd.esri.gdb.sde": "SDE Geodatabase", | |
"text/x-sql": "SQL code", | |
"application/vnd.openxmlformats-officedocument.presentationml.template": "Office Open XML Presentation Template", | |
"image/x-rpf-tlm_100": "Topographic Line Map (1:100,000) (TLM_100)", | |
"application/vnd.esri.gdb.sde.data": "Data in an SDE (SDE Data)", | |
"image/svg+xml": "Scalable Vector Graphics (SVG)", | |
"application/java-vm": "Java class file", | |
"application/x-tar": "TAR Archive", | |
"image/x-vnd.intergraphcot": "Intergraph COT", | |
"text/x-erlang": "Erlang source code", | |
"image/jpeg": "Joint Photographic Experts Group (JPEG)", | |
"text/x-asciidoc": "Asciidoc source code", | |
"application/dita+xml; format=val": "DITA Conditional Processing Profile", | |
"image/x-raw-sony": "Sony raw image", | |
"application/x-ibooks+zip": "Apple iBooks Author publication format", | |
"application/vnd.apple.keynote": "Apple Keynote", | |
"image/x-rpf-vnc": "Visual Navigation Charts (VNC)", | |
"application/x-arcgis-map-server-layer": "ArcGIS Map Service Layer (MapService Layer)", | |
"image/x-rpf-mmc": "Miscellaneous Maps & Charts", | |
"text/x-clojure": "Clojure source code", | |
"text/tab-separated-values": "Tab Separated Values (TSV)", | |
"model/vnd.parasolid.transmit.text": "Parasolid (Text)", | |
"application/vnd.ms-powerpoint": "Microsoft Powerpoint Presentation", | |
"image/x-rpf-hrc": "Helicopter Route Chart (HRC)", | |
"application/x-arcgis-service": "ArcGIS Service", | |
"application/rss+xml": "RSS", | |
"application/json": "JSON", | |
"image/x-rpf-mim": "Military Installation Maps (MIM)", | |
"text/x-cgi": "CGI script", | |
"image/x-rpf-tfc-night": "Transit Flying Chart (Night) (TFC_night)", | |
"application/x-fme-server": "FME Server", | |
"application/msword": "Microsoft Word Document", | |
"video/x-flv": "Flash Video File", | |
"text/x-d": "D source code", | |
"application/iso19115+xml": "ISO 19115", | |
"application/epub+zip": "Electronic Publication (EPUB)", | |
"application/vnd.ms-excel.sheet.binary.macroenabled.12": "Microsoft Excel 2007 Binary Spreadsheet", | |
"application/vnd.ogc.csw_xml": "Catalog Service (CSW)", | |
"text/plain": "Plain Text", | |
"application/ddms5+xml": "DDMS 5.0", | |
"image/x-vnd.erdas_lan": "ERDAS 7.5 LAN", | |
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "Office Open XML Workbook", | |
"application/vnd.esri.sdc": "Smart Data Compression (SDC)", | |
"application/vnd.ms-powerpoint.addin.macroenabled.12": "Office Open XML Presentation Add-in (macro-enabled)", | |
"application/gsip+xml": "NMIS XML", | |
"application/vnd.esri.gdb.file": "File Geodatabase (FileGDB)", | |
"application/x-tika-java-enterprise-archive": "Java Enterprise Archive File", | |
"application/java-archive": "Java Archive", | |
"application/vnd.google-earth.kmz": "Keyhole Markup Language (KMZ)", | |
"application/vnd.oasis.opendocument.spreadsheet": "OpenDocument v1.0: Spreadsheet document", | |
"text/x-sed": "Sed code", | |
"application/x-tika-iworks-protected": "Password Protected iWorks File", | |
"text/x-ruby": "Ruby source code", | |
"text/x-haxe": "Haxe source code", | |
"application/x-fme-server-workspace": "FME Server Workspace", | |
"application/x-coredump": "Coredump", | |
"image/vnd.erdas.ecw": "ER Mapper ECW", | |
"text/troff": "Roff/nroff/troff/groff Unformatted Manual Page (UNIX)", | |
"image/x-rpf-nroac": "Naval Range Operating Area Chart", | |
"image/x-rpf-cibh": "CIB .5m", | |
"application/dita+xml; format=task": "DITA Task Topic", | |
"image/x-rpf-cityg_12_500": "City Graphics (1:12,500)", | |
"application/vnd.sun.xml.writer": "OpenOffice v1.0: Writer Document", | |
"application/x-arcgis-server": "ArcGIS Server", | |
"application/x-rpf-a-toc": "RPF Table Of Contents (A.TOC)", | |
"image/x-rpf-cib5": "CIB 5m", | |
"image/x-rpf-cib2": "CIB 2m", | |
"image/x-rpf-cib1": "CIB 1m", | |
"text/x-matlab": "Matlab source code", | |
"text/x-aspectj": "AspectJ source code", | |
"application/vnd.ms-project": "Microsoft Project", | |
"application/x-tika-msoffice-embedded": "MS Office Embedded", | |
"text/x-python": "Python script", | |
"image/x-vnd.jaxa": "JAXA", | |
"image/vnd.wap.wbmp": "Wireless Bitmap File Format", | |
"application/vnd.oasis.opendocument.presentation-template": "OpenDocument v1.0: Presentation document used as template", | |
"image/x-raw-panasonic": "Panasonic raw image", | |
"text/x-scheme": "Scheme source code", | |
"text/x-ml": "ML source code", | |
"text/vnd.iptc.anpa": "American Newspaper Publishers Association Wire Feeds (ANPA)", | |
"audio/mpeg": "MPEG-1 Audio Layer 3 (MP3)", | |
"text/x-perl": "Perl script", | |
"application/vnd.apple.webloc": "Mac OS X Website Location (Webloc)", | |
"application/vnd.esri.shapefile": "Shapefile (SHP)", | |
"text/x-coffeescript": "CoffeeScript source code", | |
"text/x-web-markdown": "Markdown source code", | |
"application/vnd.ms-word.document.macroenabled.12": "Office Open XML Document (macro-enabled)", | |
"model/x-step": "STEP", | |
"text/x-emacs-lisp": "Emacs Lisp source code", | |
"application/gsip3+xml": "NMIS 3.0", | |
"image/x-vnd.psi": "Pictometry Oblique Image (PSI)", | |
"video/x-m4v": "iTunes Video", | |
"application/vnd.google-earth.kml.object": "Object within KML (KML Object)", | |
"application/x-arcgis-globe-server": "ArcGIS Globe Service (GlobeService)", | |
"image/x-img": "Macintosh Disk Image (IMG)", | |
"application/vnd.oasis.opendocument.presentation": "OpenDocument v1.0: Presentation document", | |
"application/x-arcgis-geocode-server": "ArcGIS Geocode Service (GeocodeService)", | |
"application/x-arcgis-online": "ArcGIS Online Server", | |
"application/x-debian-package": "Debian Software Package", | |
"application/vnd.esri.rpdef": "Raster Process Definition (RPDef)", | |
"image/x-rpf-cityg_11_800": "City Graphics (1:11,800)", | |
"image/x-vnd.isis": "ISIS", | |
"text/x-yacc": "Yacc/Bison source code", | |
"application/vnd.ogc.wms_xml": "Web Map Service (WMS)", | |
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "Office Open XML Document Template", | |
"application/x-bzip": "Bzip Compressed File", | |
"application/ic-pubs+xml": "PUBS IntelDoc", | |
"image/x-rpf-tfc-4": "Transit Flying Chart - 4 (TFC_4)", | |
"image/x-rpf-tfc-5": "Transit Flying Chart - 5 (TFC_5)", | |
"image/x-rpf-tfc-2": "Transit Flying Chart - 2 (TFC_2)", | |
"image/x-rpf-tfc-3": "Transit Flying Chart - 3 (TFC_3)", | |
"application/vnd.esri.gp.tool.category": "GP Tool Category", | |
"image/x-rpf-tfc-1": "Transit Flying Chart - 1 (TFC_1)", | |
"image/x-vnd.intergraphctb": "Intergraph CTB", | |
"image/x-vnd.intergraphctc": "Intergraph CTC", | |
"application/vnd.microstation.dgn": "MicroStation Design File (DGN)", | |
"application/vnd.oasis.opendocument.chart": "OpenDocument v1.0: Chart document", | |
"text/sgml": "Standard Generalized Markup Language File", | |
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "Office Open XML Presentation", | |
"text/x-ini": "Configuration file", | |
"application/gsip5+xml": "NMIS 5.0", | |
"application/vnd.ms-powerpoint.slideshow.macroenabled.12": "Office Open XML Presentation Slideshow (macro-enabled)", | |
"application/x-xmind": "XMind Pro", | |
"audio/basic": "uLaw/AU Audio File", | |
"text/x-idl": "Inteface Definition Language", | |
"text/x-c++hdr": "C++ source code header", | |
"application/vnd.oasis.opendocument.chart-template": "OpenDocument v1.0: Chart document used as template", | |
"image/x-vnd.idrisirst": "IDRISI Raster", | |
"application/vnd.oasis.opendocument.formula": "OpenDocument v1.0: Formula document", | |
"application/atom+xml": "Atom feed", | |
"text/x-java-source": "Java source code", | |
"text/x-java": "Java source code", | |
"message/rfc822": "E-mail Message", | |
"application/xml": "Extensible Markup Language (XML)", | |
"application/vnd.oasis.opendocument.graphics-template": "OpenDocument v1.0: Graphics document used as template", | |
"image/x-rpf-gnc": "Global Navigation Chart (GNC)", | |
"text/x-stsrc": "Smalltalk source code", | |
"application/x-geocortex-site": "Geocortex Site", | |
"application/x-adobe-indesign-interchange": "Adobe InDesign Interchange format (INX)", | |
"text/x-applescript": "AppleScript source code", | |
"text/x-yaml": "YAML source code", | |
"text/x-haskell": "Haskell source code", | |
"application/pdf": "Portable Document Format (PDF)", | |
"image/x-raw-nikon": "Nikon raw image", | |
"application/x-bzip2": "Bzip 2 UNIX Compressed File", | |
"text/x-forth": "Forth source code", | |
"text/x-go": "Go source code", | |
"application/x-arcgis-feature-server": "ArcGIS FeatureService", | |
"image/x-vnd.adrg_legend": "ADRG Legend", | |
"text/x-vcalendar": "vCal", | |
"text/html": "HyperText Markup Language (HTML)", | |
"image/vnd.adobe.photoshop": "Photoshop Image", | |
"application/x-arcgis-gp-server-task": "ArcGIS Geoprocessing Service Task (GPServer Task)", | |
"application/x-arcgis-image-server": "ArcGIS Image Service (ImageService)", | |
"application/ddms3+xml": "DDMS 3.0", | |
"text/x-csharp": "C# source code", | |
"text/x-basic": "Basic source code", | |
"application/x-arcgis-gp-server": "ArcGIS Geoprocessing Service (GPServer)", | |
"application/vnd.esri.connection.ags": "ArcGIS Server Connection File", | |
"application/x-arcgis-online-map": "ArcGIS Online Map", | |
"text/x-diff": "Diff", | |
"image/x-rpf-cc": "Coastal Charts", | |
"image/x-rpf-vfr_tac": "VFR Terminal Area Chart", | |
"video/x-msvideo": "Audio Video Interleave File", | |
"image/x-rpf-mim2": "Military Installation Maps, 2 (MIM2)", | |
"image/x-rpf-mim1": "Military Installation Maps, 1 (MIM1)", | |
"application/vnd.ms-excel.sheet.macroenabled.12": "Office Open XML Workbook (macro-enabled)", | |
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "Office Open XML Workbook Template", | |
"text/richtext": "Rich Text", | |
"text/x-c++src": "C++ source code", | |
"application/xml-dtd": "XML Document Type Definition", | |
"application/x-xz": "XZ Archive", | |
"application/vnd.ms-powerpoint.slide.macroenabled.12": "PowerPoint Slide with Macros", | |
"application/vnd.oasis.opendocument.formula-template": "OpenDocument v1.0: Formula document used as template", | |
"application/x-sh": "UNIX/LINUX Shell Script", | |
"application/x-arcgis-geometry-server": "ArcGIS Geometry Service (GeometryService)", | |
"image/x-vnd.gxf": "GXF (Grid eXchange File)", | |
"image/x-rpf-combatc_100": "Combat Chart (1:100,000)", | |
"application/x-arcgis-globe-server-layer": "ArcGIS Globe Service Layer (GlobeService Layer)", | |
"application/x-arcgis-online-item": "ArcGIS Online", | |
"model/vnd.dwf": "Design Web Format (DWF)", | |
"image/x-rpf-cityg_14_700": "City Graphics (1:14,700)", | |
"text/x-assembly": "Assembler source code", | |
"image/vnd.adobe.premiere": "Premiere 6 Project", | |
"application/vnd.mapinfo": "MapInfo Interchange Format", | |
"image/x-rpf-cityg_21": "City Graphics (1:21,000)", | |
"image/x-rpf-cityg_22": "City Graphics (1:22,000)", | |
"image/x-rpf-cityg_23": "City Graphics (1:23,000)", | |
"image/x-rpf-cityg_25": "City Graphics (1:25,000)", | |
"image/x-rpf-cityg_26": "City Graphics (1:26,000)", | |
"text/x-vhdl": "VHDL source code", | |
"image/x-rpf-cityg_20": "City Graphics (1:20,000)", | |
"application/x-ascii-log": "ASCII Log", | |
"image/x-rpf-cityg_18": "City Graphics (1:18,000)", | |
"application/vnd.google-earth.kml+xml": "Keyhole Markup Language (KML)", | |
"image/x-rpf-cityg_12": "City Graphics (1:12,000)", | |
"image/x-rpf-cityg_10": "City Graphics (1:10,000)", | |
"image/x-rpf-cityg_11": "City Graphics (1:11,000)", | |
"application/ddms4.1+xml": "DDMS 4.1", | |
"image/x-rpf-cityg_16": "City Graphics (1:16,000)", | |
"image/x-rpf-cityg_17": "City Graphics (1:17,000)", | |
"image/x-rpf-cityg_14": "City Graphics (1:14,000)", | |
"image/x-rpf-cityg_15": "City Graphics (1:15,000)", | |
"text/x-cobol": "COBOL source code", | |
"application/x-arcgis-mobile-server": "ArcGIS Mobile Service (MobileService)", | |
"application/vnd.ogc_sld": "Styled Layer Descriptor (SLD)", | |
"application/xv+xml": "Flex MXML", | |
"text/vnd.graphviz": "Graphviz DOT", | |
"image/x-vnd.grd": "Golden Software Grid", | |
"image/x-rpf-cityg_36": "City Graphics (1:36,000)", | |
"image/x-rpf-cityg_35": "City Graphics (1:35,000)", | |
"application/vnd.adobe.air-application-installer-package+zip": "Adobe AIR Installer", | |
"image/x-dted": "Digital Terrain Elevation Data (DTED)", | |
"application/x-tika-msoffice": "MS Office File", | |
"image/x-rpf-cityg_21_120": "City Graphics (1:21,120)", | |
"image/x-rpf-cityg_16_666": "City Graphics (1:16,666)", | |
"image/x-rpf-lfc-day": "Low Flying Chart (day) (LFC_day)", | |
"text/asp": "Active Server Page (ASP)", | |
"application/vnd.ogc_xml": "OGC XML WebService", | |
"image/x-rpf-tpc": "Tactical Pilotage Chart (TPC)", | |
"text/x-chdr": "C source code header", | |
"application/vnd.ms-outlook": "Microsoft Outlook Message", | |
"text/x-common-lisp": "Common Lisp source code", | |
"application/vnd.esri.gp.tool": "GP Tool", | |
"application/vnd.ms-excel": "Microsoft Excel Spreadsheet", | |
"application/ddms2+xml": "DDMS 2.0", | |
"application/smil+xml": "SMIL Multimedia", | |
"image/x-rpf-opg": "Operational Planning Graphic (OPG)", | |
"image/x-rpf-vfr_hrc": "VFR Helicopter Route Chart (VFR_HRC)", | |
"application/x-archive": "Archiver", | |
"text/x-vbasic": "Visual basic source code", | |
"text/aspdotnet": "ASP .NET (ASP.NET)", | |
"application/vnd.safe.fmw": "FME Workbench (FMW)", | |
"application/x-hdf": "Hierarchical Data Format File", | |
"application/x-arcgis-map-server": "ArcGIS Map Service (MapService)", | |
"application/xslt+xml": "XSL Transformations (XSLT)", | |
"application/vnd.apple.pages": "Apple Pages", | |
"application/vnd.oasis.opendocument.text-master": "OpenDocument v1.0: Global Text document", | |
"application/vnd.ms-powerpoint.template.macroenabled.12": "PowerPoint Template with Macros", | |
"text/x-verilog": "Verilog source code", | |
"application/vnd.ms-word.template.macroenabled.12": "Office Open XML Document Template (macro-enabled)", | |
"text/x-rsrc": "R source code", | |
"image/x-rpf-jnc": "Jet Navigation Chart (JNC)", | |
"application/x-las": "Lidar (LIDAR)", | |
"audio/midi": "Musical Instrument Digital Interface (MIDI)", | |
"application/x-arcgis-geodata-server": "ArcGIS GeoData Service (GeoDataService)", | |
"application/x-laz": "Compressed Lidar File (LIDAR)", | |
"text/x-eiffel": "Eiffel source code", | |
"application/x-fme-server-repository": "FME Server Repository", | |
"image/x-mrsid": "MrSID", | |
"text/x-groovy": "Groovy source code", | |
"text/x-csrc": "C source code", | |
"text/x-rexx": "Rexx source code", | |
"image/x-rpf-jog": "Joint Operations Graphic (JOG)", | |
"text/x-coldfusion": "ColdFusion source code", | |
"text/x-log": "application log", | |
"image/gif": "Graphics Interchange Format (GIF)", | |
"application/vnd.oasis.opendocument.graphics": "OpenDocument v1.0: Graphics document (Drawing)", | |
"image/x-vnd.adrg_overview": "ADRG Overview", | |
"image/x-vnd.dem": "USGS ASCII DEM", | |
"application/vnd.openxmlformats-officedocument.presentationml.slideshow": "Office Open XML Presentation Slideshow", | |
"application/x-mspublisher": "Microsoft Publisher", | |
"image/x-rpf-cityg": "City Graphics", | |
"image/x-vnd.ddf": "USGS SDTS DEM", | |
"application/ddms+xml": "DDMS", | |
"application/vnd.mindjet.mindmanager": "MindManager", | |
"text/x-expect": "Expect Script", | |
"application/wsdl+xml": "WSDL", | |
"application/vnd.ms-excel.addin.macroenabled.12": "Office Open XML Workbook Add-in (macro-enabled)", | |
"image/x-rpf-combatc": "Combat Chart", | |
"video/ogg": "Ogg Video File", | |
"image/x-rpf-onc": "Operational Navigation Chart (ONC)", | |
"text/x-lua": "Lua source code", | |
"application/vnd.oasis.opendocument.text-template": "OpenDocument v1.0: Text document used as template", | |
"image/x-rpf-atc": "Series 200 Air Target Chart (ATC)", | |
"application/vnd.apple.numbers": "Apple Numbers", | |
"text/x-ada": "Ada source code", | |
"application/x-iso9660-image": "ISO 9660 CD-ROM filesystem data", | |
"video/x-f4v": "Flash MP4 Video", | |
"model/x-sldasm": "SolidWorks Assembly Document", | |
"application/vnd.kde.kword": "KWord File", | |
"image/vnd.microsoft.icon": "Icon File (ICO)", | |
"application/x-rpm": "RedHat Package Manager", | |
"application/x-ole-storage": "Windows Installer", | |
"application/vnd.esri.layer": "ESRI Document Layer", | |
"video/x-ms-wmx": "Windows Media Redirector", | |
"application/vnd.voyager": "Voyager Base Mime Type", | |
"application/vnd.esri.3dd": "ArcGlobe Document (3DD)", | |
"application/vnd.wordperfect": "WordPerfect", | |
"audio/x-mod": "MOD", | |
"application/x-sas-putility": "SAS Permanent Utility", | |
"application/x-msmetafile": "Windows Metafile (WMF)", | |
"application/postscript": "PostScript", | |
"image/x-portable-pixmap": "UNIX Portable Bitmap Graphic (PXM)", | |
"application/vnd.esri.lpk": "ESRI Layer Package (LPK)", | |
"application/vnd.esri.loc": "Address Locator", | |
"application/vnd.lotus-freelance": "Lotus Freelance", | |
"application/vnd.esri.layer.cad": "CAD Layer", | |
"application/matlab-mat": "Matlab File", | |
"application/x-vnd.rsets": "WinRAR", | |
"image/x-portable-bitmap": "Portable Bit Map (PBM)", | |
"application/vnd.esri.sxd": "ArcScene Document (SXD)", | |
"audio/x-pn-realaudio-plugin": "RealMedia Player Plug-in", | |
"audio/x-ms-wma": "Windows Media Audio", | |
"application/mp4": "MPEG-4", | |
"image/x-raw-minolta": "Minolta raw image", | |
"audio/x-mpegurl": "MP3 Playlist File", | |
"application/vnd.ms-fontobject": "Embedded OpenType", | |
"application/vnd.ms.vs.sln": "VisualStudio Solution", | |
"application/vnd.ms-wpl": "Web Protection Library", | |
"image/x-raw-sigma": "Sigma raw image", | |
"application/vnd.lotus-approach": "Lotus Approach", | |
"image/x-raw-imacon": "Imacon raw image", | |
"application/x-adobe-indesign": "Adobe InDesign document (INDD)", | |
"video/x-mng": "Multiple Network Graphic", | |
"image/x-niff": "Navy Interchange File Format", | |
"application/vnd.ms-cab-compressed": "Cabinet", | |
"application/x-vnd.nasa_pds": "Nice Label Template", | |
"video/x-ms-wvx": "Windows Media Video", | |
"application/vnd.esri.document": "ESRI Document", | |
"application/vnd.esri.map.data.frame": "Map Frame", | |
"application/x-stuffitx": "StuffIt X Archive", | |
"application/x-sas-catalog": "SAS Catalog", | |
"model/x-stl": "Stereolithography (STL)", | |
"image/x-raw-kodak": "Kodak raw image", | |
"application/vnd.kde.kchart": "KChart File", | |
"image/jpm": "JPEG 2000 Part 6 (JPM) (JP2)", | |
"application/vnd.voyager.unknown": "Unknown Mime Type", | |
"application/x-compress": "Unix Compressed File", | |
"application/x-elc": "Emacs Lisp bytecode", | |
"audio/adpcm": "ADP Audio File", | |
"application/x-onc-dir": "ONC (Operational Nautical Chart) Directory", | |
"application/x-vnd.googlecache": "Google Earth Cache", | |
"video/mj2": "JPEG 2000 Part 3 (Motion JPEG, MJ2)", | |
"application/x-emf": "Extended Metafile (EMF)", | |
"application/vnd.esri.topology": "Topology", | |
"application/winhlp": "WinHelp", | |
"application/x-font-otf": "OpenType Font (OTF)", | |
"audio/x-aac": "Advanced Audio Coding", | |
"application/vnd.esri.mpk": "ESRI Map Package (MPK)", | |
"application/x-filemaker": "FileMaker Pro 7 (FP7)", | |
"application/vnd.openxmlformats-officedocumentument.presentationml.presentation": "PowerPoint Presentation", | |
"application/vnd.esri.layer.service": "WebService Layer", | |
"application/x-silverlight-app": "Silverlight Application Package", | |
"application/x-7z-compressed": "7-zip archive (7zip)", | |
"model/vrml": "VRML World", | |
"image/x-rgb": "Silicon Graphics RGB Bitmap", | |
"application/vnd.esri.layer.mosaic": "Mosaic Layer", | |
"application/x-mapservice-bing": "Bing Map Service", | |
"application/vnd.esri.layer.missing": "Missing Data Layer", | |
"image/x-raw-epson": "Epson raw image", | |
"application/x-sas-fdb": "SAS FDB Consolidation Database File", | |
"application/vnd.ms-batch": "Batch file", | |
"application/x-coreldraw": "Corel Drawing", | |
"application/x-latex": "LaTeX Source Document", | |
"model/x-sab": "Standard ACIS Binary (SAB)", | |
"application/x-sas-audit": "SAS Audit", | |
"image/x-jp2-container": "JPEG 2000 Container Format", | |
"application/vnd.wap.wmlc": "Compiled WML Document", | |
"application/vnd.esri.geometric.network": "Geometric Network", | |
"application/vnd.openxmlformats-officedocumentument.wordprocessingml.template": "Micosoft Word Template", | |
"application/x-futuresplash": "Macromedia FutureSplash File", | |
"application/x-sas-dmdb": "SAS DMDB Data Mining Database File", | |
"application/msword2": "Microsoft Word 2 Document", | |
"application/msword5": "Microsoft Word 5 Document", | |
"application/vnd.apple.ds_store": "Desktop Services Store", | |
"application/x-tex": "TeX Source", | |
"application/x-killustrator": "KIllustrator File", | |
"audio/x-ms-wax": "Windows Media Audio Redirect", | |
"application/x-mapservice-osm": "Open Street Map", | |
"video/x-flc": "FLIC Animation", | |
"video/x-fli": "FLI File Extension", | |
"application/vnd.esri.layer.raster": "Raster Layer", | |
"application/x-font-bdf": "Glyph Bitmap Distribution Format", | |
"image/x-raw-olympus": "Olympus raw image", | |
"application/x-font-pcf": "PaintCAD Font", | |
"application/x-sas-itemstor": "SAS Item Store (ItemStor) File", | |
"application/onenote": "Micosoft OneNote", | |
"application/x-sas-mddb": "SAS MDDB Multi-Dimensional Database File", | |
"image/x-raw-pentax": "Pentax raw image", | |
"application/x-vnd.vtp_bt": "VTP Binary Terrain", | |
"application/x-sas-data": "SAS Data Set", | |
"application/x-sas-program-data": "SAS Stored Program (DATA Step)", | |
"application/x-sas-access": "SAS Access Descriptor", | |
"application/x-seismic-unix": "Seismic Unix", | |
"application/vnd.mif": "FrameMaker Interchange Format", | |
"audio/x-flac": "Free Lossless Audio Codec (FLAC)", | |
"application/vnd.esri.dataset": "ESRI Dataset", | |
"image/x-raw-hasselblad": "Hasselblad raw image", | |
"application/x-sas-view": "SAS Data Set View", | |
"image/x-raw-phaseone": "Phase One raw image", | |
"application/vnd.esri.connection.ims": "ArcIMS Connection File", | |
"application/x-swb": "SolidWorks Older Macro", | |
"application/x-swp": "SolidWorks Macro", | |
"application/x-dvi": "TeX Device Independent Document", | |
"application/vnd.openxmlformats-officedocumentument.presentationml.template": "PowerPoint Template", | |
"application/x-font-printer-metric": "Printer Font Metric", | |
"application/vnd.esri.layer.annotation.coverage": "Coverage Annotation Layer", | |
"application/x-nga-vpf": "Vector Product (VPF)", | |
"application/x-dbase": "dBase", | |
"application/vnd.esri.layer.graphics": "Graphics Layer", | |
"application/x-bittorrent": "BitTorrent", | |
"application/ogg": "Ogg", | |
"video/x-ms-asf": "Advanced Systems Format", | |
"application/x-rar-compressed": "RAR archive", | |
"image/x-raw-casio": "Casio raw image", | |
"image/x-raw-red": "Red raw image", | |
"application/vnd.esri": "ESRI", | |
"image/x-raw-logitech": "Logitech raw image", | |
"audio/x-pn-realaudio": "Real Audio", | |
"application/vnd.esri.arcinfo.workspace": "ArcInfo Workspace", | |
"chemical/x-pdb": "Brookhaven Protein Databank File", | |
"application/x-java-jnlp-file": "Java Web Start", | |
"application/vnd.kde.kpresenter": "KPresenter File", | |
"application/vnd.esri.relationship.class": "Relationship Class", | |
"application/vnd.voyager.folder": "Folder", | |
"application/vnd.esri.afr": "Function Raster Dataset (AFR)", | |
"application/vnd.lotus-wordpro": "Lotus WordPro", | |
"application/x-nga-vpf-folder": "Vector Product Folder (VPF)", | |
"application/x-shockwave-flash": "Adobe Flash", | |
"application/vnd.tcpdump.pcap": "TCPDump pcap packet capture", | |
"application/vnd.esri.layer.dimension": "Dimension Layer", | |
"application/vnd.kde.kspread": "KSpread File", | |
"application/vnd.lotus-organizer": "Lotus Organizer", | |
"application/mathematica": "Mathematica", | |
"image/x-raw-rawzor": "Rawzor raw image", | |
"application/vnd.esri.layer.tracking.analyst": "Tracking Analyst Layer", | |
"application/vnd.esri.layer.arcgis.server": "ArcGIS Server Layer", | |
"application/x-font-linux-psf": "Photoshop Proof Settings File", | |
"application/fits": "Flexible Image Transport System (FITS)", | |
"application/vnd.esri.layer.group": "Group Layer", | |
"x-conference/x-cooltalk": "Cooltalk Audio", | |
"application/x-ms-thumbs-db": "Thumbs.db", | |
"application/vnd.openofficeorg.extension": "OpenOffice Extension", | |
"image/x-raw-leaf": "Leaf raw image", | |
"application/vnd.esri.layer.raster.catalog.gdb": "Geodatabase Raster Catalog Layer", | |
"model/x-slddrt": "SolidWorks Sheet Document", | |
"model/x-slddrw": "SolidWorks Drawing Document", | |
"image/x-raw-mamiya": "Mamiya raw image", | |
"application/vnd.esri.layer.feature": "Feature Layer", | |
"application/x-director": "Shockwave Movie", | |
"model/x-sldprt": "SolidWorks Part Document", | |
"application/vnd.esri.avl": "ArcView Legend", | |
"application/vnd.esri.layer.ims": "IMS Layer", | |
"application/x-java-pack200": "Pack200 Packed Jar File", | |
"application/vnd.esri.axl": "ArcXML Document", | |
"image/x-jp2-codestream": "JPEG 2000 Codestream", | |
"video/3gpp": "3GPP Multimedia", | |
"audio/mp4": "MPEG-4 Video", | |
"application/x-e57": "E57", | |
"application/vnd.voyager.folder.info": "Folder Info", | |
"application/vnd.openxmlformats-officedocumentument.spreadsheetml.template": "Excel Template", | |
"application/vnd.openxmlformats-officedocumentument.presentationml.slideshow": "PowerPoint Slide Show", | |
"application/x-sas-data-index": "SAS Data Set Index", | |
"image/x-raw-adobe": "Adobe Digital Negative (DNG)", | |
"application/vnd.koan": "SSEYO Koan File", | |
"application/vnd.openxmlformats-officedocumentument.presentationml.slide": "PowerPoint Slide", | |
"image/x-raw-fuji": "Fuji raw image", | |
"application/vnd.openxmlformats-officedocumentument.spreadsheetml.sheet": "Excel Workbook", | |
"application/vnd.esri.pmf": "Published Map (PMF)", | |
"application/x-vnd.quickbird.til": "Quickbird Tile Info (TIL)", | |
"application/x-sas-transport": "SAS Transport File", | |
"application/vnd.esri.memory.dataset": "Memory Dataset", | |
"image/x-raw-canon": "Canon raw image", | |
"application/x-font-type1": "ASCII Printer Font", | |
"image/x-portable-graymap": "Portable Graymap Graphic (PGM)", | |
"application/vnd.esri.gdb": "ESRI Geodatabase", | |
"application/vnd.adobe.aftereffects.template": "Adobe After Effects Template", | |
"video/vnd.mpegurl": "MPEG URL", | |
"application/vnd.adobe.aftereffects.project": "Adobe After Effects Project", | |
"application/vnd.openxmlformats-officedocumentument.wordprocessingml.documentument": "Micosoft Word Doc", | |
"application/vnd.ms-word.documentument.macroenabled.12": "Office Open with Macros", | |
"application/x-cdlink": "Virtual CD-ROM CD Image File", | |
"video/x-ms-wm": "Windows Media File Extension", | |
"application/x-sas-utility": "SAS Utility", | |
"image/x-pict": "Apple Macintosh QuickDraw/PICT Format", | |
"image/cgm": "Computer Graphics Metafile (CGM)", | |
"application/vnd.esri.layer.annotation": "Annotation Layer", | |
"application/illustrator": "Adobe Illustrator Artwork (AI)", | |
"image/x-portable-anymap": "Portable Any Map (PNM)", | |
"application/vnd.ms-htmlhelp": "MS Help", | |
"image/x-xwindowdump": "X Windows Dump", | |
"video/vnd.vivo": "VivoActive Video", | |
"application/x-sas-backup": "SAS Backup", | |
"application/seismic-segy": "SEG-Y Seismic Data", | |
"application/vnd.wap.wmlscriptc": "Compiled WML Script", | |
"application/x-foxmail": "Foxmail Email File", | |
"video/x-sgi-movie": "QuickTime Movie", | |
"application/x-stuffit": "Stuffit", | |
"application/vnd.ms.vs.dsw": "Visual C++ Project" | |
}, | |
field_names = { | |
bytes: "File Size", | |
extent_rough: "Extent (General)", | |
available: "Available", | |
downloadable: "Downloadable", | |
has_aux_files: "Has Aux Files", | |
metafs: "MetaFS", | |
ondemand: "On Demand", | |
onfs: "On Filesystem", | |
crawled: "Last Crawled", | |
created: "Created", | |
creation_date: "Creation Date", | |
discovered: "Discovered Time", | |
end_time: "End Time", | |
ags_type: "ArcGIS Online Type", | |
ags_format_keyword: "ArcGIS Online Keyword", | |
indexed: "Last Indexed", | |
last_printed: "Last Printed", | |
last_saved: "Last Saved", | |
modified: "Modified", | |
modified_date: "Modified Date", | |
start_time: "Start Time", | |
hrefs: "Links", | |
aux_file_count: "Aux File Count", | |
character_count: "Character Count", | |
columnCount: "Column Count", | |
dataCount: "Data Count", | |
discoveredCount: "Discovered Count", | |
docCount: "Document Count", | |
first_crawl: "First Crawl", | |
hpsecurity: "Hpfs Security", | |
last_crawl: "Last Crawl", | |
layerCount: "Layer Count", | |
line_count: "Line Count", | |
numBands: "Number of Bands", | |
num_points: "Number of Points", | |
num_segments: "Number of Segments", | |
page_count: "Page Count", | |
paragraph_count: "Paragraph Count", | |
rowCount: "Row Count", | |
scale: "Scale", | |
slide_count: "Slide Count", | |
tableJoinCount: "Table Join Count", | |
thumb_try_count: "Thumb Try Count", | |
timeToBuildLayer: "Time To Build Layer", | |
timeToDrawSmall: "Time To Draw Small", | |
timeToOpen: "Time To Open", | |
timeToParse: "Time To Parse", | |
transparency: "Transparency", | |
word_count: "Word Count", | |
edit_time: "Edit Time", | |
indexingTimeout: "Indexing Timeout", | |
metaBytes: "Metadata Size", | |
mime: "Format", | |
format_type: "Format Type", | |
format_category: "Format Category", | |
format_keyword: "Format Keyword", | |
format_company: "Format Company", | |
format_app: "Format Application", | |
"Content-Type": "Content-Type", | |
application_name: "Application Name", | |
application_version: "Application Version", | |
author: "Author", | |
comments: "Comments", | |
company: "Company", | |
contentHash: "Content Hash", | |
content_status: "Content Status", | |
copyright: "Copyright", | |
creator: "Creator", | |
extent: "Extent", | |
extent_norm: "Extent WGS84", | |
fgdc_access_constraint: "FGDC Access Constraint", | |
fgdc_caldate: "FGDC Calendar Date", | |
fgdc_meta_address: "FGDC Metadata Contact Address", | |
fgdc_meta_address_type: "FGDC Metdata Contract Address Type", | |
fgdc_meta_city: "FGDC Metadata Contact City", | |
fgdc_meta_org: "FGDC Metadata Organization", | |
fgdc_meta_person: "FGDC Metadata Person", | |
fgdc_meta_postal_code: "FGDC Metadata Contact Postal Code", | |
fgdc_meta_state: "FGDC Metadata Contact State", | |
fgdc_originator: "FGDC Originator", | |
fgdc_progress: "FGDC Progress", | |
fgdc_pubdate: "FGDC Publication Date", | |
fgdc_purpose: "FGDC Purpose", | |
fgdc_title: "FGDC Title", | |
fgdc_update: "FGDC Update", | |
fgdc_use_constraint: "FGDC Use Constraint", | |
fileExtension: "File Extension", | |
folder: "Folder", | |
geometryType: "Geometry Type", | |
host: "Host", | |
hotLinkType: "Hot Link Type", | |
id: "Id", | |
iso_abstract: "ISO Abstract", | |
iso_dataset_creation_date: "ISO Dataset Creation Date", | |
iso_dataset_language: "ISO Dataset Language", | |
iso_dataset_title: "ISO Dataset Title", | |
iso_metadata_classification: "ISO Metadata Classification", | |
iso_metadata_file_identifier: "ISO Metadata File Identifier", | |
iso_metadata_hierarchy_level: "ISO Metadata Hierarchy Level", | |
iso_metadata_language: "ISO Metadata Language", | |
iso_metadata_parent_identifier: "ISO Metadata Parent Identifier", | |
iso_metadata_releasability: "ISO Metadata Releasability", | |
iso_reference_system: "ISO Reference System", | |
iso_resource_classification: "ISO Resource Classification", | |
iso_resource_releasability: "ISO Resource Releasability", | |
iso_spatial_representation: "ISO Spatial Representation", | |
language: "Language", | |
last_author: "Last Author", | |
layerDesc: "Layer Description", | |
manager: "Manager", | |
nato_abstract: "NATO Abstract", | |
nato_dataset_creation_date: "NATO Dataset Creation Date", | |
nato_dataset_language: "NATO Dataset Language", | |
nato_dataset_title: "NATO Dataset Title", | |
nato_metadata_classification: "NATO Metadata Classification", | |
nato_metadata_file_identifier: "NATO Metadata File Identifier", | |
nato_metadata_hierarchy_level: "NATO Metadata Hierarchy Level", | |
nato_metadata_language: "NATO Metadata Language", | |
nato_metadata_parent_identifier: "NATO Metadata Parent Identifier", | |
nato_metadata_releasability: "NATO Metadata Releasability", | |
nato_reference_system: "NATO Reference System", | |
nato_resource_classification: "NATO Resource Classification", | |
nato_resource_releasability: "NATO Resource Releasability", | |
nato_spatial_representation: "NATO Spatial Representation", | |
nato_topic_category: "NATO Topic Category", | |
pixelType: "Pixel Type", | |
point_dd: "Point (Decimal Degrees)", | |
presentation_format: "Presentation format", | |
producer: "Producer", | |
product: "Product", | |
rasterSize: "Raster Size", | |
rasterType: "Raster Type", | |
revision_number: "Revision Number", | |
schemaHash: "Schema Hash", | |
series: "Series", | |
server: "Server", | |
service: "Service", | |
source: "Source", | |
srs_code: "Spatial Reference (code)", | |
template: "Template", | |
title: "Title", | |
uri: "Uri", | |
version: "Version", | |
CADLayers: "CAD Layer", | |
parameter_type: "Parameter Type", | |
ags_formats: "Supported Formats", | |
ags_interface: "Supported Interfaces", | |
ags_operation: "Supported Operations", | |
ags_view_in: "View In", | |
category: "Category", | |
column: "Column", | |
dpath: "Path", | |
fgdc_place: "FGDC Place", | |
fgdc_theme: "FGDC Theme", | |
fme_role: "FME Role", | |
fme_cmdline: "FME Command Line", | |
fme_service: "FME Service", | |
fme_transformer: "FME Transformer", | |
framework: "Framework", | |
indexingError: "Indexing Error", | |
indexingWarning: "Indexing Warning", | |
iso_thematic_keyword: "ISO Thematic Keyword", | |
iso_topic_category: "ISO Topic Category", | |
keywords: "Keywords", | |
missingDataPath: "Missing Data", | |
missing_meta_fields: "Missing Metadata Fields", | |
nato_thematic_keyword: "NATO Thematic Keyword", | |
subject: "Subject", | |
unknownField: "Unknown Field", | |
ft_fgdc_abstract: "FGDC Abstract", | |
ftt_notes: "Notes", | |
ftt_text: "Text", | |
fu_area: "Area", | |
fu_brightness: "Brightness", | |
fu_contrast: "Contrast", | |
fu_extent_aspect: "Extent Aspect", | |
fu_maxScale: "Maximum Scale", | |
fu_minScale: "Minimum Scale", | |
fu_pixHeight: "Pixel Height", | |
fu_pixWidth: "Pixel Width", | |
list: "List", | |
list_order: "List Order", | |
location: "Location", | |
name: "Name", | |
path: "Path", | |
properties: "Properties", | |
score: "Relevance", | |
srs: "Spatial Reference", | |
subtype: "Subtype", | |
thumbTimeout: "Thumb Timeout", | |
type: "Type", | |
_absolute_path: "Absolute Path", | |
_explain: "Query Explanation", | |
sec_class: "Security Classification", | |
sec_class_list: "All Classificaions", | |
sec_class_orig: "Original Classification" | |
}, | |
field_descriptions = { | |
bytes: "File size (on disk)", | |
extent_rough: "Low precision", | |
available: "false if data is missing", | |
downloadable: "Downloadable", | |
has_aux_files: "Has auxiliary files", | |
metafs: "Metadata is stored as a file", | |
ondemand: "Draw the image when it is requested", | |
crawled: "Last time the crawler found the entry", | |
created: "Created", | |
creation_date: "Creation Date", | |
discovered: "When the crawler first found the entry", | |
end_time: "End Time", | |
indexed: "Last time entry was indexed", | |
last_printed: "Last Printed", | |
last_saved: "Last Saved", | |
modified: "Last modified time", | |
modified_date: "Modified Date", | |
start_time: "Start Time", | |
aux_file_count: "How many auxiliary files exist", | |
character_count: "Character Count", | |
columnCount: "Number of Columns", | |
dataCount: "How many data sources are used", | |
discoveredCount: "Number of times the Crawler has found this entry", | |
docCount: "How many documents does this appear in", | |
first_crawl: "First Crawl", | |
hpsecurity: "Hpfs Security", | |
last_crawl: "Last Crawl", | |
layerCount: "For Maps -- how many layers are in the map? For Data -- in how many layers (across all maps) does the data set appear?", | |
line_count: "Line Count", | |
numBands: "Number of Bands", | |
num_points: "Number of Points", | |
num_segments: "Number of Segments", | |
page_count: "Page Count", | |
paragraph_count: "Paragraph Count", | |
rowCount: "Number of Rows", | |
scale: "Scale", | |
slide_count: "Slide Count", | |
tableJoinCount: "Number of Table Joins", | |
thumb_try_count: "How many times has the thumbnail tried to draw", | |
timeToBuildLayer: "How long it takes the indexer to build the layer file", | |
timeToDrawSmall: "How long it takes to draw the small image", | |
timeToOpen: "How long it takes the indexer to open this entry", | |
timeToParse: "How long it takes the indexer to parse this entry", | |
transparency: "Layer transparency value (0-100)", | |
word_count: "Word Count", | |
edit_time: "Edit Time", | |
indexingTimeout: "How long it too for indexing to timeout (in MS)", | |
metaBytes: "Size of the Metadata (in bytes)", | |
"Content-Type": "Content-Type", | |
application_name: "Application Name", | |
application_version: "Application Version", | |
author: "Author", | |
comments: "Comments", | |
company: "Company", | |
contentHash: "Hashed value for the content -- identical values represent various entries with identical content", | |
content_status: "Content Status", | |
copyright: "Copyright", | |
creator: "Creator", | |
extent: "Extent", | |
extent_norm: "Extent normalized to WGS84", | |
fileExtension: "File Extension", | |
folder: "Containing Folder", | |
host: "Host", | |
hotLinkType: "Hot Link Type", | |
id: "Id", | |
language: "Language", | |
last_author: "Last Author", | |
layerDesc: "Descriptive text or comments about the layer", | |
manager: "Manager", | |
pixelType: "Pixel Type", | |
point_dd: "Point in Decimal Degrees", | |
presentation_format: "Presentation Format", | |
producer: "Producer", | |
product: "Product", | |
rasterSize: "Raster Size", | |
rasterType: "Raster Type", | |
revision_number: "Revision Number", | |
schemaHash: "Hashed value for the schema -- identical values represent various entries with identical schemas", | |
series: "Series", | |
server: "Server", | |
service: "Service", | |
source: "Source", | |
template: "Template", | |
title: "Title", | |
uri: "Uri", | |
version: "Version", | |
CADLayers: "CAD Layers", | |
ags_interface: "ArcGIS Interface", | |
ags_view_in: "ArcGIS Server View In", | |
category: "Category", | |
column: "Name of the Columns available in the data set", | |
dpath: "Navigable Path", | |
framework: "The framework suppored by this item (ESRI, GDAL, PDF, etc)", | |
keywords: "Keywords", | |
subject: "Subject", | |
unknownField: "Collection of unknown fields", | |
ftt_notes: "Notes", | |
ftt_text: "Text", | |
fu_area: "Geographic area of the entry (in XXX units)", | |
fu_brightness: "image brightness", | |
fu_contrast: "Image Contrast", | |
fu_extent_aspect: "Extent Aspect", | |
fu_maxScale: "Layer setting -- maximum scale", | |
fu_minScale: "Layer setting -- minimum scale", | |
fu_pixHeight: "Pixel Height in Map Units", | |
fu_pixWidth: "Pixel Width in Map Units", | |
list: "List", | |
list_order: "List Order", | |
location: "The crawler location that found this data", | |
name: "Name", | |
path: "Path", | |
properties: "Attributes", | |
score: "Query Relevance", | |
srs: "Spatial Reference for the given entry", | |
subtype: "Subtype", | |
thumbTimeout: "How long the thumb has tried building", | |
type: "Entry Type" | |
}, | |
field_values = { | |
ags_operation: { | |
SubmitJob: "Submit Job", | |
Cut: "Cut", | |
Query: "Query", | |
Offset: "Offset", | |
ExportMap: "Export Map", | |
Densify: "Densify", | |
Lengths: "Lengths", | |
Buffer: "Buffer", | |
ConvexHul: "Convex Hull", | |
Simplify: "Simplify", | |
GenerateKML: "Generate KML", | |
TrimExtend: "Trim/Extend", | |
FindAddressCandidates: "Find Address Candidates", | |
Reshape: "Reshape", | |
RelationOperation: "Relation Operation", | |
ExportImage: "Export Image", | |
Project: "Project", | |
Download: "Download", | |
Relation: "Relation", | |
Find: "Find", | |
Distance: "Distance", | |
Union: "Union", | |
ExecuteTask: "Execute Task", | |
ReverseGeocode: "Reverse Geocode", | |
Intersect: "Intersect", | |
Generalize: "Generalize", | |
Difference: "Difference", | |
AreasAndLengths: "Areas And Lengths", | |
Identify: "Identify", | |
LabelPoints: "Label Points", | |
AutoComplete: "Auto Complete" | |
}, | |
ags_view_in: { | |
ArcGisExplorer: "ArcGIS Explorer", | |
GoogleEarth: "Google Earth", | |
ArcGisJavascript: "ArcGIS Javascript", | |
BingMaps: "Bing Maps", | |
ArcGisDotCom: "ArcGIS.com", | |
VirtualEarth: "Virtual Earth", | |
GoogleMaps: "Google Maps" | |
}, | |
indexingError: { | |
indexingTimeout: "Indexing Timeout", | |
errorReadingStructure: "Error Reading Structure", | |
errorSavingConnection: "Error Saving Connection" | |
}, | |
indexingWarning: { | |
errorSavingLayer: "Error Saving Layer", | |
errorSavingImage: "Error Saving Image", | |
md5Timeout: "MD5 Timeout" | |
}, | |
properties: { | |
hasMetadata: "Has Metadata", | |
spatial: "Spatial Data", | |
hotLinks: "Layer supports ArcView 3x style hot links", | |
stub: "Placeholder", | |
hasMissingData: "Contains Missing Data", | |
indexingError: "Indexing Error", | |
absolutePaths: "Absolute Paths", | |
misingThumbnail: "Missing Thumbnail", | |
hasTransparency: "Has Transparency", | |
thumbTimedOut: "Thumbnail Timed Out", | |
downloadable: "Downloadable", | |
missingRequiredMetadataFields: "Missing Required Metadata Fields", | |
hyperLinks: "Layer supports Hyper Links", | |
pyramids: "Pyramids Built", | |
rasterized: "Rasterized", | |
thumb_stopped_trying: "Thumbnail Won't Draw", | |
mapTips: "Layer uses Map Tips", | |
hasVisibleRange: "Has Visible Range", | |
hasBrightness: "Has Brightness", | |
hasContrast: "Has Contrast", | |
ags_fused_cache: "ArcGIS Fused Cache", | |
memoryDataset: "Uses Memory Dataset" | |
}, | |
srs: { | |
Unknown: "Unknown Spatial Reference", | |
Custom: "Custom Spatial Reference" | |
}, | |
subtype: { | |
esriDTCadastralFabric: "Cadastral Fabric", | |
wms_server: "WMS Server", | |
esriDTRasterBand: "Raster Band", | |
pdf: "PDF Document", | |
esriDTContainer: "Any Container Dataset", | |
esriDTNetworkDataset: "Network Dataset", | |
python: "Python Script", | |
missing: "Missing Data", | |
esriDTTopology: "Topology", | |
file: "File", | |
FeatureServer: "Feature Server", | |
esriGPServerTool: "GP Server Tool", | |
esriDTRepresentationClass: "Feature Class Representation", | |
ImageServer: "Image Server", | |
workbench: "Workbench", | |
gpx: "GPX", | |
wms: "WMS Service", | |
esriDTToolbox: "Toolbox", | |
esriDTLocator: "Address Locator", | |
GPServer: "Geoprocessing Server", | |
esriDTTin: "Tin Dataset", | |
esriGPCustomTool: "GP Custom Tool", | |
esriGPScriptTool: "GP Script Tool", | |
GeocodeServer: "Geocode Server", | |
MapServer: "Map Server", | |
esriDTText: "Text Dataset", | |
Access: "Personal Geodatabase", | |
esriDTAny: "Any Dataset", | |
esriDTRasterCatalog: "Raster Catalog", | |
esriDTTerrain: "Terrain dataset", | |
csw_server: "CSW Server", | |
esriGPFunctionTool: "GP Function Tool", | |
esriDTGeometricNetwork: "Geometric Network", | |
GlobeServer: "Globe Server", | |
workspace: "Workspace", | |
Sde: "ArcSDE Geodatabase", | |
esriDTCadDrawing: "CadDrawing Dataset", | |
GeoDataServer: "GeoData Server", | |
esriDTRelationshipClass: "Relationship Class", | |
FileGDB: "File Geodatabase", | |
repository: "Repository", | |
AGS: "ArcGIS Server", | |
map: "Map", | |
esriDTFeatureClass: "Feature Class", | |
esriDTTool: "Tool", | |
NAServer: "Network Analyst Server", | |
esriDTFeatureDataset: "Feature Dataset", | |
esriDTSchematicDataset: "Schematic Dataset", | |
esriDTTable: "Table Dataset", | |
layer: "Layer", | |
esriDTGeo: "Any Geo Dataset", | |
esriDTPlanarGraph: "Planar Graph", | |
Vpf: "VPF", | |
esriGPModelTool: "GP Model Tool", | |
dataset: "Dataset", | |
server: "Server", | |
GeometryServer: "Geometry Server" | |
}, | |
type: { | |
connection: "Connection", | |
fmeserver: "FME Server", | |
toolbox: "Toolbox", | |
error: "Error", | |
service_layer: "Service Layer", | |
tool: "Tool", | |
data: "Data", | |
dataFrame: "Data Frame", | |
layer: "Layer", | |
script: "Script", | |
database: "Database", | |
folder: "Folder", | |
file: "File", | |
service: "Service", | |
fme: "FME", | |
doc: "Document", | |
server: "Server" | |
}, | |
sec_class: { | |
U: "Unclassified", | |
S: "Secret", | |
R: "Restricted", | |
C: "Confidential", | |
NS: "NATO Secret", | |
NR: "NATO Restricted", | |
O: "Official", | |
TS: "Top Secret", | |
NC: "NATO Confidential", | |
CTS: "Cosmic Top Secret" | |
}, | |
sec_class_list: { | |
U: "Unclassified", | |
S: "Secret", | |
R: "Restricted", | |
C: "Confidential", | |
NS: "NATO Secret", | |
NR: "NATO Restricted", | |
O: "Official", | |
TS: "Top Secret", | |
NC: "NATO Confidential", | |
CTS: "Cosmic Top Secret" | |
}, | |
sec_class_orig: { | |
U: "Unclassified", | |
S: "Secret", | |
R: "Restricted", | |
C: "Confidential", | |
NS: "NATO Secret", | |
NR: "NATO Restricted", | |
O: "Official", | |
TS: "Top Secret", | |
NC: "NATO Confidential", | |
CTS: "Cosmic Top Secret" | |
} | |
}, | |
removePrefixList = ["fs_", "ft_", "fh_", "fi_", "fl_", "fd_", "ff_", "fu_", "fp_", "fy_", "fm_", "fb_", "tag_", "meta_", "fss_", "grp_"], | |
removePrefixHash = {}, | |
humanize = function(value) { | |
return value.replace(/_/g, " ").replace(/(\w+)/g, function(match) { | |
return match.charAt(0).toUpperCase() + match.slice(1) | |
}) | |
}, | |
lookup = function(key, map, doHumanize) { | |
var translated = map[key]; | |
return translated ? (translated.indexOf("(") !== -1 && (translated = translated.replace(/.*\(|\)/gi, "")), translated) : doHumanize ? humanize(key) : key | |
}; | |
return { | |
getType: function(key) { | |
return lookup(key, file_formats) | |
}, | |
getTypeAbbr: function(key) { | |
var val = lookup(key, file_formats), | |
pos = val.indexOf("("); | |
if (pos !== -1) { | |
var endpos = val.indexOf(")"); | |
val = val.substring(pos + 1, endpos) | |
} | |
return val | |
}, | |
getFieldName: function(key) { | |
var idx = key.indexOf("_"); | |
if (idx > -1) { | |
var prefix = key.substring(0, idx + 1); | |
removePrefixHash[prefix] && (key = key.replace(prefix, "")) | |
} | |
return lookup(key, field_names, !0) | |
}, | |
getFieldDesc: function(key) { | |
return lookup(key, field_descriptions) | |
}, | |
getLocation: function(key) { | |
return key = key.replace("_crawl", ""), lookup(key, locations) | |
}, | |
getText: function(type, key) { | |
var typeOptions = field_values[type]; | |
if (typeOptions) { | |
var translation = typeOptions[key]; | |
if (translation) return translation | |
} | |
return humanize(key) | |
}, | |
translateFilterNames: function(filters) { | |
var self = this; | |
$.each(filters, function(index, item) { | |
"" === item.value && (item.value = self.getFieldName(item.field)) | |
}) | |
}, | |
init: _init | |
} | |
}), angular.module("voyager.util").factory("urlUtil", function(filterService) { | |
"use strict"; | |
var lastUrl = "search", | |
getPrefix = function(url) { | |
var prefix = "&"; | |
return url.indexOf("?") === -1 && (prefix = "?"), prefix | |
}; | |
return { | |
buildSearchUrl2: function(solrParams, page, mapView, view, sort) { | |
var url = "search", | |
sep = "?"; | |
return $.each(solrParams, function(key, value) { | |
"*:*" !== value && "sort" !== key && (url += sep + key + "=" + value, sep = "&") | |
}), $.each(filterService.getFilters(), function(index, facet) { | |
url += "" !== facet.filter ? sep + "fq=" + facet.filter + ":" + facet.name : sep + "fq=" + encodeURIComponent(facet.name), sep = "&" | |
}), page > 1 && (url += getPrefix(url) + "pg=" + page), mapView || (mapView = "0 0 0"), url += getPrefix(url) + "vw=" + mapView, view && (url += getPrefix(url) + "view=" + view), sort && (url += getPrefix(url) + "sort=" + sort), lastUrl = url, url | |
}, | |
getLastUrl: function() { | |
return lastUrl | |
}, | |
updateParam: function(name, oldValue, value) { | |
var toReplace = name + "=" + oldValue, | |
update = name + "=" + value; | |
lastUrl.indexOf(toReplace) !== -1 ? lastUrl = lastUrl.replace(toReplace, update) : this.addParam(name, value) | |
}, | |
addParam: function(name, value) { | |
lastUrl += "&" + name + "=" + value | |
}, | |
removeParam: function(name, value) { | |
var toReplace = "&" + name + "=" + value; | |
lastUrl = lastUrl.replace(toReplace, "") | |
} | |
} | |
}), angular.module("voyager.util").factory("solrUtil", function(config, $http) { | |
"use strict"; | |
function _toFilters(ids) { | |
return ids = _toArray(ids), "fq=id:" + ids.join("+") | |
} | |
function _getFilters(params, $scope) { | |
var filters; | |
return !_.isUndefined(params.id) && params.id.length > 0 ? ($scope.idsFilter = !0, filters = _toFilters(params.id)) : ($scope.idsFilter = !1, filters = $.param(params, !0)), filters | |
} | |
function _toSolrQuery(url, params) { | |
var qs = $.extend({}, params); | |
return "rows" in qs || (qs.rows = 999999), qs.rand = Math.random(), qs.wt = "json", config.root + url + "?" + $.param(qs, !0) | |
} | |
function _stripAugmented(value) { | |
if (value.indexOf(":[") !== -1) { | |
var name = value.substring(0, value.indexOf(":[")); | |
return 0 === name.indexOf("_") && (name = name.replace("_", "")), name | |
} | |
return value | |
} | |
var _toArray = function(val) { | |
return "string" == typeof val ? [val] : _.isUndefined(val) ? [] : val.slice() | |
}; | |
return { | |
toSolrFilters: function(params, $scope) { | |
return _getFilters(params, $scope) | |
}, | |
toSolrQuery: function(url, params) { | |
return _toSolrQuery(url, params) | |
}, | |
search: function(q, fq, fl) { | |
_.isEmpty(q) && (q = "*:*"), _.isEmpty(fl) && (fl = "*"); | |
var p = { | |
q: q, | |
fl: fl | |
}; | |
return _.isEmpty(fq) || (p.fq = fq), $http({ | |
method: "GET", | |
url: _toSolrQuery("solr/v0/select", p) | |
}) | |
}, | |
heatmap: function(bbox, query, level) { | |
var bounds = bbox.split(/ *, */), | |
params = { | |
q: "*:*", | |
rows: 0, | |
facet: !0, | |
"facet.heatmap": "geohash", | |
"facet.heatmap.geom": _.template('["<%=w%> <%=s%>" TO "<%=e%> <%=n%>"]')({ | |
w: Math.max(-180, bounds[0]), | |
s: Math.max(-90, bounds[1]), | |
e: Math.min(180, bounds[2]), | |
n: Math.min(90, bounds[3]) | |
}) | |
}; | |
return level > -1 && (params["facet.heatmap.gridLevel"] = level), params = $.extend(params, query || {}), $http({ | |
url: _toSolrQuery("solr/v0/select", params) | |
}) | |
}, | |
stripAugmented: _stripAugmented | |
} | |
}), angular.module("voyager.util").factory("solrGrunt", function() { | |
"use strict"; | |
function _getSolrParams(params) { | |
var solrParams = {}; | |
return $.each(params, function(key, value) { | |
angular.isUndefined(_nonSolrParams[key]) && "" !== value && (solrParams[key] = value) | |
}), angular.isDefined(solrParams.sort) && (angular.isDefined(solrParams.sortdir) ? solrParams.sort = solrParams.sort + " " + solrParams.sortdir : solrParams.sort = solrParams.sort + " desc"), delete solrParams.sortdir, solrParams | |
} | |
var _nonSolrParams = { | |
vw: !0, | |
view: !0, | |
pg: !0, | |
bbox: !0, | |
bboxt: !0, | |
filter: !0 | |
}; | |
return { | |
getSolrParams: function(params) { | |
return _getSolrParams(params) | |
}, | |
getInput: function(value) { | |
var input = "*:*"; | |
return angular.isDefined(value) && (input = value), input | |
} | |
} | |
}), angular.module("voyager.util").directive("iframeLoad", function() { | |
return { | |
link: function(scope, element, attrs) { | |
scope.frameLoading = "frame-loading", element.on("load", function() { | |
scope.frameLoading = "", scope.$apply() | |
}), attrs.$observe("src", function() { | |
scope.frameLoading = "frame-loading" | |
}) | |
} | |
} | |
}), angular.module("voyager.util").factory("systemService", function($http, $timeout, config, authService) { | |
function _doRestart() { | |
return $http({ | |
method: "POST", | |
url: config.root + restartAPI, | |
headers: { | |
"Content-Type": "application/json" | |
} | |
}) | |
} | |
function _startPollUserInfo(successCallback, interval, initialInterval) { | |
initialInterval = initialInterval || interval, _pollSuccessCallback = successCallback, _pollInterval = interval, _nextPoll(_pollUserInfo, initialInterval) | |
} | |
function _pollUserInfo() { | |
authService.getUserInfo().then(function(resp) { | |
resp ? (_pollSuccessCallback(), _pollPromise = void 0, _pollInterval = void 0, _pollSuccessCallback = void 0) : _nextPoll(_pollUserInfo, _pollInterval) | |
}).catch(function() { | |
_nextPoll(_pollUserInfo, _pollInterval) | |
}) | |
} | |
function _nextPoll(pollCallback, interval) { | |
interval = interval || 1e3, $timeout.cancel(_pollPromise), _pollPromise = $timeout(pollCallback, interval) | |
} | |
var _pollPromise, _pollSuccessCallback, _pollInterval, restartAPI = "api/rest/system/restart"; | |
return { | |
doRestart: function() { | |
return _doRestart() | |
}, | |
checkForLife: function(successCallback, pollInterval, initialInterval) { | |
_startPollUserInfo(successCallback, pollInterval, initialInterval) | |
} | |
} | |
}), angular.module("voyager.security", []), angular.module("voyager.security").controller("AuthBaseCtrl", function($scope, authService, $window, config, localStorageService, configService) { | |
"use strict"; | |
function authFail(response) { | |
error = response.data.error, $scope.error = error | |
} | |
var error; | |
$scope.canRemember = config.rememberMe, $scope.hideDefault = config.homepage.showDefaultCredentials === !1, $scope.consentTextFile = config.customizedLogin.consentTextFile, $scope.setDefaultCred = function() { | |
$scope.user = "admin", $scope.pass = "admin" | |
}, $scope.removeDefault = function() { | |
configService.hideDefaultCredentials().then(function() { | |
$scope.hideDefault = !0 | |
}) | |
}, $scope.authSuccess = function() { | |
"function" == typeof ga && ga("set", "&uid", $scope.user), error = null, $scope.error = error | |
}, $scope.handleEnter = function(ev) { | |
13 === ev.which && $scope.ok() | |
}, $scope.hasError = function() { | |
return !!error | |
}, $scope.ok = function() { | |
_.isEmpty($scope.user) || _.isEmpty($scope.pass) ? (error = !0, $scope.error = "Please enter your username and password") : (error = !1, authService.doLogin($scope, $scope.authSuccess, authFail)) | |
}, $scope.methods = authService.getMethods(), $scope.methods.external && 1 === $scope.methods.all.length && ($window.location.href = $scope.methods.external[0].url), $scope.goExternal = function(method) { | |
$window.location.href = method.url | |
} | |
}), angular.module("voyager.security").controller("AuthCtrl", function($scope, $uibModalInstance, $controller) { | |
"use strict"; | |
$controller("AuthBaseCtrl", { | |
$scope: $scope | |
}); | |
var successCallback = $scope.authSuccess; | |
$scope.authSuccess = function() { | |
successCallback(), $uibModalInstance.close() | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("voyager.security").factory("authService", function($http, config, $q, $log, $analytics) { | |
function _setLoginState(response) { | |
return response && (_isAnonymous = angular.isUndefined(response.data.state) || "anonymous" === response.data.state, _state = response.data.state, _user = response.data.user, response.data.permissions && (permissions = response.data.permissions), response.data.user ? (loggedIn = !0, _sso = !0, _groups = response.data.user.groups) : loggedIn = !1, response.data.methods && (_methods = response.data.methods), observers.forEach(function(entry) { | |
entry(response) | |
}), authCallback && (authCallback(response), authCallback = null)), response | |
} | |
function _getInfoUrl() { | |
var url = config.root + "api/rest/auth/info.json?" + _PERMISSIONS_LIST + "&r=" + (new Date).getTime(); | |
return _sso === !1 && (url += "&sso=false"), url | |
} | |
function _getPrivileges() { | |
return $http.get(_getInfoUrl(), { | |
cache: !1, | |
headers: { | |
"Cache-Control": "no-cache" | |
} | |
}).then(_setLoginState, defaultErrorCallback) | |
} | |
var errorCallback, authCallback, _user, _state, observers = [], | |
loggedIn = !1, | |
permissions = {}, | |
_groups = [], | |
_sso = !0, | |
_isAnonymous = !0, | |
_PERMISSIONS = ["manage", "download", "process", "configure_view", "save_search", "share_saved_search", "view", "tag", "edit_fields", "flag", "view_tags", "show_metadata", "export", "shutdown_restart", "show_rss", "view_analytics"], | |
_PERMISSIONS_LIST = "check=" + _PERMISSIONS.join("&check="), | |
_methods = [], | |
defaultErrorCallback = function(response) { | |
return response.error ? $log.error(response.error) : $log.error("auth failed: " + JSON.stringify(response)), | |
response | |
}, | |
doPost = function(request, action) { | |
return $http({ | |
method: "POST", | |
url: config.root + "api/rest/auth/" + action + ".json", | |
data: request, | |
headers: { | |
"Content-Type": "application/x-www-form-urlencoded" | |
} | |
}).then(function(response) { | |
response.action = action, _setLoginState(response), $analytics.eventTrack("search", {category: action, user: _user.id}) | |
}, errorCallback) | |
}; | |
return { | |
doLogin: function($scope, successHandler, errorHandler) { | |
errorCallback = errorHandler, authCallback = successHandler; | |
var request = "user=" + encodeURIComponent($scope.user) + "&pass=" + encodeURIComponent($scope.pass) + "&" + _PERMISSIONS_LIST; | |
return $scope.keepLoggedIn === !0 && (request += "&rememberMe=true"), doPost(request, "login") | |
}, | |
doLogout: function() { | |
authCallback = null; | |
var request = "check=manage"; | |
doPost(request, "logout"), loggedIn = !1, _sso = !1 | |
}, | |
getPrivileges: function() { | |
return _getPrivileges() | |
}, | |
loadPrivileges: function() { | |
return _.isEmpty(permissions) ? _getPrivileges() : $q.when() | |
}, | |
addObserver: function(obs) { | |
var index = _.findIndex(observers, function(item) { | |
return obs === item | |
}); | |
index === -1 && observers.push(obs) | |
}, | |
removeObserver: function(obs) { | |
observers = _.without(observers, function(item) { | |
return item === obs | |
}) | |
}, | |
isLoggedIn: function() { | |
return loggedIn | |
}, | |
isAnonymous: function() { | |
return _isAnonymous | |
}, | |
hasPermission: function(type) { | |
return permissions[type] && permissions[type] === !0 | |
}, | |
getUser: function() { | |
return _user | |
}, | |
getGroups: function() { | |
return _groups | |
}, | |
getGroupsJoined: function() { | |
return _groups.join() | |
}, | |
getUserInfo: function() { | |
return $http.get(_getInfoUrl()).then(function(res) { | |
return res.data.user | |
}) | |
}, | |
fetchGroups: function() { | |
return $http.get(config.root + "api/rest/auth/info/groups").then(function(res) { | |
return res.data.groups | |
}) | |
}, | |
checkAccess: function() { | |
return _sso = !0, $http.get(_getInfoUrl()).then(function(res) { | |
var hasAccess = res.data.permissions.use_voyager; | |
return hasAccess && _setLoginState(res), hasAccess | |
}) | |
}, | |
getMethods: function() { | |
var methods = { | |
all: _methods | |
}; | |
if (angular.isDefined(_methods)) { | |
methods.all = _methods.filter(function(method) { | |
return method.enabled === !0 | |
}); | |
var _this = this; | |
methods.all.forEach(function(method) { | |
method.displayName = _this.createDisplayName(method.name) | |
}), methods.external = _.filter(_methods, function(method) { | |
return method.displayName = _this.createDisplayName(method.name), angular.isDefined(method.url) && method.enabled === !0 | |
}), 0 === methods.external.length && delete methods.external | |
} else methods.all = []; | |
return methods | |
}, | |
createDisplayName: function(name) { | |
return config && config.customizedLogin && config.customizedLogin.customizeLoginText && config.customizedLogin.customizeLoginText[name] ? config.customizedLogin.customizeLoginText[name] : "Sign in with " + _.classify(name) | |
}, | |
showLogout: function() { | |
var show = !0, | |
methods = this.getMethods().all; | |
if (1 === methods.length && "windows" === methods[0].name) { | |
var windowsAuth = methods[0]; | |
windowsAuth.enableNtlm !== !0 && windowsAuth.enableNegotiate !== !0 || (show = !windowsAuth.hideLogout) | |
} else if (methods.length > 1) { | |
var self = this; | |
_.each(methods, function(method) { | |
"windows" !== method.name || self.hasPermission("manage") || method.enableNtlm !== !0 && method.enableNegotiate !== !0 || (show = !method.hideLogout) | |
}) | |
} | |
return show | |
}, | |
getState: function() { | |
return _state | |
} | |
} | |
}), angular.module("voyager.security").controller("AuthPageCtrl", function($scope, $state, $controller) { | |
"use strict"; | |
$controller("AuthBaseCtrl", { | |
$scope: $scope | |
}); | |
var successCallback = $scope.authSuccess; | |
$scope.authSuccess = function() { | |
successCallback(), $state.go("home") | |
}, $scope.authPage = !0 | |
}), angular.module("voyager.modal", []), angular.module("voyager.modal").factory("vsModalService", function($uibModal) { | |
function _showModal(title, message, buttonText, cancelText) { | |
buttonText = buttonText || "OK"; | |
var modal = $uibModal.open({ | |
templateUrl: "common/modal/info-modal.html", | |
controller: "vsModalCtrl as vm", | |
resolve: { | |
model: function() { | |
return { | |
title: title, | |
message: message, | |
buttonText: buttonText, | |
cancelText: cancelText | |
} | |
} | |
} | |
}); | |
return modal.result.then(function() { | |
return !0 | |
}, function() { | |
return !1 | |
}) | |
} | |
return { | |
showModal: _showModal | |
} | |
}), angular.module("voyager.modal").controller("vsModalCtrl", function($scope, $uibModalInstance, model) { | |
var vm = this; | |
_.extend(vm, model), vm.ok = function() { | |
$uibModalInstance.close() | |
}, vm.cancel = function() { | |
$uibModalInstance.dismiss() | |
} | |
}), angular.module("voyager.modal").controller("ConfirmModalCtrl", function($scope, $uibModalInstance) { | |
var vm = this; | |
vm.modalHeader = "Please Confirm", vm.modalText = [], vm.confirmButtonText = "Confirm", vm.cancelLinkText = "Cancel", vm.confirm = function() { | |
$uibModalInstance.close(vm.confirmButtonText) | |
}, vm.cancel = function() { | |
$uibModalInstance.dismiss(vm.cancelLinkText) | |
} | |
}), angular.module("voyager.common.featured", []), angular.module("voyager.common.featured").factory("featuredService", function($http, $q) { | |
"use strict"; | |
function _postForm(url, data) { | |
var service = config.root + url, | |
headerConfig = { | |
headers: { | |
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" | |
} | |
}; | |
return $http.post(service, data, headerConfig) | |
} | |
function _toFormParam(key, value) { | |
var param = "&" + key + "="; | |
return param += _.isArray(value) ? value.join("&" + key + "=") : value | |
} | |
function _buildRequest(id) { | |
var service = config.root + "solr/v0/select?fq=id:" + id + "&fl=tag_flags"; | |
return service + _type + "&rand=" + Math.random() | |
} | |
var _type = "&wt=json&json.wrf=JSON_CALLBACK", | |
_features = {}; | |
return { | |
save: function(id, field, value, mode) { | |
var url = "api/rest/tag/record/" + id, | |
data = "field=" + field + _toFormParam("value", value); | |
return angular.isDefined(mode) && (data += "&mode=" + mode), _postForm(url, data) | |
}, | |
fetch: function(id) { | |
return $http.jsonp(_buildRequest(id)).then(function(data) { | |
return data.data.response.docs[0] | |
}) | |
}, | |
fetchFeatures: function() { | |
var service = config.root + "api/rest/display/extensions/config"; | |
return $http.get(service).then(function(res) { | |
return _features = _.indexBy(res.data.featureContentGroupList, "id") | |
}) | |
}, | |
getFeature: function(id) { | |
return _features[id] | |
}, | |
getFeatures: function() { | |
return _features | |
} | |
} | |
}); | |
var SavedSearchQuery = function() { | |
function _getQueryString(rows, filter) { | |
var queryString = _config.root + "solr/ssearch/select?"; | |
return queryString += "rows=" + rows + "&rand=" + Math.random(), angular.isDefined(filter) && (queryString += "&fq=" + filter), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _execute(rows, filter) { | |
return _http.jsonp(_getQueryString(rows, filter)).then(function(data) { | |
return data.data.response.docs | |
}, function(error) { | |
return console.log(error), error | |
}) | |
} | |
function _getSavedSearchParams(savedSearch) { | |
var solrParams = querystring.parse(_sugar.trim(savedSearch.query, "&")); | |
if (delete solrParams.facet, delete solrParams["facet.field"], delete solrParams["facet.mincount"], delete solrParams["extent.bbox"], angular.isUndefined(solrParams.shards) && savedSearch.path.indexOf("catalog=") !== -1) { | |
var voyagerParams = querystring.parse(_sugar.trim(savedSearch.path.replace(/\//g, "&"), "&")); | |
solrParams.shards = voyagerParams.catalog | |
} | |
return _sugar.decodeParams(solrParams), solrParams.disp = savedSearch.config, solrParams | |
} | |
var _config, _http, _sugar; | |
return function(config, $http, sugar) { | |
return _config = config, _http = $http, _sugar = sugar, { | |
execute: function() { | |
return _execute(100) | |
}, | |
fetchDefault: function() { | |
return _execute(1) | |
}, | |
fetch: function(id) { | |
return _execute(1, "id:" + id) | |
}, | |
fetchDefaultParams: function() { | |
return _execute(1).then(function(docs) { | |
if (docs && docs.length > 0) { | |
var savedSearch = docs[0]; | |
return _getSavedSearchParams(savedSearch) | |
} | |
return {} | |
}) | |
} | |
} | |
} | |
}(); | |
angular.module("voyager.common.savedsearch", ["voyager.util"]).factory("savedSearchQuery", function(config, $http, sugar) { | |
return new SavedSearchQuery(config, $http, sugar) | |
}), angular.module("simpleSearch", ["angularSpinner"]), angular.module("simpleSearch").factory("simpleSearch", function($http, config, $q, facetService, translateService) { | |
"use strict"; | |
function _bytesToSize(bytes) { | |
var sizes = ["Bytes", "KB", "MB", "GB", "TB"]; | |
if (0 === bytes) return "0 Bytes"; | |
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); | |
return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i] | |
} | |
function _decorate(docs) { | |
return angular.forEach(docs, function(doc, index) { | |
doc.bytes && (doc.size = _bytesToSize(doc.bytes)), angular.isDefined(doc.thumb) && doc.thumb.indexOf("vres/mime") !== -1 && (doc.defaultThumb = !0) | |
}), docs | |
} | |
function _getParams(input, query, page) { | |
return query.q = getInput(input), query.rows = 100, query.start = 100 * (page - 1), query.wt = "json", query["json.wrf"] = "JSON_CALLBACK", query.block = !1, query.fl && (query.fl += ",name"), query | |
} | |
function _search(input, query, page, records) { | |
var params = _getParams(input, query, page); | |
return params.facet === !0 && (angular.isUndefined(params.facet.limit) && (params["facet.limit"] = 11), angular.isUndefined(params.facet.mincount) && (params["facet.mincount"] = 1)), $http.jsonp(config.root + "solr/v0/select", { | |
params: params | |
}).then(function(res) { | |
var docs = res.data.response.docs; | |
if (docs.length > 0 && page > 1 ? (docs = _decorate(docs), $.merge(records, docs)) : 1 === page && (docs = _decorate(docs), records.splice(0, records.length), $.merge(records, docs)), res.data.facet_counts && res.data.facet_counts.facet_fields) { | |
var facetFilters = facetService.buildAllFacets(res.data.facet_counts.facet_fields), | |
facetFields = []; | |
_.each(facetFilters, function(facets, name) { | |
facetFields.push({ | |
filter: name, | |
display: translateService.getFieldName(name), | |
facets: facets | |
}) | |
}), res.data.facetFields = facetFields | |
} | |
return res.data | |
}) | |
} | |
var getInput = function(query) { | |
var input = "*:*"; | |
return query && (input = query), input | |
}; | |
return { | |
search: function(input, query, page, records) { | |
return angular.isUndefined(query) && (query = {}), _search(input, query, page, records) | |
} | |
} | |
}), angular.module("simpleSearch").directive("vgScroll", function() { | |
return { | |
restrict: "A", | |
link: function(scope, element, attrs) { | |
function _scroll() { | |
var spot = raw.scrollTop + raw.offsetHeight; | |
spot >= raw.scrollHeight - 50 && spot >= lastSpot && (scope.$emit("resultsBottom", {}), scope.$apply()), lastSpot = spot | |
} | |
var raw = element[0], | |
lastSpot = 0; | |
element.bind("scroll", _scroll), scope.$on("simpleSearch", function() { | |
element[0].scrollTop = 0 | |
}), scope.$on("$destroy", function() { | |
element.unbind("scroll", _scroll) | |
}) | |
} | |
} | |
}).controller("SimpleSearchCtrl", function($scope, $http, config, $window, $document, usSpinnerService, simpleSearch, $timeout, translateService) { | |
function _flagSelected() { | |
_.each($scope.facetFields, function(filter) { | |
_.each(filter.facets, function(facet) { | |
selectedFacets[facet.name] && (facet.isSelected = !0, lastSelected === filter.filter && (filter.displayState = "in")) | |
}) | |
}) | |
} | |
function _search(page) { | |
usSpinnerService.spin("simple-spinner"), simpleSearch.search($scope.searchInput, $scope.queryCriteria.query, page, $scope.docs).then(function(data) { | |
_busy = !1, $scope.facetFields = data.facetFields, _flagSelected(), 1 === page && $scope.$broadcast("simpleSearch", {}), usSpinnerService.stop("simple-spinner") | |
}) | |
} | |
function _initQuery() { | |
$scope.queryCriteria.query || ($scope.queryCriteria.query = {}), $scope.queryCriteria.query.fq || ($scope.queryCriteria.query.fq = []) | |
} | |
function _addFilter(facet) { | |
lastSelected = facet.filter, facet.isSelected = !0, selectedFacets[facet.name] = facet, _initQuery(), $scope.queryCriteria.query.fq.push(facet.filter + ":" + facet.name) | |
} | |
function _removeFilter(facet) { | |
facet.isSelected = !1, delete selectedFacets[facet.name], _initQuery(), $scope.queryCriteria.query.fq = _.without($scope.queryCriteria.query.fq, facet.filter + ":" + facet.name) | |
} | |
function _loadNextChunk() { | |
_page += 1, _busy = !0, _search(_page) | |
} | |
var _busy = !1, | |
_page = 1, | |
selectedFacets = {}, | |
lastSelected = ""; | |
$scope.filterState = "Show", $scope.fields = ["name", "format"]; | |
var showFields = $scope.queryCriteria.fields; | |
showFields && showFields.length > 0 && ($scope.fields = showFields), $scope.displayFields = [], _.each($scope.fields, function(field) { | |
$scope.displayFields.push(translateService.getFieldName(field)) | |
}), $scope.queryCriteria.query && $scope.queryCriteria.query["facet.field"] && ($scope.facetFields = $scope.queryCriteria.query["facet.field"]), $scope.fieldWidth = 100 / $scope.fields.length, $scope.docs = [], $("#voyagerSearch").removeClass("container"), $timeout(function() { | |
_search(1) | |
}), $scope.searchClick = function() { | |
_search(1) | |
}, $scope.clearSearch = function() { | |
delete $scope.searchInput, _search(1) | |
}, $scope.toggleFilters = function() { | |
$scope.showFilters = !$scope.showFilters, $scope.filterState = $scope.showFilters ? "Hide" : "Show" | |
}, $scope.filterResults = function(facet) { | |
facet.isSelected ? _removeFilter(facet) : _addFilter(facet), _search(1) | |
}, $scope.toggleDisplayState = function(filter) { | |
$timeout(function() { | |
_.each($scope.facetFields, function(f) { | |
filter.filter !== f.filter && (f.displayState = "") | |
}), "in" !== filter.displayState ? filter.displayState = "in" : filter.displayState = "" | |
}, 0) | |
}, $scope.handleEnter = function(ev) { | |
13 === ev.which && _search(1) | |
}, $scope.$on("resultsBottom", function() { | |
_busy === !1 && _loadNextChunk() | |
}), $scope.setItem = function(item) { | |
$("#voyagerSearch").trigger("selectedItem", $scope.item), $scope.ok(item) | |
}, $scope.closeBrowser = function() { | |
$("#voyagerSearch").trigger("cancelSearch"), $scope.cancel() | |
} | |
}), angular.module("voyager.fields", []), angular.module("voyager.fields").factory("fieldService", function($http, config) { | |
"use strict"; | |
return { | |
fetchFields: function() { | |
return $http.jsonp(config.root + "solr/fields/select?q=*:*&wt=json&rows=10000&json.wrf=JSON_CALLBACK").then(function(res) { | |
return res.data.response.docs | |
}) | |
} | |
} | |
}), angular.module("voyager.heatmap", ["voyager.util"]), angular.module("voyager.heatmap").service("colorizer", function() { | |
function toHex(c) { | |
var hex = c.toString(16); | |
return 1 === hex.length ? "0" + hex : hex | |
} | |
function RGB(r, g, b, a) { | |
this.r = r, this.g = g, this.b = b, this.a = angular.isDefined(a) ? a : 1, this.push(r, g, b, this.a) | |
} | |
function HSL(h, s, l) { | |
this.h = h, this.s = s, this.l = l, this.push(h, s, l) | |
} | |
RGB.prototype = new Array, RGB.fromHex = function(hex) { | |
var res = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex); | |
return new RGB(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16), "undefined" != typeof res[4] ? parseInt(res[4], 16) / 255 : void 0) | |
}, RGB.prototype.hsl = function() { | |
var h, s, r = this.r / 255, | |
g = this.g / 255, | |
b = this.b / 255, | |
max = Math.max(r, g, b), | |
min = Math.min(r, g, b), | |
l = (max + min) / 2; | |
if (max === min) h = s = 0; | |
else { | |
var d = max - min; | |
switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) { | |
case r: | |
h = (g - b) / d + (g < b ? 6 : 0); | |
break; | |
case g: | |
h = (b - r) / d + 2; | |
break; | |
case b: | |
h = (r - g) / d + 4 | |
} | |
h /= 6 | |
} | |
return new HSL(h, s, l) | |
}, RGB.prototype.hex = function() { | |
return "#" + toHex(this.r) + toHex(this.g) + toHex(this.b) | |
}, RGB.prototype.rgba = function() { | |
return "rgba(" + this.join(",") + ")" | |
}, RGB.prototype.opacity = function(a) { | |
return new RGB(this.r, this.g, this.b, a) | |
}, RGB.prototype.opacify = function(a) { | |
return new RGB(this.r, this.g, this.b, this.a * a) | |
}, HSL.prototype = new Array, HSL.prototype.rgb = function() { | |
var r, g, b, h = this.h, | |
s = this.s, | |
l = this.l; | |
if (0 === s) r = g = b = l; | |
else { | |
var hue2rgb = function(p, q, t) { | |
return t < 0 && (t += 1), t > 1 && (t -= 1), t < 1 / 6 ? p + 6 * (q - p) * t : t < .5 ? q : t < 2 / 3 ? p + (q - p) * (2 / 3 - t) * 6 : p | |
}, | |
q = l < .5 ? l * (1 + s) : l + s - l * s, | |
p = 2 * l - q; | |
r = hue2rgb(p, q, h + 1 / 3), g = hue2rgb(p, q, h), b = hue2rgb(p, q, h - 1 / 3) | |
} | |
return new RGB(Math.round(255 * r), Math.round(255 * g), Math.round(255 * b)) | |
}; | |
this.rgb = function(r, g, b, a) { | |
return "string" == typeof r ? RGB.fromHex(r) : new RGB(r, g, b, a) | |
}, this.hsl = function(h, s, l) { | |
return new HSL(h, s, l) | |
}, this.interpolate = function(rgb1, rgb2, val) { | |
var hsl1 = rgb1.hsl(), | |
hsl2 = rgb2.hsl(), | |
hsl = hsl1.map(function(start, index) { | |
return start + val * (hsl2[index] - start) | |
}), | |
alpha = rgb1.a + val * (rgb2.a - rgb1.a); | |
return new HSL(hsl[0], hsl[1], hsl[2]).rgb().opacity(alpha) | |
} | |
}), angular.module("voyager.heatmap").service("heatmapService", function($q, $timeout, solrUtil, colorizer, $rootScope) { | |
function interpolate(min, max, method) { | |
var fx, delta = max - min; | |
if ("linear" === method) fx = function(x) { | |
return delta * x | |
}; | |
else if ("exp" === method) fx = function(x) { | |
return Math.exp(x * Math.log(1 + delta)) - 1 | |
}; | |
else { | |
if ("log" !== method) throw "not supported: " + method; | |
fx = function(x) { | |
return delta * Math.log(x + 1) / Math.log(2) | |
} | |
} | |
return function(x) { | |
return min + fx(x) | |
} | |
} | |
function doFetch(bbox, level, offset, d) { | |
solrUtil.heatmap(bbox, query, level).then(function(result) { | |
var hm = result.data.facet_counts.facet_heatmaps.geohash; | |
0 !== offset ? doFetch(bbox, hm[1] + offset, 0, d) : (hm = _.zipObject(_.filter(hm, function(val, i) { | |
return i % 2 === 0 | |
}), _.filter(hm, function(val, i) { | |
return i % 2 !== 0 | |
})), d.resolve(hm)) | |
}) | |
} | |
function fire(evt, obj) { | |
_.forEach(callbacks[evt], function(cb) { | |
cb.call(null, obj) | |
}) | |
} | |
var query = { | |
q: "*:*" | |
}, | |
blur = 5, | |
offset = 0, | |
interpMethod = "linear", | |
callbacks = { | |
render: [] | |
}, | |
stats = !1, | |
opacity = config.searchMap.heatmapOpacity, | |
color1 = colorizer.rgb(config.searchMap.heatmapColor1), | |
color2 = colorizer.rgb(config.searchMap.heatmapColor2), | |
self = this; | |
this.fetch = function(bbox, level) { | |
var d = $q.defer(); | |
return doFetch(bbox, level, offset, d), d.promise | |
}, this.init = function(map) { | |
var throttle = null, | |
HeatmapLayer = L.CanvasLayer.extend({ | |
clear: function() { | |
var can = this.getCanvas(), | |
ctx = can.getContext("2d"); | |
ctx.clearRect(0, 0, can.width, can.height) | |
}, | |
renderGrid: function(hm) { | |
var hmRect = { | |
ul: map.latLngToContainerPoint({ | |
lng: hm.minX, | |
lat: hm.maxY | |
}), | |
lr: map.latLngToContainerPoint({ | |
lng: hm.maxX, | |
lat: hm.minY | |
}) | |
}; | |
hmRect.width = hmRect.lr.x - hmRect.ul.x, hmRect.height = hmRect.lr.y - hmRect.ul.y; | |
var can = this.getCanvas(), | |
ctx = can.getContext("2d"); | |
ctx.strokeStyle = "rgb(0,255,0)", ctx.strokeRect(hmRect.ul.x, hmRect.ul.y, hmRect.width, hmRect.height) | |
}, | |
render: function() { | |
$rootScope.$broadcast("renderHeatmapStarting", { | |
message: "started heatmap rendering" | |
}), null !== throttle && $timeout.cancel(throttle); | |
var layer = this; | |
layer.clear(), throttle = $timeout(function() { | |
self.fetch(map.getBounds().toBBoxString()).then(function(hm) { | |
layer.clear(); | |
var values = hm.counts_ints2D; | |
if (!_.isEmpty(values)) { | |
if (stats === !0) { | |
var flatValues = _.flatten(values); | |
flatValues = _.filter(flatValues, function(val) { | |
return null !== val | |
}), hm.std = _.stdDeviation(flatValues), hm.max = _.max(flatValues), hm.min = _.min(flatValues) | |
} else hm.max = _.max(values.map(_.max)), hm.min = _.min(values.map(_.min)); | |
var interp = interpolate(0, 1, interpMethod), | |
dx = (hm.maxX - hm.minX) / hm.columns, | |
dy = (hm.maxY - hm.minY) / hm.rows, | |
can = layer.getCanvas(); | |
can.style.webkitFilter = "blur(" + blur + "px)"; | |
for (var ctx = can.getContext("2d"), y = hm.maxY, i = 0; i < hm.rows; i++) { | |
var row = values[i]; | |
if (!_.isEmpty(row)) | |
for (var x = hm.minX, j = 0; j < hm.columns; j++) { | |
var p1 = map.latLngToContainerPoint({ | |
lng: x, | |
lat: y | |
}), | |
p2 = map.latLngToContainerPoint({ | |
lng: x + dx, | |
lat: y - dy | |
}), | |
val = interp(values[i][j] / hm.max); | |
if (val > 0) { | |
var rgb = colorizer.interpolate(color1, color2, val); | |
rgb = rgb.opacify(opacity), ctx.fillStyle = rgb.rgba(), ctx.fillRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y) | |
} | |
x += dx | |
} | |
y -= dy | |
} | |
fire("render", hm), $rootScope.$broadcast("renderHeatmapEnding", { | |
message: "started heatmap rendering" | |
}) | |
} | |
}) | |
}, 200) | |
} | |
}), | |
heatmap = new HeatmapLayer; | |
return map.on("zoomstart", function() { | |
heatmap.clear() | |
}), this.layer = heatmap, heatmap | |
}, this.on = function(evt, handler) { | |
callbacks[evt].push(handler) | |
}, this.filter = function(q) { | |
return query = q, self | |
}, this.blur = function(b) { | |
return blur = b, self | |
}, this.interpMethod = function(m) { | |
return interpMethod = m, self | |
}, this.offset = function(o) { | |
return offset = 0, self | |
}, this.stats = function(s) { | |
return stats = s, self | |
}, this.opacity = function(o) { | |
return opacity = o, self | |
} | |
}), angular.module("voyager.tagging", ["voyager.util"]), angular.module("voyager.tagging").controller("TagDialog", function($scope, $uibModalInstance, $analytics, tagService, doc) { | |
"use strict"; | |
$scope.doc = doc, $scope.getDoc = function() { | |
return doc | |
}, $scope.ok = function() { | |
tagService.save($scope.id, $scope.field, $scope.value).then(function(response) { | |
$uibModalInstance.close(), $analytics.eventTrack("tag", { | |
category: "results", | |
id: $scope.id | |
}) | |
}, function(error) { | |
console.log(error.data) | |
}) | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("voyager.tagging").controller("TaggingCtrl", function($scope, tagService) { | |
"use strict"; | |
function _fetch() { | |
tagService.fetch($scope.doc.id).then(function(res) { | |
$scope.tags = res.data.response.docs, $scope.working = !1 | |
}) | |
} | |
$scope.doc = $scope.getDoc(), $scope.field = config.tagFields[0].field, $scope.tagFields = config.tagFields, _fetch(), $scope.save = function() { | |
$scope.hasError = !1, $scope.working = !0, tagService.save($scope.doc.id, $scope.field, $scope.value).then(function() { | |
$scope.value = "", $scope.isSuccess = !0, _fetch() | |
}, function(error) { | |
$scope.working = !1, $scope.hasError = !0, $scope.error = error.data.error | |
}) | |
}, $scope.humanize = function(value) { | |
return value.replace(/_/g, " ").replace(/(\w+)/g, function(match) { | |
return match.charAt(0).toUpperCase() + match.slice(1) | |
}) | |
}, $scope.delete = function(pk) { | |
tagService.delete(pk).then(function() { | |
_fetch() | |
}) | |
} | |
}), angular.module("voyager.tagging").factory("tagService", function($http, $q, $location, queryBuilder, sugar, solrUtil, config, solrGrunt) { | |
function _save(field, value, query, mode) { | |
angular.isUndefined(mode) && (mode = "REPLACE"); | |
var service = solrUtil.toSolrQuery("solr/v0/usertag", query), | |
val = sugar.toArray(value); | |
"REMOVE" === mode && (val = null); | |
var updateMode = "UPDATE_DOCUMENT", | |
formBody = { | |
params: { | |
update: updateMode, | |
tags: [{ | |
field: field, | |
value: val, | |
mode: mode | |
}] | |
} | |
}; | |
return $http.post(service, formBody).then(function(response) { | |
return response.data.tagging | |
}) | |
} | |
function _fetchTags(field) { | |
var deferred = $q.defer(), | |
service = config.root + "solr/usertags/select?q=*:*&rows=0&facet=true&facet.field=fss_tag_" + field + "&facet.mincount=1&facet.limit=1000&wt=json&json.wrf=JSON_CALLBACK&rand=" + Math.random(); | |
return $http.jsonp(service).then(function(response) { | |
var tags = response.data.facet_counts.facet_fields["fss_tag_" + field]; | |
tags = _.reject(tags, function(val) { | |
return _.isNumber(val) | |
}), deferred.resolve(tags) | |
}), deferred.promise | |
} | |
return { | |
save: function(id, field, value, action) { | |
return _save(field, value, { | |
fq: "id:" + id | |
}, action) | |
}, | |
fetch: function(id) { | |
var service = config.root + "solr/usertags/select?q=*:*&fq=id:" + id + "&sort=when%20desc&wt=json&json.wrf=JSON_CALLBACK&rand=" + Math.random(); | |
return $http.jsonp(service) | |
}, | |
delete: function(pk) { | |
var service = config.root + "api/rest/tag/remove/" + pk; | |
return $http.delete(service) | |
}, | |
lookup: function(id, field) { | |
var deferred = $q.defer(); | |
return this.fetch(id).then(function(res) { | |
var tags = res.data.response.docs; | |
deferred.resolve(_.find(tags, { | |
field: field | |
})) | |
}), deferred.promise | |
}, | |
deleteByField: function(id, field) { | |
return this.save(id, field, "", "REMOVE") | |
}, | |
saveLabels: function(id, value) { | |
return _.isEmpty(value) ? void this.deleteByField(id, "tag_tags") : this.save(id, "tag_tags", value) | |
}, | |
replace: function(id, field, value) { | |
return this.save(id, field, value, "REPLACE") | |
}, | |
fetchTags: function() { | |
return _fetchTags("tags") | |
}, | |
fetchFlags: function() { | |
return _fetchTags("flags") | |
}, | |
saveBulkField: function(tagValue, field, docId) { | |
var query; | |
return query = angular.isDefined(docId) ? { | |
fq: "id:" + docId | |
} : solrGrunt.getSolrParams($location.search()), _save(field, tagValue, query) | |
}, | |
removeBulkField: function(field) { | |
return _save(field, "", $location.search(), "REMOVE") | |
}, | |
applyTag: function(tag, $scope, filterService) { | |
return $location.path().indexOf("/search") > -1 ? (filterService.clear(), $location.search("q", null), $location.search("place", null), $location.search("recent", null), $scope.$emit("removeFilterEvent", {})) : $location.path("search"), $location.search("fq", "tag_flags:" + tag), filterService.setFilters({ | |
fq: "tag_flags:" + tag | |
}), $scope.$emit("filterEvent"), !1 | |
} | |
} | |
}), angular.module("taskRunner", ["voyager.map", "fileBrowser", "ui.select2", "voyager.fields", "simpleSearch", "dialogs.main", "cart"]), angular.module("taskRunner").directive("vsGhostItems", function(taskService) { | |
"use strict"; | |
function _setFilterParams($scope) { | |
$scope.param.ids = taskService.getItems() | |
} | |
return { | |
template: "<div></div>", | |
controller: function($scope) { | |
_setFilterParams($scope) | |
} | |
} | |
}), angular.module("taskRunner").directive("vsViewItems", function() { | |
return { | |
templateUrl: "src/taskrunner/params/view-items.html", | |
controller: function($scope) { | |
$scope.items = $scope.param.response.docs | |
} | |
} | |
}), angular.module("taskRunner").factory("templateService", function() { | |
"use strict"; | |
var advancedIcon = '<i ng-show="param.advanced" class="fa fa-gear" title="Advanced"></i>', | |
requiredIcon = '<i ng-show="param.required" class="fa fa-asterisk" title="Required" style="margin-left: 2px; color: darkred; font-size: x-small"></i>', | |
errorTpl = '<div class="process-control alert alert-danger" style="color:red" ng-show="param.error"><span class="glyphicon glyphicon-arrow-up"/> {{param.error}}</div>', | |
labelTpl = '<dl style="margin-bottom: 5px"><dt>' + advancedIcon + "{{param.label}}" + requiredIcon + "<dt><dd>{{param.desc}}</dd></dl>", | |
selectTpl = '<select ui-select2="{dropdownAutoWidth: \'true\', minimumResultsForSearch: 5}" ng-model="param.value"> <option ng-repeat="option in param.choices" value="{{option}}">{{param.values[option]}}</option></select>', | |
projectionSelect = '<input type="hidden" ui-select2="select2Options" ng-model="param.selected">', | |
textInputTpl = '<input type="text" class="form-control" ng-model="param.value" style="width: 40%">', | |
intInputTpl = '<input type="number" class="form-control" ng-model="param.value" ng-blur="isInteger()" style="width: 30%">', | |
pwdInputTpl = '<input type="password" class="form-control" style="width: 40%" ng-model="param.value">', | |
fieldList = '<input vs-field-param param="param">', | |
fieldListTpl = '<div ng-hide="param.advanced && !show">' + labelTpl + fieldList + errorTpl + "</div>", | |
field = '<input vs-field-param param="param" multi="false">', | |
fieldTpl = '<div ng-hide="param.advanced && !show">' + labelTpl + field + errorTpl + "</div>", | |
permissions = '<input vs-list-param param="param" list="permissions" multi="true" data-placeholder="Private">', | |
permissionsTpl = '<div ng-hide="param.advanced && !show">' + labelTpl + permissions + errorTpl + "</div>", | |
combo = '<input vs-list-param param="param" list="permissions" multi="false" data-placeholder="">', | |
comboTpl = '<div ng-hide="param.advanced && !show">' + labelTpl + combo + errorTpl + "</div>", | |
projection = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + projectionSelect + errorTpl + "</div>", | |
stringChoice = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + selectTpl + errorTpl + "</div>", | |
textArea = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + '<textarea ng-model="param.value" style="width: 96%"></textarea>' + errorTpl + "</div>", | |
stringTpl = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + textInputTpl + errorTpl + "</div>", | |
checkBox = '<div ng-hide="param.advanced && !show" class="process-control"><dl style="margin-bottom: 5px"><dt>' + advancedIcon + '{{param.label}}<dt><dd><label style="font-weight: normal"><input type="checkbox" ng-model="param.value"> {{param.desc}}</label></dd></dl>' + errorTpl + "</div>", | |
missing = '<div class="process-control" style="color:red">Missing {{param.name}} template</div>', | |
intTpl = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + intInputTpl + errorTpl + "</div>", | |
pwdTpl = '<div ng-hide="param.advanced && !show" class="process-control">' + labelTpl + pwdInputTpl + errorTpl + "</div>", | |
readOnlyLabelTpl = '<label style="width:100%; padding-left: 5px; margin-bottom: 0px; border-color: #eeeeee; border-bottom-style: solid; border-width: 1px;color:#999999">{{param.label}} </label>', | |
readOnlyTpl = '<div class="process-control" style>' + readOnlyLabelTpl + '<div style="padding-left: 5px;">{{param.value}}</div></div>', | |
readOnlyListTpl = '<div class="process-control" style>' + readOnlyLabelTpl + '<div style="padding-left: 5px;">{{param.value.join()}}</div></div>', | |
pwdReadOnlyTpl = '<div class="process-control" style>' + readOnlyLabelTpl + '<input type="password" ng-model="param.value" ng-disabled="true" style="padding-left: 5px;"></div>', | |
dateTpl = labelTpl + '<div class="input-group date"><input type="text" placeholder="yyyy-mm-dd" class="form-control" uib-datepicker-popup="yyyy-MM-dd" is-open="isDateOpen" ng-click="openDatePicker($event)" ng-model="param.value" close-text="Close" ng-required="true"><span class="input-group-addon" style="width: 0" ng-click="openDatePicker($event)"><span class="glyphicon glyphicon-calendar" ng-click="openDatePicker($event)"></span></span></div>', | |
datePickOnlyTpl = labelTpl + '<div class="input-group date"><input type="text" readonly="true" placeholder="yyyy-mm-dd" class="form-control" uib-datepicker-popup="yyyy-MM-dd" is-open="isDateOpen" ng-click="openDatePicker($event)" ng-model="param.value" close-text="Close" ng-required="true"><span class="input-group-addon" style="width: 0" ng-click="openDatePicker($event)"><span class="glyphicon glyphicon-calendar" ng-click="openDatePicker($event)"></span></span></div>', | |
browseTpl = '<div class="input-group" style="width: 100%"><input type="text" class="form-control" ng-model="param.value"><span class="input-group-btn"><button class="btn btn-default" type="button" ng-click="open(\'lg\')"> Browse</button></span></div>', | |
searchInput = '<div class="input-group" style="width: 100%"><input type="text" class="form-control" ng-model="param.display"><span class="input-group-btn"><button class="btn btn-default" type="button" ng-click="search(\'lg\')"> Search</button></span></div>', | |
locationTpl = '<div class="process-control">' + labelTpl + browseTpl + errorTpl + "</div>", | |
searchTpl = '<div class="process-control">' + labelTpl + searchInput + errorTpl + "</div>", | |
templates = { | |
VoyagerResults: "<div vs-ghost-items></div>", | |
Projection: projection, | |
StringChoice: stringChoice, | |
Geometry: '<div style="height:100%; width:100%; max-width: 800px; display: inline-block" class="map">' + labelTpl + '<div vs-clip-map class="clip-map" />' + errorTpl + "</div>", | |
MapView: '<div style="height:100%; width:100%; max-width: 800px; display: inline-block" class="map">' + labelTpl + '<div vs-view-map class="clip-map" />' + errorTpl + "</div>", | |
TextArea: textArea, | |
String: stringTpl, | |
CheckBox: checkBox, | |
CatalogPath: locationTpl, | |
FolderLocation: locationTpl, | |
Integer: intTpl, | |
Password: pwdTpl, | |
FieldList: fieldListTpl, | |
Field: fieldTpl, | |
Permissions: permissionsTpl, | |
Combo: comboTpl, | |
IndexItem: searchTpl, | |
QueryIndex: searchTpl, | |
Date: dateTpl, | |
"VoyagerResults-readOnly": "<div>" + readOnlyLabelTpl + "<div vs-view-items></div></div>", | |
"Projection-readOnly": readOnlyTpl, | |
"StringChoice-readOnly": readOnlyTpl, | |
"Geometry-readOnly": '<div class="read-only-map">' + readOnlyLabelTpl + '<div vs-read-only-map class="clip-map" /></div>', | |
"MapView-readOnly": '<div class="read-only-map">' + readOnlyLabelTpl + '<div vs-read-only-map class="clip-map" /></div>', | |
"TextArea-readOnly": readOnlyTpl, | |
"String-readOnly": readOnlyTpl, | |
"CheckBox-readOnly": readOnlyTpl, | |
"CatalogPath-readOnly": readOnlyTpl, | |
"FolderLocation-readOnly": readOnlyTpl, | |
"Integer-readOnly": readOnlyTpl, | |
"Password-readOnly": pwdReadOnlyTpl, | |
"FieldList-readOnly": readOnlyListTpl, | |
"Permissions-readOnly": readOnlyListTpl, | |
"Combo-readOnly": readOnlyListTpl, | |
"Field-readOnly": readOnlyTpl, | |
"QueryIndex-readOnly": readOnlyTpl, | |
"Date-readOnly": datePickOnlyTpl | |
}; | |
return { | |
get: function(type, readOnly) { | |
var suffix = ""; | |
readOnly === !0 && (suffix = "-readOnly"); | |
var template = templates[type + suffix]; | |
return template || (template = missing), template | |
} | |
} | |
}), angular.module("taskRunner").factory("paramService", function(localStorageService, savedSearchService, $http) { | |
"use strict"; | |
function _getParamDisplay(param, displayData) { | |
var paramData = displayData.params[param.name]; | |
return _.isUndefined(paramData) && (paramData = { | |
display: "", | |
description: "" | |
}, paramData.display = _.str.humanize(param.name), paramData.display = _.str.titleize()), paramData | |
} | |
function _decorate(param, displayData) { | |
var paramDisplay = _getParamDisplay(param, displayData); | |
param.label = paramDisplay.display, param.desc = paramDisplay.description | |
} | |
function _initReadOnly(response, displayData) { | |
var readOnlyParams = { | |
params: [], | |
inputItems: [], | |
hasMap: !1 | |
}; | |
return $.each(response.data.params, function(index, param) { | |
"Projection" === param.type && (param.value = param.code), "Geometry" !== param.type && "MapView" !== param.type || (readOnlyParams.hasMap = !0, param.hasMap = !0), _decorate(param, displayData), "input_items" === param.name ? readOnlyParams.inputItems.push(param) : readOnlyParams.params.push(param) | |
}), readOnlyParams | |
} | |
function _applyChoicesAsValues(param) { | |
_.isUndefined(param.values) && !_.isUndefined(param.choices) && (param.values = {}, $.each(param.choices, function(index, value) { | |
param.values[value] = value | |
})) | |
} | |
function _initParam(param) { | |
"Geometry" !== param.type && "MapView" !== param.type || (param.hasMap = !0), angular.isUndefined(param.readOnly) && (param.readOnly = !1) | |
} | |
function _initParams(response, reload) { | |
var params = [], | |
mapParams = []; | |
_params.hasMap = !1, _params.hasAdvanced = !1, $.each(response[0].data.params, function(index, param) { | |
_initParam(param), param.hasMap ? (_params.hasMap = !0, param.reload = reload, mapParams.push(param)) : params.push(param), _decorate(param, response[1].data), _applyChoicesAsValues(param), param.advanced && (_params.hasAdvanced = !0), angular.isUndefined(param.readOnly) && (param.readOnly = !1) | |
}), _params.params = params, _params.mapParams = mapParams | |
} | |
var _params = {}, | |
_projections = [], | |
_groups = {}; | |
return $http.get("projections.json").then(function(response) { | |
$.each(response.data, function(name, value) { | |
var info = name.split("/"), | |
group = info[1]; | |
_groups[group] ? _groups[group].children.push({ | |
name: info[info.length - 1], | |
value: value, | |
group: info[1] | |
}) : _groups[group] = { | |
children: [{ | |
name: info[info.length - 1], | |
value: value, | |
group: info[1] | |
}], | |
text: group | |
}, _projections.push({ | |
name: info[info.length - 1], | |
value: value, | |
group: info[1] | |
}) | |
}) | |
}), { | |
initParams: function(response, reload) { | |
var lastRanParams = null; | |
return "export_result_list" !== response[0].data.task && "create_saved_search" !== response[0].data.task && (lastRanParams = localStorageService.get(response[0].data.task)), | |
null === lastRanParams ? _initParams(response, reload) : (_params = lastRanParams, _params.mapParams.length > 0 && (_params.mapParams[0].reload = reload, delete _params.mapParams[0].wkt)), _params | |
}, | |
initReadOnly: function(response, displayData) { | |
return _initReadOnly(response, displayData) | |
}, | |
getParams: function() { | |
return _params | |
}, | |
getAllParams: function() { | |
$.each(_params.params, function(index, value) { | |
"Projection" === value.type && angular.isDefined(value.code.id) && (value.code = value.code.id) | |
}); | |
var all = _params.params; | |
return _.isUndefined(_params.mapParams) || (all = all.concat(_params.mapParams)), JSON.parse(JSON.stringify(all)) | |
}, | |
setParams: function(params) { | |
_params = params | |
}, | |
getStorable: function() { | |
var params = $.extend(!0, {}, _params); | |
return params.reload = !1, $.each(params.params, function(index, param) { | |
"input_items" === param.name && (delete param.query, delete param.ids), delete param.error | |
}), angular.isDefined(params.mapParams) && $.each(params.mapParams, function(index, param) { | |
delete param.wkt, delete param.extent, delete param.center, delete param.zoom, delete param.error | |
}), params | |
}, | |
getProjections: function() { | |
return _groups | |
}, | |
applyErrors: function(params, validations) { | |
$.each(validations, function(index, validated) { | |
validated.error && $.each(params, function(index, param) { | |
if (param.name === validated.name) return void(param.error = validated.error) | |
}) | |
}) | |
} | |
} | |
}), angular.module("taskRunner").directive("vsParam", function($compile, templateService, leafletData, paramService, $timeout, mapUtil) { | |
"use strict"; | |
function _isGeometry($scope) { | |
return $scope.param.type && "Geometry" === $scope.param.type | |
} | |
function _isProjection($scope) { | |
return $scope.param.type && "Projection" === $scope.param.type | |
} | |
function _isCatalogPath($scope) { | |
return $scope.param.type && "CatalogPath" === $scope.param.type | |
} | |
function _setMapHeight(scope) { | |
var mapId = "view-map"; | |
_isGeometry(scope) && (mapId = "clip-map"); | |
scope.param.type; | |
scope.param.readOnly === !0 && (mapId = "read-only-map"), leafletData.getMap(mapId).then(function(map) { | |
var width = $(map.getContainer()).width(), | |
height = Math.round(width / 4 * 3); | |
0 === height && (height = 250), $(map.getContainer()).css("height", height), map.invalidateSize(!1), scope.param.resultsExtent && mapUtil.fitToBBox(map, scope.param.resultsExtent) | |
}) | |
} | |
function _link(scope, element, attrs) { | |
if (!scope.param.hidden) { | |
var type = scope.param.type, | |
name = scope.param.name; | |
"List" === type && "groups" === name && (type = "Permissions"), "List" === type && "saved_searches" === name && (type = "Combo"); | |
var template = templateService.get(type, scope.param.readOnly); | |
element.html(template).show(), $compile(element.contents())(scope), scope.param.hasMap === !0 && $timeout(function() { | |
_setMapHeight(scope) | |
}) | |
} | |
} | |
function _controller($scope, $uibModal) { | |
var lastTerm = "", | |
filteredGroups = []; | |
if ($scope.browserType = "folder", _isCatalogPath($scope) && ($scope.browserType = "file"), _isProjection($scope)) { | |
var defaultSelect = { | |
id: 0, | |
text: "Same As Input" | |
}; | |
$scope.param.selected && (defaultSelect = $scope.param.selected), $scope.select2Options = { | |
dropdownAutoWidth: "true", | |
minimumResultsForSearch: 5, | |
minimumInputLength: 3, | |
initSelection: function(element, callback) { | |
callback(defaultSelect) | |
}, | |
query: function(query) { | |
var groups; | |
groups = 3 === query.term.length ? paramService.getProjections() : query.term.length > lastTerm.length ? filteredGroups.slice() : paramService.getProjections(), filteredGroups = [], lastTerm = query.term; | |
var name, term, data = { | |
results: [] | |
}; | |
$.each(groups, function(key, group) { | |
var filteredGroup = { | |
text: group.text, | |
children: [] | |
}; | |
$.each(group.children, function(i, projection) { | |
name = projection.name.toLowerCase(), term = query.term.toLowerCase(), name.indexOf(term) !== -1 && (projection.id = projection.value, projection.text = projection.name, filteredGroup.children.push(projection)) | |
}), filteredGroup.children.length > 0 && filteredGroups.push(filteredGroup) | |
}), data.results = filteredGroups, query.callback(data) | |
} | |
} | |
} | |
$scope.open = function(size) { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "common/filebrowser/file-browser.html", | |
controller: "ModalBrowseCtrl", | |
size: size, | |
resolve: { | |
type: function() { | |
return $scope.browserType | |
}, | |
path: function() { | |
return $scope.param.value | |
} | |
} | |
}); | |
modalInstance.result.then(function(path) { | |
$scope.param.value = path | |
}) | |
}, $scope.search = function(size) { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "common/simple-search/search.html", | |
controller: "ModalSearchCtrl", | |
size: size, | |
resolve: { | |
queryCriteria: function() { | |
return { | |
query: $scope.param.query, | |
fields: $scope.param.fields | |
} | |
} | |
} | |
}); | |
modalInstance.result.then(function(item) { | |
$scope.param.value = item, $scope.param.display = item.name | |
}) | |
}, $scope.openDatePicker = function($event) { | |
$event.stopPropagation(), $scope.isDateOpen = !0 | |
}, $scope.isInteger = function() { | |
Number.isInteger($scope.param.value) ? $scope.param.error = null : $scope.param.error = "Must be an integer value" | |
} | |
} | |
return { | |
restrict: "E", | |
replace: !0, | |
link: _link, | |
controller: _controller, | |
scope: { | |
param: "=", | |
show: "=" | |
} | |
} | |
}), angular.module("taskRunner").directive("vsFieldParam", function(fieldService) { | |
return { | |
replace: !0, | |
scope: { | |
param: "=", | |
show: "=" | |
}, | |
template: '<input type="hidden" ui-select2="fieldOptions" ng-model="param.value" style="width: 100%;">', | |
controller: function($scope, $element, $attrs) { | |
var _fields = [], | |
isMultiple = "false" !== $attrs.multi; | |
$scope.fieldOptions = { | |
multiple: isMultiple, | |
simple_tags: !0, | |
dropdownAutoWidth: !0, | |
minimumResultsForSearch: 10, | |
data: function() { | |
return { | |
results: _fields | |
} | |
} | |
}, fieldService.fetchFields().then(function(fields) { | |
_.each(fields, function(field) { | |
0 !== field.name.indexOf("_") && _fields.push({ | |
id: field.name, | |
text: field.disp_en | |
}) | |
}) | |
}) | |
} | |
} | |
}), angular.module("taskRunner").directive("vsListParam", function($compile, authService, savedSearchService) { | |
return { | |
replace: !0, | |
scope: { | |
param: "=", | |
show: "=", | |
list: "@list", | |
multi: "=" | |
}, | |
template: '<input type="hidden" ui-select2="listOptions" ng-model="param.value" ng-change="onChange()" style="width: 50%">', | |
controller: function($scope, $element, $attrs) { | |
var _options = [], | |
_searches = [], | |
_coreRoles = [{ | |
id: "_EVERYONE", | |
text: "EVERYONE" | |
}, { | |
id: "_LOGGEDIN", | |
text: "LOGGEDIN" | |
}, { | |
id: "_ANONYMOUS", | |
text: "ANONYMOUS" | |
}], | |
isMultiple = "false" !== $attrs.multi; | |
!!$scope.multi == !1 && ($scope.onChange = function() { | |
angular.isDefined($scope.param.value) && $scope.param.value.length > 1 && ($scope.param.value = [$scope.param.value[1]]) | |
}), !!$scope.multi == !1 ? $scope.listOptions = { | |
multiple: isMultiple, | |
dropdownAutoWidth: !0, | |
minimumResultsForSearch: 5, | |
tags: _searches | |
} : $scope.listOptions = { | |
multiple: isMultiple, | |
simple_tags: !0, | |
dropdownAutoWidth: !0, | |
minimumResultsForSearch: 5, | |
data: function() { | |
return { | |
results: _options | |
} | |
} | |
}, !!$scope.multi == !1 && savedSearchService.getSavedSearches().then(function(savedSearches) { | |
var sortedSavedSearches = savedSearchService.sortSavedSearches(savedSearches); | |
angular.forEach(sortedSavedSearches.personal, function(value) { | |
_searches.indexOf(value.title) === -1 && _searches.push(value.title) | |
}) | |
}), "permissions" == $scope.list && authService.getPrivileges().then(function() { | |
authService.hasPermission("manage") ? ($.merge(_options, _coreRoles), authService.fetchGroups().then(function(groups) { | |
$.merge(_options, groups) | |
})) : authService.fetchGroups().then(function(groups) { | |
$.merge(_options, groups) | |
}) | |
}) | |
} | |
} | |
}), angular.module("taskRunner").factory("taskService", function($http, config, $q, cartService, cartItemsQuery, translateService, taskModalService, converter) { | |
"use strict"; | |
function _buildQuery(isAdmin) { | |
var filter = "&fq=available:true"; | |
return isAdmin && (filter = ""), config.root + "solr/tasks/select?q=*:*" + filter + "&rows=1000&sort=display_sort+asc&wt=json&json.wrf=JSON_CALLBACK&rand=" + Math.random() | |
} | |
function _post(request, validate) { | |
return $http({ | |
method: "POST", | |
url: config.root + "api/rest/process/task?validate=" + validate, | |
data: request, | |
headers: { | |
"Content-Type": "application/json" | |
} | |
}) | |
} | |
function _decorator(data) { | |
var groups = {}; | |
return _.each(data, function(item) { | |
_.each(item.category, function(cat) { | |
"undefined" == typeof groups[cat] ? (groups[cat] = [], groups[cat].push(item)) : groups[cat].push(item) | |
}) | |
}), groups | |
} | |
function _convertPlaceFilter(request) { | |
var inputItems = request.params.filter(function(item) { | |
return "input_items" === item.name | |
}); | |
if (inputItems) { | |
var inputItemsParam = inputItems[0]; | |
if (inputItemsParam.query && angular.isDefined(inputItemsParam.query.place)) { | |
var placeFq = converter.toPlaceFilter(inputItemsParam.query), | |
fq = []; | |
angular.isDefined(inputItemsParam.query.fq) && (fq = inputItemsParam.query.fq), fq.push(placeFq), inputItemsParam.query.fq = fq | |
} | |
} | |
} | |
var _items = [], | |
_extent = null, | |
errorMessage = "All the items in the cart are invalid formats"; | |
return angular.isDefined(config.defaultTask) && !_.isEmpty(config.defaultTask) && (errorMessage = "All the items in the cart are invalid formats for: " + _.classify(config.defaultTask)), { | |
findAllTasks: function(isAdmin) { | |
return $http.jsonp(_buildQuery(isAdmin)).then(function(data) { | |
return _decorator(data.data.response.docs) | |
}, function(error) { | |
return error | |
}) | |
}, | |
lookupTaskType: function(type) { | |
var taskPromise = $http.get(config.root + "api/rest/process/task/" + type + "/init.json"), | |
taskDisplayPromise = $http.get(config.root + "api/rest/process/task/" + type + "/display.json?lang=en"); | |
return $q.all([taskPromise, taskDisplayPromise]) | |
}, | |
lookupTask: function(type) { | |
return $http.get(config.root + "api/rest/process/task/" + type + "/init.json") | |
}, | |
lookupTaskDisplay: function(type) { | |
return $http.get(config.root + "api/rest/process/task/" + type + "/display.json?lang=en") | |
}, | |
execute: function(request) { | |
return _convertPlaceFilter(request), _post(request, !1) | |
}, | |
validate: function(request) { | |
return _post(request, !0) | |
}, | |
getTaskQueryCriteria: function(constraints, invalidItemsOnly) { | |
var query = cartService.getQuery(), | |
items = cartService.getItemsArray(); | |
return query || (query = cartItemsQuery.getQueryCriteria({})), angular.isUndefined(query.solrFilters) && (query.solrFilters = []), angular.isUndefined(query.constraintFilters) && (query.constraintFilters = []), _.each(constraints, function(value) { | |
invalidItemsOnly === !0 ? (query.invalidItems = !0, 0 === items.length ? query.solrFilters.push("-(" + value + ")") : query.constraintFilters.push("-(" + value + ")")) : 0 === items.length ? query.solrFilters.push(value) : query.constraintFilters.push(value) | |
}), query | |
}, | |
getTaskConstraintFormats: function(taskConstraints) { | |
var constraintFormats = []; | |
return _.each(taskConstraints, function(value) { | |
value = value.split(":")[1]; | |
var values = value.split(" "); | |
values ? angular.forEach(values, function(value) { | |
value = value.replace("(", ""), value = value.replace(")", ""), value = translateService.getType(value), constraintFormats.push(value) | |
}) : (value = translateService.getType(value), constraintFormats.push(value)) | |
}), constraintFormats | |
}, | |
showTaskValidationError: function(constraintFormats) { | |
taskModalService.showTaskValidationError(errorMessage, constraintFormats) | |
}, | |
validateTaskItems: function(constraints, invalidItemsOnly) { | |
var severity = 0, | |
items = cartService.getItemIds(), | |
query = this.getTaskQueryCriteria(constraints, invalidItemsOnly, items); | |
return query.constraints = !0, query.count = cartService.getCount(), invalidItemsOnly === !0 ? cartItemsQuery.execute(query, items) : cartItemsQuery.fetchItems(query, items).then(function(data) { | |
var count = data.count; | |
return angular.isDefined(data.bbox) && (_extent = data.bbox), count === query.count ? severity = 0 : 0 === count ? severity = 2 : count < query.count && (severity = 1), severity | |
}) | |
}, | |
checkStatus: function(id) { | |
return $http.get(config.root + "api/rest/process/job/" + id + ".json") | |
}, | |
checkProgress: function(id) { | |
return $http.get(config.root + "api/rest/process/job/" + id + "/status.json") | |
}, | |
cancel: function(id) { | |
return $http.delete(config.root + "api/rest/process/job/" + id + ".json") | |
}, | |
notify: function(id, email) { | |
return $http.put(config.root + "api/rest/process/job/" + id + "/callback.json?email=" + email) | |
}, | |
cancelNotify: function(id, email) { | |
return $http.delete(config.root + "api/rest/process/job/" + id + "/callback.json?email=" + email) | |
}, | |
getFileUrl: function(id, name) { | |
return config.root + "api/rest/process/job/" + id + "/output/" + name | |
}, | |
getFileDisplayName: function(name) { | |
return name.indexOf("stdout") > 0 ? "Processing Output" : name.indexOf("stderr") > 0 ? "Processing Error Log" : name | |
}, | |
refresh: function() { | |
return $http.post(config.root + "api/rest/process/tasks/refresh.json") | |
}, | |
getFileData: function(file, withoutMime) { | |
return withoutMime = withoutMime || !1, $http.get(file.downloadUrl + (withoutMime ? "" : "?mime=application/json")) | |
}, | |
setItems: function(items) { | |
_items = items | |
}, | |
getExtent: function() { | |
return _extent | |
}, | |
getItems: function() { | |
return _items | |
}, | |
getFiles: function(statusResponse) { | |
var _self = this, | |
files = []; | |
return statusResponse.data.output && statusResponse.data.output.children && $.each(statusResponse.data.output.children, function(index, file) { | |
file.format && 0 !== file.name.lastIndexOf("_", 0) && (file.downloadUrl = _self.getFileUrl(statusResponse.data.id, file.name), files.push(file)) | |
}), files | |
}, | |
getLogFiles: function(statusResponse) { | |
var _self = this, | |
files = []; | |
return statusResponse.data.output && statusResponse.data.output.children && $.each(statusResponse.data.output.children, function(index, file) { | |
file.format && 0 === file.name.lastIndexOf("_", 0) && (file.name.indexOf("stderr") > -1 || file.name.indexOf("stdout") > -1) && (file.downloadUrl = _self.getFileUrl(statusResponse.data.id, file.name), file.displayName = _self.getFileDisplayName(file.name), files.push(file)) | |
}), files | |
}, | |
getReport: function(statusResponse) { | |
var file = this.getReportFile(statusResponse); | |
return file ? $http.get(file.downloadUrl).then(function(response) { | |
return response.data | |
}) : $q.reject() | |
}, | |
getReportFile: function(statusResponse) { | |
var _file, _self = this; | |
return statusResponse.data.output && statusResponse.data.output.children && $.each(statusResponse.data.output.children, function(index, file) { | |
file.format && 0 === file.name.lastIndexOf("_", 0) && file.name.indexOf("report") > -1 && (file.downloadUrl = _self.getFileUrl(statusResponse.data.id, file.name) + "/", file.displayName = _self.getFileDisplayName(file.name), _file = file) | |
}), _file | |
}, | |
getCopyUrl: function(id) { | |
return config.root + "api/rest/process/job/" + id + "/run.json" | |
} | |
} | |
}), angular.module("taskRunner").controller("TaskCtrl", function($scope, taskService, taskModalService, usSpinnerService, paramService, localStorageService, cartService, cartItemsQuery, sugar, $location, $stateParams, $state) { | |
"use strict"; | |
function _applyExtentToMapParams() { | |
_.isEmpty($scope.extent) || _.forEach(_.filter($scope.mapParams, function(p) { | |
return p.initWithResultsExtent === !0 | |
}), function(p) { | |
p.resultsExtent = $scope.extent | |
}) | |
} | |
function _prepare() { | |
var params = $scope.params.concat($scope.mapParams); | |
$.each(params, function(index, param) { | |
angular.isUndefined(param) || ("Projection" === param.type && (param.code = param.selected.id, param.value = param.code), delete param.error) | |
}); | |
var inputItems = _.find(params, { | |
type: "VoyagerResults" | |
}), | |
query = _getQuery(cartService.getQuery(), cartService.getItemIds()); | |
return query ? (inputItems.query = query, delete inputItems.ids) : (inputItems.ids = cartService.getItemIds(), delete inputItems.query), params | |
} | |
function _validate(params) { | |
_.each(params, function(param) { | |
angular.isDefined(param.required) && angular.isDefined(param.value) && 0 === param.value.length && delete param.value | |
}); | |
var request = { | |
task: $scope.task.name, | |
params: params | |
}; | |
return taskService.validate(request) | |
} | |
function _errorHandler(error, params) { | |
$scope.isRunning = !1, $scope.hasError = !0, $scope.errors = error.data.errors, paramService.applyErrors(params, error.data.params), usSpinnerService.stop("tasks-spinner") | |
} | |
function _applyItems(queryCriteria, items) { | |
var itemsStr = "", | |
sep = ""; | |
items && items.length > 0 && (itemsStr = "id:(" + items.join(" ") + ")", sep = " OR "), angular.isDefined(queryCriteria.params.q) ? queryCriteria.params.q = itemsStr + sep + queryCriteria.params.q : "" !== itemsStr && (queryCriteria.params.q = itemsStr) | |
} | |
function _getQuery(queryCriteria, items) { | |
var query = { | |
params: {} | |
}, | |
hasItems = !1; | |
return queryCriteria && (query = _.clone(queryCriteria)), _.isEmpty(items) || (_applyItems(query, items), hasItems = !0), angular.isDefined(query.solrFilters) && hasItems ? (query.params.q += " OR (" + query.solrFilters.join(" AND "), _.isEmpty(query.bounds) || (query.params.q += " AND " + query.bounds.replace("&fq=", "")), query.params.q += ")") : hasItems && !_.isEmpty(query.bounds) ? query.params.q += " OR (" + query.bounds.replace("&fq=", "") + ")" : angular.isDefined(query.filters) ? query.filters.search("&fq=") > -1 && (query.params.fq = query.filters.split("&fq=")) : angular.isDefined(query.solrFilters) && (query.params.fq = query.solrFilters), delete query.params.bbox, delete query.params.bboxt, query.params | |
} | |
$scope.task = $stateParams.task, $scope.taskList = $stateParams.taskList, $scope.extent = taskService.getExtent(), $scope.params = [], $scope.hasMap = !0, $scope.showAdvanced = !1; | |
var _init = function() { | |
$scope.hasError = !1, $scope.errors = {}, $scope.hasAdvanced = !1, $scope.showAdvanced = !1, $scope.displayCategory = cartService.getCount() > 100, usSpinnerService.spin("tasks-spinner"), _.isEmpty($scope.task) && ($scope.task = { | |
name: $stateParams.type | |
}), taskService.lookupTaskType($scope.task.name).then(function(response) { | |
$scope.task.display = response[1].data.display, $scope.task.description = response[1].data.description, $scope.task.helpURL = response[1].data.helpURL; | |
var params = paramService.initParams(response, $scope.task.reload); | |
params.reload = $scope.task.reload, $scope.hasAdvanced = params.hasAdvanced, $scope.params = params.params, $scope.mapParams = params.mapParams, $scope.hasMap = params.hasMap, _applyExtentToMapParams(), usSpinnerService.stop("tasks-spinner") | |
}, function() { | |
$scope.setError("Error occurred loading task"), usSpinnerService.stop("tasks-spinner") | |
}) | |
}; | |
_init(), $scope.setError = function(val) { | |
$scope.errorMessage = val, $scope.hasError = !0 | |
}, $scope.selectTask = function(task) { | |
task.name !== $scope.task.name && task.available === !0 && (task.isNew = !0, $scope.task = $.extend({}, task), _init()) | |
}, $scope.execTask = function() { | |
$scope.$emit("taskStatusEvent", "alert-running"); | |
var params = _prepare(); | |
_validate(params).then(function() { | |
var request = { | |
task: $scope.task.name, | |
params: params, | |
isModal: $scope.task.isModal | |
}; | |
$scope.executeTask(request).then(function() { | |
$scope.task.isSelected = !1 | |
}) | |
}, function(error) { | |
_errorHandler(error, params) | |
}) | |
}, $scope.executeTask = function(request) { | |
usSpinnerService.spin("tasks-spinner"), _.isUndefined(request) && (request = { | |
task: $scope.task.name, | |
params: paramService.getAllParams() | |
}); | |
var params = paramService.getStorable(); | |
localStorageService.add(request.task, params), $scope.isRunning = !0, $scope.hasError = !1; | |
var inputItems = _.find(request.params, { | |
type: "VoyagerResults" | |
}); | |
return delete inputItems.ids, inputItems.query = _getQuery(cartService.getQuery(), cartService.getItemIds()), taskService.execute(request).then(function(response) { | |
request.isModal ? ($scope.$dismiss(), $stateParams.id = response.data.id, $stateParams.isModalTask = !0, taskModalService.showStatusModal()) : $state.go("status", { | |
id: response.data.id | |
}) | |
}, function(error) { | |
_errorHandler(error, params) | |
}) | |
}, $scope.cancel = function() { | |
$scope.$dismiss() | |
}, $scope.showInvalidTaskItems = function() { | |
return taskModalService.showInvalidTaskItems($scope.invalidTaskItems) | |
}, $scope.getInvalidTaskItems = function() { | |
taskService.validateTaskItems($scope.task.constraints, !0).then(function(data) { | |
$scope.invalidTaskItems = data.docs, $scope.showInvalidTaskItems($scope.invalidTaskItems).result.then(function() { | |
$scope.task.warning = !1 | |
}) | |
}) | |
} | |
}), angular.module("taskRunner").controller("TasksCtrl", function($scope, taskService, usSpinnerService, authService, $state) { | |
"use strict"; | |
function _loadTasks() { | |
taskService.findAllTasks($scope.canReload).then(function(response) { | |
$scope.taskList = response, usSpinnerService.stop("tasks-spinner"), $scope.refreshing = !1; | |
var unavailableTasks = [], | |
taskCount = 0; | |
angular.forEach($scope.taskList, function(tasks) { | |
tasks.warnings = 0, tasks.errors = 0, unavailableTasks = unavailableTasks.concat(_.filter(tasks, function(task) { | |
return taskService.validateTaskItems(task.constraints).then(function(severity) { | |
1 === severity ? tasks.warnings += 1 : 2 === severity && (tasks.errors += 1), task.severity = severity | |
}), task.available === !1 | |
})), taskCount += tasks.length | |
}), $scope.hasUnavailable = unavailableTasks.length > 0, $scope.allUnavailable = unavailableTasks.length === taskCount, $scope.allUnavailable && ($scope.toggleTasksText = "Show Available") | |
}) | |
} | |
$scope.toggleTasksText = "Show All", $scope.hasUnavailable = !1, $scope.hasInvalidItems = !1, $scope.constraintFormats = [], $scope.refreshTasks = function() { | |
$scope.refreshing = !0, usSpinnerService.spin("tasks-spinner"), taskService.refresh().then(function() { | |
_loadTasks() | |
}) | |
}, $scope.selectTask = function(task) { | |
$scope.constraintFormats = taskService.getTaskConstraintFormats(task.constraints), taskService.validateTaskItems(task.constraints).then(function(severity) { | |
0 === severity ? (task.error = !1, task.warning = !1, $state.go("task", { | |
task: task, | |
type: task.name | |
})) : 1 === severity ? (task.error = !1, task.warning = !0, $scope.hasInvalidItems = !0, $state.go("task", { | |
task: task, | |
type: task.name | |
})) : 2 === severity && taskService.showTaskValidationError($scope.constraintFormats) | |
}) | |
}, authService.getPrivileges().then(function() { | |
$scope.canReload = authService.hasPermission("manage"), _loadTasks() | |
}) | |
}), angular.module("taskRunner").controller("StatusCtrl", function($scope, taskService, $stateParams, $timeout, config, $location, paramService, $window, usSpinnerService, $analytics, $uibModal, sugar) { | |
"use strict"; | |
function _removeSolrBbox(query) { | |
var solrBbox; | |
if (_.isArray(query.fq)) { | |
var index = sugar.getIndex(query.fq, "bbox"); | |
index !== -1 && (solrBbox = query.fq[index], query.fq.splice(index, 1)) | |
} else angular.isDefined(query.fq) && query.fq.indexOf("bbox") !== -1 && (solrBbox = query.fq, delete query.fq); | |
return solrBbox | |
} | |
function _applyBbox(query) { | |
var solrBbox = _removeSolrBbox(query); | |
query.bbox || angular.isDefined(solrBbox) && (query.bboxt = "i", solrBbox.indexOf("IsWithin") !== -1 && (query.bboxt = "w"), query.bbox = solrBbox.substring(solrBbox.indexOf("(") + 1, solrBbox.indexOf(")"))) | |
} | |
function _confirmStatus() { | |
taskService.checkStatus($scope.id).then(function(statusResponse) { | |
$scope.messages = statusResponse.data.errors, $scope.files = taskService.getFiles(statusResponse), $scope.logFiles = taskService.getLogFiles(statusResponse), taskService.getReport(statusResponse).then(function(report) { | |
$scope.report = report | |
}), $scope.warnings = statusResponse.data.warnings, !angular.isUndefined($scope.warnings) && $scope.warnings.length > 0 && ($scope.hasWarning = !0) | |
}, _self.statusError) | |
} | |
function _showFailureInfo(data) { | |
done("alert-danger"), "FAILED" === data.state ? (angular.isUndefined(data.status) ? $scope.errorMessage = $scope.type + " Task " + data.taskId + " " + data.state : $scope.errorMessage = data.status.text + " for " + $scope.type + " Task " + data.taskId, $scope.hasError = !0, $scope.statusMessage = "ERROR", $scope.statusDetail = "Your task could not be completed. View task log for details. " + info, $scope.statusIcon = _getIcon(data.state), $scope.statusColor = "alert-error", $scope.statusStyle = "background-color: #f2dede;") : ($scope.statusMessage = "Cancelled", $scope.statusDetail = "Your task was cancelled.", $scope.statusIcon = _getIcon("CANCELED")), _confirmStatus(), $analytics.eventTrack("process", { | |
category: $scope.type, | |
label: data.state | |
}) | |
} | |
function _showActivityInfo(data) { | |
"RUNNING" === data.state && ($scope.statusIcon = _getIcon(data.state)), $scope.statusMessage = _.str.classify(data.state), _.isUndefined(data.status) || ($scope.progressMessage = data.status.text, $scope.hasProgressMessage = !0), _.isUndefined(data.progress) || ($scope.progress = data.progress), $scope.messageType = "alert-info" | |
} | |
function _showSuccessInfo(data, statusResponse) { | |
$scope.files = taskService.getFiles(statusResponse), $scope.logFiles = taskService.getLogFiles(statusResponse), taskService.getReport(statusResponse).then(function(report) { | |
$scope.report = report | |
}), $scope.statusMessage = "Completed", "WARNING" === data.state ? ($scope.statusMessage += " With Warnings", $scope.statusDetail = "Completed with Warnings. See task log for details.", $scope.statusIcon = _getIcon(data.state), $scope.statusColor = "alert-warning", $scope.messageType = "alert-warning") : ($scope.statusDetail = "Your task was successful.", $scope.statusIcon = _getIcon("SUCCESS"), $scope.statusColor = "alert-success", $scope.messageType = "alert-success"), $scope.files.length > 0 && ($scope.statusDetail = "You can now download your data by clicking the link below. " + $scope.statusDetail), $scope.statusDetail += info, $timeout(function() { | |
_confirmStatus() | |
}, 1e3), done($scope.messageType), $analytics.eventTrack("process", { | |
category: $scope.type, | |
label: data.state | |
}) | |
} | |
function _getIcon(status) { | |
switch (status) { | |
case "PENDING": | |
return { | |
icon: "icon-queue_status_waiting", | |
color: "black" | |
}; | |
case "RUNNING": | |
return { | |
icon: "fa fa-cog fa-spin", | |
color: "#337ab7" | |
}; | |
case "FAILED": | |
return { | |
icon: "icon-queue_status_error", | |
color: "red" | |
}; | |
case "CANCELED": | |
return { | |
icon: "icon-queue_status_cancled", | |
color: "black" | |
}; | |
case "WARNING": | |
return { | |
icon: "icon-queue_status_complete", | |
color: "orange" | |
}; | |
default: | |
return { | |
icon: "icon-queue_status_complete", | |
color: "green" | |
} | |
} | |
} | |
function _reset(isRunning) { | |
$scope.params = [], $scope.inputItems = [], $scope.files = [], $scope.statusDetail = "", $scope.progressMessage = "", $scope.isRunning = isRunning, $scope.hasProgressMessage = !1, $scope.hasProgressMessage = "", $scope.statusMessage = "is Initializing", $scope.progress = [], $scope.hasError = !1, $scope.hasWarning = !1, $scope.statusIcon = "", $scope.showFile = !1, $scope.messages = [], $scope.logFiles = [], $scope.warnings = [], isRunning && ($scope.statusIcon = _getIcon("RUNNING")) | |
} | |
$scope.messageType = "alert-info", $scope.state = "RUNNING", $scope.id = $stateParams.id, $scope.allowNotify = !1, $scope.email = "", $scope.emailButtonText = "Notify Me When Done", $scope.isRunning = !0, $scope.hasItems = !1, $scope.isSuccess = !1, $scope.downloadUrl = "", $scope.messages = [], $scope.isDetailsOpen = !0, $scope.statusMessage = "", $scope.isDetailsCollapsed = !0, $scope.showLog = !0, $scope.logFiles = [], $scope.showFile = !1, $scope.$emit("taskStatusEvent", "alert-running"); | |
var timer, info = "", | |
isModalTask = $stateParams.isModalTask, | |
_self = this, | |
attempts = 0, | |
canNotify = !0, | |
done = function(messageType) { | |
attempts = 0, $scope.messageType = messageType, $scope.allowNotify = !1, $scope.isRunning = !1, $scope.hasProgressMessage = !1, $scope.progress = [], $scope.$emit("taskStatusEvent", messageType) | |
}; | |
this.statusError = function(data) { | |
done("alert-danger"), $scope.messages.push({ | |
message: data.error, | |
trace: data.error | |
}), $scope.state = "FAILED", $scope.statusIcon = _getIcon($scope.state) | |
}; | |
var updateStatusCallback = function(id) { | |
$scope.statusReady = !0, usSpinnerService.stop("status-spinner"), _.isUndefined(id) && (id = $scope.id), $scope.id === id && taskService.checkProgress(id).then(_self.updateStatus) | |
}; | |
this.startCheckStatus = function(response) { | |
$scope.copyUrl = taskService.getCopyUrl($scope.id), taskService.lookupTaskDisplay(response.data.task).then(function(res) { | |
if ($scope.type = res.data.display, !_.isUndefined(response.data.params)) { | |
var readOnlyParams = paramService.initReadOnly(response, res.data), | |
searchParams = $location.search(); | |
$scope.params = readOnlyParams.params, $scope.inputItems = readOnlyParams.inputItems; | |
var query = readOnlyParams.inputItems[0].query; | |
if (query) sugar.removeDoubleQuotes(query), _applyBbox(query), $scope.searchItemURL = "search?disp=" + searchParams.disp + "&" + sugar.toNavigoQueryString(query); | |
else { | |
var ids = readOnlyParams.inputItems[0].ids, | |
idParams = ids.join("&fq=id:"); | |
$scope.searchItemURL = "search?disp=" + searchParams.disp + "&fq=id:" + idParams | |
} | |
$scope.hasMap = readOnlyParams.hasMap, $scope.taskItems = readOnlyParams.inputItems[0].response.docs, $scope.itemCount = readOnlyParams.inputItems[0].response.numFound | |
} | |
updateStatusCallback(response.data.id) | |
}) | |
}, this.updateStatus = function(response) { | |
var data = response.data; | |
$scope.hasItems = !0, $scope.state = _.str.classify(data.state), "FAILED" === data.state || "CANCELED" === data.state ? _showFailureInfo(data) : "RUNNING" === data.state || "PENDING" === data.state ? (_showActivityInfo(data), attempts++, $scope.allowNotify === !1 && config.enableEmail === !0 && canNotify === !0 && ($scope.allowNotify = !0), timer = $timeout(function() { | |
updateStatusCallback(data.taskId) | |
}, 1e3)) : ($scope.isSuccess = !0, taskService.checkStatus($scope.id).then(function(statusResponse) { | |
$scope.warnings = statusResponse.data.warnings, !angular.isUndefined($scope.warnings) && $scope.warnings.length > 0 && ($scope.hasWarnings = !0), _showSuccessInfo(data, statusResponse) | |
}, _self.statusError)) | |
}, $location.path().indexOf("status") > -1 && ($scope.id = $stateParams.id, taskService.checkStatus($scope.id).then(_self.startCheckStatus, _self.statusError), $scope.isStandalone = !0), isModalTask && (taskService.checkStatus($scope.id).then(_self.startCheckStatus, _self.statusError), $scope.isStandalone = !0), $scope.hasMessage = function() { | |
return $scope.messages && $scope.messages.length > 0 | |
}, $scope.emailClick = function() { | |
"Cancel Notify" === $scope.emailButtonText ? (taskService.cancelNotify($scope.id, $scope.email), $scope.emailButtonText = "Notify Me When Done") : (taskService.notify($scope.id, $scope.email), $scope.emailButtonText = "Cancel Notify"), $(".hover_flyout, .opened").removeClass("opened") | |
}, $scope.cancelClick = function() { | |
usSpinnerService.spin("status-spinner"), timer && $timeout.cancel(timer), _reset(!1), $scope.statusMessage = "Cancelled", taskService.cancel($scope.id).then(function() { | |
usSpinnerService.stop("status-spinner") | |
}, function() { | |
usSpinnerService.stop("status-spinner") | |
}) | |
}, $scope.$on("$destroy", function() { | |
timer && $timeout.cancel(timer) | |
}), $scope.cancel = function() { | |
$scope.$dismiss() | |
}, $scope.getData = function(file) { | |
$uibModal.open({ | |
templateUrl: "src/taskrunner/task-log.html", | |
controller: "TaskLogCtrl", | |
size: "lg", | |
resolve: { | |
file: function() { | |
return file | |
}, | |
task: function() { | |
return { | |
id: $scope.id, | |
type: $scope.type | |
} | |
} | |
} | |
}) | |
}, $scope.showDetails = function() { | |
$uibModal.open({ | |
templateUrl: "src/taskrunner/task-details.html", | |
controller: "TaskDetailsCtrl", | |
size: "lg", | |
resolve: { | |
inputItems: function() { | |
return $scope.inputItems | |
}, | |
params: function() { | |
return $scope.params | |
}, | |
task: function() { | |
return { | |
id: $scope.id, | |
type: $scope.type | |
} | |
} | |
} | |
}) | |
}, $scope.showUrl = function() { | |
$scope.showCopyUrl = !0, $timeout(function() { | |
document.getElementById("copy-url").select() | |
}, 0) | |
}, $scope.showReport = function() { | |
var size = "sm"; | |
($scope.report.Skipped || $scope.report.Errors) && (size = "lg"), $uibModal.open({ | |
templateUrl: "src/taskrunner/task-report.html", | |
controller: "TaskReportCtrl", | |
size: size, | |
resolve: { | |
data: function() { | |
return { | |
report: $scope.report, | |
size: size | |
} | |
} | |
} | |
}) | |
} | |
}), angular.module("taskRunner").controller("TaskLogCtrl", function($scope, $uibModalInstance, taskService, usSpinnerService, file, task) { | |
"use strict"; | |
$scope.task = task, usSpinnerService.spin("spinner"), taskService.getFileData(file, !0).then(function(response) { | |
usSpinnerService.stop("spinner"), $scope.logFileData = response.data | |
}), $scope.download = function() { | |
window.location.href = file.downloadUrl | |
}, $scope.cancel = function() { | |
$uibModalInstance.close() | |
} | |
}), angular.module("taskRunner").controller("TaskDetailsCtrl", function($scope, $uibModalInstance, inputItems, params, task) { | |
"use strict"; | |
$scope.task = task, $scope.inputItems = inputItems, $scope.params = params, $scope.cancel = function() { | |
$uibModalInstance.close() | |
} | |
}), angular.module("taskRunner").controller("TaskReportCtrl", function($scope, $uibModalInstance, data) { | |
"use strict"; | |
$scope.data = data.report, $scope.hasDetails = "lg" === data.size, $scope.cancel = function() { | |
$uibModalInstance.close() | |
} | |
}), angular.module("taskRunner").factory("taskModalService", function($uibModal) { | |
"use strict"; | |
var modalInstance = null; | |
return { | |
showTaskValidationError: function(errorMessage, constraintFormats) { | |
$uibModal.open({ | |
templateUrl: "src/taskrunner/task-error-dialog.html", | |
controller: "TaskErrorCtrl", | |
size: "lg", | |
resolve: { | |
errorMessage: function() { | |
return errorMessage | |
}, | |
constraintFormats: function() { | |
return constraintFormats | |
} | |
} | |
}) | |
}, | |
showInvalidTaskItems: function(invalidTaskItems) { | |
return modalInstance = $uibModal.open({ | |
templateUrl: "src/taskrunner/invalid-items-dialog.html", | |
controller: "InvalidItemsCtrl", | |
size: "lg", | |
resolve: { | |
invalidTaskItems: function() { | |
return invalidTaskItems | |
} | |
} | |
}) | |
}, | |
showStatusModal: function() { | |
return modalInstance = $uibModal.open({ | |
templateUrl: "src/taskrunner/status_modal.html", | |
controller: "StatusCtrl", | |
size: "lg" | |
}) | |
}, | |
close: function() { | |
modalInstance.close() | |
} | |
} | |
}), angular.module("taskRunner").controller("TaskErrorCtrl", function($scope, $uibModalInstance, errorMessage, constraintFormats) { | |
"use strict"; | |
$scope.errorMessage = errorMessage, $scope.constraintFormats = constraintFormats, $scope.cancel = function() { | |
$uibModalInstance.dismiss("close") | |
} | |
}), angular.module("taskRunner").directive("vsCartItems", function(cartItemsQuery, cartService, taskService, taskModalService, $location) { | |
return { | |
templateUrl: "src/taskrunner/cart-items.html", | |
scope: { | |
cartItems: "=", | |
invalid: "=", | |
displayCategory: "=", | |
task: "=" | |
}, | |
controller: function($scope) { | |
$scope.disp = $location.search().disp || "default"; | |
var _removeValue = function(array, id) { | |
return _.reject(array, function(item) { | |
return item.id === id | |
}) | |
}; | |
$scope.removeItem = function(id) { | |
cartService.remove(id), $scope.cartItems = _removeValue($scope.cartItems, id) | |
}, $scope.removeInvalidItems = function(invalidItems) { | |
$.each(invalidItems, function(index, item) { | |
cartService.remove(item.id), $scope.cartItems = _removeValue($scope.cartItems, item.id) | |
}), taskModalService.close() | |
}, $scope.removeItemByFormat = function(item) { | |
if (angular.isDefined(item)) cartService.removeByFormat(item.key), cartService.fetch().then(function(data) { | |
cartService.setQueryCount(data.count), | |
$scope.cartItemCount = data.count, $scope.cartItems = data.docs, $scope.loading = !1 | |
}); | |
else { | |
var items = cartService.getItemIds(), | |
query = taskService.getTaskQueryCriteria($scope.task.constraints, !1, items); | |
cartItemsQuery.fetchItems(query, items).then(function(data) { | |
cartService.addQuery(query, items), cartService.setQueryCount(data.count), taskModalService.close() | |
}) | |
} | |
} | |
} | |
} | |
}), angular.module("taskRunner").controller("InvalidItemsCtrl", function($scope, $uibModalInstance, invalidTaskItems) { | |
"use strict"; | |
$scope.invalidTaskItems = invalidTaskItems, $scope.cancel = function() { | |
$uibModalInstance.dismiss("close") | |
} | |
}), angular.module("taskRunner").factory("jobService", function($http, config, $q) { | |
return { | |
fetchJobs: function() { | |
var jobsPromise = $http.jsonp(config.root + "solr/jobs/select?q=*:*&sort=queue_time%20desc&wt=json&rows=100&json.wrf=JSON_CALLBACK&rand=" + Math.random()), | |
displayPromise = $http.jsonp(config.root + "solr/tasks/select?q=*:*&fl=name,display&wt=json&rows=1000&json.wrf=JSON_CALLBACK"); | |
return $q.all([jobsPromise, displayPromise]) | |
}, | |
execute: function(job) { | |
return $http.post(config.root + "api/rest/process/job/" + job.id + "/run.json") | |
}, | |
getCopyUrl: function(id) { | |
return config.root + "api/rest/process/job/" + id + "/run.json" | |
} | |
} | |
}), angular.module("taskRunner").controller("JobsCtrl", function($scope, jobService, $stateParams, config, $window, taskService, sugar, usSpinnerService, urlUtil, $location) { | |
function getIcon(status) { | |
switch (status) { | |
case "PENDING": | |
return { | |
icon: "icon-queue_status_waiting", | |
color: "black" | |
}; | |
case "RUNNING": | |
return { | |
icon: "fa fa-cog fa-spin", | |
color: "#337ab7" | |
}; | |
case "FAILED": | |
return { | |
icon: "icon-queue_status_error", | |
color: "red" | |
}; | |
case "CANCELED": | |
return { | |
icon: "icon-queue_status_cancled", | |
color: "black" | |
}; | |
case "WARNING": | |
return { | |
icon: "icon-queue_status_complete", | |
color: "orange" | |
}; | |
case "SUCCESS": | |
return { | |
icon: "icon-queue_status_complete", | |
color: "green" | |
}; | |
default: | |
return { | |
icon: "icon-queue_status_radioactive", | |
color: "slategray" | |
} | |
} | |
} | |
function _getItems(list) { | |
return _.find(list, function(item) { | |
return "VoyagerResults" === item.type | |
}) | |
} | |
function _getFiles(output) { | |
var files = sugar.toArray(output); | |
return _.filter(files, function(file) { | |
return file.indexOf("_") === -1 | |
}) | |
} | |
$scope.display = $location.search().disp || "default", $scope.goBack = function() { | |
var params = sugar.retroParams($stateParams); | |
$window.location.href = config.root + config.explorePath + "/" + params | |
}, jobService.fetchJobs().then(function(response) { | |
var jobs = response[0].data.response.docs, | |
jobsDisplay = _.indexBy(response[1].data.response.docs, "name"); | |
$.each(jobs, function(index, job) { | |
job.statusIcon = getIcon(job.state), angular.isUndefined(job.output_name) || $.each(job.output_name, function(index, value) { | |
value.indexOf("_") === -1 && (job.hasDownload = !0) | |
}); | |
var jobDisplay = jobsDisplay[job.task]; | |
angular.isUndefined(jobDisplay) ? job.displayName = _(job.task).chain().humanize().titleize().value() : job.displayName = jobDisplay.display | |
}), $scope.jobs = jobs, usSpinnerService.stop("job-spinner") | |
}), $scope.viewItems = function(job) { | |
var data = JSON.parse(job.json), | |
resultsParam = _getItems(data.params), | |
params = $location.search(); | |
sugar.removeDoubleQuotes(resultsParam.query), $window.location = "search?disp=" + params.disp + "&" + sugar.toQueryString(resultsParam.query) | |
}, $scope.download = function(job) { | |
var files = _getFiles(job.output_name); | |
if (1 === files.length) { | |
var file = files[0], | |
downloadUrl = taskService.getFileUrl(job.id, file); | |
$window.location.href = downloadUrl | |
} else $window.location.href = "status?id=" + job.id | |
}, $scope.isDone = function(job) { | |
return "PENDING" !== job && "RUNNING" !== job | |
}, $scope.run = function(job) { | |
usSpinnerService.spin("job-spinner"), jobService.execute(job).then(function(response) { | |
var newJobId = response.data.id; | |
$window.location.href = "status?id=" + newJobId | |
}, function() { | |
usSpinnerService.stop("job-spinner") | |
}) | |
} | |
}), angular.module("taskRunner").controller("ModalBrowseCtrl", function($scope, $uibModalInstance, type, path) { | |
"use strict"; | |
$scope.browserType = type, $scope.path = path, $scope.ok = function(path) { | |
$uibModalInstance.close(path) | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("taskRunner").controller("ModalSearchCtrl", function($scope, $uibModalInstance, queryCriteria) { | |
"use strict"; | |
$scope.queryCriteria = queryCriteria, $scope.isModal = !0, $scope.ok = function(path) { | |
$uibModalInstance.close(path) | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("voyager.map", ["voyager.util"]), angular.module("voyager.map").factory("mapUtil", function(leafletData, config, $timeout) { | |
"use strict"; | |
function _getWeight(type) { | |
var weight = 3; | |
return void 0 !== type && (weight = "within" === type.toLowerCase() ? config.searchMap.bboxWithinWidth : config.searchMap.bboxIntersectsWidth), weight | |
} | |
function _getBounds(bbox) { | |
bbox = bbox.replace(/,/g, " "); | |
var bboxCoords = bbox.split(" "), | |
recStart = { | |
lat: bboxCoords[3], | |
lng: bboxCoords[0] | |
}, | |
recEnd = { | |
lat: bboxCoords[1], | |
lng: bboxCoords[2] | |
}; | |
return [recStart, recEnd] | |
} | |
function _getStyle(type, weight) { | |
var color = config.searchMap.footprintColor, | |
_weight = config.searchMap.footprintWidth; | |
return angular.isDefined(type) && (color = "within" === type.toLowerCase() ? config.searchMap.bboxWithinColor : config.searchMap.bboxIntersectsColor, _weight = _getWeight(type)), angular.isDefined(weight) && (_weight = weight), { | |
color: color, | |
weight: _weight | |
} | |
} | |
return { | |
getWGS84CRS: function() { | |
var _wgs84Proj = L.extend({}, L.Projection.LonLat, { | |
bounds: L.bounds([-180, -90], [180, 90]) | |
}), | |
_wgs84 = L.extend({}, L.CRS, { | |
projection: _wgs84Proj, | |
transformation: new L.Transformation(1 / 180, 1, -1 / 180, .5), | |
getSize: function(zoom) { | |
var b = this.projection.bounds, | |
s = this.scale(zoom), | |
min = this.transformation.transform(b.min, s), | |
max = this.transformation.transform(b.max, s); | |
return L.point(Math.abs(max.x - min.x), Math.abs(max.y - min.y)) | |
} | |
}); | |
return _wgs84 | |
}, | |
getRectangle: function(bbox, type, weight) { | |
var bounds = _getBounds(bbox), | |
style = _getStyle(type, weight); | |
return L.rectangle(bounds, { | |
color: style.color, | |
weight: style.weight, | |
fill: !1 | |
}) | |
}, | |
getPolygon: function(geo, type, weight) { | |
var style = _getStyle(type, weight); | |
return L.polygon(geo.coordinates[0], { | |
color: style.color, | |
weight: style.weight, | |
fill: !1 | |
}) | |
}, | |
getGeoJson: function(geo, type, weight) { | |
_.isString(geo) && (geo = JSON.parse(geo)); | |
var style = _getStyle(type, weight), | |
isPoint = "Point" === geo.type || "MultiPoint" === geo.type; | |
return L.geoJson(geo, { | |
style: { | |
color: style.color, | |
weight: isPoint ? 0 : style.weight, | |
opacity: .65, | |
fill: isPoint, | |
fillOpacity: .65 | |
}, | |
pointToLayer: function(f, ll) { | |
return L.circleMarker(ll, { | |
radius: 6, | |
fillColor: style.color | |
}) | |
} | |
}) | |
}, | |
drawBBox: function(map, bbox, fit, type) { | |
var weight = _getWeight(type), | |
box = this.getRectangle(bbox, type, weight); | |
return map.addLayer(box), fit && map.fitBounds(_getBounds(bbox)), box | |
}, | |
drawPolygon: function(map, geo, fit, type) { | |
var weight = _getWeight(type), | |
polygon = this.getPolygon(geo, type, weight); | |
return map.addLayer(polygon), fit && map.fitBounds(polygon.getBounds()), polygon | |
}, | |
drawGeoJson: function(map, geo, fit, type, checkArea) { | |
var weight = _getWeight(type), | |
geoJson = this.getGeoJson(geo, type, weight), | |
bounds = geoJson.getBounds(), | |
area = 1e5; | |
if (checkArea) { | |
var lyr = L.GeoJSON.geometryToLayer(geo), | |
latlngs = lyr.getLatLngs(); | |
if (area = L.GeometryUtil.geodesicArea(latlngs), area < 15e3 && 0 !== area && "Point" !== geo.type) { | |
geo.type = "Point"; | |
var center = bounds.getCenter(); | |
geo.coordinates = [center.lng, center.lat], geoJson = this.getGeoJson(geo, type, 3) | |
} | |
} | |
return map.addLayer(geoJson), fit && $timeout(function() { | |
map.currentBounds = bounds, map.fitBounds(bounds), area < 15e3 && 0 !== area && map.setZoom(3) | |
}), geoJson | |
}, | |
fitToBBox: function(map, bbox, checkArea) { | |
var bounds = _getBounds(bbox); | |
if (map.fitBounds(bounds), checkArea) { | |
var area = L.GeometryUtil.geodesicArea(bounds); | |
area < 15e3 && map.setZoom(3) | |
} | |
}, | |
isWkt: function(args) { | |
var wkt = new Wkt.Wkt; | |
try { | |
wkt.read(args) | |
} catch (e1) { | |
try { | |
wkt.read(args.replace("\n", "").replace("\r", "").replace("\t", "")) | |
} catch (e2) { | |
return !1 | |
} | |
} | |
return !0 | |
}, | |
getWkt: function(args) { | |
var wkt = new Wkt.Wkt; | |
try { | |
wkt.read(args) | |
} catch (e1) { | |
try { | |
wkt.read(args.replace("\n", "").replace("\r", "").replace("\t", "")) | |
} catch (e2) { | |
if ("WKTError" === e2.name) return void alert("Wicket could not understand the WKT string you entered. Check that you have parentheses balanced, and try removing tabs and newline characters.") | |
} | |
} | |
return wkt.toObject({}) | |
}, | |
moveMapTo: function(wktObj, map) { | |
if (void 0 !== wktObj.getBounds && "function" == typeof wktObj.getBounds) { | |
var height = $(map.getContainer()).height(); | |
height > 0 ? map.fitBounds(wktObj.getBounds()) : map.moveToLater = wktObj.getBounds() | |
} else void 0 !== wktObj.getLatLng && "function" == typeof wktObj.getLatLng && map.panTo(wktObj.getLatLng()) | |
}, | |
setExtent: function(map, param) { | |
var bounds = map.getBounds(); | |
param.extent = bounds.toBBoxString().replace(/,/g, " "); | |
var center = bounds.getCenter(); | |
param.center = center.lat + " " + center.lng, param.zoom = map.getZoom() | |
}, | |
startDraw: function(e, mapId) { | |
leafletData.getMap(mapId).then(function(map) { | |
var options = { | |
shapeOptions: { | |
strokeOpacity: .8, | |
fillOpacity: 0 | |
}, | |
showArea: !1 | |
}; | |
if ("clip-rectangle" === e.target.id) new L.Draw.Rectangle(map, options).enable(); | |
else { | |
var polygon = new L.Draw.Polygon(map, options); | |
polygon.enable() | |
} | |
}) | |
}, | |
getBounds: function(bbox) { | |
return _getBounds(bbox) | |
}, | |
isBbox: function(value) { | |
var isBbox = !1; | |
if (_.isString(value) && !_.isEmpty(value)) { | |
var coords = value.split(" "), | |
nonNumeric = _.find(coords, function(val) { | |
return isNaN(val) | |
}); | |
angular.isUndefined(nonNumeric) && (isBbox = !0) | |
} | |
return isBbox | |
}, | |
convertToWkt: function(latlngs) { | |
var wkt = new Wkt.Wkt; | |
return wkt.fromObject(latlngs), wkt.write() | |
}, | |
formatWktForDisplay: function(wkt) { | |
if (!this.isWkt(wkt)) return wkt; | |
var wktArray = wkt.split(" "), | |
firstPartWkt = wktArray[0].split("."), | |
lastPartWkt = wktArray.pop().split("."), | |
shortWkt = firstPartWkt[0]; | |
if (firstPartWkt[1] && (shortWkt += "." + firstPartWkt[1].substring(0, firstPartWkt[1].length > 1 ? 2 : 1)), shortWkt += " ... " + lastPartWkt[0], lastPartWkt[1]) { | |
var endLastPartArray = lastPartWkt[1].split(")"); | |
endLastPartArray[0].length > 2 && (endLastPartArray[0] = endLastPartArray[0].substring(0, 2)), shortWkt += "." + endLastPartArray.join(")") | |
} | |
return shortWkt | |
}, | |
currentColor: function(type) { | |
return "Within" === type ? config.searchMap.bboxWithinColor : config.searchMap.bboxIntersectsColor | |
}, | |
currentWeight: function(type) { | |
return _getWeight(type) | |
} | |
} | |
}), angular.module("voyager.map").factory("mapControls", function($compile, leafletData, mapUtil, configService) { | |
"use strict"; | |
function _getControls(template, $scope) { | |
var controls = L.control(); | |
return controls.setPosition("topleft"), controls.onAdd = function() { | |
return $compile($(template))($scope)[0] | |
}, controls | |
} | |
function _toggleState(map, $scope, zoomLevel) { | |
void 0 === zoomLevel && (zoomLevel = map.getZoom()), zoomLevel === map.getMaxZoom() ? $scope.zoomInClass = "leaflet-disabled" : $scope.zoomInClass = "", zoomLevel === map.getMinZoom() ? $scope.zoomOutClass = "leaflet-disabled" : $scope.zoomOutClass = "" | |
} | |
var _bbox, _bounds, container = '<div class="leaflet-bar leaflet-draw-toolbar">', | |
rectangle = '<a class="leaflet-draw-draw-rectangle" id="clip-rectangle" target="_self" ng-click="startDraw($event)" title="Clip Rectangle" style="cursor: pointer;"></a>', | |
polygon = '<a class="leaflet-draw-draw-polygon" id="clip-polygon" target="_self" ng-click="startDraw($event)" title="Clip Polygon" style="cursor: pointer;"></a>', | |
endContainer = "</div>", | |
zoomContainer = '<div class="leaflet-control-zoom leaflet-bar leaflet-control">', | |
zoomIn = '<a class="leaflet-control-zoom-in {{zoomInClass}}" href="#" ng-click="zoomIn($event)" ng-dblClick="preventDoubleClick($event)" title="Zoom in" style="cursor: pointer;">+</a>', | |
pan = '<a class="voyager-pan" ng-click="cancelDraw($event)" title="Pan"><span class="icon-map_pan"><span class="path1"></span><span class="path2"></span></span></a>', | |
zoomOut = '<a class="leaflet-control-zoom-out {{zoomOutClass}}" href="#" ng-click="zoomOut($event)" ng-dblClick="preventDoubleClick($event)" title="Zoom out" style="cursor: pointer;">-</a>', | |
defaultExtent = '<a class="voyager-default-extent" id="default-extent" ng-click="defaultExtent($event)" title="Default Extent" style="cursor: pointer;"><span class="icon-map_home"></span></a>', | |
_extent = configService.getDefaultMapView(); | |
return { | |
setBbox: function(val) { | |
_bbox = val | |
}, | |
setBounds: function(bounds) { | |
_bounds = bounds | |
}, | |
init: function($scope, mapId) { | |
$scope.zoomOutClass = "", $scope.zoomInClass = "", _bbox = null, _bounds = null, $scope.zoomIn = function(e) { | |
e.preventDefault(), leafletData.getMap(mapId).then(function(map) { | |
var zoomLevel = map.getZoom(); | |
zoomLevel < map.getMaxZoom() && (map.zoomIn(), _toggleState(map, $scope, zoomLevel + 1)) | |
}), $(".leaflet-draw-actions").hide() | |
}, $scope.zoomOut = function(e) { | |
e.preventDefault(), leafletData.getMap(mapId).then(function(map) { | |
var zoomLevel = map.getZoom(); | |
zoomLevel > map.getMinZoom() && (map.zoomOut(), _toggleState(map, $scope, zoomLevel - 1)) | |
}), $(".leaflet-draw-actions").hide() | |
}, $scope.defaultExtent = function(e) { | |
leafletData.getMap(mapId).then(function(map) { | |
_bbox ? mapUtil.fitToBBox(map, _bbox) : _bounds ? map.fitBounds(_bounds) : map.setView([_extent.lat, _extent.lng], _extent.zoom) | |
}) | |
}, $scope.startDraw = function(e) { | |
mapUtil.startDraw(e, mapId) | |
}, $scope.preventDoubleClick = function(e) { | |
return e.preventDefault(), e.stopPropagation(), !1 | |
}, $scope.cancelDraw = function(e) { | |
e.preventDefault(), $scope.$emit("cancelledDraw") | |
} | |
}, | |
getClipControls: function(withPolygon, $scope) { | |
var template = container + rectangle; | |
return withPolygon && (template += polygon), template += endContainer, _getControls(template, $scope) | |
}, | |
getZoomControls: function($scope) { | |
var template = zoomContainer + zoomIn + zoomOut + defaultExtent; | |
return $scope.showPan && (template += pan), _getControls(template, $scope) | |
}, | |
toggleState: function(map, $scope) { | |
_toggleState(map, $scope) | |
} | |
} | |
}), angular.module("voyager.map").factory("mapCustomControls", function(config, $http) { | |
"use strict"; | |
function _bufferTemplate() { | |
var markup = '<div class="buffer-option" style="min-width: 145px">'; | |
return markup += '<form name="bufferOption">', markup += '<div class="buffer-content"><div class="buffer-label semi">Buffer distance</div>', markup += '<div style="white-space: nowrap;">', markup += '<input type="text" ng-model="buffer.distance" style="float: left"/>', markup += dropdown, markup += "</div>", markup += '<div class="buffer-footer">', markup += '<input type="submit" value="Done" class="btn btn-primary" ng-click="addBuffer()" style="width: 70px; padding-left: 15px"/>', markup += '<a href="#" ng-click="bufferCancel($event)" class="link_secondary">Cancel</a>', markup += "</div>", markup += "</form>", markup += "</div>" | |
} | |
function _drawingToolTemplate() { | |
var template = '<div class="leaflet-draw-section"><div class="leaflet-bar">'; | |
return template += '<a class="voyager-draw-rect" ng-class="{\'selected\': _drawing}" ng-mouseover="toggleDrawingOption($event)" ng-mouseleave="toggleDrawingTools(false)"><i class="icon-map_draw_{{toolType}}"></i></a>', template += "</div>", template += '<div class="leaflet-bar drawing-option-cont" ng-if="showDrawingTools" ng-mouseover="toggleDrawingTools(true)" ng-mouseleave="toggleDrawingTools(false)">', template += '<ul id="drawingTools">', template += '<li><a ng-click="selectDrawingTool($event, \'rectangle\')" title="Rectangle"><i class="icon-map_draw_rectangle"></i></a></li>', template += '<li><a ng-click="selectDrawingTool($event, \'polygon\')" title="Polygon"><i class="icon-map_draw_polygon"></i></a></li>', template += '<li><a ng-click="selectDrawingTool($event, \'polyline\')" title="Line"><i class="icon-map_draw_polyline"></i></a></li>', template += '<li><a ng-click="selectDrawingTool($event, \'point\')" title="Marker"><i class="icon-map_draw_point"></i></a></li>', template += "</ul>", template += "</div></div>" | |
} | |
var dropdown = '<div class="hover_flyout" style="display: inline">'; | |
return dropdown += '<span style="font-weight: bold; font-size: 15px; padding-right: 5px">{{buffer.measure}}</span>', dropdown += '<a href="javascript:;" class="fa fa-chevron-down underline flyout_trigger"></a>', dropdown += '<div class="flyout user_flyout">', dropdown += '<div class="arrow"></div>', dropdown += '<div class="flyout_inner">', dropdown += "<ul>", dropdown += '<li ng-repeat="type in ::bufferMeasures" role="menuitem"><a href="javascript:;" ng-click="buffer.measure = type.id">{{::type.text}}</a></li>', dropdown += "</ul></div></div></div>", { | |
getBufferTemplate: function() { | |
return _bufferTemplate() | |
}, | |
getDrawingToolTemplate: function() { | |
return _drawingToolTemplate() | |
}, | |
convertBuffer: function(buffer, geoJSON) { | |
return $http.post(config.root + "api/rest/spatial/buffer?diff=false&distance=" + buffer.distance + "&units=" + buffer.measure, geoJSON) | |
} | |
} | |
}), angular.module("voyager.map").directive("vsViewMap", function(config, mapUtil, baseMapService, searchService, $timeout) { | |
"use strict"; | |
function _setParam($scope, map) { | |
$scope.param && mapUtil.setExtent(map, $scope.param) | |
} | |
var zoomLayer; | |
$.extend({}, config.mapDefault); | |
return { | |
compile: function(element) { | |
element.append('<leaflet id="view-map" style="height: 100%" defaults="defaults" layers="layers" controls="controls"></leaflet>') | |
}, | |
controller: function($scope, leafletData, mapControls) { | |
mapControls.init($scope, "view-map"), $scope.defaults = $.extend({ | |
zoomControl: !1 | |
}, baseMapService.getDefaultConfig()), $scope.layers = baseMapService.getLayers(), $scope.controls = { | |
custom: [mapControls.getZoomControls($scope)] | |
}, leafletData.getMap("view-map").then(function(map) { | |
_setParam($scope, map), map.on("draw:drawstop", function(e) { | |
map.fitBounds(zoomLayer.getBounds()) | |
}), map.on("draw:created", function(e) { | |
zoomLayer = e.layer | |
}), map.on("moveend", function(e) { | |
_setParam($scope, e.target), mapControls.toggleState(map, $scope) | |
}) | |
}), $scope.$on("$destroy", function() { | |
leafletData.unresolveMap("view-map") | |
}) | |
} | |
} | |
}), angular.module("voyager.map").directive("vsReadOnlyMap", function(mapUtil, baseMapService, $timeout, searchService) { | |
"use strict"; | |
function _isGeometry($scope) { | |
return $scope.param.type && "Geometry" === $scope.param.type | |
} | |
function _applyWkt($scope, map) { | |
var wktObj = mapUtil.getWkt($scope.param.wkt); | |
_isGeometry($scope) && wktObj.addTo(map), $timeout(function() { | |
mapUtil.moveMapTo(wktObj, map) | |
}, 200) | |
} | |
function _applyBbox($scope, bbox, map) { | |
_isGeometry($scope) ? (mapUtil.drawBBox(map, bbox, !1), $timeout(function() { | |
mapUtil.fitToBBox(map, bbox) | |
}, 200)) : mapUtil.fitToBBox(map, bbox) | |
} | |
return { | |
compile: function(element) { | |
element.append('<leaflet id="read-only-map" style="height: 100%" defaults="defaults" layers="layers"></leaflet>') | |
}, | |
controller: function($scope, leafletData) { | |
var config = $.extend({}, baseMapService.getDefaultConfig()); | |
$scope.defaults = config, $scope.layers = baseMapService.getLayers(), $scope.param.wkt ? leafletData.getMap("read-only-map").then(function(map) { | |
_applyWkt($scope, map) | |
}) : $scope.param.extent && leafletData.getMap("read-only-map").then(function(map) { | |
_applyBbox($scope, $scope.param.extent, map) | |
}), $scope.$on("$destroy", function() { | |
leafletData.unresolveMap("read-only-map") | |
}), $timeout(function() { | |
leafletData.getMap("read-only-map").then(function(map) { | |
map.invalidateSize() | |
}) | |
}, 200) | |
} | |
} | |
}), angular.module("voyager.map").directive("vsClipMap", function(config, mapUtil, baseMapService, searchService, $timeout) { | |
"use strict"; | |
function _applyWkt($scope, map) { | |
var wktObj = mapUtil.getWkt($scope.param.wkt), | |
layer = wktObj.addTo(map); | |
return $timeout(function() { | |
mapUtil.moveMapTo(wktObj, map) | |
}, 200), layer | |
} | |
function _updateScope(layer, $scope, digest) { | |
var wkt = new Wkt.Wkt(layer); | |
$scope.$parent.wkt = wkt.write(), $scope.$parent.hasError = !1, digest && $scope.$parent.$digest(), $scope.param && ($scope.param.wkt = $scope.$parent.wkt) | |
} | |
var layer; | |
$.extend({}, config.mapDefault); | |
return { | |
compile: function(element) { | |
element.append('<leaflet id="clip-map" defaults="defaults" layers="layers" controls="controls"></leaflet>') | |
}, | |
controller: function($scope, leafletData, mapControls) { | |
mapControls.init($scope, "clip-map"), $scope.defaults = $.extend({ | |
zoomControl: !1 | |
}, baseMapService.getDefaultConfig()), $scope.layers = baseMapService.getLayers(); | |
var withPolygon = $scope.param && $scope.param.extentParam !== !0; | |
$scope.controls = { | |
custom: [mapControls.getZoomControls($scope), mapControls.getClipControls(withPolygon, $scope)] | |
}, leafletData.getMap("clip-map").then(function(map) { | |
map.on("draw:drawstart", function(e) { | |
layer && (map.removeLayer(layer), layer = null) | |
}), map.on("draw:drawstop", function(e) { | |
map.addLayer(layer), _updateScope(layer, $scope, !0) | |
}), map.on("draw:created", function(e) { | |
layer = e.layer | |
}), map.on("moveend", function(e) { | |
mapControls.toggleState(map, $scope) | |
}), $scope.param && $scope.param.resultsExtent && (layer = mapUtil.getRectangle($scope.param.resultsExtent), layer.options.fill = !1, layer.options.fillColor = "#f06eaa", layer.addTo(map), _updateScope(layer, $scope, !1)) | |
}), $scope.param && $scope.param.reload === !0 && $scope.param.wkt && leafletData.getMap("clip-map").then(function(map) { | |
layer = _applyWkt($scope, map), _updateScope(layer, $scope) | |
}), $scope.$on("$destroy", function() { | |
leafletData.unresolveMap("clip-map") | |
}) | |
} | |
} | |
}), angular.module("voyager.map").factory("mapService", function(config, converter, $q, $timeout) { | |
"use strict"; | |
function _createDynamicLayer(map, mapInfo, spatialReference) { | |
var options = { | |
url: mapInfo.root | |
}; | |
mapInfo.isLayer && (options.layers = [mapInfo.layer]); | |
var layer = L.esri.dynamicMapLayer(options); | |
return layer.addTo(map), 102100 !== spatialReference.wkid && 102113 !== spatialReference.wkid && (layer.options.bboxSR = 102100, layer.options.imageSR = 102100, layer._update()), layer | |
} | |
function _createTiledLayer(map, mapInfo, spatialReference) { | |
var options = { | |
url: mapInfo.root | |
}; | |
mapInfo.isLayer && (options.layers = [mapInfo.layer]); | |
var layer = L.esri.tiledMapLayer(options); | |
return layer.addTo(map), layer | |
} | |
function _createImageLayer(map, mapInfo, spatialReference) { | |
var layer = new L.esri.imageMapLayer({ | |
url: mapInfo.path | |
}); | |
return map.addLayer(layer), layer | |
} | |
function _getSpatialReference(data) { | |
var spatialReference = data.spatialReference; | |
return angular.isUndefined(spatialReference) && (spatialReference = data.extent.spatialReference), spatialReference | |
} | |
function _getExtent(data) { | |
var extent = data.initialExtent; | |
return angular.isUndefined(extent) && (extent = data.extent), extent | |
} | |
function _moveToExtent(data, map, layer) { | |
var extent = _getExtent(data), | |
spatialReference = _getSpatialReference(data); | |
converter.toWebMercator(extent, spatialReference).then(function(bounds) { | |
layer.bounds = bounds, map.fitBounds(bounds), map.currentBounds = bounds | |
}) | |
} | |
function _getWmsExtent(data) { | |
var extent = data.targetBoundingBox, | |
crs = extent.CRS; | |
return angular.isUndefined(crs) && (crs = extent.SRS), "1.1.1" === extent.version ? { | |
ymin: parseFloat(extent.minx), | |
xmin: parseFloat(extent.miny), | |
ymax: parseFloat(extent.maxx), | |
xmax: parseFloat(extent.maxy), | |
crs: crs.replace("EPSG:", "") | |
} : { | |
xmin: parseFloat(extent.minx), | |
ymin: parseFloat(extent.miny), | |
xmax: parseFloat(extent.maxx), | |
ymax: parseFloat(extent.maxy), | |
crs: crs.replace("EPSG:", "") | |
} | |
} | |
function _moveToWmsExtent(data, map, layer) { | |
if (angular.isDefined(data.geoBbox)) { | |
var geoBox = data.geoBbox, | |
bounds = [ | |
[geoBox.southBoundLatitude, geoBox.westBoundLongitude], | |
[geoBox.northBoundLatitude, geoBox.eastBoundLongitude] | |
]; | |
layer.bounds = bounds, map.fitBounds(bounds), map.currentBounds = bounds | |
} else { | |
var extent = _getWmsExtent(data), | |
spatialReference = { | |
wkid: parseInt(extent.crs) | |
}; | |
converter.toLatLng(extent, spatialReference).then(function(bounds) { | |
layer.bounds = bounds, map.fitBounds(bounds), map.currentBounds = bounds | |
}) | |
} | |
} | |
function _validate(data) { | |
var validation = { | |
isValid: !0 | |
}; | |
return angular.isDefined(data.error) && (validation.isValid = !1, validation.error = data.error), validation | |
} | |
function _getError(e, name) { | |
var details = e.statusText; | |
return "abort" === details && (details = "Timed out getting info for: " + name), { | |
message: "Unable to add to map", | |
details: [details] | |
} | |
} | |
function _getMetadata(mapInfo, isFeature) { | |
var deferred = $q.defer(), | |
p = $.getJSON(mapInfo.path + "?f=json&callback=?", function(data) { | |
var validation = _validate(data); | |
if (validation.isValid) | |
if (!mapInfo.isLayer || isFeature) deferred.resolve(data); | |
else { | |
var rootInfo = { | |
path: mapInfo.root, | |
isLayer: !1, | |
name: mapInfo.name | |
}; | |
_getMetadata(rootInfo, !1).then(function(rootData) { | |
data.singleFusedMapCache = rootData.singleFusedMapCache, deferred.resolve(data) | |
}) | |
} | |
else deferred.reject(validation) | |
}).error(function(e) { | |
deferred.reject({ | |
isValid: !1, | |
error: _getError(e, mapInfo.name) | |
}) | |
}); | |
return $timeout(function() { | |
p.abort() | |
}, 5e3), deferred.promise | |
} | |
function _getWmsMetadata(mapInfo) { | |
var deferred = $q.defer(), | |
url = encodeURIComponent(mapInfo.path), | |
p = $.getJSON(config.proxy + ":callback=?", url, function(data) { | |
var validation = _validate(data); | |
if (validation.isValid) { | |
var root = "WMS_Capabilities"; | |
if (angular.isUndefined(data[root]) && (root = "WMT_MS_Capabilities"), mapInfo.isLayer) { | |
var param, layerName, pathTokens = mapInfo.path.split("&"); | |
$.each(pathTokens, function(index, value) { | |
param = value.split("="), "layer.name" === param[0] && (layerName = param[1]) | |
}); | |
var layers = data[root].Capability.Layer.Layer, | |
targetLayer = _.find(layers, { | |
Name: layerName | |
}); | |
targetLayer.targetBoundingBox = targetLayer.BoundingBox, data.geoBbox = data[root].Capability.Layer.EX_GeographicBoundingBox, data.version = data[root].version, "1.1.1" === data.version && (data.targetBoundingBox = data[root].Capability.Layer.LatLonBoundingBox, data.targetBoundingBox.CRS = "EPSG:4326", data.targetBoundingBox.version = "1.1.1"), targetLayer.name = targetLayer.Name, deferred.resolve(targetLayer) | |
} else { | |
data.targetBoundingBox = data[root].Capability.Layer.BoundingBox, data.geoBbox = data[root].Capability.Layer.EX_GeographicBoundingBox, data.version = data[root].version, "1.1.1" === data.version && (data.targetBoundingBox = data[root].Capability.Layer.LatLonBoundingBox, data.targetBoundingBox.CRS = "EPSG:4326", data.targetBoundingBox.version = "1.1.1"); | |
var layerNames = _.pluck(data[root].Capability.Layer.Layer, "Name"); | |
data.name = layerNames.join(), deferred.resolve(data) | |
} | |
} else deferred.reject(validation) | |
}).error(function(e) { | |
deferred.reject({ | |
isValid: !1, | |
error: _getError(e, mapInfo.name) | |
}) | |
}); | |
return $timeout(function() { | |
p.abort() | |
}, 5e3), deferred.promise | |
} | |
function _addMapServerLayer(map, mapInfo) { | |
var deferred = $q.defer(); | |
return _getMetadata(mapInfo, !1).then(function(data) { | |
var layer, spatialReference = _getSpatialReference(data); | |
layer = mapInfo.format.indexOf("application/x-arcgis-image-server") > -1 ? _createImageLayer(map, mapInfo, spatialReference) : data.singleFusedMapCache === !0 && 102100 === spatialReference.wkid ? _createTiledLayer(map, mapInfo, spatialReference) : _createDynamicLayer(map, mapInfo, spatialReference), _moveToExtent(data, map, layer), deferred.resolve(layer) | |
}, function(error) { | |
deferred.reject(error) | |
}), deferred.promise | |
} | |
function _addFeatureServiceLayer(map, mapInfo) { | |
var deferred = $q.defer(); | |
return _getMetadata(mapInfo, !1).then(function(data) { | |
var layer = null; | |
mapInfo.isLayer ? layer = new L.esri.FeatureLayer({ | |
url: mapInfo.path | |
}).addTo(map) : $.each(data.layers, function(index, value) { | |
var url = mapInfo.path + "/" + value.id; | |
layer = new L.esri.FeatureLayer({ | |
url: url | |
}).addTo(map) | |
}), layer.on("load", function() { | |
loaded || (loaded = !0, layer.query().bounds(function(error, latlngbounds) { | |
layer.bounds = latlngbounds, map.fitBounds(latlngbounds), map.currentBounds = latlngbounds | |
})) | |
}), deferred.resolve(layer) | |
}, function(error) { | |
deferred.reject(error) | |
}), deferred.promise | |
} | |
function _addWMSLayer(map, mapInfo) { | |
var deferred = $q.defer(), | |
urlInfo = mapInfo.path.split("?"); | |
return _getWmsMetadata(mapInfo, !1).then(function(data) { | |
var layer = L.tileLayer.wms(urlInfo[0], { | |
layers: data.name, | |
format: "image/png", | |
transparent: !0 | |
}); | |
layer.on("load", function() { | |
loaded || (loaded = !0) | |
}), layer.addTo(map), _moveToWmsExtent(data, map, layer), deferred.resolve(layer) | |
}), deferred.promise | |
} | |
var loaded = !0, | |
mappable = { | |
"application/x-arcgis-image-server": !0, | |
"application/x-arcgis-feature-server": !0, | |
"application/x-arcgis-feature-server-layer": !0, | |
"application/x-arcgis-map-server": !0, | |
"application/x-arcgis-map-server-layer": !0, | |
"application/vnd.ogc.wms_xml": !0, | |
"application/vnd.ogc.wms_layer_xml": !0 | |
}; | |
return { | |
addToMap: function(mapInfo, map) { | |
return loaded = !1, mapInfo.format.indexOf("application/x-arcgis-map-server") > -1 || mapInfo.format.indexOf("application/x-arcgis-image-server") > -1 ? _addMapServerLayer(map, mapInfo) : mapInfo.format.indexOf("application/x-arcgis-feature-server") > -1 ? _addFeatureServiceLayer(map, mapInfo) : mapInfo.format.indexOf("application/vnd.ogc.wms") > -1 ? _addWMSLayer(map, mapInfo) : $q.reject({ | |
isValid: !1, | |
error: "Not Supported" | |
}) | |
}, | |
isMappable: function(format) { | |
return mappable[format] | |
} | |
} | |
}), angular.module("voyager.map").factory("wmsLayerQuery", function(config, $http) { | |
function _getQueryString(id) { | |
return config.root + "solr/v0/select?links.to=" + id + ":_root&fl=wms_layer_name&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
return { | |
execute: function(id) { | |
return $http.jsonp(_getQueryString(id)).then(function(data) { | |
return _.pluck(data.data.response.docs, "wms_layer_name") | |
}, function(error) { | |
return console.log(error), error | |
}) | |
} | |
} | |
}), angular.module("voyager.map").factory("simpleMapService", function(mapUtil, $q) { | |
function _getOptions(mapInfo) { | |
var options = {}; | |
return options.url = mapInfo.root, mapInfo.isLayer && (options.layers = [mapInfo.layer]), options | |
} | |
function _createDynamicLayer(map, mapInfo, spatialReference) { | |
var layer = L.esri.dynamicMapLayer(_getOptions(mapInfo)); | |
return layer.addTo(map), layer | |
} | |
function _createTiledLayer(map, mapInfo) { | |
var layer = L.esri.tiledMapLayer(_getOptions(mapInfo)); | |
return layer.addTo(map), layer | |
} | |
function _createImageLayer(map, mapInfo, spatialReference) { | |
var layer = new L.esri.imageMapLayer({ | |
url: mapInfo.path | |
}); | |
return map.addLayer(layer), layer | |
} | |
function _moveToExtent(map, layer, mapInfo) { | |
var bounds = mapUtil.getBounds(mapInfo.bbox); | |
layer.bounds = bounds, map.fitBounds(bounds), map.currentBounds = bounds | |
} | |
function _addMapServerLayer(map, mapInfo) { | |
var layer; | |
return layer = mapInfo.format.indexOf("application/x-arcgis-image-server") > -1 ? _createImageLayer(map, mapInfo) : mapInfo.ags_fused_cache === !0 ? _createTiledLayer(map, mapInfo) : _createDynamicLayer(map, mapInfo), _moveToExtent(map, layer, mapInfo), layer | |
} | |
var loaded = !0; | |
return { | |
addToMap: function(mapInfo, map) { | |
loaded = !1; | |
var layer = _addMapServerLayer(map, mapInfo); | |
return $q.when(layer) | |
} | |
} | |
}), angular.module("voyager.map").factory("simpleFeatureServer", function(config, converter, $q) { | |
"use strict"; | |
function _addFeatureServiceLayer(map, mapInfo) { | |
var layer = null, | |
layerCount = 1; | |
return angular.isDefined(mapInfo.linkcount__children) && (layerCount = mapInfo.linkcount__children), mapInfo.isLayer ? layer = new L.esri.Services.featureLayerService({ | |
url: mapInfo.path | |
}).addTo(map) : $.each(new Array(layerCount), function(index, value) { | |
var url = mapInfo.path + "/" + index; | |
layer = new L.esri.FeatureLayer({ | |
url: url | |
}).addTo(map) | |
}), layer.on("load", function() { | |
_loaded || (_loaded = !0, layer.query().bounds(function(error, latlngbounds) { | |
layer.bounds = latlngbounds, map.fitBounds(latlngbounds), map.currentBounds = latlngbounds | |
})) | |
}), layer | |
} | |
var _loaded = !0; | |
return { | |
addToMap: function(mapInfo, map) { | |
_loaded = !1; | |
var layer = _addFeatureServiceLayer(map, mapInfo); | |
return $q.when(layer) | |
} | |
} | |
}), angular.module("voyager.map").factory("simpleWmsService", function(config, converter, $q, mapUtil, wmsLayerQuery) { | |
function _moveToExtent(map, layer, mapInfo) { | |
var bounds = mapUtil.getBounds(mapInfo.bbox); | |
layer.bounds = bounds, map.fitBounds(bounds), map.currentBounds = bounds | |
} | |
function _addLayer(map, mapInfo) { | |
var urlInfo = mapInfo.path.split("?"), | |
layers = mapInfo.wms_layer_name; | |
mapInfo.layerNames && (layers = mapInfo.layerNames); | |
var layer = L.tileLayer.wms(urlInfo[0], { | |
layers: layers, | |
format: "image/png", | |
transparent: !0 | |
}); | |
return layer.on("load", function() { | |
loaded || (loaded = !0) | |
}), layer.addTo(map), _moveToExtent(map, layer, mapInfo), layer | |
} | |
var loaded = !0; | |
return { | |
addToMap: function(mapInfo, map) { | |
if (loaded = !1, mapInfo.contains_name) return wmsLayerQuery.execute(mapInfo.id).then(function(layerNames) { | |
return layerNames = layerNames.slice(0, 10), mapInfo.layerNames = layerNames.join(), _addLayer(map, mapInfo) | |
}); | |
var layer = _addLayer(map, mapInfo); | |
return $q.when(layer) | |
} | |
} | |
}), angular.module("voyager.map").factory("mapServiceFactory", function(config, converter, $q, simpleMapService, mapService, simpleFeatureServer, simpleWmsService) { | |
function _getRootPath(mapInfo) { | |
var path = mapInfo.path, | |
index = path.lastIndexOf("/"), | |
root = path.substring(0, index + 1), | |
layer = path.substring(index + 1, path.length); | |
mapInfo.root = root, mapInfo.layer = layer | |
} | |
var mappable = { | |
"application/x-arcgis-image-server": !0, | |
"application/x-arcgis-feature-server": !0, | |
"application/x-arcgis-feature-server-layer": !0, | |
"application/x-arcgis-map-server": !0, | |
"application/x-arcgis-map-server-layer": !0, | |
"application/vnd.ogc.wms_xml": !0, | |
"application/vnd.ogc.wms_layer_xml": !0 | |
}; | |
return { | |
getMapService: function(mapInfo) { | |
return angular.isUndefined(mapInfo.path) && (mapInfo.path = mapInfo.fullpath), mapInfo.path = mapInfo.path.replace(/\+/g, "%20"), mapInfo.root = mapInfo.path, mapInfo.format.indexOf("layer") > -1 && (mapInfo.isLayer = !0, _getRootPath(mapInfo)), mapInfo.format.indexOf("application/x-arcgis-map-server") > -1 || mapInfo.format.indexOf("application/x-arcgis-image-server") > -1 ? angular.isDefined(mapInfo.bbox) ? simpleMapService : mapService : mapInfo.format.indexOf("application/x-arcgis-feature-server") > -1 ? angular.isDefined(mapInfo.linkcount__children) ? simpleFeatureServer : mapService : mapInfo.format.indexOf("application/vnd.ogc.wms") > -1 ? angular.isDefined(mapInfo.bbox) ? simpleWmsService : mapService : { | |
isValid: !1, | |
error: "Not Supported" | |
} | |
}, | |
isMappable: function(format) { | |
return mappable[format] | |
} | |
} | |
}), angular.module("voyager.map").factory("baseMapService", function(config, converter, mapUtil, $http, $q) { | |
"use strict"; | |
function _fetchBaselayers() { | |
var service = config.root + "api/rest/display/maps"; | |
return $http.get(service).then(function(response) { | |
return response.data | |
}) | |
} | |
function _getBaselayers() { | |
return angular.isDefined(_baselayers) ? $q.when(_baselayers) : _fetchBaselayers().then(function(data) { | |
if (_baselayers = _processBaselayerData(data), Object.keys(_baselayers).length <= 0) { | |
var layerData = [{ | |
name: _layers.baselayers.base.name, | |
url: _layers.baselayers.base.url, | |
layers: _layers.baselayers.base.layerOptions.layers, | |
selected: !0 | |
}]; | |
_baselayers = _processBaselayers(_baselayers, layerData, _layers.baselayers.base.type) | |
} | |
return _baselayers | |
}) | |
} | |
function _processBaselayerData(layerData) { | |
var baselayers = {}; | |
return layerData.ags && (baselayers = _processBaselayers(baselayers, layerData.ags, "ags")), layerData.bing && (baselayers = _processBaselayers(baselayers, layerData.bing, "bing")), layerData.google && (baselayers = _processBaselayers(baselayers, layerData.google, "google")), layerData.mapbox && (baselayers = _processBaselayers(baselayers, layerData.mapbox, "mapbox")), layerData.wms && (baselayers = _processBaselayers(baselayers, layerData.wms, "wms")), baselayers | |
} | |
function _processBaselayers(baselayers, layers, type) { | |
return baselayers = baselayers || {}, $.each(layers, function(index, layer) { | |
var layerType = type, | |
layerUrl = layer.url; | |
config.map.config.proxy && (layerUrl = config.root + "proxy?" + layerUrl); | |
var layerOptions = { | |
continuousWorld: !1, | |
showOnSelector: !0 | |
}, | |
layerDefault = layer.selected || !1, | |
layerCached = !1; | |
if (layerUrl) { | |
switch (type) { | |
case "ags": | |
layer.cached === !0 ? (layerUrl += "tile/{z}/{y}/{x}/", layerType = "xyz", layerCached = !0) : layerType = "agsDynamic", layerOptions.layers = layer.layers; | |
break; | |
case "google": | |
layerCached = !0; | |
break; | |
case "bing": | |
layerCached = !0; | |
break; | |
case "mapbox": | |
layerUrl = layerUrl.replace(/\$/g, ""), layerCached = !0; | |
break; | |
case "wms": | |
layerOptions.layers = layer.layers, layerOptions.format = "image/png", layerOptions.transparent = !0, layerCached = !0 | |
} | |
var layerInfo = { | |
name: layer.name, | |
type: layerType, | |
url: layerUrl, | |
cached: layerCached, | |
default: layerDefault, | |
options: layerOptions | |
}; | |
layerDefault && (_defaultBaselayer = { | |
name: layerInfo.name, | |
type: layerInfo.type, | |
url: layerInfo.url, | |
cached: layerCached, | |
layerOptions: layerInfo.options | |
}, _defaultBaselayer.layerOptions.showOnSelector = !1), baselayers[layerInfo.name] = layerInfo | |
} | |
}), baselayers | |
} | |
var _baselayers, _defaultBaselayer, _baselayerStorageName = "selected-base-layer", | |
_defaultConfig = { | |
attributionControl: !1, | |
scrollWheelZoom: !0, | |
zoomControl: !1, | |
minZoom: 1 | |
}, | |
_layers = { | |
baselayers: { | |
base: { | |
name: "arcgis", | |
type: "xyz", | |
url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}/", | |
layerParams: {}, | |
layerOptions: { | |
showOnSelector: !1 | |
} | |
} | |
} | |
}, | |
baseMap = _.getPath(config, "map.config.url"); | |
return angular.isDefined(baseMap) && (config.map.config.proxy && (baseMap = config.root + "proxy?" + baseMap), "WMSLayerDefinition" === config.map.type ? (delete _defaultConfig.tileLayer, _defaultConfig.crs = "EPSG4326", _layers = { | |
baselayers: { | |
base: { | |
name: config.map.config.name, | |
type: "wms", | |
url: baseMap, | |
layerOptions: { | |
layers: config.map.config.layers, | |
showOnSelector: !1 | |
}, | |
layerParams: {} | |
} | |
} | |
}) : "MapboxLayerDefinition" === config.map.type ? _layers.baselayers.base.url = baseMap.replace(/\$/g, "") : config.map.config.cached === !0 ? (_layers.baselayers.base.url = baseMap + "tile/{z}/{y}/{x}/", config.map.config.simpleWGS84 && (_defaultConfig.crs = mapUtil.getWGS84CRS())) : (delete _defaultConfig.tileLayer, _layers = { | |
baselayers: { | |
base: { | |
name: config.map.config.name, | |
type: "agsDynamic", | |
url: baseMap, | |
layerOptions: { | |
layers: config.map.config.layers, | |
showOnSelector: !1 | |
} | |
} | |
} | |
})), { | |
BASELAYER_STORAGE_NAME: _baselayerStorageName, | |
getDefaultConfig: function() { | |
return _defaultConfig | |
}, | |
getLayers: function(origin) { | |
if ("home" === origin) { | |
var homeLayer = _.clone(_layers, !0); | |
return config.homepage.wrapMap === !1 && (homeLayer.baselayers.base.layerParams.noWrap = !0), homeLayer | |
} | |
return _layers | |
}, | |
getBaselayers: function() { | |
return _getBaselayers() | |
}, | |
getDefaultBaselayer: function() { | |
return _defaultBaselayer | |
}, | |
getCRSForLayerType: function(type) { | |
return "wms" === type ? L.CRS.EPSG4326 : L.CRS.EPSG3857 | |
} | |
} | |
}), angular.module("fileBrowser", []), angular.module("fileBrowser").factory("fileBrowserService", function($http, config) { | |
"use strict"; | |
return { | |
browse: function(uri) { | |
return $http.get(config.root + "api/rest/system/browse.json?uri=" + uri) | |
} | |
} | |
}), angular.module("fileBrowser").controller("FileBrowserCtrl", function($scope, fileBrowserService, usSpinnerService, $timeout, translateService, config, $stateParams) { | |
"use strict"; | |
function _decorate(list) { | |
return $.each(list, function(index, value) { | |
value.isFile = !1, value.iconUrl = config.root + "vres/mime/icon/application/vnd.voyager.folder", angular.isUndefined(value.parentUri) ? (value.icon = "fa fa-hdd-o", value.type = "Drive") : value.folder === !0 ? (value.icon = "fa fa-folder gridFolder", value.type = "Folder") : (value.type = translateService.getType(value.format), value.iconUrl = config.root + "vres/mime/icon/" + value.format, value.isFile = !0), angular.isDefined(value.parts) && value.parts.length > 0 && (value.hasParts = !0, value.partsCount = value.parts.length, value.partsDisplay = value.parts.join("<br/>")) | |
}), list | |
} | |
function _getPathArray(response) { | |
var pathLinks = []; | |
return response.data.uri.indexOf("\\") > -1 ? (pathLinks = response.data.uri.split("\\"), "" === pathLinks[1] && (pathLinks = pathLinks.splice(0, 1))) : response.data.uri.indexOf("/") > -1 && (pathLinks = response.data.uri.split("/"), "" === pathLinks[1] && (pathLinks = pathLinks.splice(0, 1)), pathSep = "/"), pathLinks | |
} | |
function _browse(path, selected) { | |
var encoded = encodeURIComponent(path); | |
usSpinnerService.spin("browser-spinner"), fileBrowserService.browse(encoded).then(function(response) { | |
$scope.gridData = _decorate(response.data.children), $scope.pathLinks = _getPathArray(response), $scope.editPath = !1, $scope.path = path, $("#voyagerSearch").trigger("selectedPath", path), usSpinnerService.stop("browser-spinner") | |
}, function(error) { | |
usSpinnerService.stop("browser-spinner"), $scope.error = "Could not open " + decodeURIComponent(path), "" === path || selected || _browse("") | |
}) | |
} | |
function _selectRow(rowItem, event) { | |
rowItem.selected && rowItem.entity.folder === !0 && _browse(rowItem.entity.uri, !0), "folder" !== $scope.browserType && ($scope.path = rowItem.entity.uri, $("#voyagerSearch").trigger("selectedPath", $scope.path)) | |
} | |
function _getUri(path, index) { | |
var uri; | |
return "" !== path ? ($scope.pathLinks.splice(index + 1, $scope.pathLinks.length - (index + 1)), uri = $scope.pathLinks.length > 1 ? $scope.pathLinks.join(pathSep) : $scope.pathLinks[0] + pathSep) : uri = "", uri | |
} | |
var pathSep = "\\"; | |
angular.isUndefined($scope.browserType) && ($scope.browserType = "folder"), $scope.isInline = $stateParams.inline, angular.isUndefined($scope.path) && ($scope.path = ""); | |
var pathClicked = !1, | |
componentsTemplate = '<div class="ngCellText"> <a tooltip-html-unsafe="{{row.getProperty(\'partsDisplay\')}}" tooltip-append-to-body="true" tooltip-placement="left" class="badge" ng-show="{{row.getProperty(\'hasParts\')}}">{{row.getProperty(\'partsCount\')}}</a> {{row.getProperty(col.field)}}</div>', | |
nameTemplate = '<div class="ngCellText"><img src="{{row.getProperty(\'iconUrl\')}}"/> {{row.getProperty(col.field)}}</div>'; | |
$scope.gridOptions = { | |
enableHighlighting: !0, | |
multiSelect: !1, | |
data: "gridData", | |
enableColumnResize: !0, | |
afterSelectionChange: _selectRow, | |
columnDefs: [{ | |
field: "name", | |
displayName: "Name", | |
cellTemplate: nameTemplate | |
}, { | |
field: "type", | |
displayName: "Type" | |
}, { | |
field: "fileSize", | |
displayName: "File Size", | |
cellTemplate: componentsTemplate | |
}] | |
}, $timeout(function() { | |
$(window).resize() | |
}, 0), $scope.$on("ngGridEventData", function() {}), _browse($scope.path), $scope.browse = function() { | |
_browse($scope.path) | |
}, $scope.pathClick = function(path, index) { | |
pathClicked = !0, $scope.editPath = !1, $scope.path = _getUri(path, index), _browse($scope.path) | |
}, $scope.pathContainerClick = function(path) { | |
pathClicked || ($scope.editPath = !0, $timeout(function() { | |
angular.element("#pathInput").focus() | |
}, 0)), pathClicked = !1 | |
}, $scope.movedAway = function() { | |
$scope.editPath = !1 | |
}, $scope.setPath = function() { | |
$("#voyagerSearch").trigger("selectedPath", $scope.path), $scope.ok($scope.path) | |
}, $scope.closeBrowser = function() { | |
$("#voyagerSearch").trigger("cancelBrowse"), $scope.cancel() | |
} | |
}), angular.module("voyager.config", ["voyager.common.savedsearch"]), angular.module("voyager.config").factory("configService", function(config, translateService, complexFilterService, $http, $q, catalogService, $location, solrUtil) { | |
function _getPageFramework() { | |
return _pageFramework | |
} | |
function _getDefaultView() { | |
return _defaultView.toLowerCase() | |
} | |
function _getCardView() { | |
return _cardView | |
} | |
function _setConfigFields(displayFields) { | |
$.each(displayFields, function(index, value) { | |
_displayFields[value.name] = translateService.getFieldName(value.name), _displayFieldsOrder[value.name] = index, _displayFieldsStyle[value.name] = value.style, _solrParams += "," + value.name, value.editable && (_editable[value.name] = value.name) | |
}) | |
} | |
function _setSummaryFields(summaryFields) { | |
$.each(summaryFields, function(index, value) { | |
_summaryFields[value.name] = translateService.getFieldName(value.name), _summaryFieldsOrder[value.name] = index, _summaryFieldsStyle[value.name] = value.style, _summaryFieldsShowLabels[value.name] = value.showLabel, _summaryFieldsMaxLines[value.name] = value.maxLines, _summarySolrParams += "," + value.name | |
}) | |
} | |
function _setTableFields(table) { | |
_tableFields = [], $.each(table, function(index, value) { | |
var name = value.name; | |
value.name = solrUtil.stripAugmented(value.name), _tableFieldsStyle[value.name] = value.style; | |
var tableField = { | |
field: value.name, | |
display: translateService.getFieldName(value.name), | |
width: value.width, | |
sortable: name === value.name | |
}; | |
_tableFields.push(tableField), angular.isDefined(value.width) && (_tableColumnWidthMap[value.field] = { | |
value: parseFloat(value.width) | |
}) | |
}) | |
} | |
function _setCardViewFields(cardViewFields) { | |
_cardViewFields = [], $.each(cardViewFields, function(index, value) { | |
var cardViewField = { | |
field: value.name, | |
display: translateService.getFieldName(value.name) | |
}; | |
cardViewField.maxLines = value.maxLines || 3, cardViewField.showLabel = value.showLabel, _cardViewFields.push(cardViewField) | |
}) | |
} | |
function _setCardViewNames(cardViewNames) { | |
_cardViewNames = [], $.each(cardViewNames, function(index, value) { | |
var cardViewName = { | |
field: value, | |
display: translateService.getFieldName(value) | |
}; | |
_cardViewNames.push(cardViewName) | |
}) | |
} | |
function _updateConfig(configData) { | |
_shards = null, _systemFilterMap = _.indexBy(configData.filters, "field"), _isQueryAllCatalogs = configData.queryAllCatalogs, _setConfigFields(configData.details.detailsTableFields), _globalEditable = configData.details.detailsTableFieldsAreEditable, _homepage = configData.homepage, _pageFramework = configData.pageElements, _defaultView = configData.defaultView, _cardView = configData.cardView, _gridView = configData.gridView, configData.cardView ? _setSummaryFields(configData.cardView.fields || []) : (_summaryFields = {}, _summarySolrParams = "", _summaryFieldsOrder = {}, _summaryFieldsStyle = {}), angular.isDefined(configData.listView) && _setTableFields(configData.listView.fields || []), angular.isDefined(configData.cardView) && (angular.isDefined(configData.cardView.fields) && _setCardViewFields(configData.cardView.fields), angular.isDefined(configData.cardView.names) && _setCardViewNames(configData.cardView.names)) | |
} | |
function _setFilterDataTypes() { | |
var filterString = _.keys(_systemFilterMap).join(" "); | |
return $http.jsonp(config.root + "solr/fields/select?fq=name:(" + filterString + ")&fl=name,multivalued,disp:disp_en,stype&wt=json&json.wrf=JSON_CALLBACK&rows=1000").then(function(filterData) { | |
_.each(filterData.data.response.docs, function(doc) { | |
var filter = _systemFilterMap[doc.name]; | |
filter.stype = doc.stype, filter.multivalued = doc.multivalued, filter.disp = doc.disp | |
}) | |
}) | |
} | |
function _load(configId) { | |
return $http.get(config.root + "api/rest/display/config/" + configId + ".json").then(function(res) { | |
return _configId = configId, config.settings = res, _updateConfig(config.settings.data), _setFilterDataTypes().then(function() { | |
return config.settings.data | |
}) | |
}) | |
} | |
function _setDefaultConfig() { | |
return null !== _configId ? (_configId = null, _load(config.configid).then(function() { | |
return $location.search("disp", config.configid), { | |
configId: config.configid | |
} | |
})) : config.settings ? (_updateConfig(config.settings.data), $q.when({ | |
configId: config.configid | |
})) : _load(config.configid).then(function() { | |
return $location.search("disp", config.configid), { | |
configId: config.configid | |
} | |
}, function(error) { | |
return $q.reject(error) | |
}) | |
} | |
function _setFilterConfig(configId) { | |
var deferred = $q.defer(); | |
return configId === _configId ? deferred.resolve({ | |
configId: configId | |
}) : angular.isDefined(configId) ? _load(configId).then(function() { | |
deferred.resolve({ | |
configId: configId | |
}) | |
}, function() { | |
_setDefaultConfig().then(function(config) { | |
deferred.resolve(config) | |
}) | |
}) : _setDefaultConfig().then(function(config) { | |
deferred.resolve(config) | |
}), deferred.promise | |
} | |
function _createCatalogFacet(catalog, urlShards) { | |
var selected = _.indexOf(urlShards, catalog.id) !== -1 || _isQueryAllCatalogs; | |
return { | |
display: catalog.name, | |
style: "CHECK", | |
isSelected: selected, | |
field: "shard", | |
hasCount: !1, | |
id: catalog.id, | |
raw: catalog.url | |
} | |
} | |
function _createCatalogFilter(catalogFilter, facetTypes) { | |
catalogFilter || (catalogFilter = { | |
field: "shards", | |
value: "Catalog", | |
values: [] | |
}, facetTypes.unshift(catalogFilter)), catalogFilter.value = "Catalog"; | |
var urlShards = $location.search().shards; | |
angular.isDefined(urlShards) && (urlShards = urlShards.split(",")), _catalogsPromise = catalogService.fetch().then(function(catalogs) { | |
var selectedCount = 0; | |
if (_.each(catalogs, function(catalog) { | |
var facet = _createCatalogFacet(catalog, urlShards); | |
catalogFilter.values.push(facet), facet.isSelected && selectedCount++ | |
}), 1 === selectedCount) { | |
var filter = _.find(catalogFilter.values, { | |
isSelected: !0 | |
}); | |
filter.disabled = !0 | |
} | |
_isQueryAllCatalogs && _.each(catalogFilter.values, function(facet) { | |
facet.disabled = !0 | |
}) | |
}) | |
} | |
var _catalogsPromise, _pageFramework, _defaultView, _cardView, _gridView, _globalEditable, _isQueryAllCatalogs, _configId = null, | |
_systemFilters = null, | |
_systemFilterMap = {}, | |
_displayFields = {}, | |
_summaryFields = {}, | |
_solrParams = "", | |
_summarySolrParams = "", | |
_tableFields = [], | |
_tableFieldsStyle = [], | |
_cardViewFields = [], | |
_cardViewNames = [], | |
_displayFieldsOrder = {}, | |
_displayFieldsStyle = {}, | |
_displayFieldsShowLabels = {}, | |
_displayFieldsMaxLines = {}, | |
_summaryFieldsOrder = {}, | |
_summaryFieldsStyle = {}, | |
_summaryFieldsShowLabels = {}, | |
_summaryFieldsMaxLines = {}, | |
_tableColumnWidthMap = {}, | |
_shards = null, | |
_homepage = {}, | |
_editable = {}, | |
_defaultMapView = { | |
lng: 0, | |
lat: 0, | |
zoom: 3 | |
}; | |
try { | |
_updateConfig(config.settings.data) | |
} catch (err) {} | |
return { | |
getPageFramework: _getPageFramework, | |
getDefaultView: _getDefaultView, | |
getCardView: _getCardView, | |
getGridView: function() { | |
return _gridView | |
}, | |
getDisplayFilters: function() { | |
var catalogFilter, discoveryStatusFilter, facetTypes = config.settings.data.filters, | |
hasShard = !1; | |
return $.each(facetTypes, function(index, value) { | |
value.value = "", value.values = [], "HIERARCHY" === value.style && (value.value = translateService.getFieldName(value.field)), "shards" === value.field && (hasShard = !0, catalogFilter = value), "discoveryStatus" === value.field && (discoveryStatusFilter = value) | |
}), translateService.translateFilterNames(facetTypes), config.settings.data.showFederatedSearch && _createCatalogFilter(catalogFilter, facetTypes), config.settings.data.showDiscoveryStatus && complexFilterService.createDiscoveryStatusFilter(discoveryStatusFilter, facetTypes), facetTypes | |
}, | |
getDisplay: function() { | |
return config.settings.data | |
}, | |
getAllowsTextWrappingOnTableView: function() { | |
return config.settings.data.listView.allowTextWrapping | |
}, | |
getShowThumbnailOnTableView: function() { | |
return config.settings.data.listView.showThumbnail | |
}, | |
getShowFlagOnTableView: function() { | |
return config.settings.data.listView.showFlag | |
}, | |
lookupFilter: function(filter) { | |
return _systemFilterMap[filter] | |
}, | |
lookupFilterStyle: function(filterName) { | |
var filterConfig = this.lookupFilter(filterName); | |
return angular.isDefined(filterConfig) ? "date" === filterConfig.stype ? "DATE" : filterConfig.style : "" | |
}, | |
getSystemFilters: function() { | |
return _systemFilters | |
}, | |
getFilters: function() { | |
return null === config.settings.data.filters && (config.settings.data.filters = []), config.settings.data.filters | |
}, | |
setConfigId: function(configId) { | |
_configId = configId | |
}, | |
getConfigId: function() { | |
return null !== _configId ? _configId : angular.isDefined(config.defaultId) ? config.defaultId : config.configid | |
}, | |
setFilterConfig: function(configId) { | |
return _setFilterConfig(configId) | |
}, | |
getConfigDetails: function(id) { | |
return $http.get(config.root + "api/rest/display/config/" + id + ".json") | |
}, | |
getSolrFields: function() { | |
return "" !== _summarySolrParams ? _summarySolrParams : _solrParams | |
}, | |
getDisplayFields: function(doc) { | |
var fields, order, style, labels, lines, prettyFields = []; | |
return fields = _displayFields, order = _displayFieldsOrder, style = _displayFieldsStyle, labels = _displayFieldsShowLabels, lines = _displayFieldsMaxLines, _.isEmpty(_summaryFields) || (fields = _summaryFields, order = _summaryFieldsOrder, style = _summaryFieldsStyle, labels = _summaryFieldsShowLabels, lines = _summaryFieldsMaxLines), $.each(doc, function(name, value) { | |
fields[name] && (_.isArray(value) && (value = value.join(", ")), prettyFields.push({ | |
name: fields[name], | |
value: value, | |
order: order[name], | |
style: style[name], | |
raw: name, | |
showLabel: labels[name], | |
maxLines: lines[name] | |
})) | |
}), _.sortBy(prettyFields, "order") | |
}, | |
getCardViewFields: function() { | |
return _cardViewFields | |
}, | |
getCardViewNames: function() { | |
return _cardViewNames | |
}, | |
getTableFields: function() { | |
return _tableFields.forEach(function(field) { | |
field.style = _tableFieldsStyle[field.field] | |
}), _tableFields | |
}, | |
getTableFieldNames: function() { | |
return _.map(_tableFields, "field") | |
}, | |
updateColumnWidth: function(field, value) { | |
_tableColumnWidthMap[field] = { | |
changed: !0, | |
value: value | |
} | |
}, | |
getColumnWidth: function(field) { | |
var col = _tableColumnWidthMap[field]; | |
return angular.isDefined(col) ? col.value : col | |
}, | |
resetColumns: function() { | |
$.each(_tableFields, function(index, field) { | |
angular.isDefined(field.width) && (_tableColumnWidthMap[field.field] = { | |
value: parseFloat(field.width) | |
}) | |
}) | |
}, | |
hasChanges: function() { | |
return !_.isEmpty(_tableColumnWidthMap) | |
}, | |
getUpdatedSettings: function() { | |
var colInfo; | |
return $.each(config.settings.data.listView.fields, function(index, column) { | |
colInfo = _tableColumnWidthMap[column.field || column.name], angular.isDefined(colInfo) && (column.width = colInfo.value) | |
}), config.settings.data | |
}, | |
getSort: function() { | |
var sort = {}; | |
return sort.direction = angular.isDefined(config.defaultSortDirection) ? config.defaultSortDirection : "desc", sort.field = angular.isDefined(config.defaultSort) ? config.defaultSort : "score", sort | |
}, | |
showMap: function() { | |
null === config.settings.data.pageElements && (config.settings.data.pageElements = { | |
showMap: !0 | |
}); | |
var showMap = config.settings.data.pageElements.showMap; | |
return angular.isUndefined(showMap) && (showMap = !0), showMap | |
}, | |
getSortable: function() { | |
var sortable = []; | |
return angular.isDefined(config.settings.data.sorting) && $.each(config.settings.data.sorting, function(index, field) { | |
sortable.push({ | |
key: field, | |
value: translateService.getFieldName(field) | |
}) | |
}), sortable | |
}, | |
setShards: function(shards) { | |
_shards = shards | |
}, | |
getShards: function() { | |
return _shards | |
}, | |
getHomePage: function() { | |
return _homepage | |
}, | |
getEditable: function() { | |
return _editable | |
}, | |
getDefaultMapView: function() { | |
return _defaultMapView | |
}, | |
setDefaultMapView: function(mapView) { | |
_defaultMapView = mapView | |
}, | |
parseMapViewString: function(str, delim) { | |
var coords = str.split(_.isEmpty(delim) ? "," : delim); | |
coords = _.map(coords, function(val) { | |
return parseFloat(val) | |
}); | |
var view = { | |
lng: 0, | |
lat: 0, | |
zoom: 3 | |
}; | |
return coords.length > 1 && (view.lng = coords[0], view.lat = coords[1]), coords.length > 2 && (view.zoom = coords[2]), view | |
}, | |
getCatalogs: function() { | |
return _catalogsPromise | |
}, | |
hideDefaultCredentials: function() { | |
return $http.post(config.root + "api/rest/appearance/defaultCredentials?show=false") | |
}, | |
updateConfig: function(data) { | |
return _updateConfig(data) | |
}, | |
getIsGlobalEditable: function() { | |
return _globalEditable | |
}, | |
fetchCartTasks: function() { | |
return $http.get(config.root + "api/rest/appearance").then(function(res) { | |
return res.data.cartTasks | |
}) | |
} | |
} | |
}), angular.module("voyager.config").factory("configLoader", function($http, $q, config, configService, savedSearchQuery, $location, $timeout, translateService, savedSearchService, catalogService, baseMapService) { | |
function _setConfigRoot(hostname) { | |
"127.0.0.1" !== hostname && "localhost" !== hostname && (config.root = config.root.replace("localhost", window.location.hostname)), "https:" === window.location.protocol && config.root.indexOf("https:") === -1 && (config.root = config.root.replace("http:", "https:")) | |
} | |
function _setProxy(hostname) { | |
if ("127.0.0.1" !== hostname && "localhost" !== hostname && config.proxy.indexOf("localhost") > -1) { | |
var port = window.location.port; | |
"" !== port && (port = ":" + port); | |
var root = location.pathname; | |
root = _.str.trim(root, "/"), root = root.split("/"), root.length > 1 && (root.pop(), root = root.join("/")), config.proxy = config.proxy.replace("http://localhost:8888", window.location.protocol + "//" + window.location.hostname + port + "/" + root) | |
} | |
} | |
function _loadDependencies() { | |
var url, promises = []; | |
return $.each(config.require, function(index, value) { | |
url = config.root + value; | |
var promise = $http.get(url, { | |
headers: { | |
"Content-Type": "application/json; charset=utf-8" | |
}, | |
withCredentials: !0 | |
}).then(function(response) { | |
config[index] = response | |
}); | |
promises.push(promise) | |
}), promises.push(catalogService.fetch()), promises.push(baseMapService.getBaselayers()), $q.all(promises) | |
} | |
function _prepare() { | |
if (_prepared) return _prepared = !0, $q.when({}); | |
angular.isDefined(config.rootOverride) && (config.root = config.rootOverride); | |
var hostname = window.location.hostname; | |
return _setConfigRoot(hostname), _setProxy(hostname), _loadDependencies($q, $http) | |
} | |
var _configId, _prepared = !1; | |
return { | |
load: function(configId) { | |
return _prepare().then(function() { | |
translateService.init(); | |
var defaultView = _.getPath(config, "map.config.defaultView"); | |
return angular.isDefined(defaultView) && configService.setDefaultMapView(configService.parseMapViewString(defaultView)), angular.isUndefined(configId) ? savedSearchQuery.fetchDefault().then(function(docs) { | |
var defaultSearch = docs[0]; | |
return defaultSearch || (defaultSearch = {}), configService.setFilterConfig(defaultSearch.config).then(function(config) { | |
$timeout(function() { | |
var params = {}; | |
defaultSearch && (params = savedSearchService.getParams(defaultSearch)), params.disp = config.configId, $location.search(params) | |
}) | |
}) | |
}) : _configId !== configId ? configService.setFilterConfig(configId).then(function() { | |
$location.search().disp !== configId && $timeout(function() { | |
$location.search("disp", configId) | |
}), _configId = configId | |
}) : $q.when() | |
}) | |
}, | |
prepare: function() { | |
return _prepare() | |
} | |
} | |
}), angular.module("voyager.component", []), angular.module("voyager.component").directive("placeholder", function($timeout) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element, attr, ctrl) { | |
if (!$(element).parents("#ecobar_addin").length) { | |
var test = document.createElement("input"); | |
if ("placeholder" in test) return !0; | |
if ($timeout(function() { | |
element.val(element.attr("placeholder")).addClass("placeholder") | |
}), "password" === element.attr("type").toLowerCase() && element.data("oType", "password").attr("type", "text"), element.bind("focus", function() { | |
"password" === element.data("oType") && element.attr("type", "password"), element.val() === element.attr("placeholder") && element.val("").removeClass("placeholder") | |
}).bind("blur", function() { | |
"" === element.val() && (element.val(element.attr("placeholder")).addClass("placeholder"), "password" === element.data("oType") && element.attr("type", "text")) | |
}), void 0 !== attr.ngModel && void 0 !== ctrl) { | |
var value; | |
scope.$watch(attr.ngModel, function(val) { | |
value = val || "" | |
}), ctrl.$formatters.unshift(function(val) { | |
return val ? val : (element.val(element.attr("placeholder")), value = "", attr.placeholder) | |
}) | |
} | |
} | |
} | |
} | |
}), angular.module("voyager.component").directive("vsHighlight", function() { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element) { | |
function _unhighlight() { | |
document.selection ? document.selection.empty() : window.getSelection && window.getSelection().removeAllRanges() | |
} | |
function _highlight(event) { | |
var range, id = $(event.currentTarget).attr("id"), | |
index = parseInt(id.replace("locationPath", "")), | |
highlightList = $("#locationPathWrap a"); | |
if (index >= highlightList.length) | |
for (var i = highlightList.length; i <= index; i++) $("#locationPathWrap").append($("#locationPath" + i)); | |
if (document.body.createTextRange) range = document.body.createTextRange(), range.moveToElementText(document.getElementById("locationPathWrap")), range.select(); | |
else if (window.getSelection) { | |
var selection = window.getSelection(); | |
selection.removeAllRanges(), range = document.createRange(), range.selectNodeContents(document.getElementById("locationPathWrap")), selection.addRange(range) | |
} | |
} | |
var parent = $(element); | |
parent.on("mouseover", "a", function(event) { | |
_unhighlight(), _highlight(event) | |
}).on("mouseout", "a", function(event) { | |
for (var id = $(event.currentTarget).attr("id"), index = parseInt(id.replace("locationPath", "")), highlightList = $("#locationPathWrap a"), i = highlightList.length; i >= index; i--) $("#locationPathNotHighlight").prepend($("#locationPath" + i)); | |
_unhighlight() | |
}) | |
} | |
} | |
}), angular.module("voyager.component").directive("vsPopover", function($timeout, $window) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element) { | |
function _anchorPopover(event, triggerEl, popOverEl) { | |
var winHeight = $(window).height(), | |
winWidth = $(window).width() > $(document).width() ? $(window).width() : $(document).width(), | |
popOverYPos = event.clientY, | |
popOverXPos = triggerEl.offset().left, | |
popOverContent = popOverEl.find(".flyout"), | |
popOverContentHeight = popOverContent.data("height"), | |
popOverContentWidth = popOverContent.data("width"); | |
popOverContentHeight || (popOverContentHeight = popOverContent.addClass("offscreen").height() + 30, popOverContent.data("height", popOverContentHeight), popOverContentWidth = popOverContent.addClass("offscreen").width(), popOverContent.data("width", popOverContentWidth), popOverContent.removeClass("offscreen")), popOverEl.hasClass("top_only") || (winHeight - popOverYPos < popOverContentHeight ? popOverEl.addClass("bottom") : popOverEl.removeClass("bottom")), popOverXPos + popOverContentWidth > winWidth - 10 ? popOverEl.find(".flyout_inner").css("left", winWidth - popOverXPos - popOverContentWidth - 10 + "px") : popOverEl.find(".flyout_inner").css("left", 0) | |
} | |
element.on("click", "a", function(event) { | |
$timeout.cancel(this.timer); | |
var trigger = $(event.currentTarget), | |
el = trigger.parents(".hover_flyout"); | |
trigger.hasClass("flyout_trigger") ? el.hasClass("opened") ? el.removeClass("opened") : (_anchorPopover(event, trigger, el), el.hasClass("max_height") && el.find(".flyout_inner").css("max-height", $window.innerHeight - (el.offset().top - $window.pageYOffset) - 80 + "px"), el.addClass("opened").siblings().removeClass("opened")) : trigger.hasClass("keep_open") ? trigger.hasClass("subcat_trigger") && (trigger.parent().toggleClass("opened"), el.length > 0 && el.find(".flyout_inner").css("max-height", $window.innerHeight - (el.offset().top - $window.pageYOffset) - 80 + "px")) : trigger.parents(".hover_flyout").removeClass("opened") | |
}).on("mouseleave", ".hover_flyout", function(event) { | |
var trigger = $(event.currentTarget); | |
trigger.hasClass("keep_open") || (this.timer = $timeout(function() { | |
$(event.currentTarget).removeClass("opened") | |
}, 500)) | |
}).on("mouseenter", ".hover_flyout", function() { | |
$timeout.cancel(this.timer) | |
}) | |
} | |
} | |
}), angular.module("voyager.component").filter("bytes", function() { | |
"use strict"; | |
return function(bytes, precision) { | |
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return "-"; | |
"undefined" == typeof precision && (precision = 1); | |
var units = ["bytes", "kB", "MB", "GB", "TB", "PB"], | |
number = Math.floor(Math.log(bytes) / Math.log(1024)); | |
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + " " + units[number] | |
} | |
}), angular.module("voyager.component").directive("vsSearchToolToggle", function() { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element, attr) { | |
var _update = !0; | |
scope.$watch(attr.ngModel, function() { | |
_update ? scope.$emit("searchDrawingTypeChanged", scope.selectedDrawingType) : _update = !0 | |
}), scope.$on("updateSearchDrawingType", function(event, args) { | |
_update = !1, scope.selectedDrawingType = args | |
}) | |
} | |
} | |
}), angular.module("voyager.component").directive("vsSelectedFilter", function($timeout, $window) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element, attr) { | |
var windowEl = angular.element($window), | |
windowWidth = windowEl.width(), | |
windowHeight = windowEl.height(), | |
_adjustSelectedFilterContainer = function() { | |
$timeout(function() { | |
var searchResultMapContainer = angular.element("#searchResultMapContainer"), | |
selectedFilterEl = angular.element("#selectedFilters"), | |
selectedFilterContainer = selectedFilterEl.find(".overtop"), | |
filterContainerHeight = 0, | |
listWrapEl = selectedFilterEl.next(".list_wrap"); | |
scope.filters.length && (filterContainerHeight = selectedFilterEl.find(".overtop").outerHeight(), selectedFilterContainer.css("width", selectedFilterEl.parent().outerWidth() + "px")), listWrapEl.css({ | |
"padding-top": filterContainerHeight + "px" | |
}); | |
var banner = angular.element("#top-banner"); | |
if ("table" === attr.view) { | |
var top = 118 + filterContainerHeight; | |
banner.length > 0 && (top += banner.height()), searchResultMapContainer.css("top", top + "px") | |
} else { | |
selectedFilterEl.next(".list_wrap").css({ | |
"margin-top": 0 | |
}); | |
var height = ""; | |
banner.length && (height = $window.innerHeight - banner.height() - 64 - 5 + "px"), searchResultMapContainer.css({ | |
top: "", | |
height: height, | |
visibility: "visible" | |
}) | |
} | |
}, 100) | |
}; | |
element.ready(function() { | |
scope.$watch("filters", function() { | |
_adjustSelectedFilterContainer() | |
}), scope.$watch("$parent.filterVisible", function() { | |
_adjustSelectedFilterContainer() | |
}), scope.$watch("$parent.view", function() { | |
_adjustSelectedFilterContainer() | |
}), windowEl.on("resize", function() { | |
windowWidth === windowEl.width() && windowHeight === windowEl.height() || (windowWidth = windowEl.width(), windowHeight = windowEl.height(), _adjustSelectedFilterContainer()) | |
}), scope.$on("destroy", function() { | |
windowEl.unbind("resize", _adjustSelectedFilterContainer) | |
}) | |
}) | |
} | |
} | |
}), angular.module("voyager.component").directive("vsDetailScroll", function($window, $document, $timeout) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element) { | |
function bannerAdjust() { | |
$banner = angular.element("#top-banner"), $banner.outerHeight() > 0 && $timeout(function() { | |
var paddingTop = detailTopStickyContent.css("padding-top"); | |
paddingTop = parseInt(paddingTop.replace("px", "")), detailTopStickyContent.css("padding-top", $banner.outerHeight() + paddingTop), detailSecondaryColumn.css("padding-top", $banner.outerHeight() + paddingTop), scope.resize() | |
}) | |
} | |
function _scroll() { | |
var $nameHeader = angular.element("h1[name=doc-header]"), | |
$floatingNav = angular.element(".floating-nav"), | |
floatingNavBottom = $floatingNav.offset().top + $floatingNav.height() + 30, | |
nameHeaderBottom = $nameHeader.offset().top + $nameHeader.height(), | |
$floatingHeader = angular.element(".floating-header > h1"); | |
floatingNavBottom < nameHeaderBottom ? $floatingHeader.hide() : $floatingHeader.show(), detailTabContentNav.offset().top < floatingNavBottom && !detailTabContentNavClone && (detailTabContentNavClone = detailTabContentNav.clone().prop("id", detailTabContentNav.prop("id") + "-clone"), detailTabContentNavClone = detailTabContentNavClone.insertBefore(detailTabContentNav), detailTabContentNav.addClass("fixed")); | |
var $divider = angular.element("hr[name=divider]"); | |
$divider.offset().top > detailTabContentNav.offset().top && detailTabContentNavClone && (detailTabContentNavClone.remove(), detailTabContentNavClone = null, detailTabContentNav.removeClass("fixed")) | |
} | |
var windowEl, detailTopStickyContent, detailTabContentNav, detailTabContentNavClone, detailTabContentNavTipPoint, detailTabContentNavHeight, detailSecondaryColumn, itemDetailEl, $banner; | |
scope.initialize = function() { | |
element.ready(function() { | |
$timeout(function() { | |
detailTopStickyContent = angular.element("#detailTopStickyContent"), detailTabContentNav = angular.element("#detailTabContentNav"), detailSecondaryColumn = angular.element("#detailSecondaryColumn"), bannerAdjust(), detailTabContentNavHeight = detailTabContentNav.outerHeight(), itemDetailEl = angular.element("#itemDetailContent"), windowEl.on("scroll", _scroll), windowEl.on("resize", scope.resize), scope.$on("$destroy", function() { | |
scope.destroy() | |
}) | |
}, 350) | |
}) | |
}, windowEl = angular.element($window), scope.$watch("loading", function() { | |
scope.loading === !1 && scope.initialize() | |
}), scope.$watch("showTab", function() { | |
angular.isDefined(scope.showTab) && $document.scrollTop(detailTabContentNavTipPoint) | |
}), scope.resize = function() { | |
$timeout.cancel(scope.resizeTimer), scope.resizeTimer = $timeout(function() {}, 100) | |
}, scope.destroy = function() { | |
windowEl.unbind("scroll", _scroll), windowEl.unbind("resize", scope.resize) | |
} | |
} | |
} | |
}), angular.module("voyager.component").directive("vsTableResults", function($window, $timeout, $document, tableResultsService) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope, element, attr) { | |
scope.windowEl = angular.element($window), scope.windowWidth = scope.windowEl.width(), scope.windowHeight = scope.windowEl.height(); | |
var searchResultMapContainerEl = angular.element("#searchResultMapContainer"), | |
listWrapEl = angular.element(".list_wrap"); | |
scope.getAvailableHeight = function(size, availableHeight) { | |
return "small" === size ? scope.minHeight(availableHeight - 600) : "large" === size ? scope.minHeight(availableHeight - 280) : 0 | |
}, scope.minHeight = function(availableHeight) { | |
return availableHeight < 250 && (availableHeight = 250), availableHeight | |
}, scope.animate = function(el, animateParams, callback) { | |
el.stop().css("visibility", "visible").animate(animateParams, 250, "linear", function() { | |
callback && callback() | |
}) | |
}, scope.hideElement = function(el) { | |
el.css("visibility", "hidden") | |
}, scope.resizeContent = function() { | |
$timeout(function() { | |
if (scope.windowWidth < 768) return searchResultMapContainerEl.css({ | |
visibility: "hidden", | |
height: 0 | |
}), void listWrapEl.css("margin-top", scope.windowWidth < 640 ? "155px" : "110px"); | |
var mapTopPosition = angular.element(".search-map").offset().top, | |
availableHeight = scope.windowHeight - mapTopPosition; | |
"small" === attr.size ? (availableHeight = scope.getAvailableHeight("small", availableHeight), scope.animate(searchResultMapContainerEl, { | |
height: availableHeight | |
})) : "no" === attr.size ? (availableHeight = 0, scope.animate(searchResultMapContainerEl, 0, function() { | |
scope.hideElement(searchResultMapContainerEl) | |
})) : availableHeight = scope.getAvailableHeight("large", availableHeight), scope.animate(searchResultMapContainerEl, { | |
height: availableHeight | |
}), scope.animate(listWrapEl, { | |
marginTop: availableHeight - 20 | |
}), tableResultsService.setFixedWidths() | |
}, 100) | |
}, scope.resize = function() { | |
scope.windowWidth === scope.windowEl.width() && scope.windowHeight === scope.windowEl.height() || (scope.windowWidth = scope.windowEl.width(), scope.windowHeight = scope.windowEl.height(), scope.resizeContent()) | |
}, $document.ready(function() { | |
scope.resizeContent(), scope.windowEl.on("resize", scope.resize), scope.$watch("tableViewMapSize", scope.resizeContent) | |
}), scope.$on("$destroy", function() { | |
scope.windowEl.unbind("resize", scope.resize) | |
}) | |
} | |
} | |
}), angular.module("voyager.component").filter("urlValue", function(sugar) { | |
"use strict"; | |
var urlValueFilter = function(input) { | |
return sugar.isUrl(input) ? '<a href="' + input + '" target="_blank">' + input + "</a>" : input | |
}; | |
return urlValueFilter | |
}), angular.module("voyager.layout", []), angular.module("voyager.layout").directive("vsLayout", function($location) { | |
"use strict"; | |
return { | |
restrict: "A", | |
link: function(scope) { | |
function toggleScreen() { | |
"/search" === $location.path() ? $("body").addClass("full") : $("body").removeClass("full") | |
} | |
if (scope.$on("$stateChangeSuccess", toggleScreen), !_.isUndefined(config.ecobar) && config.ecobar) { | |
var fileref = document.createElement("script"); | |
fileref.setAttribute("type", "text/javascript"), fileref.setAttribute("src", "assets/js/vendor/ecobar/jquery.ecobar.js"), document.getElementsByTagName("head")[0].appendChild(fileref) | |
} | |
} | |
} | |
}), angular.module("voyager.layout").controller("HeaderCtrl", function(config, $rootScope, $scope, $uibModal, $window, $location, $stateParams, $timeout, sugar, cartService, taskService, authService, systemService, savedSearchService, $state, catalogService, configService) { | |
function _init() { | |
_updateUserInfo(), cartService.addObserver(_updateQueueTotal), authService.addObserver(_updateUserInfo), $scope.$on("$stateChangeSuccess", _updateClassicLink), configService.fetchCartTasks().then(function(cartTasks) { | |
vm.cartTasks = cartTasks | |
}) | |
} | |
function _updateClassicLink() { | |
if (authService.hasPermission("manage")) { | |
var path = $location.path(); | |
vm.showClassicLink = path.indexOf("/search") > -1 || path.indexOf("/show") > -1 || path.indexOf("/home") > -1 | |
} else vm.showClassicLink = !1 | |
} | |
function _logout() { | |
authService.doLogout(), $state.go("login") | |
} | |
function _updateQueueTotal() { | |
vm.queueTotal = cartService.getCount() || "0" | |
} | |
function _updateUserInfo() { | |
vm.isAnonymous = authService.isAnonymous(), vm.state = authService.getState(), vm.user = authService.getUser(), vm.canCart = authService.hasPermission("process"), vm.canManage = authService.hasPermission("manage"), vm.canSaveSearch = authService.hasPermission("save_search"), vm.canRestart = authService.hasPermission("shutdown_restart"), vm.showLogout = authService.showLogout(), vm.canViewAnalytics = authService.hasPermission("view_analytics"), _updateClassicLink(), vm.canCart && _updateQueueTotal() | |
} | |
function _showLoginDialog() { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "common/security/login.html", | |
size: "md", | |
controller: "AuthCtrl" | |
}); | |
modalInstance.result.then(function() {}, function() {}), vm.toggleMobileNav() | |
} | |
function _login() { | |
vm.loggedIn ? authService.doLogout() : authService.checkAccess().then(function(hasAccess) { | |
hasAccess || _showLoginDialog() | |
}) | |
} | |
function _showSavedSearch() { | |
$uibModal.open({ | |
template: "<saved-content />", | |
size: "lg", | |
scope: $scope | |
}), vm.toggleMobileNav() | |
} | |
function _getTaskObject(taskName) { | |
return taskService.findAllTasks(!1).then(function(taskList) { | |
var task; | |
for (var property in taskList) | |
if (taskList.hasOwnProperty(property)) { | |
var category = taskList[property]; | |
if (void 0 !== task) { | |
task.isModal = !0, $stateParams.task = task; | |
break | |
} | |
task = _.find(category, { | |
name: taskName | |
}) | |
} | |
}) | |
} | |
var vm = this; | |
vm.queue = {}, vm.login = _login, vm.logout = _logout, vm.showSavedSearch = _showSavedSearch, vm.manageLink = config.root + "manage", vm.myVoyagerLink = config.root + "manage", vm.analyticsLink = config.root + "analytics", vm.showClassicLink = !1, vm.showNav = "/login" !== $location.path(), vm.buildRev = "d8d7fd7", vm.mobileToggleClass = "fa fa-bars", vm.logo = config.root + "pub/header.png", vm.uiText = config.ui.navbar, vm.debug = "true" === $location.search().debug, angular.isDefined($location.search().disp) && (vm.disp = "?disp=" + $location.search().disp), $scope.$on("filterChanged", function() { | |
angular.isDefined($location.search().disp) && (vm.disp = "?disp=" + $location.search().disp) | |
}), $rootScope.$on("$stateChangeStart", function(event, toState) { | |
vm.showNav = "login" !== toState.name | |
}), vm.gotoPage = function(route) { | |
route.indexOf("task?") !== -1 ? $window.location.href = route : $window.location.href = route + "?disp=" + ($location.search().disp || "default"), vm.toggleMobileNav() | |
}, vm.clearQueue = function() { | |
cartService.clear(), $scope.$emit("removeAllCartEvent", {}), vm.toggleMobileNav() | |
}, vm.toggleMobileNav = function() { | |
"" === vm.navClass || void 0 === vm.navClass ? (vm.navClass = "full_width", vm.mobileToggleClass = "icon-x") : (vm.navClass = "", vm.mobileToggleClass = "fa fa-bars") | |
}, vm.openTaskModal = function(taskName) { | |
_getTaskObject(taskName).then(function() { | |
$uibModal.open({ | |
templateUrl: "src/taskrunner/task_modal.html", | |
controller: "TaskCtrl", | |
size: "lg", | |
scope: $scope | |
}) | |
}) | |
}, _init(), vm.goToClassic = function() { | |
var params = $location.search(), | |
baseUrl = config.root + config.explorePath + "/#/"; | |
if ("card" === params.view && delete params.view, angular.isDefined(params.shard)) { | |
var catalog = catalogService.lookup(params.shard); | |
angular.isDefined(catalog) && (params.shard = catalog.id) | |
} | |
params = sugar.retroParams(params); | |
var path = $location.path(); | |
path.indexOf("/show") !== -1 ? baseUrl += path.replace("/show", "") : path.indexOf("/home") !== -1 && (params = ""), $window.open(baseUrl + params, "_blank") | |
}, vm.restart = function() { | |
$uibModal.open({ | |
templateUrl: "common/modal/confirm-modal.html", | |
controller: "ConfirmRestartCtrl", | |
controllerAs: "vm", | |
size: "md" | |
}) | |
}, $scope.$on("$destroy", function() { | |
authService.removeObserver(_updateUserInfo), cartService.removeObserver(_updateQueueTotal) | |
}) | |
}), angular.module("voyager.layout").controller("ConfirmRestartCtrl", function($scope, $uibModalInstance, systemService) { | |
function _setStatus_WAITING() { | |
vm.showMessage = !0, vm.isWaiting = !0, vm.hasCompleted = !1, vm.hasError = !1 | |
} | |
function _setStatus_COMPLETED() { | |
vm.showMessage = !0, vm.isWaiting = !1, vm.hasCompleted = !0, vm.hasError = !1 | |
} | |
function _setStatus_FAILED() { | |
vm.showMessage = !0, vm.isWaiting = !1, vm.hasCompleted = !1, vm.hasError = !0 | |
} | |
function _restart() { | |
systemService.doRestart().then(function() { | |
systemService.checkForLife(_setRestartSuccessful, 2500, 1e4) | |
}, function() { | |
_setRestartFailed() | |
}).catch(function() { | |
_setRestartFailed() | |
}) | |
} | |
function _setRestartSuccessful() { | |
_setStatus_COMPLETED(), vm.statusMessage = "Voyager Restart has Completed Successfully", vm.confirmButtonText = "Restart", vm.cancelLinkText = "Dismiss" | |
} | |
function _setRestartFailed() { | |
_setStatus_FAILED(), vm.statusMessage = "Voyager Restart has Failed", vm.confirmButtonText = "Retry", vm.cancelLinkText = "Dismiss" | |
} | |
var vm = this; | |
vm.modalHeader = "Confirm Restart", vm.modalText = ["This will restart Voyager.", "Are you sure you want to continue?"], vm.confirmButtonText = "Confirm", vm.cancelLinkText = "Cancel", vm.statusMessage = "", vm.showMessage = !1, vm.isWaiting = !1, vm.hasCompleted = !1, vm.hasError = !1, vm.confirm = function() { | |
vm.statusMessage = "Warning: The Server is Restarting", _setStatus_WAITING(), _restart() | |
}, vm.cancel = function() { | |
$uibModalInstance.dismiss(vm.cancelLinkText) | |
} | |
}), angular.module("voyager.home", ["leaflet-directive", "voyager.common.featured", "voyager.common.savedsearch", "voyager.util", "voyager.config", "voyager.search"]), angular.module("voyager.home").service("featureQuery", function(config, $http, cartService, $q, configService, translateService, featuredService, savedSearchQuery, sugar, authService, resultsDecorator, $location) { | |
function _getSavedSearchQueryString(savedSearch) { | |
var config = $location.search().disp; | |
return angular.isUndefined(config) && (config = savedSearch.config), configService.setFilterConfig(config).then(function() { | |
var solrParams = querystring.parse(sugar.trim(savedSearch.query, "&")); | |
delete solrParams.facet, delete solrParams["facet.field"], delete solrParams["facet.mincount"], delete solrParams["extent.bbox"], sugar.decodeParams(solrParams); | |
var queryString = _getQueryString(); | |
return queryString += "&" + querystring.stringify(solrParams) | |
}) | |
} | |
function _getDefaultQueryString() { | |
var savedSearch; | |
return savedSearchQuery.fetchDefault().then(function(docs) { | |
return docs && docs.length > 0 ? (savedSearch = docs[0], _featureQuery = savedSearch, _getSavedSearchQueryString(savedSearch)) : (_featureQuery = void 0, _getQueryString()) | |
}) | |
} | |
function _getConfiguredQuery() { | |
var savedSearch, featuredQuery = ""; | |
return config.homepage && config.homepage.featuredContentQuery && (featuredQuery = config.homepage.featuredContentQuery), "" !== featuredQuery ? savedSearchQuery.fetch(featuredQuery).then(function(docs) { | |
return docs && docs.length > 0 ? (savedSearch = docs[0], _featureQuery = savedSearch, _getSavedSearchQueryString(savedSearch)) : _getDefaultQueryString() | |
}) : _getDefaultQueryString() | |
} | |
function _getQueryString() { | |
var rows = 12, | |
queryString = config.root + "solr/v0/select?"; | |
return queryString += "fl=id,title, name:[name],format,abstract,fullpath:[absolute],thumb:[thumbURL], path_to_thumb, subject,download:[downloadURL],format_type,bytes,modified,shard:[shard],bbox,format_category, component_files, tag_flags", queryString += configService.getSolrFields(), queryString += "&rows=" + rows, queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _execute() { | |
var deferred = $q.defer(), | |
queryPromise = _getConfiguredQuery().then(function(queryString) { | |
return $http.jsonp(queryString) | |
}); | |
return $q.all([queryPromise]).then(function(res) { | |
var searchResult = res[0].data.response.docs; | |
return resultsDecorator.decorate(searchResult, []), deferred.resolve(searchResult) | |
}), deferred.promise | |
} | |
var _featureQuery; | |
return { | |
execute: function() { | |
return _execute() | |
}, | |
getFeatureQuery: function() { | |
return _featureQuery | |
} | |
} | |
}), angular.module("voyager.home").service("collectionsQuery", function(config, $http) { | |
function _getQueryString(count) { | |
var rows = 1e3, | |
label = config.homepage.sidebarLinksLabel, | |
queryString = config.root + "solr/ssearch/select?fq=labels:" + label + "&fl=id,title,query,display:[display],*"; | |
return count && (queryString += ",count:[count]"), queryString += "&rows=" + rows + "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK&block=false", queryString += "&sort=order desc" | |
} | |
function _execute(count) { | |
return $http.jsonp(_getQueryString(count)).then(function(data) { | |
return data.data.response.docs | |
}, function(error) { | |
return error | |
}) | |
} | |
return { | |
execute: function(count) { | |
return _execute(count) | |
} | |
} | |
}), angular.module("voyager.home").service("homeService", function(config, $http, $q, featureQuery, collectionsQuery) { | |
function _collectionsAction(count) { | |
return config.homepage && config.homepage.showSidebarLinks ? collectionsQuery.execute(count) : $q.when(null) | |
} | |
return { | |
fetchCollections: function(count) { | |
return _collectionsAction(count) | |
}, | |
fetchFeatured: function() { | |
return featureQuery.execute() | |
}, | |
getFeaturedQuery: function() { | |
return featureQuery.getFeatureQuery() | |
} | |
} | |
}), angular.module("voyager.home").controller("HomeCtrl", function(config, $scope, $window, $location, homeService, authService, leafletData, filterService, searchService, savedSearchService, sugar, configService, savedSearchQuery, $uibModal, cartService, $log) { | |
function _reload(response) { | |
"login" === response.action && _init() | |
} | |
function _init() { | |
cartService.fetch(!1).then(function(data) { | |
cartService.setQueryCount(data.count) | |
}, function(error) { | |
$log.error(error) | |
}), homeService.fetchCollections(!1).then(function(respond) { | |
$scope.collections = respond, _fetchCounts() | |
}), homeService.fetchFeatured().then(function(respond) { | |
$scope.featured = respond | |
}), $scope.$watch("selectedMapType", function() { | |
"Map" === $scope.selectedMapType ? ($scope.showMap = !0, $scope.displayFormat = "short_format") : ($scope.showMap = !1, $scope.displayFormat = "detail_format") | |
}), $scope.$on("updateSearchType", function(e, type) { | |
$scope.selectedMapType = type | |
}), $scope.$on("updateSearchDrawingType", function(event, args) { | |
$scope.selectedDrawingType = args | |
}) | |
} | |
function _fetchCounts() { | |
_.isEmpty($scope.collections) || homeService.fetchCollections(!0).then(function(docs) { | |
var docMap = sugar.toMap("id", docs); | |
$scope.collections.forEach(function(item) { | |
item.count = docMap[item.id].count | |
}) | |
}) | |
} | |
function _changeSearchTab(type) { | |
$scope.showRecent = "recent" === type | |
} | |
function _submitSearch() { | |
filterService.clear(); | |
var params = {}; | |
if (_.isEmpty($scope.search.query) || ($scope.useExpandedQueries && !_.startsWith($scope.search.query, "{!expand}") ? $scope.search.query = "{!expand}" + $scope.search.query : $scope.useExpandedQueries || ($scope.search.query = $scope.search.query.replace("{!expand}", "")), params.q = $scope.search.query), _.isEmpty($scope.search.q) && ($scope.search.q = null), "Place" === $scope.selectedMapType) { | |
if (!_.isEmpty($scope.search.location)) { | |
params.place = $scope.search.location; | |
var placeId = $location.search()["place.id"]; | |
angular.isDefined(placeId) && (params["place.id"] = placeId), params["place.op"] = $scope.selectedDrawingType.toLowerCase() | |
} | |
} else void 0 !== $scope.search.place && (params.place = $scope.search.place, params["place.op"] = $scope.selectedDrawingType.toLowerCase()); | |
var disp = $location.search().disp; | |
return angular.isDefined(disp) && (params.disp = disp), savedSearchQuery.fetchDefaultParams().then(function(solrParams) { | |
_.isEmpty(params.q) || delete solrParams.q, _.isEmpty(params.place) || (delete solrParams.place, delete solrParams["place.op"], delete solrParams["place.id"]), params = _.extend(params, solrParams), $location.path("search").search(params) | |
}), !1 | |
} | |
function _changeSelectedType(type) { | |
$scope.selectedMapType = type | |
} | |
$scope.search = {}, $scope.mapTypes = ["Place", "Map"], $scope.selectedMapType = "Place", $scope.drawingTypes = ["Within", "Intersects"], $scope.selectedDrawingType = "Within", $scope.displayFormat = "detail_format", $scope.showRecent = !0, $scope.changeTab = _changeSearchTab, $scope.submitSearch = _submitSearch, $scope.changeSelectedType = _changeSelectedType, $scope.showPan = !0, $scope.hideMap = !configService.showMap(), $scope.featuredTitle = "Featured", $scope.collectionsTitle = "Collections", $scope.searchInputClass = "col-md-6 col-xs-6", $scope.placeInputClass = "col-md-6 col-xs-6", $scope.QueryExpansionInputClass = "col-md-2 col-xs-2", $scope.showSpatialInput = !0, $scope.useExpandedQueries = config.queryExpansion && config.queryExpansion.checkedByDefault, $scope.queryExpansionEnabled = config.queryExpansion && config.queryExpansion.enabled, $scope.toggleUseExpandedQueries = function() { | |
$scope.useExpandedQueries = !$scope.useExpandedQueries | |
}, $scope.showAll = function() { | |
var search = homeService.getFeaturedQuery(); | |
angular.isDefined(search) ? savedSearchService.applySavedSearch(search, $scope) : _submitSearch() | |
}, $scope.hideMap && ($scope.containerStyle = "margin-top: -60px; height: 180px"), config.homepage && angular.isDefined(config.homepage.featuredContentTitle) && ($scope.featuredTitle = config.homepage.featuredContentTitle), config.homepage && angular.isDefined(config.homepage.sidebarLinksTitle) && ($scope.collectionsTitle = config.homepage.sidebarLinksTitle), config.homepage && config.homepage.showPlaceQuery === !1 && ($scope.mapTypes = ["Map"], $scope.showMap = !0, $scope.displayFormat = "short_format", $scope.selectedMapType = "Map"), $scope.hideMap && ($scope.mapTypes = ["Place"], $scope.showMap = !1, $scope.selectedMapType = "Place"), config.homepage && config.homepage.showPlaceQuery === !1 && $scope.hideMap && ($scope.searchInputClass = "col-xs-12", $scope.showSpatialInput = !1), $scope.hasPermission = function(permission) { | |
return authService.hasPermission(permission) | |
}, authService.addObserver(_reload), _init(), $scope.saveLocation = function() { | |
$uibModal.open({ | |
template: "<vs-save-location-dialog />", | |
size: "md", | |
scope: $scope | |
}) | |
}, $scope.clearField = function() { | |
$scope.showMap ? delete $scope.search.displayBBox : $scope.search.location = "" | |
}, $scope.$on("$destroy", function() { | |
authService.removeObserver(_reload) | |
}) | |
}), angular.module("voyager.home").directive("vsSearchform", function($timeout) { | |
function _adjustMap(element) { | |
var availableHeight = $(window).height() - $("#header").height(), | |
timeDuration = .5 * availableHeight; | |
$(".content-header-padding").length && (availableHeight -= $(".content-header-padding").height()), $("#searchContainer").stop().animate({ | |
height: availableHeight | |
}, timeDuration, "linear"), element.stop().animate({ | |
top: availableHeight - $("#searchContainer .search_wrap").outerHeight() - 3, | |
height: $(".search_wrap").outerHeight() | |
}, timeDuration, "linear") | |
} | |
return { | |
restrict: "A", | |
link: function(scope, element) { | |
function _resizeMap() { | |
$timeout.cancel(timer), "short_format" === scope.displayFormat && (timer = $timeout(function() { | |
_adjustMap(element) | |
}, 15)) | |
} | |
$timeout(function() { | |
element.find("input[name=query]").trigger("focus").parents("fieldset").addClass("focused").siblings().removeClass("focused") | |
}, 155), element.on("focus", ".input_field", function(event) { | |
$(event.currentTarget).parents("fieldset").addClass("focused").siblings().removeClass("focused") | |
}).on("blur", ".input_field", function(event) { | |
$(event.currentTarget).parents("fieldset").removeClass("focused") | |
}), scope.$watch("displayFormat", function() { | |
"short_format" === scope.displayFormat ? element.find(".location_fieldset").addClass("focused") : element.find(".location_fieldset").removeClass("focused") | |
}); | |
var initialized = !1; | |
scope.$watch("displayFormat", function() { | |
return initialized ? ($(window).scrollTop(0), void("short_format" === scope.displayFormat ? _adjustMap(element) : (element.css("height", "auto").stop().animate({ | |
top: 100, | |
height: $(".search_wrap").outerHeight() + $("#searchHistory").outerHeight() | |
}, 300, "linear", function() { | |
$(this).css("height", "auto") | |
}), $("#searchContainer").stop().animate({ | |
height: 540 | |
}, 300, "linear")))) : void(initialized = !0) | |
}); | |
var timer; | |
$(window).on("resize", _resizeMap), scope.$on("$destroy", function() { | |
$timeout.cancel(timer), $(window).unbind("resize", _resizeMap) | |
}) | |
} | |
} | |
}), angular.module("voyager.search", ["voyager.filters", "voyager.util", "angularSpinner", "ui.router", "ui.slider", "leaflet-directive", "voyager.map", "dialogs.main", "leaflet-directive", "ui.bootstrap", "cart", "voyager.security", "ngGrid", "angulartics", "voyager.map", "voyager.common.featured", "voyager.heatmap", "vs.tools.displayConfig", "toastr"]), | |
function() { | |
"use strict"; | |
function resultsDecorator(configService, sugar, translateService, cartService, authService, $location, config, $filter, catalogService) { | |
function _setFormatProperties(doc) { | |
doc.displayFormat = translateService.getType(doc.format), doc.isService = _mappable[doc.format] | |
} | |
function _loadDisplayFields(doc) { | |
var htmlified = ""; | |
return doc.displayFields = configService.getDisplayFields(doc), $.each(doc.displayFields, function(index, field) { | |
htmlified += _decorateField(field) | |
}), htmlified | |
} | |
function _loadExtraRelationshipFields(doc, fields) { | |
var htmlified = ""; | |
return $.each(fields, function(index, field) { | |
var _f = { | |
raw: field | |
}; | |
doc[_f.raw] && (_f.name = translateService.getFieldName(_f.raw), _f.value = doc[_f.raw], _f.showLabel = !0, _f.maxLines = 3, sugar.isUrl(_f.value) && (_f.isHref = !0), htmlified += _decorateField(_f)) | |
}), htmlified | |
} | |
function _decorateField(field) { | |
var values, formattedValues, trimmed, facetValue, htmlified = "", | |
actualValues = {}, | |
formattedValue = field.value, | |
lowerFieldName = field.name.toLowerCase(); | |
if ("format" === lowerFieldName && (formattedValue = translateService.getType(field.value)), "STRIP_HTML" === field.style && (formattedValue = $("<p>" + field.value + "</p>").text()), "HTML" === field.style && (field.isHtml = !0), ("HREF" === field.style || sugar.isUrl(field.value)) && (field.isHref = !0), "contains_mime" === field.raw ? field.value.indexOf(",") !== -1 ? (formattedValues = [], values = formattedValue.split(","), _.each(values, function(val) { | |
trimmed = _.trim(val), formattedValue = translateService.getType(trimmed), formattedValues.push(formattedValue), actualValues[formattedValue] = trimmed | |
}), formattedValue = formattedValues.join()) : formattedValue = translateService.getType(field.value) : "bytes" === field.raw ? formattedValue = $filter("bytes")(field.value) : sugar.isDate(field.value) && (formattedValue = $filter("date")(Date.parse(field.value), "M/d/yyyy, hh:mma")), field.formattedValue = formattedValue, "description" !== lowerFieldName && "abstract" !== lowerFieldName && isNaN(field.value) && "extent" !== lowerFieldName && !field.isHref) | |
if (formattedValue.indexOf(",") !== -1) { | |
field.showLabel && (htmlified += "<b>" + field.name + "</b>:"), values = formattedValue.split(","); | |
var sep = ""; | |
_.each(values, function(val) { | |
htmlified += sep, facetValue = _.trim(val), angular.isDefined(actualValues[facetValue]) && (facetValue = actualValues[facetValue]), htmlified += '<a href="javascript:;" ng-click="applyFilter(\'' + field.raw + "','" + facetValue + "')\"> " + val + "</a>", sep = "," | |
}), htmlified += "<br>" | |
} else htmlified += (field.showLabel ? "<b>" + field.name + "</b>: " : "") + '<a href="javascript:;" ng-click="applyFilter(\'' + field.raw + "','" + field.value + "')\">" + $("<p>" + field.formattedValue + "</p>").text() + "</a><br>"; | |
else htmlified += field.isHref ? (field.showLabel ? "<b>" + field.name + "</b>: " : "") + '<a href="' + field.value + '">' + $("<p>" + field.formattedValue + "</p>").text() + "</a><br>" : (field.showLabel ? "<b>" + field.name + "</b>: " : "") + $("<p>" + field.formattedValue + "</p>").text() + "<br>"; | |
return field.maxLines && (htmlified = '<div class="max-lines" style="max-height: ' + 20 * field.maxLines + 'px;">' + htmlified + "</div>"), htmlified | |
} | |
function _getDetailsLink(doc, disp) { | |
var link = "show?id=" + encodeURIComponent(encodeURIComponent(doc.id)) + "&disp=" + disp; | |
return angular.isDefined(doc.shard) && "[not a shard request]" !== doc.shard && (link += "&shard=" + doc.shard, doc.isRemote = catalogService.isRemote(doc.shard)), link | |
} | |
function _removeLongTextFieldNames(htmlValue) { | |
return htmlValue = htmlValue.replace("<b>Description</b>:", ""), htmlValue = htmlValue.replace("<b>Abstract</b>:", "") | |
} | |
function _decorateRelationships(docs, fields) { | |
var htmlified; | |
$.each(docs, function(index, doc) { | |
htmlified = _loadExtraRelationshipFields(doc, fields), doc.htmlValue = _removeLongTextFieldNames(htmlified) | |
}) | |
} | |
function _decorate(docs, recordIds, visitor) { | |
var htmlified, disp = $location.search().disp || "default"; | |
return $.each(docs, function(index, doc) { | |
recordIds.push({ | |
id: doc.id, | |
shard: doc.shard | |
}), doc.isopen = !1, doc.getActionText = "Download", angular.isDefined(doc.download) && (doc.hasDownload = !0, 0 === doc.download.indexOf("file:") && (doc.canOpen = !0, doc.getActionText = "Open")), angular.isDefined(doc.layerURL) && (doc.isEsriLayer = !0), angular.isDefined(doc.format) && _setFormatProperties(doc), _.isEmpty(doc.format) || (doc.formatValue = translateService.getTypeAbbr(doc.format), doc.formatLink = "search?fq=format:" + doc.format + "&disp=" + disp), angular.isDefined(doc.bytes) && (doc.size = sugar.bytesToSize(doc.bytes)), htmlified = _loadDisplayFields(doc), doc.htmlValue = _removeLongTextFieldNames(htmlified), doc.detailLink = _getDetailsLink(doc, disp), doc.inCart = cartService.isInCart(doc.id), doc.isRemote !== !0 && (doc.canCart = authService.hasPermission("process")), angular.isDefined(doc.thumb) && doc.thumb.indexOf("vres/mime") !== -1 && (doc.defaultThumb = !0), visitor && visitor(doc) | |
}), recordIds | |
} | |
var _mappable = { | |
"application/x-arcgis-image-server": !0, | |
"application/x-arcgis-feature-server": !0, | |
"application/x-arcgis-feature-server-layer": !0, | |
"application/x-arcgis-map-server": !0, | |
"application/x-arcgis-map-server-layer": !0, | |
"application/vnd.ogc.wms_xml": !0, | |
"application/vnd.ogc.wms_layer_xml": !0 | |
}; | |
return { | |
decorate: _decorate, | |
decorateField: _decorateField, | |
decorateRelationships: _decorateRelationships | |
} | |
} | |
angular.module("voyager.search").factory("resultsDecorator", resultsDecorator) | |
}(), angular.module("voyager.search").factory("searchService", function($http, translateService, filterService, urlUtil, config, queryBuilder, sugar, $q, configService, solrGrunt, cartService, $analytics, authService, resultsDecorator) { | |
"use strict"; | |
function _setParams(params) { | |
if (angular.isUndefined(_sortField) && (_sortField = _defaultSortField), angular.isDefined(params.sort)) | |
if (params.sort.indexOf(" ") !== -1) { | |
var sortInfo = params.sort.split(" "); | |
_sortField = sortInfo[0], _sortDirection = sortInfo[1] | |
} else _sortField = params.sort; | |
angular.isDefined(params.sortdir) && (_sortDirection = params.sortdir), _searchParams = solrGrunt.getSolrParams(params) | |
} | |
function _track(solrPage, data, endTime) { | |
$analytics.eventTrack("search", { | |
category: "time", | |
label: solrPage, | |
value: endTime, | |
user: authService.getUser().id | |
}), $analytics.eventTrack("search", { | |
category: "size", | |
label: solrPage, | |
value: data.response.docs.length, | |
user: authService.getUser().id | |
}), $analytics.eventTrack("search-group", { | |
category: authService.getGroupsJoined(), | |
label: solrPage, | |
user: authService.getUser().id | |
}) | |
} | |
var _searchParams, _page = 1, | |
_idsPage = _page, | |
_itemsPerPage = 48, | |
_solrService = "", | |
_lastResult = {}, | |
_recordIds = [], | |
_sortDirection = angular.isDefined(config.defaultSortDirection) ? config.defaultSortDirection : "desc", | |
_defaultSortField = angular.isDefined(config.defaultSort) ? config.defaultSort : "score", | |
_sortField = "score", | |
_mapView = "0 0 0", | |
getMapView = function(mapView) { | |
var val; | |
return _mapView ? (val = _mapView, _mapView = null, val) : mapView | |
}; | |
return { | |
doSearch2: function(params, append) { | |
_setParams(params); | |
var service = queryBuilder.doBuild2(_searchParams, _page, _itemsPerPage, _sortDirection, _sortField, !0); | |
_solrService = service; | |
var solrPage = service.substring(service.indexOf("solr") - 1); | |
urlUtil.buildSearchUrl2(_searchParams, _page, getMapView(params.vw), params.view, _sortField); | |
var startTime = Date.now(); | |
return $http.get(service).success(function(data) { | |
var endTime = Date.now() - startTime; | |
_lastResult = data, append || (_recordIds = [], _idsPage = _page), resultsDecorator.decorate(data.response.docs, _recordIds), _track(solrPage, data, endTime) | |
}) | |
}, | |
setPage: function(value) { | |
_page = value | |
}, | |
getPage: function() { | |
return _page | |
}, | |
clear: function() { | |
filterService.clear(), _page = 1 | |
}, | |
getLastQuery: function() { | |
return _solrService | |
}, | |
getLastSearch: function() { | |
return urlUtil.getLastUrl() | |
}, | |
setSort: function(direction) { | |
_sortDirection = direction | |
}, | |
setSortField: function(field) { | |
_sortField = field | |
}, | |
getSortField: function() { | |
return _sortField | |
}, | |
getPrettySortField: function() { | |
return translateService.getFieldName(_sortField) | |
}, | |
getSort: function() { | |
return _sortDirection | |
}, | |
setMapView: function(val) { | |
_mapView = val | |
}, | |
setItemsPerPage: function(val) { | |
_itemsPerPage = val | |
}, | |
getItemsPerPage: function() { | |
return _itemsPerPage | |
}, | |
getResults: function() { | |
return _lastResult | |
}, | |
hasRecords: function() { | |
return _recordIds.length > 0 | |
}, | |
getPageIds: function() { | |
return _recordIds | |
}, | |
getPreviousId: function(id) { | |
var index = _.findIndex(_recordIds, { | |
id: id | |
}); | |
return 0 !== index ? _recordIds[index - 1] : null | |
}, | |
getNextId: function(id) { | |
var deferred = $q.defer(), | |
index = _.findIndex(_recordIds, { | |
id: id | |
}), | |
nextId = null; | |
if (index !== _recordIds.length - 1 && (nextId = _recordIds[index + 1], deferred.resolve(nextId)), null === nextId) { | |
_idsPage += 1; | |
var service = queryBuilder.doBuild2(_searchParams, _idsPage, _itemsPerPage, _sortDirection, _sortField); | |
$http.jsonp(service).success(function(data) { | |
$.each(data.response.docs, function(index, doc) { | |
0 === index && (nextId = { | |
id: doc.id, | |
shard: doc.shard | |
}), _recordIds.push({ | |
id: doc.id, | |
shard: doc.shard | |
}) | |
}), deferred.resolve(nextId) | |
}) | |
} | |
return deferred.promise | |
}, | |
getAllIds: function() { | |
var service = queryBuilder.buildAllIds(_searchParams); | |
return $http.jsonp(service) | |
}, | |
getAllBboxes: function() { | |
var service = queryBuilder.buildAllBboxes(_searchParams); | |
return $http.jsonp(service) | |
}, | |
reset: function() { | |
_sortDirection = angular.isDefined(config.defaultSortDirection) ? config.defaultSortDirection : "desc", _sortField = _defaultSortField || "score" | |
}, | |
testEsriGeocodeService: function() { | |
var d = $q.defer(); | |
return $http.jsonp(queryBuilder.buildEsriGeocodeServiceTestQuery()).success(function(rsp) { | |
_.isEmpty(rsp.placefinder.results) ? d.resolve(!1) : d.resolve(!0) | |
}), d.promise | |
} | |
} | |
}), | |
function() { | |
function searchScroll(searchService, $timeout, $window) { | |
function _resetItemsPerPage(view) { | |
"table" === view ? searchService.setItemsPerPage(50) : searchService.setItemsPerPage(48) | |
} | |
var _position = 0, | |
_actualPage = 0; | |
return { | |
setPosition: function(pos) { | |
_position = pos | |
}, | |
getPosition: function() { | |
return _position | |
}, | |
do: function(view) { | |
$timeout(function() { | |
if (_position > 0) { | |
var windowEl = angular.element($window); | |
windowEl.scrollTop(_position), searchService.setPage(_actualPage) | |
} | |
_resetItemsPerPage(view) | |
}) | |
}, | |
getPage: function() { | |
return _actualPage | |
}, | |
prepare: function(view) { | |
if (_position > 0) { | |
_actualPage = searchService.getPage(); | |
var records = 0; | |
records = "table" === view ? 50 * _actualPage : 48 * _actualPage, searchService.setItemsPerPage(records) | |
} | |
}, | |
setItemsPerPage: function() { | |
_resetItemsPerPage() | |
} | |
} | |
} | |
angular.module("voyager.search").factory("searchScroll", searchScroll) | |
}(), angular.module("voyager.search").controller("SearchCtrl", function($scope, cartService, searchService, $location, authService, loading, $window, $document, usSpinnerService, configService, localStorageService, config, $analytics, savedSearchService, recentSearchService, filterService, cartItemsQuery, $timeout, inView, $q, searchScroll, urlUtil, searchViewService, searchModalService, tagService, $log, extractionService) { | |
function _init() { | |
inView.reset(), $scope.uiText = config.ui.list, $scope.bigMap = !1, $scope.mapSize = "small-map", $scope.showGrid = !1, $scope.result = {}, $scope.filterVisible = !1, $scope.placefinderLink = config.root + "manage/settings/placefinder", $scope.eof = !1, $scope.pageFramework = configService.getPageFramework(), $scope.pageFramework.showMap || angular.element("body").addClass("no-map"), loading.show("#working"), _params.pg && _params.pg > 1 && (_page = parseInt(_params.pg)), _.isEmpty(_params.disp) || ($scope.disp = _params.disp), _.isEmpty(_params.mapsize) ? $scope.tableViewMapSize = "large" : $scope.tableViewMapSize = _params.mapsize, $scope.count = 0, $scope.maxSize = 5, $scope.totalItems = 1, _.isEmpty(_params.view) ? ($scope.view = configService.getDefaultView(), $location.search("view", $scope.view)) : "table" === _params.view ? ($scope.view = "table", searchService.setItemsPerPage(50)) : $scope.view = _params.view, _initFilters(), $scope.canCart = !hasRemoteShard() && authService.hasPermission("process"), $scope.canAdmin = authService.hasPermission("manage"), $scope.canViewFeed = authService.hasPermission("show_rss"), $scope.canViewAnalytics = authService.hasPermission("view_analytics") | |
} | |
function _initFilters() { | |
$timeout(function() { | |
_.isEmpty(_params.fq) || filterService.setFilters(_params.fq), $scope.$emit("filterEvent", {}), searchService.clear(), "true" === $location.search().filter && ($scope.filterVisible = !1, $scope.toggleFilter()) | |
}) | |
} | |
function _reloadResults(response) { | |
"login" === response.action && _init() | |
} | |
function _setSortDirection() { | |
searchService.getSort() ? $scope.sortDirection = searchService.getSort() : $scope.sortDirection = "asc" | |
} | |
function _searchSuccess() { | |
$scope.currentPage = _page, _setSortDirection(), _initializing = !1, "table" === $scope.view && ($scope.showGrid = !0), loading.done(), $scope.selectedFilters = filterService.getFilters(), _busy = !1 | |
} | |
function _setSortField() { | |
if (_.isEmpty(_params.sort)) $scope.sortable.length > 0 && ($scope.displaySortField = $scope.sortable[0].value, $scope.sortField = $scope.sortable[0].key); | |
else { | |
0 !== _params.sort.indexOf(" ") ? $scope.sortField = _params.sort.split(" ")[0] : $scope.sortField = _params.sort; | |
for (var field in $scope.sortable) | |
if ($scope.sortable[field].key === $scope.sortField) { | |
$scope.displaySortField = $scope.sortable[field].value; | |
break | |
} | |
} | |
} | |
function _syncCartState(docs) { | |
if (cartService.hasItems()) { | |
var itemIds = searchService.getPageIds(); | |
return itemIds = itemIds.slice(Math.max(itemIds.length - searchService.getItemsPerPage(), 0)), cartService.fetchQueued(itemIds).then(function(items) { | |
_setCartState(items, docs), $scope.$broadcast("syncCard", {}) | |
}) | |
} | |
return $q.when({}) | |
} | |
function _syncCartCount() { | |
cartService.fetch(!1).then(function(data) { | |
cartService.setQueryCount(data.count) | |
}, function(error) { | |
$log.error(error) | |
}) | |
} | |
function _formatErrorReason(error) { | |
var reason = "Search failed."; | |
return error && (error.msg || "").toLowerCase().indexOf("undefined field") > -1 && (reason += " One or more fields do not exist for this saved search."), | |
reason | |
} | |
function _handleSearchError(res) { | |
searchScroll.setPosition(0), $scope.eof = !1, $scope.totalItems = 0, $scope.results = {}, loading.done(), _busy = !1, _searching = !1, _initializing = !1, $scope.searchError = !0, $scope.searchErrorReason = _formatErrorReason((res.data || {}).error), res.data = { | |
response: { | |
docs: [] | |
} | |
}, $scope.$emit("searchComplete", res.data), _setPageClass() | |
} | |
function checkFederations(res) { | |
var shards = res.data["shards.info"]; | |
if (shards) | |
for (var shard in shards) | |
if (!_.isEmpty(shards[shard].error)) { | |
$scope.resultError = !0, $scope.resultStackTrace = shards, _setPageClass(); | |
break | |
} | |
} | |
function checkEsriGeocoder(res) { | |
var placefinder = res.data.response.placefinder; | |
$scope.esriGeocodeServiceError = placefinder && placefinder.errors && placefinder.errors.esri | |
} | |
function _doSearch() { | |
!$scope.pageFramework.showHeaderInfo && $location.path().indexOf("/search") > -1 ? angular.element("body").addClass("no-header") : angular.element("body").removeClass("no-header"), _searching = !0, $scope.sortable = configService.getSortable(), _setSortField(), document.body.scrollTop = document.documentElement.scrollTop = 0, loading.show("#working"), _params = $location.search(), searchScroll.prepare(_params.view), searchService.setPage(1), searchService.doSearch2(_params).then(function(res) { | |
loading.done(), $scope.$emit("searchComplete", res.data), $scope.results = res.data.response.docs, $scope.totalItems = res.data.response.numFound, $scope.eof = $scope.totalItems > 0 && $scope.results.length >= $scope.totalItems, _syncCartState($scope.results), _syncCartCount(), _searchSuccess(), _searching = !1, $scope.searchError = !1, checkFederations(res), checkEsriGeocoder(res), $location.search("block", null), searchScroll.getPosition() > 0 && (_page = searchScroll.getPage(), searchScroll.do(_params.view)), $scope.resetTable = !1, $scope.gridView = configService.getGridView() | |
}, function(res) { | |
_handleSearchError(res) | |
}), 1 === _page && _.isEmpty(_params.id) && _.isEmpty(_params.recent) && recentSearchService.addItem(_params) | |
} | |
function _setCartState(items, docs) { | |
var itemMap = _.indexBy(items, "id"); | |
$.each(docs, function(index, item) { | |
itemMap[item.id] && (item.inCart = !0) | |
}) | |
} | |
function hasRemoteShard() { | |
var shards = $location.search().shards; | |
if (angular.isDefined(shards)) { | |
if (shards.indexOf(",") !== -1) return !0; | |
if ("local" !== shards.toLowerCase()) return !0 | |
} | |
return !1 | |
} | |
function _setPageClass() { | |
var _pageClass = searchViewService.getPageClass($scope.filterVisible, $scope.view, $scope.pageFramework.showMap, $scope.searchError, $scope.resultError); | |
$scope.mapWrapperClass = _pageClass.mapWrapperClass, $scope.mapContentClass = _pageClass.mapContentClass, $scope.headerClass = _pageClass.headerClass, $scope.listViewClass = _pageClass.listViewClass | |
} | |
function _bannerAdjust(view) { | |
if (_bannerAdjusted || "table" !== view) { | |
var mapContent = angular.element(".map_content"); | |
mapContent.css("top", ""), _bannerAdjusted = !1 | |
} else _bannerAdjusted = !0, $timeout(function() { | |
var banner = angular.element("#top-banner"); | |
if (banner.length > 0) { | |
var bannerHeight = banner.height(), | |
mapContent = angular.element(".map_content"); | |
mapContent.offset({ | |
top: mapContent.offset().top + bannerHeight | |
}) | |
} | |
}) | |
} | |
function _setView(view, doSearch) { | |
var currentView = $scope.view; | |
$scope.view = angular.isUndefined(view) ? "card" : view, _page = 1, $location.search("view", $scope.view), _bannerAdjust(view), "table" === view ? searchService.setItemsPerPage(50) : (searchService.setItemsPerPage(48), doSearch === !0 && _doSearch(_page)), urlUtil.updateParam("view", currentView, $scope.view), _setPageClass() | |
} | |
function _loadNextChunk($scope) { | |
_page += 1, _busy = !0, searchScroll.setItemsPerPage(), searchService.setPage(_page), _params = $location.search(), searchService.doSearch2(_params, !0).then(function(res) { | |
var docs = res.data.response.docs; | |
checkFederations(res), _syncCartState(docs).then(function() { | |
docs.length > 0 ? $.merge($scope.results, docs) : $scope.eof = !0, res.data.response.docs = $scope.results, res.data.scrolled = !0, $scope.$emit("searchComplete", res.data), _busy = !1, usSpinnerService.stop("scroll-spinner") | |
}) | |
}, function(res) { | |
_handleSearchError(res) | |
}) | |
} | |
function _windowScroll() { | |
if (inView.clear(), inView.notify(), $location.path().indexOf("/search") !== -1) { | |
var windowEl = angular.element($window); | |
windowEl.scrollTop() + windowEl.height() >= $document.height() - 200 && _busy === !1 && !$scope.eof && (usSpinnerService.spin("scroll-spinner"), _loadNextChunk($scope)), searchScroll.setPosition(windowEl.scrollTop()), inView.check(), inView.notify(), $scope.$apply() | |
} | |
} | |
var _busy = !0, | |
_initializing = !0, | |
_page = 1, | |
_params = $location.search(), | |
_searching = !1, | |
_bannerAdjusted = !1; | |
$scope.showPan = !0, _init(), authService.addObserver(_reloadResults), $scope.$on("doSearch", function(e, options) { | |
(!_initializing || options && options.force) && (searchScroll.setPosition(0), _params = $location.search(), angular.isDefined(_params.sort) && (searchService.setSortField(_params.sort), angular.isDefined(_params.sortdir) ? searchService.setSort(_params.sortdir) : searchService.setSort("desc")), _page = 1, _doSearch()) | |
}), $scope.$on("filterChanged", function(event, args) { | |
if (searchViewService.setViewChanged(!1), $scope.resetTable = !1, !(args && args.refresh === !1 || _initializing)) { | |
searchScroll.setPosition(0), _page = 1, _params = $location.search(); | |
var view = _params.view, | |
switched = $scope.switchView(view); | |
switched && "table" !== view ? $timeout(function() { | |
_doSearch() | |
}) : switched || $timeout(function() { | |
_doSearch() | |
}); | |
var showMap = configService.showMap(); | |
showMap !== $scope.pageFramework.showMap && ($scope.showMap = showMap, _setPageClass()) | |
} | |
}), $scope.$on("updateBBox", function() { | |
$location.search("id", null), $location.search("recent", null), $location.search("pg", null), $scope.$emit("filterEvent", {}) | |
}), $scope.$on("updateSearchSaveStatus", function(events, args) { | |
$location.search("id", args.id) | |
}), $scope.$watch("sortField", function() { | |
_initializing || ($location.search("sort", $scope.sortField), searchService.setSortField($scope.sortField), _page = 1, _searching || (searchScroll.setPosition(0), _doSearch())) | |
}), $scope.hasResults = function() { | |
return $scope.totalItems && $scope.totalItems > 0 | |
}, $scope.hasPermission = function(permission) { | |
return authService.hasPermission(permission) | |
}, $scope.hasOnePermission = function() { | |
return $scope.canEditPermission() || $scope.flagPermission() || $scope.canCart || $scope.canViewFeed | |
}, $scope.canEditPermission = function() { | |
return !hasRemoteShard() && $scope.hasPermission("edit_fields") | |
}, $scope.flagPermission = function() { | |
return !hasRemoteShard() && $scope.hasPermission("flag") | |
}, $scope.exportPermission = function() { | |
return $scope.hasPermission("export") | |
}, $scope.addToCart = function(item) { | |
cartService.addItem(item), $analytics.eventTrack("addToList", { | |
category: "results", | |
label: "table", | |
id: item.id, | |
user: authService.getUser().id | |
}) | |
}, $scope.addAllToCart = function() { | |
$scope.isCartOpen = !1; | |
var query = cartItemsQuery.getQueryCriteria($location.search()); | |
query.count = $scope.totalItems, cartService.replace(query), $scope.$emit("addAllToCartEvent", {}) | |
}, $scope.flagAllResults = function() { | |
var modal = searchModalService.flagModal("src/bulk-update/flag-all.html", "FlagAllCtrl", $scope.totalItems); | |
modal.result.then(function() { | |
_doSearch() | |
}) | |
}, $scope.removeAllFlags = function() { | |
var modal = searchModalService.flagModal("src/bulk-update/remove-flag-all.html", "RemoveAllFlagsCtrl", $scope.totalItems); | |
modal.result.then(function() { | |
_doSearch() | |
}) | |
}, $scope.editAllPresentation = function() { | |
var modal = searchModalService.editAllPresentation($scope.totalItems); | |
modal.result.then(function() { | |
_doSearch() | |
}) | |
}, $scope.exportResultsList = function() { | |
searchModalService.exportResultsList($scope) | |
}, $scope.openFeed = function(type) { | |
var params = filterService.getFilterParams().replace("&", "?"), | |
path = "rss" === type ? "feed/voyager.rss" : "feed/atom.xml"; | |
$window.open(config.root + path + params, "_blank") | |
}, $scope.hideResultErrorMessage = function($event) { | |
$event.preventDefault(), $scope.resultError = !1, _setPageClass() | |
}, $scope.showResultErrorTrace = function() { | |
searchModalService.showResultErrorTrace($scope.resultStackTrace) | |
}, $scope.removeFromCart = function(id) { | |
cartService.remove(id), $analytics.eventTrack("removeFromList", { | |
category: "results", | |
label: "table", | |
id: id, | |
user: authService.getUser().id | |
}) | |
}, $scope.inCart = function(doc) { | |
return cartService.isInCart(doc.id) | |
}, $scope.toggleSave = function() { | |
savedSearchService.showSaveSearchDialog(_params) | |
}, $scope.toggleFilter = function() { | |
$scope.filterVisible = !$scope.filterVisible, $scope.filterVisible ? (urlUtil.updateParam("filter", "true", "true"), $location.search("filter", "true")) : ($location.search("filter", null), urlUtil.removeParam("filter", "true")), _setPageClass() | |
}, $scope.getLastQuery = function() { | |
var solrQuery = searchService.getLastQuery(); | |
return solrQuery | |
}, $scope.getAnalyticsUrl = function() { | |
var q = $location.search().q, | |
fq = $location.search().fq, | |
place = $location.search().place, | |
placeOp = $location.search()["place.op"], | |
url = config.root + "analytics/chart/create"; | |
return angular.isDefined(q) && (url += ";q=" + encodeURIComponent(q)), angular.isDefined(fq) && (_.isArray(fq) || (fq = [fq]), url += ";fq=" + encodeURIComponent(encodeURIComponent(fq.join()))), angular.isDefined(place) && (url += ";place=" + encodeURIComponent(place) + ";place.op=" + placeOp), url | |
}, $scope.hideSearchError = function($event) { | |
$event.preventDefault(), $scope.searchError = !1, _setPageClass() | |
}, $scope.changeSortDirection = function(direction) { | |
if (searchService.getSort() !== direction && !_initializing) { | |
searchScroll.setPosition(0); | |
var currentSort = $location.search().sort; | |
if (angular.isDefined(currentSort) && currentSort.indexOf(" ") !== -1) { | |
var sortInfo = currentSort.split(" "); | |
sortInfo[1] = direction, $location.search("sort", sortInfo.join(" ")) | |
} else $location.search("sortdir", direction); | |
searchService.setSort(direction), _page = 1, _doSearch() | |
} | |
}, $scope.changeSort = function(field) { | |
searchScroll.setPosition(0), $scope.displaySortField = field.value, $scope.sortField = field.key | |
}, $scope.checkDownload = function($event, doc) { | |
doc.hasDownload || $event.preventDefault() | |
}, $scope.switchView = function(view) { | |
return $scope.view !== view && (searchScroll.setPosition(0), _setView(view), !0) | |
}, $scope.addToMap = function(doc) { | |
doc.isopen = !1, doc.isService && ($scope.mapInfo = doc, $scope.$broadcast("addToMap", doc)) | |
}, $scope.showOnMap = function(doc) { | |
if (doc.isopen = !1, doc.isService) { | |
$scope.mapInfo = doc; | |
var webMapSettings = { | |
webMap: config.mapApp, | |
urls: [doc.fullpath], | |
back: $location.absUrl() | |
}; | |
localStorageService.add("web-map-settings", webMapSettings), $window.location.href = "map.html" | |
} | |
}, $scope.toggleMap = function() { | |
var newSetting = searchViewService.changeMapSize($scope.mapSize); | |
$scope.bigMap = newSetting.bigMap, $scope.mapClass = newSetting.mapClass, $scope.mapSize = newSetting.mapSize | |
}, $scope.$on("changeView", function(event, args) { | |
if (!_initializing) { | |
_params = $location.search(), searchService.setSortField(_params.sort), searchService.setSort(_params.sortdir), searchScroll.setPosition(0); | |
var doSearch = args && args.search === !0; | |
_setView(_params.view, doSearch) | |
} | |
}), $scope.$watch("view", function() { | |
_params = $location.search(), _setView(_params.view, _initializing) | |
}), $scope.switchMap = function(size) { | |
$scope.tableViewMapSize !== size && ($scope.tableViewMapSize = size, $location.search("mapsize", size)) | |
}, $scope.$on("mapSizeChanged", function(event, size) { | |
$scope.switchMap(size) | |
}), $scope.clearSearch = function() { | |
filterService.clear(), searchService.reset(), $location.search(""), _page = 1, _doSearch() | |
}, $scope.$on("clearSearch", function() { | |
$scope.resetTable = !0, searchService.reset() | |
}), angular.element($window).bind("scroll", _windowScroll), $scope.$on("$destroy", function() { | |
angular.element($window).unbind("scroll", _windowScroll), inView.reset(), authService.removeObserver(_reloadResults) | |
}), $scope.hoverIn = function(doc) { | |
doc.hoverShow = !0 | |
}, $scope.hoverOut = function(doc) { | |
doc.hoverShow = !1 | |
}, $scope.applyTag = function(tag) { | |
tagService.applyTag(tag, $scope, filterService) | |
}, $scope.updateQueue = function(type) { | |
extractionService.updateQueue(type) | |
} | |
}), angular.module("voyager.search").controller("SearchMapCtrl", function($scope, filterService, $location, localStorageService, searchService, $stateParams, mapUtil, usSpinnerService, $compile, $timeout, dialogs, config, leafletData, $analytics, mapServiceFactory, baseMapService, inView, heatmapService, configService, searchViewService) { | |
"use strict"; | |
function _setCurrentView(local) { | |
var point = $scope.map.getCenter(), | |
vw = point.lng + " " + point.lat + " " + $scope.map.getZoom(); | |
return angular.isUndefined(local) && searchService.setMapView(vw), searchViewService.setUserView({ | |
lat: point.lat, | |
lng: point.lng, | |
zoom: $scope.map.getZoom() | |
}), vw | |
} | |
function _compileLayersControl() { | |
var elem = $(".leaflet-control-layers-overlays"); | |
$compile(elem.contents())($scope); | |
var mapSizeClass = "table" === $scope.view ? "leaflet-bottom-search" : ""; | |
$(".leaflet-control-layers .leaflet-control-layers-toggle").addClass("icon-map_layers").parents(".leaflet-right").removeClass("leaflet-top").addClass("leaflet-bottom " + mapSizeClass) | |
} | |
function _addClickToggleLayersControl(map) { | |
var LayersControl = L.Control.Layers.extend({ | |
_expand: function() {}, | |
_collapse: function() {} | |
}); | |
layersControl = new LayersControl(null, null, { | |
collapsed: !0 | |
}).addTo(map), $timeout(function() { | |
$(".leaflet-control-layers-toggle").click(function(e) { | |
$(".leaflet-control-layers").toggleClass("leaflet-control-layers-expanded"), e.preventDefault() | |
}), $(".leaflet-control-layers-list").click(function(e) { | |
var tagClicked = e.target.tagName; | |
"INPUT" !== tagClicked && "SPAN" !== tagClicked && (e.preventDefault(), $(".leaflet-control-layers").removeClass("leaflet-control-layers-expanded")) | |
}), $(".leaflet-control-layers-list").mouseleave(function(e) { | |
e.preventDefault(), $(".leaflet-control-layers").removeClass("leaflet-control-layers-expanded") | |
}) | |
}) | |
} | |
function _refreshMap(baselayerType) { | |
var center = $scope.map.getCenter(); | |
$scope.map.options.crs = baseMapService.getCRSForLayerType(baselayerType), $scope.map.setView(center), $scope.map._resetView($scope.map.getCenter(), $scope.map.getZoom(), !0) | |
} | |
function _addToLayerControl(layer, map, mapInfo, permanent) { | |
addedLayer = !0, layers[mapInfo.mapKey] = layer, null === layersControl && _addClickToggleLayersControl(map); | |
var template = '<a class="btn btn-xs" style="cursor: pointer;" ng-click="removeLayer(\'' + mapInfo.mapKey + "')\">X</a>"; | |
permanent && (template = ""), _.isEmpty(mapInfo.extra) || (template += " " + mapInfo.extra), layersControl.addOverlay(layer, mapInfo.mapKey + template), $timeout(function() { | |
_compileLayersControl() | |
}) | |
} | |
function _removeSearchBoundary() { | |
layersControl && (delete layers.Place, layersControl.removeLayer(_searchBoundaryLayer)), $scope.map.removeLayer(_searchBoundaryLayer), _searchBoundaryLayer = null, _.isEmpty(layers) && layersControl ? ($scope.map.removeControl(layersControl), layersControl = null, delete $scope.map.currentBounds) : layersControl && _compileLayersControl(), $scope.map.currentBounds = null | |
} | |
function _getDefaultExtent(params) { | |
var extent = $.extend({}, configService.getDefaultMapView()); | |
return params.vw && (extent = configService.parseMapViewString(params.vw, " ")), extent | |
} | |
function _addGeoJson(docs) { | |
_geoGroup && ($scope.map.removeLayer(_geoGroup), _geoGroup = null); | |
var boxes = []; | |
_.each(docs, function(doc) { | |
angular.isDefined(doc.geo) && boxes.push(mapUtil.getGeoJson(doc.geo)) | |
}), boxes.length > 0 && (_geoGroup = L.featureGroup(boxes), _geoGroup.vgCount = boxes.length, $scope.map.addLayer(_geoGroup)) | |
} | |
function _moveToDefaultExtent() { | |
var defaultExtent = _getDefaultExtent($stateParams); | |
$scope.map.setView([defaultExtent.lat, defaultExtent.lng], defaultExtent.zoom) | |
} | |
function _showError(error) { | |
var message = null; | |
angular.isDefined(error.details) && (message = error.details[0]), dialogs.error(error.message, message) | |
} | |
var _points, _searchBoundary, _searchBoundaryLayer, _resultsBoundary, _heatmapLayer, _geoGroup, _geoHighlightLayer, _docs, _baselayers, loaded = !1, | |
layersControl = null, | |
layers = {}, | |
addedLayer = !1, | |
_cancelledDraw = !1; | |
$scope.hasMapError = config.hasMapError, $scope.$on("drawingTypeChanged", function(event, args) { | |
$scope.selectedDrawingType = args | |
}), $scope.selectedDrawingType = "intersects" === $location.search()["place.op"] ? "Intersects" : "Within", leafletData.getMap("search-map").then(function(map) { | |
$scope.map = map, map.on("moveend", function() { | |
_setCurrentView(!0) | |
}) | |
}), $scope.removeLayer = function(layerName) { | |
if (null !== layersControl && angular.isDefined(layers[layerName])) { | |
var layer = layers[layerName]; | |
delete layers[layerName], layersControl.removeLayer(layer), $scope.map.removeLayer(layer), "Place" === layerName && ($location.search("place", null), $location.search("place.op", null), $location.search("place.id", null), $scope.$emit("removeFilterEvent", { | |
isBbox: !0 | |
})), _.isEmpty(layers) ? ($scope.map.removeControl(layersControl), layersControl = null, delete $scope.map.currentBounds) : _compileLayersControl() | |
} | |
}, $scope.$on("clearBbox", function() { | |
_searchBoundaryLayer && _removeSearchBoundary() | |
}), $scope.$on("addToMap", function() { | |
angular.isDefined(layers[$scope.mapInfo.name]) || (usSpinnerService.spin("map-spinner"), $scope.addToMap()) | |
}), inView.setViewObserver(_addGeoJson), $scope.$on("searchResults", function(event, results) { | |
if (results.scrolled !== !0) { | |
if (results.placefinder && results.placefinder.match) { | |
_searchBoundaryLayer && _removeSearchBoundary(); | |
var place = results.placefinder.match; | |
_searchBoundary = place.extent.join(" "), _searchBoundaryLayer = mapUtil.drawGeoJson($scope.map, place.geo, !0, results.placefinder.search.op, !1), _addToLayerControl(_searchBoundaryLayer, $scope.map, { | |
mapKey: "Place" | |
}) | |
} else _searchBoundaryLayer ? (_removeSearchBoundary(), angular.isDefined(results["extent.bbox"]) ? (_resultsBoundary = results["extent.bbox"], mapUtil.fitToBBox($scope.map, _resultsBoundary)) : _moveToDefaultExtent()) : searchViewService.viewChanged() || (angular.isDefined(results["extent.bbox"]) ? (_resultsBoundary = results["extent.bbox"], mapUtil.fitToBBox($scope.map, _resultsBoundary)) : (_searchBoundary = null, _resultsBoundary = null, _moveToDefaultExtent())); | |
_docs = results.response.docs, _addGeoJson(results.response.docs) | |
} | |
}), $scope.addToMap = function() { | |
addedLayer = !0, $scope.map.invalidateSize(!1); | |
var mapService = mapServiceFactory.getMapService($scope.mapInfo); | |
mapService.addToMap($scope.mapInfo, $scope.map).then(function(layer) { | |
$scope.mapInfo.mapKey = $scope.mapInfo.name.replace(/'/g, ""), layer.isValid !== !1 ? (loaded = !1, layer.on("loading", function() { | |
loaded === !1 && usSpinnerService.spin("map-spinner") | |
}), _addToLayerControl(layer, $scope.map, $scope.mapInfo), usSpinnerService.stop("map-spinner"), layer.on("load", function() { | |
loaded = !0, usSpinnerService.stop("map-spinner") | |
}), $analytics.eventTrack("addToMap", { | |
category: "results", | |
label: $scope.mapInfo.format, | |
id: $scope.mapInfo.id | |
})) : (usSpinnerService.stop("map-spinner"), $analytics.eventTrack("addToMap", { | |
category: "error", | |
label: $scope.mapInfo.format, | |
id: $scope.mapInfo.id | |
}), _showError(layer.error)) | |
}, function(error) { | |
usSpinnerService.stop("map-spinner"), $analytics.eventTrack("addToMap", { | |
category: "error", | |
label: $scope.mapInfo.format, | |
id: $scope.mapInfo.id | |
}), _showError(error.error) | |
}) | |
}, $scope.$watch("map", function(old) { | |
angular.isUndefined(old) || ($scope.map.on("overlayadd", function(e) { | |
_compileLayersControl(), e.target.fitBounds(e.layer.bounds) | |
}), $scope.map.on("layeradd", function() { | |
addedLayer && (addedLayer = !1, _compileLayersControl()) | |
}), $scope.map.on("draw:drawstart", function() { | |
_cancelledDraw = !1 | |
}), $scope.map.on("draw:drawstop", function() { | |
$timeout(function() { | |
if (!_cancelledDraw) { | |
_searchBoundaryLayer && _removeSearchBoundary(), $location.search("place", $scope._bbox); | |
var placeType = $scope.selectedDrawingType.toLowerCase(); | |
$location.search("place.op", placeType); | |
var vw = _setCurrentView(); | |
$location.search("vw", vw), $scope.$emit("bboxChangeEvent", { | |
bbox: $scope._bbox, | |
bboxt: placeType, | |
vw: vw, | |
place: $scope._bbox, | |
"place.op": placeType | |
}) | |
} | |
}) | |
}), $scope.map.on("baselayerchange", function(e) { | |
localStorageService.set(baseMapService.BASELAYER_STORAGE_NAME, e.name), _baselayers && _refreshMap(_baselayers[e.name].type) | |
}), $scope.$on("cancelledDraw", function() { | |
_cancelledDraw = !0 | |
}), $scope.map.on("draw:created", function(e) { | |
_cancelledDraw = !1, "point" === $scope.toolType ? (_points = e.layer.getLatLng(), _searchBoundary = e.layer.getLatLng()) : (_points = e.layer.getLatLngs(), _searchBoundary = e.layer.getBounds().toBBoxString()) | |
}), $scope.$on("resultHover", function(evt, data) { | |
if (_geoHighlightLayer || (_geoHighlightLayer = L.geoJson(null, { | |
style: { | |
color: "#e6e600", | |
weight: 6, | |
fill: !0 | |
}, | |
pointToLayer: function(f, ll) { | |
return L.circleMarker(ll, { | |
radius: 6, | |
color: "#e6e600", | |
fillOpacity: .65 | |
}) | |
} | |
}).addTo($scope.map)), data.doc && data.doc.geo) try { | |
_geoHighlightLayer.addData(data.doc.geo) | |
} catch (err) { | |
console.log("WARNING: failed adding geojson layer to search map") | |
} else _geoHighlightLayer.clearLayers() | |
}), $scope.heatmapOpts = { | |
opacity: 100 * config.searchMap.heatmapOpacity | |
}, $scope.$watch("heatmapOpts.opacity", function(newVal) { | |
angular.isDefined(newVal) && angular.isDefined(_heatmapLayer) && (heatmapService.opacity(newVal / 100), _heatmapLayer.render()) | |
}), $scope.heatmapOpacityClick = function(e) { | |
e.preventDefault(), e.stopPropagation() | |
}, heatmapService.fetch("-180,-90,180,90", 1).then(function(hm) { | |
_.isEmpty(hm.counts_ints2D) || (_heatmapLayer = heatmapService.init($scope.map), _addToLayerControl(_heatmapLayer, $scope.map, { | |
mapKey: "Heatmap", | |
extra: '<slider floor="0" ceiling="100" step="1" ng-model="heatmapOpts.opacity" class="heatmap-opacity-control" ng-click="heatmapOpacityClick($event)"></slider>' | |
}, !0)) | |
}), baseMapService.getBaselayers().then(function(baselayers) { | |
if (_baselayers = baselayers, null === layersControl && _addClickToggleLayersControl($scope.map), baselayers) { | |
var defaultBaselayer, defaultBaselayer_Type, selectedBaselayer, selectedBaselayer_Type, selectedBaselayer_Name = localStorageService.get(baseMapService.BASELAYER_STORAGE_NAME); | |
$.each(baselayers, function(index, layerInfo) { | |
var layer; | |
switch (layerInfo.options.crs = baseMapService.getCRSForLayerType(layerInfo.type), layerInfo.type) { | |
case "wms": | |
layer = new L.TileLayer.WMS(layerInfo.url, layerInfo.options); | |
break; | |
default: | |
layerInfo.cached ? layer = new L.TileLayer(layerInfo.url) : (layerInfo.options.url = layerInfo.url, layer = L.esri.dynamicMapLayer(layerInfo.options)) | |
} | |
layersControl.addBaseLayer(layer, layerInfo.name), layerInfo.name === selectedBaselayer_Name && (selectedBaselayer = layer, selectedBaselayer_Type = layerInfo.type), layerInfo.default && (defaultBaselayer = layer, defaultBaselayer_Type = layerInfo.type) | |
}), selectedBaselayer ? (selectedBaselayer.addTo($scope.map), _refreshMap(selectedBaselayer_Type)) : defaultBaselayer && (defaultBaselayer.addTo($scope.map), _refreshMap(defaultBaselayer_Type)) | |
} | |
$timeout(function() { | |
_compileLayersControl() | |
}) | |
})) | |
}), $scope.$on("filterChanged", function() { | |
var params = _.pick($location.search(), function(val, key) { | |
return "q" === key || "fq" === key || 0 === key.indexOf("place") | |
}); | |
heatmapService.filter(params) | |
}), $scope.$on("renderHeatmapStarting", function() { | |
$(".leaflet-control-layers-list").unbind("mouseleave") | |
}), $scope.$on("renderHeatmapEnding", function() { | |
$timeout(function() { | |
$(".leaflet-control-layers-list").mouseleave(function(e) { | |
e.preventDefault(), $(".leaflet-control-layers").removeClass("leaflet-control-layers-expanded") | |
}) | |
}, 300) | |
}) | |
}), angular.module("voyager.search").directive("vsSearchMap", function($compile, config, mapUtil, baseMapService, $timeout, mapControls, configService, $window, $http, sugar, $rootScope, mapCustomControls, searchViewService) { | |
"use strict"; | |
function getMapSizeTemplate() { | |
var mapSizeTemplate = '<div ng-show="view == \'table\'" class="leaflet-control-map-size-toggle leaflet-bar leaflet-control">'; | |
return mapSizeTemplate += '<div class="map-size-drop-down">', mapSizeTemplate += '<div class="icon-arrow flyout-trigger" ng-click="toggleMapSizeDropDown()"><span class="icon-search_map"></span></div>', mapSizeTemplate += '<div class="flyout"><div class="arrow"></div><div class="flyout_inner">', mapSizeTemplate += '<ul><li><a href="javascript:;" ng-click="switchMap(\'large\')">Large map</a></li>', mapSizeTemplate += '<li><a href="javascript:;" ng-click="switchMap(\'small\')">Small map</a></li>', mapSizeTemplate += '<li><a href="javascript:;" ng-click="switchMap(\'no\')">No map</a></li>', mapSizeTemplate += "</ul></div></div></div></div>" | |
} | |
function getExtent(params) { | |
var extent = $.extend({}, configService.getDefaultMapView()); | |
return params.vw && (extent = configService.parseMapViewString(params.vw, " ")), extent | |
} | |
function toggleMapMode($element, $scope, leafletData) { | |
"detail_format" === $scope.displayFormat ? leafletData.getMap("search-map").then(function(map) { | |
map.dragging.disable(), map.doubleClickZoom.disable(), map.scrollWheelZoom.disable(), void 0 !== map.drawRectangle && map.drawRectangle.disable(), $element.addClass("dragging_disabled") | |
}) : (leafletData.getMap("search-map").then(function(map) { | |
map.dragging.enable(), map.doubleClickZoom.enable(), map.scrollWheelZoom.disable(), $element.removeClass("dragging_disabled"), $scope.resizeMap(!0) | |
}), $("#searchByMap").addClass("selected").siblings().removeClass("selected")) | |
} | |
return { | |
compile: function(element, attr) { | |
return element.append('<leaflet class="search-map" style="height: 100%" center="clientDefault" defaults="defaults" controls="controls" layers="layers" id="search-map" watch-markers="no"></leaflet>'), | |
function(scope) { | |
angular.isDefined(attr.zoom) && (scope.clientDefault.zoom = parseInt(attr.zoom)) | |
} | |
}, | |
controller: function($scope, $element, $attrs, leafletData, $stateParams) { | |
function _cancelDraw() { | |
$scope.$emit("cancelledDraw"), $scope._drawing = !1, _cancelledDraw = !0, _drawedShape && _drawedShape.disable() | |
} | |
function currentColor() { | |
return mapUtil.currentColor($scope.selectedDrawingType) | |
} | |
function _createShape(color) { | |
leafletData.getMap("search-map").then(function(map) { | |
map.vsSearchType = $scope.selectedDrawingType; | |
var weight = mapUtil.currentWeight($scope.selectedDrawingType); | |
$timeout(function() { | |
_drawedShape && _drawedShape.disable(), _drawedShape = "polyline" === $scope.toolType ? new L.Draw.Polyline(map, { | |
shapeOptions: _shapeOptions(color, weight), | |
repeatMode: !0, | |
showArea: !1 | |
}) : "polygon" === $scope.toolType ? new L.Draw.Polygon(map, { | |
shapeOptions: _shapeOptions(color, weight), | |
repeatMode: !0, | |
showArea: !0 | |
}) : "point" === $scope.toolType ? new L.Draw.Marker(map, { | |
icon: markerIcon, | |
repeatMode: !1 | |
}) : new L.Draw.Rectangle(map, { | |
shapeOptions: _shapeOptions(color, weight), | |
repeatMode: !0, | |
showArea: !1 | |
}), _drawedShape.enable() | |
}) | |
}) | |
} | |
function _shapeOptions(color, weight) { | |
return { | |
color: color, | |
weight: weight, | |
fillColor: color, | |
strokeOpacity: .8, | |
fillOpacity: 0 | |
} | |
} | |
function _option(type) { | |
var color = currentColor(), | |
weight = mapUtil.currentWeight(type); | |
return { | |
color: color, | |
weight: weight, | |
"stroke-color": color, | |
"stoke-opacity": .8, | |
fill: !1 | |
} | |
} | |
function _convertBuffer(geoJSON) { | |
mapCustomControls.convertBuffer($scope.buffer, geoJSON.geometry).then(function(response) { | |
geoJSON.geometry = response.data, _bufferBoundaryLayer && _map.removeLayer(_bufferBoundaryLayer), _bufferBoundaryLayer = L.geoJson(geoJSON, { | |
style: { | |
color: currentColor(), | |
weight: 0, | |
fill: !0, | |
opacity: .8 | |
} | |
}).addTo(_map), $scope.search.place = mapUtil.convertToWkt(geoJSON.geometry), $scope.search.displayBBox = mapUtil.formatWktForDisplay($scope.search.place), "false" === $attrs.cancel && $rootScope.$broadcast("bboxChangeEvent", { | |
place: $scope.search.place | |
}) | |
}) | |
} | |
function _mapEvents(map) { | |
map.on("draw:drawstop", function() { | |
if (_.isEmpty(map.vsSearchType) || void 0 === _searchBoundary || _remove) return void(_remove = !1); | |
var latLngs, placeType = map.vsSearchType, | |
pointInx = 0; | |
angular.isUndefined($scope.search) && ($scope.search = {}), $scope.search["place.op"] = placeType, angular.isDefined(_searchBoundaryLayer) && _removeLayers(), "rectangle" === $scope.toolType ? (latLngs = _searchBoundary.layer.getLatLngs(), _searchBoundaryLayer = L.rectangle(_searchBoundary.layer.getBounds(), _option(placeType)), pointInx = 2, $scope._bbox = _searchBoundary.layer.getBounds().toBBoxString().replace(/,/g, " "), $scope.search.displayBBox = sugar.formatBBox($scope._bbox)) : "polyline" === $scope.toolType ? (latLngs = _searchBoundary.layer.getLatLngs(), _searchBoundaryLayer = L.polyline(latLngs, _option(placeType)), pointInx = 1) : "polygon" === $scope.toolType ? (latLngs = _searchBoundary.layer.getLatLngs(), _searchBoundaryLayer = L.polygon(latLngs, _option(placeType))) : "point" === $scope.toolType && (latLngs = _searchBoundary.layer.getLatLng(), _searchBoundaryLayer = L.marker(latLngs, { | |
icon: markerIcon | |
})), "rectangle" !== $scope.toolType && ($scope._bbox = mapUtil.convertToWkt(_searchBoundaryLayer), $scope.search.displayBBox = mapUtil.formatWktForDisplay($scope._bbox)), _searchBoundaryLayer.addTo(map), $scope.search.place = $scope._bbox, _addLayerMarkers(map, pointInx), $scope._drawing = !1 | |
}), map.on("layeradd", function() { | |
config.map.config.cached || $(".leaflet-image-layer").css("z-index", "-1") | |
}) | |
} | |
function _addLayerMarkers(map, pointInx) { | |
"point" !== $scope.toolType ? (_addEditBufferMarker(map, _searchBoundaryLayer.getLatLngs()[pointInx]), _addClearBoundaryMarker(map, _searchBoundaryLayer.getLatLngs()[pointInx])) : (_addEditBufferMarker(map, _searchBoundaryLayer.getLatLng()), _addClearBoundaryMarker(map, _searchBoundaryLayer.getLatLng())) | |
} | |
function _addEditBufferMarker(map, pointPosition) { | |
if (angular.isDefined(_editMarker) && null !== _editMarker) _editMarker.setLatLng(pointPosition); | |
else { | |
var anchor = [0, 0]; | |
"rectangle" === $scope.toolType ? anchor = [-2, 2] : "point" === $scope.toolType && (anchor = [0, 25]); | |
var editIcon = L.icon({ | |
iconUrl: "assets/img/icon_edit.png", | |
iconSize: [20, 20], | |
iconAnchor: anchor, | |
popupAnchor: [-95, 160] | |
}); | |
_editMarker = L.marker(pointPosition, { | |
icon: editIcon, | |
zIndexOffset: 5e3 | |
}).addTo(map).bindPopup(addBufferOption()), _editMarker.on("click", function() { | |
_editMarker.openPopup() | |
}) | |
} | |
} | |
function _addClearBoundaryMarker(map, pointPosition) { | |
if (angular.isDefined(_closeMarker) && null !== _closeMarker) _closeMarker.setLatLng(pointPosition); | |
else { | |
if ("false" === $attrs.cancel) return; | |
var anchor = [-20, 0]; | |
"rectangle" === $scope.toolType ? anchor = [-22, 2] : "point" === $scope.toolType && (anchor = [-20, 25]); | |
var closeIcon = L.icon({ | |
iconUrl: "assets/img/icon_x.png", | |
iconSize: [20, 20], | |
iconAnchor: anchor | |
}); | |
_closeMarker = L.marker(pointPosition, { | |
icon: closeIcon, | |
zIndexOffset: 5e3 | |
}).addTo(map), _closeMarker.on("mousedown", function() { | |
_removeLayers(), _removeMarkers(), _remove = !0 | |
}) | |
} | |
} | |
function _removeLayers() { | |
angular.isDefined(_searchBoundaryLayer) && (_map.removeLayer(_searchBoundaryLayer), $scope.search.displayBBox = null, $scope.search.place = null, angular.isDefined(_bufferBoundaryLayer) && _map.removeLayer(_bufferBoundaryLayer)) | |
} | |
function _removeMarkers() { | |
angular.isDefined(_editMarker) && null !== _editMarker && (_map.removeLayer(_editMarker), _editMarker = null), angular.isDefined(_closeMarker && null !== _closeMarker) && (_map.removeLayer(_closeMarker), _closeMarker = null) | |
} | |
function addBufferOption() { | |
return $compile($(mapCustomControls.getBufferTemplate()))($scope)[0] | |
} | |
var _drawedShape, _searchBoundaryLayer, _searchBoundary, _remove, _closeMarker, _editMarker, _bufferBoundaryLayer, _timer, _cancelledDraw = !1, | |
windowEl = angular.element($window); | |
$scope._drawing = !1, $scope.toolType = "rectangle", $scope.clientDefault = getExtent($stateParams, config), $scope.defaults = baseMapService.getDefaultConfig(), "false" !== $attrs.basemapvisible ? $scope.layers = baseMapService.getLayers($attrs.origin) : $scope.layers = {}, $scope.controls = { | |
custom: [] | |
}, mapControls.init($scope, "search-map"); | |
var _unbindResize = function() { | |
windowEl.unbind("resize", $scope.resizeMap) | |
}; | |
$scope.$on("removeFilter", function() { | |
_cancelDraw(), _removeLayers(), _removeMarkers() | |
}), $scope.$on("clearBboxEvent", function() { | |
_removeLayers(), _removeMarkers() | |
}); | |
var zoomIn = $scope.zoomIn; | |
$scope.zoomIn = function(e) { | |
_cancelDraw(), zoomIn(e), _unbindResize() | |
}; | |
var zoomOut = $scope.zoomOut; | |
$scope.zoomOut = function(e) { | |
_cancelDraw(), zoomOut(e), _unbindResize() | |
}; | |
var defaultExtent = $scope.defaultExtent; | |
$scope.defaultExtent = function(e) { | |
_cancelDraw(), defaultExtent(e) | |
}, $scope.toggleDisplayFormat = function(type, event) { | |
event.preventDefault(), event.stopPropagation(), $scope.selectedMapType !== type && ($scope.selectedMapType = type, $(event.currentTarget).addClass("selected").siblings().removeClass("selected"), $scope.$emit("searchTypeChanged", type), "Map" !== type ? _cancelDraw() : $scope.selectDrawingTool(event, $scope.toolType)) | |
}; | |
var searchControls = L.control(); | |
$scope.addDrawingTool = function() { | |
searchControls.setPosition("topleft"), searchControls.onAdd = function() { | |
return $compile($(mapCustomControls.getDrawingToolTemplate()))($scope)[0] | |
} | |
}, $scope.addDrawingTool(); | |
var clickTime; | |
$scope.toggleDrawingOption = function($event) { | |
return clickTime = new Date, $event.preventDefault(), $event.stopPropagation(), $scope.releaseDrawingOption($event), !1 | |
}, $scope.releaseDrawingOption = function($event) { | |
var newTime = new Date; | |
return $event.preventDefault(), $event.stopPropagation(), angular.isDefined(clickTime) || clickTime.getSeconds() !== newTime.getSeconds() ? (_cancelDraw(), $scope.showDrawingTools = !0) : $scope.selectDrawingTool($event, $scope.toolType), !1 | |
}, $scope.toggleDrawingTools = function(show) { | |
_timer && $timeout.cancel(_timer), show === !1 ? _timer = $timeout(function() { | |
$scope.showDrawingTools = !1 | |
}, 1e3) : $scope.showDrawingTools = !0 | |
}, $scope.selectDrawingTool = function($event, toolType) { | |
$event.preventDefault(), $scope.toolType = toolType, $scope.showDrawingTools = !1, $scope._drawing && _cancelDraw(), | |
$scope._drawing = !0, _createShape(currentColor()) | |
}; | |
var _map, markerIcon = L.icon({ | |
iconUrl: "assets/img/marker-icon.png", | |
iconSize: [14, 14] | |
}); | |
leafletData.getMap("search-map").then(function(map) { | |
_map = map, map.on("draw:created", function(e) { | |
_searchBoundary = e | |
}), _mapEvents(map) | |
}), $scope.bufferMeasures = [{ | |
id: "mi", | |
text: "Miles" | |
}, { | |
id: "km", | |
text: "Kilometers" | |
}, { | |
id: "m", | |
text: "Meters" | |
}, { | |
id: "ft", | |
text: "Feet" | |
}, { | |
id: "deg", | |
text: "Lat/Lng Degree" | |
}, { | |
id: "nmi", | |
text: "Nautical Miles" | |
}], $scope.buffer = { | |
measure: "mi" | |
}, addBufferOption(), $scope.addBuffer = function() { | |
isNaN($scope.buffer.distance) || (angular.element(".leaflet-popup-close-button")[0].click(), _convertBuffer(_searchBoundaryLayer.toGeoJSON())) | |
}, $scope.bufferCancel = function($event) { | |
$event.preventDefault(), $scope.buffer = { | |
measure: "mi" | |
}, angular.element(".leaflet-popup-close-button")[0].click() | |
}; | |
var mapTypeToggleControls = L.control(); | |
if (mapTypeToggleControls.setPosition("topleft"), mapTypeToggleControls.onAdd = function() { | |
var template = '<div class="leaflet-map-toggle-section"><div class="leaflet-bar">'; | |
return template += '<a ng-click="toggleDisplayFormat(\'Place\', $event)" id="searchByPlace" class="selected" title="Search by place"><span class="icon-place_search"></span></a>', template += '<a ng-click="toggleDisplayFormat(\'Map\', $event)" id="searchByMap" title="Search by map"><span class="icon-search_map"></span></a>', template += "</div>", template += "</div>", $compile($(template))($scope)[0] | |
}, "false" !== $attrs.resize) { | |
$scope.sizeIcon = "glyphicon-resize-full"; | |
var sizeControl = L.control(); | |
sizeControl.setPosition("bottomright"), sizeControl.onAdd = function() { | |
var template = '<div class="leaflet-bar leaflet-draw-toolbar">'; | |
return template += '<a class="voyager-default-extent" target="_self" ng-click="resize()" title="Resize" style="cursor: pointer"><span class="glyphicon {{sizeIcon}}"></span></a>', template += "</div>", $compile($(template))($scope)[0] | |
}, $scope.controls.custom.push(sizeControl) | |
} | |
$scope.addMapSizeToggleControl = function() { | |
var mapSizeControl = L.control(); | |
mapSizeControl.setPosition("bottomright"), mapSizeControl.onAdd = function() { | |
return $compile(getMapSizeTemplate())($scope)[0] | |
}, $scope.controls.custom.push(mapSizeControl) | |
}, $attrs.control && $scope.addMapSizeToggleControl(), $scope.displayFormat && $scope.controls.custom.push(mapTypeToggleControls), $scope.controls.custom.push(mapControls.getZoomControls($scope)), $scope.controls.custom.push(searchControls), $element.on("click", function(e) { | |
angular.isDefined($scope.displayFormat) && $element.hasClass("dragging_disabled") && ($scope.toggleDisplayFormat("Map", e), $scope.$apply()) | |
}), $element.on("keydown", function(e) { | |
27 === e.keyCode && _cancelDraw() | |
}), $scope.$watch("displayFormat", function() { | |
angular.isDefined($scope.displayFormat) && toggleMapMode($element, $scope, leafletData) | |
}), $scope.$watch("view", function(view) { | |
_cancelDraw(), leafletData.getMap("search-map").then(function(map) { | |
"map" === view ? map.options.minZoom = 2 : map.options.minZoom = 1, $timeout(function() { | |
map.invalidateSize(), angular.isUndefined(map.currentBounds) && angular.isUndefined(searchViewService.getUserView()) && "home" !== $attrs.origin && $scope.resizeMap(), "table" === view ? $(".leaflet-control-layers-toggle").parent().parent().addClass("leaflet-bottom-search") : $(".leaflet-control-layers-toggle").parent().parent().removeClass("leaflet-bottom-search") | |
}, 200) | |
}) | |
}), $scope.switchMap = function(size) { | |
$scope.$emit("mapSizeChanged", size) | |
}, $scope.toggleMapSizeDropDown = function() { | |
var dropDownEl = angular.element(".map-size-drop-down"); | |
dropDownEl.hasClass("opened") ? dropDownEl.removeClass("hover_flyout bottom opened") : dropDownEl.addClass("hover_flyout bottom opened") | |
}, $scope.preventDoubleClick = function(event) { | |
event.stopPropagation() | |
}, $scope.cancelDraw = function(event) { | |
_cancelDraw(), event.preventDefault(), $(".voyager-pan").addClass("selected").parents(".leaflet-control").siblings().find("a").not("#searchByMap").removeClass("selected") | |
}, $scope.resize = function() { | |
var zoom = 10; | |
"glyphicon-resize-full" === $scope.sizeIcon ? ($scope.sizeIcon = "glyphicon-resize-small", zoom = 2) : $scope.sizeIcon = "glyphicon-resize-full", $scope.toggleMap(), leafletData.getMap("search-map").then(function(map) { | |
$timeout(function() { | |
map.invalidateSize(), angular.isDefined(map.currentBounds) || map.setZoom(zoom) | |
}, 200) | |
}) | |
}, $scope.resizeMap = function(isFull) { | |
leafletData.getMap("search-map").then(function(map) { | |
if (map.currentBounds) map.invalidateSize(); | |
else { | |
var ratio; | |
$timeout(function() { | |
ratio = isFull ? (windowEl.innerHeight() - 85) / 256 : $element.outerHeight() / 256; | |
Math.ceil(ratio - Math.floor(ratio)) + 1; | |
isFull && $timeout(function() { | |
map.invalidateSize() | |
}, 200) | |
}, 200) | |
} | |
}) | |
}, $scope.$on("$destory", function() { | |
_unbindResize() | |
}) | |
} | |
} | |
}), angular.module("voyager.search").directive("cleanExpand", [function() { | |
"use strict"; | |
return { | |
require: "ngModel", | |
link: function(scope, element, attr, ngModel) { | |
ngModel.$formatters.push(function(value) { | |
return value ? value.replace("{!expand}", "") : null | |
}) | |
} | |
} | |
}]).controller("SearchInputCtrl", function($scope, config, $location, searchService, $timeout, filterService, mapUtil, sugar, $uibModal) { | |
"use strict"; | |
function _init() { | |
if ("/search" !== $location.path()) return void($scope.showSearch = !1); | |
$scope.showSearch = !0; | |
var initParams = $location.search(); | |
if (_.isEmpty(initParams.q) ? $scope.search.q = "" : ($scope.search.q = initParams.q, $scope.useExpandedQueries = $scope.search.q.indexOf("{!expand}") > -1, $scope.$emit("expandedQueryToggle", $scope.useExpandedQueries)), _.isEmpty(initParams.place)) _.isEmpty(initParams.bbox) ? $scope.search.place = "" : _updatePlaceToBbox(initParams); | |
else { | |
$scope.search.place = initParams.place, mapUtil.isBbox(initParams.place) && ($scope.search.place = sugar.formatBBox(initParams.place)); | |
var placeType = initParams["place.op"]; | |
angular.isDefined(placeType) ? ($scope.search["place.op"] = placeType.toLowerCase(), $scope.selectedDrawingType = _.classify(placeType)) : angular.isDefined($scope.selectedDrawingType) && ($scope.search["place.op"] = $scope.selectedDrawingType.toLowerCase()), $location.search("place.op", $scope.search["place.op"]), _setBBoxNull() | |
} | |
} | |
function _updatePlaceToBbox(params) { | |
null === params.place || _.isEmpty(params.place) || ($scope.search.place = null, $location.search("place", params.place), $location.search("place.id", null), $timeout(function() { | |
mapUtil.isBbox(params.place) ? $scope.search.place = sugar.formatBBox(params.place) : $scope.search.place = params.place, $scope.search["place.op"] = params["place.op"], _.isNull(params.vw) || ($scope.search.vw = params.vw) | |
}, 1)) | |
} | |
function _setBBoxNull() { | |
$scope.search.vw = null | |
} | |
function _submitSearch() { | |
if (placeChanged && ($location.search("place.id", null), $scope.$emit("clearBboxEvent", {})), $scope.search["place.op"] = $scope.selectedDrawingType.toLowerCase(), angular.isDefined($scope.selectedDrawingType) && $location.search("place.op", $scope.selectedDrawingType.toLowerCase()), _.isEmpty($scope.search.place) ? ($scope.search.place = null, $location.search("place.id", null), _setBBoxNull()) : placeChanged && mapUtil.isBbox($scope.search.place) && _setBBoxNull(), _.isEmpty($scope.search.q) && delete $scope.search.q, _.isEmpty($scope.search.q) || ($scope.useExpandedQueries && !_.startsWith($scope.search.q, "{!expand}") ? $scope.search.q = "{!expand}" + $scope.search.q : $scope.useExpandedQueries || ($scope.search.q = $scope.search.q.replace("{!expand}", ""))), !_.isEmpty($scope.search.q) || !_.isEmpty($scope.search.place)) { | |
var params = $location.search(); | |
delete params.id, delete params.recent, delete params.expanded, params.block = "false", _.extend(params, $scope.search), _.extend(params, { | |
fq: filterService.getFilterAsLocationParams() | |
}), $location.search(params), $location.search("expand.exclude", $scope.search["expand.exclude"]), $scope.$emit("filterEvent", {}) | |
} | |
placeChanged = !1 | |
} | |
function _locationChange() { | |
placeChanged = !0 | |
} | |
function _clearPlace(args) { | |
delete args.place, delete args["place.id"], delete args["place.iop"], delete args.block | |
} | |
function _clearField(field, isPlace) { | |
var eventArgs = {}, | |
args = $location.search(); | |
isPlace ? (eventArgs.isBbox = mapUtil.isBbox($scope.search.place), eventArgs.isBbox || (eventArgs.isWkt = mapUtil.isWkt($scope.search.place)), $scope.search.place = "", _clearPlace(args), _locationChange()) : (delete args[field], $scope.search[field] = ""), $location.search(args), $scope.$emit("removeFilterEvent", eventArgs) | |
} | |
function _clearAllField(event, args) { | |
var params = $location.search(); | |
_clearPlace(params), $location.search(params), $scope.search = {}, filterService.clear(), args && args.filter === !0 && $scope.$emit("filterEvent", {}) | |
} | |
var placeChanged = !1; | |
$scope.search = {}, $scope.submitSearch = _submitSearch, $scope.clearField = _clearField, $scope.locationChange = _locationChange, $scope.showLocation = config.homepage && config.homepage.showPlaceQuery !== !1, $scope.drawingTypes = ["Within", "Intersects"], $scope.selectedDrawingType = "intersects" === $location.search()["place.op"] ? "Intersects" : "Within", $scope.defaultSelected = !1, $scope.expandedSelected = !0, $scope.useExpandedQueries = config.queryExpansion && config.queryExpansion.checkedByDefault, $scope.queryExpansionEnabled = config.queryExpansion && config.queryExpansion.enabled, $scope.placeOpChange = function(type) { | |
$scope.selectedDrawingType !== type && ($scope.selectedDrawingType = type), $scope.$emit("selectedDrawingTypeChanged", type) | |
}, $scope.saveLocation = function() { | |
$uibModal.open({ | |
template: "<vs-save-location-dialog />", | |
size: "md", | |
scope: $scope | |
}) | |
}, $scope.toggleUseExpandedQueries = function() { | |
$scope.useExpandedQueries = !$scope.useExpandedQueries, $scope.$emit("expandedQueryToggle", $scope.useExpandedQueries) | |
}, _init(), $scope.$on("$stateChangeSuccess", _init), $scope.$on("updateBBox", function(event, args) { | |
_updatePlaceToBbox(args) | |
}), $scope.$on("clearSearch", _clearAllField), $scope.$on("filterChanged", function(args) { | |
args && args.refresh === !1 || _init() | |
}) | |
}), angular.module("voyager.search").factory("searchViewService", function() { | |
var _view, _mapView, _viewChanged = !1; | |
return { | |
getPageClass: function(filterVisible, view, showMap, searchError, resultError) { | |
var viewChanged = !angular.isUndefined(_view) && _view !== view; | |
viewChanged && (_viewChanged = !0), _view = view; | |
var isMapFilterVisible = filterVisible && "map" === view, | |
page = {}; | |
return page.listViewClass = "", showMap ? "card" === view || "list" === view || "grid" === view ? (page.mapContentClass = "col-lg-8 col-md-8 col-sm-8 col-xs-6 col-lg-push-4 col-md-push-4 col-sm-push-4 col-xs-push-6 no_float", page.headerClass = "col-lg-8 col-md-8 col-sm-12 col-xs-12", page.filterVisible ? page.mapWrapperClass = "map_fixed col-lg-4 col-md-4 col-sm-4 col-xs-6 filter_opened" : page.mapWrapperClass = "map_fixed col-lg-4 col-md-4 col-sm-4 col-xs-6") : "table" === view ? (page.mapContentClass = "col-lg-12 col-md-12 col-sm-12 col-xs-12 no_float", page.headerClass = "col-lg-12 col-md-12 col-sm-12 col-xs-12", filterVisible ? page.mapWrapperClass = "map_fixed tab_center filter_opened" : page.mapWrapperClass = "map_fixed tab_center col-lg-12 col-md-12 col-sm-12 col-xs-12") : isMapFilterVisible ? (page.mapWrapperClass = "map_fixed col-lg-6 col-md-6 col-sm-5 col-xs-5 filter_opened", page.mapContentClass = "map_view_content col-lg-6 col-md-6 col-sm-7 col-xs-7 col-lg-push-6 col-md-push-6 col-sm-push-5 col-xs-push-5", page.headerClass = "col-lg-6 col-md-6 col-sm-12 col-xs-12") : (page.mapWrapperClass = "map_fixed col-lg-8 col-md-8 col-sm-6 col-xs-6", page.mapContentClass = "map_view_content col-lg-4 col-md-4 col-sm-6 col-xs-6 col-lg-push-8 col-md-push-8 col-sm-push-6 col-xs-push-6", page.headerClass = "col-lg-4 col-md-4 col-sm-12 col-xs-12", page.listViewClass = "alt_list_view") : (page.mapWrapperClass = "tab_center", page.mapContentClass = "col-lg-12 col-md-12 no_float", page.headerClass = "col-lg-12 col-md-12 col-sm-12 col-xs-12 no_float"), (searchError || resultError) && (page.mapContentClass += " extra_height"), page | |
}, | |
changeMapSize: function(mapSize) { | |
return "small-map" === mapSize ? { | |
bigMap: !0, | |
mapClass: "col-sm-12", | |
mapSize: "big-map" | |
} : { | |
bigMap: !1, | |
mapClass: "col-md-4 col-sm-5 col-lg-3 col-xs-5", | |
mapSize: "small-map" | |
} | |
}, | |
viewChanged: function() { | |
return _viewChanged | |
}, | |
setViewChanged: function(viewChanged) { | |
_viewChanged = viewChanged, viewChanged === !1 && (_mapView = void 0) | |
}, | |
setUserView: function(mapView) { | |
_mapView = mapView | |
}, | |
getUserView: function() { | |
return _mapView | |
} | |
} | |
}), angular.module("voyager.search").factory("searchModalService", function($uibModal) { | |
"use strict"; | |
return { | |
exportResultsList: function(scope) { | |
$uibModal.open({ | |
template: "<div><vs-export-results /></div>", | |
size: "md", | |
scope: scope | |
}) | |
}, | |
showResultErrorTrace: function(resultStackTrace) { | |
$uibModal.open({ | |
templateUrl: "src/results/result-error.html", | |
controller: "ResultErrorCtrl", | |
size: "lg", | |
resolve: { | |
resultStackTrace: function() { | |
return resultStackTrace | |
} | |
} | |
}) | |
}, | |
flagModal: function(templateUrl, controller, totalItems) { | |
return $uibModal.open({ | |
templateUrl: templateUrl, | |
controller: controller, | |
resolve: { | |
resultData: function() { | |
return { | |
totalItemCount: totalItems | |
} | |
} | |
} | |
}) | |
}, | |
editAllPresentation: function(totalItems) { | |
return $uibModal.open({ | |
templateUrl: "src/bulk-update/edit-all.html", | |
controller: "EditAllCtrl", | |
size: "lg", | |
resolve: { | |
resultTotalCount: function() { | |
return totalItems | |
} | |
} | |
}) | |
} | |
} | |
}), angular.module("voyager.search").factory("extractionService", function(config, $http, $location, converter, vsModalService, toastr) { | |
function _getArgs() { | |
var params = _.clone($location.search()), | |
args = { | |
q: params.q || "*:*", | |
fq: [] | |
}; | |
return angular.isDefined(params.fq) && (_.isArray(params.fq) ? args.fq = params.fq : args.fq.push(params.fq)), angular.isDefined(params.place) && args.fq.push(converter.toPlaceFilter(params)), args | |
} | |
var service = config.root + "api/rest/discovery/extraction"; | |
return { | |
updateQueue: function(type) { | |
var message, args = _getArgs(); | |
return "add" === type ? $http.post(service, {}, { | |
params: args | |
}).then(function() { | |
toastr.success("The current query set has been added to the Extraction Queue for re-indexing.") | |
}) : void("replace" === type ? (message = "The records in this query will replace items in the indexing queue. Are you sure you want to proceed?", vsModalService.showModal("Extraction Queue Replace", message, "Yes", "No").then(function(proceed) { | |
if (proceed) return $http.put(service, {}, { | |
params: args | |
}).then(function() { | |
var statusLink = config.root + "manage/#/discovery/status/"; | |
message = "The Extraction Queue has been updated and these records are being re-indexed. </br></br>", message += 'Please visit the <a class="status-link" target="_blank" href="' + statusLink + '">Status</a> page in the Management controls to monitor indexing.', toastr.success(message, { | |
timeOut: 6e3, | |
extendedTimeOut: 1e3 | |
}) | |
}) | |
})) : "remove" === type && (message = "The records in this query will be removed from the Extraction Queue for reindexing. Are you sure you want to proceed?", vsModalService.showModal("Extraction Queue Replace", message, "Yes", "No").then(function(proceed) { | |
if (proceed) return $http.delete(service, { | |
params: args | |
}).then(function() { | |
message = "The records were removed from the Extraction Queue.", toastr.success(message) | |
}) | |
}))) | |
} | |
} | |
}), angular.module("voyager.search").factory("exportService", function($http, config, sugar, filterService, configService, solrGrunt) { | |
"use strict"; | |
function _setParams(params) { | |
if (angular.isUndefined(_sortField) && (_sortField = _defaultSortField), angular.isDefined(params.sort)) | |
if (params.sort.indexOf(" ") !== -1) { | |
var sortInfo = params.sort.split(" "); | |
_sortField = sortInfo[0], _sortDirection = sortInfo[1] | |
} else _sortField = params.sort; | |
angular.isDefined(params.sortdir) && (_sortDirection = params.sortdir), _searchParams = solrGrunt.getSolrParams(params) | |
} | |
function buildQueryForCSV(solrParams, itemsPerPage, sortDirection, sortField) { | |
delete solrParams.fq; | |
var queryString = config.root + selectPath; | |
queryString += "?" + sugar.toQueryString(solrParams), queryString += "&start=0", queryString += "&fl=id"; | |
var tableFieldNames = configService.getTableFieldNames(); | |
return tableFieldNames.length && (queryString += "," + tableFieldNames.join(","), queryString += ",absolute_path:[absolute]"), queryString += "&rows=" + itemsPerPage, queryString += "&extent.bbox=true&block=false", queryString += filterService.getFilterParams(), angular.isDefined(configService.getConfigId()) && angular.isUndefined(solrParams["voyager.config.id"]) && (queryString += "&voyager.config.id=" + configService.getConfigId()), angular.isDefined(sortField) && (angular.isUndefined(sortDirection) && (sortDirection = angular.isDefined(config.defaultSortDirection) ? config.defaultSortDirection : "desc"), queryString += "&sort=" + sortField + " " + sortDirection), queryString += "&rand=" + Math.random(), queryString += "&wt=csv" | |
} | |
var _searchParams, _sortDirection, selectPath = "solr/v0/select", | |
_defaultSortField = angular.isDefined(config.defaultSort) ? config.defaultSort : "score", | |
_sortField = "score"; | |
return { | |
getCSV: function(params, rowCount) { | |
_setParams(params); | |
var service = buildQueryForCSV(_searchParams, rowCount, _sortDirection, _sortField); | |
return $http.get(service).then(function(response) { | |
return response | |
}, function(exception) { | |
return exception | |
}) | |
} | |
} | |
}), angular.module("voyager.search").directive("vsExportResults", function(usSpinnerService, searchService, $location, exportService) { | |
return { | |
restrict: "E", | |
replace: !0, | |
templateUrl: "src/export-results/export-results.html", | |
link: function(scope) { | |
scope.error = !1, scope.hasError = function() { | |
return scope.error !== !1 | |
}, scope.save = function() { | |
if (_.isEmpty(scope.CSVFileName)) scope.success = !1, scope.error = "Please enter a file name"; | |
else { | |
scope.error = !1, usSpinnerService.spin("task-spinner"); | |
var _params = $location.search(); | |
delete _params.recent, scope.getCSVFile(_params, scope.totalItems) | |
} | |
}, scope.cancel = function() { | |
scope.$dismiss() | |
}, scope.getFileName = function() { | |
var fileNameParts = scope.CSVFileName.split("."), | |
fileExt = ""; | |
return "csv" !== fileNameParts.pop().toLowerCase() && (fileExt = ".csv"), scope.CSVFileName + fileExt | |
}, scope.createAnchorTag = function(data, filename) { | |
var anchor = angular.element("<a/>"); | |
return navigator.msSaveBlob ? anchor[0].addEventListener("click", function() { | |
var blob = new Blob([data], { | |
type: "text/csv;charset=utf-8;" | |
}); | |
navigator.msSaveBlob(blob, filename) | |
}, !1) : anchor.attr({ | |
href: "data:attachment/csv;charset=utf-8," + encodeURI(data), | |
target: "_blank", | |
download: filename | |
}), anchor | |
}, scope.successHandler = function(response, filename) { | |
if (usSpinnerService.stop("task-spinner"), 200 === response.status && angular.isUndefined(response.error)) { | |
scope.success = !0; | |
var anchor = scope.createAnchorTag(response.data, filename)[0]; | |
"function" == typeof anchor.click && anchor.click(), scope.cancel() | |
} else scope.error = response.error || "Please try again later" | |
}, scope.errorHandler = function(response) { | |
usSpinnerService.stop("task-spinner"), scope.error = response.error || "Please try again later" | |
}, scope.getCSVFile = function(params, rowCount) { | |
exportService.getCSV(params, rowCount).then(function(response) { | |
scope.successHandler(response, scope.getFileName()) | |
}, function(response) { | |
scope.errorHandler(response) | |
}) | |
} | |
} | |
} | |
}), angular.module("voyager.search").factory("suggestQuery", function($http, config) { | |
return { | |
execute: function(name) { | |
var query = config.root + "solr/v0/select?place=" + name + "&place.suggest=true&block=false&rows=0&wt=json&json.wrf=JSON_CALLBACK&rand=" + Math.random(); | |
return $http.jsonp(query).then(function(res) { | |
return res.data.placefinder.results | |
}) | |
} | |
} | |
}), angular.module("voyager.search").directive("vsSuggest", function($timeout, suggestQuery, $compile, $q, $location, urlUtil, mapUtil) { | |
function _check(value) { | |
return value.length > 3 ? suggestQuery.execute(value) : $q.when([]) | |
} | |
function _link(scope, element, attrs) { | |
function _getSuggestions() { | |
scope.hasRecommendations = !1, _check(element.val()).then(function(suggestions) { | |
suggestions = _.filter(suggestions, function(s) { | |
return null !== s.name | |
}), _.find(suggestions, { | |
name: element.val() | |
}) ? scope.hasSuggestions = !1 : (scope.suggestions = suggestions, scope.hasSuggestions = suggestions.length > 0) | |
}) | |
} | |
function _handleDownArrow(index) { | |
index < scope.suggestions.length - 1 && (index > -1 && (scope.suggestions[index].highlighted = !1), scope.suggestions[index + 1].highlighted = !0) | |
} | |
function _handleUpArrow(index) { | |
index > 0 && (scope.suggestions[index].highlighted = !1, scope.suggestions[index - 1].highlighted = !0) | |
} | |
var t = '<div ng-show="hasSuggestions" vs-suggest-list class="suggest-container hdpi" style="width:100%"></div>'; | |
element.after($compile(t)(scope)); | |
var _typeTimer, handleKeydown = function(e) { | |
if (scope.selectedPlace = !1, _placeSearch = !1, scope.hasRecommendations = !1, $timeout.cancel(_typeTimer), 13 === e.which) { | |
if (scope.suggestions) { | |
var selectedIndex = _.findIndex(scope.suggestions, function(item) { | |
return item.highlighted | |
}); | |
selectedIndex > -1 && scope.select(scope.suggestions[selectedIndex]) | |
} | |
return scope.suggestions = [], scope.hasSuggestions = !1, scope.selectedPlace = !0, void(_placeSearch = !0) | |
} | |
if (40 === e.which || 38 === e.which) { | |
var arrowFn = 40 === e.which ? _handleDownArrow : _handleUpArrow; | |
if (scope.suggestions && scope.suggestions.length > 0) { | |
var index = _.findIndex(scope.suggestions, function(item) { | |
return item.highlighted | |
}); | |
return arrowFn(index), void scope.$digest() | |
} | |
} | |
_typeTimer = $timeout(function() { | |
_getSuggestions() | |
}, 300) | |
}; | |
element.on("keydown", handleKeydown); | |
var handleBlur = function() { | |
$timeout(function() { | |
scope.suggestions = [], scope.hasSuggestions = !1, _focused = !1 | |
}) | |
}; | |
element.on("blur", handleBlur); | |
var handleFocus = function() { | |
var val = element.val(); | |
_focused || scope.selectedPlace || mapUtil.isBbox(val) || _getSuggestions() | |
}; | |
element.on("focus", handleFocus), scope.select = function(item) { | |
scope.selectedPlace = !0, _placeSearch = !0, scope.hasRecommendations = !1, scope.hasSuggestions = !1, element.val(item.name), scope.search && angular.isDefined(scope.search.location) && (scope.search.location = item.name), $location.search("place", item.name), $location.search("place.id", item.id), "off" !== attrs.autosearch && scope.$emit("filterEvent", {}) | |
}, scope.$on("$destroy", function() { | |
element.off("focus", handleFocus), element.off("blur", handleBlur), element.off("keydown", handleKeydown) | |
}) | |
} | |
var _focused = !1, | |
_placeSearch = !1; | |
return { | |
compile: function() { | |
return _link | |
}, | |
controller: function($scope, $document) { | |
var docClickHandler = function() { | |
$scope.selectedPlace = !0, $scope.hasRecommendations = !1, $scope.hasSuggestions = !1, $scope.$apply(), $document.off("click", docClickHandler) | |
}; | |
$scope.$on("searchResults", function(event, data) { | |
var isChosen = $location.search()["place.id"]; | |
if (!angular.isDefined(isChosen)) { | |
var place = $location.search().place; | |
if (_placeSearch = angular.isDefined(place) && "" !== place, _placeSearch && data.placefinder && !mapUtil.isBbox(place)) { | |
if (!_.find(data.placefinder.results, { | |
name: place | |
})) { | |
$scope.hasRecommendations = !0, $scope.suggestions = data.placefinder.results, $scope.hasSuggestions = $scope.suggestions && $scope.suggestions.length > 0; | |
var matchName = data.placefinder.match.name; | |
matchName === place && ($scope.hasSuggestions = !1), _.isEmpty(matchName) && (matchName = data.placefinder.search.text), $scope.location = matchName, $location.search("place", $scope.location), urlUtil.updateParam("place", place, $scope.location), $location.search("place.id", data.placefinder.match.id), urlUtil.addParam("place.id", data.placefinder.match.id), $scope.$emit("filterEvent", { | |
refresh: !1 | |
}) | |
} | |
} else $scope.hasRecommendations = !1; | |
$scope.hasRecommendations ? $document.on("click", docClickHandler) : $document.off("click", docClickHandler) | |
} | |
}), $scope.$on("$destroy", function() { | |
$document.off("click", docClickHandler) | |
}) | |
} | |
} | |
}), angular.module("voyager.search").directive("vsSuggestList", function() { | |
return { | |
templateUrl: "src/suggest/suggest.html" | |
} | |
}), angular.module("voyager.results", ["ngTable", "voyager.tagging"]), | |
function() { | |
"use strict"; | |
function actionManager($window, $analytics, $uibModal, authService, sugar, config, $location) { | |
function _isVisible(action, scope) { | |
var visible = action.visible; | |
return visible === !0 || visible === !1 ? visible : visible.indexOf("doc.") > -1 ? scope.$eval(visible) : scope.doc[action.visible] | |
} | |
function _toggleDisplay(action, scope) { | |
scope.doc[action.toggle] === !0 ? (action.display = action.off, action.icon = action.offIcon, scope.isTable && (action.display = action.offList), action.buttonType = "btn-default") : (action.display = action.text, action.icon = action.onIcon, action.buttonType = "btn-primary") | |
} | |
function _setAction(action, scope) { | |
action.visible = _isVisible(action, scope), "add" === action.action ? (action.do = function() { | |
scope.doc.isopen = !1, scope.toggleCart(scope.doc), _toggleDisplay(action, scope) | |
}, _toggleDisplay(action, scope)) : "preview" === action.action ? action.do = function() { | |
$analytics.eventTrack("mapped", { | |
category: "results", | |
label: scope.doc.format, | |
id: scope.doc.id, | |
user: authService.getUser().id | |
}), scope.doc.isopen = !1, scope.addToMap(scope.doc), $window.scrollTo(0, 0) | |
} : "download" === action.action ? action.do = function() { | |
scope.doc.isopen = !1, $analytics.eventTrack("download", { | |
category: "results", | |
label: scope.doc.format, | |
id: scope.doc.id, | |
user: authService.getUser().id | |
}), sugar.canOpen(scope.doc) ? $window.open(scope.doc.download) : authService.getUserInfo().then(function(user) { | |
$window.location.href = scope.doc.download + sugar.paramDelimiter(scope.doc.download) + "_vgp=" + user.exchangeToken | |
}) | |
} : "open" === action.action ? action.do = function() { | |
scope.doc.isopen = !1, $analytics.eventTrack("openWith", { | |
category: "results", | |
label: action.url, | |
id: scope.doc.id, | |
user: authService.getUser().id | |
}); | |
var param = ""; | |
action.url.indexOf("?") === -1 && (param = "?url="), action.param && (param = "?" + action.param + "="), $window.open(action.url + param + encodeURIComponent(scope.doc.fullpath)) | |
} : "openArcMap" === action.action ? action.do = function() { | |
scope.doc.isopen = !1, $analytics.eventTrack("openArcMap", { | |
category: "results", | |
label: scope.doc.id, | |
id: scope.doc.id, | |
user: authService.getUser().id | |
}), $window.location.href = scope.doc.layerURL | |
} : "tag" === action.action && (action.do = function() { | |
scope.doc.isopen = !1, $analytics.eventTrack("tag", { | |
category: "results", | |
label: action.url, | |
id: scope.doc.id, | |
user: authService.getUser().id | |
}), $uibModal.open({ | |
templateUrl: "common/tagging/tagging.html", | |
size: "md", | |
controller: "TagDialog", | |
resolve: { | |
doc: function() { | |
return scope.doc | |
} | |
} | |
}) | |
}) | |
} | |
function _initActions(scope, view) { | |
var actionMap = {}, | |
defaultAction = null, | |
displayActions = [], | |
actions = sugar.copy(config.docActions); | |
return $.each(actions, function(index, action) { | |
action.buttonType = "btn-primary", _setAction(action, scope), actionMap[action.action] = action, "preview" === action.action && "/home" === $location.path() && (action.visible = !1), action.display = angular.isDefined(action.display) ? action.display : action.text, action.enabled = !!angular.isUndefined(action.enabled) || action.enabled, action.visible = !!action.enabled && action.visible, action.visible && (null === defaultAction && "table" !== view ? defaultAction = action : displayActions.push(action), "download" === action.action && angular.isDefined(scope.doc.download) && sugar.canOpen(scope.doc) && (action.text = action.alt)) | |
}), displayActions.length > 0 && angular.isDefined(displayActions[0].sort) && (displayActions = _.sortBy(displayActions, "sort")), { | |
display: displayActions, | |
defaultAction: defaultAction, | |
types: actionMap | |
} | |
} | |
return { | |
setAction: _setAction, | |
toggleDisplay: _toggleDisplay, | |
initActions: _initActions | |
} | |
} | |
angular.module("voyager.results").factory("actionManager", actionManager) | |
}(), angular.module("voyager.results").directive("vgBindHtml", function($compile) { | |
return function(scope, element, attrs) { | |
scope.$watch(function(scope) { | |
return scope.$eval(attrs.vgBindHtml) | |
}, function(value) { | |
element.html(value), $compile(element.contents())(scope) | |
}) | |
} | |
}).directive("vsCard", function(authService, cartService, config, $window, $analytics, actionManager, sugar, inView, $document, $location, tagService) { | |
return { | |
templateUrl: "src/results/card.html", | |
link: function($scope, $element) { | |
function _isInView() { | |
var clientHeight, imageRect, visible = $element.is(":visible"), | |
isIn = !1; | |
visible && (clientHeight = $document[0].documentElement.clientHeight, imageRect = $element[0].getBoundingClientRect(), isIn = imageRect.top >= 0 && imageRect.bottom <= clientHeight || imageRect.bottom >= 0 && imageRect.bottom <= clientHeight || imageRect.top >= 0 && imageRect.top <= clientHeight), isIn ? inView.add($scope.doc) : inView.remove($scope.doc) | |
} | |
angular.isDefined($scope.doc.geo) && inView.addCheckObserver(_isInView) | |
}, | |
controller: function($scope, filterService, translateService, $timeout, $location, configService, $filter) { | |
$scope.imagePrefix = config.root + "meta/", $scope.link = sugar.copy(config.docLink), $scope.cardView = configService.getCardView(), actionManager.setAction($scope.link, $scope), $scope.fields = configService.getCardViewFields(), $scope.names = configService.getCardViewNames(), "preview" === $scope.link.action && "/home" === $location.path() && ($scope.link.visible = !1), $scope.toggleCart = function(doc) { | |
doc.inCart ? (cartService.remove(doc.id), $scope.cartAction = "Add", $scope.btnType = "btn-primary", doc.inCart = !1, $analytics.eventTrack("removeFromList", { | |
category: "results", | |
label: "card", | |
id: doc.id, | |
user: authService.getUser().id | |
})) : (cartService.addItem(doc), $scope.cartAction = "Remove", $scope.btnType = "btn-default", doc.inCart = !0, $analytics.eventTrack("addToList", { | |
category: "results", | |
label: "card", | |
id: doc.id, | |
user: authService.getUser().id | |
})) | |
}, $scope.canCart = function() { | |
return authService.hasPermission("process") | |
}, $scope.applyTag = function(tag) { | |
tagService.applyTag(tag, $scope, filterService) | |
}, $scope.hover = function(active) { | |
$scope.$emit("resultHoverEvent", { | |
doc: active ? $scope.doc : null | |
}) | |
}; | |
var actions = actionManager.initActions($scope); | |
$scope.actions = actions.display, $scope.default = actions.defaultAction, $scope.$on("addAllToCart", function() { | |
$scope.cartAction = "Remove", $scope.btnType = "btn-default", $scope.doc.inCart = !0, actionManager.toggleDisplay(actions.types.add, $scope) | |
}), $scope.$on("removeAllCart", function() { | |
$scope.cartAction = "Add", $scope.btnType = "btn-primary", $scope.doc.inCart = !1, actionManager.toggleDisplay(actions.types.add, $scope) | |
}), $scope.$on("syncCard", function() { | |
$scope.doc.inCart ? ($scope.cartAction = "Remove", $scope.btnType = "btn-default") : ($scope.cartAction = "Add", $scope.btnType = "btn-primary"), actionManager.toggleDisplay(actions.types.add, $scope) | |
}), $scope.applyFilter = function(filter, value) { | |
if ("/search" === $location.path()) { | |
var facet = { | |
field: value, | |
filter: filter, | |
humanized: translateService.getFieldName(filter) + ":" + value, | |
name: value, | |
pretty: translateService.getType(value) | |
}; | |
filterService.addFilter(facet), $location.search("fq", filterService.getFilterAsLocationParams()), $timeout(function() { | |
$scope.$emit("filterEvent", {}) | |
}) | |
} else { | |
var searchPage = config.root + "navigo/search?fq=" + filter + ":" + encodeURIComponent(value) + "&disp=" + $location.search().disp; | |
$window.location.href = searchPage | |
} | |
}, $scope.getNameToUse = function(doc, names) { | |
var selectedName = null; | |
return $.each(names, function(idx, name) { | |
selectedName || _.isEmpty(doc[name.field]) || (selectedName = name) | |
}), selectedName ? selectedName.field : null | |
}, $scope.formatField = function(doc, facet) { | |
var formatted = "", | |
value = doc[facet.field]; | |
return angular.isDefined(value) && (formatted = "format" === facet.field ? translateService.getTypeAbbr(value) : "modified" === facet.field ? $filter("date")(Date.parse(value), "M/d/yyyy, hh:mma") : "bytes" === facet.field ? value > 0 ? $filter("bytes")(value) : "0 bytes" : sugar.isDate(value) ? $filter("date")(Date.parse(value), "M/d/yyyy, hh:mma") : value), formatted | |
} | |
} | |
} | |
}), angular.module("voyager.results").directive("vsCardRecent", function() { | |
return { | |
strict: "A", | |
templateUrl: "src/results/card-recent.html" | |
} | |
}), angular.module("voyager.results").directive("vsTableRow", function(inView, $document, sugar, actionManager, config, $location, tagService) { | |
return { | |
link: function($scope, $element) { | |
function _isInView() { | |
var clientHeight, imageRect, visible = $element.is(":visible"), | |
isIn = !1; | |
visible && (clientHeight = $document[0].documentElement.clientHeight, imageRect = $element.children()[0].getBoundingClientRect(), isIn = imageRect.top >= 0 && imageRect.bottom <= clientHeight || imageRect.bottom >= 0 && imageRect.bottom <= clientHeight || imageRect.top >= 0 && imageRect.top <= clientHeight), isIn ? inView.add($scope.doc) : inView.remove($scope.doc) | |
} | |
angular.isDefined($scope.doc.geo) && inView.addCheckObserver(_isInView) | |
}, | |
controller: function($scope, filterService, translateService, $timeout, $location, $analytics, authService, cartService) { | |
$scope.link = sugar.copy(config.docLink), actionManager.setAction($scope.link, $scope), $scope.toggleCart = function(doc) { | |
var action = _.find($scope.actions, { | |
action: "add" | |
}); | |
doc.inCart ? (cartService.remove(doc.id), $scope.cartAction = "Add", $scope.btnType = "btn-primary", doc.inCart = !1, $analytics.eventTrack("removeFromList", { | |
category: "results", | |
label: "card", | |
id: doc.id, | |
user: authService.getUser().id | |
}), action.display = action.text) : (cartService.addItem(doc), $scope.cartAction = "Remove", $scope.btnType = "btn-default", doc.inCart = !0, $analytics.eventTrack("addToList", { | |
category: "results", | |
label: "card", | |
id: doc.id, | |
user: authService.getUser().id | |
}), action.onList = action.display, action.display = action.offList) | |
}, $scope.applyTag = function(tag) { | |
tagService.applyTag(tag, $scope, filterService) | |
}, $scope.hover = function(active) { | |
$scope.$emit("resultHoverEvent", { | |
doc: active ? $scope.doc : null | |
}) | |
}; | |
var actions = actionManager.initActions($scope, "table"); | |
$scope.actions = actions.display, $scope.default = actions.defaultAction, $scope.$on("addAllToCart", function() { | |
$scope.cartAction = "Remove", $scope.btnType = "btn-default", $scope.doc.inCart = !0, | |
actionManager.toggleDisplay(actions.types.add, $scope) | |
}), $scope.$on("removeAllCart", function() { | |
$scope.cartAction = "Add", $scope.btnType = "btn-primary", $scope.doc.inCart = !1, actionManager.toggleDisplay(actions.types.add, $scope) | |
}), $scope.$on("syncCard", function() { | |
$scope.doc.inCart ? ($scope.cartAction = "Remove", $scope.btnType = "btn-default") : ($scope.cartAction = "Add", $scope.btnType = "btn-primary"), $scope.isTable = !0, actionManager.toggleDisplay(actions.types.add, $scope) | |
}) | |
} | |
} | |
}), angular.module("voyager.results").factory("tableResultsService", function($window) { | |
return { | |
setFixedWidths: function() { | |
var windowWidth = angular.element($window).width(), | |
imgCol = $("th.semi.img"), | |
imageWidth = 100 / windowWidth * 100; | |
imgCol.css("width", imageWidth + "%"); | |
var toolsCol = $("#resultsTable").find("th").last(), | |
toolsWidth = 85 / windowWidth * 100; | |
toolsCol.css("width", toolsWidth + "%") | |
}, | |
forceWidths: function() { | |
var $header, width, toWidth, $tableHeaders = angular.element(".ng-table").find("th"); | |
_.each($tableHeaders, function(header) { | |
$header = angular.element(header), width = $header.css("width"), toWidth = $header.data("width"), angular.isDefined(toWidth) && width !== toWidth && $header.css("width", toWidth) | |
}) | |
} | |
} | |
}), angular.module("voyager.results").controller("TableCtrl", function($scope, ngTableParams, $timeout, $location, configService, translateService, $filter, filterService, config, sugar, tableResultsService) { | |
"use strict"; | |
function _setDefaultColumnWidths() { | |
var defaultWidth = 88 / vm.tableFields.length, | |
width = 0, | |
totalWidth = 0; | |
$.each(vm.tableFields, function(index, field) { | |
angular.isUndefined(field.width) ? field.width = "" + defaultWidth + "%" : field.width.indexOf("%") === -1 && (field.width = field.width + "%"), width = field.width.replace("%", ""), width = Number(parseFloat(width).toFixed(2)), totalWidth += width | |
}) | |
} | |
function _getSort(sortParam) { | |
var name; | |
for (name in sortParam) | |
if (sortParam.hasOwnProperty(name)) return { | |
sort: name, | |
direction: sortParam[name] | |
} | |
} | |
var deferred, vm = this, | |
loaded = !1, | |
reloading = !1, | |
lastSort = {}; | |
vm.getTableWidth = function() { | |
var table = angular.element(document.getElementById("resultsTable"))[0]; | |
return table.clientWidth | |
}; | |
var addAction = _.find(config.docActions, { | |
action: "add" | |
}); | |
$scope.addActionText = "Add to Queue", addAction && ($scope.addActionText = addAction.text); | |
var Store = function() { | |
return { | |
set: function(field, value) { | |
var fieldName = field.split("-")[1]; | |
configService.updateColumnWidth(fieldName, value) | |
}, | |
get: function(field) { | |
var fieldName = field.split("-")[1]; | |
return configService.getColumnWidth(fieldName) | |
} | |
} | |
}(); | |
window.store = Store, vm.tableFields = configService.getTableFields(), vm.textWrappingNotAllowed = !configService.getAllowsTextWrappingOnTableView(), _setDefaultColumnWidths(), $scope.hideThumbnails = !configService.getShowThumbnailOnTableView(), $scope.hideFlags = !configService.getShowFlagOnTableView(), $scope.toggleThumbnails = function() { | |
$scope.hideThumbnails = !$scope.hideThumbnails | |
}, $scope.applyFlag = function(flag) { | |
filterService.clear(); | |
var params = $location.search(); | |
return delete params.q, delete params.place, delete params.recent, params.fq = "tag_flags" + flag, $location.search(params), filterService.setFilters({ | |
fq: "tag_flags:" + flag | |
}), $scope.$emit("filterEvent"), !1 | |
}, $scope.$on("searchResults", function(event, data) { | |
vm.tableLoading = !1, vm.tableFields = configService.getTableFields(), _setDefaultColumnWidths(); | |
var docs = data.response.docs; | |
loaded ? (reloading = !0, $scope.tableParams.reload(), deferred.resolve(docs), reloading = !1) : (loaded = !0, deferred.resolve(docs)), $timeout(function() { | |
tableResultsService.setFixedWidths(), tableResultsService.forceWidths() | |
}), $timeout(function() { | |
$(window).trigger("resize") | |
}, 200) | |
}), $scope.$on("changeView", function() { | |
var view = $location.search().view; | |
"table" === view && ($scope.$emit("doSearch", {}), vm.tableLoading = !0) | |
}), $scope.$on("$destroy", function() { | |
configService.resetColumns() | |
}); | |
var tableParams = { | |
count: 10, | |
filter: {}, | |
sorting: {} | |
}; | |
$scope.tableParams = new ngTableParams(tableParams, { | |
counts: [], | |
total: 0, | |
getData: function($defer, params) { | |
deferred = $defer; | |
var isSort = !angular.equals(lastSort, params.sorting()); | |
if (!isSort || loaded && !reloading) { | |
if (isSort) { | |
lastSort = params.sorting(); | |
var sort = _getSort(params.sorting()); | |
$location.search("sort", sort.sort), $location.search("sortdir", sort.direction), $scope.$emit("doSearch", sort) | |
} else loaded || ($scope.$emit("doSearch", { | |
force: !0 | |
}), vm.tableLoading = !0); | |
if (!isSort) { | |
var sortField = $location.search().sort, | |
sortDir = $location.search().sortdir; | |
if (angular.isDefined(sortField)) { | |
var sortParam = {}; | |
sortParam[sortField] = sortDir, params.sorting(sortParam) | |
} | |
} | |
} | |
} | |
}), $scope.formatField = function(doc, facet) { | |
var formatted = "", | |
value = doc[facet.field]; | |
return angular.isDefined(value) && (formatted = "format" === facet.field ? translateService.getTypeAbbr(value) : "modified" === facet.field ? $filter("date")(Date.parse(value), "M/d/yyyy, hh:mma") : "bytes" === facet.field ? value > 0 ? $filter("bytes")(value) : "0 bytes" : sugar.isDate(value) ? $filter("date")(Date.parse(value), "M/d/yyyy, hh:mma") : value), formatted | |
}, vm.hover = function(doc) { | |
$scope.$emit("resultHoverEvent", { | |
doc: doc | |
}) | |
}, $scope.setDefer = function(defer) { | |
deferred = defer | |
} | |
}), angular.module("voyager.results").factory("inView", function() { | |
function _check() { | |
_.each(_checkObservers, function(observer) { | |
observer() | |
}) | |
} | |
var _inView = {}, | |
_checkObservers = [], | |
_viewObserver = function() {}; | |
return { | |
add: function(doc) { | |
_inView[doc.id] = doc | |
}, | |
remove: function(doc) { | |
delete _inView[doc.id] | |
}, | |
addCheckObserver: function(observer) { | |
_checkObservers.push(observer) | |
}, | |
reset: function() { | |
_inView = {}, _checkObservers = [] | |
}, | |
clear: function() { | |
_inView = {} | |
}, | |
check: function() { | |
_check() | |
}, | |
getAll: _inView, | |
setViewObserver: function(observer) { | |
_viewObserver = observer | |
}, | |
notify: function() { | |
_viewObserver(_inView) | |
} | |
} | |
}), angular.module("voyager.results").controller("ResultErrorCtrl", function($scope, $uibModalInstance, resultStackTrace) { | |
"use strict"; | |
$scope.resultStackTrace = JSON.stringify(resultStackTrace), $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("voyager.details", ["leaflet-directive", "cart", "voyager.search", "voyager.util", "voyager.security", "dialogs.main", "voyager.map", "ui.router", "angularSpinner"]), | |
function() { | |
"use strict"; | |
function detailsActions($window, $analytics, config, sugar, authService) { | |
function _isVisible(action, doc, $scope) { | |
var visible = action.visible; | |
return action.enabled = !!angular.isUndefined(action.enabled) || action.enabled, visible = !!action.enabled && visible, visible === !0 || visible === !1 ? visible : (visible = visible.indexOf("doc.") > -1 ? $scope.$eval(visible) && "preview" !== action.action && "tag" !== action.action : doc[action.visible] && "preview" !== action.action && "tag" !== action.action, !!action.enabled && visible) | |
} | |
function _setAction(action, doc, $scope) { | |
action.visible = _isVisible(action, doc, $scope), doc.isopen = !1, "download" === action.action ? (angular.isDefined(doc.download) && sugar.canOpen(doc) && (action.text = action.alt), action.do = function() { | |
$analytics.eventTrack("download", { | |
category: "results", | |
label: doc.format, | |
id: doc.id, | |
user: authService.getUser().id | |
}), sugar.canOpen(doc) ? $window.open(doc.download) : authService.getUserInfo().then(function(user) { | |
$window.location.href = doc.download + sugar.paramDelimiter(doc.download) + "_vgp=" + user.exchangeToken | |
}) | |
}) : "open" === action.action ? action.do = function() { | |
$analytics.eventTrack("openWith", { | |
category: "results", | |
label: action.url, | |
id: doc.id, | |
user: authService.getUser().id | |
}); | |
var param = ""; | |
action.url.indexOf("?") === -1 && (param = "?url="), action.param && (param = "?" + action.param + "="), $window.open(action.url + param + encodeURIComponent(doc.fullpath)) | |
} : "openArcMap" === action.action && (action.do = function() { | |
$analytics.eventTrack("openArcMap", { | |
category: "results", | |
label: doc.id, | |
id: doc.id, | |
user: authService.getUser().id | |
}), $window.location.href = doc.layerURL | |
}) | |
} | |
function _getActions(doc, $scope) { | |
var actions = _.cloneDeep(config.docActions); | |
return _.each(actions, function(action) { | |
_setAction(action, doc, $scope), action.display = angular.isDefined(action.display) ? action.display : action.text | |
}), actions | |
} | |
return { | |
setAction: _setAction, | |
getActions: _getActions | |
} | |
} | |
angular.module("voyager.details").factory("detailsActions", detailsActions) | |
}(), angular.module("voyager.details").factory("detailService", function($http, config, $q, resultsDecorator, solrUtil, catalogService, authService) { | |
"use strict"; | |
function _buildTreeRequest(id, shard) { | |
var service = config.root + "solr/v0/select?fq=id:" + id, | |
fields = "&fl=tree, format, id", | |
shards = ""; | |
return _.isEmpty(shard) || (shards = "&shards.info=true&shards.tolerant=true&shards=" + shard), service + fields + shards + _type + "&r=" + Math.random() | |
} | |
function _buildRelationshipRequest(id, shard, type, direction, displayFields) { | |
var service = config.root + "api/rest/index/links/" + id + "?dir=" + direction + "&rel=" + type, | |
fields = "&fl=id,name:[name],fullpath:[absolute],content:[contentURL],thumb:[thumbURL],preview:[previewURL],download:[downloadURL],bbox, format, hasMetadata, root, tree, tag_tags, links, hasMissingData, shard:[shard]"; | |
_.isArray(displayFields) ? fields += "," + displayFields.join(",") : "string" == typeof displayFields && (fields += "," + displayFields); | |
var shards = ""; | |
return _.isEmpty(shard) || (shards = "&shards=" + shard), service + fields + shards + "&r=" + Math.random() | |
} | |
function _fetchTranslation() { | |
return _.isEmpty(_translation) ? $http.get(config.root + "api/rest/i18n/links?block=false").then(function(res) { | |
return _translation = res.data | |
}) : $q.when(_translation) | |
} | |
function _fetchTypes(direction) { | |
return _fetchTranslation().then(function(types) { | |
return types[direction] | |
}) | |
} | |
function _fetchRelationship(id, shard, type, direction, fields) { | |
var deferred = $q.defer(), | |
request = _buildRelationshipRequest(id, shard, type, direction, fields); | |
return $http.get(request).then(function(res) { | |
var docs = res.data.docs; | |
angular.isDefined(docs) && docs.length > 0 ? deferred.resolve(res.data) : deferred.reject(id + " not found") | |
}), deferred.promise | |
} | |
function _fetchLink(relationship, id, shard, type, direction, fields) { | |
return _fetchRelationship(id, shard, type, direction, fields).then(function(response) { | |
var docs = response.docs; | |
return resultsDecorator.decorate(docs, []), resultsDecorator.decorateRelationships(docs, fields), relationship.numFound += response.numFound, $.merge(relationship.values, docs), relationship | |
}, function() { | |
return relationship | |
}) | |
} | |
function _getRelationship(relationships, name, type) { | |
var relationship = relationships[type]; | |
return relationship || (relationship = { | |
name: name, | |
type: type, | |
values: [], | |
numFound: 0 | |
}, relationships[type] = relationship), relationship | |
} | |
function _getTokenParam(shard) { | |
return angular.isDefined(shard) ? authService.getUserInfo().then(function(user) { | |
return "&_vgp=" + user.exchangeToken | |
}) : $q.when("") | |
} | |
function _getFields(shard) { | |
var root = config.root, | |
catalog = "local"; | |
if (angular.isDefined(shard)) { | |
var remoteCatalog = catalogService.lookup(shard); | |
angular.isDefined(remoteCatalog) && (root = remoteCatalog.url, catalog = shard) | |
} | |
return _.isEmpty(_fields[catalog]) ? _getTokenParam(shard).then(function(tokenParam) { | |
var request = root + "solr/fields/select?fl=name,multivalued,disp:disp_en,stype,displayable,filterable" + _type + "&rows=100000&r=" + Math.random() + tokenParam; | |
return $http.jsonp(request).then(function(res) { | |
return _fields[catalog] = _.indexBy(res.data.response.docs, function(key) { | |
return solrUtil.stripAugmented(key.name) | |
}), _fields[catalog] | |
}) | |
}) : $q.when(_fields[catalog]) | |
} | |
function _fetchRelationships(direction, id, shard, fields) { | |
var relationships = {}, | |
promises = [], | |
deferred = $q.defer(); | |
return _fetchTypes(direction).then(function(types) { | |
_.each(types, function(name, type) { | |
var relationship = _getRelationship(relationships, name, type), | |
promise = _fetchLink(relationship, id, shard, type, direction, fields); | |
promises.push(promise) | |
}), $q.all(promises).then(function() { | |
deferred.resolve(relationships) | |
}) | |
}), deferred.promise | |
} | |
var _type = "&wt=json&json.wrf=JSON_CALLBACK&block=false", | |
_translation = {}, | |
_recentViews = [], | |
_fields = {}, | |
buildRequest = function(id, displayFields, shard, disp) { | |
var service = config.root + "solr/v0/select?fq=id:" + id, | |
fields = "&fl=id,name:[name],fullpath:[absolute],absolute_path:[absolute],content:[contentURL],thumb:[thumbURL],preview:[previewURL],download:[downloadURL],bbox,format,hasMetadata,root,tree,tag_tags,links,geo:[geo],hasMissingData,schema,layerURL:[lyrURL]"; | |
fields += displayFields; | |
var shards = ""; | |
return _.isEmpty(shard) || (shards = "&shards.info=true&shards.tolerant=true&shards=" + shard), service + fields + shards + _type + "&rand=" + Math.random() + "&disp=" + disp | |
}; | |
return { | |
lookup: function(id, fields, shard, disp) { | |
var promises = []; | |
promises.push(_getFields(shard)); | |
var request = buildRequest(id, fields, shard, disp); | |
return promises.push($http.jsonp(request)), $q.all(promises).then(function(result) { | |
return result[1] | |
}) | |
}, | |
fetchTree: function(id, shard) { | |
var deferred = $q.defer(), | |
request = _buildTreeRequest(id, shard); | |
return $http.jsonp(request).then(function(res) { | |
var docs = res.data.response.docs; | |
angular.isDefined(docs) && docs.length > 0 ? deferred.resolve(docs[0]) : deferred.reject(id + " not found") | |
}), deferred.promise | |
}, | |
fetchToRelationships: function(id, fields, shard) { | |
var direction = "to"; | |
return _fetchRelationships(direction, id, shard, fields) | |
}, | |
fetchFromRelationships: function(doc, fields, shard) { | |
var direction = "from"; | |
return _fetchRelationships(direction, doc.id, shard, fields) | |
}, | |
addRecent: function(doc) { | |
var exists = _.findIndex(_recentViews, { | |
id: doc.id | |
}) !== -1; | |
exists || _recentViews.push(doc), _recentViews.length > 5 && _recentViews.splice(0, 1) | |
}, | |
getRecent: function() { | |
return _recentViews.slice() | |
}, | |
getFields: function(shard) { | |
var catalog = "local"; | |
if (angular.isDefined(shard)) { | |
var remoteCatalog = catalogService.lookup(shard); | |
angular.isDefined(remoteCatalog) && (catalog = shard) | |
} | |
return _fields[catalog] | |
}, | |
fetchMetadataStyles: function(id) { | |
return $http.get(config.root + "api/rest/appearance/metadata/styles/" + id).then(function(res) { | |
return res.data | |
}) | |
} | |
} | |
}), angular.module("voyager.details").directive("vsDetailsMap", function($compile, config, mapUtil, baseMapService, mapControls, $timeout) { | |
"use strict"; | |
var geoLayer; | |
return { | |
compile: function(element) { | |
element.append('<leaflet style="height: 100%" defaults="defaults" controls="controls" layers="layers" id="details-map"></leaflet>') | |
}, | |
link: function() { | |
geoLayer = null | |
}, | |
controller: function($scope, leafletData) { | |
if ($scope.doc.isMappable); | |
else if ($scope.doc.geo) { | |
var geo = $scope.doc.geo; | |
leafletData.getMap("details-map").then(function(map) { | |
$timeout(function() { | |
map.invalidateSize(!1); | |
var geoType = angular.isDefined(geo.type) ? geo.type.toLowerCase() : "", | |
checkArea = geoType.indexOf("point") === -1; | |
geoLayer = mapUtil.drawGeoJson(map, geo, !0, void 0, checkArea) | |
}), map.on("layeradd", function() { | |
config.map.config.cached || $(".leaflet-image-layer").css("z-index", "-1") | |
}) | |
}) | |
} | |
$scope.defaults = baseMapService.getDefaultConfig(), $scope.layers = baseMapService.getLayers(); | |
var spinControl = L.control(); | |
spinControl.setPosition("topright"), spinControl.onAdd = function() { | |
var template = '<div class="leaflet-bar leaflet-draw-toolbar">'; | |
return template += "<span us-spinner=\"{top:'-25px',left:'-5px',radius:4, width:3, length: 5}\" spinner-key=\"map-spinner\"></span>", template += "</div>", $compile($(template))($scope)[0] | |
}, $scope.controls = { | |
custom: [spinControl] | |
}, mapControls.init($scope, "details-map"), geoLayer && mapControls.setBounds(geoLayer.getBounds()), $scope.controls.custom.push(mapControls.getZoomControls($scope).setPosition("bottomleft")) | |
} | |
} | |
}), angular.module("voyager.details").factory("detailConfig", function(config, $q, configService, translateService, configLoader, sugar, solrUtil) { | |
function _setInclusions() { | |
$.each(displayFields, function(index, value) { | |
value.name = solrUtil.stripAugmented(value.name), inclusions[value.name] = value.name, _styles[value.name] = value.style, _showLabels[value.name] = value.showLabel, _maxLines[value.name] = value.maxLines, displayParams += ", " + value.name, _displayFieldsOrder[value.name] = index, _editable[value.name] = value.editable | |
}) | |
} | |
function _setSummaryInclusions() { | |
$.each(_summaryFields, function(index, value) { | |
value.name = solrUtil.stripAugmented(value.name), _summaryInclusions[value.name] = value.name, _summaryStyles[value.name] = value.style, _summaryMaxLines[value.name] = value.maxLines, _summaryShowLabels[value.name] = value.showLabel, _summaryParams += ", " + value.name, _summaryFieldsOrder[value.name] = index | |
}) | |
} | |
function _getPageFramework() { | |
return _pageFramework | |
} | |
function _getSummaryFlags() { | |
return _summaryFlags | |
} | |
function _getDefaultMetadataStylesheet() { | |
return _defaultMetadataStylesheet | |
} | |
function _load(configId, allFields) { | |
var deferred = $q.defer(); | |
return configLoader.prepare().then(function() { | |
translateService.init(), configService.setFilterConfig(configId).then(function() { | |
configService.getConfigDetails(configId).then(function(response) { | |
var display = response.data.details; | |
_pageFramework = display.pageElements, _summaryFlags = display.summaryFields, _defaultMetadataStylesheet = display.defaultMetadataStylesheet, display.path === !1 && (_showPath = !1), display.ref === !1 && (_showFormat = !1), displayFields = display.detailsTableFields, _showAllFields = "ALL" === display.detailsTableConfig || "true" === allFields, _globalEditable = config.editAll, display.summaryFields && (_summaryFields = display.summaryFields.fields, _setSummaryInclusions()), _setInclusions(), deferred.resolve() | |
}) | |
}) | |
}), deferred.promise | |
} | |
function _exclude(name) { | |
var index = _.findIndex(excludePrefix, function(prefix) { | |
return 0 === name.indexOf(prefix) || name === prefix | |
}); | |
return index !== -1 | |
} | |
function _getFields(doc, fields, typeInclusions, typeStyles, typeShowAllFields) { | |
var prettyFields = [], | |
emptyFields = _.clone(typeInclusions), | |
isArray = !1, | |
formattedValue = ""; | |
return $.each(doc, function(name, value) { | |
if ((typeInclusions[name] || typeShowAllFields === !0) && angular.isDefined(fields[name]) && fields[name].displayable === !0 && (delete emptyFields[name], !_exclude(name))) { | |
formattedValue = value, isArray = !1; | |
var formattedValues = {}; | |
_.isArray(value) && (formattedValue = value.join(", "), isArray = !0, formattedValues = _.indexBy(value)), "format" === name ? formattedValue = translateService.getType(value) : "contains_mime" === name ? _.isArray(value) ? (formattedValues = {}, _.each(value, function(val) { | |
formattedValues[val] = translateService.getType(val) | |
})) : formattedValue = translateService.getType(value) : "location" === name ? formattedValue = translateService.getLocation(value) : "bytes" === name && (formattedValue = sugar.bytesToSize(value)), "STRIP_HTML" === typeStyles[name] && (formattedValue = $("<p>" + value + "</p>").text()); | |
var isHref = !1; | |
"STRING" !== typeStyles[name] && "STRIP_HTML" !== typeStyles[name] && (isHref = _.isArray(value) && "HREF" !== typeStyles[name] ? _.any(value, function(v) { | |
return sugar.isUrl(v) | |
}) : "HREF" === typeStyles[name] || sugar.isUrl(value)); | |
var isHtml = "HTML" === typeStyles[name]; | |
fields[name].filterable || isHtml || isHref ? isHref && (typeStyles[name] = "HREF") : typeStyles[name] = "STRING", prettyFields.push({ | |
name: translateService.getFieldName(name), | |
stype: fields[name].stype, | |
isArray: isArray, | |
value: value, | |
formattedValue: formattedValue, | |
formattedValues: formattedValues, | |
order: _displayFieldsOrder[name], | |
editable: _editable[name] || _globalEditable, | |
maxLines: _maxLines[name], | |
showLabel: _showLabels[name], | |
key: name, | |
style: typeStyles[name], | |
isHtml: isHtml, | |
isHref: isHref | |
}) | |
} | |
prettyFields.length > 0 && ("abstract" !== name || _.isEmpty(doc.abstract) ? "description" !== name || _.isEmpty(doc.description) || (doc.displayDescription = _.last(prettyFields)) : doc.displayDescription = _.last(prettyFields)) | |
}), $.each(emptyFields, function(name) { | |
(_editable[name] === !0 || _globalEditable) && prettyFields.push({ | |
name: translateService.getFieldName(name), | |
value: "", | |
formattedValue: "", | |
order: _displayFieldsOrder[name], | |
editable: !0, | |
key: name | |
}) | |
}), _.sortBy(prettyFields, "order") | |
} | |
function _getDisplayFields(doc, fields) { | |
return _getFields(doc, fields, inclusions, _styles, _showAllFields) | |
} | |
function _getSummaryFields(doc, fields) { | |
return _getFields(doc, fields, _summaryInclusions, _summaryStyles, !1) | |
} | |
var displayFields; | |
config.settings && (displayFields = config.settings.data.details.detailsTableFields); | |
var _summaryFields = [], | |
_summaryFlags = {}, | |
_summaryInclusions = {}, | |
_summaryParams = "", | |
_summaryFieldsOrder = {}, | |
inclusions = {}, | |
_displayFieldsOrder = {}, | |
displayParams = "", | |
_showAllFields = !1, | |
_editable = {}, | |
_styles = {}, | |
_showLabels = {}, | |
_maxLines = {}, | |
_summaryStyles = {}, | |
_summaryMaxLines = {}, | |
_summaryShowLabels = {}, | |
_pageFramework = {}, | |
_showPath = !0, | |
_showFormat = !0, | |
_defaultMetadataStylesheet = "", | |
_globalEditable = !1, | |
excludePrefix = config.excludeDetails; | |
return { | |
load: _load, | |
showPath: function() { | |
return _showPath | |
}, | |
showFormat: function() { | |
return _showFormat | |
}, | |
getFields: _getDisplayFields, | |
getSummaryFields: _getSummaryFields, | |
getPageFramework: _getPageFramework, | |
getDefaultMetadataStylesheet: _getDefaultMetadataStylesheet, | |
getSummaryFlags: _getSummaryFlags | |
} | |
}), angular.module("voyager.details").controller("DetailsCtrl", function($scope, $stateParams, cartService, translateService, authService, config, detailService, mapServiceFactory, leafletData, usSpinnerService, dialogs, $sce, $q, configService, $timeout, tagService, searchService, $location, $window, urlUtil, resultsDecorator, loading, detailConfig, $analytics, $uibModal, filterService, detailsActions, $log, converter) { | |
function _getExtraRelationshipFields() { | |
return config.extraRelationshipFields || [] | |
} | |
function _setPermissions() { | |
$scope.canEdit = authService.hasPermission("edit_fields") && $scope.isRemote !== !0, $scope.canTag = authService.hasPermission("tag"), $scope.canAdmin = authService.hasPermission("manage"), $scope.canFlag = authService.hasPermission("flag"), $scope.canViewTags = authService.hasPermission("view_tags"), $scope.canViewMetadata = authService.hasPermission("show_metadata") | |
} | |
function _adjustForBanner() { | |
$timeout(function() { | |
var $banner = angular.element("#top-banner"); | |
if ($banner.outerHeight() > 0) { | |
var $floatingNav = angular.element(".floating-nav"); | |
$floatingNav.length > 0 ? $floatingNav.offset({ | |
top: $floatingNav.offset().top + $banner.outerHeight() | |
}) : _adjustForBanner() | |
} | |
}, 250) | |
} | |
function _hasShard(shard) { | |
return angular.isDefined(shard) && "[not a shard request]" !== shard | |
} | |
function _activate() { | |
_hasShard($stateParams.shard) && ($scope.shard = $stateParams.shard, $scope.shardParam = "&shard=" + $stateParams.shard, $scope.shardsParam = "&shards=" + $stateParams.shard), !$scope.pageFramework.showHeaderInfo && $location.path().indexOf("/search") > -1 ? angular.element("body").addClass("no-header") : angular.element("body").removeClass("no-header"), _doLookup($stateParams.id), $analytics.eventTrack("view", { | |
category: "details", | |
label: $stateParams.id, | |
id: $stateParams.id | |
}), detailService.fetchMetadataStyles($stateParams.id).then(function(styleSheets) { | |
$scope.styleSheets = styleSheets | |
}), _setPermissions(), tagService.fetchTags().then(function(tags) { | |
$.merge(_tags, tags) | |
}), $scope.onUpdateTags = function(tags) { | |
var index = $scope.displayFields.findIndex(function(item) { | |
return "tag_tags" === item.key | |
}); | |
if (index !== -1) { | |
var field = $scope.displayFields[index]; | |
field.value = tags, field.formattedValue = tags.join(); | |
var formattedValues = {}; | |
_.each(tags, function(val) { | |
formattedValues[val] = val | |
}), field.formattedValues = formattedValues | |
} | |
}, authService.addObserver(_setPermissions) | |
} | |
function createFolderLinks(doc, url) { | |
$scope.doc_path = { | |
url: "search?disp=" + $scope.disp + "&fq=location:" + doc.location, | |
path: doc.fullpath.substring(0, doc.fullpath.indexOf(doc.folder.replace(/\//g, "\\"))) | |
}; | |
var tempFolders = doc.folder.split("/"); | |
_.each(tempFolders, function(item) { | |
"" !== url && (url += "/"), url += encodeURI(item), $scope.sub_paths.push({ | |
path: item + "\\", | |
url: "search?disp=" + $scope.disp + "&fq=path:" + url + "&fq=location:" + doc.location | |
}) | |
}); | |
var filename = doc.fullpath.split("\\").pop(); | |
$scope.sub_paths.push({ | |
path: filename, | |
url: "search?disp=" + $scope.disp + "&fq=path:" + (url + "/" + filename) + "&fq=location:" + doc.location | |
}) | |
} | |
function createDatasetLinks(doc) { | |
var tempFolders = doc.fullpath.split("Dataset"); | |
if (tempFolders && ($scope.doc_path = { | |
url: "search?disp=" + $scope.disp + "&fq=location:" + doc.location, | |
path: tempFolders[0] + "Dataset" | |
}, tempFolders[1])) { | |
var path = tempFolders[1].replace(/^[\/\\]/, "").replace(/\s[|]\s/g, "\\").replace(/\\/g, "%255C"); | |
$scope.sub_paths.push({ | |
path: tempFolders[1], | |
url: "search?disp=" + $scope.disp + "&fq=location:" + doc.location + "&fq=path:" + path | |
}) | |
} | |
} | |
function createPathLinks(doc) { | |
if ($scope.isURL = 0 === doc.fullpath.indexOf("http:") || 0 === doc.fullpath.indexOf("https:"), !$scope.isURL) { | |
var url = ""; | |
$scope.sub_paths = [], doc.folder ? createFolderLinks(doc, url) : createDatasetLinks(doc) | |
} | |
} | |
function _doSyncFields(id) { | |
detailService.lookup(id, ",*", $stateParams.shard, $stateParams.disp).then(function(data) { | |
var doc = data.data.response.docs[0]; | |
$scope.displayFields = detailConfig.getFields(doc, detailService.getFields($stateParams.shard)), $scope.summaryFields = detailConfig.getSummaryFields(doc, detailService.getFields($stateParams.shard)) | |
}) | |
} | |
function _doLookup(id) { | |
detailService.lookup(id, ",*", $stateParams.shard, $stateParams.disp).then(function(data) { | |
var doc = data.data.response.docs[0]; | |
resultsDecorator.decorate([doc], []); | |
var shardInfo = data.data["shards.info"]; | |
shardInfo && doc.isRemote && _.each(shardInfo, function(shard) { | |
doc.remoteDetails = shard.shardAddress, doc.remoteDetails = doc.remoteDetails.substring(0, doc.remoteDetails.indexOf("/solr")), doc.remoteDetails += "/show?id=" + doc.id + "&disp=default" | |
}), $scope.doc = doc, $scope.image = doc.thumb, $scope.preview = doc.preview, angular.isUndefined(doc.preview) && ($scope.preview = $scope.image), $scope.download = doc.download, angular.isDefined(doc.format) && ($scope.format = translateService.getType(doc.format), $scope.doc.displayFormat = $scope.format), $scope.displayFields = detailConfig.getFields(doc, detailService.getFields($stateParams.shard)), $scope.summaryFields = detailConfig.getSummaryFields(doc, detailService.getFields($stateParams.shard)), $scope.pageFramework = detailConfig.getPageFramework(), $scope.summaryFlags = detailConfig.getSummaryFlags(), $scope.description = doc.displayDescription, doc.fullpath ? createPathLinks(doc) : $scope.isURL = !1, doc.bbox && ($scope.hasBbox = !0), doc.hasSchema = angular.isDefined(doc.schema), doc.hasSchema && ($scope.schema = JSON.parse(doc.schema), $scope.schemaLink = "search?disp=" + $scope.disp + "&fq=schema_hash:" + $scope.schema.hash), $scope.doc.isMappable = mapServiceFactory.isMappable(doc.format), $scope.doc.isService = $scope.doc.isMappable, $scope.showMap = $scope.hasBbox || $scope.doc.isMappable, $scope.getAction = "Download", $scope.recent = detailService.getRecent(), resultsDecorator.decorate($scope.recent, []), detailService.addRecent($scope.doc), doc.hasMetadata && $scope.canViewMetadata && _setStyle(), angular.isDefined(doc.tag_tags) && ($scope.select2Options.tags = doc.tag_tags, $scope.labels = doc.tag_tags), $scope.getRelationships(), _setSelectedTab(), loading.done(), $timeout(function() { | |
$scope.loading = !1, $scope.doc.isMappable && $scope.addToMap() | |
}, 100), angular.isDefined($scope.doc.thumb) && $scope.doc.thumb.indexOf("vres/mime") !== -1 && (doc.defaultThumb = !0), $scope.doc.canCart = authService.hasPermission("process"), $scope.actions = detailsActions.getActions($scope.doc, $scope); | |
var addAction = _.find($scope.actions, { | |
action: "add" | |
}); | |
$scope.canCart = $scope.doc.canCart && !$scope.isRemote && addAction.visible, addAction.visible = !1, cartService.fetchQueued([{ | |
id: doc.id | |
}]).then(function(items) { | |
doc.inCart = items.length > 0 | |
}), _adjustForBanner(), doc.isVideo = "video/mp4" === doc.format | |
}) | |
} | |
function _setStyle() { | |
$scope.theme = {}, $scope.theme.selected = detailConfig.getDefaultMetadataStylesheet() || config.metadataStyle, $scope.$watch("theme.selected", function() { | |
$scope.metadataUrl = $scope.doc.content, $scope.metadataUrl && ($scope.metadataUrl.indexOf("/", $scope.metadataUrl.length - 1) === -1 && ($scope.metadataUrl += "/"), $scope.metadataUrl += "meta.xml?style=" + $scope.theme.selected, _hasShard($scope.doc.shard) && ($scope.metadataUrl += "&shard=" + $scope.doc.shard)) | |
}) | |
} | |
function _showError(error) { | |
var message = null; | |
angular.isDefined(error.details) && (message = error.details[0]), dialogs.error(error.message, message) | |
} | |
function _flagMissing(nodes) { | |
for (var format, node, i = 0; i < nodes.length; i++) node = nodes[i], format = node.mime, node.hasMissingData = angular.isDefined(format) && format.indexOf("missing") !== -1, node.children && _flagMissing(node.children) | |
} | |
function _applyRelationships(relationships, type) { | |
$.isEmptyObject(relationships) ? $log.log("no result") : _.each(relationships, function(obj) { | |
if (obj.values && obj.values.length > 0) return $scope[type] = relationships, $scope.hasRelationships = !0, _removeDuplicateRelationshipChildren(), _setSelectedTab(), !1 | |
}) | |
} | |
function _removeDuplicateRelationshipChildren() { | |
$scope.relationships && $scope.relationships._root && $scope.fromRelationships && $scope.fromRelationships._children && $scope.relationships._root.numFound === $scope.fromRelationships._children.numFound && _.isEqual($scope.relationships._root.values, $scope.fromRelationships._children.values) && delete $scope.fromRelationships._children | |
} | |
function _setSelectedTab() { | |
$scope.showTab || ($scope.displayFields.length ? $scope.showTab = "summary" : $scope.doc.hasMetadata && $scope.canViewMetadata ? $scope.showTab = "metadata" : $scope.hasRelationships && ($scope.showTab = "relationship")) | |
} | |
function _getId() { | |
return decodeURIComponent($location.search().id) | |
} | |
function _move(direction, doc) { | |
var flag = "no" + direction; | |
if (null !== doc) { | |
$scope[flag] = !1; | |
var encodedId = encodeURIComponent(encodeURIComponent(doc.id)), | |
params = { | |
id: encodedId, | |
disp: configService.getConfigId() | |
}; | |
return _hasShard(doc.shard) && (params.shard = doc.shard), $location.search(params), !0 | |
} | |
return $scope[flag] = !0, !1 | |
} | |
function _searchTag(tagField, value) { | |
return $location.path("search"), $location.search("fq", tagField + ":" + value), filterService.setFilters({ | |
fq: tagField + ":" + value | |
}), $scope.$emit("filterEvent"), !1 | |
} | |
var _layer; | |
loading.show("#working"), $scope.imagePrefix = config.root + "vres/mime/icon/", $scope.showTab = "", $scope.demo = config.demo, $scope.rate = {}, $scope.rate.current_rating = 0, $scope.rate.total_user = 0, $scope.rate.user_rated = !1, $scope.labels = [], $scope.loading = !0, $scope.disp = $stateParams.disp || "default", $scope.hasRelationships = !1, $scope.pageFramework = {}, $scope.uiText = config.ui.details, $scope.showPath = detailConfig.showPath(), $scope.showFormat = detailConfig.showFormat(); | |
var _tags = []; | |
$scope.select2Options = { | |
multiple: !0, | |
simple_tags: !0 | |
}, _.isEmpty(config.homepage.tagValues) ? $scope.select2Options.tags = _tags : $scope.select2Options.data = converter.toIdTextArray(config.homepage.tagValues), _activate(), $scope.openOnRemote = function() { | |
$window.open($scope.doc.remoteDetails, "_blank") | |
}, $scope.addToCart = function() { | |
$scope.doc.inCart = !0, cartService.addItem($scope.doc) | |
}, $scope.removeFromCart = function() { | |
$scope.doc.inCart = !1, cartService.remove($scope.doc.id) | |
}, $scope.inCart = function(id) { | |
return cartService.isInCart(id) | |
}, $scope.showEditTag = !1, $scope.toggleEditTag = function() { | |
$scope.showEditTag = !$scope.showEditTag | |
}, $scope.addToMap = function() { | |
return !$scope.addedToMap && void $timeout(function() { | |
leafletData.getMap("details-map").then(function(map) { | |
var mapInfo = _.clone($scope.doc), | |
mapService = mapServiceFactory.getMapService(mapInfo); | |
mapService.addToMap(mapInfo, map).then(function(layer) { | |
layer.isValid !== !1 ? (layer.on("loading", function() { | |
usSpinnerService.spin("map-spinner") | |
}), usSpinnerService.stop("map-spinner"), layer.on("load", function() { | |
$scope.addedToMap = !0, _layer = layer, usSpinnerService.stop("map-spinner") | |
})) : (usSpinnerService.stop("map-spinner"), _showError(layer.error)) | |
}, function(error) { | |
usSpinnerService.stop("map-spinner"), _showError(error.error) | |
}), map.invalidateSize(!1) | |
}) | |
}) | |
}, $scope.removeFromMap = function() { | |
leafletData.getMap("details-map").then(function(map) { | |
map.removeLayer(_layer), $scope.addedToMap = !1, _layer = null | |
}) | |
}, $scope.trustSrc = function(src) { | |
return $sce.trustAsResourceUrl(src) | |
}, $scope.metadataSelect = function() { | |
window.scrollTo(0, document.body.scrollHeight) | |
}, $scope.getRelationships = function() { | |
var root = $scope.doc.id; | |
angular.isDefined($scope.doc.root) && (root = $scope.doc.root), detailService.fetchTree(root, $stateParams.shard).then(function(response) { | |
if (angular.isDefined(response.tree)) { | |
var tree = JSON.parse(response.tree); | |
tree.children && _flagMissing(tree.children), $scope.tree = [{ | |
mime: response.format, | |
name: tree.name, | |
id: tree.id, | |
children: tree.children | |
}], $scope.hasRelationships = !0, _setSelectedTab() | |
} | |
}), detailService.fetchToRelationships($scope.doc.id, _getExtraRelationshipFields(), $stateParams.shard).then(function(relationships) { | |
_applyRelationships(relationships, "relationships") | |
}), detailService.fetchFromRelationships($scope.doc, _getExtraRelationshipFields(), $stateParams.shard).then(function(relationships) { | |
_applyRelationships(relationships, "fromRelationships") | |
}) | |
}, $scope.fetchPreview = function(node) { | |
$scope.previewVisible = !0, node.promise = $timeout(function() { | |
detailService.fetchTreePreview(node.id, $stateParams.shard).then(function(preview) { | |
$scope.previewNodeData = preview.data.response.docs[0] | |
}) | |
}, 150) | |
}, $scope.cancelPreview = function(node) { | |
$scope.previewVisible = !1, $timeout.cancel(node.promise) | |
}, $scope.changeTab = function(tab) { | |
$scope.showTab !== tab && ($scope.showTab = tab, "relationship" === tab && void 0 === $scope.tree && $scope.getRelationships()) | |
}, $scope.edit = function(field) { | |
field.editing = !0, field.originalValue = field.value, field.originalFormatted = field.formattedValue, | |
"tag_tags" === field.key && "" === field.value && (field.value = []) | |
}, $scope.append = function(field) { | |
field.appending = !0 | |
}, $scope.cancel = function(field) { | |
field.editing = !1, field.appending = !1, field.value = field.originalValue, field.formattedValue = field.originalFormatted | |
}, $scope.isArray = function(data) { | |
return _.isArray(data) | |
}, $scope.doSave = function(field) { | |
if (field.isArray && !_.isArray(field.value)) { | |
var values = field.value.split(","), | |
edits = []; | |
_.each(values, function(val) { | |
edits.push(val.trim()) | |
}), field.value = edits | |
} | |
tagService.replace($scope.doc.id, field.key, field.value).then(function() { | |
field.editing = !1; | |
var canViewTags = $scope.canViewTags; | |
"tag_tags" === field.key && ($scope.labels = field.value, field.formattedValue = field.value.join(), canViewTags && ($scope.canViewTags = !1)), $timeout(function() { | |
canViewTags && ($scope.canViewTags = !0), _doSyncFields($scope.doc.id) | |
}, 200) | |
}) | |
}, $scope.lastSearch = urlUtil.getLastUrl(), $scope.hasRecords = searchService.hasRecords(), $scope.getPrevious = function() { | |
var id = searchService.getPreviousId(_getId()); | |
_move("Previous", id) && ($scope.noNext = !1) | |
}, $scope.getNext = function() { | |
usSpinnerService.spin("nav-spinner"), searchService.getNextId(_getId()).then(function(id) { | |
_move("Next", id) && ($scope.noPrevious = !1), usSpinnerService.stop("nav-spinner") | |
}) | |
}, $scope.showFlagModal = function() { | |
var modal = $uibModal.open({ | |
templateUrl: "src/bulk-update/flag-all.html", | |
controller: "FlagAllCtrl", | |
resolve: { | |
resultData: function() { | |
return { | |
totalItemCount: 1, | |
docId: $scope.doc.id | |
} | |
} | |
} | |
}); | |
modal.result.then(function() { | |
_doLookup($stateParams.id) | |
}) | |
}, $scope.removeFlag = function() { | |
tagService.deleteByField($scope.doc.id, "tag_flags").then(function(res) { | |
res.documents > 0 && delete $scope.doc.tag_flags | |
}) | |
}, $scope.searchFlag = function(tag) { | |
return _searchTag("tag_flags", tag) | |
}, $scope.searchTag = function(tag) { | |
return _searchTag("tag_tags", tag) | |
}, $scope.$on("$destroy", function() { | |
authService.removeObserver(_setPermissions) | |
}) | |
}), angular.module("voyager.details").directive("vgTags", function($timeout, tagService, $window, searchService) { | |
"use strict"; | |
function _decorateTags() { | |
var $container = $("#s2id_labels"), | |
$tags = $container.children(".select2-choices").children(".select2-search-choice").children("div"), | |
hasTags = !1; | |
return $.each($tags, function(name, value) { | |
$(value).hover(function(e) { | |
$(e.currentTarget).css({ | |
"text-decoration": "underline", | |
cursor: "pointer" | |
}) | |
}, function(e) { | |
$(e.currentTarget).css({ | |
"text-decoration": "none", | |
cursor: "auto" | |
}) | |
}), hasTags = !0 | |
}), hasTags | |
} | |
function _searchByTag() { | |
$("#labels").off("choice-selected"), $("#labels").on("choice-selected", function(e, v) { | |
var tag = $(v).text().trim(); | |
searchService.getLastSearch().indexOf("?") === -1 ? $window.location.href = searchService.getLastSearch() + "?fq=tag_tags:" + tag : $window.location.href = searchService.getLastSearch() + "&fq=tag_tags:" + tag | |
}) | |
} | |
return { | |
restrict: "A", | |
require: "ngModel", | |
link: function(scope, el, attrs) { | |
var autosave = "true" === attrs.autosave; | |
return scope.$watch(attrs.ngModel, function(newValues, last) { | |
$timeout(function() { | |
_decorateTags() && _searchByTag() | |
}, 0), _.isEqual(newValues, last) || scope.loading || !autosave || (tagService.saveLabels(scope.doc.id, newValues), scope.onUpdateTags && scope.onUpdateTags(newValues)) | |
}) | |
} | |
} | |
}), angular.module("voyager.details").directive("vsPreview", function(detailService, $timeout, translateService, loading, detailConfig) { | |
return { | |
restrict: "A", | |
link: function($scope, element) { | |
function _lookup(id, shard, el) { | |
_positionPreview(el), $scope.previewLoading = !0, loading.show("#previewLoading"), $scope.node = {}, detailService.lookup(id, "", shard).then(function(data) { | |
return $scope.node = data.data.response.docs[0], void 0 === $scope.node ? void $("#preview").css({ | |
display: "none" | |
}) : ($scope.previewNodeData = detailConfig.getFields(data.data.response.docs[0], detailService.getFields(shard)), angular.isDefined(data.data.response.docs[0].format) && ($scope.node.displayFormat = translateService.getType(data.data.response.docs[0].format)), $scope.previewLoading = !1, void loading.done()) | |
}) | |
} | |
function _positionPreview(el) { | |
var cp = el.offset(), | |
parentOffset = el.parents(".relationship").offset(); | |
$("#preview").css({ | |
display: "block", | |
left: parseInt(cp.left - parentOffset.left + el.parents("div").width() - 20) + "px", | |
top: parseInt(cp.top - parentOffset.top - 22) + "px" | |
}) | |
} | |
element.on("mouseenter", ".label a", function(event) { | |
$scope.node = {}; | |
var el = $(event.currentTarget); | |
this.timeoutPromise = $timeout(function() { | |
_lookup(el.data("id"), el.data("shard"), el) | |
}, 100) | |
}).on("mouseleave", ".label a", function() { | |
angular.isDefined(this.timeoutPromise) && $timeout.cancel(this.timeoutPromise), $("#preview").css({ | |
display: "none" | |
}) | |
}) | |
} | |
} | |
}), angular.module("voyager.search").controller("SavedSearchCtrl", function($scope, $location, filterService, savedSearchService, authService, $analytics, recentSearchService) { | |
function _loadSavedSearches() { | |
savedSearchService.getSavedSearches().then(function(savedSearches) { | |
var sortedSavedSearches = savedSearchService.sortSavedSearches(savedSearches); | |
vm.savedSearches = sortedSavedSearches.global, vm.personalSavedSearches = sortedSavedSearches.personal | |
}), $scope.isAnonymous = authService.isAnonymous() | |
} | |
var vm = this; | |
_loadSavedSearches(), authService.addObserver(_loadSavedSearches), savedSearchService.addObserver(_loadSavedSearches), recentSearchService.addObserver(_loadSavedSearches), vm.applySavedSearch = function(saved) { | |
savedSearchService.applySavedSearch(saved, $scope) | |
}, vm.deleteSearch = function(id) { | |
savedSearchService.deleteSearch(id).then(function() { | |
_loadSavedSearches(), $analytics.eventTrack("saved-search", { | |
category: "delete" | |
}) | |
}) | |
}, vm.dragControlListeners = { | |
enabled: !0, | |
accept: function() { | |
return vm.dragControlListeners.enabled | |
}, | |
orderChanged: function(eventObj) { | |
var list = vm.personalSavedSearches, | |
index = eventObj.dest.index, | |
beforeId = null, | |
afterId = null; | |
0 !== index && (beforeId = list[index - 1].id), index + 1 !== list.length && (afterId = list[index + 1].id), vm.dragControlListeners.enabled = !1, savedSearchService.order(list[index].id, beforeId, afterId).then(function() { | |
vm.dragControlListeners.enabled = !0 | |
}) | |
} | |
}, $scope.$on("$destroy", function() { | |
authService.removeObserver(_loadSavedSearches), savedSearchService.removeObserver(_loadSavedSearches), recentSearchService.removeObserver(_loadSavedSearches) | |
}), vm.criteriaMatch = function(term) { | |
return function(item) { | |
return !!angular.isUndefined(term) || item.title.toLowerCase().indexOf(term.toLowerCase()) > -1 | |
} | |
} | |
}), angular.module("voyager.search").factory("savedSearchService", function(sugar, $http, configService, $q, authService, $uibModal, recentSearchService, $location, filterService, $analytics, converter, displayConfigResource, solrGrunt, $timeout, catalogService) { | |
"use strict"; | |
function _applyBbox(solrParams, voyagerParams) { | |
if (_.isArray(solrParams.fq)) { | |
var index = sugar.getIndex(solrParams.fq, "bbox"); | |
solrParams.fq.splice(index, 1) | |
} else delete solrParams.fq; | |
solrParams.place = voyagerParams.bbox, solrParams["place.op"] = "WITHIN" === voyagerParams["bbox.mode"] ? "within" : "intersects" | |
} | |
function _getView(voyagerParams, defaultView) { | |
defaultView = defaultView ? defaultView.toLowerCase() : "card"; | |
var view = { | |
type: defaultView | |
}; | |
return angular.isDefined(voyagerParams.view) && (voyagerParams.view = voyagerParams.view.toLowerCase(), "table" !== voyagerParams.view && "map" !== voyagerParams.view || (view.type = voyagerParams.view)), view | |
} | |
function _decode(params) { | |
$.each(params, function(index, param) { | |
"string" == typeof param ? params[index] = decodeURIComponent(param) : $.each(param, function(index, value) { | |
param[index] = decodeURIComponent(value) | |
}) | |
}) | |
} | |
function _doSave(request) { | |
if (configService.hasChanges()) { | |
var settings = configService.getUpdatedSettings(); | |
request.display_override = { | |
listView: { | |
fields: settings.listView.fields | |
} | |
} | |
} | |
return request.path += "/disp=" + request.config, sugar.postJson(request, "display", "ssearch") | |
} | |
function _getQueryString(name) { | |
var rows = 150, | |
queryString = config.root + "solr/ssearch/select?&fl=*,display:[display]&"; | |
return queryString += "rows=" + rows + "&rand=" + Math.random(), angular.isDefined(name) && (name = name.replace(/ /g, "\\%20"), queryString += "&fq=title:" + name), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _fetch(name) { | |
var time = 100; | |
return void 0 !== name && (time = 0), $timeout.cancel(delay), delay = $timeout(function() { | |
$http.jsonp(_getQueryString(name)).then(function(data) { | |
deferred.resolve(data.data.response.docs), deferred = $q.defer() | |
}, function(error) { | |
console.log(error), deferred.error(error), deferred = $q.defer() | |
}) | |
}, time), deferred.promise | |
} | |
function _mergeOrFilters(params) { | |
var filters = params.fq; | |
if (_.isArray(filters) && filters.length > 1) { | |
var orIndex = _.findIndex(filters, function(filter) { | |
return filter.indexOf("(") !== -1 | |
}); | |
if (orIndex !== -1) { | |
var orParam = filters[orIndex], | |
facetValues = orParam.split(":"), | |
facet = facetValues[0], | |
values = facetValues[1]; | |
values = values.replace(/\(|\)/g, ""), values = values.split(" "); | |
for (var nameValue, fq = [], i = 0; i < filters.length; i++) nameValue = filters[i].split(":"), nameValue[0] === facet && i !== orIndex ? values.push(nameValue[1]) : i !== orIndex && fq.push(filters[i]); | |
fq.push(facet + ":" + values.join(" ")), params.fq = fq | |
} | |
} | |
} | |
var delay, observers = [], | |
deferred = $q.defer(); | |
return { | |
getSavedSearches: function() { | |
return _fetch() | |
}, | |
fetch: function(savedSearch) { | |
return _fetch(savedSearch.title) | |
}, | |
getParams: function(saved) { | |
saved.query = saved.query.replace(/\+/g, "%2B"); | |
var solrParams = querystring.parse(sugar.trim(saved.query, "&")); | |
delete solrParams.facet, delete solrParams["facet.field"], delete solrParams["facet.mincount"], delete solrParams["extent.bbox"], delete solrParams["f.format_category.facet.mincount"], delete solrParams["shards.info"], delete solrParams["shards.tolerant"], _decode(solrParams); | |
var voyagerParams; | |
voyagerParams = void 0 === saved.path ? querystring.parse(sugar.trim(saved.query.replace(/\//g, "&"), "&")) : querystring.parse(sugar.trim(saved.path.replace(/\//g, "&"), "&")), angular.isDefined(voyagerParams.catalog) && angular.isUndefined(solrParams.shards) && (solrParams.shards = _.isArray(voyagerParams.catalog) ? voyagerParams.catalog.join(",") : voyagerParams.catalog), angular.isDefined(solrParams.shards) && (solrParams.shards = catalogService.removeInvalid(solrParams.shards)), angular.isDefined(voyagerParams.bbox) && _applyBbox(solrParams, voyagerParams), angular.isDefined(voyagerParams.disp) && (solrParams.disp = voyagerParams.disp); | |
var view = _getView(voyagerParams, saved.display ? saved.display.defaultView : void 0); | |
if (solrParams.view = view.type, angular.isDefined(solrParams.sort)) { | |
var sort = solrParams.sort.split(" "); | |
solrParams.sort = sort[0].replace("_sort", ""), solrParams.sortdir = sort[1] | |
} | |
return solrParams | |
}, | |
addObserver: function(obs) { | |
var index = _.findIndex(observers, function(item) { | |
return obs === item | |
}); | |
index === -1 && observers.push(obs) | |
}, | |
removeObserver: function(observer) { | |
observers = _.without(observers, function(item) { | |
return item === observer | |
}) | |
}, | |
saveSearch: function(savedSearch, params) { | |
return savedSearch.config = configService.getConfigId(), _mergeOrFilters(params), savedSearch.path = converter.toClassicParams(params, !0), _doSave(savedSearch) | |
}, | |
deleteSearch: function(id) { | |
return $http.delete(config.root + "api/rest/display/ssearch/" + id).then(function() { | |
observers.forEach(function(entry) { | |
entry(id) | |
}) | |
}) | |
}, | |
showSaveSearchDialog: function(item) { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "src/saved-search/save-search-dialog.html", | |
size: "md", | |
controller: "SaveSearchDialog", | |
resolve: { | |
searchItem: function() { | |
return item | |
} | |
} | |
}); | |
modalInstance.result.then(function() {}, function() {}) | |
}, | |
showSearchModal: function(tab) { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "src/saved-search/saved-search-modal.html", | |
size: "lg", | |
controller: "SavedSearchModalCtrl", | |
resolve: { | |
tab: function() { | |
return tab | |
} | |
} | |
}); | |
modalInstance.result.then(function() {}, function() {}) | |
}, | |
applySavedSearch: function(saved, $scope) { | |
var currentView = $location.search().view, | |
solrParams = this.getParams(saved); | |
$scope.$emit("clearSearchEvent"), $location.search(solrParams), "/search" !== $location.path() && $location.path("/search"), configService.updateConfig(saved.display), filterService.applyFromUrl($location.search()).then(function() { | |
var params = {}; | |
"table" === solrParams.view && "table" === currentView && (params.refresh = !1), $timeout(function() { | |
$scope.$emit("filterEvent", params) | |
}) | |
}), $analytics.eventTrack("saved-search", { | |
category: "run" | |
}), this.addToRecent(saved) | |
}, | |
addToRecent: function(searchItem) { | |
var item = {}; | |
item.id = searchItem.id, item.title = searchItem.title, item.query = this.getParams(searchItem), item.query = sugar.toQueryStringEncoded(item.query), item.saved = !0, recentSearchService.addItem(item) | |
}, | |
order: function(id, beforeId, afterId) { | |
var data = ""; | |
return null !== beforeId && (data += "before=" + beforeId), "" !== data && (data += "&"), null !== afterId && (data += "after=" + afterId), sugar.postForm("api/rest/display/ssearch/" + id + "/order", data) | |
}, | |
sortSavedSearches: function(savedSearches) { | |
var global = [], | |
personal = [], | |
userHasSaveSearch = authService.hasPermission("save_search"), | |
authUser = authService.getUser(); | |
$.each(savedSearches, function(index, saved) { | |
authUser && userHasSaveSearch && saved.owner === authUser.name ? personal.push(saved) : global.push(saved) | |
}); | |
var sortedSavedSearches = { | |
global: global, | |
personal: personal | |
}; | |
return sortedSavedSearches | |
} | |
} | |
}), angular.module("voyager.search").controller("SaveSearchDialog", function($scope, $uibModalInstance, savedSearchService, $location, authService, $analytics, recentSearchService, searchItem, displayConfigResource, $q) { | |
function _loadGroups() { | |
$scope.canAdmin ? ($.merge(_shareGroups, _coreRoles), authService.fetchGroups().then(function(groups) { | |
$.merge(_shareGroups, groups) | |
})) : $scope.canShare && authService.getUserInfo().then(function(user) { | |
var groups = []; | |
_(user.groups).forEach(function(n) { | |
groups.push({ | |
id: n, | |
text: n | |
}) | |
}), $.merge(_shareGroups, groups) | |
}) | |
} | |
function _getPrivileges() { | |
authService.getPrivileges().then(function() { | |
$scope.canAdmin = authService.hasPermission("manage"), $scope.canSave = authService.hasPermission("save_search"), $scope.canShare = authService.hasPermission("share_saved_search"), _loadGroups() | |
}) | |
} | |
function _activate() { | |
_getPrivileges() | |
} | |
function _saveSearch(savedSearch) { | |
return savedSearchService.saveSearch(savedSearch, searchItem).then(function(response) { | |
$uibModalInstance.close(), $analytics.eventTrack("saved-search", { | |
category: "save" | |
}), recentSearchService.updateSearchID(searchItem, response.data), $scope.$emit("saveSearchSuccess", response.data) | |
}, function(error) { | |
console.log(error.data) | |
}) | |
} | |
$scope.savedSearch = { | |
query: searchItem.query | |
}; | |
var _shareGroups = [], | |
_coreRoles = [{ | |
id: "_EVERYONE", | |
text: "EVERYONE" | |
}, { | |
id: "_LOGGEDIN", | |
text: "LOGGEDIN" | |
}, { | |
id: "_ANONYMOUS", | |
text: "ANONYMOUS" | |
}], | |
_existingSearch = {}; | |
$scope.sharedOptions = { | |
multiple: !0, | |
tags: _shareGroups | |
}, _activate(), $scope.ok = function() { | |
if (!_.isEmpty($scope.savedSearch.title)) { | |
$scope.savedSearch.makeDefault && ($scope.savedSearch.order = (new Date).getTime()); | |
var savedSearchCopy = _.cloneDeep($scope.savedSearch); | |
savedSearchCopy.share = _.pluck(savedSearchCopy.share, "id"); | |
var promises = [savedSearchService.fetch(savedSearchCopy), displayConfigResource.getDisplayConfig($location.search().disp)]; | |
$q.all(promises).then(function(response) { | |
var docs = response[0], | |
dispConfig = response[1].data; | |
return 0 === docs.length || _.contains($scope.error, "Overwrite") ? (delete $scope.error, savedSearchCopy.labels = _existingSearch.labels, docs.length > 0 && (savedSearchCopy.id = docs[0].id), searchItem.view === dispConfig.defaultView.toLowerCase() && delete searchItem.view, _saveSearch(savedSearchCopy)) : void(docs[0].owner === authService.getUser().id || authService.hasPermission("manage") ? (_existingSearch = docs[0], $scope.error = "Saved Search exists. Overwrite?") : $scope.error = "Saved Search exists. You don't have permission to overwrite. Please rename your search.") | |
}) | |
} | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
}, $scope.hasPermission = function(permission) { | |
return authService.hasPermission(permission) | |
}, $scope.handleEnter = function(ev) { | |
delete $scope.error, 13 === ev.which && $scope.ok() | |
} | |
}), angular.module("voyager.search").directive("savedContent", function(authService) { | |
return { | |
restrict: "E", | |
templateUrl: "src/saved-content/saved-content-modal.html", | |
link: function(scope) { | |
function _syncState() { | |
scope.isAnonymous = authService.isAnonymous(), scope.canSave = authService.hasPermission("save_search") | |
} | |
scope.showSearch = !0, scope.showTab = scope.tab || "suggested", scope.showCategory = function($event, category) { | |
return $event.preventDefault(), "search" === category ? scope.showSearch || (scope.showSearch = !0, scope.showTab = scope.canSave ? "saved" : "suggested") : (scope.showSearch = !1, scope.showTab = scope.canSave ? "saved" : "suggested"), !1 | |
}, scope.changeTab = function(tab) { | |
scope.showTab !== tab && (scope.showTab = tab) | |
}, scope.cancel = function() { | |
scope.$dismiss() | |
}, scope.$on("filterChanged", function() { | |
scope.cancel() | |
}), scope.isAnonymous = authService.isAnonymous(), scope.canSave = authService.hasPermission("save_search"), authService.addObserver(_syncState), scope.$on("$destroy", function() { | |
authService.removeObserver(_syncState) | |
}) | |
} | |
} | |
}), angular.module("voyager.search").factory("savedLocationService", function(sugar, $http, configService, $q, authService, $location, $analytics, filterService, converter) { | |
"use strict"; | |
function _doSave(request) { | |
if (configService.hasChanges()) { | |
var deferred = $q.defer(); | |
return sugar.postJson(configService.getUpdatedSettings(), "display", "config").then(function(response) { | |
request.config = response.data.id, request.query += "/disp=" + request.config, request.path = request.query, sugar.postJson(request, "display", "slocation").then(function(savedResponse) { | |
deferred.resolve() | |
}, function(error) { | |
deferred.reject(error) | |
}) | |
}, function(error) { | |
deferred.reject(error) | |
}), deferred.promise | |
} | |
return request.query += "/disp=" + request.config, request.path = request.query, sugar.postJson(request, "display", "slocation") | |
} | |
function _getQueryString() { | |
var rows = 150, | |
queryString = config.root + "solr/slocation/select?"; | |
return queryString += "rows=" + rows + "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _execute(url) { | |
return $http.jsonp(url).then(function(data) { | |
return data.data ? data.data.response.docs : [] | |
}, function(error) { | |
return console.log(error), error | |
}) | |
} | |
function _getSearchResult(term) { | |
var rows = 150, | |
queryString = config.root + "solr/slocation/select?"; | |
return queryString += "fq=name:" + term, queryString += "&fl=name", queryString += "&rows=" + rows + "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
var observers = []; | |
return { | |
getSavedLocations: function() { | |
return _execute(_getQueryString()) | |
}, | |
searchByTerm: function(term) { | |
return _execute(_getSearchResult(term)) | |
}, | |
getParams: function(saved) { | |
return querystring.parse(sugar.trim(saved.value.replace(/\//g, "&"), "&")) | |
}, | |
addObserver: function(obs) { | |
var index = _.findIndex(observers, function(item) { | |
return obs === item | |
}); | |
index === -1 && observers.push(obs) | |
}, | |
removeObserver: function(obs) { | |
observers = _.without(observers, function(item) { | |
return obs === item | |
}) | |
}, | |
saveLocation: function(SavedLocation, params) { | |
return SavedLocation.config = configService.getConfigId(), SavedLocation.value = converter.toClassicParams(params), _doSave(SavedLocation) | |
}, | |
applySavedLocation: function(saved, $scope) { | |
var solrParams = this.getParams(saved); | |
$scope.$emit("clearSearchEvent"), $location.path("search").search(solrParams), filterService.applyFromUrl($location.search()).then(function() { | |
$scope.$emit("filterEvent", {}) | |
}) | |
}, | |
deleteLocation: function(id) { | |
return $http.delete(config.root + "api/rest/display/slocation/" + id).then(function() { | |
observers.forEach(function(entry) { | |
entry(id) | |
}) | |
}) | |
}, | |
order: function(id, beforeId, afterId) { | |
var data = ""; | |
return null !== beforeId && (data += "before=" + beforeId), "" !== data && (data += "&"), null !== afterId && (data += "after=" + afterId), sugar.postForm("api/rest/display/slocation/" + id + "/order", data) | |
} | |
} | |
}), angular.module("voyager.search").directive("vsSaveLocationDialog", function(authService, $location, savedLocationService) { | |
return { | |
restrict: "E", | |
templateUrl: "src/saved-location/save-location-dialog.html", | |
link: function(scope) { | |
function _loadGroups() { | |
scope.canAdmin && ($.merge(_shareGroups, _coreRoles), authService.fetchGroups().then(function(groups) { | |
$.merge(_shareGroups, groups) | |
})) | |
} | |
function _getPrivileges() { | |
authService.getPrivileges().then(function() { | |
scope.canAdmin = authService.hasPermission("manage"), _loadGroups() | |
}) | |
} | |
function _activate() { | |
_getPrivileges() | |
} | |
scope.savedLocation = {}, scope.error = !1; | |
var _shareGroups = [], | |
_coreRoles = [{ | |
id: "_EVERYONE", | |
text: "EVERYONE" | |
}, { | |
id: "_LOGGEDIN", | |
text: "LOGGEDIN" | |
}, { | |
id: "_ANONYMOUS", | |
text: "ANONYMOUS" | |
}]; | |
scope.sharedOptions = { | |
multiple: !0, | |
simple_tags: !0, | |
data: function() { | |
return { | |
results: _shareGroups | |
} | |
} | |
}, scope.hasError = function() { | |
return scope.error !== !1 | |
}, _activate(), scope.ok = function() { | |
if (!_.isEmpty(scope.savedLocation.name)) { | |
var params = {}; | |
if ("Place" === scope.selectedMapType) { | |
if (!_.isEmpty(scope.search.location)) { | |
params.place = scope.search.location; | |
var placeId = $location.search()["place.id"]; | |
angular.isDefined(placeId) && (params["place.id"] = placeId), params["place.op"] = scope.selectedDrawingType.toLowerCase() | |
} | |
} else void 0 !== scope.search.place && (params.place = scope.search.place, params["place.op"] = scope.selectedDrawingType.toLowerCase()); | |
savedLocationService.saveLocation(scope.savedLocation, params).then(function(response) { | |
angular.isDefined(response.data.error) ? scope.error = response.data.error : (scope.$dismiss(), scope.error = !1) | |
}, function() { | |
scope.error = "please try again later" | |
}) | |
} | |
}, scope.cancel = function() { | |
scope.$dismiss() | |
} | |
} | |
} | |
}), angular.module("voyager.search").controller("SavedLocationsCtrl", function($scope, $location, savedLocationService, authService) { | |
function _loadSavedLocations() { | |
savedLocationService.getSavedLocations().then(function(savedLocations) { | |
var permissions, global = [], | |
personal = [], | |
all = "_EVERYONE"; | |
$.each(savedLocations, function(index, saved) { | |
if (permissions = _.indexBy(saved.share), angular.isDefined(permissions[all]) ? global.push(saved) : personal.push(saved), 6 === global.length && 6 === personal.length) return !1 | |
}), vm.savedLocations = global, vm.personalSavedLocations = personal | |
}) | |
} | |
var vm = this; | |
_loadSavedLocations(), authService.addObserver(_loadSavedLocations), savedLocationService.addObserver(_loadSavedLocations), vm.applySavedLocation = function(saved) { | |
savedLocationService.applySavedLocation(saved, $scope) | |
}, vm.deleteLocation = function(id) { | |
savedLocationService.deleteLocation(id) | |
}, vm.search = function() { | |
return _.isEmpty(vm.savedTerm) ? void _loadSavedLocations() : void savedLocationService.searchByTerm(vm.savedTerm).then(function(savedLocations) { | |
var permissions, personal = [], | |
all = "_EVERYONE"; | |
$.each(savedLocations, function(index, saved) { | |
permissions = _.indexBy(saved.share), angular.isDefined(permissions[all]) || personal.push(saved) | |
}), vm.personalSavedLocations = personal | |
}) | |
}, vm.dragLocationControlListeners = { | |
enabled: !0, | |
accept: function() { | |
return vm.dragLocationControlListeners.enabled | |
}, | |
orderChanged: function(eventObj) { | |
var list = vm.personalSavedLocations, | |
index = eventObj.dest.index, | |
beforeId = null, | |
afterId = null; | |
0 !== index && (beforeId = list[index - 1].id), index + 1 !== list.length && (afterId = list[index + 1].id), vm.dragLocationControlListeners.enabled = !1, savedLocationService.order(list[index].id, beforeId, afterId).then(function() { | |
vm.dragLocationControlListeners.enabled = !0 | |
}) | |
} | |
}, $scope.$on("$destroy", function() { | |
authService.removeObserver(_loadSavedLocations), savedLocationService.removeObserver(_loadSavedLocations) | |
}) | |
}), angular.module("voyager.search").factory("recentSearchService", function(localStorageService, $location, filterService, mapUtil, sugar) { | |
"use strict"; | |
var RECENT_ITEM_NAME = "recent-items", | |
observers = [], | |
_notify = function(itemMap) { | |
observers.forEach(function(entry) { | |
entry(itemMap) | |
}) | |
}, | |
_getItems = function() { | |
var items = localStorageService.get(RECENT_ITEM_NAME); | |
return items ? items : [] | |
}, | |
_formatQuery = function(item) { | |
var query = []; | |
for (var i in item) "saved" !== i && i.indexOf("$") === -1 && i.indexOf("display") === -1 && query.push(i + "=" + item[i]); | |
return query.join("&") | |
}; | |
return { | |
addItem: function(item) { | |
var itemMap = _getItems(), | |
duplicate = !1; | |
if (!(_.isEmpty(item.q) && _.isEmpty(item.query) && _.isEmpty(item.place) && _.isEmpty(item.bbox))) { | |
if (itemMap.length) | |
for (var i = 0, t = itemMap.length; i < t; i++) | |
if (void 0 === item.q) { | |
if (angular.isDefined(item.place) && itemMap[i].place === item.place || angular.isDefined(item.bbox) && itemMap[i].bbox === item.bbox) { | |
duplicate = !0, itemMap[i] = item; | |
break | |
} | |
} else if (item.q === itemMap[i].q) { | |
if (angular.isDefined(item.place) && itemMap[i].place === item.place || angular.isDefined(item.bbox) && itemMap[i].bbox === item.bbox) { | |
duplicate = !0, itemMap[i] = item; | |
break | |
} | |
if (!angular.isDefined(item.place) && !angular.isDefined(item.bbox)) { | |
duplicate = !0, itemMap[i] = item; | |
break | |
} | |
} else if (itemMap[i].query && (itemMap[i].query.indexOf(item.q) !== -1 || itemMap[i].query.indexOf(encodeURIComponent(item.q)) !== -1) && item.q && item.q.indexOf("!func") !== -1) { | |
duplicate = !0; | |
break | |
} | |
duplicate || (itemMap.length > 5 && itemMap.pop(), itemMap.splice(0, 0, item)), localStorageService.add(RECENT_ITEM_NAME, itemMap), _notify(itemMap) | |
} | |
}, | |
getItems: function() { | |
return _getItems() | |
}, | |
deleteSearch: function(inx) { | |
var itemMap = _getItems(); | |
itemMap.splice(inx, 1), localStorageService.add(RECENT_ITEM_NAME, itemMap), _notify(itemMap) | |
}, | |
addObserver: function(observer) { | |
observers.push(observer) | |
}, | |
removeObserver: function(observer) { | |
observers = _.without(observers, function(item) { | |
return item === observer | |
}) | |
}, | |
changeSaveStatus: function(id) { | |
for (var itemMap = _getItems(), i = 0, t = itemMap.length; i < t; i++) | |
if (itemMap[i].id === id) { | |
itemMap[i].saved = !itemMap[i].saved; | |
break | |
} | |
localStorageService.add(RECENT_ITEM_NAME, itemMap), _notify(itemMap) | |
}, | |
updateSearchID: function(searchItem, data) { | |
for (var isFound, itemMap = _getItems(), i = 0, totalItemMapLength = itemMap.length; i < totalItemMapLength; i++) { | |
isFound = !0; | |
for (var attr in searchItem) attr.indexOf("$") !== -1 || attr.indexOf("display") !== -1 || "fq" === attr || searchItem[attr] === itemMap[i][attr] || (isFound = !1); | |
if (isFound) break | |
} | |
isFound && (itemMap[i].id = data.id, itemMap[i].title = data.title, itemMap[i].saved = !0, localStorageService.add(RECENT_ITEM_NAME, itemMap), _notify(itemMap)) | |
}, | |
syncWithSavedSearches: function(savedSearches) { | |
for (var savedSearchInx, found, itemMap = _getItems(), i = 0, totalItemMapLength = itemMap.length, savedSearchLength = savedSearches.length; i < totalItemMapLength; i++) { | |
for (found = !1, savedSearchInx = 0; savedSearchInx < savedSearchLength; savedSearchInx++) | |
if (itemMap[i].id === savedSearches[savedSearchInx].id) { | |
found = !0; | |
break | |
} | |
itemMap[i].saved = !!found | |
} | |
localStorageService.add(RECENT_ITEM_NAME, itemMap) | |
}, | |
getItemsWithFormatBBox: function() { | |
for (var itemMap = _getItems(), i = 0, totalItemMapLength = itemMap.length; i < totalItemMapLength; i++) mapUtil.isBbox(itemMap[i].place) ? itemMap[i].displayBBox = sugar.formatBBox(itemMap[i].place) : _.isEmpty(itemMap[i].place) || (itemMap[i].displayBBox = mapUtil.formatWktForDisplay(itemMap[i].place)), itemMap[i].displayPlaceOP = itemMap[i]["place.op"]; | |
return itemMap | |
}, | |
applyRecentSearch: function(item, $scope) { | |
var query = ""; | |
query = _.isEmpty(item.query) ? _formatQuery(item) : item.query, $scope.$emit("clearSearchEvent"), $location.path("search").search(query).search("recent", "true"), filterService.applyFromUrl($location.search()).then(function() { | |
$scope.$emit("filterEvent", {}) | |
}) | |
} | |
} | |
}), angular.module("voyager.search").controller("RecentSearchCtrl", function($scope, recentSearchService, savedSearchService, $timeout, authService) { | |
"use strict"; | |
function _init() { | |
savedSearchService.getSavedSearches().then(function(respond) { | |
recentSearchService.syncWithSavedSearches(respond), _getRecentSearch() | |
}), recentSearchService.addObserver(_getRecentSearch), savedSearchService.addObserver(_changeSearchStatus) | |
} | |
function _getRecentSearch() { | |
$timeout(function() { | |
$scope.recentSearches = recentSearchService.getItemsWithFormatBBox() | |
}, 10) | |
} | |
function _toggleSaveStatus(item) { | |
item.saved ? savedSearchService.deleteSearch(item.id) : savedSearchService.showSaveSearchDialog(item) | |
} | |
function _changeSearchStatus(id) { | |
recentSearchService.changeSaveStatus(id), _getRecentSearch() | |
} | |
function _deleteSearchByIndex(id) { | |
recentSearchService.deleteSearch(id) | |
} | |
function _openSearchModal() { | |
savedSearchService.showSearchModal("recent") | |
} | |
function _applyRecentSearch(searchItem) { | |
recentSearchService.applyRecentSearch(searchItem, $scope), "function" == typeof $scope.cancel && $scope.cancel() | |
} | |
$scope.toggleSave = _toggleSaveStatus, $scope.deleteSearch = _deleteSearchByIndex, $scope.openSearchModal = _openSearchModal, $scope.applyRecentSearch = _applyRecentSearch, $scope.hasPermission = function(permission) { | |
return authService.hasPermission(permission) | |
}, _init(), $scope.$on("$destroy", function() { | |
recentSearchService.removeObserver(_getRecentSearch), savedSearchService.removeObserver(_changeSearchStatus) | |
}) | |
}), angular.module("voyager.search").controller("BaseUpdateCtrl", function($scope, $uibModalInstance, tagService, resultTotalCount, $timeout, usSpinnerService, config) { | |
var _loading = !1; | |
$scope.hasError = function() { | |
return angular.isDefined($scope.error) | |
}, $scope.resultTotalCount = resultTotalCount, $scope.overLimit = resultTotalCount > config.bulkLimit, $scope.overLimit && ($scope.error = "This operation is limited to " + config.bulkLimit + " records. Please refine your search."), $scope.validate = function() { | |
return !0 | |
}, $scope.save = function() { | |
$scope.validate() && (delete $scope.error, _loading = !0, usSpinnerService.spin("task-spinner"), $scope.doSaveAll()) | |
}, $scope.handleEnter = function(ev) { | |
13 !== ev.which || _loading || $scope.save() | |
}, $scope.handleResponse = function(response) { | |
_loading = !1, usSpinnerService.stop("task-spinner"), angular.isUndefined(response.error) ? ($scope.successMessage = response.documents + " items were updated.", $timeout(function() { | |
$scope.done() | |
}, 2e3)) : $scope.error = "Sorry, please try again later" | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel"), $scope.successMessage = !1 | |
}, $scope.done = function() { | |
$uibModalInstance.close() | |
} | |
}), angular.module("voyager.search").controller("FlagAllCtrl", function($scope, $uibModalInstance, tagService, resultData, $controller) { | |
function _init() { | |
tagService.fetchFlags().then(function(tags) { | |
$.merge(_tags, tags) | |
}) | |
} | |
$controller("BaseUpdateCtrl", { | |
$scope: $scope, | |
resultTotalCount: resultData.totalItemCount, | |
$uibModalInstance: $uibModalInstance | |
}); | |
var _tags = []; | |
$scope.select2Options = { | |
tags: _tags | |
}, _init(), $scope.validate = function() { | |
return !_.isEmpty($scope.flag) || ($scope.error = "Enter a flag.", !1) | |
}, $scope.doSaveAll = function() { | |
tagService.saveBulkField($scope.flag, "tag_flags", resultData.docId).then($scope.handleResponse) | |
} | |
}), angular.module("voyager.search").controller("EditAllCtrl", function($scope, $uibModalInstance, tagService, configService, resultTotalCount, $controller, config, converter) { | |
function _init() { | |
tagService.fetchTags().then(function(tags) { | |
$.merge(_tags, tags) | |
}), _getFieldList() | |
} | |
function _getFieldList() { | |
$scope.fieldList = configService.getEditable() | |
} | |
$controller("BaseUpdateCtrl", { | |
$scope: $scope, | |
resultTotalCount: resultTotalCount, | |
$uibModalInstance: $uibModalInstance | |
}); | |
var _tags = []; | |
$scope.select2Options = { | |
multiple: !0, | |
simple_tags: !0 | |
}, _.isEmpty(config.homepage.editValues) ? $scope.select2Options.tags = _tags : $scope.select2Options.data = converter.toIdTextArray(config.homepage.editValues), _init(), $scope.validate = function() { | |
return !_.isEmpty($scope.fieldText) && !_.isEmpty($scope.selectedField) || ($scope.error = "Please select a field and enter a value.", !1) | |
}, $scope.doSaveAll = function() { | |
tagService.saveBulkField($scope.fieldText, $scope.selectedField).then($scope.handleResponse) | |
} | |
}), angular.module("voyager.search").controller("RemoveAllFlagsCtrl", function($scope, $uibModalInstance, tagService, resultData, $timeout, usSpinnerService, config, $controller) { | |
$controller("BaseUpdateCtrl", { | |
$scope: $scope, | |
resultTotalCount: resultData.totalItemCount, | |
$uibModalInstance: $uibModalInstance | |
}), $scope.doSaveAll = function() { | |
tagService.removeBulkField("tag_flags").then($scope.handleResponse) | |
} | |
}), angular.module("voyager.filters", ["voyager.util", "ui-rangeSlider", "voyager.config", "blockUI"]).config(function(blockUIConfig) { | |
blockUIConfig.delay = 300, blockUIConfig.requestFilter = function(config) { | |
return config.url.indexOf("block=false") === -1 && ((!config.params || config.params.block !== !1) && (config.url.indexOf("api/rest") === -1 && void 0)) | |
} | |
}), angular.module("voyager.filters").factory("catalogService", function(config, $http, $location, $q) { | |
function _fetch() { | |
return _fetched ? $q.when(_cachedCatalogs) : $http.get(config.root + "api/rest/index/config/federation.json").then(function(res) { | |
var catalogs = res.data.servers; | |
return catalogs.forEach(function(catalog) { | |
angular.isDefined(catalog.url) && (_catalogLookup[catalog.url.replace("http://", "").replace("https://", "")] = catalog) | |
}), _cachedCatalogs = res.data.servers, _fetched = !0, res.data.servers | |
}) | |
} | |
function _loadRemoteLocations() { | |
return "/search" === $location.path() && (angular.isDefined($location.search().shards) || config.settings.data.queryAllCatalogs) ? _fetch().then(function(catalogs) { | |
var catalogPromises = []; | |
return _.each(catalogs, function(catalog) { | |
if (angular.isDefined(catalog.url)) { | |
var url = catalog.url + config.require.locations, | |
catalogPromise = $http.get(url, { | |
withCredentials: !1 | |
}).then(function(response) { | |
_.extend(config.locations.data.VALUE.location, response.data.VALUE.location); | |
}); | |
catalogPromises.push(catalogPromise) | |
} | |
}), $q.all(catalogPromises).then(function(res) { | |
return res | |
}, function(error) { | |
return error | |
}) | |
}) : $q.when({}) | |
} | |
function _lookup(shard) { | |
var catalog = shard.replace("http://", "").replace("https://", "").toLowerCase(), | |
pos = catalog.indexOf("solr"); | |
return pos > -1 && (catalog = catalog.substring(0, pos)), _catalogLookup[catalog] | |
} | |
function _isRemote(shard) { | |
return angular.isDefined(_lookup(shard)) | |
} | |
function _removeInvalid(shards) { | |
var arr = shards.split(","), | |
valid = arr.filter(function(shard) { | |
return _.findIndex(_cachedCatalogs, { | |
id: shard | |
}) !== -1 | |
}); | |
return valid.join(",") | |
} | |
var _catalogLookup = {}, | |
_cachedCatalogs = [], | |
_fetched = !1; | |
return { | |
fetch: _fetch, | |
loadRemoteLocations: _loadRemoteLocations, | |
isRemote: _isRemote, | |
removeInvalid: _removeInvalid, | |
lookup: _lookup | |
} | |
}), angular.module("voyager.filters").factory("statsService", function(config, $http, configService, translateService, $q, solrGrunt, sugar) { | |
function _getStatsParams() { | |
var configFilters = configService.getFilters(), | |
facetParams = ""; | |
return $.each(configFilters, function(index, filter) { | |
"STATS" === filter.style && (facetParams += "&stats.field=" + filter.field) | |
}), facetParams | |
} | |
function _hasStatsParam() { | |
var configFilters = configService.getFilters(), | |
hasStats = !1; | |
return $.each(configFilters, function(index, filter) { | |
if ("STATS" === filter.style) return hasStats = !0, !1 | |
}), hasStats | |
} | |
function _getQueryString(params, filterParams, bboxParams) { | |
var solrParams = solrGrunt.getSolrParams(params); | |
delete solrParams.fq, solrParams.q = solrGrunt.getInput(solrParams.q); | |
var queryString = config.root + "solr/v0/select?rows=0&stats=true" + _getStatsParams(); | |
return queryString += "&" + sugar.toQueryString(solrParams), queryString += filterParams, queryString += bboxParams, angular.isDefined(configService.getConfigId()) && (queryString += "&voyager.config.id=" + configService.getConfigId()), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _setStats(params, filterParams, bboxParams) { | |
var deferred = $q.defer(); | |
return _hasStatsParam() ? $http.jsonp(_getQueryString(params, filterParams, bboxParams)).success(function(data) { | |
_stats = data.stats.stats_fields, deferred.resolve(_stats) | |
}) : deferred.resolve(null), deferred.promise | |
} | |
function _parseInt(val) { | |
var ret = 0; | |
return angular.isDefined(val) && (ret = parseInt(val)), ret | |
} | |
var _stats = {}, | |
_statsFields = {}; | |
return { | |
updateStats: function(params, filterParams, bboxParams, filters) { | |
_setStats(params, filterParams, bboxParams).then(function(stats) { | |
null !== stats && $.each(filters, function(index, filter) { | |
"STATS" === filter.style && $.each(filter.values, function(i, facet) { | |
facet.stddev = _parseInt(stats[filter.field].stddev), facet.sum = _parseInt(stats[filter.field].sum), facet.mean = _parseInt(stats[filter.field].mean) | |
}) | |
}) | |
}) | |
}, | |
setStatsFields: function(statsFields) { | |
_statsFields = statsFields | |
} | |
} | |
}), angular.module("voyager.filters").factory("treeService", function(config, $http, configService, $q, solrGrunt, sugar, facetService, catalogService) { | |
function _isHierarchy(filter) { | |
return "HIERARCHY" === filter.style || "hierarchy" === filter.stype | |
} | |
function _getTreeParams() { | |
var configFilters = configService.getFilters(), | |
facetParams = ""; | |
return $.each(configFilters, function(index, filter) { | |
_isHierarchy(filter) && (facetParams += "&facet.field=" + filter.field + "&f." + filter.field + ".facet.mincount=1&f." + filter.field + ".facet.prefix=%s/", _trees[filter.field] = {}) | |
}), facetParams | |
} | |
function _hasTreeParam() { | |
var configFilters = configService.getFilters(), | |
hasTree = !1; | |
return $.each(configFilters, function(index, filter) { | |
if (_isHierarchy(filter)) return hasTree = !0, !1 | |
}), hasTree | |
} | |
function _getQueryString(params, filterParams, bboxParams) { | |
var solrParams = solrGrunt.getSolrParams(params); | |
angular.isDefined(solrParams.shards) && (solrParams.shards = catalogService.removeInvalid(solrParams.shards)), delete solrParams.fq, solrParams.q = solrGrunt.getInput(solrParams.q); | |
var queryString = config.root + "solr/v0/select?rows=0&block=false&facet=true" + _getTreeParams(); | |
return queryString += "&" + sugar.toQueryString(solrParams), queryString += filterParams, queryString += bboxParams, angular.isDefined(configService.getConfigId()) && (queryString += "&voyager.config.id=" + configService.getConfigId()), queryString += "&wt=json&json.wrf=JSON_CALLBACK", queryString += "&rand=" + Math.random() | |
} | |
function _getSelectedLevel(params) { | |
var paths, level = 0; | |
if (params.fq && (paths = _.filter(sugar.toArray(params.fq), function(f) { | |
return f.indexOf("path_path") > -1 | |
}), paths.length > 0)) { | |
var path = paths[0]; | |
path = path.replace(/\\/g, ""), level = path.split("/").length | |
} | |
return level | |
} | |
function _queryLevels(queryString, level) { | |
var deferred = $q.defer(), | |
promises = [], | |
level1 = "1", | |
level2 = "2"; | |
level > 0 && (level1 = level.toString(), level2 = (level + 1).toString()); | |
var queryLevel = queryString.replace(/%s/g, level1), | |
queryLevel2 = queryString.replace(/%s/g, level2), | |
queries = [queryLevel, queryLevel2]; | |
return $.each(queries, function(index, query) { | |
promises.push($http.jsonp(query)) | |
}), $q.all(promises).then(function(response) { | |
$.each(_trees, function(name) { | |
var raw = response[0].data.facet_counts.facet_fields[name], | |
tree = facetService.buildFacets(raw, { | |
field: name, | |
style: "HIERARCHY" | |
}, {}); | |
raw = response[1].data.facet_counts.facet_fields[name]; | |
var next = facetService.buildFacets(raw, { | |
field: name, | |
style: "HIERARCHY" | |
}, {}); | |
$.merge(tree, next), _trees[name] = tree | |
}), deferred.resolve(_trees) | |
}, function() { | |
console.log("failed"), deferred.reject() | |
}), deferred.promise | |
} | |
function _queryNodeLevels(queryString, name, level, path) { | |
var deferred = $q.defer(), | |
promises = [], | |
level1 = level.toString() + "/" + path, | |
level2 = (level + 1).toString() + "/" + path, | |
queryLevel = queryString.replace(/%s/g, level1), | |
queryLevel2 = queryString.replace(/%s/g, level2), | |
queries = [queryLevel, queryLevel2]; | |
return $.each(queries, function(index, query) { | |
promises.push($http.jsonp(query)) | |
}), $q.all(promises).then(function(response) { | |
var raw = response[0].data.facet_counts.facet_fields[name], | |
tree = facetService.buildFacets(raw, { | |
field: name, | |
style: "HIERARCHY" | |
}, {}); | |
raw = response[1].data.facet_counts.facet_fields[name]; | |
var next = facetService.buildFacets(raw, { | |
field: name, | |
style: "HIERARCHY" | |
}, {}); | |
$.merge(tree, next), deferred.resolve(tree) | |
}, function() { | |
console.log("failed"), deferred.reject() | |
}), deferred.promise | |
} | |
function _setTree(params, filterParams, bboxParams) { | |
_trees = {}; | |
var deferred = $q.defer(); | |
if (_hasTreeParam()) { | |
var level = _getSelectedLevel(params), | |
queryString = _getQueryString(params, filterParams, bboxParams); | |
_queryLevels(queryString, level).then(function() { | |
deferred.resolve() | |
}) | |
} else deferred.resolve(null); | |
return deferred.promise | |
} | |
function _addChild(folder, nodes, collapsed, field) { | |
var child = nodes[folder.path]; | |
angular.isUndefined(child) && (child = { | |
level: folder.level, | |
root: folder.node[0], | |
path: folder.path, | |
children: [], | |
childMap: {}, | |
mime: "application/vnd.voyager.folder", | |
id: folder.path, | |
collapsed: !0, | |
field: field | |
}, nodes[child.path] = child), angular.isUndefined(nodes[folder.parentPath].childMap[child.path]) && (nodes[folder.parentPath].children.push(child), nodes[folder.parentPath].childMap[child.path] = child), nodes[folder.parentPath].collapsed === !0 && (nodes[folder.parentPath].collapsed = collapsed) | |
} | |
function _getFolder(row, index) { | |
var folder = {}; | |
return folder.level = row[0], folder.node = row.slice(1, index + 1), folder.name = folder.node[folder.node.length - 1], folder.path = folder.node.join("/"), folder.parent = row.slice(1, index), folder.parentPath = folder.parent.join("/"), folder | |
} | |
function _getPathInfo(path) { | |
var pathInfo = {}; | |
return pathInfo.value = path.value.replace(/\\/g, "/"), pathInfo.name = path.name.replace(/\\/g, "/"), pathInfo.folders = pathInfo.name.split("/"), pathInfo.level = pathInfo.folders.length - 1, pathInfo.display = pathInfo.value.substring(pathInfo.value.lastIndexOf("/") + 1, pathInfo.value.length), pathInfo.path = pathInfo.name.substring(pathInfo.name.indexOf("/") + 1, pathInfo.name.length), pathInfo.count = path.count, pathInfo | |
} | |
function _getNode(pathInfo, selected, field) { | |
var node = { | |
level: pathInfo.level, | |
root: pathInfo.folders[1], | |
path: pathInfo.path, | |
children: [], | |
display: pathInfo.display, | |
childMap: {}, | |
mime: "application/vnd.voyager.folder", | |
id: pathInfo.path, | |
collapsed: !0, | |
field: field | |
}; | |
return angular.isDefined(selected[node.path]) && (node.selected = !0), node | |
} | |
function _getParentNode(folder, field, pathInfo) { | |
var parentNode = { | |
level: folder.parent.length, | |
root: folder.parent[0], | |
path: folder.parentPath, | |
children: [], | |
childMap: {}, | |
mime: "application/vnd.voyager.folder", | |
id: folder.parentPath, | |
collapsed: !0, | |
field: field | |
}, | |
name = parentNode.path; | |
return name.indexOf("/") !== -1 && (name = name.split("/"), name = name[name.length - 1]), parentNode.display = name + " (" + pathInfo.count + ")", parentNode | |
} | |
function _buildStructure(pathList, selected, field) { | |
var pathInfo, nodes = {}; | |
return $.each(pathList, function(index, path) { | |
pathInfo = _getPathInfo(path); | |
var node = _getNode(pathInfo, selected, field); | |
nodes[pathInfo.path] = node; | |
for (var i = pathInfo.folders.length - 1; i > 1; i--) { | |
var folder = _getFolder(pathInfo.folders, i); | |
if (angular.isDefined(nodes[folder.parentPath])) _addChild(folder, nodes, !node.selected, field); | |
else { | |
var parentNode = _getParentNode(folder, field, pathInfo); | |
nodes[parentNode.path] = parentNode, angular.isDefined(selected[parentNode.path]) && (parentNode.selected = !0), parentNode.children.push(nodes[folder.path]), parentNode.childMap[folder.path] = nodes[folder.path] | |
} | |
} | |
}), nodes | |
} | |
function _getSelected(filters) { | |
var selected = {}; | |
return filters = sugar.toArray(filters), angular.isDefined(filters) && $.each(filters, function(key, value) { | |
if (value.indexOf("path_path") !== -1) { | |
var path = value.split(":")[1].replace(/\\/g, ""); | |
selected[path] = path | |
} | |
}), selected | |
} | |
function _getNodesToExpand(name) { | |
var path = name.split("/"), | |
key = null, | |
expanded = []; | |
return $.each(path, function(index, node) { | |
key = null === key ? node : key + "/" + node, expanded.push(key) | |
}), expanded | |
} | |
var _tree = {}, | |
_fields = {}, | |
_trees = {}; | |
return { | |
updateTree: function(params, filterParams, bboxParams, filters) { | |
var self = this; | |
_setTree(params, filterParams, bboxParams).then(function() { | |
_.isEmpty(_trees) || $.each(filters, function(index, filter) { | |
if (_isHierarchy(filter)) { | |
var structure = _buildStructure(_trees[filter.field], _getSelected(params.fq), filter.field), | |
expanded = []; | |
$.each(structure, function(name, node) { | |
node.selected && !node.loaded && (expanded = expanded.concat(_getNodesToExpand(name)), self.loadNode(params, filterParams, bboxParams, filters, node)) | |
}), $.each(expanded, function(index, node) { | |
structure[node].collapsed = !1 | |
}); | |
var tree = _.where(structure, { | |
level: 1 | |
}); | |
void 0 === filter.style && (filter.style = "HIERARCHY"), filter.values = [{ | |
tree: tree, | |
filter: filter.field, | |
style: filter.style | |
}] | |
} | |
}) | |
}) | |
}, | |
loadNode: function(params, filterParams, bboxParams, filters, node) { | |
node.loaded = !0; | |
var queryString = _getQueryString(params, filterParams, bboxParams); | |
_queryNodeLevels(queryString, node.field, node.level + 1, node.path).then(function(data) { | |
var structure = _buildStructure(data, _getSelected(params.fq), node.field), | |
children = _.where(structure, { | |
level: node.level + 1 | |
}); | |
node.children = children | |
}) | |
}, | |
setTreeFields: function(fields) { | |
_fields = fields | |
}, | |
getTree: function(filter) { | |
return _tree[filter] | |
} | |
} | |
}), angular.module("voyager.filters").factory("complexFilterService", function() { | |
function _createComplexFilter(filterField, filterValue, filterValues) { | |
var complexFilter = { | |
field: filterField, | |
value: filterValue, | |
values: [], | |
style: _complexFilterStyle | |
}; | |
return _updateComplexFilter(complexFilter, filterValue, filterValues) | |
} | |
function _updateComplexFilter(filter, filterValue, filterValues) { | |
return filterValue && (filter.value = filterValue), filterValues && (filter.values = filterValues), filter | |
} | |
function _calculateIsSelected(facet, selectedFilters) { | |
var isSelected = !0; | |
return $.each(facet.name, function(index, facetName) { | |
var facetFilter = facet.filter[index]; | |
isSelected = isSelected && !!selectedFilters[facetName] && selectedFilters[facetName].filter === facetFilter | |
}), isSelected | |
} | |
var _complexFilterStyle = "COMPLEX", | |
_discoveryStatusFilter_Field = "discoveryStatus", | |
_discoveryStatusFilter_Value = "Discovery Status", | |
_discoveryStatusFilter_Values = [{ | |
name: ["(SCAN SCAN_FULL)", "false"], | |
value: "First Pass: Scan Complete", | |
filter: ["_index_reason", "__to_extract"], | |
humanized: "1st Pass: Scan Complete", | |
count: 0, | |
hasCount: !1, | |
display: "1st Pass: Scan Complete", | |
style: "COMPLEX" | |
}, { | |
name: ["true"], | |
value: "Second Pass: Read Pending", | |
filter: ["__to_extract"], | |
humanized: "nd Pass: Read Pending", | |
count: 0, | |
hasCount: !1, | |
display: "2nd Pass: Read Pending", | |
style: "COMPLEX" | |
}, { | |
name: ["CHECKOUT", "false"], | |
value: "Second Pass: Read Complete", | |
filter: ["_index_reason", "__to_extract"], | |
humanized: "2nd Pass: Read Complete", | |
count: 0, | |
hasCount: !1, | |
display: "2nd Pass: Read Complete", | |
style: "COMPLEX" | |
}]; | |
return { | |
calculateIsSelected: function(facet, selectedFilters) { | |
return _calculateIsSelected(facet, selectedFilters) | |
}, | |
createDiscoveryStatusFilter: function(discoveryStatusFilter, facetTypes) { | |
discoveryStatusFilter ? _updateComplexFilter(discoveryStatusFilter, _discoveryStatusFilter_Value, _discoveryStatusFilter_Values) : (discoveryStatusFilter = _createComplexFilter(_discoveryStatusFilter_Field, _discoveryStatusFilter_Value, _discoveryStatusFilter_Values), facetTypes.unshift(discoveryStatusFilter)) | |
} | |
} | |
}), angular.module("voyager.filters").directive("vsFilter", function($compile) { | |
function _link(scope, element) { | |
var template = ""; | |
template = "date" === scope.facet.stype ? date : "CHECK" === scope.facet.style ? checkbox : "RANGE" === scope.facet.style ? scope.facet.units ? unitslider : nounitslider : "STATS" === scope.facet.style ? nounitslider + stats : "HIERARCHY" === scope.facet.style ? tree : button, element.html(template).show(), $compile(element.contents())(scope) | |
} | |
function _controller($scope, config) { | |
$scope.imagePrefix = config.root + "vres/mime/icon/" | |
} | |
var button = '<a href="javascript:;" ng-click="filterResults(facet)" class="underline" ng-class="facet.isSelected ? \'active\':\'\'">'; | |
button += '<span class="text">{{facet.display}}<span class="facet_count" ng-hide="facet.hasCount == false"> ({{facet.count}} filter items)</span></span> <span ng-show="facet.isSelected" class="icon-x"></span>', button += "</a>"; | |
var checkbox = '<div class="checkbox">'; | |
checkbox += '<label><input type="checkbox" ng-click="filterResults(facet)" ng-disabled="facet.disabled" ng-checked="facet.isSelected">{{facet.display}} ', checkbox += '<span class="facet_count" ng-hide="facet.hasCount == false">({{facet.count}})</span>', checkbox += "</label>", checkbox += '<span title="Not Available" class="facet_error icon-error" ng-show="facet.hasError == true"> </span>', checkbox += '<span class="fa fa-star-o pull-right checkbox-only" ng-hide="facet.hasCount == false" ng-click="filterOnly(facet)" title="Only This"></span>', checkbox += "</div>"; | |
var slider = '<div class="ui_slider_wrap">'; | |
slider += '<div range-slider id="slider" min="facet.min" max="facet.max" model-min="facet.model[0]" model-max="facet.model[1]" step="1"></div></div>', slider += '<div class="slider_range"><span class="min pull-left" ng-bind="facet.min"></span>', slider += '<span class="min pull-right" ng-bind="facet.max | number"></span></div>', slider += '<button class="btn btn-xs btn-primary" ng-click="addRangeFilter(facet)">Apply filter</button></form>', slider += "</div>"; | |
var nounitslider = '<div class="slider_wrap"><form class="form-inline" role="form"><div class="form-group">'; | |
nounitslider += '<input class="form-control input-xs semi" type="text" ng-model="facet.model[0]" ng-init="facet.model[0] = (facet.model[0] == undefined) ? facet.min : facet.model[0]">', nounitslider += '<span class="dash"></span>', nounitslider += '<input class="form-control input-xs semi" type="text" ng-model="facet.model[1]" ng-init="facet.model[1] = (facet.model[1] == undefined) ? facet.max : facet.model[1]"></div>', nounitslider += slider; | |
var unitslider = '<div class="slider_wrap"><form class="form-inline" role="form"><div class="form-group">'; | |
unitslider += '<input class="form-control input-xs semi" type="text" style="width:84px; padding:6px;" ng-model="facet.model[0]" ng-init="facet.model[0] = (facet.model[0] == undefined) ? facet.min : facet.model[0]">', unitslider += '<span class="dash thin-dash"></span>', unitslider += '<div class="input-group">', unitslider += '<input class="form-control input-xs semi" type="text" ng-model="facet.model[1]" ng-init="facet.model[1] = (facet.model[1] == undefined) ? facet.max : facet.model[1]">', unitslider += '<span class="input-group-addon" style="width:0px; padding-left:0px; padding-right:0px; border:none;"></span>', unitslider += '<select class="form-control" ng-model="facet.selectedUnit" ng-change="facet.convert(facet)" ng-options="unit for unit in facet.units"></select>', unitslider += "</div>", unitslider += slider; | |
var stats = '<div class="row stats_wrap"><ul><li><div class="pull-left col-xs-4">Total</div>{{facet.sum | number}}</li><li><div class="pull-left col-xs-4">Average</div>{{facet.mean | number}}</li><li><div class="pull-left col-xs-4">Deviation</div>{{facet.stddev | number}}</li></ul></div>', | |
tree = '<div><ul class="folder_tree" frang-tree>'; | |
tree += '<li frang-tree-repeat="node in facet.tree">', tree += "<div ng-class=\"node.children && node.children.length > 0 ? 'folderNode' : 'leaf'\"><span class=\"icon\"", tree += 'ng-class="{collapsed: node.collapsed, expanded: !node.collapsed}"', tree += 'ng-show="node.children && node.children.length > 0"', tree += 'ng-click="loadNode(node)"></span>', tree += "<i class=\"fa\" ng-class=\"{'fa-folder': node.collapsed, 'fa-folder-open': !node.collapsed}\"></i>", tree += '<span class="label" ng-class="{folder: node.children && node.children.length > 0}">', tree += '<a href="javascript:;" ng-click="addFolderFilter(node)" ng-class="{selected:node.id === doc.id}">{{node.display}}</a>', tree += "</span>", tree += "</div>", tree += '<ul class="noindent" ng-if="!node.collapsed && node.children && node.children.length > 0"', tree += 'frang-tree-insert-children="node.children"></ul>', tree += "</li>", tree += "</ul></div>"; | |
var date = '<div class="slider_wrap"><form class="form-inline" role="form"><div class="form-group">'; | |
return date += '<label class="semi">Date</label><br />', date += '<input type="text" placeholder="yyyy-mm-dd" class="form-control input-xs semi min_date_picker_input {{facet.minError}}" uib-datepicker-popup="yyyy-MM-dd" is-open="facet.isMinOpened" ng-click="openMinDatePicker($event, facet)" datepicker-options="{formatYear: \'yy\', startingDay: 1, showWeeks: false, showButtonBar: false}" ng-model="facet.dateModel[0]" close-text="Close" ng-required="true" />', date += '<span class="dash"></span>', date += '<input type="text" placeholder="yyyy-mm-dd" class="form-control input-xs semi max_date_picker_input {{facet.maxError}}" uib-datepicker-popup="yyyy-MM-dd" is-open="facet.isMaxOpened" ng-focus="openMaxDatePicker($event, facet)" datepicker-options="{formatYear: \'yy\', startingDay: 1, showWeeks: false, showButtonBar: false}" ng-model="facet.dateModel[1]" close-text="Close" ng-required="true" />', date += '</div><button class="btn btn-xs btn-primary" ng-click="addCalendarFilter(facet)">Apply filter</button></form>', date += "</div>", { | |
restrict: "A", | |
replace: !0, | |
link: _link, | |
controller: _controller | |
} | |
}), angular.module("voyager.filters").directive("vsFilters", function($document, $window) { | |
return { | |
restrict: "A", | |
link: function(scope, element) { | |
function onDestroy() { | |
angular.element($window).unbind("scroll", _windowScroll) | |
} | |
var lastScroll = 0, | |
uptick = 0, | |
_windowScroll = function() { | |
if (!element.is(":hidden")) { | |
var scrollTop = $document.scrollTop(), | |
winHeight = $window.innerHeight, | |
filterHeight = element.outerHeight(); | |
if ($(".result_container .list").outerHeight() < filterHeight && $(".result_container .list").css("min-height", filterHeight + "px"), scrollTop < 10) return void element.css("margin-top", 0); | |
if (filterHeight > winHeight) { | |
var actualHeight, marginTop; | |
actualHeight = scrollTop + winHeight + parseInt(element.css("padding-bottom")), marginTop = filterHeight > actualHeight ? -scrollTop : winHeight - filterHeight, lastScroll > scrollTop && marginTop < 0 ? uptick += 50 : uptick = 0, marginTop += uptick, marginTop < 50 && (marginTop > 0 && (marginTop = 0), element.css("margin-top", marginTop + "px")) | |
} | |
lastScroll = scrollTop, scope.$apply() | |
} | |
}; | |
angular.element($window).bind("scroll", _windowScroll), scope.$on("$destroy", onDestroy); | |
var padding, $banner = $("#top-banner"); | |
$(".content-header-padding").length ? (padding = 210, $banner.length && (padding += $banner.height()), element.css("padding-top", padding + "px")) : $banner.length && (padding = element.css("padding-top"), padding = padding.replace("px", ""), padding = parseInt(padding), padding += $banner.height(), element.css("padding-top", padding + "px")) | |
} | |
} | |
}), angular.module("voyager.filters").controller("FacetsCtrl", function($scope, $uibModalInstance, selectedFilter, updateFilters, facetService, $location, translateService, usSpinnerService) { | |
$scope.selectedFilter = translateService.getFieldName(selectedFilter.field), $scope.updateFilters = updateFilters, $scope.predicate = "-count", facetService.doLookup(selectedFilter, $location.search(), function(facets) { | |
if (facets.length > 0 && "CHECK" === facets[0].style) | |
for (var idx = 0; idx < facets.length; idx++) | |
for (var i = 0; i < selectedFilter.values.length; i++) | |
if (facets[idx].name === selectedFilter.values[i].name) { | |
facets[idx].isSelected = selectedFilter.values[i].isSelected; | |
break | |
} | |
$scope.facets = facets, usSpinnerService.stop("facets-spinner") | |
}), $scope.filterResults = function(facet, evt) { | |
"CHECK" !== facet.style ? $uibModalInstance.close(facet) : (facet.checked = evt.currentTarget.checked, $scope.updateFilters(facet)) | |
}, $scope.cancel = function() { | |
$uibModalInstance.dismiss("cancel") | |
} | |
}), angular.module("voyager.filters").factory("calendarFilter", function() { | |
function _styleDate(num) { | |
return num < 10 ? "0" + num : num | |
} | |
function _validateDate(date, facet, formattedDate) { | |
return "" === date ? (facet.minError = "error", !0) : isNaN(formattedDate.getTime()) ? (facet.minError = "error", !0) : (facet.minError = "", !1) | |
} | |
return { | |
decorate: function(facet) { | |
var calendar = facet.dateModel, | |
minDate = new Date(calendar[0]), | |
maxDate = new Date(calendar[1]), | |
seeError = _validateDate(calendar[0], facet, minDate); | |
if (seeError ? _validateDate(calendar[1], facet, maxDate) : seeError = _validateDate(calendar[1], facet, maxDate), !seeError) { | |
var formatMinDate = minDate.getFullYear() + "-" + _styleDate(minDate.getMonth() + 1) + "-" + _styleDate(minDate.getDate()), | |
formatMaxDate = maxDate.getFullYear() + "-" + _styleDate(maxDate.getMonth() + 1) + "-" + _styleDate(maxDate.getDate()); | |
if (!(formatMinDate > formatMaxDate)) return facet.humanize = facet.display + ": [" + formatMinDate + "T07:00:00Z TO " + formatMaxDate + "T07:00:00Z]", facet.model[0] = formatMinDate + "T07:00:00Z", facet.model[1] = formatMaxDate + "T07:00:00Z", facet; | |
facet.maxError = "error", facet.minError = "error" | |
} | |
return !1 | |
} | |
} | |
}), angular.module("voyager.filters").controller("FiltersCtrl", function($scope, filterService, $location, $uibModal, $timeout, statsService, treeService, configService, filterQuery, translateService, filterStyle, calendarFilter, $document, catalogService) { | |
function _appendIfMissing(filter, selectedFacet) { | |
if (angular.isDefined(filter)) { | |
var facetsMap = _.indexBy(filter.values, "name"); | |
if (0 === selectedFacet.name.indexOf("(")) { | |
var facets = selectedFacet.name.replace(" )", ")").replace(")", "").replace("(", "").split(" "); | |
facets.forEach(function(facet) { | |
var facetObj = angular.copy(selectedFacet); | |
facetObj.name = facet, facetObj.pretty = facet, facetObj.humanized = facet, _appendIfMissing(filter, facetObj) | |
}) | |
} else angular.isUndefined(facetsMap[selectedFacet.name]) && filter.values.push({ | |
name: selectedFacet.name, | |
display: selectedFacet.humanized, | |
style: selectedFacet.style, | |
filter: selectedFacet.filter, | |
isSelected: !0, | |
count: selectedFacet.count | |
}) | |
} | |
} | |
function _showMissingSelectedFacets() { | |
var i, selectedFacet, filter, selectedFilters = filterService.getFilters().slice(0), | |
filtersMap = _.indexBy($scope.filters, "field"); | |
for (i = 0; i < selectedFilters.length; i++) selectedFacet = selectedFilters[i], "CHECK" === selectedFacet.style && (filter = filtersMap[selectedFacet.filter], _appendIfMissing(filter, selectedFacet)) | |
} | |
function _addFilter(facet) { | |
filterService.removeExisting(facet), filterService.addFilter(facet), $location.search("fq", filterService.getFilterAsLocationParams()), _notifyFilter = !0, _fetchFilter() | |
} | |
function _clearBounds() { | |
$location.search("bbox", null), $location.search("bboxt", null), $scope.$emit("clearBboxEvent", {}) | |
} | |
function _clearSearchInput() { | |
$location.search("q", null), $scope.$emit("clearSearchEvent", {}) | |
} | |
function _scrollIntoView(filter) { | |
$timeout(function() { | |
var clientHeight = $document[0].documentElement.clientHeight, | |
element = $("#" + filter.field); | |
element[0].getBoundingClientRect().bottom > clientHeight && $("body").animate({ | |
scrollTop: element.offset().top | |
}, "slow") | |
}, 250) | |
} | |
function _fetchFilter() { | |
_busy || (_busy = !0, filterService.applyFromUrl($location.search()).then(function() { | |
_busy = !1, _notifyFilter && $scope.$emit("filterEvent", { | |
from: "filtersController" | |
}), catalogService.loadRemoteLocations().then(function() { | |
filterQuery.execute($location.search(), filterService.getFilterParams(), "", filterService.getSelectedFilters()).then(function(res) { | |
$scope.filters = filterStyle.apply(res.filters), _.isEmpty(res.badShards) || configService.getCatalogs().then(function() { | |
var shardUrl, catalogFilter = _.find($scope.filters, { | |
field: "shards" | |
}); | |
_.each(catalogFilter.values, function(catalogFacet) { | |
angular.isDefined(catalogFacet.raw) && (shardUrl = catalogFacet.raw, shardUrl = shardUrl.substring(shardUrl.indexOf("://") + 3), shardUrl += "solr/v0", catalogFacet.hasError = angular.isDefined(res.badShards[shardUrl])) | |
}) | |
}), _showMissingSelectedFacets(), statsService.updateStats($location.search(), filterService.getFilterParams(), "", $scope.filters), treeService.updateTree($location.search(), filterService.getFilterParams(), "", $scope.filters) | |
}) | |
}) | |
})) | |
} | |
var _busy = !1, | |
_notifyFilter = !1; | |
$scope.maxFacets = 10, $scope.$on("doSearch", function() { | |
_notifyFilter = !1, _fetchFilter() | |
}), $scope.$on("filterChanged", function(event, args) { | |
!args || "filtersController" !== args.from && args.refresh !== !1 ? (_notifyFilter = !1, _fetchFilter()) : _notifyFilter = !1 | |
}), $scope.$on("searchResults", function(event, data) { | |
angular.isDefined(data.stats) && filterService.setStatsFields(data.stats.stats_fields) | |
}), $scope.openMinDatePicker = function($event, facet) { | |
$event.preventDefault(), $event.stopPropagation(), facet.isMinOpened = !0, facet.isMaxOpened = !1 | |
}, $scope.openMaxDatePicker = function($event, facet) { | |
$event.preventDefault(), $event.stopPropagation(), facet.isMaxOpened = !0, facet.isMinOpened = !1 | |
}, $scope.filterResults = function(facet) { | |
var shards = [], | |
forceSelectedParameter = !1; | |
if (angular.isDefined(facet.checked) && (facet.isSelected = !facet.checked, delete facet.checked, forceSelectedParameter = !0), facet.isSelected) "shard" === facet.field ? $scope.removeFilter(facet) : (filterService.removeFilter(facet), facet.isSelected = !1), forceSelectedParameter && (facet.isSelected = !1); | |
else if ("shard" === facet.field) { | |
var urlShards = $location.search().shards; | |
"" !== urlShards && angular.isDefined(urlShards) && (shards = urlShards.split(",")), shards.push(facet.id), $location.search("shards", shards.join()) | |
} else filterService.addFilter(facet), forceSelectedParameter && (facet.isSelected = !0); | |
$location.search("fq", filterService.getFilterAsLocationParams()), _notifyFilter = !0, _fetchFilter() | |
}, $scope.filterOnly = function(facet) { | |
filterService.removeThisFilter(facet), _addFilter(facet) | |
}, $scope.addRangeFilter = function(facet) { | |
var range = facet.model; | |
facet.units && (range[0] = facet.convertValue(range[0], facet.selectedUnit, facet.units[0], facet), range[1] = facet.convertValue(range[1], facet.selectedUnit, facet.units[0], facet)), facet.humanized = facet.display + ": [" + range[0] + " TO " + range[1] + "]", _addFilter(facet) | |
}, $scope.addCalendarFilter = function(facet) { | |
var calendarFacet = calendarFilter.decorate(facet); | |
calendarFacet && _addFilter(facet) | |
}, $scope.addFolderFilter = function(node) { | |
var facet = { | |
field: "path_path", | |
filter: "path_path", | |
humanized: "Path: " + node.path, | |
name: node.path | |
}; | |
_addFilter(facet) | |
}, $scope.loadNode = function(node) { | |
node.collapsed = !node.collapsed, node.loaded || treeService.loadNode($location.search(), filterService.getFilterParams(), "", $scope.filters, node) | |
}, $scope.removeFilter = function(facet) { | |
if (facet.isInput) _clearSearchInput(); | |
else if (facet.isBbox) _clearBounds(); | |
else if ("shard" === facet.field) { | |
var shards = $location.search().shards.split(","), | |
urlShards = []; | |
facet.selected = !1, _.each(shards, function(shard) { | |
facet.id === shard || urlShards.push(shard) | |
}), $location.search("shards", urlShards.join()) | |
} else filterService.removeFilter(facet), $location.search("fq", filterService.getFilterAsLocationParams()); | |
_notifyFilter = !0, _fetchFilter() | |
}, $scope.$on("removeFilter", function(e, facet) { | |
$scope.removeFilter(facet) | |
}), $scope.hasFacets = function(filter) { | |
return filter.values.length > 0 | |
}, $scope.hasMoreFacets = function(filter) { | |
return filter.values.length > $scope.maxFacets | |
}, $scope.toggleDisplayState = function(filter) { | |
$timeout(function() { | |
"in" !== filter.displayState ? filter.displayState = "in" : filter.displayState = "", filterService.setFilterState(filter, filter.displayState), "in" === filter.displayState && _scrollIntoView(filter) | |
}, 0) | |
}, $scope.showAllFacets = function(filter) { | |
var modalInstance = $uibModal.open({ | |
templateUrl: "src/filters/facets.html", | |
controller: "FacetsCtrl", | |
resolve: { | |
selectedFilter: function() { | |
return filter | |
}, | |
updateFilters: function() { | |
return $scope.filterResults | |
} | |
} | |
}); | |
modalInstance.result.then(function(facet) { | |
$scope.filterResults(facet) | |
}, function() {}) | |
}, $scope.getFieldName = function(key) { | |
return translateService.getFieldName(key) || key | |
} | |
}), angular.module("voyager.filters").controller("SelectedFiltersCtrl", function($scope, filterService, $location, mapUtil, sugar, translateService) { | |
function _applyOrFacets() { | |
$scope.filters.forEach(function(filter) { | |
if (filter.isOr = 0 === filter.name.indexOf("("), filter.isOr) { | |
filter.parts = []; | |
var parts = filter.name.replace("(", "").replace(")", "").replace("{!expand}", "").trim().split(" "); | |
parts.forEach(function(part) { | |
var facet = { | |
name: part, | |
filter: filter.filter, | |
pretty: part | |
}; | |
filter.parts.push(facet), "location" === filter.filter && (facet.pretty = translateService.getLocation(part)) | |
}) | |
} | |
}) | |
} | |
function _setSelectedFilters() { | |
var params = $location.search(); | |
if ($scope.filters = filterService.getFilters().slice(0), _applyOrFacets(), params.q && "*:*" !== params.q && $scope.filters.push({ | |
isInput: !0, | |
name: "search", | |
humanized: "Search:" + params.q, | |
pretty: params.q.replace("{!expand}", "") | |
}), params.place) { | |
var humanized, formattedPlace = params.place, | |
isBbox = !1, | |
isWkt = !1; | |
mapUtil.isBbox(params.place) ? (formattedPlace = sugar.formatBBox(params.place), isBbox = !0) : (formattedPlace = mapUtil.formatWktForDisplay(params.place), isWkt = !0), humanized = ("within" === params["place.op"] ? "Within" : "Intersects") + ": " + formattedPlace, $scope.filters.push({ | |
isInput: !0, | |
name: "place", | |
humanized: humanized, | |
isBbox: isBbox, | |
isWkt: isWkt, | |
pretty: formattedPlace | |
}) | |
} | |
params["links.to"] && $scope.filters.push({ | |
isInput: !1, | |
name: "linksTo", | |
humanized: "Links.To:" + params["links.to"], | |
pretty: params["links.to"] | |
}), params["links.from"] && $scope.filters.push({ | |
isInput: !1, | |
name: "linksFrom", | |
humanized: "Links.From:" + params["links.from"], | |
pretty: params["links.from"] | |
}) | |
} | |
function clearPlace(params) { | |
return delete params.place, delete params["place.op"], delete params["place.id"], params | |
} | |
$scope.removeExpanded = function(term) { | |
var exp_exclude = $location.search()["expand.exclude"]; | |
"undefined" == typeof exp_exclude && (exp_exclude = ""), exp_exclude += " " + term, $location.search("expand.exclude", exp_exclude.trim()), $scope.$emit("removeFilterEvent", {}) | |
}, $scope.removeFilter = function(facet) { | |
if ("search" === facet.name) $location.search("q", null), $scope.$emit("removeFilterEvent", {}); | |
else if ("place" === facet.name) { | |
var filterHumanized = facet.humanized.split(": "); | |
filterHumanized.splice(0, 1); | |
var args = { | |
isBbox: facet.isBbox, | |
isWkt: facet.isWkt | |
}; | |
$location.search(clearPlace($location.search())), $scope.$emit("removeFilterEvent", args) | |
} else if ("linksTo" === facet.name || "linksFrom" === facet.name) { | |
var params = $location.search(); | |
delete params["links.to"], delete params["links.from"], $location.search(params), $scope.$emit("removeFilterEvent", facet) | |
} else filterService.removeFilter(facet), $location.search("fq", filterService.getFilterAsLocationParams()), $scope.$emit("removeFilterEvent", facet); | |
_setSelectedFilters() | |
}, $scope.clearAllFilter = function() { | |
var params = $location.search(); | |
delete params.q, delete params.fq, $location.search(clearPlace(params)), filterService.clear(), $scope.$emit("removeFilterEvent", {}), _setSelectedFilters() | |
}, $scope.resetExpanded = function() { | |
delete $location.search()["expand.exclude"], delete $scope.expanded, $scope.$emit("removeFilterEvent", {}) | |
}, $scope.$on("filterChanged", function() { | |
_setSelectedFilters() | |
}), $scope.$on("searchResults", function(event, data) { | |
data && data.expansion && data.expansion.terms && _.isArray(data.expansion.terms) && data.expansion.terms.length > 0 ? $scope.expanded = data.expansion.terms : delete $scope.expanded | |
}), $scope.$on("clearSearch", function() { | |
_setSelectedFilters() | |
}), $location.search().fq ? filterService.setFilters($location.search().fq) : (angular.isDefined($location.search()["links.to"]) || angular.isDefined($location.search()["links.from"])) && filterService.clear(), _setSelectedFilters() | |
}), angular.module("voyager.filters").factory("rangeService", function(config, $http, $timeout, configService, translateService, $q) { | |
function _getRangeParams() { | |
var configFilters = configService.getFilters(), | |
facetParams = ""; | |
return $.each(configFilters, function(index, filter) { | |
"RANGE" !== filter.style && "STATS" !== filter.style || (facetParams += "&stats.field=" + filter.field) | |
}), facetParams | |
} | |
function _hasRangeParam() { | |
var configFilters = configService.getFilters(), | |
hasRange = !1; | |
return $.each(configFilters, function(index, filter) { | |
if ("RANGE" === filter.style || "STATS" === filter.style) return hasRange = !0, !1 | |
}), hasRange | |
} | |
function _getRangeLimitsQuery() { | |
var queryString = config.root + "solr/v0/select?rows=0&stats=true" + _getRangeParams(); | |
return angular.isDefined(configService.getConfigId()) && (queryString += "&voyager.config.id=" + configService.getConfigId()), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function _setRangeLimits() { | |
var deferred = $q.defer(); | |
return _hasRangeParam() ? $http.jsonp(_getRangeLimitsQuery()).success(function(data) { | |
_rangeLimits = data.stats.stats_fields, deferred.resolve() | |
}) : deferred.resolve(), deferred.promise | |
} | |
function _parseInt(val) { | |
var ret = 0; | |
return angular.isDefined(val) && (ret = parseInt(val)), ret | |
} | |
var _rangeLimits = {}, | |
_statsFields = {}, | |
_rangeUnitMap = { | |
fileSize: { | |
options: ["B", "KB", "MB", "GB", "TB"], | |
convertValue: function(value, unitFrom, unitTo, facet) { | |
var unitFrom_Index = facet.units.indexOf(unitFrom), | |
unitTo_Index = facet.units.indexOf(unitTo), | |
converted = value; | |
return converted = unitFrom_Index > unitTo_Index ? value * Math.pow(1e3, unitFrom_Index - unitTo_Index) : value / Math.pow(1e3, unitTo_Index - unitFrom_Index) | |
} | |
} | |
}; | |
return { | |
fetchAllRangeLimits: function() { | |
return _setRangeLimits() | |
}, | |
setStatsFields: function(statsFields) { | |
_statsFields = statsFields | |
}, | |
getRangeLimits: function(filter) { | |
return _rangeLimits[filter] | |
}, | |
buildRangeFilter: function(filter, selectedFilter) { | |
var range = { | |
min: _rangeLimits[filter.field].min, | |
max: _rangeLimits[filter.field].max, | |
style: filter.style, | |
name: filter.field, | |
filter: filter.field, | |
display: filter.value | |
}; | |
return selectedFilter ? range.model = selectedFilter.model : range.model = [range.min, range.max], range.stddev = _parseInt(_rangeLimits[filter.field].stddev), range.sum = _parseInt(_rangeLimits[filter.field].sum), range.mean = _parseInt(_rangeLimits[filter.field].mean), filter.unit && "none" !== filter.unit && (range.units = _rangeUnitMap[filter.unit].options, range.selectedUnit = range.units[0], range.storedUnit = range.selectedUnit, range.convertValue = _rangeUnitMap[filter.unit].convertValue, range.convert = function(rangeFacet) { | |
rangeFacet.min = rangeFacet.convertValue(rangeFacet.min, rangeFacet.storedUnit, rangeFacet.selectedUnit, rangeFacet), rangeFacet.max = rangeFacet.convertValue(rangeFacet.max, rangeFacet.storedUnit, rangeFacet.selectedUnit, rangeFacet), rangeFacet.storedUnit = rangeFacet.selectedUnit | |
}), range | |
}, | |
buildCalendarFilter: function(filter, selectedFilter) { | |
var calendar = { | |
style: filter.style, | |
name: filter.field, | |
filter: filter.field, | |
display: filter.value, | |
stype: filter.stype, | |
multivalued: filter.multivalued | |
}; | |
return selectedFilter ? (calendar.model = decodeURIComponent(selectedFilter.name).replace(/[\[\]]/g, "").split(" TO "), calendar.dateModel = [new Date(calendar.model[0]), new Date(calendar.model[1])]) : (calendar.model = [], calendar.dateModel = []), calendar | |
}, | |
decorateSelected: function(selectedFilter, filterKeyValue) { | |
var range = filterKeyValue.value.replace("TO", ","); | |
selectedFilter.name = filterKeyValue.name, selectedFilter.model = JSON.parse(range), selectedFilter.humanized = translateService.getFieldName(filterKeyValue.name) + ": " + filterKeyValue.value | |
} | |
} | |
}), angular.module("voyager.filters").factory("facetService", function($http, config, translateService, $injector) { | |
function _checkSelectedOr(selectedFilters, facet) { | |
for (var selectedKeys = Object.keys(selectedFilters), i = 0; i < selectedKeys.length; i++) { | |
var selected = selectedFilters[selectedKeys[i]]; | |
if (0 === selected.name.indexOf("(") && (_checkSelectedOrFacet(selected, facet), facet.isSelected)) break | |
} | |
} | |
function _checkSelectedOrFacet(selected, facet) { | |
var facets = selected.name.replace("(", "").replace(" )", "").replace(")", ""); | |
facets = facets.split(" "); | |
for (var i = 0; i < facets.length; i++) | |
if (facets[i] === facet.name) { | |
facet.isSelected = !0; | |
break | |
} | |
} | |
function lookup(filter, params, callback) { | |
QueryBuilder || (QueryBuilder = $injector.get("queryBuilder")); | |
var service = QueryBuilder.buildAllFacets(params, filter.field); | |
$http.jsonp(service).success(function(data) { | |
var rawFacets = data.facet_counts.facet_fields[filter.field]; | |
callback(_buildFacets(rawFacets, filter)) | |
}) | |
} | |
var QueryBuilder, isEven = function(someNumber) { | |
return someNumber % 2 === 0 | |
}, | |
_buildFacet = function(facetName, value, filter, selectedFilters) { | |
var filterName = angular.isString(filter) ? filter : filter.field, | |
builtValue = facetName + " (" + value + ")", | |
facet = { | |
name: facetName, | |
value: builtValue, | |
filter: filterName, | |
style: filter.style | |
}; | |
if (config.rawFields[filterName] ? facet.humanized = facet.name : "location" === facet.filter ? facet.humanized = translateService.getLocation(facet.name) : facet.humanized = translateService.getType(facet.name), facet.count = value, facet.display = facet.humanized, selectedFilters) { | |
var selectedFilter = selectedFilters[facet.name]; | |
selectedFilter ? facet.isSelected = !0 : _checkSelectedOr(selectedFilters, facet) | |
} | |
return facet | |
}, | |
_buildFacets = function(rawFacets, filter, selectedFilters) { | |
var facets = []; | |
return $.each(rawFacets, function(index, value) { | |
if (!isEven(index)) { | |
var facetName = rawFacets[index - 1], | |
facet = _buildFacet(facetName, value, filter, selectedFilters); | |
facets.push(facet) | |
} | |
}), facets | |
}; | |
return { | |
doLookup: function(filter, params, callback) { | |
lookup(filter, params, callback) | |
}, | |
buildFacet: function(facetName, value, filterName, selectedFilters) { | |
return _buildFacet(facetName, value, filterName, selectedFilters) | |
}, | |
buildFacets: function(rawFacets, filter, selectedFilters) { | |
return _buildFacets(rawFacets, filter, selectedFilters) | |
}, | |
buildAllFacets: function(filters, selectedFilters) { | |
var nameValues = {}; | |
return $.each(filters, function(filterName, values) { | |
var prettyFacetValues = _buildFacets(values, filterName, selectedFilters); | |
nameValues[filterName] = prettyFacetValues | |
}), nameValues | |
} | |
} | |
}), angular.module("voyager.filters").factory("filterQuery", function(config, facetService, configService, sugar, $http, queryBuilder, catalogService, converter) { | |
function _convertPlaceFilter(params) { | |
var placeFilter = ""; | |
return angular.isDefined(params.place) && (placeFilter = "&fq=" + converter.toPlaceFilter(params)), placeFilter | |
} | |
function _getQueryString(params, filters, bounds) { | |
var placeFilter = _convertPlaceFilter(params); | |
delete params.fq, delete params.sort, angular.isDefined(params.shards) && (params.shards = catalogService.removeInvalid(params.shards)), angular.isDefined(params.disp) && angular.isUndefined(params["voyager.config.id"]) ? params["voyager.config.id"] = params.disp : angular.isUndefined(params.disp) && angular.isDefined(configService.getConfigId()) && (params["voyager.config.id"] = configService.getConfigId()); | |
var queryString = config.root + "solr/v0/select"; | |
queryString += "?" + sugar.toQueryString(params); | |
var facetLimit = 11; | |
return queryString += "&rows=0", queryString += "&facet=true&facet.mincount=1&facet.limit=" + facetLimit + queryBuilder.buildFacetParams(), queryString += filters, queryString += bounds, queryString += placeFilter, queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK" | |
} | |
function checkFederations(res) { | |
var shards = res.data["shards.info"], | |
badShards = {}; | |
if (shards) | |
for (var shard in shards) _.isEmpty(shards[shard].error) || (badShards[shard] = shards[shard].shardAddress); | |
return badShards | |
} | |
return { | |
execute: function(params, filters, bounds, selectedFilters) { | |
var paramCopy = _.clone(params); | |
return $http.jsonp(_getQueryString(paramCopy, filters, bounds)).then(function(res) { | |
var resultData = res.data.facet_counts.facet_fields, | |
badShards = checkFederations(res), | |
filterFacets = facetService.buildAllFacets(resultData, selectedFilters); | |
return { | |
filters: filterFacets, | |
badShards: badShards | |
} | |
}) | |
} | |
} | |
}), angular.module("voyager.filters").factory("filterService", function(translateService, facetService, $q, configService, rangeService, converter, $filter, sugar) { | |
function _setFilters(filterList) { | |
filters = filterList, $.each(filters, function(index, value) { | |
filterMap[value.name] = value | |
}) | |
} | |
function _clear() { | |
filters.length = 0, filterMap = {} | |
} | |
function _getKeyValue(filter) { | |
var pos = filter.indexOf(":"), | |
keyValue = {}; | |
return keyValue.name = filter.substring(0, pos), keyValue.value = filter.substring(pos + 1), keyValue.value = keyValue.value.replace(/\\/g, ""), keyValue | |
} | |
function _buildSelectedFilter(filterKeyValue) { | |
var style, filterName = filterKeyValue.name; | |
filterName.indexOf("{!tag=") !== -1 ? (filterKeyValue.name = filterName.substring(filterName.indexOf("}") + 1), style = "CHECK") : style = configService.lookupFilterStyle(filterKeyValue.name); | |
var pretty = "location" === filterKeyValue.name ? translateService.getLocation(filterKeyValue.value) : translateService.getType(decodeURI(filterKeyValue.value)), | |
humanized = translateService.getFieldName(filterKeyValue.name) + ":" + pretty, | |
decodeValue = decodeURIComponent(filterKeyValue.value), | |
timeValues = decodeValue.replace(/[\[\]]/g, "").split(" TO "); | |
if ("RANGE" !== style && sugar.isValidDate(timeValues[0])) { | |
style = "DATE"; | |
var dateFilterValue = Date.parse(timeValues[0]); | |
pretty = $filter("date")(dateFilterValue, "M/d/yyyy"), timeValues[1] && (dateFilterValue = Date.parse(timeValues[1]), pretty += " TO " + $filter("date")(dateFilterValue, "M/d/yyyy")), humanized = translateService.getFieldName(filterKeyValue.name) + ":" + decodeValue | |
} | |
var selectedFilter = { | |
filter: filterKeyValue.name, | |
name: filterKeyValue.value, | |
humanized: humanized, | |
isSelected: !0, | |
style: style, | |
displayState: "in", | |
pretty: pretty | |
}; | |
return "RANGE" === style && rangeService.decorateSelected(selectedFilter, filterKeyValue), selectedFilter | |
} | |
function _getFilterList(urlFilters) { | |
var filterList = []; | |
return $.each(urlFilters, function(index, filter) { | |
var filterKeyValue = _getKeyValue(filter), | |
selectedFilter = _buildSelectedFilter(filterKeyValue); | |
filterList.push(selectedFilter), angular.isUndefined(filterState[filterKeyValue.name]) && (filterState[filterKeyValue.name] = "in") | |
}), filterList | |
} | |
function _syncFilters(urlFilters, resetState) { | |
if (resetState && (filterState = {}), "string" == typeof urlFilters && (urlFilters = [urlFilters]), urlFilters) { | |
var filterList = _getFilterList(urlFilters); | |
_setFilters(filterList) | |
} else _clear() | |
} | |
function _replaceName(target, source) { | |
var name = target.replace("(" + source + " ", "(").replace(" " + source + ")", ")").replace(" " + source + " ", " ").replace(" )", ")"); | |
return name.indexOf(" ") === -1 && (name = name.replace("(", "").replace(")", "")), name | |
} | |
var searchBounds, filters = [], | |
filterMap = {}, | |
filterState = {}, | |
_systemFilters = null, | |
_statsFields = {}; | |
return { | |
getSystemFilters: function() { | |
return _systemFilters | |
}, | |
buildFacets: function(filters) { | |
return facetService.buildAllFacets(filters, filterMap) | |
}, | |
getFilterAsLocationParams: function() { | |
var name, filterList = []; | |
return $.each(filters, function(index, facet) { | |
name = facet.name, "RANGE" === facet.style || "STATS" === facet.style ? (name = "date" === facet.stype ? "[" + encodeURIComponent(facet.model[0] + " TO " + facet.model[1]) + "]" : "[" + facet.model[0] + " TO " + facet.model[1] + "]", filterList.push(facet.filter + ":" + name)) : "COMPLEX" === facet.style ? filterList.push(facet.filter + ":" + facet.name) : (name = converter.solrReady(name), filterList.push(facet.filter + ":" + name)) | |
}), filterList | |
}, | |
getFilterParams: function() { | |
return converter.toSolrParams(filters) | |
}, | |
getSolrList: function() { | |
return converter.toSolrQueryList(filters) | |
}, | |
getFilters: function() { | |
return filters | |
}, | |
setFilters: function(fq) { | |
_syncFilters(fq) | |
}, | |
getSelectedFilters: function() { | |
return filterMap | |
}, | |
addFilter: function(facet) { | |
"COMPLEX" === facet.style ? $.each(facet.name, function(index) { | |
if (!filterMap[facet.name[index]]) { | |
var simpleFacet = $.extend({}, facet); | |
simpleFacet.name = facet.name[index], simpleFacet.filter = facet.filter[index], filters.push(simpleFacet), filterMap[simpleFacet.name] = simpleFacet | |
} | |
}) : filterMap[facet.name] || (filters.push(facet), filterMap[facet.name] = facet) | |
}, | |
removeFilter: function(facet) { | |
var isCalendar = "DATE" === facet.style || !angular.isUndefined(facet.stype) && "date" === facet.stype, | |
isRange = "RANGE" === facet.style, | |
isComplex = "COMPLEX" === facet.style; | |
filters = _.reject(filters, function(el) { | |
return isCalendar || isRange ? el.filter === facet.filter : isComplex ? facet.name.indexOf(el.name) >= 0 && facet.filter[facet.name.indexOf(el.name)] === el.filter : el.name === facet.name | |
}), filters.forEach(function(filter) { | |
0 === filter.name.indexOf("(") && filter.name.indexOf(facet.name) !== -1 && (delete filterMap[filter.name], filter.name = _replaceName(filter.name, facet.name), filter.pretty = _replaceName(filter.pretty, facet.name), filter.humanized = _replaceName(filter.humanized, facet.name), filterMap[filter.name] = filter) | |
}), filters = filters.filter(function(filter) { | |
return "()" !== filter.name && filter.humanized.indexOf("()") === -1 | |
}), isCalendar || isRange ? delete filterMap[facet.filter] : isComplex ? $.each(facet.name, function(index, facetName) { | |
delete filterMap[facetName] | |
}) : delete filterMap[facet.name] | |
}, | |
clear: function() { | |
_clear() | |
}, | |
applyFromUrl: function(params) { | |
var deferred = $q.defer(); | |
return configService.setFilterConfig(params.disp).then(function(config) { | |
rangeService.fetchAllRangeLimits().then(function() { | |
_syncFilters(params.fq, config.configId !== params.disp), deferred.resolve({}) | |
}) | |
}), deferred.promise | |
}, | |
clearBbox: function() { | |
searchBounds = null | |
}, | |
setStatsFields: function(statsFields) { | |
_statsFields = statsFields | |
}, | |
getFilterState: function(filter) { | |
return filterState[filter.field] | |
}, | |
setFilterState: function(filter, state) { | |
filterState[filter.field] = state | |
}, | |
removeExisting: function(facet) { | |
var self = this; | |
$.each(filters, function(index, selectedFilter) { | |
if (selectedFilter.filter === facet.filter) return self.removeFilter(facet), !1 | |
}) | |
}, | |
removeThisFilter: function(facet) { | |
filters = _.reject(filters, function(filter) { | |
return filter.filter === facet.filter && (delete filterMap[filter.name], filter.isSelected = !1, !0) | |
}) | |
} | |
} | |
}), angular.module("voyager.filters").factory("filterStyle", function(config, facetService, configService, rangeService, filterService, complexFilterService) { | |
function _decorateFacets(facetValues, filter) { | |
$.each(facetValues, function(i, facet) { | |
facet.style = filter.style, "RANGE" === filter.style ? facet.numeric = parseInt(facet.name) : "COMPLEX" === facet.style && (facet.isSelected = complexFilterService.calculateIsSelected(facet, filterService.getSelectedFilters())) | |
}) | |
} | |
function _decorateFilters(systemFilters, facets) { | |
var selectedFilters = filterService.getFilters(); | |
$.each(systemFilters, function(index, filter) { | |
var selectedFilter, facetValues = facets[filter.field] || filter.values; | |
facetValues && facetValues.length > 0 && (facetValues.multivalued = filter.multivalued, facetValues.stype = filter.stype, _decorateFacets(facetValues, filter), "RANGE" !== filter.style && "STATS" !== filter.style && "HIERARCHY" !== filter.style ? filter.values = facetValues : "HIERARCHY" !== filter.style && (selectedFilter = _.find(selectedFilters, { | |
filter: filter.field | |
}), "date" === filter.stype ? filter.values = [rangeService.buildCalendarFilter(filter, selectedFilter)] : filter.values = [rangeService.buildRangeFilter(filter, selectedFilter)])), filter.displayState = filterService.getFilterState(filter) | |
}) | |
} | |
return { | |
apply: function(filters) { | |
var displayFilters = configService.getDisplayFilters(); | |
return _decorateFilters(displayFilters, filters), displayFilters | |
} | |
} | |
}), angular.module("cart", ["taskRunner", "voyager.util", "LocalStorageModule", "voyager.filters"]), angular.module("cart").config(["localStorageServiceProvider", function(localStorageServiceProvider) { | |
"use strict"; | |
localStorageServiceProvider.setPrefix("vs") | |
}]).factory("cartService", function(localStorageService, queryBuilder, $http, $q, translateService, cartItemsQuery) { | |
"use strict"; | |
function _setItems(items) { | |
var itemMap = {}; | |
$.each(items, function(index, value) { | |
itemMap[value.id] = value.id | |
}), localStorageService.add(CART_STORAGE_NAME, itemMap), _notify(itemMap) | |
} | |
function _syncItems() { | |
return cartItemsQuery.fetchItemsOnly(_getItems()).then(function(items) { | |
_setItems(items) | |
}) | |
} | |
function _appendFilter(filter, query) { | |
var solrFilters = query.solrFilters; | |
angular.isUndefined(solrFilters) && (query.solrFilters = []), query.solrFilters.push(filter) | |
} | |
var observers = [], | |
CART_STORAGE_NAME = "cart-items", | |
_notify = function(itemMap, action) { | |
var length = _.size(itemMap), | |
query = localStorageService.get("cart-query"); | |
query && (length += query.count), observers.forEach(function(entry) { | |
entry(length, itemMap, action) | |
}) | |
}, | |
_getItems = function() { | |
var items = localStorageService.get(CART_STORAGE_NAME); | |
return items ? items : {} | |
}, | |
_notifyCount = function(count) { | |
var items = _getItems(); | |
observers.forEach(function(entry) { | |
entry(count, items) | |
}) | |
}; | |
return { | |
addItem: function(item) { | |
var query = localStorageService.get("cart-query"), | |
removedFilter = !1; | |
if (query) { | |
if (angular.isDefined(query.solrFilters)) { | |
var length = query.solrFilters.length; | |
query.solrFilters = query.solrFilters.filter(function(item) { | |
return item !== "-id:" + item.id | |
}), removedFilter = query.solrFilters.length !== length | |
} | |
query.count = query.count + 1, this.addQuery(query) | |
} | |
if (!removedFilter) { | |
var itemMap = _getItems(); | |
itemMap[item.id] = item.id, localStorageService.add(CART_STORAGE_NAME, itemMap) | |
} | |
_notify(_getItems()) | |
}, | |
addItems: function(items) { | |
var itemMap = _getItems(); | |
$.each(items, function(index, item) { | |
itemMap[item.id] = item.id | |
}), localStorageService.add(CART_STORAGE_NAME, itemMap), _notify(itemMap); | |
var query = localStorageService.get("cart-query"); | |
query && (query.count += items.length, this.addQuery(query)) | |
}, | |
getItems: function() { | |
return _getItems() | |
}, | |
setItems: function(items) { | |
_setItems(items) | |
}, | |
getCount: function() { | |
var count = 0, | |
query = this.getQuery(); | |
return query && (count += query.count, query.actualCount) ? count : count += _.size(_getItems()) | |
}, | |
addObserver: function(observer) { | |
observers.push(observer) | |
}, | |
removeObserver: function(observer) { | |
observers = _.without(observers, function(item) { | |
return item === observer | |
}) | |
}, | |
remove: function(id) { | |
var itemMap = _getItems(), | |
query = localStorageService.get("cart-query"); | |
angular.isDefined(itemMap[id]) && (delete itemMap[id], localStorageService.add(CART_STORAGE_NAME, itemMap), _notify(itemMap)), query && (_appendFilter("-id:" + id, query), query.count = query.count - 1, this.addQuery(query)) | |
}, | |
isInCart: function(id) { | |
return angular.isDefined(_getItems()[id]) | |
}, | |
getItemIds: function() { | |
return $.map(_getItems(), function(item) { | |
return item | |
}) | |
}, | |
fetch: function(block) { | |
var query = this.getQuery(), | |
itemIds = this.getItemIds(); | |
return query || itemIds.length > 0 ? cartItemsQuery.execute(query, itemIds, block) : $q.when({ | |
count: 0, | |
docs: [] | |
}) | |
}, | |
fetchQueued: function(items) { | |
var query = this.getQuery(), | |
itemIds = this.getItemIds(); | |
return query || itemIds.length > 0 ? cartItemsQuery.fetchQueued(query, itemIds, items) : $q.when([]) | |
}, | |
clear: function() { | |
localStorageService.remove(CART_STORAGE_NAME), localStorageService.remove("cart-query"), _notify({}, "clear") | |
}, | |
getItemsArray: function() { | |
var itemsArray = []; | |
return $.map(_getItems(), function(item) { | |
itemsArray.push(item) | |
}), itemsArray | |
}, | |
removeByFormat: function(format) { | |
var query = localStorageService.get("cart-query"); | |
query && (format = format.replace("+", "%2B"), _appendFilter("-format:" + format, query), query.actualCount = !1, this.addQuery(query)) | |
}, | |
addQuery: function(query, items) { | |
angular.isUndefined(items) && (items = _getItems()); | |
var length = _.keys(items).length; | |
length > 0 && query.actualCount !== !0 && (query.count += length), query.actualCount = !0, localStorageService.add("cart-query", query), _notifyCount(query.count) | |
}, | |
replace: function(query) { | |
localStorageService.remove(CART_STORAGE_NAME), this.addQuery(query) | |
}, | |
getQuery: function() { | |
return localStorageService.get("cart-query") | |
}, | |
setQueryCount: function(count) { | |
var query = localStorageService.get("cart-query"); | |
query ? (query.count = count, query.actualCount = !0, this.addQuery(query)) : count !== this.getCount() && _syncItems(), _notifyCount(count) | |
}, | |
hasItems: function() { | |
var query = localStorageService.get("cart-query"), | |
items = localStorageService.get(CART_STORAGE_NAME); | |
return query || items | |
} | |
} | |
}), angular.module("cart").factory("cartItemsQuery", function(config, filterService, configService, sugar, $http, translateService, $log, converter) { | |
function _cleanFilters(filters) { | |
var pos, cleanFilters = _.clone(filters); | |
return _.each(cleanFilters, function(filter, index) { | |
pos = filter.indexOf("{!tag"), pos !== -1 && (pos = filter.indexOf("}"), cleanFilters[index] = filter.substring(pos + 1)), cleanFilters[index] = cleanFilters[index].replace("+", "%2B") | |
}), cleanFilters.join(" AND ") | |
} | |
function _applyItems(queryCriteria, items) { | |
var filters, itemsStr = "", | |
sep = "", | |
hasItems = !1, | |
q = "", | |
oper = ""; | |
items && items.length > 0 && (itemsStr = "id:(" + items.join(" ") + ")", sep = " OR ", hasItems = !0), angular.isDefined(queryCriteria.params.q) && _.isEmpty(queryCriteria.solrFilters) ? (q = queryCriteria.params.q, angular.isDefined(queryCriteria.params.place) && (q = "(" + q + " AND " + converter.toPlaceFilter(queryCriteria.params) + ")"), queryCriteria.params.q = itemsStr + sep + q) : hasItems && (_.isEmpty(queryCriteria.solrFilters) ? (angular.isDefined(queryCriteria.params.place) && (q = "(" + converter.toPlaceFilter(queryCriteria.params) + ")", oper = " OR "), angular.isDefined(queryCriteria.constraintFilters) && queryCriteria.constraintFilters.length > 0 ? queryCriteria.params.q = itemsStr + oper + q + " AND " + _cleanFilters(queryCriteria.constraintFilters) : queryCriteria.params.q = itemsStr + oper + q) : (filters = _cleanFilters(queryCriteria.solrFilters), angular.isDefined(queryCriteria.params.q) && (q = queryCriteria.params.q, oper = " AND "), angular.isDefined(queryCriteria.params.place) && (q += oper + converter.toPlaceFilter(queryCriteria.params), oper = " AND "), _.has(queryCriteria, "constraints") ? filters.length > 0 ? (angular.isDefined(queryCriteria.invalidItems) && queryCriteria.invalidItems === !0 && (filters = filters.replace(" AND ", "&fq=")), queryCriteria.params.q = itemsStr + " OR " + q + oper + filters + "&fq=" + queryCriteria.constraintFilters.join("&fq=")) : queryCriteria.params.q = itemsStr + " AND " + q + oper + _cleanFilters(queryCriteria.constraintFilters) : queryCriteria.params.q = itemsStr + sep + "(" + q + oper + filters + ")")) | |
} | |
function _convertPlaceIf(queryCriteria) { | |
if (angular.isDefined(queryCriteria.params.place)) { | |
var fq = []; | |
angular.isDefined(queryCriteria.solrFilters) && (fq = queryCriteria.solrFilters), fq.push(converter.toPlaceFilter(queryCriteria.params)), queryCriteria.solrFilters = fq | |
} | |
} | |
function _setParams(queryCriteria, items) { | |
var queryString = ""; | |
return queryCriteria || (queryCriteria = { | |
params: {}, | |
hasQuery: !1 | |
}), _.isEmpty(items) ? _convertPlaceIf(queryCriteria) : _applyItems(queryCriteria, items), queryString += "?" + sugar.toQueryString(queryCriteria.params) | |
} | |
function _addRow(results, add, item) { | |
return add ? results.push({ | |
key: item, | |
displayFormat: translateService.getType(item) | |
}) : results[results.length - 1].count = item, !add | |
} | |
function _buildRows(items) { | |
var isKey = !0, | |
results = [], | |
count = 0; | |
return $.each(items, function(index, item) { | |
isKey = _addRow(results, isKey, item), isKey && (count += item) | |
}), { | |
results: results, | |
count: count | |
} | |
} | |
function _buildQuery(settings, queryCriteria, items, block) { | |
var queryString = config.root + "solr/v0/select"; | |
if (queryString += _setParams(queryCriteria, items), queryString += settings, queryCriteria && (angular.isUndefined(items) || 0 === items.length)) { | |
if (!_.isEmpty(queryCriteria.solrFilters)) { | |
for (var i = 0; i < queryCriteria.solrFilters.length; i++) queryCriteria.solrFilters[i] = sugar.safeUrlEncode(queryCriteria.solrFilters[i]); | |
queryString += "&fq=" + queryCriteria.solrFilters.join("&fq=") | |
} | |
angular.isDefined(queryCriteria.bounds) && (queryString += queryCriteria.bounds) | |
} | |
return angular.isDefined(block) && (queryString += "&block=" + block), queryString += "&wt=json&json.wrf=JSON_CALLBACK&r=" + Math.random(), $log.debug("Cart queryString: " + queryString), queryString | |
} | |
function _getSummaryQueryString(queryCriteria, items, block) { | |
var settings = "&fl=id,name:[name],format&extent.bbox=true"; | |
return settings += "&facet=true&facet.field=format&facet.mincount=1&rows=0", _buildQuery(settings, queryCriteria, items, block) | |
} | |
function _getQueryString(queryCriteria, items, block) { | |
var settings = "&fl=id,title,name:[name],format,thumb:[thumbURL]"; | |
return settings += "&rows=100&extent.bbox=true", _buildQuery(settings, queryCriteria, items, block) | |
} | |
function _getQueuedQueryString(queryCriteria, items, queued) { | |
if (queryCriteria || (queryCriteria = { | |
params: {}, | |
hasQuery: !1 | |
}), queued && queued.length > 0) { | |
var ids = _.pluck(queued, "id"); | |
queryCriteria.params.fq ? queryCriteria.params.fq.push("id:(" + ids.join(" ") + ")") : queryCriteria.params.fq = "id:(" + ids.join(" ") + ")" | |
} | |
var settings = "&fl=id&rows=100&extent.bbox=true&block=false"; | |
return _buildQuery(settings, queryCriteria, items, !1) | |
} | |
function _getQueryCriteria(solrParams) { | |
var params = _.clone(solrParams), | |
solrFilters = filterService.getSolrList(); | |
return delete params.fq, delete params.sort, delete params.view, delete params.vw, delete params.disp, "*:*" === params.q && delete params.q, { | |
params: params, | |
bounds: "", | |
solrFilters: solrFilters | |
} | |
} | |
function _decorate(items) { | |
$.each(items, function(index, item) { | |
angular.isDefined(item.format) ? item.displayFormat = translateService.getType(item.format) : item.displayFormat = "Unknown", angular.isDefined(item.thumb) && item.thumb.indexOf("vres/mime") !== -1 && (item.defaultThumb = !0) | |
}) | |
} | |
function _fetchItems(queryCriteria, items, block) { | |
return $http.jsonp(_getQueryString(queryCriteria, items, block)).then(function(res) { | |
var docs = res.data.response.docs; | |
return _decorate(docs), { | |
docs: docs, | |
bbox: res.data["extent.bbox"], | |
count: res.data.response.numFound | |
} | |
}) | |
} | |
function _fetchQueued(queryCriteria, items, queued) { | |
return $http.jsonp(_getQueuedQueryString(queryCriteria, items, queued)).then(function(res) { | |
return res.data.response.docs | |
}) | |
} | |
function _fetchSummary(queryCriteria, items, block) { | |
return $http.jsonp(_getSummaryQueryString(queryCriteria, items, block)).then(function(res) { | |
var rows = _buildRows(res.data.facet_counts.facet_fields.format); | |
return { | |
docs: rows.results, | |
bbox: res.data["extent.bbox"], | |
count: res.data.response.numFound | |
} | |
}) | |
} | |
function _fetchItemsOnly(query) { | |
return $http.jsonp(query).then(function(res) { | |
return res.data.response.docs | |
}) | |
} | |
return { | |
getQueryCriteria: function(params) { | |
return _getQueryCriteria(params) | |
}, | |
execute: function(queryCriteria, items, block) { | |
var count = 1; | |
return queryCriteria && (count = queryCriteria.count, delete queryCriteria.params.sort), count <= 100 ? _fetchItems(_.clone(queryCriteria), items, block) : _fetchSummary(_.clone(queryCriteria), items, block) | |
}, | |
fetchItems: function(queryCriteria, items) { | |
return _fetchItems(queryCriteria, items) | |
}, | |
fetchQueued: function(queryCriteria, items, queued) { | |
return _fetchQueued(_.clone(queryCriteria), items, queued) | |
}, | |
fetchItemsOnly: function(items) { | |
var queryString = config.root + "solr/v0/select"; | |
if (items) { | |
var ids = _.keys(items); | |
queryString += "?fq=id:(" + ids.join(" ") + ")" | |
} | |
return queryString += "&fl=id", queryString += "&rows=100", queryString += "&rand=" + Math.random(), queryString += "&wt=json&json.wrf=JSON_CALLBACK", _fetchItemsOnly(queryString) | |
} | |
} | |
}), angular.module("cart").controller("CartNavCtrl", function(config, $scope, $location, searchService, cartService, authService, usSpinnerService, $uibModal, taskService, $timeout, $state) { | |
"use strict"; | |
function _init() { | |
$scope.taskStatusIcon = "fa fa-cog fa-spin", $scope.lastSearch = searchService.getLastSearch(); | |
var path = $location.path().split("/"); | |
$scope.page = path[1], "history" === $scope.page ? $scope.showTaskList = !1 : ($scope.showTaskList = cartService.getCount() > 0, _loadTasks(), $scope.cartItemCount = cartService.getCount(), cartService.addObserver(function() { | |
$scope.cartItemCount = cartService.getCount(), $scope.showTaskList = $scope.cartItemCount > 0 | |
}), _setPermissions(), authService.addObserver(_setPermissions)), $scope.uiText = config.ui.list | |
} | |
function _setPermissions() { | |
$scope.canReload = authService.hasPermission("manage") | |
} | |
function _getTask() { | |
var task = $location.search().task; | |
return angular.isUndefined(task) && $location.path().indexOf("status") <= -1 && $location.path().indexOf("tasks") <= -1 && $location.path().indexOf("task") <= -1 && $location.path().indexOf("tasks") <= -1 ? config.defaultTask : task | |
} | |
function _loadTasks() { | |
taskService.findAllTasks($scope.canReload).then(function(response) { | |
$scope.taskList = response, $scope.refreshing = !1; | |
var task = _getTask(); | |
_.isEmpty(task) || $timeout(function() { | |
var defaultTask; | |
_.isArray($scope.taskList) ? defaultTask = _.find($scope.taskList, { | |
name: task | |
}) : _.each($scope.taskList, function(category) { | |
defaultTask || (defaultTask = _.find(category, { | |
name: task | |
})) | |
}), defaultTask && defaultTask.available === !0 && $scope.selectTask(defaultTask) | |
}), usSpinnerService.stop("tasks-spinner") | |
}) | |
} | |
$scope.refreshTasks = function() { | |
$scope.refreshing || ($scope.refreshing = !0, usSpinnerService.spin("tasks-spinner"), taskService.refresh().then(function() { | |
_loadTasks() | |
})) | |
}, $scope.selectTask = function(task) { | |
if (task.isSelected = !task.isSelected, task.available === !0) { | |
task.isNew = !0; | |
var constraintFormats = taskService.getTaskConstraintFormats(task.constraints); | |
taskService.validateTaskItems(task.constraints).then(function(severity) { | |
0 === severity ? (task.error = !1, task.warning = !1, $state.go("task", { | |
task: task | |
})) : 1 === severity ? (task.error = !1, task.warning = !0, $scope.hasInvalidItems = !0, $state.go("task", { | |
task: task | |
})) : 2 === severity && taskService.showTaskValidationError(constraintFormats) | |
}) | |
} | |
}, $scope.$on("taskStatusChanged", function(event, args) { | |
$scope.loadDefaultTask = !1, "alert-running" === args ? $scope.taskStatusIcon = "fa fa-cog fa-spin" : "alert-success" === args ? $scope.taskStatusIcon = "glyphicon glyphicon-ok" : "alert-warning" === args ? $scope.taskStatusIcon = "icon-warning" : $scope.taskStatusIcon = "icon-error" | |
}), _init() | |
}), angular.module("cart").controller("CartCtrl", function($scope, cartService, searchService, $location, config, $log) { | |
function _updateCartCount(length, items, action) { | |
"clear" === action && ($scope.cartItems = [], $scope.cartItemCount = 0) | |
} | |
$scope.hasError = !1, $scope.loading = !0, $scope.cartName = config.ui.list.name.toLowerCase(), $scope.disp = $location.search().disp || "default", $scope.uiText = config.ui.list; | |
var _removeValue = function(array, id) { | |
return _.reject(array, function(item) { | |
return item.id === id | |
}) | |
}; | |
cartService.addObserver(_updateCartCount); | |
var init = function() { | |
$scope.displayCategory = cartService.getCount() > 100, cartService.fetch().then(function(data) { | |
cartService.setQueryCount(data.count), $scope.cartItemCount = data.count, $scope.cartItems = data.docs, $scope.loading = !1 | |
}, function(error) { | |
$log.error(error) | |
}) | |
}; | |
init(), $scope.removeItem = function(id) { | |
cartService.remove(id), $scope.cartItems = _removeValue($scope.cartItems, id), $scope.cartItemCount = cartService.getCount() | |
}, $scope.removeItemByFormat = function(item) { | |
cartService.removeByFormat(item.key), init() | |
}, $scope.hasItems = function() { | |
return cartService.getCount() > 0 | |
}, $scope.clearQueue = function() { | |
cartService.clear() | |
}, $scope.$on("$destroy", function() { | |
cartService.removeObserver(_updateCartCount) | |
}) | |
}), angular.module("tree.directive", []).directive("frangTree", function($parse, $animate) { | |
return { | |
restrict: "EA", | |
controller: function($scope, $element) { | |
this.insertChildren = null, this.init = function(insertChildren) { | |
this.insertChildren = insertChildren | |
} | |
} | |
} | |
}).directive("frangTreeRepeat", function($parse, $animate) { | |
function hashKey(obj) { | |
var key, objType = typeof obj; | |
return "object" == objType && null !== obj ? "function" == typeof(key = obj.$$hashKey) ? key = obj.$$hashKey() : void 0 === key && (key = obj.$$hashKey = nextUid()) : key = obj, objType + ":" + key | |
} | |
function isArrayLike(obj) { | |
if (null == obj || isWindow(obj)) return !1; | |
var length = obj.length; | |
return !(1 !== obj.nodeType || !length) || (isString(obj) || isArray(obj) || 0 === length || "number" == typeof length && length > 0 && length - 1 in obj) | |
} | |
function isWindow(obj) { | |
return obj && obj.document && obj.location && obj.alert && obj.setInterval | |
} | |
function isString(value) { | |
return "string" == typeof value | |
} | |
function isArray(value) { | |
return "[object Array]" == toString.apply(value) | |
} | |
function nextUid() { | |
for (var digit, index = uid.length; index;) { | |
if (index--, digit = uid[index].charCodeAt(0), 57 == digit) return uid[index] = "A", uid.join(""); | |
if (90 != digit) return uid[index] = String.fromCharCode(digit + 1), uid.join(""); | |
uid[index] = "0" | |
} | |
return uid.unshift("0"), uid.join("") | |
} | |
function assertNotHasOwnProperty(name, context) { | |
if ("hasOwnProperty" === name) throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context) | |
} | |
function minErr(module) { | |
return function() { | |
var message, i, code = arguments[0], | |
prefix = "[" + (module ? module + ":" : "") + code + "] ", | |
template = arguments[1], | |
templateArgs = arguments, | |
stringify = function(obj) { | |
return isFunction(obj) ? obj.toString().replace(/ \{[\s\S]*$/, "") : isUndefined(obj) ? "undefined" : isString(obj) ? obj : JSON.stringify(obj) | |
}; | |
for (message = prefix + template.replace(/\{\d+\}/g, function(match) { | |
var arg, index = +match.slice(1, -1); | |
return index + 2 < templateArgs.length ? (arg = templateArgs[index + 2], isFunction(arg) ? arg.toString().replace(/ ?\{[\s\S]*$/, "") : isUndefined(arg) ? "undefined" : isString(arg) ? arg : toJson(arg)) : match | |
}), message = message + "\nhttp://errors.angularjs.org/" + version.full + "/" + (module ? module + "/" : "") + code, i = 2; i < arguments.length; i++) message = message + (2 == i ? "?" : "&") + "p" + (i - 2) + "=" + encodeURIComponent(stringify(arguments[i])); | |
return new Error(message) | |
} | |
} | |
function getBlockElements(block) { | |
if (block.startNode === block.endNode) return jqLite(block.startNode); | |
var element = block.startNode, | |
elements = [element]; | |
do { | |
if (element = element.nextSibling, !element) break; | |
elements.push(element) | |
} while (element !== block.endNode); | |
return jqLite(elements) | |
} | |
function addRepeatWatch($scope, $element, _lastBlockMap, valueIdentifier, keyIdentifier, rhs, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, linker, expression) { | |
var lastBlockMap = _lastBlockMap; | |
$scope.$watchCollection(rhs, function(collection) { | |
var index, length, nextNode, arrayLength, childScope, key, value, trackById, trackByIdFn, collectionKeys, block, elementsToRemove, previousNode = $element[0], | |
nextBlockMap = {}, | |
nextBlockOrder = []; | |
if (isArrayLike(collection)) collectionKeys = collection, trackByIdFn = trackByIdExpFn || trackByIdArrayFn; | |
else { | |
trackByIdFn = trackByIdExpFn || trackByIdObjFn, collectionKeys = []; | |
for (key in collection) collection.hasOwnProperty(key) && "$" != key.charAt(0) && collectionKeys.push(key); | |
collectionKeys.sort() | |
} | |
for (arrayLength = collectionKeys.length, length = nextBlockOrder.length = collectionKeys.length, index = 0; index < length; index++) | |
if (key = collection === collectionKeys ? index : collectionKeys[index], value = collection[key], trackById = trackByIdFn(key, value, index), assertNotHasOwnProperty(trackById, "`track by` id"), lastBlockMap.hasOwnProperty(trackById)) block = lastBlockMap[trackById], delete lastBlockMap[trackById], nextBlockMap[trackById] = block, nextBlockOrder[index] = block; | |
else { | |
if (nextBlockMap.hasOwnProperty(trackById)) throw forEach(nextBlockOrder, function(block) { | |
block && block.startNode && (lastBlockMap[block.id] = block) | |
}), ngRepeatMinErr("dupes", "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}", expression, trackById); | |
nextBlockOrder[index] = { | |
id: trackById | |
}, nextBlockMap[trackById] = !1 | |
} | |
for (key in lastBlockMap) lastBlockMap.hasOwnProperty(key) && (block = lastBlockMap[key], elementsToRemove = getBlockElements(block), $animate.leave(elementsToRemove), forEach(elementsToRemove, function(element) { | |
element[NG_REMOVED] = !0 | |
}), block.scope.$destroy()); | |
for (index = 0, length = collectionKeys.length; index < length; index++) { | |
if (key = collection === collectionKeys ? index : collectionKeys[index], value = collection[key], block = nextBlockOrder[index], nextBlockOrder[index - 1] && (previousNode = nextBlockOrder[index - 1].endNode), block.startNode) { | |
childScope = block.scope, nextNode = previousNode; | |
do nextNode = nextNode.nextSibling; while (nextNode && nextNode[NG_REMOVED]); | |
block.startNode == nextNode || $animate.move(getBlockElements(block), null, jqLite(previousNode)), previousNode = block.endNode | |
} else childScope = $scope.$new(); | |
childScope[valueIdentifier] = value, keyIdentifier && (childScope[keyIdentifier] = key), childScope.$index = index, childScope.$first = 0 === index, childScope.$last = index === arrayLength - 1, childScope.$middle = !(childScope.$first || childScope.$last), childScope.$odd = !(childScope.$even = index % 2 == 0), block.startNode || linker(childScope, function(clone) { | |
clone[clone.length++] = document.createComment(" end ngRepeat: " + expression + " "), $animate.enter(clone, null, jqLite(previousNode)), previousNode = clone, block.scope = childScope, block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0], block.endNode = clone[clone.length - 1], nextBlockMap[block.id] = block | |
}) | |
} | |
lastBlockMap = nextBlockMap | |
}) | |
} | |
var uid = ["0", "0", "0"], | |
jqLite = angular.element, | |
forEach = angular.forEach, | |
NG_REMOVED = "$$NG_REMOVED", | |
ngRepeatMinErr = minErr("ngRepeat"), | |
ngMinErr = minErr("ng"), | |
toString = Object.prototype.toString, | |
isFunction = angular.isFunction, | |
isUndefined = angular.isUndefined, | |
toJson = angular.toJson; | |
return { | |
restrict: "A", | |
transclude: "element", | |
priority: 1e3, | |
terminal: !0, | |
require: "^frangTree", | |
compile: function(element, attr, linker) { | |
return function($scope, $element, $attr, ctrl) { | |
var trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, lhs, rhs, valueIdentifier, keyIdentifier, expression = $attr.frangTreeRepeat, | |
match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), | |
hashFnLocals = { | |
$id: hashKey | |
}; | |
if (!match) throw ngRepeatMinErr("iexp", "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", expression); | |
if (lhs = match[1], rhs = match[2], trackByExp = match[4], trackByExp ? (trackByExpGetter = $parse(trackByExp), trackByIdExpFn = function(key, value, index) { | |
return keyIdentifier && (hashFnLocals[keyIdentifier] = key), hashFnLocals[valueIdentifier] = value, hashFnLocals.$index = index, trackByExpGetter($scope, hashFnLocals) | |
}) : (trackByIdArrayFn = function(key, value) { | |
return hashKey(value) | |
}, trackByIdObjFn = function(key) { | |
return key | |
}), match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/), !match) throw ngRepeatMinErr("iidexp", "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", lhs); | |
valueIdentifier = match[3] || match[1], keyIdentifier = match[2]; | |
addRepeatWatch($scope, $element, {}, valueIdentifier, keyIdentifier, rhs, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, linker, expression), ctrl.init(function($scope, $element, collection) { | |
addRepeatWatch($scope, $element, {}, valueIdentifier, keyIdentifier, collection, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, linker, expression) | |
}) | |
} | |
} | |
} | |
}).directive("frangTreeInsertChildren", function() { | |
return { | |
restrict: "EA", | |
require: "^frangTree", | |
link: function(scope, element, attrs, ctrl) { | |
var comment = document.createComment("treeRepeat"); | |
element.append(comment), ctrl.insertChildren(scope, angular.element(comment), attrs.frangTreeInsertChildren) | |
} | |
} | |
}).directive("frangTreeDrag", function($parse) { | |
return { | |
restrict: "A", | |
require: "^frangTree", | |
link: function(scope, element, attrs, ctrl) { | |
var el = element[0], | |
parsedDrag = $parse(attrs.frangTreeDrag); | |
el.draggable = !0, el.addEventListener("dragstart", function(e) { | |
return e.stopPropagation && e.stopPropagation(), e.dataTransfer.effectAllowed = "move", e.dataTransfer.setData("Text", "nothing"), element.addClass("tree-drag"), ctrl.dragData = parsedDrag(scope), !1 | |
}, !1), el.addEventListener("dragend", function(e) { | |
return e.stopPropagation && e.stopPropagation(), element.removeClass("tree-drag"), ctrl.dragData = null, !1 | |
}, !1) | |
} | |
} | |
}).directive("frangTreeDrop", function($parse) { | |
return { | |
restrict: "A", | |
require: "^frangTree", | |
link: function(scope, element, attrs, ctrl) { | |
var el = element[0], | |
parsedDrop = $parse(attrs.frangTreeDrop), | |
parsedAllowDrop = $parse(attrs.frangTreeAllowDrop || "true"); | |
el.addEventListener("dragover", function(e) { | |
return parsedAllowDrop(scope, { | |
dragData: ctrl.dragData | |
}) && (e.stopPropagation && e.stopPropagation(), e.dataTransfer.dropEffect = "move", element.addClass("tree-drag-over"), e.preventDefault && e.preventDefault()), !1 | |
}, !1), el.addEventListener("dragenter", function(e) { | |
return parsedAllowDrop(scope, { | |
dragData: ctrl.dragData | |
}) && (e.stopPropagation && e.stopPropagation(), element.addClass("tree-drag-over"), e.preventDefault && e.preventDefault()), !1 | |
}, !1), el.addEventListener("dragleave", function(e) { | |
return parsedAllowDrop(scope, { | |
dragData: ctrl.dragData | |
}) && (e.stopPropagation && e.stopPropagation(), element.removeClass("tree-drag-over")), !1 | |
}, !1), el.addEventListener("drop", function(e) { | |
return parsedAllowDrop(scope, { | |
dragData: ctrl.dragData | |
}) && (e.stopPropagation && e.stopPropagation(), element.removeClass("tree-drag-over"), scope.$apply(function() { | |
parsedDrop(scope, { | |
dragData: ctrl.dragData | |
}) | |
}), ctrl.dragData = null, e.preventDefault && e.preventDefault()), !1 | |
}, !1) | |
} | |
} | |
}), angular.module("ngTableResizableColumns", []).directive("ngTableResizableColumns", function() { | |
function ResizableColumns($table, loading) { | |
var __bind = function(fn, me) { | |
return function() { | |
return fn.apply(me, arguments) | |
} | |
}; | |
this.loading = loading, this.pointerdown = __bind(this.pointerdown, this); | |
this.options = { | |
store: window.store, | |
rigidSizing: !1, | |
resizeFromBody: !0 | |
}, this.$table = $table, this.setHeaders(), this.restoreColumnWidths(), this.syncHandleWidths() | |
} | |
var parseWidth = function(node) { | |
return parseFloat(node.style.width.replace("%", "")) | |
}, | |
setWidth = function(node, table, width) { | |
return table && (table.find(".results-column")[node.cellIndex].style.width = "" + width.toFixed(2) + "%"), node.style.width = "" + width.toFixed(2) + "%" | |
}, | |
pointerX = function(e) { | |
return 0 === e.type.indexOf("touch") ? (e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]).pageX : e.pageX | |
}; | |
return ResizableColumns.prototype.getColumnId = function($el) { | |
return this.$table.data("resizable-columns-id") + "-" + $el.attr("data-resizable-column-id") | |
}, ResizableColumns.prototype.setHeaders = function() { | |
return this.$tableHeaders = this.$table.find("thead tr:first th:visible"), this.assignPercentageWidths(), this.createHandles() | |
}, ResizableColumns.prototype.destroy = function() { | |
return this.$handleContainer.remove(), this.$table.removeData("resizableColumns"), $(window).off(".rc") | |
}, ResizableColumns.prototype.assignPercentageWidths = function() { | |
var _this = this, | |
variableWidthHeaders = [], | |
totalWidth = 0; | |
return this.$tableHeaders.each(function(i, el) { | |
var $el; | |
$el = $(el), $el[0].attributes.getNamedItem("data-noresize") || variableWidthHeaders.push($el); | |
var elWidth = $el.outerWidth() / _this.$table.width() * 100; | |
if (totalWidth += Math.round(100 * elWidth) / 100, !_this.loading) { | |
if (i === _this.$tableHeaders.length - 1 && 100 != totalWidth && variableWidthHeaders.length > 0) { | |
var currentWidth = Number(parseWidth(variableWidthHeaders[0][0])); | |
setWidth(variableWidthHeaders[0][0], _this.$table, currentWidth + (100 - totalWidth)) | |
} | |
return setWidth($el[0], _this.$table, elWidth) | |
} | |
}) | |
}, ResizableColumns.prototype.createHandles = function() { | |
var _ref, _this = this; | |
return null != (_ref = this.$handleContainer) && _ref.remove(), this.$table.before(this.$handleContainer = $("<div class='rc-handle-container' />")), this.$tableHeaders.each(function(i, el) { | |
var $handle; | |
if (0 !== _this.$tableHeaders.eq(i + 1).length && null == _this.$tableHeaders.eq(i).attr("data-noresize") && null == _this.$tableHeaders.eq(i + 1).attr("data-noresize")) return $handle = $("<div class='rc-handle' />"), $handle.data("th", $(el)), $handle.appendTo(_this.$handleContainer) | |
}), this.$handleContainer.on("mousedown touchstart", ".rc-handle", this.pointerdown) | |
}, ResizableColumns.prototype.syncHandleWidths = function() { | |
var _this = this; | |
this.setHeaders(); | |
var theColumns = this.$table.find(".results-column"); | |
return this.$tableHeaders.each(function(i, el) { | |
var myCol = theColumns[i]; | |
myCol.style.width = el.style.width | |
}), this.$handleContainer.width(this.$table.width()).find(".rc-handle").each(function(_, el) { | |
var $el; | |
return $el = $(el), $el.css({ | |
left: $el.data("th").outerWidth() + ($el.data("th").offset().left - _this.$handleContainer.offset().left), | |
height: _this.options.resizeFromBody ? _this.$table.height() : _this.$table.find("thead").height() | |
}) | |
}) | |
}, ResizableColumns.prototype.saveColumnWidths = function() { | |
var _this = this; | |
return this.$tableHeaders.each(function(_, el) { | |
var $el; | |
if ($el = $(el), null == $el.attr("data-noresize") && null != _this.options.store) return _this.options.store.set(_this.getColumnId($el), parseWidth($el[0])) | |
}) | |
}, ResizableColumns.prototype.restoreColumnWidths = function() { | |
var _this = this; | |
return this.$tableHeaders.each(function(_, el) { | |
var $el, width; | |
if ($el = $(el), null != _this.options.store && (width = _this.options.store.get(_this.getColumnId($el)))) return setWidth($el[0], _this.$table, width) | |
}) | |
}, ResizableColumns.prototype.totalColumnWidths = function() { | |
var total; | |
return total = 0, this.$tableHeaders.each(function(_, el) { | |
return total += parseFloat($(el)[0].style.width.replace("%", "")) | |
}), total | |
}, ResizableColumns.prototype.pointerdown = function(e) { | |
var $currentGrip, $leftColumn, $rightColumn, startPosition, widths, _this = this; | |
return e.preventDefault(), startPosition = pointerX(e), $currentGrip = $(e.currentTarget), $leftColumn = $currentGrip.data("th"), $rightColumn = this.$tableHeaders.eq(this.$tableHeaders.index($leftColumn) + 1), widths = { | |
left: parseWidth($leftColumn[0]), | |
right: parseWidth($rightColumn[0]) | |
}, this.$table.addClass("rc-table-resizing"), $(document).on("mousemove.rc touchmove.rc", function(e) { | |
var difference; | |
return difference = (pointerX(e) - startPosition) / _this.$table.width() * 100, setWidth($rightColumn[0], _this.$table, widths.right - difference), setWidth($leftColumn[0], _this.$table, widths.left + difference) | |
}), $(document).one("mouseup touchend", function() { | |
return $(document).off("mousemove.rc touchmove.rc"), _this.$table.removeClass("rc-table-resizing"), _this.syncHandleWidths(), _this.saveColumnWidths() | |
}) | |
}, { | |
restrict: "C", | |
priority: 999, | |
require: "ngTable", | |
link: function(scope, element, args, ngTable) { | |
var data; | |
scope.$watch("$data", function() { | |
data.destroy(), data = new ResizableColumns(element) | |
}), scope.$watch(function() { | |
return element[0].clientWidth | |
}, function() { | |
data.syncHandleWidths() | |
}), data = new ResizableColumns(element, !0) | |
} | |
} | |
}), angular.module("voyager.search").component("vsBotSearch", { | |
templateUrl: "src/bot/bot-search.html", | |
controller: function(searchService, $location, $scope) { | |
function _doSearch() { | |
var _params = $location.search(); | |
searchService.doSearch2(_params).then(function(res) { | |
vm.list = res.data.response.docs, vm.hasMore = 50 === vm.list.length | |
}) | |
} | |
var vm = this; | |
vm.hasMore = !0, $scope.$on("$locationChangeSuccess", function() { | |
if ("/bot" === $location.path()) { | |
var page = $location.search().page; | |
angular.isDefined(page) && parseInt(page) !== vm.page && (vm.page = parseInt(page), searchService.setPage(vm.page), _doSearch()) | |
} | |
}), vm.$onInit = function() { | |
vm.page = 1, angular.isDefined($location.search().page) && (vm.page = parseInt($location.search().page)), searchService.setItemsPerPage(50), searchService.setPage(vm.page), _doSearch() | |
} | |
} | |
}); | |
var VoyagerHome; | |
! function(VoyagerHome) { | |
var QuickLinks = function() { | |
function QuickLinks() { | |
this.templateUrl = "src/home/quick-links.html", this.bindings = { | |
title: "@", | |
list: "<" | |
}, this.controller = Controller | |
} | |
return QuickLinks | |
}(); | |
VoyagerHome.QuickLinks = QuickLinks; | |
var Controller = function() { | |
function Controller(savedSearchService, $scope, $timeout, sugar) { | |
this.savedSearchService = savedSearchService, this.$scope = $scope, this.$timeout = $timeout, this.sugar = sugar, this.categories = [] | |
} | |
return Controller.prototype.$onChanges = function(changesObj) { | |
if (changesObj.list && changesObj.list.currentValue) { | |
var categoryMap = this.sugar.toMapList("categories", changesObj.list.currentValue), | |
categoryList = this.sugar.mapToList(categoryMap); | |
if (categoryList.length > 0) { | |
var others = changesObj.list.currentValue.filter(function(item) { | |
return void 0 === item.categories | |
}); | |
others.length > 0 && categoryList.push({ | |
key: "Others", | |
list: others | |
}), this.categories = _.sortBy(categoryList, "title"), this.categories[0].displayState = "in" | |
} | |
} | |
}, Controller.prototype.applyCollection = function(saved) { | |
this.savedSearchService.applySavedSearch(saved, this.$scope) | |
}, Controller.prototype.toggleDisplayState = function(category) { | |
this.$timeout(function() { | |
category.displayState = "in" === category.displayState ? "" : "in" | |
}, 0) | |
}, Controller | |
}() | |
}(VoyagerHome || (VoyagerHome = {})); | |
var VoyagerHome; | |
! function(VoyagerHome) { | |
function init() { | |
angular.module("voyager.home").component("vsQuickLinks", new VoyagerHome.QuickLinks) | |
} | |
VoyagerHome.init = init | |
}(VoyagerHome || (VoyagerHome = {})), VoyagerHome.init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment