changeset 1606:2c8b985ebde5

mod_http_muc_log: Switch to a calendar view for selecting dates
author Kim Alvefur <zash@zash.se>
date Tue, 10 Feb 2015 15:00:10 +0100
parents c8a51d1bc96d
children 8b997d9cf09e
files mod_http_muc_log/http_muc_log.html mod_http_muc_log/mod_http_muc_log.lua
diffstat 2 files changed, 82 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/mod_http_muc_log/http_muc_log.html	Mon Feb 09 00:47:38 2015 +0100
+++ b/mod_http_muc_log/http_muc_log.html	Tue Feb 10 15:00:10 2015 +0100
@@ -26,6 +26,10 @@
 nav .next::after{content:" →";}
 nav .prev::before{content:"← ";}
 nav :empty::after,nav :empty::before{content:""}
+table{display:inline-block; margin:1ex 1em;}
+th{font-size:x-small}
+td{text-align:right;color:#bababa;padding:.5ex}
+td a{padding:0}
 .content{background-color:white;padding:1em;list-style-position:inside;}
 .time{float:right;font-size:small;opacity:0.2;}
 li:hover .time{opacity:1;}
@@ -51,9 +55,16 @@
 <dt class="name"><a href="{href}">{name}</a></dt>
 <dd class="description">{description?}</dd>}
 </dl>
-<ul class="dates">{dates#
-<li><a href="{date}">{date}</a></li>}
-</ul>
+{years#
+<h2 id="{year}">{year}</h2>
+{months#
+<table id="{month}-{year}">
+<caption>{month}</caption>
+<tr><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th><th>Sun</th></tr>{weeks#
+<tr>{days#<td>{plain?}{links#<a href="{href}">{day}</a>}</td>}</tr>}
+</table>
+}
+}
 </nav>
 <ol class="chat-logs">{lines#
 <li class="{st_name} {st_type?}" id="{key}">
--- a/mod_http_muc_log/mod_http_muc_log.lua	Mon Feb 09 00:47:38 2015 +0100
+++ b/mod_http_muc_log/mod_http_muc_log.lua	Tue Feb 10 15:00:10 2015 +0100
@@ -1,4 +1,5 @@
 local st = require "util.stanza";
+local mt = require"util.multitable";
 local datetime = require"util.datetime";
 local jid_split = require"util.jid".split;
 local nodeprep = require"util.encodings".stringprep.nodeprep;
@@ -8,6 +9,7 @@
 local url = require"socket.url";
 local xml_escape = st.xml_escape;
 local t_concat = table.concat;
+local os_time, os_date = os.time, os.date;
 
 local archive = module:open_store("muc_log", "archive");
 
@@ -92,40 +94,90 @@
 		and room._data.logging == true);
 end
 
--- FIXME Invent some more efficient API for this
-local function dates_page(event, path)
+local function sort_Y(a,b) return a.year > b.year end
+local function sort_m(a,b) return a.n > b.n end
+
+local t_diff = os_time(os_date("*t")) - os_time(os_date("!*t"));
+local function time(t)
+	return os_time(t) + t_diff;
+end
+
+local function years_page(event, path)
 	local request, response = event.request, event.response;
 
 	local room = nodeprep(path:match("^(.*)/$"));
 	if not room or not public_room(room) then return end
 
-	local dates, i = {}, 1;
+	local dates = mt.new();
 	module:log("debug", "Find all dates with messages");
-	local prev_day;
+	local next_day, t;
 	repeat
 		local iter = archive:find(room, {
-			["end"] = prev_day;
+			start = next_day;
 			limit = 1;
 			with = "message<groupchat";
-			reverse = true;
 		})
 		if not iter then break end
-		prev_day = nil;
+		next_day = nil;
 		for key, message, when in iter do
-			prev_day = datetime.date(when);
-			dates[i], i = {
-				date = prev_day;
-			}, i + 1;
-			prev_day = datetime.parse(prev_day .. "T00:00:00Z") - 1;
+			t = os_date("!*t", when);
+			dates:set(t.year, t.month, t.day, when );
+			next_day = when + (86400 - (when % 86400));
 			break;
 		end
-	until not prev_day;
+	until not next_day;
+
+	local year, years;
+	local month, months;
+	local week, weeks;
+	local days;
+	local tmp, n;
+
+	years = {};
+
+	for Y, m in pairs(dates.data) do
+		t = { year = Y, month = 1, day = 1 };
+		months = { };
+		year = { year = Y, months = months };
+		years[#years+1] = year;
+		for m, d in pairs(m) do
+			t.day = 1;
+			t.month = m;
+			tmp = os_date("!*t", time(t));
+			days = {};
+			week = { days = days }
+			weeks = { week };
+			month = { year = year.year, month = os_date("!%B", time(t)), n = m, weeks = weeks };
+			months[#months+1] = month;
+			n = 1;
+			for i=1, (tmp.wday+5)%7 do
+				days[n], n = {}, n+1;
+			end
+			for i = 1, 31 do
+				t.day = i;
+				tmp = os_date("!*t", time(t));
+				if tmp.month ~= m then break end
+				if i > 1 and tmp.wday == 2 then
+					days = {};
+					weeks[#weeks+1] = { days = days };
+					n = 1;
+				end
+				if d[i] then
+					days[n], n = { wday = tmp.wday, links = {{ href = datetime.date(d[i]), day = i }} }, n+1;
+				else
+					days[n], n = { wday = tmp.wday, plain = i }, n+1;
+				end
+			end
+		end
+		table.sort(year, sort_m);
+	end
+	table.sort(years, sort_Y);
 
 	response.headers.content_type = "text/html; charset=utf-8";
 	return render(template, {
 		title = get_room(room):get_name();
 		jid = get_room(room).jid;
-		dates = dates;
+		years = years;
 		links = {
 			{ href = "../", rel = "up", text = "Back to room list" },
 		};
@@ -138,7 +190,7 @@
 	local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$");
 	room = nodeprep(room);
 	if not room then
-		return dates_page(event, path);
+		return years_page(event, path);
 	end
 	if not public_room(room) then return end
 
@@ -208,7 +260,7 @@
 		jid = get_room(room).jid;
 		lines = logs;
 		links = {
-			{ href = "./", rel = "up", text = "Back to date list" },
+			{ href = "./", rel = "up", text = "Back to calendar" },
 			{ href = prev_when, rel = "prev", text = prev_when},
 			{ href = next_when, rel = "next", text = next_when},
 		};