blob: 65675a1b6f0678698387349009deb851ed6ec850 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// toggleCalendar: Expands/contracts years in the calendar (to show/hide months)
function toggleCalendar(year) {
var cal = document.getElementById('cal_' + year)
if (cal) {
cal.style.display = (cal.style.display == 'none') ? 'block' : 'none';
for (var i = 1970; i < 3000; i++) {
var x = document.getElementById('cal_' + i)
if (x && x != cal) {
x.style.display = 'none'
}
}
}
}
// buildCalendar: build the calendar
function buildCalendar(firstYear, lastYear) {
var dp = document.getElementById('datepicker')
dp.style.width = "150px"
dp.innerHTML = "<h3>Archive:</h3>"
var fyear = lastYear ? lastYear : new Date().getFullYear();
// Check we don't esplode
if (fyear > new Date().getFullYear()) {
fyear = new Date().getFullYear();
}
for (var year = fyear; year >= (firstYear ? firstYear : current_cal_min); year--) {
var n = "none";
if (fyear == firstYear) {
n = "block"
}
dp.innerHTML += "<label onmouseout='this.setAttribute(\"class\", \"label label-success\");' onmouseover='this.setAttribute(\"class\", \"label label-warning\");' onclick='toggleCalendar(" + year + ");' class='label label-success' style='float: left; width: 120px; font-size: 11pt; cursor: pointer'>" + year + "</label><br/>"
var cale = "<div style='float: left; width: 90%; display: " + n + "; padding-left: 20px; margin-bottom: 15px;' id='cal_" + year + "'>"
var em = (new Date().getFullYear() == year) ? new Date().getMonth() : 11;
for (var y = em; y >= 0; y--) {
var url = "/list.html?" + xlist + ":" + (year+"-"+(y+1))
cale += "<a href='" + url + "' onclick='return false;'><label id='calmonth_" + (year+"-"+(y+1)) + "' style='width: 80px; float: left;cursor: pointer;' class='label label-default label-hover' onclick='toggleEmail(" + year + ", " + (y + 1) + ");' >" + months[y] + "</label></a><br/>"
}
cale += "</div>"
dp.innerHTML += cale
}
}
// dailyStats: compiles the day-by-day stats for a chunk of emails
function dailyStats(json) {
var days = {}
for (var i in json) {
var day = new Date(json[i].epoch * 1000).getDate()
days[day] = days[day] ? (days[day] + 1) : 1
}
var stats = []
for (var z = 0; z < 32; z++) {
stats.push(days[z] ? days[z] : 0)
}
return stats
}
function clearCalendarHover() {
kiddos = []
traverseThread(document.getElementById('datepicker'), 'calmonth', 'LABEL')
for (var n in kiddos) {
kiddos[n].setAttribute("class", "label label-default label-hover")
}
}
// checkCalendar: keep the calendar in check with the result set
function checkCalendar(json) {
if (json.list && !list_year[json.list]) {
xlist = (json.list && json.list.search(/\*/) == -1) ? json.list : xlist
list_year[json.list] = json.firstYear
buildCalendar(json.firstYear, json.lastYear)
}
if (xlist != json.list || current_cal_min != json.firstYear) {
buildCalendar(json.firstYear, json.lastYear)
xlist = (json.list && json.list.search(/\*/) == -1) ? json.list : xlist
current_cal_min = json.firstYear
}
}
// buildStats: build the stats window
function buildStats(json, state, show) {
var stats = document.getElementById('stats')
stats.style.width = "300px"
stats.innerHTML = "<br/><h4>Stats for this blob of emails:</h4>"
if (!json.emails || json.emails.length == 0) {
stats.innerHTML = "<br/><br/>No emails found matching this criteria"
document.getElementById('emails').innerHTML = ""
return;
}
if (json.emails && json.emails.length >= json.max) {
stats.innerHTML += "<font color='#FA0'>More than " + json.max.toLocaleString() + " emails found, truncating!</font><br/>"
}
var ap = ""
if (json.numparts && json.numparts > 1) {
ap = " by " + json.numparts + " people"
}
stats.innerHTML += (json.emails.length ? json.emails.length : 0) + " emails sent" + ap + ", divided into " + json.no_threads + " topics."
stats.innerHTML += "[<a href='/trends.html" + document.location.search + "'>details</a>]"
stats.innerHTML += "<br/>"
var ts = "<table border='0'><tr>"
var ms = dailyStats(json.emails)
var max = 1
for (var i in ms) {
max = Math.max(max, ms[i])
}
for (var i in ms) {
ts += "<td style='padding-left: 2px; vertical-align: bottom'><div title='" + ms[i] + " emails' style='background: #369; width: 6px; height: " + parseInt((ms[i] / max) * 60) + "px;'> </div></td>"
}
ts += "</tr></table>"
stats.innerHTML += ts
stats.innerHTML += "<h4>Top 10 contributors:</h4>"
for (var i in json.participants) {
if (i >= 10) {
break;
}
var par = json.participants[i]
if (par.name.length > 24) {
par.name = par.name.substr(0, 23) + "..."
}
if (par.name.length == 0) {
par.name = par.email
}
stats.innerHTML += "<img src='https://secure.gravatar.com/avatar/" + par.gravatar + ".jpg?s=32&r=g&d=mm' style='vertical-align:middle'/>&nbsp;<a href='javascript:void(0)' onclick='do_search(\"" + par.email + "\", \"" + current_retention + "\")'><b>" + par.name.replace(/[<>]/g, "") + "</a>:</b> " + par.count + " email(s)<br/>";
}
// Show display modes
stats.innerHTML += "<br/><br/><b>Display mode:</b><br/>"
for (var mode in viewModes) {
var btn = document.createElement('a')
btn.setAttribute("href", "javascript:void(0);")
btn.setAttribute("class", "btn btn-" + ((prefs.displayMode == mode) ? 'info' : 'default'))
btn.setAttribute("onclick", "prefs.displayMode='" + mode + "'; buildPage();")
btn.style.marginRight = "10px"
btn.innerHTML = mode
stats.appendChild(btn)
}
var btn = document.createElement('a')
btn.setAttribute("href", "javascript:void(0);")
btn.setAttribute("class", "btn btn-warning")
btn.setAttribute("onclick", "prefs.hideStats='yes'; buildStats(old_json, old_state, false);")
btn.style.marginRight = "10px"
btn.innerHTML = "Hide me!"
stats.appendChild(btn)
if (prefs.hideStats == 'yes' || show == false) {
document.getElementById('emails').style.width = "calc(100% - 190px)"
// Resize on resize to work around CSS bug. Might wanna move this elsewhere later on..
window.onresize = function() {
document.getElementById('emails').style.width = "calc(100% - 190px)"
}
stats.setAttribute("class", "col-md-1 vertical-text")
stats.innerHTML = "<div onclick=\"prefs.hideStats='no'; buildStats(old_json, old_state, true);\">Show stats panel..</div>"
}
if (prefs.hideStats == 'no' || show == true) {
stats.setAttribute("class", "hidden-xs hidden-sm hidden-md col-lg-3")
var sw = document.getElementById('datepicker').offsetWidth + 30 + stats.offsetWidth;
document.getElementById('emails').style.width = "calc(100% - " + sw + "px)"
// Resize on resize to work around CSS bug. Might wanna move this elsewhere later on..
window.onresize = function() {
var sw = document.getElementById('datepicker').offsetWidth + 30 + stats.offsetWidth;
document.getElementById('emails').style.width = "calc(100% - " + sw + "px)"
}
stats.removeAttribute("onclick")
//stats.style.display = "block"
if (json.cloud) {
for (var i in json.cloud) {
stats.innerHTML += "<h4 style='text-align: center;'>Hot topics:</h4>"
stats.appendChild(wordCloud(json.cloud, 250, 80))
break // so..this'll run if cloud has stuff, otherwise not.
}
}
}
}
// buildPage: build the entire page!
function buildPage(json, state) {
start = new Date().getTime()
pb_refresh = start
json = json ? json : old_json
old_json = json
old_state = state
current_thread_mids = []
checkCalendar(json)
document.title = json.list + " - Pony Mail!"
// if we have xdomain, rewrite the wording in quick search.
var lcheckall = document.getElementById('lcheckall')
if (lcheckall && gxdomain) {
lcheckall.innerHTML = "Search all " + gxdomain + " lists"
}
// Add Opensearch title to OS image
var os = document.getElementById('opensearch')
if (os){
os.setAttribute("title", "Add " + gxdomain + " archives to your search engines")
}
buildStats(json, state, null)
nest = ""
viewModes[prefs.displayMode].list(json, 0, 0, state ? state.deep : false);
if (!json.emails || !json.emails.length || json.emails.length == 0) {
document.getElementById('emails').innerHTML += "<h3>No emails found fitting this criteria</h3>"
}
if (json.private && json.private == true) {
document.getElementById('emails').innerHTML += "<h4>Looks like you don't have access to this archive. Maybe you need to be logged in?</h4>"
}
if (json.took) {
var rtime = new Date().getTime() - start
document.getElementById('emails').innerHTML += "<br/><br/><small><i>Compiled in " + parseInt(json.took / 1000) + "ms, rendered in " + rtime + "ms</i></small>"
}
if (json.debug && pm_config.debug) {
document.getElementById('emails').innerHTML += "<br/><br/><small><i>Debug times: " + json.debug.join(" + ") + "</i></small>"
}
}
// getListInfo: Renders the top ML index
function getListInfo(list, xdomain, nopush) {
current_query = ""
var dealtwithit = false
if (xdomain && xdomain.search("utm_source=opensearch") != -1) {
var strs = xdomain.split(/&/)
for (var i in strs) {
var kv = strs[i].split(/=/)
if (kv[0] == "websearch") {
current_query = kv[1]
}
if (kv[0] == "domain") {
xdomain = kv[1]
xlist = "*@" + xdomain;
list = xlist;
if (document.getElementById('checkall')) {
document.getElementById('checkall').checked = true
}
}
}
nopush = true
dealtwithit = true
search(current_query, "lte=1M", true, true)
}
else if (xdomain && xdomain != "") {
if (xdomain.length <= 1) {
xdomain = null
} else {
if (xdomain.search(/:/) != -1) {
var arr = xdomain.split(/:/)
xdomain = arr[0]
xlist = xdomain
if (arr[1].search(/-/) != -1 && arr[1].search("|") == -1) {
var ya = arr[1].split(/-/)
toggleEmail(ya[0], ya[1], nopush)
dealtwithit = true
} else {
current_retention = parseInt(arr[1])
if (("x"+current_retention) != ("x"+arr[1])) {
current_retention = arr[1]
nopush = true
}
current_query = unescape(arr[2])
}
}
if (xdomain.search(/@/) != -1) {
list = xdomain;
xlist = list
xdomain = xdomain.replace(/^.*?@/, "")
}
}
}
if (xdomain == undefined || xdomain == "" && list) {
xdomain = list.replace(/^.*?@/, "")
}
if (!list || list.length <= 1) {
list = 'dev@' + xdomain
}
if (!firstVisit && !nopush) {
window.history.pushState({}, "", "list.html?" + xlist);
firstVisit = false
}
//buildCalendar()
var dp = document.getElementById('dp')
dp[0].text = datePickerValue(current_retention)
dp[0].value = current_retention
document.getElementById('q').value = unescape(current_query)
document.getElementById('aq').value = unescape(current_query)
xlist = list;
var arr = list.split('@', 2)
var listname = arr[0]
var domain = arr[1]
var lc = document.getElementById('lc_dropdown');
lc.innerHTML = ""
var dom_sorted = []
for (var dom in all_lists) {
dom_sorted.push(dom)
}
// Sort out available domains with MLs
for (var i in dom_sorted.sort()) {
var dom = dom_sorted[i]
var li = document.createElement("li")
var a = document.createElement("a")
var t = document.createTextNode(dom)
a.setAttribute("href", "list.html?" + dom)
a.appendChild(t)
li.appendChild(a)
lc.appendChild(li)
}
// If we have a domain ML listing, sort out the nav bar
if (all_lists[xdomain]) {
var ll = document.getElementById('listslist')
ll.innerHTML = ""
var listnames = []
for (var key in all_lists[xdomain]) {
listnames.push(key)
}
var overlaps = []
listnames = listnames.sort(function(a, b) {
return all_lists[xdomain][b] - all_lists[xdomain][a]
})
for (var i in listnames) {
var key = listnames[i]
var collapse = ''
if (i >= 4) {
collapse = 'hidden-xs hidden-sm hidden-md hidden-lg'
overlaps.push(key)
}
var ln = key + '@' + xdomain
//alert("adding" + ln)
var li = document.createElement("li")
var a = document.createElement("a")
var t = document.createTextNode(key + '@')
a.setAttribute("href", "javascript:void(0);")
a.setAttribute("onclick", "getListInfo(this.getAttribute('id'))")
a.setAttribute("id", ln)
a.appendChild(t)
li.appendChild(a)
ll.appendChild(li)
if (!all_lists[xdomain][listname]) {
listname = key
list = ln
xlist = ln
}
if (list == ln) {
li.setAttribute("class", "active " + collapse)
} else {
li.setAttribute("class", collapse)
}
}
if (overlaps.length > 0) {
ll.innerHTML += '<li class="dropdown navbar-right" id="otherlists"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Other lists:<span class="caret"></span></a><ul class="dropdown-menu" id="otherlists_dropdown"></ul></li>'
var ul = document.getElementById('otherlists_dropdown')
for (var i in overlaps) {
var key = overlaps[i]
var ln = key + '@' + xdomain
var li = document.createElement("li")
var a = document.createElement("a")
var t = document.createTextNode(key + '@')
a.setAttribute("href", "javascript:void(0);")
a.setAttribute("onclick", "getListInfo(this.getAttribute('id'))")
a.setAttribute("id", ln)
a.appendChild(t)
li.appendChild(a)
ul.appendChild(li)
if (list == ln) {
li.setAttribute("class", "active")
} else {
li.setAttribute("class", "")
}
}
}
}
gxdomain = xdomain
addSearchBar();
if (!dealtwithit) {
kiddos = []
traverseThread(document.getElementById('datepicker'), 'calmonth', 'LABEL')
for (var n in kiddos) {
kiddos[n].setAttribute("class", "label label-default label-hover")
}
document.getElementById('listtitle').innerHTML = list + ", last month"
if (current_query == "") {
global_deep = false
current_query = ""
GetAsync("/api/stats.lua?list=" + listname + "&domain=" + domain, null, buildPage)
if (!nopush) {
window.history.pushState({}, "", "list.html?" + xlist);
}
} else {
search(current_query, current_retention, nopush)
}
}
}