Skip to content

Commit

Permalink
#7524 remove toolbar spark status on kernel restart
Browse files Browse the repository at this point in the history
  • Loading branch information
Mariusz Jurowicz committed Jun 14, 2018
1 parent e6d9558 commit 382f8a3
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 91 deletions.
123 changes: 32 additions & 91 deletions js/notebook/src/SparkUI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import {Widget} from "@phosphor/widgets";
import BeakerXApi from "./tree/Utils/BeakerXApi";
import widgets from './widgets';
import Timer = NodeJS.Timer;
import {ToolbarSparkConnectionStatus} from "./sparkUI/toolbarSparkConnectionStatus";

const bkUtils = require("./shared/bkUtils");

Expand All @@ -37,20 +39,20 @@ export class SparkUIModel extends widgets.VBoxModel {
}

export class SparkUIView extends widgets.VBoxView {
private sparkStats: Widget;
private toolbarSparkStats: Widget;
sparkStats: Widget;
connectionStatusElement: HTMLElement;

private sparkAppId: string;
private sparkUiWebUrl: string;
private sparkMasterUrl: string;
private apiCallIntervalId: number;
private toolbarStatusContainer: HTMLElement|null;
private apiCallIntervalId: Timer;
private connectionLabelActive: HTMLElement;
private connectionLabelMemory: HTMLElement;
private connectionLabelDead: HTMLElement;
private connectionStatusElement: HTMLElement;
private masterUrlInput: HTMLInputElement;
private executorCoresInput: HTMLInputElement;
private executorMemoryInput: HTMLInputElement;
private toolbarSparkConnectionStatus: ToolbarSparkConnectionStatus;

initialize(parameters) {
super.initialize(parameters);
Expand All @@ -59,7 +61,8 @@ export class SparkUIView extends widgets.VBoxView {
this.openExecutors = this.openExecutors.bind(this);
this.updateChildren = this.updateChildren.bind(this);
this.toggleExecutorConfigInputs = this.toggleExecutorConfigInputs.bind(this);
this.handleToolbarSparkClick = this.handleToolbarSparkClick.bind(this);

this.toolbarSparkConnectionStatus = new ToolbarSparkConnectionStatus(this);
}

public render(): void {
Expand All @@ -79,6 +82,14 @@ export class SparkUIView extends widgets.VBoxView {
this.updateChildren();
}

public openWebUi(): void {
window.open(this.sparkUiWebUrl, '_blank');
}

public openExecutors(): void {
window.open(`${this.sparkUiWebUrl}/executors`, '_blank');
}

private addSparkUrls() {
if (!this.connectionStatusElement) {
this.connectionStatusElement = this.el.querySelector('.bx-connection-status');
Expand All @@ -88,11 +99,11 @@ export class SparkUIView extends widgets.VBoxView {
return;
}

this.addSparUiWebUrl();
this.addSparkUiWebUrl();
this.addMasterUrl();
}

private addSparUiWebUrl(): void {
private addSparkUiWebUrl(): void {
this.sparkUiWebUrl = this.model.get("sparkUiWebUrl");

if (!this.sparkUiWebUrl) {
Expand All @@ -105,28 +116,7 @@ export class SparkUIView extends widgets.VBoxView {
this.sparkStats.node.addEventListener('click', this.openExecutors);
this.connectionStatusElement.style.cursor = 'pointer';
this.sparkStats.node.style.cursor = 'pointer';

this.bindToolbarSparkEvents();
}

private bindToolbarSparkEvents(): void {
if (!this.toolbarSparkStats) {
return;
}

this.toolbarSparkStats.node.addEventListener('click', this.handleToolbarSparkClick);
}

private handleToolbarSparkClick(event): void {
const relatedTarget = (event.relatedTarget || event.target) as HTMLElement;

if (relatedTarget.classList.contains('bx-connection-status')) {
return this.openWebUi();
}

if (relatedTarget.classList.contains('label')) {
return this.openExecutors();
}
this.toolbarSparkConnectionStatus.bindToolbarSparkEvents();
}

private addMasterUrl() {
Expand Down Expand Up @@ -161,14 +151,6 @@ export class SparkUIView extends widgets.VBoxView {
}
}

private openWebUi() {
window.open(this.sparkUiWebUrl, '_blank');
}

private openExecutors() {
window.open(`${this.sparkUiWebUrl}/executors`, '_blank');
}

private updateChildren() {
const noop = () => {};

Expand All @@ -179,7 +161,7 @@ export class SparkUIView extends widgets.VBoxView {
this.resolveChildren(view)
.then((views) => {
this.handleLocalMasterUrl();
this.appendToToolbar();
this.toolbarSparkConnectionStatus.append();
this.addSparkUrls();
})
.catch(noop);
Expand All @@ -190,7 +172,7 @@ export class SparkUIView extends widgets.VBoxView {
}

private resolveChildren(view) {
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
if (!view || !view.children_views) {
reject();
}
Expand Down Expand Up @@ -224,53 +206,6 @@ export class SparkUIView extends widgets.VBoxView {
this.connectionStatusElement.insertAdjacentElement('afterend', this.sparkStats.node);
}

private appendToToolbar(): void {
if (!this.el.querySelector('.bx-status-panel')) {
return;
}

if (this.toolbarStatusContainer && this.toolbarStatusContainer.contains(this.toolbarSparkStats.node)) {
this.propagateToolbarWidget();

return;
}

const toolbarContainer = this.el.closest('.jp-NotebookPanel') || this.el.closest('.notebook_app');

if (!toolbarContainer) {
return;
}

const toolbar = toolbarContainer.querySelector('#maintoolbar-container') || toolbarContainer.querySelector('.jp-NotebookPanel-toolbar');

if (!toolbar) {
return;
}

this.toolbarSparkStats = new Widget();
this.toolbarStatusContainer = toolbar;
this.toolbarSparkStats.node.classList.add('bx-toolbar-spark-widget');
this.propagateToolbarWidget();
this.appendToolbarSparkStats();
}

private propagateToolbarWidget() {
this.toolbarSparkStats.node.innerHTML = `<div class="p-Widget bx-status-panel widget-box widget-hbox">
${this.connectionStatusElement.outerHTML}
${this.sparkStats.node.outerHTML}
</div>`;
}

private appendToolbarSparkStats() {
const spacer: HTMLElement|null = this.toolbarStatusContainer.querySelector('.jp-Toolbar-spacer');

if (spacer) {
spacer.insertAdjacentElement("afterend", this.toolbarSparkStats.node);
} else {
this.toolbarStatusContainer.appendChild(this.toolbarSparkStats.node);
}
}

private connectToApi() {
let baseUrl;
let api;
Expand Down Expand Up @@ -300,12 +235,14 @@ export class SparkUIView extends widgets.VBoxView {
const response = await fetch(sparkUrl, { method: 'GET', credentials: 'include' });

if (!response.ok) {
this.toolbarSparkConnectionStatus.destroy();
return this.clearApiCallInterval();
}

const data = await response.json();
this.updateMetrics(data);
} catch(error) {
this.toolbarSparkConnectionStatus.destroy();
this.clearApiCallInterval();
}
};
Expand All @@ -319,7 +256,7 @@ export class SparkUIView extends widgets.VBoxView {
this.sparkAppId = null;

if (!this.el.querySelector('.bx-status-panel')) {
this.toolbarSparkStats.node.innerHTML = '';
this.toolbarSparkConnectionStatus.clear();
}
}

Expand All @@ -340,7 +277,7 @@ export class SparkUIView extends widgets.VBoxView {
this.connectionLabelActive.innerText = `${activeTasks}`;
this.connectionLabelMemory.innerText = `${bkUtils.formatBytes(storageMemory)}`;
this.connectionLabelDead.innerText = `${deadExecutors}`;
this.propagateToolbarWidget();
this.toolbarSparkConnectionStatus.propagateToolbarWidget();
}

private addSparkMetricsWidget() {
Expand All @@ -350,7 +287,7 @@ export class SparkUIView extends widgets.VBoxView {
views.forEach((view) => {
if (view instanceof widgets.LabelView && view.el.classList.contains('bx-connection-status')) {
this.createSparkMetricsWidget();
this.appendToToolbar();
this.toolbarSparkConnectionStatus.append();
this.addSparkUrls();
}
});
Expand All @@ -363,7 +300,11 @@ export class SparkUIView extends widgets.VBoxView {
super.dispose();
this.clearApiCallInterval();
this.sparkStats && this.sparkStats.isAttached && this.sparkStats.dispose();
this.toolbarSparkStats && this.toolbarSparkStats.isAttached && this.toolbarSparkStats.dispose();
this.toolbarSparkConnectionStatus.destroy();
}

remove() {
this.toolbarSparkConnectionStatus.destroy();
}
}

Expand Down
115 changes: 115 additions & 0 deletions js/notebook/src/sparkUI/toolbarSparkConnectionStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright 2018 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {SparkUIView} from "../SparkUI";
import {Widget} from "@phosphor/widgets";

export class ToolbarSparkConnectionStatus {
private sparkUIView: SparkUIView;
private toolbarSparkStats: Widget;
private toolbarStatusContainer: HTMLElement|null;

constructor(sparkUIView: SparkUIView) {
this.sparkUIView = sparkUIView;

this.handleToolbarSparkClick = this.handleToolbarSparkClick.bind(this);
}

bindToolbarSparkEvents(): void {
if (!this.toolbarSparkStats) {
return;
}

this.toolbarSparkStats.node.addEventListener('click', this.handleToolbarSparkClick);
}

destroy() {
this.clear();
this.toolbarSparkStats && this.toolbarSparkStats.isAttached && this.toolbarSparkStats.dispose();
this.sparkUIView = null;
}

clear() {
this.toolbarSparkStats.node.innerHTML = '';
}

propagateToolbarWidget() {
this.toolbarSparkStats.node.innerHTML = `<div class="p-Widget bx-status-panel widget-box widget-hbox">
${this.sparkUIView.connectionStatusElement.outerHTML}
${this.sparkUIView.sparkStats.node.outerHTML}
</div>`;
}

append(): void {
if (!this.sparkUIView.el.querySelector('.bx-status-panel')) {
return;
}

if (
this.toolbarStatusContainer
&& this.toolbarStatusContainer.contains(this.toolbarSparkStats.node)
) {
this.propagateToolbarWidget();

return;
}

const toolbarContainer = this.sparkUIView.el.closest('.jp-NotebookPanel')
|| this.sparkUIView.el.closest('.notebook_app');

if (!toolbarContainer) {
return;
}

const toolbar = toolbarContainer.querySelector('#maintoolbar-container')
|| toolbarContainer.querySelector('.jp-NotebookPanel-toolbar');

if (!toolbar) {
return;
}

this.toolbarSparkStats = new Widget();
this.toolbarStatusContainer = toolbar;
this.toolbarSparkStats.node.classList.add('bx-toolbar-spark-widget');
this.propagateToolbarWidget();
this.appendToolbarSparkStats();
}

private handleToolbarSparkClick(event): void {
const relatedTarget = (event.relatedTarget || event.target) as HTMLElement;

if (relatedTarget.classList.contains('bx-connection-status')) {
return this.sparkUIView.openWebUi();
}

if (relatedTarget.classList.contains('label')) {
return this.sparkUIView.openExecutors();
}
}

private appendToolbarSparkStats() {
const previous = this.toolbarStatusContainer.querySelector('.bx-toolbar-spark-widget');
const spacer: HTMLElement|null = this.toolbarStatusContainer.querySelector('.jp-Toolbar-spacer');

previous && this.toolbarStatusContainer.removeChild(previous);

if (spacer) {
spacer.insertAdjacentElement("afterend", this.toolbarSparkStats.node);
} else {
this.toolbarStatusContainer.appendChild(this.toolbarSparkStats.node);
}
}
}

0 comments on commit 382f8a3

Please sign in to comment.