diff --git a/images/checkmark.svg b/images/checkmark.svg new file mode 100644 index 0000000..c560639 --- /dev/null +++ b/images/checkmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js/workflows/ble.js b/js/workflows/ble.js index fc8fde2..5cecbda 100644 --- a/js/workflows/ble.js +++ b/js/workflows/ble.js @@ -29,6 +29,12 @@ class BLEWorkflow extends Workflow { this.infoDialog = new DeviceInfoModal("device-info"); this.partialWrites = true; this.type = CONNTYPE.Ble; + this.buttonStates = [ + {reconnect: false, request: false, bond: false}, + {reconnect: false, request: true, bond: false}, + {reconnect: true, request: true, bond: false}, + {reconnect: false, request: false, bond: true}, + ]; } // This is called when a user clicks the main disconnect button @@ -50,6 +56,13 @@ class BLEWorkflow extends Workflow { btnBond = modal.querySelector('#promptBond'); btnReconnect = modal.querySelector('#bleReconnect'); + // Map the button states to the buttons + this.connectButtons = { + reconnect: btnReconnect, + request: btnRequestBluetoothDevice, + bond: btnBond + }; + btnRequestBluetoothDevice.addEventListener('click', async (event) => { await this.onRequestBluetoothDeviceButtonClick(event); }); @@ -273,23 +286,6 @@ class BLEWorkflow extends Workflow { async showInfo(documentState) { return await this.infoDialog.open(this, documentState); } - - // Handle the different button states for various connection steps - connectionStep(step) { - const buttonStates = [ - {reconnect: false, request: false, bond: false}, - {reconnect: false, request: true, bond: false}, - {reconnect: true, request: true, bond: false}, - {reconnect: false, request: false, bond: true}, - ]; - - if (step < 0) step = 0; - if (step > buttonStates.length - 1) step = buttonStates.length - 1; - - btnReconnect.disabled = !buttonStates[step].reconnect; - btnRequestBluetoothDevice.disabled = !buttonStates[step].request; - btnBond.disabled = !buttonStates[step].bond; - } } export {BLEWorkflow}; diff --git a/js/workflows/usb.js b/js/workflows/usb.js index fec12ff..00b6ca0 100644 --- a/js/workflows/usb.js +++ b/js/workflows/usb.js @@ -24,6 +24,11 @@ class USBWorkflow extends Workflow { this._messageCallback = null; this._btnSelectHostFolderCallback = null; this._btnUseHostFolderCallback = null; + this.buttonStates = [ + {request: false, select: false}, + {request: true, select: false}, + {request: false, select: true}, + ]; } async init(params) { @@ -140,7 +145,7 @@ class USBWorkflow extends Workflow { } console.log(this._serialDevice); if (this._serialDevice != null) { - this._connectionStep(2); + this.connectionStep(2); return true; } @@ -156,6 +161,12 @@ class USBWorkflow extends Workflow { btnUseHostFolder = modal.querySelector('#useHostFolder'); lblWorkingfolder = modal.querySelector('#workingFolder'); + // Map the button states to the buttons + this.connectButtons = { + request: btnRequestSerialDevice, + select: btnSelectHostFolder, + }; + btnRequestSerialDevice.disabled = true; btnSelectHostFolder.disabled = true; let serialConnect = async (event) => { @@ -191,13 +202,13 @@ class USBWorkflow extends Workflow { if (stepOne = modal.querySelector('.step:first-of-type')) { stepOne.classList.add("hidden"); } - this._connectionStep(1); + this.connectionStep(1); } else { // If not, hide all steps beyond the message modal.querySelectorAll('.step:not(:first-of-type)').forEach((stepItem) => { stepItem.classList.add("hidden"); }); - this._connectionStep(0); + this.connectionStep(0); } // Hide the last step until we determine that we need it @@ -250,7 +261,6 @@ class USBWorkflow extends Workflow { // Workflow specific Functions async _switchToDevice(device) { - device.removeEventListener("message", this._messageCallback); this._messageCallback = this.onSerialReceive.bind(this); device.addEventListener("message", this._messageCallback); @@ -365,21 +375,6 @@ print(binascii.hexlify(microcontroller.cpu.uid).decode('ascii').upper())` async showInfo(documentState) { return await this.infoDialog.open(this, documentState); } - - // Handle the different button states for various connection steps - _connectionStep(step) { - const buttonStates = [ - {request: false, select: false}, - {request: true, select: false}, - {request: true, select: true}, - ]; - - if (step < 0) step = 0; - if (step > buttonStates.length - 1) step = buttonStates.length - 1; - - btnRequestSerialDevice.disabled = !buttonStates[step].request; - btnSelectHostFolder.disabled = !buttonStates[step].select; - } } export {USBWorkflow}; diff --git a/js/workflows/web.js b/js/workflows/web.js index b78ac28..5c26438 100644 --- a/js/workflows/web.js +++ b/js/workflows/web.js @@ -23,6 +23,8 @@ class WebWorkflow extends Workflow { this.deviceDiscoveryDialog = new DiscoveryModal("device-discovery"); this.connIntervalId = null; this.type = CONNTYPE.Web; + this.buttonStates = []; + this.buttons = {}; } // This is called when a user clicks the main disconnect button diff --git a/js/workflows/workflow.js b/js/workflows/workflow.js index 0889768..661acb0 100644 --- a/js/workflows/workflow.js +++ b/js/workflows/workflow.js @@ -50,6 +50,8 @@ class Workflow { this.repl = new REPL(); this.plotterEnabled = false; this.plotterChart = false; + this.buttonStates = []; + this.connectButtons = {}; } async init(params) { @@ -308,6 +310,33 @@ class Workflow { async available() { return Error("This work flow is not available."); } + + // Handle the different button states for various connection steps + connectionStep(step) { + if (step < 0) step = 0; + if (step > this.buttonStates.length - 1) step = this.buttonStates.length - 1; + + for (let button in this.connectButtons) { + this.connectButtons[button].disabled = !this.buttonStates[step][button]; + } + + // Mark all previous steps as completed (hidden or not) + for (let stepNumber = 0; stepNumber < step; stepNumber++) { + this._markStepCompleted(stepNumber); + } + } + + _markStepCompleted(stepNumber) { + let modal = this.connectDialog.getModal(); + let steps = modal.querySelectorAll('.step'); + // For any steps prior to the last step, add a checkmark + for (let i = 0; i < steps.length - 1; i++) { + let step = steps[stepNumber]; + if (!step.classList.contains('completed')) { + step.classList.add('completed'); + } + } + } } export { diff --git a/sass/layout/_grid.scss b/sass/layout/_grid.scss index fc2e3f2..36c9221 100644 --- a/sass/layout/_grid.scss +++ b/sass/layout/_grid.scss @@ -55,6 +55,17 @@ &.hidden { display: none; } + + &.completed .step-number::after { + content: ""; + background: url('/images/checkmark.svg'); + position: relative; + display: block; + top: 20px; + width: 50px; + height: 50px; + filter: drop-shadow(2px 2px 2px #888); + } } }