blob: 8a863c5343e9d045f112cb996a647ff58aea246d [file] [log] [blame]
/*
* Copyright (C) 2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WI.AuditNavigationSidebarPanel = class AuditNavigationSidebarPanel extends WI.NavigationSidebarPanel
{
constructor()
{
super("audit", WI.UIString("Audits"));
}
// Public
showDefaultContentView()
{
let contentView = new WI.ContentView;
if (WI.auditManager.editing) {
let contentPlaceholder = WI.createMessageTextView(WI.UIString("Editing audits"));
contentPlaceholder.classList.add("finish-editing-audits-placeholder");
contentView.element.appendChild(contentPlaceholder);
let finishEditingNavigationItem = new WI.ButtonNavigationItem("finish-editing-audits", WI.UIString("Done"));
finishEditingNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, (event) => {
WI.auditManager.editing = false;
});
let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing"), finishEditingNavigationItem);
contentPlaceholder.appendChild(importHelpElement);
} else {
let contentPlaceholder = WI.createMessageTextView(WI.UIString("No audit selected"));
contentView.element.appendChild(contentPlaceholder);
let importNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15);
importNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
importNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import a test or result file"), importNavigationItem);
contentPlaceholder.appendChild(importHelpElement);
}
let versionContainer = contentView.element.appendChild(document.createElement("div"));
versionContainer.classList.add("audit-version");
let version = WI.AuditTestBase.Version;
if (InspectorBackend.hasDomain("Audit"))
version = Math.min(version, InspectorBackend.getVersion("Audit"));
versionContainer.textContent = WI.UIString("Audit version: %s").format(version);
this.contentBrowser.showContentView(contentView);
}
// Protected
initialLayout()
{
super.initialLayout();
this.contentTreeOutline.allowsRepeatSelection = false;
let controlsNavigationBar = new WI.NavigationBar;
this._startStopButtonNavigationItem = new WI.ToggleButtonNavigationItem("audit-start-stop", WI.UIString("Start"), WI.UIString("Stop"), "Images/AuditStart.svg", "Images/AuditStop.svg", 13, 13);
this._startStopButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
this._updateStartStopButtonNavigationItemState();
this._startStopButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleStartStopButtonNavigationItemClicked, this);
controlsNavigationBar.addNavigationItem(this._startStopButtonNavigationItem);
controlsNavigationBar.addNavigationItem(new WI.DividerNavigationItem);
let importButtonNavigationItem = new WI.ButtonNavigationItem("audit-import", WI.UIString("Import"), "Images/Import.svg", 15, 15);
importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
importButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
controlsNavigationBar.addNavigationItem(importButtonNavigationItem);
this.addSubview(controlsNavigationBar);
let editNavigationbar = new WI.NavigationBar;
this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done"));
this._editButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);
editNavigationbar.addNavigationItem(this._editButtonNavigationItem);
this.contentView.addSubview(editNavigationbar);
for (let test of WI.auditManager.tests)
this._addTest(test);
WI.auditManager.results.forEach((result, i) => {
this._addResult(result, i);
});
WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleAuditManagerEditingChanged, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestAdded, this._handleAuditTestAdded, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditTestCompleted, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestRemoved, this._handleAuditTestRemoved, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditTestScheduled, this);
this.contentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
}
closed()
{
super.closed();
WI.auditManager.removeEventListener(null, null, this);
}
updateFilter()
{
super.updateFilter();
if (!this.hasActiveFilters)
this._updateNoAuditsPlaceholder();
}
hasCustomFilters()
{
return true;
}
matchTreeElementAgainstCustomFilters(treeElement, flags)
{
if (WI.auditManager.editing) {
if (treeElement.representedObject instanceof WI.AuditTestResultBase || treeElement.hasAncestor(this._resultsFolderTreeElement) || treeElement === this._resultsFolderTreeElement)
return false;
} else {
if (treeElement.representedObject instanceof WI.AuditTestBase && treeElement.representedObject.disabled)
return false;
}
return super.matchTreeElementAgainstCustomFilters(treeElement, flags);
}
// Private
_addTest(test)
{
let treeElement = new WI.AuditTreeElement(test);
if (this._resultsFolderTreeElement) {
this.contentTreeOutline.insertChild(treeElement, this.contentTreeOutline.children.indexOf(this._resultsFolderTreeElement));
this._resultsFolderTreeElement.hidden = !this._resultsFolderTreeElement.children.length;
} else
this.contentTreeOutline.appendChild(treeElement);
this._updateStartStopButtonNavigationItemState();
this._updateEditButtonNavigationItemState();
this._updateNoAuditsPlaceholder();
}
_addResult(result, index)
{
this.element.classList.add("has-results");
if (!this._resultsFolderTreeElement) {
this._resultsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Results"));
this.contentTreeOutline.appendChild(this._resultsFolderTreeElement);
}
this._resultsFolderTreeElement.expand();
let resultFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Run %d").format(index + 1));
if (result instanceof WI.AuditTestResultBase) {
resultFolderTreeElement.subtitle = WI.UIString("Imported");
result = [result];
}
this._resultsFolderTreeElement.appendChild(resultFolderTreeElement);
console.assert(this._resultsFolderTreeElement.children.length === WI.auditManager.results.length);
for (let resultItem of result)
resultFolderTreeElement.appendChild(new WI.AuditTreeElement(resultItem));
this._updateStartStopButtonNavigationItemState();
this._updateEditButtonNavigationItemState();
}
_updateStartStopButtonNavigationItemState()
{
this._startStopButtonNavigationItem.toggled = WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping;
this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.some((test) => !test.disabled) && (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive || WI.auditManager.runningState === WI.AuditManager.RunningState.Active);
}
_updateEditButtonNavigationItemState()
{
this._editButtonNavigationItem.label = WI.auditManager.editing ? this._editButtonNavigationItem.activatedToolTip : this._editButtonNavigationItem.defaultToolTip;
this._editButtonNavigationItem.activated = WI.auditManager.editing;
this._editButtonNavigationItem.enabled = WI.auditManager.tests.length && (WI.auditManager.editing || WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive);
}
_updateNoAuditsPlaceholder()
{
if (WI.auditManager.editing || WI.auditManager.tests.some((test) => !test.disabled)) {
if (!this.hasActiveFilters)
this.hideEmptyContentPlaceholder();
return;
}
let contentPlaceholder = this.showEmptyContentPlaceholder(WI.UIString("No Enabled Audits"));
contentPlaceholder.classList.add("no-enabled-audits");
if (WI.auditManager.results.length) {
// Move the placeholder to be the first element in the content area, where it will
// be styled so that it doesn't obstruct the results elements.
this.contentView.element.insertBefore(contentPlaceholder, this.contentView.element.firstChild);
}
}
_handleAuditManagerEditingChanged(event)
{
if (WI.auditManager.editing) {
console.assert(!this._selectedTreeElementBeforeEditing);
this._selectedTreeElementBeforeEditing = this.contentTreeOutline.selectedTreeElement;
if (this._selectedTreeElementBeforeEditing)
this._selectedTreeElementBeforeEditing.deselect();
} else if (this._selectedTreeElementBeforeEditing) {
if (!(this._selectedTreeElementBeforeEditing.representedObject instanceof WI.AuditTestBase) || !this._selectedTreeElementBeforeEditing.representedObject.disabled)
this._selectedTreeElementBeforeEditing.select();
this._selectedTreeElementBeforeEditing = null;
}
if (!this.contentTreeOutline.selectedTreeElement)
this.showDefaultContentView();
this._updateStartStopButtonNavigationItemState();
this._updateEditButtonNavigationItemState();
this.updateFilter();
}
_handleAuditTestAdded(event)
{
this._addTest(event.data.test);
}
_handleAuditTestCompleted(event)
{
let {result, index} = event.data;
this._addResult(result, index);
}
_handleAuditTestRemoved(event)
{
let {test} = event.data;
let treeElement = this.treeElementForRepresentedObject(test);
this.contentTreeOutline.removeChild(treeElement);
this._updateStartStopButtonNavigationItemState();
this._updateEditButtonNavigationItemState();
this._updateNoAuditsPlaceholder();
}
_handleAuditTestScheduled(event)
{
this._updateStartStopButtonNavigationItemState();
this._updateEditButtonNavigationItemState();
}
_treeSelectionDidChange(event)
{
if (!this.selected)
return;
let treeElement = this.contentTreeOutline.selectedTreeElement;
if (!treeElement || treeElement instanceof WI.FolderTreeElement) {
this.showDefaultContentView();
return;
}
if (WI.auditManager.editing)
return;
let representedObject = treeElement.representedObject;
if (representedObject instanceof WI.AuditTestCase || representedObject instanceof WI.AuditTestGroup
|| representedObject instanceof WI.AuditTestCaseResult || representedObject instanceof WI.AuditTestGroupResult) {
WI.showRepresentedObject(representedObject);
return;
}
console.error("Unknown tree element", treeElement);
}
_handleStartStopButtonNavigationItemClicked(event)
{
if (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive)
WI.auditManager.start();
else if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active)
WI.auditManager.stop();
this._updateStartStopButtonNavigationItemState();
}
_handleImportButtonNavigationItemClicked(event)
{
WI.FileUtilities.importJSON((result) => WI.auditManager.processJSON(result), {multiple: true});
}
_handleEditButtonNavigationItemClicked(event)
{
WI.auditManager.editing = !WI.auditManager.editing;
}
};