diff --git a/package-lock.json b/package-lock.json
index 35e604c..4d1cd84 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "ui-barebones",
+ "name": "ui",
"lockfileVersion": 3,
"requires": true,
"packages": {
diff --git a/src/index.ts b/src/index.ts
index b691602..6f598ec 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,16 +1,9 @@
-import { FarpatchWidget } from './interfaces';
-import { UartWidget } from './interface/uart';
-import { DashboardWidget } from './interface/dashboard';
-
-var FarpatchWidgets: { [key: string]: FarpatchWidget } = {
- "dashboard": new DashboardWidget(),
- "uart": new UartWidget(),
-};
+import { FarpatchWidget, farpatchWidgets } from './interfaces';
// TODO: Get the current widget from the address bar, if one exists
-var currentWidgetName: string = "dashboard";
-var currentWidget: FarpatchWidget = FarpatchWidgets[currentWidgetName];
-var currentWidgetView: HTMLElement = document.getElementById(currentWidgetName + "-view") as HTMLElement;
+var currentWidget: FarpatchWidget = farpatchWidgets[0];
+var widgetViews: HTMLElement[] = [];
+// var currentWidgetView: HTMLElement = document.getElementById(currentWidgetName + "-view") as HTMLElement;
function addToggleSidebarListener(element: HTMLElement) {
// Hide or show the sidebar. MaterialUI calls this toggling between
@@ -31,97 +24,88 @@ function addToggleSidebarListener(element: HTMLElement) {
}, false);
}
-// On load, add a listener for mouse clicks on the navigation bar.
-function setupNavItem(element: HTMLElement) {
- // Get the base name of the element in order to set up the callback.
- var elementBase = element.id.replace("-button", "");
- if (typeof (FarpatchWidgets[elementBase]) === 'undefined') {
- console.log("No widget found for " + elementBase);
- // return;
- } else {
- console.log("Setting up widget for " + elementBase);
- var elementContent = document.getElementById(elementBase + "-view");
- if (typeof (elementContent) === 'undefined' || elementContent === null) {
- console.log("No element found for " + elementBase + "-view");
- return;
- }
- FarpatchWidgets[elementBase].onInit();
+function deactivateWidget(widget: FarpatchWidget) {
+ widget.navItem.classList.remove("sidenav-item-active");
+ widgetViews[widget.index].classList.remove("main-content-active");
+ widget.onBlur(widgetViews[widget.index]);
+}
- if (FarpatchWidgets[elementBase] === currentWidget) {
- element.classList.add("sidenav-item-active");
- FarpatchWidgets[elementBase].onFocus(elementContent);
- currentWidgetView = elementContent;
- elementContent.classList.add("main-content-active");
- } else {
- console.log("Not initializing widget " + elementBase);
- }
+function activateWidget(widget: FarpatchWidget) {
+ widget.navItem.classList.add("sidenav-item-active");
+ widgetViews[widget.index].classList.add("main-content-active");
+ widget.onFocus(widgetViews[widget.index]);
+}
+
+function switchToWidget(widget: FarpatchWidget) {
+ if (widget === currentWidget) {
+ return;
}
+ deactivateWidget(currentWidget);
+ currentWidget = widget;
+ activateWidget(widget);
+}
- // Hook "click" for each navigation item. The listener will:
- // 1. Loop through each nav item and remove the "active" class for
- // each inactive item and add it to the newly-clicked item.
- // 2. Unhide the correct view to activate it
- element.addEventListener('click', function () {
- var main = document.getElementsByTagName("main")[0];
- var navItems = document.querySelectorAll(".sidenav-item");
- var elementBase = element.id.replace("-button", "");
- if (typeof (FarpatchWidgets[elementBase]) !== 'undefined') {
- if (FarpatchWidgets[elementBase] !== currentWidget) {
- var newElementContent = document.getElementById(elementBase + "-view");
- if (typeof (newElementContent) === 'undefined' || newElementContent === null) {
- console.log("No element found for " + elementBase + "-view");
- return;
- }
-
- currentWidget.onBlur(currentWidgetView);
- FarpatchWidgets[elementBase].onFocus(newElementContent);
- currentWidget = FarpatchWidgets[elementBase];
- currentWidgetName = elementBase;
- currentWidgetView = newElementContent;
- }
- }
-
- for (var i = 0; i < navItems.length; i++) {
- var navItem = navItems[i];
- if (navItem === element) {
- if (!navItem.classList.contains("sidenav-item-active")) {
- navItem.classList.add("sidenav-item-active");
- }
- } else {
- navItem.classList.remove("sidenav-item-active");
- }
- }
-
- var mainViews = document.querySelectorAll(".main-content-active");
- for (var i = 0; i < mainViews.length; i++) {
- var mainView = mainViews[i];
- mainView.classList.remove("main-content-active");
- }
-
- var elementBase = element.id.replace("-button", "");
- var elementContent = document.getElementById(elementBase + "-view");
- if (typeof (elementContent) === 'undefined' || elementContent === null) {
- console.log("No element found for " + elementBase + "-view");
- return;
- }
- elementContent.classList.add("main-content-active");
+// On load, add a listener for mouse clicks on the navigation bar.
+function setupNavItem(widget: FarpatchWidget) {
+ var w = widget;
+ widget.navItem.addEventListener('click', function () {
+ switchToWidget(w);
}, false);
}
document.addEventListener('DOMContentLoaded', function () {
- var navItems = document.querySelectorAll(".sidenav-item");
- for (var i = 0; i < navItems.length; i++) {
- // For the "toggle" button, don't add a listener. Instead, have it
- // toggle the visibility of the sidebar.
- if (navItems[i].classList.contains("sidenav-item-toggle")) {
- addToggleSidebarListener(navItems[i] as HTMLElement);
- } else {
- setupNavItem(navItems[i] as HTMLElement);
- }
+ // Populate the page
+ var body = document.getElementsByTagName("body")[0];
+ var sidenav = document.createElement("nav");
+ var mainView: HTMLElement = document.createElement("main");
+
+ sidenav.classList.add("sidenav");
+ var sidenavList = document.createElement("ul");
+ sidenavList.classList.add("sidenav-nav");
+
+ for (var i = 0; i < farpatchWidgets.length; i++) {
+ var widget = farpatchWidgets[i];
+ widget.onInit();
+
+ var widgetView = document.createElement("div");
+ widgetView.classList.add("main-content");
+ widgetView.id = widget.name + "-view";
+ widgetViews.push(widgetView);
+
+ mainView.appendChild(widgetView);
+ sidenavList.appendChild(widget.navItem);
+
+ setupNavItem(widget);
}
- // var navItems = document.querySelectorAll(".main-viewport");
- // for (var i = 0; i < navItems.length; i++) {
- // addNavListener(navItems[i]);
- // }
+ // Add the button to collapse the sidebar
+ var sidebarFiller = document.createElement("li");
+ sidebarFiller.classList.add("sidenav-item-filler");
+ sidenavList.appendChild(sidebarFiller);
+ var toggleSidebar = document.createElement("li");
+ toggleSidebar.classList.add("sidenav-item");
+ toggleSidebar.classList.add("sidenav-item-toggle");
+ toggleSidebar.id = "rail-toggle-button";
+ var toggleSidebarLink = document.createElement("a");
+ toggleSidebarLink.classList.add("sidenav-link");
+ var toggleSidebarIcon = document.createElement("span");
+ toggleSidebarIcon.classList.add("las");
+ toggleSidebarIcon.classList.add("la-3x");
+ toggleSidebarIcon.classList.add("la-bars");
+ toggleSidebarIcon.classList.add("icon");
+ var toggleSidebarText = document.createElement("span");
+ toggleSidebarText.classList.add("link-text");
+ toggleSidebarText.innerText = "Hide Sidebar";
+ toggleSidebarLink.appendChild(toggleSidebarIcon);
+ toggleSidebarLink.appendChild(toggleSidebarText);
+ toggleSidebar.appendChild(toggleSidebarLink);
+ sidenavList.appendChild(toggleSidebar);
+ addToggleSidebarListener(toggleSidebar);
+
+ sidenav.appendChild(sidenavList);
+ body.appendChild(sidenav);
+ body.appendChild(mainView);
+
+ currentWidget = farpatchWidgets[0];
+ activateWidget(farpatchWidgets[0]);
}, false);
diff --git a/src/interface/dashboard.ts b/src/interface/dashboard.ts
index 0b972fa..fc4ff58 100644
--- a/src/interface/dashboard.ts
+++ b/src/interface/dashboard.ts
@@ -1,10 +1,24 @@
-import { FarpatchWidget } from "../interfaces";
+import { FarpatchWidget, makeNavView as makeNavItem } from "../interfaces";
export class DashboardWidget implements FarpatchWidget {
- view: Element = document.createElement("div");
+ index: number = 0;
+ view: HTMLElement = document.createElement("div");
+ navItem: HTMLElement;
+ name: string;
+ icon: string = "home";
+ title: string = "Dashboard";
- onInit(): void {
- this.view.innerHTML = `
+ constructor(name: string) {
+ this.name = name;
+ this.navItem = makeNavItem(name, this.icon, this.title);
+ }
+
+ updateIndex(index: number): void {
+ this.index = index;
+ }
+
+ onInit(): void {
+ this.view.innerHTML = `
`;
- console.log("Initialized Dashboard Widget");
- }
- onFocus(element: HTMLElement): void {
- console.log("Displaying Dashboard Widget");
- element.appendChild(this.view);
- }
- onBlur(element: HTMLElement): void {
- console.log("Archiving Dashboard Widget");
- element.removeChild(this.view);
- }
+ console.log("Initialized Dashboard Widget");
+ }
+ onFocus(element: HTMLElement): void {
+ console.log("Displaying Dashboard Widget");
+ element.appendChild(this.view);
+ }
+ onBlur(element: HTMLElement): void {
+ console.log("Archiving Dashboard Widget");
+ element.removeChild(this.view);
+ }
}
diff --git a/src/interface/debug.ts b/src/interface/debug.ts
new file mode 100644
index 0000000..d57ebfc
--- /dev/null
+++ b/src/interface/debug.ts
@@ -0,0 +1,76 @@
+import { FarpatchWidget, makeNavView } from "../interfaces";
+import { Terminal } from '@xterm/xterm';
+import { FitAddon } from '@xterm/addon-fit';
+import { SerializeAddon } from '@xterm/addon-serialize';
+
+export class DebugWidget implements FarpatchWidget {
+ name: string;
+ icon: string = "scroll";
+ title: string = "Debug";
+ index: number = 0;
+
+ view: HTMLElement;
+ navItem: HTMLElement;
+
+ terminal: Terminal;
+ fitAddon: FitAddon;
+ serializeAddon: SerializeAddon;
+ resizeFunction: () => void;
+ initialized: boolean = false;
+ constructor(name: string) {
+ this.name = name;
+ this.navItem = makeNavView(name, this.icon, this.title);
+ this.view = document.createElement("div");
+ this.view.classList.add("terminal");
+ this.terminal = new Terminal({ theme: { background: "#000000" } });
+ this.fitAddon = new FitAddon();
+ this.serializeAddon = new SerializeAddon();
+ this.resizeFunction = this.resizeTerminal.bind(this);
+ }
+
+ updateIndex(index: number): void {
+ this.index = index;
+ }
+
+ onInit(): void {
+ console.log("Initialized Debug Widget");
+ }
+ onFocus(element: HTMLElement): void {
+ console.log("Displaying Debug Widget");
+ if (!this.initialized) {
+ // Ensure the parent frame doesn't get any scrollbars, since we're taking up the whole view
+ element.style.overflow = "hidden";
+ console.log("Initializing xterm.js");
+ // var terminalContainer = document.createElement("div");
+ // this.view.appendChild(terminalContainer);
+ this.terminal.loadAddon(this.fitAddon);
+ this.terminal.loadAddon(this.serializeAddon);
+ this.terminal.onKey((e) => {
+ console.log("Key pressed: " + e.key);
+ this.terminal.write(e.key);
+ if (e.key === '\r') {
+ this.terminal.write('\n');
+ }
+ });
+ this.terminal.open(this.view);
+ this.terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n');
+ this.initialized = true;
+ }
+ element.appendChild(this.view);
+ window.addEventListener('resize', this.resizeFunction);
+ window.setTimeout(() => {
+ this.terminal.focus();
+ this.resizeFunction();
+ }, 10);
+ }
+ onBlur(element: HTMLElement): void {
+ console.log("Archiving UART Widget");
+ element.removeChild(this.view);
+ window.removeEventListener('resize', this.resizeFunction);
+ }
+
+ // Whenever the window is resized, update the size of the terminal
+ resizeTerminal() {
+ this.fitAddon.fit();
+ }
+}
diff --git a/src/interface/rtt.ts b/src/interface/rtt.ts
new file mode 100644
index 0000000..e961858
--- /dev/null
+++ b/src/interface/rtt.ts
@@ -0,0 +1,76 @@
+import { FarpatchWidget, makeNavView } from "../interfaces";
+import { Terminal } from '@xterm/xterm';
+import { FitAddon } from '@xterm/addon-fit';
+import { SerializeAddon } from '@xterm/addon-serialize';
+
+export class RttWidget implements FarpatchWidget {
+ name: string;
+ icon: string = "microchip";
+ title: string = "RTT";
+ index: number = 0;
+
+ view: HTMLElement;
+ navItem: HTMLElement;
+
+ terminal: Terminal;
+ fitAddon: FitAddon;
+ serializeAddon: SerializeAddon;
+ resizeFunction: () => void;
+ initialized: boolean = false;
+ constructor(name: string) {
+ this.name = name;
+ this.navItem = makeNavView(name, this.icon, this.title);
+ this.view = document.createElement("div");
+ this.view.classList.add("terminal");
+ this.terminal = new Terminal({ theme: { background: "#000000" } });
+ this.fitAddon = new FitAddon();
+ this.serializeAddon = new SerializeAddon();
+ this.resizeFunction = this.resizeTerminal.bind(this);
+ }
+
+ updateIndex(index: number): void {
+ this.index = index;
+ }
+
+ onInit(): void {
+ console.log("Initialized RTT Widget");
+ }
+ onFocus(element: HTMLElement): void {
+ console.log("Displaying RTT Widget");
+ if (!this.initialized) {
+ // Ensure the parent frame doesn't get any scrollbars, since we're taking up the whole view
+ element.style.overflow = "hidden";
+ console.log("Initializing xterm.js");
+ // var terminalContainer = document.createElement("div");
+ // this.view.appendChild(terminalContainer);
+ this.terminal.loadAddon(this.fitAddon);
+ this.terminal.loadAddon(this.serializeAddon);
+ this.terminal.onKey((e) => {
+ console.log("Key pressed: " + e.key);
+ this.terminal.write(e.key);
+ if (e.key === '\r') {
+ this.terminal.write('\n');
+ }
+ });
+ this.terminal.open(this.view);
+ this.terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n');
+ this.initialized = true;
+ }
+ element.appendChild(this.view);
+ window.addEventListener('resize', this.resizeFunction);
+ window.setTimeout(() => {
+ this.terminal.focus();
+ this.resizeFunction();
+ }, 10);
+ }
+ onBlur(element: HTMLElement): void {
+ console.log("Archiving UART Widget");
+ element.removeChild(this.view);
+ window.removeEventListener('resize', this.resizeFunction);
+ }
+
+ // Whenever the window is resized, update the size of the terminal
+ resizeTerminal() {
+ this.fitAddon.fit();
+ }
+}
diff --git a/src/interface/settings.ts b/src/interface/settings.ts
new file mode 100644
index 0000000..a5a4c39
--- /dev/null
+++ b/src/interface/settings.ts
@@ -0,0 +1,57 @@
+import { FarpatchWidget, makeNavView as makeNavItem } from "../interfaces";
+
+export class SettingsWidget implements FarpatchWidget {
+ index: number = 0;
+ view: HTMLElement = document.createElement("div");
+ navItem: HTMLElement;
+ name: string;
+ icon: string = "sliders-h";
+ title: string = "Settings";
+
+ constructor(name: string) {
+ this.name = name;
+ this.navItem = makeNavItem(name, this.icon, this.title);
+ }
+
+ updateIndex(index: number): void {
+ this.index = index;
+ }
+
+ onInit(): void {
+ this.view.innerHTML = `
+
+
+
+
+
+
+
+ `;
+ console.log("Initialized Dashboard Widget");
+ }
+ onFocus(element: HTMLElement): void {
+ console.log("Displaying Dashboard Widget");
+ element.appendChild(this.view);
+ }
+ onBlur(element: HTMLElement): void {
+ console.log("Archiving Dashboard Widget");
+ element.removeChild(this.view);
+ }
+}
diff --git a/src/interface/uart.ts b/src/interface/uart.ts
index 0299652..5fceccc 100644
--- a/src/interface/uart.ts
+++ b/src/interface/uart.ts
@@ -1,16 +1,25 @@
-import { FarpatchWidget } from "../interfaces";
+import { FarpatchWidget, makeNavView } from "../interfaces";
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import { SerializeAddon } from '@xterm/addon-serialize';
export class UartWidget implements FarpatchWidget {
+ name: string;
+ icon: string = "keyboard";
+ title: string = "UART";
+ index: number = 0;
+
view: HTMLElement;
+ navItem: HTMLElement;
+
terminal: Terminal;
fitAddon: FitAddon;
serializeAddon: SerializeAddon;
resizeFunction: () => void;
initialized: boolean = false;
- constructor() {
+ constructor(name: string) {
+ this.name = name;
+ this.navItem = makeNavView(name, this.icon, this.title);
this.view = document.createElement("div");
this.view.classList.add("terminal");
this.terminal = new Terminal({ theme: { background: "#000000" } });
@@ -18,6 +27,11 @@ export class UartWidget implements FarpatchWidget {
this.serializeAddon = new SerializeAddon();
this.resizeFunction = this.resizeTerminal.bind(this);
}
+
+ updateIndex(index: number): void {
+ this.index = index;
+ }
+
onInit(): void {
console.log("Initialized UART Widget");
}
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 3c0421c..bced5ed 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -1,5 +1,57 @@
+
+import { UartWidget } from "./interface/uart";
+import { DashboardWidget } from "./interface/dashboard";
+import { RttWidget } from "./interface/rtt";
+import { DebugWidget } from "./interface/debug";
+import { SettingsWidget } from "./interface/settings";
+
export interface FarpatchWidget {
+ index: number,
+ name: string,
+ view: HTMLElement,
+ navItem: HTMLElement,
+ icon: string,
+ title: string,
+ updateIndex(index: number): void,
onInit(): void,
onFocus(element: HTMLElement): void,
onBlur(element: HTMLElement): void,
}
+
+export function makeNavView(name: string, icon: string, title: string): HTMLElement {
+ var navView: HTMLElement = document.createElement("li");
+ navView.classList.add("sidenav-item");
+ navView.id = name + "-button";
+
+ var navViewLink = document.createElement("a");
+ navViewLink.classList.add("sidenav-link");
+
+ var navViewIcon = document.createElement("span");
+ navViewIcon.classList.add("las");
+ navViewIcon.classList.add("la-3x");
+ navViewIcon.classList.add("la-" + icon);
+ navViewIcon.classList.add("icon");
+
+ var navViewText = document.createElement("span");
+ navViewText.classList.add("link-text");
+ navViewText.innerText = title;
+
+ navViewLink.appendChild(navViewIcon);
+ navViewLink.appendChild(navViewText);
+
+ navView.appendChild(navViewLink);
+
+ return navView;
+}
+
+export const farpatchWidgets: FarpatchWidget[] = [
+ new DashboardWidget("dashboard"),
+ new UartWidget("uart"),
+ new RttWidget("rtt"),
+ new DebugWidget("debug"),
+ new SettingsWidget("settings"),
+];
+
+for (var i = 0; i < farpatchWidgets.length; i++) {
+ farpatchWidgets[i].updateIndex(i);
+}
\ No newline at end of file
diff --git a/static/index.html b/static/index.html
index 75067d3..d3bd96a 100644
--- a/static/index.html
+++ b/static/index.html
@@ -13,7 +13,7 @@
-