diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..089d79b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,63 @@ +name: Node.js CI + +# This workflow will attempt to build static resources with NPM for any commit to main, or PR'ed to main. +# Additionally, for any tags pushed (that start with 'v' indicating a version), a release will be created +# including the static resources. This release will be created as a draft so that more detailed notes can +# be added before marking it as a proper release. If a draft release already exists matching the tag name, +# the existing artifacts will be overridden, but the release body will remain. If the existing release is +# not a draft, nothing will be overridden. + +on: + push: + tags: + - 'v*' + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x] + + steps: + - uses: actions/checkout@v2 + - name: Reconfigure git to use HTTP authentication + run: > + GIT_TRACE=1 git config --global url."https://github.com/".insteadOf ssh://git@github.com/ + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + timeout-minutes: 2 + - run: npm run build --if-present + timeout-minutes: 10 + #- run: npm test temporarily remove; I think it's failing due to axios module import in odin-react + + - name: Create zip archive + run: | + cd build + zip -r build.zip . + - name: List contents of zip + run: unzip -l build/build.zip + - name: Create release if tagged + if: startsWith(github.ref, 'refs/tags/v') + uses: ncipollo/release-action@v1 + with: + artifactErrorsFailBuild: true + artifacts: build/build.zip + + # Create as a draft so that it can be vetted and notes added + draft: true + generateReleaseNotes: true + skipIfReleaseExists: true + + # Update an existing release, but only if it's draft or prerelease. If notes already exist, leave them. + allowUpdates: true + updateOnlyUnreleased: true + omitBodyDuringUpdate: true diff --git a/src/App.js b/src/App.js index d2718d5..daab6d7 100644 --- a/src/App.js +++ b/src/App.js @@ -8,13 +8,12 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import {OdinApp, StatusBox, useAdapterEndpoint, TitleCard, DropdownSelector, WithEndpoint, ToggleSwitch, OdinGraph, OdinDoubleSlider} from 'odin-react'; import 'odin-react/dist/index.css' -import {StatusBadge, LOKIConnectionAlert, LOKIClockGenerator, LOKICarrierInfo, LOKILEDDisplay, LOKIEnvironment, LOKICarrierTaskStatus} from './Loki.js' +import {StatusBadge, LOKIConnectionAlert, LOKIClockGenerator, LOKICarrierInfo, LOKIEnvironment, LOKICarrierTaskStatus} from './Loki.js' -import {Row, Col, Container, Dropdown, Card, Alert, Button, Spinner, Image, Modal} from 'react-bootstrap' +import {Row, Col, Container, Dropdown, Card, Alert, Button, Spinner, Image} from 'react-bootstrap' import * as Icon from 'react-bootstrap-icons'; import Mermaid from "./Mermaid"; -import mermaid from "mermaid"; const ResetMonitorEndpointButton = WithEndpoint(Button); const SyncEndpointToggleSwitch = WithEndpoint(ToggleSwitch); @@ -52,41 +51,38 @@ function BabyD() { - + - + - + - + - + - {/* - - */} - + - + @@ -104,12 +100,12 @@ function BabyD() { - + - + @@ -126,7 +122,7 @@ function BabyD() { const MainEndpointButton = WithEndpoint(Button); const InitialisedEndpointButton = WithEndpoint(Button); -function BabyD_System_Status({adapterEndpoint, loki_connection_state, asic_enabled, set_asic_enabled, foundLoopException}) { +function BabyDSystemStatus({adapterEndpoint, loki_connection_state, asic_enabled, set_asic_enabled, foundLoopException}) { let latest_asic_enabled = adapterEndpoint.data.application?.system_state?.ASIC_EN; if (latest_asic_enabled) { @@ -245,7 +241,7 @@ function BabyD_System_Status({adapterEndpoint, loki_connection_state, asic_enabl - + @@ -257,7 +253,7 @@ function BabyD_System_Status({adapterEndpoint, loki_connection_state, asic_enabl } -function BabyD_Device_Init_Badges({adapterEndpoint, hide_init_done=true}) { +function BabyDDeviceInitBadges({adapterEndpoint, hide_init_done=true}) { let devices = { 'FireFly' : 'FIREFLY', 'DAC u1' : 'DAC_U1', @@ -276,7 +272,7 @@ function BabyD_Device_Init_Badges({adapterEndpoint, hide_init_done=true}) { console.log('device key', device_key); return ( - {(device_state != 'initialised' || !hide_init_done) && } + {(device_state !== 'initialised' || !hide_init_done) && } ) }); @@ -291,17 +287,11 @@ function BabyD_Device_Init_Badges({adapterEndpoint, hide_init_done=true}) { } } -function BabyD_Main_Control({periodicEndpoint}) { - // This should be the main component used to bring up the system. It should clearly indicate current state, - // and if possible make obvious what next steps should be. Intuitiveness is key. The user should KNOW when - // it's safe to power down etc just by glancing at it, and KNOW what to click next. -} - -const FIFO_input_Dropdown = WithEndpoint(DropdownSelector); -const Aurora_input_Dropdown = WithEndpoint(DropdownSelector); -const Output_Dropdown = WithEndpoint(DropdownSelector); -const PRBS_len_Dropdown = WithEndpoint(DropdownSelector); -function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { +const FIFOInputDropdown = WithEndpoint(DropdownSelector); +const AuroraInputDropdown = WithEndpoint(DropdownSelector); +const OutputDropdown = WithEndpoint(DropdownSelector); +const PRBSLenDropdown = WithEndpoint(DropdownSelector); +function BabyDDataConfig({adapterEndpoint, asic_enabled, showgraph=false}) { // Show intuitively the configuration of what's being output via the fast data and pixel logic as a flowchart. // Also allow configuration of these settings. // Also show the full pathway including the carrier board, therefore retimer settings and firefly settings @@ -321,13 +311,13 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { subgraph FIFO - ` + ((output_currently_selected == 'aurora' && aurora_currently_selected == 'fifo') ? ` + ` + ((output_currently_selected === 'aurora' && aurora_currently_selected === 'fifo') ? ` fifo{FIFO} style fifo stroke:#333,stroke-width:4px ` : ` fifo{FIFO} `) + ` - ` + (fifo_currently_selected == 'prbs15' ? ` + ` + (fifo_currently_selected === 'prbs15' ? ` PRBS15 ==> fifo pixel -.-> fifo ` : ` @@ -338,14 +328,14 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { subgraph PRBS-Select - ` + ((output_currently_selected == 'prbs') || (output_currently_selected == 'aurora' && aurora_currently_selected == 'prbs') ? ` + ` + ((output_currently_selected === 'prbs') || (output_currently_selected === 'aurora' && aurora_currently_selected === 'prbs') ? ` prbssel{PRBS
SELECT} style prbssel stroke:#333,stroke-width:4px ` : ` prbssel{PRBS
SELECT} `) + ` - ` + (prbs_currently_selected == '15' ? ` + ` + (prbs_currently_selected === '15' ? ` PRBS23 -.-> prbssel PRBS15 ==> prbssel ` : ` @@ -355,13 +345,13 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { end subgraph Aurora - ` + (output_currently_selected == 'aurora' ? ` + ` + (output_currently_selected === 'aurora' ? ` aurora{Aurora} style aurora stroke:#333,stroke-width:4px ` : ` aurora{Aurora} `) + ` - ` + (aurora_currently_selected == 'fifo' ? ` + ` + (aurora_currently_selected === 'fifo' ? ` prbssel -.-> aurora fifo ==> aurora ` : ` @@ -370,8 +360,8 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { `) + ` end ` + ( - ` user[User Pattern
` + adapterEndpoint.data.application?.pipeline?.user_pattern + `
0x` + adapterEndpoint.data.application?.pipeline?.user_pattern.toString(16) +`]`) + ` - ` + (output_currently_selected == 'user' ? ` + ` user[User Pattern
` + adapterEndpoint.data.application?.pipeline?.user_pattern + `
0x` + adapterEndpoint.data.application?.pipeline?.user_pattern.toString(16) +`]`) + + (output_currently_selected === 'user' ? ` style user stroke:#333,stroke-width:4px ` : ` `) + ` @@ -379,11 +369,11 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { subgraph Output output[Output] style output stroke:#333,stroke-width:4px - ` + (output_currently_selected == 'user' ? ` + ` + (output_currently_selected === 'user' ? ` prbssel -...-> output user ==> output aurora -.-> output - ` : (output_currently_selected == 'prbs' ? ` + ` : (output_currently_selected === 'prbs' ? ` prbssel ====> output user -.-> output aurora -.-> output @@ -406,31 +396,31 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { {/*{adapterEndpoint.data.application?.pipeline?.prbs_length}*/} - + PRBS-15 PRBS-23 - + - + prbs15 pixel - + - + fifo prbs - + - + prbs aurora user - + @@ -448,7 +438,7 @@ function BabyD_Data_Config({adapterEndpoint, asic_enabled, showgraph=false}) { } const EndpointRowSelectSlider = WithEndpoint(OdinDoubleSlider); -function BabyD_Frame_Config({adapterEndpoint, asic_enabled}) { +function BabyDFrameConfig({adapterEndpoint, asic_enabled}) { // Show intuitively the configuration of what's being output via the fast data and pixel logic as a flowchart. // Also allow configuration of these settings. // Also show the full pathway including the carrier board, therefore retimer settings and firefly settings @@ -476,9 +466,8 @@ function BabyD_Frame_Config({adapterEndpoint, asic_enabled}) { } } -const SerialiserHalfrateButton = WithEndpoint(Button); const SerialiserHalfrateToggleSwitch = WithEndpoint(ToggleSwitch); -function BabyD_Serialiser_Config({adapterEndpoint, asic_enabled}) { +function BabyDSerialiserConfig({adapterEndpoint, asic_enabled}) { let halfrate_en = adapterEndpoint?.data?.application?.serialiser?.halfrate; if (asic_enabled) { @@ -499,12 +488,7 @@ function BabyD_Serialiser_Config({adapterEndpoint, asic_enabled}) { } } -function BabyD_SPIReadout() { - // A basic trigger for SPI readout, with in-browser heatmap rendering. - // Potentially allow configuration of system for multi-frame etc -} - -function BabyD_Timing_Settings({adapterEndpoint, asic_enabled}) { +function BabyDTimingSettings({adapterEndpoint, asic_enabled}) { // Intuitively display the current timing settings if (!asic_enabled) { @@ -552,7 +536,7 @@ function BabyD_Timing_Settings({adapterEndpoint, asic_enabled}) { const VDACReadbackButton = WithEndpoint(Button); const IDACReadbackButton = WithEndpoint(Button); -function BabyD_Bias_Control({adapterEndpoint, asic_enabled}) { +function BabyDBiasControl({adapterEndpoint, asic_enabled}) { // Allow configuration of DACs, ADCs, both internal and external (bias settings). // Visually demonstrate where sources of signals are. if (!asic_enabled) { @@ -586,7 +570,7 @@ function BabyD_Bias_Control({adapterEndpoint, asic_enabled}) { {source_select && {source_select}} - {source_select == 'internal' && {bias_info[bias_name]?.sources?.internal?.count}} + {source_select === 'internal' && {bias_info[bias_name]?.sources?.internal?.count}} @@ -620,16 +604,7 @@ function BabyD_Bias_Control({adapterEndpoint, asic_enabled}) { } -function BabyD_RegisterAccess() { - // Simple UI element to read and write ASIC registers. Potentially a table or just - // simple form? This will not be synchronous in any way, but could be quite useful. - // This should also somehow make use of the field-based system for browsing register - // mappings, as these should make things intuitive. - // Consider efficient access, and whether this will end up spamming requests to the - // ASIC where bits are volatile. -} - -function BabyD_Readout_Image({adapterEndpoint, asic_enabled}) { +function BabyDReadoutImage({adapterEndpoint, asic_enabled}) { let image_source = adapterEndpoint.data?.application?.readout?.imgout; if (!asic_enabled) { @@ -651,7 +626,7 @@ function BabyD_Readout_Image({adapterEndpoint, asic_enabled}) { } } -function BabyD_Readout_Render({adapterEndpoint, asic_enabled}) { +function BabyDReadoutRender({adapterEndpoint, asic_enabled}) { let image_dat_fine = adapterEndpoint.data?.application?.readout?.imgdat_fine; let image_dat_coarse = adapterEndpoint.data?.application?.readout?.imgdat_coarse; let image_dat_combined = adapterEndpoint.data?.application?.readout?.imgdat_combined; @@ -660,7 +635,7 @@ function BabyD_Readout_Render({adapterEndpoint, asic_enabled}) { return (<>); } - if ((typeof image_dat_fine !== 'undefined' && image_dat_fine != null) && (typeof image_dat_coarse !== 'undefined' || image_dat_coarse != null) && (typeof image_dat_combined !== 'undefined' && image_dat_combined != null)) { + if ((typeof image_dat_fine !== 'undefined' && image_dat_fine !== null) && (typeof image_dat_coarse !== 'undefined' || image_dat_coarse !== null) && (typeof image_dat_combined !== 'undefined' && image_dat_combined !== null)) { return ( @@ -683,7 +658,7 @@ function BabyD_Readout_Render({adapterEndpoint, asic_enabled}) { } } -function BabyD_Lane_Config({adapterEndpoint, asic_enabled}) { +function BabyDLaneConfig({adapterEndpoint, asic_enabled}) { // This will combine firefly and retimer controls for given lanes. if (!asic_enabled) { return (<>); @@ -708,10 +683,10 @@ function BabyD_Lane_Config({adapterEndpoint, asic_enabled}) { - + - + ) diff --git a/src/Loki.js b/src/Loki.js index c794d70..d248034 100644 --- a/src/Loki.js +++ b/src/Loki.js @@ -1,19 +1,18 @@ import React from 'react'; -import {useAdapterEndpoint, DropdownSelector, WithEndpoint, TitleCard, OdinGraph} from 'odin-react'; -import {Dropdown, Row, Col, Alert} from 'react-bootstrap'; -import {useState} from 'react'; +import {DropdownSelector, WithEndpoint, TitleCard, OdinGraph} from 'odin-react'; +import {Dropdown, Row, Alert} from 'react-bootstrap'; const ClkgenEndpointDropdown = WithEndpoint(DropdownSelector); export function StatusBadge(_ref) { let label = _ref.label; let type = _ref.type; - if (type == null) { + if (type === null || typeof type === 'undefined') { type = "primary"; } let wrap = _ref.wrap; - if (wrap == null) { + if (wrap === null || typeof wrap === 'undefined') { wrap = false } @@ -68,7 +67,7 @@ export function LOKIClockGenerator({adapterEndpoint}) { return ( - Clock Generator Device: + Clock Generator Device: {options} @@ -196,7 +195,7 @@ export function LOKIEnvironment({adapterEndpoint, records_to_render}) { } function LOKIEnvironmentGraph({tempreadings, tempHeaders, humreadings, humHeaders}) { - if (tempreadings == null) { + if (tempreadings === null || typeof tempreadings === 'undefined') { return (<>) } return ( @@ -260,12 +259,11 @@ export function LOKICarrierTaskStatus({adapterEndpoint, loki_connection_state, s if (typeof loopstatus !== 'undefined') { let loopnames = Object.keys(loopstatus); looprows = loopnames.map((loopname) => { - let loopinfo = loopstatus[loopname]; let looprunning = adapterEndpoint.data.carrier_info?.loopstatus[loopname]?.running; let loopdone = adapterEndpoint.data.carrier_info?.loopstatus[loopname]?.done; let loopexception = adapterEndpoint.data.carrier_info?.loopstatus[loopname]?.exception; - if (loopexception != "N/A") { + if (loopexception !== "N/A") { loop_exception_found = true; }; @@ -275,7 +273,7 @@ export function LOKICarrierTaskStatus({adapterEndpoint, loki_connection_state, s - + )