--- a/testing/extensions/community/chrome/content/browserOverlays.xul
+++ b/testing/extensions/community/chrome/content/browserOverlays.xul
@@ -11,35 +11,43 @@
<script type="application/x-javascript" src="chrome://qa/content/MochiKit/MochiKit.js" />
<script type="application/x-javascript" src="chrome://qa/content/prefs.js" />
<script type="application/x-javascript" src="chrome://qa/content/qa.js" />
<script type="application/x-javascript" src="chrome://qa/content/notifications.js" />
<statusbar id="status-bar">
<statusbarpanel class="statusbarpanel-iconic" id="qa-statusbar-overlay"
- src="chrome://qa/skin/qmo-16px.png" onclick="qaMain.openQATool(); qaNotifications.checkNotificationStatus();" />
+ src="chrome://qa/skin/qmo-16px.png"
+ onclick="qaMain.openQATool(); qaNotifications.checkNotificationStatus();" />
</statusbar>
<window id="main-window">
<vbox id="qa-notify" class="qa-notify" hidden="true">
<vbox flex="1" class="qa-notify">
<hbox pack="end" align="center">
- <toolbarbutton class="tabs-closebutton"
+ <toolbarbutton class="tabs-closebutton" id="qa-notify-close"
oncommand="qaNotifications.showHideNotify(false);" />
</hbox>
<vbox id="qa-notify-box">
<vbox>
+ <label id="qa-notify-inprogress" value="&qa.notification.inprogress;" />
<hbox align="center" id="qa-notify-header-box" style="overflow: hidden">
<label id="qa-notify-header" value="" />
</hbox>
- <vbox>
- <description id="qa-notify-text"></description>
+ <vbox id="qa-notify-event" style="display: none;">
+ <label id="qa-notify-event-datetime" value="" />
+ <label id="qa-notify-event-place" value="" />
+ </vbox>
+ <vbox id="qa-notify-content">
+ <description id="qa-notify-text" />
<label id="qa-notify-infolink" class="text-link" href=""
- value="" />
+ value="" />
+ <label id="qa-notify-getstartedlink" class="text-link" href=""
+ value="" style="display: none;" />
</vbox>
</vbox>
</vbox>
</vbox>
</vbox>
</window>
--- a/testing/extensions/community/chrome/content/notifications.js
+++ b/testing/extensions/community/chrome/content/notifications.js
@@ -1,8 +1,12 @@
+document.addEventListener('load', function() {
+ window.setTimeout();
+}, false)
+
var qaNotifications = {
storageService : Components.classes["@mozilla.org/storage/service;1"]
.getService(Ci.mozIStorageService),
dbHandle : null,
openDatabase : function() {
var file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
@@ -23,28 +27,36 @@ var qaNotifications = {
this.db.executeSimpleSQL("CREATE TABLE if not exists notifications ( \
id text, \
datetime integer, \
firstNotification integer, \
secondNotification integer, \
serializedJSData string)");
},
- checkNotificationStatus : function() {
+ updateNotificationStore : function() {
var req = new XMLHttpRequest();
var url = qaPref.getPref('qa.extension.hermes.url', 'char');
req.open('GET', url, true);
req.onreadystatechange = function(evt) {
if (req.readyState == 4 && req.status == 200) {
- var notif = new Notification('xml', req.responseXML);
- notif.serializeToDbIfNotExists();
+ if (req.responseXML.getElementsByTagName('notifications') == null)
+ return;
+ var notifs = req.responseXML.getElementsByTagName('notification');
+ for (var i=0; i<notifs.length; i++) {
+ var notif = notifs[i];
+ notif = new Notification('xml', notif);
+ notif.serializeToDb();
+ }
}
};
req.send(null);
+ },
+ checkNotificationStatus : function() {
// see if we are elegible for notification:
var time = qaPref.getPref(qaPref.prefBase+'.lastNotificationCheckTime', 'int');
var interval = qaPref.getPref(qaPref.prefBase+'.minNotificationCheckInterval', 'int');
if (time + interval > new Date().valueOf())
return; // nothing to see here, try again later
var sth = this.db.createStatement("SELECT * FROM notifications");
var notifications = [];
@@ -93,51 +105,45 @@ function Notification() {
}
function Notification(type, data) {
if (type == 'json') {
this.id = data.id;
this.notificationClass = data.notificationClass;
this.type = data.type;
this.headline = data.headline;
- this.datetime = data.datetime;
+ this.datetime = MochiKit.DateTime.isoTimestamp(data.datetime);
this.place = data.place;
this.infotext = data.infotext;
this.infolinktext = data.infolinktext;
this.infolinkhref = data.infolinkhref;
this.golinktext = data.golinktext;
this.golinkhref = data.golinkhref;
} else if (type == 'xml') {
- if (data.getElementsByTagName('notifications') == null)
- return;
- var notifs = data.getElementsByTagName('notification');
- for (var i=0; i<notifs.length; i++) {
- var notif = notifs[i];
-
- this.id = notif.getAttribute('id');
- this.notificationClass = notif.getAttribute('class');
- this.type = notif.getAttribute('type');
- if (notif.getElementsByTagName('headline')[0] != null)
- this.headline = notif.getElementsByTagName('headline')[0].textContent;
-
- // eventinfo
- if (this.notificationClass == 'event') {
- var eventInfo = notif.getElementsByTagName('eventinfo')[0];
- this.datetime = MochiKit.DateTime.isoTimestamp(
- eventInfo.getElementsByTagName('datetime')[0].textContent);
- this.place = eventInfo.getElementsByTagName('place')[0].textContent;
- }
- this.infotext = notif.getElementsByTagName('infotext')[0].textContent;
- this.infolinktext = notif.getElementsByTagName('infolink')[0].textContent;
- this.infolinkhref = notif.getElementsByTagName('infolink')[0]
- .getAttribute('href');
- this.golinktext = notif.getElementsByTagName('golink')[0].textContent;
- this.golinkhref = notif.getElementsByTagName('golink')[0]
- .getAttribute('href');
+ var notif = data;
+ this.id = notif.getAttribute('id');
+ this.notificationClass = notif.getAttribute('class');
+ this.type = notif.getAttribute('type');
+ if (notif.getElementsByTagName('headline')[0] != null)
+ this.headline = notif.getElementsByTagName('headline')[0].textContent;
+
+ // eventinfo
+ if (this.notificationClass == 'event') {
+ var eventInfo = notif.getElementsByTagName('eventinfo')[0];
+ this.datetime = MochiKit.DateTime.isoTimestamp(
+ eventInfo.getElementsByTagName('datetime')[0].textContent);
+ this.place = eventInfo.getElementsByTagName('place')[0].textContent;
}
+ this.infotext = notif.getElementsByTagName('infotext')[0].textContent;
+ this.infolinktext = notif.getElementsByTagName('infolink')[0].textContent;
+ this.infolinkhref = notif.getElementsByTagName('infolink')[0]
+ .getAttribute('href');
+ this.golinktext = notif.getElementsByTagName('golink')[0].textContent;
+ this.golinkhref = notif.getElementsByTagName('golink')[0]
+ .getAttribute('href');
}
}
Notification.prototype = {
id : null,
notificationClass : null,
type : null,
headline : null,
@@ -148,42 +154,70 @@ Notification.prototype = {
infolinkhref : null,
golinktext : null,
golinkhref : null,
hasHadFirstNotification : false,
hasHadSecondNotification : false,
serializedJSData : null,
- serializeToDbIfNotExists : function() {
+ serializeToDb: function() {
var query = qaNotifications.db.createStatement("SELECT id FROM notifications \
WHERE id = ?1");
query.bindStringParameter(0, this.id);
var foundRow;
while (query.executeStep()) {
foundRow = 1;
}
query.reset();
- if (foundRow == 1) // it's already been inserted
+ if (foundRow == 1) { // it's already been inserted, so update
return;
+ }
var sth = qaNotifications.db.createStatement("INSERT into notifications \
values (?1, ?2, ?3, ?4, ?5)");
sth.bindStringParameter(0, this.id);
sth.bindStringParameter(1, this.datetime);
sth.bindStringParameter(2, this.hasHadFirstNotification);
sth.bindStringParameter(3, this.hasHadSecondNotification);
- sth.bindStringParameter(4, MochiKit.Base.serializeJSON(this));
+
+ // avoid having serialized data inside serialized data:
+ this.serializedJSData = null;
+ var jsData = MochiKit.Base.serializeJSON(this);
+ sth.bindStringParameter(4, jsData);
+
sth.execute();
},
displayToBox : function() {
$('qa-notify-header').value=this.headline;
- $('qa-notify-text').value=this.infotext;
+
+ if ($('qa-notify-text').firstChild)
+ $('qa-notify-text').removeChild($('qa-notify-text').firstChild);
+ $('qa-notify-text').appendChild(document.createTextNode(this.infotext));
+
$('qa-notify-infolink').value=this.infolinktext;
$('qa-notify-infolink').href=this.infolinkhref;
+ $('qa-notify-infolink').style.display = '';
+
+ if (this.notificationClass == 'event') {
+ var inprogress = 0;
+ $('qa-notify-event-datetime').value=this.datetime;
+ $('qa-notify-event-place').value=this.place;
+ $('qa-notify-event').style.display = '';
+ $('qa-notify-inprogress').style.display = 'none';
+
+ $('qa-notify-getstartedlink').value=this.golinktext;
+ $('qa-notify-getstartedlink').href=this.golinkhref;
+
+ if (inprogress == 1) {
+ $('qa-notify-inprogress').style.display = '';
+ $('qa-notify-getstartedlink').style.display = '';
+ $('qa-notify-infolink').style.display = 'none';
+ }
+ }
},
okToShow : function() {
var prefs = qaNotifications.getNotificationSettings();
if (prefs[0] == '1') // all notifications disabled
return false;
if (this.type == 'testday' && ! prefs[1] == '0')
return true;
if (this.type == 'bugday' && ! prefs[2] == '0')
--- a/testing/extensions/community/chrome/content/prefs.js
+++ b/testing/extensions/community/chrome/content/prefs.js
@@ -131,20 +131,19 @@ if (CC_passwordManager != null) { // old
var login = this.getPasswordObj();
if (login != false) {
this.manager().removeLogin(login);
}
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Components.interfaces.nsILoginInfo,
"init");
- var newLogin = new nsLoginInfo();
- newLogin.init('chrome://qa', 'Litmus Login', litmus.baseURL,
+ var newLogin = new nsLoginInfo('chrome://qa', 'Litmus Login', litmus.baseURL,
username, password, null, null);
- this.manager().addLogin(newLogin);
+ this.manager().addLogin(newLogin);
},
getPasswordObj: function() {
try {
var logins = this.manager().findLogins({}, 'chrome://qa',
'Litmus Login', litmus.baseURL);
if (logins.length > 0 && logins[0] != null)
return logins[0];
return false;
--- a/testing/extensions/community/chrome/content/settings.js
+++ b/testing/extensions/community/chrome/content/settings.js
@@ -121,17 +121,22 @@ var qaSetup = {
// we're creating a new account, so get the uname and passwd
// from the account created page:
var page = document.getElementById('qa-setup-createaccount-iframe').
contentDocument;
if (!page) {
alert("create account page is missing");
return false;
}
- if (page.location == 'http://laptop.local/litmus/extension.cgi?createAccount=1'
+ if (page.wrappedJSObject == null)
+ page.wrappedJSObject = page;
+ if (page.forms[0] && page.forms[0].wrappedJSObject == null)
+ page.forms[0].wrappedJSObject = page.forms[0];
+
+ if (page.location == litmus.baseURL+'extension.cgi?createAccount=1'
&& qaSetup.didSubmitForm==0) {
document.getElementById('qa-setup-accountconfirmloading').value =
document.getElementById("bundle_qa").getString("qa.extension.prefs.loadingMsg");
page.forms[0].wrappedJSObject.submit();
qaSetup.didSubmitForm = 1;
setTimeout("qaSetup.validateAccount()", 5000);
return false;
}
@@ -158,22 +163,22 @@ document.getElementById("bundle_qa").get
document.getElementById('qa-setup-accountconfirmloading').value =
document.getElementById("bundle_qa").getString("qa.extension.prefs.loadingMsg");
var uname = document.getElementById('username').value;
var passwd = document.getElementById('password').value;
var callback = function(resp) {
- if (resp.responseText == 0) {
+ if (resp.responseText != 1) { // failure
alert(document.getElementById("bundle_qa").
getString("qa.extension.prefs.loginError"));
document.getElementById('qa-setup-accountconfirmloading').value = null;
return false;
- } else {
+ } else { // all's well
qaPref.litmus.setPassword(uname, passwd);
document.getElementById('qa-setup-accountconfirmloading').value = null;
document.getElementById('qa-setup').pageIndex++; // advance
return true;
}
}
litmus.validateLogin(uname, passwd, callback);
return false; // not ready to advance yet
@@ -224,11 +229,10 @@ document.getElementById("bundle_qa").get
qaPref.setPref(qaPref.prefBase+'.sysconfig.opsys',
$('qa-setup-opsys').selectedItem.label, 'char');
}
return true;
},
finish : function() {
qaPref.setPref(qaPref.prefBase+'.isFirstTime', false, 'bool');
- qaPrefsWindow.loadPrefsWindow();
},
-};
\ No newline at end of file
+};
--- a/testing/extensions/community/chrome/content/tabs/selecttests.xul
+++ b/testing/extensions/community/chrome/content/tabs/selecttests.xul
@@ -17,17 +17,17 @@
<script type="application/x-javascript" src="chrome://qa/content/MochiKit/MochiKit.js" />
<script type="application/x-javascript" src="chrome://qa/content/prefs.js" />
<script type="application/x-javascript" src="chrome://qa/content/litmus.js" />
<script type="application/x-javascript" src="chrome://qa/content/qa.js" />
<script type="application/x-javascript" src="chrome://qa/content/settings.js" />
<script type="application/x-javascript" src="chrome://qa/content/common.js" />
<script type="application/x-javascript" src="chrome://qa/content/tabs/selecttests.js" />
- <dialogheader title="Select test group" />
+ <dialogheader description="&qa.selecttests.header;" />
<spacer height="20" />
<vbox>
<hbox>
<description value="Test Run:" />
<menulist label=" " id="qa-st-testrun" onselect="handleRunSelect()">
<menupopup >
<menuitem label="&qa.selecttests.load;" selected="true" />
</menupopup>
--- a/testing/extensions/community/chrome/locale/en-US/qa.dtd
+++ b/testing/extensions/community/chrome/locale/en-US/qa.dtd
@@ -8,16 +8,17 @@
<!ENTITY qa.testcase.steps "Steps to Perform">
<!ENTITY qa.testcase.expected "Expected Results">
<!ENTITY qa.testcase.result.pass "Test Passed">
<!ENTITY qa.testcase.result.fail "Test Failed">
<!ENTITY qa.testcase.result.unclearbroken "Test is unclear or broken">
<!ENTITY qa.testcase.comment "Comment (optional):">
<!ENTITY qa.selecttests.load "Loading...">
+<!ENTITY qa.selecttests.header "Select test group">
<!ENTITY qa.preferences.title "Settings">
<!ENTITY qa.preferences.litmus.title "Litmus Settings">
<!ENTITY qa.preferences.litmus.username "Email:">
<!ENTITY qa.preferences.litmus.password "Password:">
<!ENTITY qa.preferences.litmus.OK "Save">
<!ENTITY qa.preferences.litmus.createAccount "Create New Account">
@@ -138,9 +139,11 @@ possible, but please check the settings
<!ENTITY qa.chat.intro2 "If you have a favorite IRC client, you can connect to <html:em>irc.mozilla.org</html:em>, channel #qa, but the easist way to get on IRC right now is through your web browser. Just click the button below.">
<!ENTITY qa.chat.howdoItitle "How do I get on IRC?">
<!ENTITY qa.chat.howdoI.imo "Learn more about irc.mozilla.org">
<!ENTITY qa.chat.howdoI.imourl "http://irc.mozilla.org">
<!ENTITY qa.chat.howdoI.irchelp "Visit irchelp.org">
<!ENTITY qa.chat.howdoI.irchelpurl "http://www.irchelp.org">
<!ENTITY qa.chat.howdoI.joinnow "Join IRC Now">
-<!ENTITY qa.help.title "Help">
\ No newline at end of file
+<!ENTITY qa.help.title "Help">
+
+<!ENTITY qa.notification.inprogress "Come Join! Event in Progress Now!">
--- a/testing/extensions/community/chrome/skin/qa.css
+++ b/testing/extensions/community/chrome/skin/qa.css
@@ -37,24 +37,52 @@ html|a {
.qa-notify {
height: 140px;
width: 420px;
}
#qa-notify-box {
padding: 0px 6px 6px 6px;
- display: table;
+ display: table;
}
#qa-notify-header {
font-size: 1.5em;
font-weight: bold;
}
+#qa-notify-header-box {
+ position: absolute;
+ top: 2px;
+}
+
+#qa-notify-content {
+ position: absolute;
+ left: 12px;
+}
+
+#qa-notify description {
+ max-width: 400px;
+}
+
+#qa-notify-event {
+ border-style: dashed;
+ border-width: 1px;
+ margin-left: 15px;
+}
+
+#qa-notify-inprogress {
+ color: red;
+ font-size: 1.25em;
+}
+
+#qa-notify-text {
+ margin-top: 3px;
+}
/* general formatting */
.list {
padding-left: 10px;
}
--- a/testing/extensions/community/install.rdf
+++ b/testing/extensions/community/install.rdf
@@ -8,17 +8,17 @@
<em:version>0.0.1</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
- <em:minVersion>1.5</em:minVersion>
+ <em:minVersion>2.0</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Mozilla Quality Extension</em:name>
<em:description>The QA tool</em:description>
<em:creator>Mozilla Quality Assurance</em:creator>