mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
fd79a08030
--HG-- extra : rebase_source : d085de61306c18fd9490c44b89d277bb1edef02f
479 lines
17 KiB
JavaScript
479 lines
17 KiB
JavaScript
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (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.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Test Pilot.
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
* Portions created by the Initial Developer are Copyright (C) 2007
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Jono X <jono@mozilla.com>
|
|
* Raymond Lee <raymond@appcoast.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
// TODO Show individual status page in new chromeless window as html with
|
|
// background color set to "moz-dialog".
|
|
|
|
const NO_STUDIES_IMG = "chrome://testpilot/skin/testPilot_200x200.png";
|
|
const PROPOSE_STUDY_URL =
|
|
"https://wiki.mozilla.org/Labs/Test_Pilot#For_researchers";
|
|
|
|
var TestPilotXulWindow = {
|
|
_stringBundle : null,
|
|
|
|
onSubmitButton: function(experimentId) {
|
|
Components.utils.import("resource://testpilot/modules/setup.js");
|
|
let task = TestPilotSetup.getTaskById(experimentId);
|
|
let button = document.getElementById("submit-button-" + task.id);
|
|
|
|
// Hide the upload button so it doesn't get clicked again...
|
|
let parent = button.parentNode;
|
|
while (parent.firstChild) {
|
|
parent.removeChild(parent.firstChild);
|
|
}
|
|
// Replace it with a message:
|
|
this.addLabel(
|
|
parent,
|
|
this._stringBundle.getString("testpilot.studiesWindow.uploading"));
|
|
let self = this;
|
|
|
|
task.upload( function(success) {
|
|
while (parent.firstChild) {
|
|
parent.removeChild(parent.firstChild);
|
|
}
|
|
if (success) {
|
|
self.addThanksMessage(parent);
|
|
// TODO or should we move it to 'finished studies' immediately?
|
|
} else {
|
|
// TODO a better error message?
|
|
self.addLabel(
|
|
parent,
|
|
self._stringBundle.getString(
|
|
"testpilot.studiesWindow.unableToReachServer"));
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
addThanksMessage: function(container) {
|
|
// Fill in status box with icon and message to show success
|
|
let hbox = document.createElement("hbox");
|
|
container.appendChild(this.makeSpacer());
|
|
container.appendChild(hbox);
|
|
this.addLabel(
|
|
container,
|
|
this._stringBundle.getString(
|
|
"testpilot.studiesWindow.thanksForContributing"));
|
|
container.appendChild(this.makeSpacer());
|
|
hbox.appendChild(this.makeSpacer());
|
|
this.addImg(hbox, "study-submitted");
|
|
hbox.appendChild(this.makeSpacer());
|
|
},
|
|
|
|
addXulLink: function (container, text, url, openInTab) {
|
|
let linkContainer = document.createElement("hbox");
|
|
let link = document.createElement("label");
|
|
let spacer = document.createElement("spacer");
|
|
link.setAttribute("value", text);
|
|
link.setAttribute("class", "text-link");
|
|
if (openInTab) {
|
|
link.setAttribute(
|
|
"onclick",
|
|
"if (event.button==0) { " +
|
|
"TestPilotWindowUtils.openInTab('" + url + "'); }");
|
|
} else {
|
|
link.setAttribute(
|
|
"onclick",
|
|
"if (event.button==0) { " +
|
|
"TestPilotWindowUtils.openChromeless('" + url + "'); }");
|
|
}
|
|
linkContainer.appendChild(link);
|
|
spacer.setAttribute("flex", "1");
|
|
linkContainer.appendChild(spacer);
|
|
container.appendChild(linkContainer);
|
|
},
|
|
|
|
addLabel: function(container, text, styleClass) {
|
|
let label = document.createElement("label");
|
|
label.setAttribute("value", text);
|
|
if (styleClass) {
|
|
label.setAttribute("class", styleClass);
|
|
}
|
|
container.appendChild(label);
|
|
},
|
|
|
|
addImg: function(container, iconClass) {
|
|
let newImg = document.createElement("image");
|
|
newImg.setAttribute("class", iconClass);
|
|
container.appendChild(newImg);
|
|
},
|
|
|
|
makeSpacer: function() {
|
|
let spacer = document.createElement("spacer");
|
|
spacer.setAttribute("flex", "1");
|
|
return spacer;
|
|
},
|
|
|
|
addThumbnail: function(container, imgUrl) {
|
|
let boundingBox = document.createElement("vbox");
|
|
boundingBox.setAttribute("class", "results-thumbnail");
|
|
let bBox2 = document.createElement("hbox");
|
|
|
|
boundingBox.appendChild(this.makeSpacer());
|
|
boundingBox.appendChild(bBox2);
|
|
boundingBox.appendChild(this.makeSpacer());
|
|
|
|
bBox2.appendChild(this.makeSpacer());
|
|
let newImg = document.createElement("image");
|
|
newImg.setAttribute("src", imgUrl);
|
|
newImg.setAttribute("class", "results-thumbnail");
|
|
bBox2.appendChild(newImg);
|
|
bBox2.appendChild(this.makeSpacer());
|
|
|
|
container.appendChild(boundingBox);
|
|
},
|
|
|
|
addProgressBar: function(container, percent) {
|
|
let progBar = document.createElement("progressmeter");
|
|
progBar.setAttribute("mode", "determined");
|
|
progBar.setAttribute("value", Math.ceil(percent).toString());
|
|
container.appendChild(progBar);
|
|
},
|
|
|
|
addDescription: function(container, title, paragraph) {
|
|
let desc = document.createElement("description");
|
|
desc.setAttribute("class", "study-title");
|
|
let txtNode = document.createTextNode(title);
|
|
desc.appendChild(txtNode);
|
|
container.appendChild(desc);
|
|
|
|
desc = document.createElement("description");
|
|
desc.setAttribute("class", "study-description");
|
|
desc.setAttribute("crop", "none");
|
|
txtNode = document.createTextNode(paragraph);
|
|
desc.appendChild(txtNode);
|
|
container.appendChild(desc);
|
|
},
|
|
|
|
addButton: function(container, label, id, onClickHandler) {
|
|
let button = document.createElement("button");
|
|
button.setAttribute("label", label);
|
|
button.setAttribute("id", id);
|
|
button.setAttribute("oncommand", onClickHandler);
|
|
container.appendChild(button);
|
|
},
|
|
|
|
_sortNewestFirst: function(experiments) {
|
|
experiments.sort(
|
|
function sortFunc(a, b) {
|
|
if (a.endDate && b.endDate) {
|
|
return b.endDate - a.endDate;
|
|
}
|
|
if (a.publishDate && b.publishDate) {
|
|
if (isNaN(a.publishDate) || isNaN(b.publishDate)) {
|
|
return 0;
|
|
}
|
|
return b.publishDate - a.publishDate;
|
|
}
|
|
return 0;
|
|
});
|
|
return experiments;
|
|
},
|
|
|
|
onLoad: function () {
|
|
Components.utils.import("resource://testpilot/modules/Observers.js");
|
|
Components.utils.import("resource://testpilot/modules/setup.js");
|
|
Components.utils.import("resource://testpilot/modules/tasks.js");
|
|
|
|
this._stringBundle = document.getElementById("testpilot-stringbundle");
|
|
this.sizeWindow();
|
|
this._init(false);
|
|
Observers.add("testpilot:task:changed", this._onTaskStatusChanged, this);
|
|
},
|
|
|
|
onUnload: function() {
|
|
document.getElementById("settings-pane").writePreferences(true);
|
|
Observers.remove("testpilot:task:changed", this._onTaskStatusChanged, this);
|
|
},
|
|
|
|
_onTaskStatusChanged : function() {
|
|
this._init(true);
|
|
},
|
|
|
|
onTakeSurveyButton: function(taskId) {
|
|
let task = TestPilotSetup.getTaskById(taskId);
|
|
TestPilotWindowUtils.openChromeless(task.defaultUrl);
|
|
task.onDetailPageOpened();
|
|
},
|
|
|
|
_init: function(aReload) {
|
|
let experiments;
|
|
let ready = false;
|
|
|
|
// Are we done loading tasks?
|
|
if (TestPilotSetup.startupComplete) {
|
|
experiments = TestPilotSetup.getAllTasks();
|
|
if (experiments.length > 0 ) {
|
|
ready = true;
|
|
}
|
|
}
|
|
|
|
if (!ready) {
|
|
// If you opened the window before tasks are done loading, exit now
|
|
// but try again in a few seconds.
|
|
window.setTimeout(
|
|
function() { TestPilotXulWindow._init(aReload); }, 2000);
|
|
return;
|
|
}
|
|
|
|
let numFinishedStudies = 0;
|
|
let numCurrentStudies = 0;
|
|
|
|
/* Remove 'loading' message */
|
|
let msg = window.document.getElementById("still-loading-msg");
|
|
msg.setAttribute("hidden", "true");
|
|
|
|
if (aReload) {
|
|
/* If we're reloading, start by clearing out any old stuff already
|
|
* present in the listboxes. */
|
|
let listboxIds =
|
|
["current-studies-listbox", "finished-studies-listbox",
|
|
"study-results-listbox"];
|
|
for (let i = 0; i < listboxIds.length; i++) {
|
|
let listbox = document.getElementById(listboxIds[i]);
|
|
|
|
while (listbox.lastChild) {
|
|
listbox.removeChild(listbox.lastChild);
|
|
}
|
|
}
|
|
}
|
|
|
|
experiments = this._sortNewestFirst(experiments);
|
|
|
|
for (let i = 0; i < experiments.length; i++) {
|
|
let task = experiments[i];
|
|
let newRow = document.createElement("richlistitem");
|
|
newRow.setAttribute("class", "tp-study-list");
|
|
|
|
this.addThumbnail(newRow, task.thumbnail);
|
|
|
|
let textVbox = document.createElement("vbox");
|
|
newRow.appendChild(textVbox);
|
|
|
|
let openInTab = (task.taskType == TaskConstants.TYPE_LEGACY);
|
|
|
|
this.addDescription(textVbox, task.title, task.summary);
|
|
this.addXulLink(
|
|
textVbox, this._stringBundle.getString("testpilot.moreInfo"),
|
|
task.defaultUrl, openInTab);
|
|
|
|
// Create the rightmost status area, depending on status:
|
|
let statusVbox = document.createElement("vbox");
|
|
if (task.status == TaskConstants.STATUS_FINISHED) {
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getFormattedString(
|
|
"testpilot.studiesWindow.finishedOn",
|
|
[(new Date(task.endDate)).toLocaleDateString()]));
|
|
this.addButton(statusVbox,
|
|
this._stringBundle.getString("testpilot.submit"),
|
|
"submit-button-" + task.id,
|
|
"TestPilotXulWindow.onSubmitButton(" + task.id + ");");
|
|
}
|
|
if (task.status == TaskConstants.STATUS_CANCELLED) {
|
|
let hbox = document.createElement("hbox");
|
|
newRow.setAttribute("class", "tp-opted-out");
|
|
statusVbox.appendChild(this.makeSpacer());
|
|
statusVbox.appendChild(hbox);
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getString("testpilot.studiesWindow.canceledStudy"));
|
|
statusVbox.appendChild(this.makeSpacer());
|
|
hbox.appendChild(this.makeSpacer());
|
|
this.addImg(hbox, "study-canceled");
|
|
hbox.appendChild(this.makeSpacer());
|
|
}
|
|
if (task.status == TaskConstants.STATUS_NEW ||
|
|
task.status == TaskConstants.STATUS_PENDING ) {
|
|
newRow.setAttribute("class", "tp-new-results");
|
|
|
|
if (task.taskType == TaskConstants.TYPE_SURVEY) {
|
|
this.addButton(
|
|
statusVbox,
|
|
this._stringBundle.getString("testpilot.takeSurvey"),
|
|
"survey-button",
|
|
"TestPilotXulWindow.onTakeSurveyButton('" + task.id + "');");
|
|
} else if (task.taskType == TaskConstants.TYPE_EXPERIMENT) {
|
|
if (task.startDate) {
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getFormattedString(
|
|
"testpilot.studiesWindow.willStart",
|
|
[(new Date(task.startDate)).toLocaleDateString()]));
|
|
}
|
|
}
|
|
}
|
|
if (task.status == TaskConstants.STATUS_IN_PROGRESS ||
|
|
task.status == TaskConstants.STATUS_STARTING) {
|
|
|
|
if (task.taskType == TaskConstants.TYPE_SURVEY) {
|
|
this.addButton(
|
|
statusVbox,
|
|
this._stringBundle.getString("testpilot.takeSurvey"),
|
|
"survey-button",
|
|
"TestPilotXulWindow.onTakeSurveyButton('" + task.id + "');");
|
|
} else if (task.taskType == TaskConstants.TYPE_EXPERIMENT) {
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getString(
|
|
"testpilot.studiesWindow.gatheringData"));
|
|
let now = (new Date()).getTime();
|
|
let progress =
|
|
100 * (now - task.startDate) / (task.endDate - task.startDate);
|
|
this.addProgressBar(statusVbox, progress);
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getFormattedString(
|
|
"testpilot.studiesWindow.willFinish",
|
|
[(new Date(task.endDate)).toLocaleDateString()]));
|
|
}
|
|
}
|
|
if (task.status >= TaskConstants.STATUS_SUBMITTED) {
|
|
if (task.taskType == TaskConstants.TYPE_RESULTS) {
|
|
let maintask = TestPilotSetup.getTaskById(task.relatedStudyId);
|
|
if (maintask && maintask.status >= TaskConstants.STATUS_SUBMITTED) {
|
|
this.addThanksMessage(statusVbox);
|
|
}
|
|
} else {
|
|
if (task.status == TaskConstants.STATUS_MISSED) {
|
|
// Icon for missed studies
|
|
let hbox = document.createElement("hbox");
|
|
newRow.setAttribute("class", "tp-opted-out");
|
|
statusVbox.appendChild(this.makeSpacer());
|
|
statusVbox.appendChild(hbox);
|
|
this.addLabel(
|
|
statusVbox,
|
|
this._stringBundle.getString("testpilot.studiesWindow.missedStudy"));
|
|
statusVbox.appendChild(this.makeSpacer());
|
|
hbox.appendChild(this.makeSpacer());
|
|
this.addImg(hbox, "study-missed");
|
|
hbox.appendChild(this.makeSpacer());
|
|
} else {
|
|
this.addThanksMessage(statusVbox);
|
|
numFinishedStudies ++;
|
|
}
|
|
}
|
|
}
|
|
let spacer = document.createElement("spacer");
|
|
spacer.setAttribute("flex", "1");
|
|
newRow.appendChild(spacer);
|
|
newRow.appendChild(statusVbox);
|
|
|
|
// Use status to decide which panel to add this to:
|
|
let rowset;
|
|
if (task.taskType == TaskConstants.TYPE_RESULTS) {
|
|
rowset = document.getElementById("study-results-listbox");
|
|
} else if (task.status > TaskConstants.STATUS_FINISHED) {
|
|
rowset = document.getElementById("finished-studies-listbox");
|
|
} else {
|
|
rowset = document.getElementById("current-studies-listbox");
|
|
numCurrentStudies++;
|
|
}
|
|
|
|
// TODO further distinguish by background colors.
|
|
rowset.appendChild(newRow);
|
|
}
|
|
|
|
// If there are no current studies, show a message about upcoming
|
|
// studies:
|
|
if (numCurrentStudies == 0) {
|
|
let newRow = document.createElement("richlistitem");
|
|
newRow.setAttribute("class", "tp-study-list");
|
|
this.addThumbnail(newRow, NO_STUDIES_IMG);
|
|
let textVbox = document.createElement("vbox");
|
|
textVbox.setAttribute("class", "pilot-largetext");
|
|
newRow.appendChild(textVbox);
|
|
this.addDescription(
|
|
textVbox, "",
|
|
this._stringBundle.getString("testpilot.studiesWindow.noStudies"));
|
|
this.addXulLink(
|
|
textVbox,
|
|
this._stringBundle.getString("testpilot.studiesWindow.proposeStudy"),
|
|
PROPOSE_STUDY_URL, true);
|
|
document.getElementById("current-studies-listbox").appendChild(newRow);
|
|
}
|
|
|
|
// Show number of studies the user finished on badge:
|
|
document.getElementById("num-finished-badge").setAttribute(
|
|
"value", numFinishedStudies);
|
|
},
|
|
|
|
sizeWindow: function() {
|
|
// Size listboxes based on available screen size, then size window to fit
|
|
// list boxes.
|
|
let currList = document.getElementById("current-studies-listbox");
|
|
let finList = document.getElementById("finished-studies-listbox");
|
|
let resultsList = document.getElementById("study-results-listbox");
|
|
|
|
let screenWidth = window.screen.availWidth;
|
|
let screenHeight = window.screen.availHeight;
|
|
let width = screenWidth >= 800 ? 700 : screenWidth - 100;
|
|
let height = screenHeight >= 800 ? 700 : screenHeight - 100;
|
|
|
|
height -= 130; // Or whatever is height of title bar plus windowdragbox
|
|
|
|
currList.width = width;
|
|
currList.height = height;
|
|
finList.width = width;
|
|
finList.height = height;
|
|
resultsList.width = width;
|
|
resultsList.height = height;
|
|
window.sizeToContent();
|
|
},
|
|
|
|
focusPane: function(paneIndex) {
|
|
document.getElementById("tp-xulwindow-deck").selectedIndex = paneIndex;
|
|
|
|
// When you focus the 'study findings' tab, any results there which
|
|
// are still marked "new" should have their status changed as the user
|
|
// is considered to have seen them.
|
|
if (paneIndex == 2) {
|
|
Components.utils.import("resource://testpilot/modules/setup.js");
|
|
Components.utils.import("resource://testpilot/modules/tasks.js");
|
|
|
|
let experiments = TestPilotSetup.getAllTasks();
|
|
for each (let experiment in experiments) {
|
|
if (experiment.taskType == TaskConstants.TYPE_RESULTS) {
|
|
if (experiment.status == TaskConstants.STATUS_NEW) {
|
|
experiment.changeStatus(TaskConstants.STATUS_ARCHIVED, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|