diff --git a/forum-network/.eslintrc.js b/forum-network/.eslintrc.js index 3a4f0e3..6f3bea1 100644 --- a/forum-network/.eslintrc.js +++ b/forum-network/.eslintrc.js @@ -37,6 +37,7 @@ module.exports = { 'no-multi-assign': ['off'], 'no-constant-condition': ['off'], 'no-await-in-loop': ['off'], + 'no-underscore-dangle': ['off'], }, globals: { _: 'readonly', @@ -44,5 +45,6 @@ module.exports = { sinon: 'readonly', sinonChai: 'readonly', should: 'readonly', + mocha: 'readonly', }, }; diff --git a/forum-network/src/classes/display/box.js b/forum-network/src/classes/display/box.js index faacf17..46f49f6 100644 --- a/forum-network/src/classes/display/box.js +++ b/forum-network/src/classes/display/box.js @@ -2,16 +2,20 @@ import { DisplayValue } from './display-value.js'; import { randomID } from '../../util.js'; export class Box { - constructor(name, parentEl, elementType = 'div') { + constructor(name, parentEl, options = {}) { this.name = name; - this.el = document.createElement(elementType); + this.el = document.createElement('div'); this.el.id = `box_${randomID()}`; this.el.classList.add('box'); if (name) { this.el.setAttribute('box-name', name); } if (parentEl) { - parentEl.appendChild(this.el); + if (options.prepend) { + parentEl.prepend(this.el); + } else { + parentEl.appendChild(this.el); + } } } @@ -35,8 +39,8 @@ export class Box { return this; } - addBox(name, elementType) { - const box = new Box(name, this.el, elementType); + addBox(name) { + const box = new Box(name, this.el); return box; } diff --git a/forum-network/src/classes/display/controls.js b/forum-network/src/classes/display/controls.js new file mode 100644 index 0000000..4911456 --- /dev/null +++ b/forum-network/src/classes/display/controls.js @@ -0,0 +1,52 @@ +class Button { + constructor(innerHTML, onclick) { + this.el = document.createElement('button'); + this.el.innerHTML = innerHTML; + this.el.onclick = onclick; + } +} + +export class Controls { + constructor(parentBox) { + this.disableAutoplayButton = new Button('Disable Auto-play', () => { + const url = new URL(window.location.href); + url.searchParams.set('auto', 'false'); + window.location.href = url.href; + }); + this.enableAutoplayButton = new Button('Enable Auto-play', () => { + const url = new URL(window.location.href); + url.searchParams.delete('auto'); + window.location.href = url.href; + }); + this.stepButton = new Button('Next Action', () => { + console.log('Next Action button clicked'); + document.dispatchEvent(new Event('next-action')); + }); + + if (window.autoPlay) { + parentBox.el.appendChild(this.disableAutoplayButton.el); + } else { + parentBox.el.appendChild(this.enableAutoplayButton.el); + parentBox.el.appendChild(this.stepButton.el); + // Disable `stepButton` when test is complete + setInterval(() => { + this.stepButton.el.disabled = mocha._state !== 'running'; + }, 200); + } + } +} + +export async function delayOrWait(delayMs) { + if (window.autoPlay) { + await new Promise((resolve) => { + setTimeout(resolve, delayMs); + }); + } else { + await new Promise((resolve) => { + document.addEventListener('next-action', () => { + console.log('next-action event received'); + resolve(); + }, { once: true }); + }); + } +} diff --git a/forum-network/src/classes/display/scene.js b/forum-network/src/classes/display/scene.js index e455421..f0e76b3 100644 --- a/forum-network/src/classes/display/scene.js +++ b/forum-network/src/classes/display/scene.js @@ -4,6 +4,8 @@ import { MermaidDiagram } from './mermaid.js'; import { SequenceDiagram } from './sequence.js'; import { Table } from './table.js'; import { Flowchart } from './flowchart.js'; +import { Controls } from './controls.js'; +import { Box } from './box.js'; export class Scene { constructor(name, rootBox) { @@ -24,6 +26,14 @@ export class Scene { this.options = { edgeNodeColor: '#4d585c', }; + + window.autoPlay = new URL(window.location.href).searchParams.get('auto') !== 'false'; + + if (!window.disableSceneControls) { + this.topRail = new Box('Top rail', document.body, { prepend: true }).addClass('top-rail'); + this.controlsBox = this.topRail.addBox('Controls').addClass('controls'); + this.controls = new Controls(this.controlsBox); + } } withSequenceDiagram() { diff --git a/forum-network/src/index.css b/forum-network/src/index.css index 1c71ee9..1ff9007 100644 --- a/forum-network/src/index.css +++ b/forum-network/src/index.css @@ -36,6 +36,17 @@ a:visited { .padded { padding: 20px; } +.top-rail { + position: sticky; + top: 0; + left: 0; + width: 100%; + height: 0; +} +.controls { + position: relative; + left: 150px; +} svg { width: 800px; } @@ -49,3 +60,14 @@ td { .edge > rect { fill: #216262 !important; } +button { + margin: 5px; + margin-top: 1em; + background-color: #c6f4ff; + border-color: #b6b6b6; + border-radius: 5px; +} +button:disabled { + background-color: #2a535e; + color: #919191; +} diff --git a/forum-network/src/tests/all.test.html b/forum-network/src/tests/all.test.html index 82baba7..7f89e7c 100644 --- a/forum-network/src/tests/all.test.html +++ b/forum-network/src/tests/all.test.html @@ -12,6 +12,9 @@