Mercurial > bugzilla-dashboard
view js/modules/app.js @ 82:03bf0a1b85da
made 'storage' point to sessionStorage instead of localStorage
author | Atul Varma <avarma@mozilla.com> |
---|---|
date | Mon, 26 Apr 2010 04:32:50 -0700 |
parents | e3de1fe32f40 |
children | ee0a4597c067 |
line wrap: on
line source
Require.modules["app/loader"] = function(exports, require) { exports.init = function init(moduleExports, options) { var bugzilla = require("app/bugzilla-auth").create(options.Bugzilla); moduleExports.bugzilla = bugzilla; moduleExports.window = options.window; moduleExports.storage = options.window.sessionStorage; moduleExports.jQuery = options.jQuery; require("app/ui").init(options.window.document); }; }; Require.modules["app/login"] = function(exports) { var callbacks = []; var username; var password; var passwordProvider; exports.setPasswordProvider = function setPasswordProvider(pp) { passwordProvider = pp; }; exports.whenChanged = function whenChanged(cb) { callbacks.push(cb); }; exports.get = function get() { var isLoggedIn = (username && username != ""); var isAuthenticated = (isLoggedIn && password && password != ""); return { username: username, password: password, isLoggedIn: isLoggedIn, isAuthenticated: isAuthenticated }; }; exports.set = function set(newUsername, newPassword) { if ((newUsername && newUsername != "") && (!newPassword || newPassword == "") && (passwordProvider)) newPassword = passwordProvider(newUsername); if (newUsername == username && newPassword == password) return; username = newUsername; password = newPassword; var info = exports.get(); callbacks.forEach(function(cb) { cb(info); }); }; }; Require.modules["app/bugzilla-auth"] = function(exports, require) { exports.create = function(Bugzilla) { function AuthenticatedBugzilla() { this.ajax = function ajax(options) { var user = require("app/login").get(); if (user.isAuthenticated) { if (!options.data) options.data = {}; options.data.username = user.username; options.data.password = user.password; } return Bugzilla.ajax.call(this, options); }; } AuthenticatedBugzilla.prototype = Bugzilla; return new AuthenticatedBugzilla(); }; }; Require.modules["app/commands"] = function(exports, require) { var commands = {}; exports.get = function get(name) { if (!(name in commands)) throw new Error("command not found: " + name); return commands[name]; }; exports.register = function(options) { if (options.name in commands) throw new Error("command already registered: " + options.name); commands[options.name] = options; }; }; Require.modules["app/ui/login-form"] = function(exports, require) { var $ = require("jQuery"); var cachedUsername = $("#login .username").val(); var cachedPassword = $("#login .password").val(); $("#login form").submit( function(event) { event.preventDefault(); require("app/login").set($("#login .username").val(), $("#login .password").val()); $("#login").fadeOut(); }); require("app/login").whenChanged( function maybeChangeUsernameField(user) { var usernameField = $("#login .username"); if (user.isLoggedIn && usernameField.val() != user.username) usernameField.val(user.username); }); require("app/login").setPasswordProvider( function maybeGetCachedPasswordFromForm(username) { if (cachedUsername == username) return cachedPassword; return ""; }); exports.init = function init() { }; }; Require.modules["app/ui/file-bug"] = function(exports, require) { const EM_DASH = "\u2014"; var $ = require("jQuery"); var cache = require("cache"); var bugzilla = require("bugzilla"); var window = require("window"); var config = cache.get("configuration"); var needToFetchConfig = config ? false : true; var categories; var queuedRespond; function buildCategories() { categories = []; for (product in config.product) for (component in config.product[product].component) categories.push(product + EM_DASH + component); } function fetchConfig() { bugzilla.ajax({url: "/configuration", data: {flags: 0}, success: function(result) { config = result; cache.set("configuration", result); if (queuedRespond) queuedRespond(); }}); } var categoryOptions = { minLength: 2, source: function(request, response) { function respond() { queuedRespond = null; var suggs = []; var terms = request.term.split(" "); if (!categories) buildCategories(); categories.forEach( function(category) { for (var i = 0; i < terms.length; i++) if (!category.match(terms[i], "i")) return; suggs.push(category); }); response(suggs); }; if (!config) { queuedRespond = respond; if (needToFetchConfig) { needToFetchConfig = false; fetchConfig(); } } else respond(); } }; $("#file-bug .category").autocomplete(categoryOptions); $("#file-bug").submit( function(event) { event.preventDefault(); var parts = $("#file-bug .category").val().split(EM_DASH); window.open(bugzilla.BASE_UI_URL + "/enter_bug.cgi?" + "product=" + escape(parts[0]) + "&" + "component=" + escape(parts[1])); }); exports.init = function init() { }; }; Require.modules["app/ui/repair"] = function(exports, require) { var $ = require("jQuery"); $("#repair form").submit( function() { var phrase = $("#repair .phrase").val(); var response; if (phrase == "repair my dashboard") { require("cache").clear(); response = $("#templates .repair-success").clone(); } else response = $("#templates .repair-failure").clone(); $("#repair .result").empty().append(response); $("#repair .result").hide().slideDown(); }); exports.init = function init() { }; }; Require.modules["app/ui/find-user"] = function(exports, require) { var $ = require("jQuery"); var bugzilla = require("bugzilla"); var window = require("window"); var currReq; var options = { minLength: 2, delay: 1000, source: function(request, response) { function success(result) { currReq = null; var suggs = []; result.users.forEach( function(user) { suggs.push({label: user.real_name + " (" + user.name + ")", value: user.name}); }); response(suggs); } if (currReq) currReq.abort(); currReq = bugzilla.ajax({url: "/user", data: {match: request.term}, success: success}); } }; $("#find-user .query").autocomplete(options); $("#find-user form").submit( function(event) { event.preventDefault(); var username = $("#find-user .query").val(); var url = require("app/ui/hash").usernameToHash(username); window.open(url); }); exports.init = function init() { }; }; Require.modules["app/ui"] = function(exports, require) { var $ = require("jQuery"); require("app/login").whenChanged( function changeUI(user) { var show = { "no-login": false, "login": false, "auth-login": false, "no-auth": false, "no-auth-login": false }; if (user.isLoggedIn) { show["login"] = true; if (user.isAuthenticated) show["auth-login"] = true; else { show["no-auth"] = true; show["no-auth-login"] = true; } } else { show["no-login"] = true; show["no-auth"] = true; } for (classSuffix in show) { var query = $(".requires-" + classSuffix); if (show[classSuffix]) query.show(); else query.hide(); } }); $("#header .menu li").click( function onMenuItemClick(event) { if (this.hasAttribute("data-command")) { var cmdName = this.getAttribute("data-command"); require("app/commands").get(cmdName).execute(); } else openDialog(this.getAttribute("data-dialog")); }); $(".dialog").click( function dismissDialogOnOutsideClick(event) { if (event.target == this) $(this).fadeOut(); }); function dismissDialogOnEscape(event) { if (event.keyCode == 27) $(this).fadeOut(); } // For Safari. $(".dialog").keyup(dismissDialogOnEscape); // For Firefox. $(".dialog").keypress(dismissDialogOnEscape); function setupDocumentTitleChanger(document) { const BASE_TITLE = document.title; require("app/login").whenChanged( function changeTitle(user) { var title = BASE_TITLE; if (user.isLoggedIn) title = user.username + "'s " + BASE_TITLE; if (document.title != title) { document.title = title; $("#header .title").text(title); } }); }; function openDialog(name) { var dialog = $("#" + name); if (dialog.length == 0) throw new Error("dialog not found: " + name); dialog.fadeIn( function() { dialog.find("input:first").focus(); }); }; exports.init = function init(document) { setupDocumentTitleChanger(document); require("app/ui/repair").init(); require("app/ui/dashboard").init(); require("app/ui/login-form").init(); require("app/ui/find-user").init(); require("app/ui/file-bug").init(); require("app/ui/hash").init(document); if (!require("app/login").get().isLoggedIn) openDialog("login"); }; }; Require.modules["app/ui/hash"] = function(exports, require) { function usernameFromHash(location) { if (location.hash) { var match = location.hash.match(/#username=(.*)/); if (match) return unescape(match[1]); } return ""; } function setLoginFromHash(location) { var username = usernameFromHash(location); var user = require("app/login").get(); if (user.username != username) require("app/login").set(username); } exports.usernameToHash = function usernameToHash(username) { return "#username=" + escape(username); }; exports.init = function init(document) { require("app/login").whenChanged( function(user) { if (user.isLoggedIn) { var hash = exports.usernameToHash(user.username); if (document.location.hash != hash) document.location.hash = hash; } else document.location.hash = ""; }); var window = document.defaultView; function onHashChange() { setLoginFromHash(document.location); } if ("onhashchange" in window) window.addEventListener("hashchange", onHashChange, false); else window.setInterval(onHashChange, 1000); onHashChange(); }; }; Require.modules["app/ui/dashboard"] = function(exports, require) { var $ = require("jQuery"); var cache = require("cache"); var dateUtils = require("date-utils"); var bugzilla = require("bugzilla"); var window = require("window"); var xhrQueue = require("xhr/queue").create(); function sortByLastChanged(bugs) { var lctimes = {}; bugs.forEach( function(bug) { lctimes[bug.id] = dateUtils.dateFromISO8601(bug.last_change_time); }); function compare(a, b) { var alc = lctimes[a.id]; var blc = lctimes[b.id]; if (alc < blc) return -1; if (alc > blc) return 1; return 0; } bugs.sort(compare); } function updatePrettyDates(query) { query.find(".last-changed").each( function() { var lcTime = $(this).attr("data-last-change"); $(this).text(dateUtils.prettyDate(lcTime)); }); } const PRETTY_DATE_UPDATE_INTERVAL = 1000 * 60; window.setInterval(function() { updatePrettyDates($("#reports")); }, PRETTY_DATE_UPDATE_INTERVAL); const BUGS_TO_SHOW = 10; function showBugs(query, bugs) { var table = $("#templates .bugs").clone(); var rowTemplate = table.find(".bug-row").remove(); function appendRowForBug(bug) { var row = rowTemplate.clone(); row.attr("id", "bug-id-" + bug.id); row.find(".summary").text(bug.summary); row.addClass("status-" + bug.status); if (bug.priority != "--") { row.addClass(bug.priority); row.addClass(bug.severity); } row.find(".last-changed").attr("data-last-change", bug.last_change_time); row.click( function onClick() { window.open(bugzilla.getShowBugURL(bug.id)); }); row.hover( function onIn() { var tooltip = $("#templates .bug-tooltip").clone(); tooltip.find(".priority").text(bug.priority); // TODO: Show more information in tooltip. $(this).append(tooltip); }, function onOut() { $(this).find(".bug-tooltip").remove(); }); table.append(row); } sortByLastChanged(bugs); bugs.reverse(); var extraBugs = bugs.slice(BUGS_TO_SHOW); bugs = bugs.slice(0, BUGS_TO_SHOW); bugs.forEach(appendRowForBug); updatePrettyDates(table); query.find(".bugs").remove(); query.find(".more-link").remove(); query.append(table); if (extraBugs.length) { var moreLink = $("#templates .more-link").clone(); moreLink.find(".number").text(extraBugs.length); moreLink.click( function() { moreLink.remove(); extraBugs.forEach(appendRowForBug); updatePrettyDates(table); removeDuplicateBugs(); }); query.append(moreLink); } table.hide(); removeDuplicateBugs(); table.fadeIn(); } // Remove duplicate bugs, preferring the first listing of a bug in // the DOM to later ones. This is b/c the reports further down the // page are the less "interesting" ones, and we want to capture // the most "interesting" part of each bug. function removeDuplicateBugs() { var visited = {}; $("#reports .bug-row").each( function() { var id = $(this).attr("id"); if (id in visited) $(this).remove(); else visited[id] = true; }); } function report(selector, key, forceUpdate, searchTerms) { var newTerms = {__proto__: defaults}; for (name in searchTerms) newTerms[name.replace(/_DOT_/g, ".")] = searchTerms[name]; var cacheKey = key + "/" + selector; var cached = cache.get(cacheKey); if (cached) { showBugs($(selector), cached); if (!forceUpdate) return; } $(selector).find("h2").addClass("loading"); xhrQueue.enqueue( function() { return bugzilla.search( newTerms, function(response) { cache.set(cacheKey, response.bugs); showBugs($(selector), response.bugs); $(selector).find("h2").removeClass("loading"); }); }); } function timeAgo(ms) { var now = new Date(); var then = new Date(now - ms); return dateUtils.dateToISO8601(then); } const MS_PER_HOUR = 1000 * 60 * 60; const MS_PER_DAY = MS_PER_HOUR * 24; const MS_PER_WEEK = MS_PER_DAY * 7; var defaults = { changed_after: timeAgo(MS_PER_WEEK * 14) }; function update(myUsername, forceUpdate) { xhrQueue.clear(); report("#code-reviews", myUsername, forceUpdate, {status: ["NEW", "UNCONFIRMED", "ASSIGNED", "REOPENED"], flag_DOT_requestee: myUsername}); report("#assigned-bugs", myUsername, forceUpdate, {status: ["NEW", "UNCONFIRMED", "ASSIGNED", "REOPENED"], email1: myUsername, email1_type: "equals", email1_assigned_to: 1}); report("#reported-bugs", myUsername, forceUpdate, {status: ["NEW", "UNCONFIRMED", "ASSIGNED", "REOPENED"], email1: myUsername, email1_type: "equals", email1_reporter: 1, email2: myUsername, email2_type: "not_equals", email2_assigned_to: 1}); report("#cc-bugs", myUsername, forceUpdate, {status: ["NEW", "UNCONFIRMED", "ASSIGNED", "REOPENED"], email1: myUsername, email1_type: "equals", email1_cc: 1, email2: myUsername, email2_type: "not_equals", email2_assigned_to: 1, email2_reporter: 1}); report("#fixed-bugs", myUsername, forceUpdate, {resolution: ["FIXED"], changed_after: timeAgo(MS_PER_WEEK), email1: myUsername, email1_type: "equals", email1_assigned_to: 1, email1_reporter: 1, email1_cc: 1}); }; var refreshCommand = { name: "refresh-dashboard", execute: function execute() { var user = require("app/login").get(); if (user.isLoggedIn) update(user.username, true); } }; exports.init = function init() { require("app/commands").register(refreshCommand); require("app/login").whenChanged( function changeSearchCriteria(user) { if (user.isLoggedIn) { update(user.username, false); } }); }; };