diff --git a/.github/workflows/e2e_testing.yml b/.github/workflows/e2e_testing.yml new file mode 100644 index 00000000..47c01472 --- /dev/null +++ b/.github/workflows/e2e_testing.yml @@ -0,0 +1,15 @@ +name: E2E Testing +on: push + +jobs: + cypress-run: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Cypress run + uses: cypress-io/github-action@v6 + with: + build: npm run build + start: npm start + browser: chrome \ No newline at end of file diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ebbb93bd..0614e439 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -1,4 +1,4 @@ -name: Testing +name: Units Testing on: push diff --git a/README.md b/README.md index 121098cc..95fee091 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,21 @@ $ yarn start [demo & step-by-step manual](https://github.com/ComPlat/react-spectra-editor/blob/master/DEMO_MANUAL.md) +### Testing +#### Unit test +``` +$ yarn test +``` + +#### E2E test +``` +$ yarn start +``` + +Open another terminal +``` +$ yarn e2e +``` ## Acknowledgments diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 00000000..a119229d --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + experimentalStudio: true + }, +}); diff --git a/cypress/e2e/cv_spec.cy.ts b/cypress/e2e/cv_spec.cy.ts new file mode 100644 index 00000000..8550112a --- /dev/null +++ b/cypress/e2e/cv_spec.cy.ts @@ -0,0 +1,259 @@ +describe('CV', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('#btn-cv').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'V vs Ref') + cy.get('.d3Svg text.yLabel').should('have.text', 'A') + }) + + function addMaxPeak(view, offset=0) { + cy.get('.btn-sv-bar-addpeak').click() + cy.get('.d3Svg') + .trigger('click', 1110 + offset, 480, { + which: 1, + view: view, + }) + } + + function addMinPeak(view, offset=0) { + cy.get('.btn-sv-bar-addpeak').click() + cy.get('.d3Svg') + .trigger('click', 1050 + offset, 1480, { + which: 1, + view: view, + }) + } + + function addPecker(view, offset=0) { + cy.get('.btn-sv-bar-addpecker').click() + cy.get('.d3Svg') + .trigger('click', 1350 + offset, 1480, { + which: 1, + view: view, + }) + } + + function removeMaxPeak(view, offset=0) { + cy.get('.btn-sv-bar-rmpeak').click() + cy.get('.d3Svg') + .trigger('click', 1110 + offset, 450, { + which: 1, + view: view, + }) + } + + function removeMinPeak(view, offset=0) { + cy.get('.btn-sv-bar-rmpeak').click() + cy.get('.d3Svg') + .trigger('click', 1050 + offset, 900, { + which: 1, + view: view, + }) + } + + function removePecker(view, offset=0) { + cy.get('.btn-sv-bar-rmpecker').click() + cy.get('.d3Svg') + .trigger('click', 1350 + offset, 800, { + which: 1, + view: view, + }) + } + + it('Zoom in and zoom out on peaks', () => { + cy.get('[data-testid="GraphSelectionPanel"]').click(); + cy.get('[data-testid="GraphSelectionPanel"] ul > li:nth-child(2)').click(); + + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 1000, 300, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 1200, + clientY: 800, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + + }) + + it('Add peak and pecker', () => { + cy.window().then(win => { + cy.get('[data-testid="GraphSelectionPanel"]').click(); + cy.get('[data-testid="GraphSelectionPanel"] ul > li:nth-child(2)').click(); + cy.get('[data-testid="PanelVoltammetry"]').click(); + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(2)').click(); + + addMaxPeak(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(3)').click(); + + addMinPeak(win); + + addPecker(win); + }); + }) + + it('Remove peak and pecker', () => { + cy.window().then(win => { + cy.get('[data-testid="GraphSelectionPanel"]').click(); + cy.get('[data-testid="GraphSelectionPanel"] ul > li:nth-child(2)').click(); + cy.get('[data-testid="PanelVoltammetry"]').click(); + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(2)').click(); + + addMaxPeak(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(3)').click(); + + addMinPeak(win); + + addPecker(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(2)').click(); + + removeMaxPeak(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(3)').click(); + + removeMinPeak(win); + + removePecker(win); + }); + }) + + it('Add new list peak and pecker', () => { + cy.window().then(win => { + cy.get('[data-testid="GraphSelectionPanel"]').click(); + cy.get('[data-testid="GraphSelectionPanel"] ul > li:nth-child(2)').click(); + cy.get('[data-testid="PanelVoltammetry"]').click(); + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(2)').click(); + + addMaxPeak(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(3)').click(); + + addMinPeak(win); + + addPecker(win); + + + /* ==== Generated with Cypress Studio ==== */ + cy.get('[data-testid="AddCircleOutlineIcon"] > path').click(); + /* ==== End Cypress Studio ==== */ + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(2) > td:nth-child(2)').click(); + + addMaxPeak(win, 50); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(2) > td:nth-child(3)').click(); + + addMinPeak(win, 50); + + addPecker(win, 50); + + /* ==== Generated with Cypress Studio ==== */ + cy.get(':nth-child(1) > :nth-child(8) > [data-testid="RemoveCircleIcon"] > path').click({force: true}); + /* ==== End Cypress Studio ==== */ + }); + }) + + it('Set reference peaks', () => { + cy.window().then(win => { + cy.get('[data-testid="GraphSelectionPanel"]').click(); + cy.get('[data-testid="GraphSelectionPanel"] ul > li:nth-child(2)').click(); + cy.get('[data-testid="PanelVoltammetry"]').click(); + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(2)').click(); + + addMaxPeak(win); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(1) > td:nth-child(3)').click(); + + addMinPeak(win); + + addPecker(win); + + + /* ==== Generated with Cypress Studio ==== */ + cy.get('[data-testid="AddCircleOutlineIcon"] > path').click(); + /* ==== End Cypress Studio ==== */ + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(2) > td:nth-child(2)').click(); + + addMaxPeak(win, 50); + + cy.get('[data-testid="PanelVoltammetry"] table > tbody > tr:nth-child(2) > td:nth-child(3)').click(); + + addMinPeak(win, 50); + + addPecker(win, 50); + + /* ==== Generated with Cypress Studio ==== */ + cy.get(':nth-child(2) > :nth-child(1) > .MuiButtonBase-root > .PrivateSwitchBase-input').check(); + cy.get('[data-testid="AddLocationOutlinedIcon"]').click(); + cy.get('[data-testid="Pecker"] > .MuiFormControl-root > .MuiInputBase-root > #intg-factor-name').click(); + cy.get('[data-testid="Pecker"] > .MuiFormControl-root > .MuiInputBase-root > #intg-factor-name').click(); + cy.get('[data-testid="Pecker"] > .MuiFormControl-root > .MuiInputBase-root > #intg-factor-name').click(); + cy.get('[data-testid="AddLocationOutlinedIcon"]').click(); + cy.get(':nth-child(1) > :nth-child(1) > .MuiButtonBase-root > .PrivateSwitchBase-input').check(); + cy.get('[data-testid="AddLocationOutlinedIcon"]').click(); + /* ==== End Cypress Studio ==== */ + }); + }) + + it('Change axes labels', () => { + /* ==== Generated with Cypress Studio ==== */ + cy.get('[aria-labelledby="select-x-axis-label"]').click(); + cy.get('[data-value="Voltage in V"]').click(); + cy.get('[aria-labelledby="select-y-axis-label"]').click(); + cy.get('[data-value="Current in A"]').click(); + // /* ==== End Cypress Studio ==== */ + + cy.get('.d3Svg text.xLabel').should('have.text', 'Voltage in V') + cy.get('.d3Svg text.yLabel').should('have.text', 'Current in A') + + /* ==== Generated with Cypress Studio ==== */ + cy.get('[aria-labelledby="select-x-axis-label"]').click(); + cy.get('[data-value="Voltage vs Ref in V"]').click(); + cy.get('[aria-labelledby="select-y-axis-label"]').click(); + cy.get('[data-value="Current in mA"]').click(); + // /* ==== End Cypress Studio ==== */ + + cy.get('.d3Svg text.xLabel').should('have.text', 'Voltage vs Ref in V') + cy.get('.d3Svg text.yLabel').should('have.text', 'Current in mA') + + /* ==== Generated with Cypress Studio ==== */ + cy.get('[aria-labelledby="select-x-axis-label"]').click(); + cy.get('[data-value="Potential in V"]').click(); + cy.get('[aria-labelledby="select-y-axis-label"]').click(); + cy.get('[data-value="Current in A"]').click(); + /* ==== End Cypress Studio ==== */ + + cy.get('.d3Svg text.xLabel').should('have.text', 'Potential in V') + cy.get('.d3Svg text.yLabel').should('have.text', 'Current in A') + + // /* ==== Generated with Cypress Studio ==== */ + cy.get('[aria-labelledby="select-x-axis-label"]').click(); + cy.get('[data-value="Potential vs Ref in V"]').click(); + cy.get('[aria-labelledby="select-y-axis-label"]').click(); + cy.get('[data-value="Current in mA"]').click(); + /* ==== End Cypress Studio ==== */ + + cy.get('.d3Svg text.xLabel').should('have.text', 'Potential vs Ref in V') + cy.get('.d3Svg text.yLabel').should('have.text', 'Current in mA') + + }) +}) \ No newline at end of file diff --git a/cypress/e2e/hplc_spec.cy.ts b/cypress/e2e/hplc_spec.cy.ts new file mode 100644 index 00000000..d9bf0abe --- /dev/null +++ b/cypress/e2e/hplc_spec.cy.ts @@ -0,0 +1,118 @@ +describe('HPLC UV/VIS', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('#btn-hplc').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (MINUTES)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (TRANSMITTANCE)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + function addIntegration(view) { + cy.get('.btn-add-inter').click() + cy.get('.d3Svg') + .trigger('mousedown', 600, 1200, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 700, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }); + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 400, 100, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1000, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) + + it('Add integration', () => { + cy.window().then(win => { + addIntegration(win); + }); + }) + + it('Remove integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-remove-inter').click() + cy.get('.d3Svg') + .trigger('click', 700, 1400, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all integration', () => { + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-yes').click() + }) +}) \ No newline at end of file diff --git a/cypress/e2e/ir_spec.cy.ts b/cypress/e2e/ir_spec.cy.ts new file mode 100644 index 00000000..adc4063a --- /dev/null +++ b/cypress/e2e/ir_spec.cy.ts @@ -0,0 +1,74 @@ +describe('IR', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('button').contains('IR').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (1/CM)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (TRANSMITTANCE)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 170, { + which: 1, + view: view, + }) + } + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 800, 500, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 1000, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/nmr13c_dept_spec.cy.ts b/cypress/e2e/nmr13c_dept_spec.cy.ts new file mode 100644 index 00000000..03086457 --- /dev/null +++ b/cypress/e2e/nmr13c_dept_spec.cy.ts @@ -0,0 +1,238 @@ +describe('NMR 13C DEPT', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('button').contains('NMR 13C DEPT').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (PPM)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (ARBITRARY)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + function addIntegration(view) { + cy.get('.btn-add-inter').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 1200, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }); + } + + function addMultiplicity(view) { + cy.get('.btn-sv-bar-addmpy').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 100, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }) + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 650, 100, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 750, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) + + it('Add peak reference', () => { + cy.window().then(win => { + addPeak(win); + + cy.get('.btn-sv-bar-setref').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', 50*index, 670, { + which: 1, + view: win, + }) + } + }); + }) + + it('Add integration', () => { + cy.window().then(win => { + addIntegration(win); + }); + }) + + it('Remove integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-remove-inter').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Change ref area', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('#intg-factor-name').type('10') + cy.get('#intg-factor-name').clear().type('2') + }); + }) + + it('Set ref integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-set-inter-ref').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all integration', () => { + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + }); + }) + + it('Remove mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-rmmpy').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all multiplicity', () => { + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + }); + }) + + it('Remove peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + + cy.get('.btn-sv-bar-rmpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1485, { + which: 1, + view: win, + }) + } + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/nmr13c_spec.cy.ts b/cypress/e2e/nmr13c_spec.cy.ts new file mode 100644 index 00000000..968c62eb --- /dev/null +++ b/cypress/e2e/nmr13c_spec.cy.ts @@ -0,0 +1,238 @@ +describe('NMR 13C', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('button').contains('NMR 13C').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (PPM)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (ARBITRARY)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + function addIntegration(view) { + cy.get('.btn-add-inter').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 1200, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }); + } + + function addMultiplicity(view) { + cy.get('.btn-sv-bar-addmpy').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 100, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }) + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 350, 1400, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 450, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) + + it('Add peak reference', () => { + cy.window().then(win => { + addPeak(win); + + cy.get('.btn-sv-bar-setref').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', 50*index, 1420, { + which: 1, + view: win, + }) + } + }); + }) + + it('Add integration', () => { + cy.window().then(win => { + addIntegration(win); + }); + }) + + it('Remove integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-remove-inter').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Change ref area', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('#intg-factor-name').type('10') + cy.get('#intg-factor-name').clear().type('2') + }); + }) + + it('Set ref integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-set-inter-ref').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all integration', () => { + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + }); + }) + + it('Remove mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-rmmpy').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all multiplicity', () => { + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + }); + }) + + it('Remove peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + + cy.get('.btn-sv-bar-rmpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1485, { + which: 1, + view: win, + }) + } + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/nmr1h_spec.cy.ts b/cypress/e2e/nmr1h_spec.cy.ts new file mode 100644 index 00000000..4c35a634 --- /dev/null +++ b/cypress/e2e/nmr1h_spec.cy.ts @@ -0,0 +1,245 @@ +describe('NMR 1H', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + function addIntegration(view) { + cy.get('.btn-add-inter').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 1200, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }); + } + + function addMultiplicity(view) { + cy.get('.btn-sv-bar-addmpy').click() + cy.get('.d3Svg') + .trigger('mousedown', 500, 1200, { + which: 1, + view: view, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: view, + }) + } + + it('Open layout', () => { + cy.get('button').contains('NMR 1H').click() + cy.get('.btn-sv-bar-spctrum').click() + cy.get('.input-sv-bar-layout').click() + cy.get('.option-sv-bar-layout').should($li => { + expect($li).to.have.length(22) + }) + cy.get('ul li:nth-child(8)').click() + + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (PPM)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (ARBITRARY)') + }) + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 350, 1400, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 450, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) + + it('Add peak reference', () => { + cy.window().then(win => { + addPeak(win); + + cy.get('.btn-sv-bar-setref').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', 50*index, 1420, { + which: 1, + view: win, + }) + } + }); + }) + + it('Add integration', () => { + cy.window().then(win => { + addIntegration(win); + }); + }) + + it('Remove integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-remove-inter').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Change ref area', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('#intg-factor-name').type('10') + cy.get('#intg-factor-name').clear().type('2') + }); + }) + + it('Set ref integration', () => { + cy.window().then(win => { + addIntegration(win); + + cy.get('.btn-set-inter-ref').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all integration', () => { + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.icon-sv-bar-rmallint').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + }); + }) + + it('Remove mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-rmmpy').click() + cy.get('.d3Svg') + .trigger('click', 500, 50, { + which: 1, + view: win, + }) + }); + }) + + it('Clear all multiplicity', () => { + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-no').click() + cy.get('.txt-sv-bar-rmallmpy').click() + cy.get('.btn-sv-bar-yes').click() + }) + + it('Add peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + }); + }) + + it('Remove peak for mulitplicity', () => { + cy.window().then(win => { + addMultiplicity(win); + + cy.get('.btn-sv-bar-addpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1200, { + which: 1, + view: win, + }) + } + + cy.get('.btn-sv-bar-rmpeakmpy').click() + for (let index = 0; index < 5; index++) { + cy.get('.d3Svg') + .trigger('click', 500+(index*10 + 10), 1485, { + which: 1, + view: win, + }) + } + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/raman_spec.cy.ts b/cypress/e2e/raman_spec.cy.ts new file mode 100644 index 00000000..656d6766 --- /dev/null +++ b/cypress/e2e/raman_spec.cy.ts @@ -0,0 +1,74 @@ +describe('Raman', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('button').contains('RAMAN').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (1/CM)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (TRANSMITTANCE)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 400, 500, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 1000, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/tga_spec.cy.ts b/cypress/e2e/tga_spec.cy.ts new file mode 100644 index 00000000..0c9b7733 --- /dev/null +++ b/cypress/e2e/tga_spec.cy.ts @@ -0,0 +1,74 @@ +describe('TGA', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('#btn-tga').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (SECONDS)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (ARBITRARY UNITS)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 170, { + which: 1, + view: view, + }) + } + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 800, 500, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 1000, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) +}) \ No newline at end of file diff --git a/cypress/e2e/uvvis_spec.cy.ts b/cypress/e2e/uvvis_spec.cy.ts new file mode 100644 index 00000000..b7c935e8 --- /dev/null +++ b/cypress/e2e/uvvis_spec.cy.ts @@ -0,0 +1,74 @@ +describe('UV/VIS', () => { + beforeEach(() => { + cy.viewport(2000, 2000) + cy.visit('http://localhost:3000/') + cy.get('#btn-uv-vis').click() + }) + + it('Open layout', () => { + cy.get('.d3Line').children().should('have.class', 'd3Svg') + cy.get('.d3Svg text.xLabel').should('have.text', 'X (MINUTES)') + cy.get('.d3Svg text.yLabel').should('have.text', 'Y (mAU)') + }) + + function addPeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1200, { + which: 1, + view: view, + }) + } + } + + function removePeak(view) { + cy.get('.btn-sv-bar-addpeak').click() + const basePointX = 50; + cy.get('.btn-sv-bar-rmpeak').click() + for (let index = 0; index < 10; index++) { + cy.get('.d3Svg') + .trigger('click', basePointX*index, 1420, { + which: 1, + view: view, + }) + } + } + + it('Zoom in and zoom out on peaks', () => { + cy.window().then(win => { + cy.get('.d3Svg') + .trigger('mousedown', 400, 500, { + which: 1, + view: win, + }) + .trigger('mousemove', { + clientX: 800, + clientY: 1500, + force: true, + }) + .trigger('mouseup', { + force: true, + view: win, + }); + + cy.wait(1000) + cy.get('.btn-sv-bar-zoomreset').click() + }); + }) + + it('Add peak', () => { + cy.window().then(win => { + addPeak(win); + }); + }) + + it('Remove peak', () => { + cy.window().then(win => { + addPeak(win); + + removePeak(win); + }); + }) +}) \ No newline at end of file diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 00000000..02e42543 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 00000000..698b01a4 --- /dev/null +++ b/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 00000000..f80f74f8 --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/dist/actions/detector.js b/dist/actions/detector.js new file mode 100644 index 00000000..4736ec21 --- /dev/null +++ b/dist/actions/detector.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.updateDetector = void 0; +var _action_type = require("../constants/action_type"); +/* eslint-disable import/prefer-default-export */ + +const updateDetector = payload => ({ + type: _action_type.SEC.UPDATE_DETECTOR, + payload +}); +exports.updateDetector = updateDetector; \ No newline at end of file diff --git a/dist/actions/manager.js b/dist/actions/manager.js index 9efc4763..0033d319 100644 --- a/dist/actions/manager.js +++ b/dist/actions/manager.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.resetInitNmr = exports.resetInitMs = exports.resetInitCommonWithIntergation = exports.resetInitCommon = exports.resetAll = void 0; +exports.resetInitNmr = exports.resetInitMs = exports.resetInitCommonWithIntergation = exports.resetInitCommon = exports.resetDetector = exports.resetAll = void 0; var _action_type = require("../constants/action_type"); const resetAll = payload => ({ type: _action_type.MANAGER.RESETALL, @@ -29,6 +29,10 @@ const resetInitCommonWithIntergation = payload => ({ type: _action_type.MANAGER.RESET_INIT_COMMON_WITH_INTERGATION, payload }); +exports.resetInitCommonWithIntergation = resetInitCommonWithIntergation; +const resetDetector = () => ({ + type: _action_type.MANAGER.RESET_DETECTOR +}); // eslint-disable-line -exports.resetInitCommonWithIntergation = resetInitCommonWithIntergation; \ No newline at end of file +exports.resetDetector = resetDetector; \ No newline at end of file diff --git a/dist/components/cmd_bar/04_integration.js b/dist/components/cmd_bar/04_integration.js index cffbb7cd..35a446cb 100644 --- a/dist/components/cmd_bar/04_integration.js +++ b/dist/components/cmd_bar/04_integration.js @@ -104,7 +104,7 @@ const Integration = _ref => { className: "txt-sv-tp" }, "Add Integration") }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_common.MuButton, { - className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddIntgSt, classes)), + className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddIntgSt, classes), 'btn-add-inter'), disabled: isDisableSt, onClick: onSweepIntegtAdd }, /*#__PURE__*/_react.default.createElement(_react2.default, { @@ -119,7 +119,7 @@ const Integration = _ref => { className: "txt-sv-tp" }, "Remove Integration") }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_common.MuButton, { - className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmIntgSt, classes)), + className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmIntgSt, classes), 'btn-remove-inter'), disabled: isDisableSt, onClick: onSweepIntegtRm }, /*#__PURE__*/_react.default.createElement(_react2.default, { @@ -134,7 +134,7 @@ const Integration = _ref => { className: "txt-sv-tp" }, "Set Integration Reference") }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_common.MuButton, { - className: (0, _classnames.default)((0, _common.focusStyle)(isFocusSetRefSt, classes)), + className: (0, _classnames.default)((0, _common.focusStyle)(isFocusSetRefSt, classes), 'btn-set-inter-ref'), disabled: isDisableSt, onClick: onSweepIntegtSR }, /*#__PURE__*/_react.default.createElement(_react2.default, { diff --git a/dist/components/cmd_bar/07_pecker.js b/dist/components/cmd_bar/07_pecker.js index 4731ebb3..45c5cf5b 100644 --- a/dist/components/cmd_bar/07_pecker.js +++ b/dist/components/cmd_bar/07_pecker.js @@ -102,7 +102,7 @@ const Pecker = _ref => { className: "txt-sv-tp" }, "Add Pecker") }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_common.MuButton, { - className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddPeckerSt, classes), 'btn-sv-bar-addpeak'), + className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddPeckerSt, classes), 'btn-sv-bar-addpecker'), onClick: onSweepPeckerAdd }, /*#__PURE__*/_react.default.createElement("span", { className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-addpeak') @@ -111,7 +111,7 @@ const Pecker = _ref => { className: "txt-sv-tp" }, "Remove Pecker") }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_common.MuButton, { - className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmPeckerSt, classes), 'btn-sv-bar-rmpeak'), + className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmPeckerSt, classes), 'btn-sv-bar-rmpecker'), onClick: onSweepPeckerDELETE }, /*#__PURE__*/_react.default.createElement("span", { className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmpeak') diff --git a/dist/components/cmd_bar/index.js b/dist/components/cmd_bar/index.js index b4a8bb61..4d949587 100644 --- a/dist/components/cmd_bar/index.js +++ b/dist/components/cmd_bar/index.js @@ -23,6 +23,7 @@ var _r04_submit = _interopRequireDefault(require("./r04_submit")); var _r07_wavelength_btn = _interopRequireDefault(require("./r07_wavelength_btn")); var _pecker = _interopRequireDefault(require("./07_pecker")); var _r08_change_axes = _interopRequireDefault(require("./r08_change_axes")); +var _r09_detector = _interopRequireDefault(require("./r09_detector")); /* eslint-disable prefer-object-spread, function-paren-newline, react/function-component-definition, react/require-default-props */ @@ -59,7 +60,7 @@ const CmdBar = _ref => { }), /*#__PURE__*/_react.default.createElement(_r01_layout.default, { feature: feature, hasEdit: hasEdit - }), /*#__PURE__*/_react.default.createElement(_r07_wavelength_btn.default, null), /*#__PURE__*/_react.default.createElement(_r08_change_axes.default, null)); + }), /*#__PURE__*/_react.default.createElement(_r07_wavelength_btn.default, null), /*#__PURE__*/_react.default.createElement(_r08_change_axes.default, null), /*#__PURE__*/_react.default.createElement(_r09_detector.default, null)); }; const mapStateToProps = (state, _) => ( // eslint-disable-line diff --git a/dist/components/cmd_bar/r05_submit_btn.js b/dist/components/cmd_bar/r05_submit_btn.js index e39c24ef..734ff0dd 100644 --- a/dist/components/cmd_bar/r05_submit_btn.js +++ b/dist/components/cmd_bar/r05_submit_btn.js @@ -21,7 +21,7 @@ react/function-component-definition, function-call-argument-newline, react/require-default-props */ const styles = () => Object.assign({}, _common.commonStyle); -const onClickCb = (operation, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt) => () => { +const onClickCb = (operation, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt) => () => { operation({ peaks: peaksEdit, layout: layoutSt, @@ -39,7 +39,8 @@ const onClickCb = (operation, peaksEdit, isAscend, isIntensity, scan, thres, lay waveLength: waveLengthSt, cyclicvoltaSt, curveSt, - axesUnitsSt + axesUnitsSt, + detectorSt }); }; const BtnSubmit = _ref => { @@ -62,7 +63,8 @@ const BtnSubmit = _ref => { waveLengthSt, cyclicvoltaSt, curveSt, - axesUnitsSt + axesUnitsSt, + detectorSt } = _ref; const peaksEdit = (0, _extractPeaksEdit.extractPeaksEdit)(feature, editPeakSt, thresSt, shiftSt, layoutSt); // const disBtn = peaksEdit.length === 0 || statusSt.btnSubmit || disabled; @@ -77,7 +79,7 @@ const BtnSubmit = _ref => { }, /*#__PURE__*/_react.default.createElement(_common.MuButton, { className: (0, _classnames.default)('btn-sv-bar-submit'), color: "primary", - onClick: onClickCb(operation.value, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt) + onClick: onClickCb(operation.value, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt) }, /*#__PURE__*/_react.default.createElement(_PlayCircleOutline.default, { className: classes.icon }))); @@ -98,7 +100,8 @@ const mapStateToProps = (state, props) => ( waveLengthSt: state.wavelength, cyclicvoltaSt: state.cyclicvolta, curveSt: state.curve, - axesUnitsSt: state.axesUnits + axesUnitsSt: state.axesUnits, + detectorSt: state.detector }); const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({}, dispatch); BtnSubmit.propTypes = { @@ -120,6 +123,7 @@ BtnSubmit.propTypes = { waveLengthSt: _propTypes.default.object.isRequired, cyclicvoltaSt: _propTypes.default.object.isRequired, curveSt: _propTypes.default.object, - axesUnitsSt: _propTypes.default.object.isRequired + axesUnitsSt: _propTypes.default.object.isRequired, + detectorSt: _propTypes.default.object.isRequired }; var _default = exports.default = (0, _redux.compose)((0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps), (0, _styles.withStyles)(styles))(BtnSubmit); \ No newline at end of file diff --git a/dist/components/cmd_bar/r09_detector.js b/dist/components/cmd_bar/r09_detector.js new file mode 100644 index 00000000..28f1a606 --- /dev/null +++ b/dist/components/cmd_bar/r09_detector.js @@ -0,0 +1,99 @@ +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _react = _interopRequireDefault(require("react")); +var _propTypes = _interopRequireDefault(require("prop-types")); +var _reactRedux = require("react-redux"); +var _classnames = _interopRequireDefault(require("classnames")); +var _redux = require("redux"); +var _material = require("@mui/material"); +var _withStyles = _interopRequireDefault(require("@mui/styles/withStyles")); +var _detector = require("../../actions/detector"); +var _format = _interopRequireDefault(require("../../helpers/format")); +var _common = require("./common"); +var _list_detectors = require("../../constants/list_detectors"); +/* eslint-disable prefer-object-spread, react/jsx-one-expression-per-line, +react/function-component-definition */ + +const styles = () => Object.assign({ + fieldShift: { + width: 160 + }, + fieldLayout: { + width: 100 + } +}, _common.commonStyle); +const detectorSelect = (classes, detectorSt, curveSt, layoutSt, updateDetectorAct) => { + if (!_format.default.isSECLayout(layoutSt)) { + return /*#__PURE__*/_react.default.createElement("i", null); + } + const { + curveIdx + } = curveSt; + const { + curves + } = detectorSt; + const getSelectedDetectorForCurve = (_detectorSt, targetCurveIdx) => { + const targetCurve = curves.find(curve => curve.curveIdx === targetCurveIdx); + return targetCurve ? targetCurve.selectedDetector : ''; + }; + const selectedDetector = getSelectedDetectorForCurve(detectorSt, curveIdx); + const onChange = e => updateDetectorAct({ + curveIdx, + selectedDetector: e.target.value + }); + return /*#__PURE__*/_react.default.createElement(_material.FormControl, { + className: (0, _classnames.default)(classes.fieldLayout) + }, /*#__PURE__*/_react.default.createElement(_material.InputLabel, { + id: "select-detector-label", + className: (0, _classnames.default)(classes.selectLabel, 'select-sv-bar-label') + }, "Detector"), /*#__PURE__*/_react.default.createElement(_material.Select, { + labelId: "select-detector-label", + label: "Detector", + value: selectedDetector, + onChange: onChange, + className: (0, _classnames.default)(classes.selectInput, 'input-sv-bar-layout') + }, /*#__PURE__*/_react.default.createElement(_material.MenuItem, { + value: "" + }, /*#__PURE__*/_react.default.createElement("span", { + className: (0, _classnames.default)(classes.txtOpt, 'option-sv-bar-layout') + })), _list_detectors.LIST_DETECTORS.map(item => /*#__PURE__*/_react.default.createElement(_material.MenuItem, { + value: item + }, /*#__PURE__*/_react.default.createElement("span", { + className: (0, _classnames.default)(classes.txtOpt, 'option-sv-bar-layout') + }, item.name))))); +}; +const Detector = _ref => { + let { + classes, + detectorSt, + curveSt, + layoutSt, + updateDetectorAct + } = _ref; + return /*#__PURE__*/_react.default.createElement("span", { + className: classes.groupRight + }, detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct)); +}; +const mapStateToProps = (state, _props) => ( +// eslint-disable-line +{ + detectorSt: state.detector, + curveSt: state.curve, + layoutSt: state.layout +}); +const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({ + updateDetectorAct: _detector.updateDetector +}, dispatch); +Detector.propTypes = { + classes: _propTypes.default.object.isRequired, + layoutSt: _propTypes.default.string.isRequired, + curveSt: _propTypes.default.object.isRequired, + updateDetectorAct: _propTypes.default.func.isRequired, + detectorSt: _propTypes.default.object.isRequired +}; +var _default = exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)((0, _withStyles.default)(styles)(Detector)); \ No newline at end of file diff --git a/dist/components/d3_line/line_focus.js b/dist/components/d3_line/line_focus.js index 5418c251..6ea27844 100644 --- a/dist/components/d3_line/line_focus.js +++ b/dist/components/d3_line/line_focus.js @@ -252,9 +252,9 @@ class LineFocus { this.grid.x.call(this.axisCall.x.tickSize(-this.h, 0, 0)).selectAll('line').attr('stroke', '#ddd').attr('stroke-opacity', 0.6).attr('fill', 'none'); this.grid.y.call(this.axisCall.y.tickSize(-this.w, 0, 0)).selectAll('line').attr('stroke', '#ddd').attr('stroke-opacity', 0.6).attr('fill', 'none'); } - onClickTarget(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickTarget(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPeak = true; this.clickUiTargetAct(data, onPeak); } @@ -291,15 +291,15 @@ class LineFocus { return yt(0); }).y1(d => yt(d.y))(ps); }; - auc.enter().append('path').attr('class', 'auc').attr('fill', 'red').attr('stroke', 'none').attr('fill-opacity', 0.2).attr('stroke-width', 2).merge(auc).attr('d', d => integCurve(d)).attr('id', d => `auc${(0, _focus.itgIdTag)(d)}`).on('mouseover', d => { + auc.enter().append('path').attr('class', 'auc').attr('fill', 'red').attr('stroke', 'none').attr('fill-opacity', 0.2).attr('stroke-width', 2).merge(auc).attr('d', d => integCurve(d)).attr('id', d => `auc${(0, _focus.itgIdTag)(d)}`).on('mouseover', (event, d) => { d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'none'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'red'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill-opacity', 0.2); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } drawPeaks(editPeakSt) { const { @@ -333,28 +333,28 @@ class LineFocus { }]; // const faktor = layoutSt === LIST_LAYOUT.IR ? -1 : 1; const lineSymbol = d3.line().x(d => d.x).y(d => d.y)(linePath); - mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', 'red').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (d, i, n) => { + mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', 'red').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); - }).on('mouseout', (d, i, n) => { + this.tip.show(tipParams, event.target); + }).on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); - }).on('click', d => this.onClickTarget(d)); + this.tip.hide(tipParams, event.target); + }).on('click', (event, d) => this.onClickTarget(event, d)); const ignoreRef = _format.default.isHplcUvVisLayout(this.layout); if (ignoreRef) { const bpTxt = this.tags.bpTxt.selectAll('text').data(dPks); bpTxt.exit().attr('class', 'exit').remove(); - bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', d => this.onClickTarget(d)); + bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', (event, d) => this.onClickTarget(event, d)); } } drawInteg(integationSt) { @@ -401,15 +401,15 @@ class LineFocus { } = (0, _compass.TfRescale)(this); const dh = 50; const integBar = data => d3.line()([[xt(data.xL - shift), dh], [xt(data.xL - shift), dh - 10], [xt(data.xL - shift), dh - 5], [xt(data.xU - shift), dh - 5], [xt(data.xU - shift), dh - 10], [xt(data.xU - shift), dh]]); - igbp.enter().append('path').attr('class', 'igbp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igbp).attr('id', d => `igbp${(0, _focus.itgIdTag)(d)}`).attr('d', d => integBar(d)).on('mouseover', d => { + igbp.enter().append('path').attr('class', 'igbp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igbp).attr('id', d => `igbp${(0, _focus.itgIdTag)(d)}`).attr('d', d => integBar(d)).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); const integCurve = border => { const { xL, @@ -425,24 +425,24 @@ class LineFocus { } return d3.line().x(d => xt(d.x)).y(d => 300 - (d.k - kRef) * 400 / kMax)(ps); }; - igcp.enter().append('path').attr('class', 'igcp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igcp).attr('id', d => `igbc${(0, _focus.itgIdTag)(d)}`).attr('d', d => integCurve(d)).on('mouseover', d => { + igcp.enter().append('path').attr('class', 'igcp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igcp).attr('id', d => `igbc${(0, _focus.itgIdTag)(d)}`).attr('d', d => integCurve(d)).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); - igtp.enter().append('text').attr('class', 'igtp').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(igtp).attr('id', d => `igtp${(0, _focus.itgIdTag)(d)}`).text(d => (0, _integration.calcArea)(d, refArea, refFactor, ignoreRef)).attr('transform', d => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + igtp.enter().append('text').attr('class', 'igtp').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(igtp).attr('id', d => `igtp${(0, _focus.itgIdTag)(d)}`).text(d => (0, _integration.calcArea)(d, refArea, refFactor, ignoreRef)).attr('transform', d => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } } drawMtply(mtplySt) { @@ -497,42 +497,42 @@ class LineFocus { } = d.xExtent; return smExtext.xL === xL && smExtext.xU === xU ? 'purple' : '#DA70D6'; }; - mpyb.enter().append('path').attr('class', 'mpyb').attr('fill', 'none').attr('stroke-width', 2).merge(mpyb).attr('stroke', d => mpyColor(d)).attr('id', d => `mpyb${(0, _focus.mpyIdTag)(d)}`).attr('d', d => mpyBar(d)).on('mouseover', d => { + mpyb.enter().append('path').attr('class', 'mpyb').attr('fill', 'none').attr('stroke-width', 2).merge(mpyb).attr('stroke', d => mpyColor(d)).attr('id', d => `mpyb${(0, _focus.mpyIdTag)(d)}`).attr('d', d => mpyBar(d)).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); - mpyt1.enter().append('text').attr('class', 'mpyt1').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt1).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt1${(0, _focus.mpyIdTag)(d)}`).text(d => `${(0, _multiplicity_calc.calcMpyCenter)(d.peaks, shift, d.mpyType).toFixed(3)}`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + mpyt1.enter().append('text').attr('class', 'mpyt1').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt1).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt1${(0, _focus.mpyIdTag)(d)}`).text(d => `${(0, _multiplicity_calc.calcMpyCenter)(d.peaks, shift, d.mpyType).toFixed(3)}`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); - mpyt2.enter().append('text').attr('class', 'mpyt2').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt2).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt2${(0, _focus.mpyIdTag)(d)}`).text(d => `(${d.mpyType})`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + mpyt2.enter().append('text').attr('class', 'mpyt2').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt2).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt2${(0, _focus.mpyIdTag)(d)}`).text(d => `(${d.mpyType})`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); const mpypH = height - dh; const mpypPath = pk => [{ x: xt(pk.x - shift) - 0.5, @@ -549,18 +549,18 @@ class LineFocus { }]; // const faktor = layoutSt === LIST_LAYOUT.IR ? -1 : 1; const lineSymbol = d3.line().x(d => d.x).y(d => d.y); - mpyp.enter().append('path').attr('class', 'mpyp').attr('fill', 'none').merge(mpyp).attr('stroke', d => mpyColor(d)).attr('d', d => lineSymbol(mpypPath(d))).attr('id', d => `mpyp${(0, _focus.mpyIdTag)(d)}`).on('mouseover', d => { + mpyp.enter().append('path').attr('class', 'mpyp').attr('fill', 'none').merge(mpyp).attr('stroke', d => mpyColor(d)).attr('d', d => lineSymbol(mpypPath(d))).attr('id', d => `mpyp${(0, _focus.mpyIdTag)(d)}`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } drawRef() { // rescale for zoom diff --git a/dist/components/d3_multi/multi_focus.js b/dist/components/d3_multi/multi_focus.js index 73d70fea..0b2dc193 100644 --- a/dist/components/d3_multi/multi_focus.js +++ b/dist/components/d3_multi/multi_focus.js @@ -284,9 +284,9 @@ class MultiFocus { this.grid.x.call(this.axisCall.x.tickSize(-this.h, 0, 0)).selectAll('line').attr('stroke', '#ddd').attr('stroke-opacity', 0.6).attr('fill', 'none'); this.grid.y.call(this.axisCall.y.tickSize(-this.w, 0, 0)).selectAll('line').attr('stroke', '#ddd').attr('stroke-opacity', 0.6).attr('fill', 'none'); } - onClickTarget(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickTarget(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPeak = true; if (this.layout === _list_layout.LIST_LAYOUT.CYCLIC_VOLTAMMETRY) { const { @@ -299,9 +299,9 @@ class MultiFocus { this.clickUiTargetAct(data, onPeak, false, this.jcampIdx); } } - onClickPecker(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickPecker(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPecker = true; const { spectraList @@ -365,15 +365,15 @@ class MultiFocus { return yt(0); }).y1(d => yt(d.y))(ps); }; - auc.enter().append('path').attr('class', 'auc').attr('fill', 'red').attr('stroke', 'none').attr('fill-opacity', 0.2).attr('stroke-width', 2).merge(auc).attr('d', d => integCurve(d)).attr('id', d => `auc${(0, _focus.itgIdTag)(d)}`).on('mouseover', d => { + auc.enter().append('path').attr('class', 'auc').attr('fill', 'red').attr('stroke', 'none').attr('fill-opacity', 0.2).attr('stroke-width', 2).merge(auc).attr('d', d => integCurve(d)).attr('id', d => `auc${(0, _focus.itgIdTag)(d)}`).on('mouseover', (event, d) => { d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'none'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'red'); d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill-opacity', 0.2); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } drawPeaks(editPeakSt) { const { @@ -406,28 +406,28 @@ class MultiFocus { y: 10 }]; const lineSymbol = d3.line().x(d => d.x).y(d => d.y)(linePath); - mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', 'red').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (d, i, n) => { + mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', 'red').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); - }).on('mouseout', (d, i, n) => { + this.tip.show(tipParams, event.target); + }).on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); - }).on('click', d => this.onClickTarget(d)); + this.tip.hide(tipParams, event.target); + }).on('click', (event, d) => this.onClickTarget(event, d)); const ignoreRef = _format.default.isHplcUvVisLayout(this.layout); if (ignoreRef) { const bpTxt = this.tags.bpTxt.selectAll('text').data(dPks); bpTxt.exit().attr('class', 'exit').remove(); - bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', d => this.onClickTarget(d)); + bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', (event, d) => this.onClickTarget(event, d)); } } drawPeckers() { @@ -461,23 +461,23 @@ class MultiFocus { y: 10 }]; const lineSymbol = d3.line().x(d => d.x).y(d => d.y)(linePath); - mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', '#228B22').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (d, i, n) => { + mpp.enter().append('path').attr('d', lineSymbol).attr('class', 'enter-peak').attr('fill', '#228B22').attr('stroke', 'pink').attr('stroke-width', 3).attr('stroke-opacity', 0.0).merge(mpp).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); - }).on('mouseout', (d, i, n) => { + this.tip.show(tipParams, event.target); + }).on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', '#228B22'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); - }).on('click', d => this.onClickPecker(d)); + this.tip.hide(tipParams, event.target); + }).on('click', (event, d) => this.onClickPecker(event, d)); } drawInteg(integationSt) { const { @@ -532,15 +532,15 @@ class MultiFocus { } = (0, _compass.TfRescale)(this); const dh = 50; const integBar = data => d3.line()([[xt(data.xL - shift), dh], [xt(data.xL - shift), dh - 10], [xt(data.xL - shift), dh - 5], [xt(data.xU - shift), dh - 5], [xt(data.xU - shift), dh - 10], [xt(data.xU - shift), dh]]); - igbp.enter().append('path').attr('class', 'igbp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igbp).attr('id', d => `igbp${(0, _focus.itgIdTag)(d)}`).attr('d', d => integBar(d)).on('mouseover', d => { + igbp.enter().append('path').attr('class', 'igbp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igbp).attr('id', d => `igbp${(0, _focus.itgIdTag)(d)}`).attr('d', d => integBar(d)).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); const integCurve = border => { const { xL, @@ -556,24 +556,24 @@ class MultiFocus { } return d3.line().x(d => xt(d.x)).y(d => 300 - (d.k - kRef) * 400 / kMax)(ps); }; - igcp.enter().append('path').attr('class', 'igcp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igcp).attr('id', d => `igbc${(0, _focus.itgIdTag)(d)}`).attr('d', d => integCurve(d)).on('mouseover', d => { + igcp.enter().append('path').attr('class', 'igcp').attr('fill', 'none').attr('stroke', '#228B22').attr('stroke-width', 2).merge(igcp).attr('id', d => `igbc${(0, _focus.itgIdTag)(d)}`).attr('d', d => integCurve(d)).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); - igtp.enter().append('text').attr('class', 'igtp').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(igtp).attr('id', d => `igtp${(0, _focus.itgIdTag)(d)}`).text(d => (0, _integration.calcArea)(d, refArea, refFactor, ignoreRef)).attr('transform', d => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + igtp.enter().append('text').attr('class', 'igtp').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(igtp).attr('id', d => `igtp${(0, _focus.itgIdTag)(d)}`).text(d => (0, _integration.calcArea)(d, refArea, refFactor, ignoreRef)).attr('transform', d => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`).on('mouseover', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22'); d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22'); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } } drawMtply(mtplySt) { @@ -649,42 +649,42 @@ class MultiFocus { } = d.xExtent; return smExtext.xL === xL && smExtext.xU === xU ? 'purple' : '#DA70D6'; }; - mpyb.enter().append('path').attr('class', 'mpyb').attr('fill', 'none').attr('stroke-width', 2).merge(mpyb).attr('stroke', d => mpyColor(d)).attr('id', d => `mpyb${(0, _focus.mpyIdTag)(d)}`).attr('d', d => mpyBar(d)).on('mouseover', d => { + mpyb.enter().append('path').attr('class', 'mpyb').attr('fill', 'none').attr('stroke-width', 2).merge(mpyb).attr('stroke', d => mpyColor(d)).attr('id', d => `mpyb${(0, _focus.mpyIdTag)(d)}`).attr('d', d => mpyBar(d)).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); - mpyt1.enter().append('text').attr('class', 'mpyt1').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt1).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt1${(0, _focus.mpyIdTag)(d)}`).text(d => `${(0, _multiplicity_calc.calcMpyCenter)(d.peaks, shift, d.mpyType).toFixed(3)}`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + mpyt1.enter().append('text').attr('class', 'mpyt1').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt1).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt1${(0, _focus.mpyIdTag)(d)}`).text(d => `${(0, _multiplicity_calc.calcMpyCenter)(d.peaks, shift, d.mpyType).toFixed(3)}`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); - mpyt2.enter().append('text').attr('class', 'mpyt2').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt2).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt2${(0, _focus.mpyIdTag)(d)}`).text(d => `(${d.mpyType})`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`).on('mouseover', d => { + }).on('click', (event, d) => this.onClickTarget(event, d)); + mpyt2.enter().append('text').attr('class', 'mpyt2').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').merge(mpyt2).attr('fill', d => mpyColor(d)).attr('id', d => `mpyt2${(0, _focus.mpyIdTag)(d)}`).text(d => `(${d.mpyType})`).attr('transform', d => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); const mpypH = height - dh; const mpypPath = pk => [{ x: xt(pk.x - shift) - 0.5, @@ -701,18 +701,18 @@ class MultiFocus { }]; // const faktor = layoutSt === LIST_LAYOUT.IR ? -1 : 1; const lineSymbol = d3.line().x(d => d.x).y(d => d.y); - mpyp.enter().append('path').attr('class', 'mpyp').attr('fill', 'none').merge(mpyp).attr('stroke', d => mpyColor(d)).attr('d', d => lineSymbol(mpypPath(d))).attr('id', d => `mpyp${(0, _focus.mpyIdTag)(d)}`).on('mouseover', d => { + mpyp.enter().append('path').attr('class', 'mpyp').attr('fill', 'none').merge(mpyp).attr('stroke', d => mpyColor(d)).attr('d', d => lineSymbol(mpypPath(d))).attr('id', d => `mpyp${(0, _focus.mpyIdTag)(d)}`).on('mouseover', (event, d) => { d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', 'blue'); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', 'blue'); - }).on('mouseout', d => { + }).on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); d3.selectAll(`#mpyt1${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyt2${(0, _focus.mpyIdTag)(d)}`).style('fill', dColor); d3.selectAll(`#mpyp${(0, _focus.mpyIdTag)(d)}`).attr('stroke', dColor); - }).on('click', d => this.onClickTarget(d)); + }).on('click', (event, d) => this.onClickTarget(event, d)); } drawRef() { // rescale for zoom diff --git a/dist/components/d3_rect/rect_focus.js b/dist/components/d3_rect/rect_focus.js index 222caee6..17960287 100644 --- a/dist/components/d3_rect/rect_focus.js +++ b/dist/components/d3_rect/rect_focus.js @@ -136,22 +136,22 @@ class RectFocus { const bars = this.bars.selectAll('rect').data(this.data); bars.exit().attr('class', 'exit').remove(); const gnd = yt(0); - bars.enter().append('rect').attr('class', 'enter-bar').attr('width', 1.5).merge(bars).attr('fill', d => this.barColor(d.y, yRef)).attr('height', d => this.posHeight(gnd, yt(d.y))).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (d, i, n) => { + bars.enter().append('rect').attr('class', 'enter-bar').attr('width', 1.5).merge(bars).attr('fill', d => this.barColor(d.y, yRef)).attr('height', d => this.posHeight(gnd, yt(d.y))).attr('id', d => `mpp${Math.round(1000 * d.x)}`).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y)})`).on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); - }).on('mouseout', (d, i, n) => { + this.tip.show(tipParams, event.target); + }).on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`).attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`).style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); + this.tip.hide(tipParams, event.target); }); } drawThres() { diff --git a/dist/components/panel/cyclic_voltamery_data.js b/dist/components/panel/cyclic_voltamery_data.js index c6a313a2..6c971706 100644 --- a/dist/components/panel/cyclic_voltamery_data.js +++ b/dist/components/panel/cyclic_voltamery_data.js @@ -171,7 +171,9 @@ const CyclicVoltammetryPanel = _ref => { }), onCheckRefChanged: e => changeCheckRefPeaks(idx, e) })); - return /*#__PURE__*/_react.default.createElement(_material.Accordion, null, /*#__PURE__*/_react.default.createElement(_material.AccordionSummary, { + return /*#__PURE__*/_react.default.createElement(_material.Accordion, { + "data-testid": "PanelVoltammetry" + }, /*#__PURE__*/_react.default.createElement(_material.AccordionSummary, { expandIcon: /*#__PURE__*/_react.default.createElement(_ExpandMore.default, null), className: (0, _classnames.default)(classes.panelSummary) }, /*#__PURE__*/_react.default.createElement(_material.Typography, { diff --git a/dist/components/panel/info.js b/dist/components/panel/info.js index be58e9d4..e3df546d 100644 --- a/dist/components/panel/info.js +++ b/dist/components/panel/info.js @@ -125,7 +125,8 @@ const InfoPanel = _ref => { theoryMass, onExapnd, canChangeDescription, - onDescriptionChanged + onDescriptionChanged, + detectorSt } = _ref; if (!feature) return null; const { @@ -136,6 +137,19 @@ const InfoPanel = _ref => { const { curveIdx } = curveSt; + const { + curves + } = detectorSt; + const getSelectedDetectorForCurve = (_detectorSt, targetCurveIdx) => { + const targetCurve = curves.find(curve => curve.curveIdx === targetCurveIdx); + return targetCurve ? targetCurve.selectedDetector.name : ''; + }; + let selectedDetector = getSelectedDetectorForCurve(detectorSt, curveIdx); + + // default detector from jcamp + if (!selectedDetector && feature.detector) { + selectedDetector = feature.detector; + } const { shifts } = shiftSt; @@ -190,7 +204,13 @@ const InfoPanel = _ref => { className: (0, _classnames.default)(classes.tTxt, classes.tHead, 'txt-sv-panel-txt') }, "Theoretical mass: "), /*#__PURE__*/_react.default.createElement("span", { className: (0, _classnames.default)(classes.tTxt, 'txt-sv-panel-txt') - }, `${parseFloat(theoryMass).toFixed(6)} g/mol`)) : null, !molSvg ? null : /*#__PURE__*/_react.default.createElement(_reactSvgFileZoomPan.default, { + }, `${parseFloat(theoryMass).toFixed(6)} g/mol`)) : null, _format.default.isSECLayout(layoutSt) ? /*#__PURE__*/_react.default.createElement("div", { + className: (0, _classnames.default)(classes.rowRoot, classes.rowOdd) + }, /*#__PURE__*/_react.default.createElement("span", { + className: (0, _classnames.default)(classes.tTxt, classes.tHead, 'txt-sv-panel-txt') + }, "Detector: "), /*#__PURE__*/_react.default.createElement("span", { + className: (0, _classnames.default)(classes.tTxt, 'txt-sv-panel-txt') + }, selectedDetector)) : null, !molSvg ? null : /*#__PURE__*/_react.default.createElement(_reactSvgFileZoomPan.default, { svg: molSvg, duration: 300, resize: true @@ -222,7 +242,8 @@ const mapStateToProps = (state, props) => ( layoutSt: state.layout, simulationSt: state.simulation, shiftSt: state.shift, - curveSt: state.curve + curveSt: state.curve, + detectorSt: state.detector }); const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({}, dispatch); InfoPanel.propTypes = { @@ -240,7 +261,8 @@ InfoPanel.propTypes = { onExapnd: _propTypes.default.func.isRequired, canChangeDescription: _propTypes.default.bool.isRequired, onDescriptionChanged: _propTypes.default.func, - theoryMass: _propTypes.default.string + theoryMass: _propTypes.default.string, + detectorSt: _propTypes.default.object.isRequired }; var _default = exports.default = (0, _reactRedux.connect)( // eslint-disable-line diff --git a/dist/constants/action_type.js b/dist/constants/action_type.js index 7e7194a5..c25d424e 100644 --- a/dist/constants/action_type.js +++ b/dist/constants/action_type.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.XRD = exports.UI = exports.THRESHOLD = exports.SUBMIT = exports.STATUS = exports.SIMULATION = exports.SHIFT = exports.SCAN = exports.MULTIPLICITY = exports.META = exports.MANAGER = exports.LAYOUT = exports.JCAMP = exports.INTEGRATION = exports.FORECAST = exports.EDITPEAK = exports.CYCLIC_VOLTA_METRY = exports.CURVE = exports.AXES = void 0; +exports.XRD = exports.UI = exports.THRESHOLD = exports.SUBMIT = exports.STATUS = exports.SIMULATION = exports.SHIFT = exports.SEC = exports.SCAN = exports.MULTIPLICITY = exports.META = exports.MANAGER = exports.LAYOUT = exports.JCAMP = exports.INTEGRATION = exports.FORECAST = exports.EDITPEAK = exports.CYCLIC_VOLTA_METRY = exports.CURVE = exports.AXES = void 0; const THRESHOLD = exports.THRESHOLD = { UPDATE_VALUE: 'THRESHOLD_UPDATE_VALUE', RESET_VALUE: 'THRESHOLD_RESET_VALUE', @@ -29,7 +29,8 @@ const MANAGER = exports.MANAGER = { RESET_INIT_COMMON: 'RESET_INIT_COMMON', RESET_INIT_NMR: 'RESET_INIT_NMR', RESET_INIT_MS: 'RESET_INIT_MS', - RESET_INIT_COMMON_WITH_INTERGATION: 'RESET_INIT_COMMON_WITH_INTERGATION' + RESET_INIT_COMMON_WITH_INTERGATION: 'RESET_INIT_COMMON_WITH_INTERGATION', + RESET_DETECTOR: 'RESET_DETECTOR' }; const LAYOUT = exports.LAYOUT = { UPDATE: 'UPDATE_LAYOUT' @@ -139,4 +140,7 @@ const CURVE = exports.CURVE = { const AXES = exports.AXES = { UPDATE_X_AXIS: 'UPDATE_X_AXIS', UPDATE_Y_AXIS: 'UPDATE_Y_AXIS' +}; +const SEC = exports.SEC = { + UPDATE_DETECTOR: 'UPDATE_DETECTOR' }; \ No newline at end of file diff --git a/dist/constants/list_detectors.js b/dist/constants/list_detectors.js new file mode 100644 index 00000000..fcbda7ec --- /dev/null +++ b/dist/constants/list_detectors.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LIST_DETECTORS = void 0; +const rI = { + name: 'Refractive index', + label: 'RI' +}; +const uV = { + name: 'Ultraviolet', + label: 'UV' +}; +const LIST_DETECTORS = exports.LIST_DETECTORS = [rI, uV]; \ No newline at end of file diff --git a/dist/helpers/brush.js b/dist/helpers/brush.js index 35fcac91..8d85bd84 100644 --- a/dist/helpers/brush.js +++ b/dist/helpers/brush.js @@ -10,19 +10,19 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /* eslint-disable prefer-object-spread */ -const wheeled = focus => { +const wheeled = (focus, event) => { const { currentExtent, scrollUiWheelAct } = focus; // WORKAROUND: firefox wheel compatibilty - const wheelEvent = focus.isFirefox ? -d3.event.deltaY : d3.event.wheelDelta; // eslint-disable-line + const wheelEvent = focus.isFirefox ? -event.deltaY : event.wheelDelta; // eslint-disable-line const direction = wheelEvent > 0; scrollUiWheelAct(Object.assign({}, currentExtent, { direction })); }; -const brushed = (focus, isUiAddIntgSt) => { +const brushed = (focus, isUiAddIntgSt, event) => { const { selectUiSweepAct, data, @@ -32,7 +32,7 @@ const brushed = (focus, isUiAddIntgSt) => { h, scales } = focus; - const selection = d3.event.selection && d3.event.selection.reverse(); + const selection = event.selection && event.selection.reverse(); if (!selection) return; let xes = [w, 0].map(scales.x.invert).sort((a, b) => a - b); let yes = [h, 0].map(scales.y.invert).sort((a, b) => a - b); @@ -82,15 +82,15 @@ const MountBrush = (focus, isUiAddIntgSt, isUiNoBrushSt) => { } = focus; svg.selectAll('.brush').remove(); svg.selectAll('.brushX').remove(); - const brushedCb = () => brushed(focus, isUiAddIntgSt); - const wheeledCb = () => wheeled(focus); + const brushedCb = event => brushed(focus, isUiAddIntgSt, event); + const wheeledCb = event => wheeled(focus, event); if (isUiNoBrushSt) { const target = isUiAddIntgSt ? brushX : brush; target.handleSize(10).extent([[0, 0], [w, h]]).on('end', brushedCb); // append brush components const klass = isUiAddIntgSt ? 'brushX' : 'brush'; - root.append('g').attr('class', klass).on('mousemove', () => (0, _compass.MouseMove)(focus)).call(target); + root.append('g').attr('class', klass).on('mousemove', event => (0, _compass.MouseMove)(event, focus)).call(target); } svg.on('wheel', wheeledCb); }; diff --git a/dist/helpers/chem.js b/dist/helpers/chem.js index 6935bbd1..8628e448 100644 --- a/dist/helpers/chem.js +++ b/dist/helpers/chem.js @@ -773,7 +773,10 @@ const extrFeaturesCylicVolta = (jcamp, layout, peakUp) => { const lowerThres = _format.default.isXRDLayout(layout) ? 100 : calcLowerThres(s); const cpo = buildPeakFeature(jcamp, layout, peakUp, s, 100, upperThres, lowerThres); const bnd = getBoundary(s); - return Object.assign({}, base, cpo, bnd); + const detector = _format.default.isSECLayout(layout) && jcamp.info.$DETECTOR ? jcamp.info.$DETECTOR : ''; + return Object.assign({}, base, cpo, bnd, { + detector + }); }).filter(r => r != null); return features; }; @@ -819,7 +822,7 @@ const extractTemperature = jcamp => { const ExtractJcamp = source => { const jcamp = _jcampconverter.default.convert(source, { xy: true, - keepRecordsRegExp: /(\$CSTHRESHOLD|\$CSSCANAUTOTARGET|\$CSSCANEDITTARGET|\$CSSCANCOUNT|\$CSSOLVENTNAME|\$CSSOLVENTVALUE|\$CSSOLVENTX|\$CSCATEGORY|\$CSITAREA|\$CSITFACTOR|\$OBSERVEDINTEGRALS|\$OBSERVEDMULTIPLETS|\$OBSERVEDMULTIPLETSPEAKS|\.SOLVENTNAME|\.OBSERVEFREQUENCY|\$CSSIMULATIONPEAKS|\$CSUPPERTHRESHOLD|\$CSLOWERTHRESHOLD|\$CSCYCLICVOLTAMMETRYDATA|UNITS|SYMBOL|CSAUTOMETADATA)/ // eslint-disable-line + keepRecordsRegExp: /(\$CSTHRESHOLD|\$CSSCANAUTOTARGET|\$CSSCANEDITTARGET|\$CSSCANCOUNT|\$CSSOLVENTNAME|\$CSSOLVENTVALUE|\$CSSOLVENTX|\$CSCATEGORY|\$CSITAREA|\$CSITFACTOR|\$OBSERVEDINTEGRALS|\$OBSERVEDMULTIPLETS|\$OBSERVEDMULTIPLETSPEAKS|\.SOLVENTNAME|\.OBSERVEFREQUENCY|\$CSSIMULATIONPEAKS|\$CSUPPERTHRESHOLD|\$CSLOWERTHRESHOLD|\$CSCYCLICVOLTAMMETRYDATA|UNITS|SYMBOL|CSAUTOMETADATA|\$DETECTOR)/ // eslint-disable-line }); const layout = readLayout(jcamp); const peakUp = !_format.default.isIrLayout(layout); diff --git a/dist/helpers/compass.js b/dist/helpers/compass.js index 183b0254..8d01e4a9 100644 --- a/dist/helpers/compass.js +++ b/dist/helpers/compass.js @@ -19,11 +19,11 @@ const TfRescale = focus => { }; }; exports.TfRescale = TfRescale; -const fetchPt = (focus, xt) => { +const fetchPt = (event, focus, xt) => { // const rawMouseX = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetX // : d3.mouse(focus.root.node())[0]; - const rawMouseX = d3.mouse(focus.root.node())[0]; + const rawMouseX = d3.pointer(event, focus.root.node())[0]; const mouseX = xt.invert(rawMouseX); const bisectDate = d3.bisector(d => +d.x).left; const dt = focus.data; @@ -32,15 +32,15 @@ const fetchPt = (focus, xt) => { const idx = bisectDate(sortData, +mouseX); return sortData[idx]; }; -const fetchFreePt = (focus, xt, yt) => { +const fetchFreePt = (event, focus, xt, yt) => { // const rawMouseX = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetX // : d3.mouse(focus.root.node())[0]; // const rawMouseY = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetY // : d3.mouse(focus.root.node())[1]; - const rawMouseX = d3.mouse(focus.root.node())[0]; - const rawMouseY = d3.mouse(focus.root.node())[1]; + const rawMouseX = d3.pointer(event, focus.root.node())[0]; + const rawMouseY = d3.pointer(event, focus.root.node())[1]; const mouseX = xt.invert(rawMouseX); const mouseY = yt.invert(rawMouseY); const distance2 = (x1, x2, y1, y2) => { @@ -60,7 +60,7 @@ const fetchFreePt = (focus, xt, yt) => { }); return selectPoint; }; -const MouseMove = focus => { +const MouseMove = (event, focus) => { const { xt, yt @@ -71,7 +71,7 @@ const MouseMove = focus => { wavelength } = focus; if (_format.default.isCyclicVoltaLayout(layout)) { - const pt = fetchFreePt(focus, xt, yt); + const pt = fetchFreePt(event, focus, xt, yt); if (pt) { const tx = xt(pt.x); const ty = yt(pt.y); @@ -85,7 +85,7 @@ const MouseMove = focus => { } } } else { - const pt = fetchPt(focus, xt); + const pt = fetchPt(event, focus, xt); if (pt) { const tx = xt(pt.x); const ty = yt(pt.y); @@ -99,6 +99,8 @@ const MouseMove = focus => { dValue = (0, _chem.Convert2DValue)(pt.x).toExponential(2); } focus.root.select('.cursor-txt-hz').attr('transform', `translate(${tx},${ty - 30})`).text(`2Theta: ${pt.x.toExponential(2)}, d-value: ${dValue}`); + } else if (_format.default.isTGALayout(layout)) { + focus.root.select('.cursor-txt').attr('transform', `translate(${tx},${10})`).text(`X: ${pt.x.toFixed(3)}, Y: ${pt.y.toFixed(3)}`); } else { focus.root.select('.cursor-txt').attr('transform', `translate(${tx},${10})`).text(pt.x.toFixed(3)); if (freq) { @@ -111,21 +113,21 @@ const MouseMove = focus => { } }; exports.MouseMove = MouseMove; -const ClickCompass = focus => { - d3.event.stopPropagation(); - d3.event.preventDefault(); +const ClickCompass = (event, focus) => { + event.stopPropagation(); + event.preventDefault(); const { xt, yt } = TfRescale(focus); - let pt = fetchPt(focus, xt); + let pt = fetchPt(event, focus, xt); const { layout, cyclicvoltaSt, jcampIdx } = focus; if (_format.default.isCyclicVoltaLayout(layout)) { - pt = fetchFreePt(focus, xt, yt); + pt = fetchFreePt(event, focus, xt, yt); const onPeak = false; if (cyclicvoltaSt) { const { @@ -155,6 +157,6 @@ const MountCompass = focus => { compass.append('circle').attr('r', 4).attr('fill', 'none').attr('stroke', '#777').attr('stroke-width', 2); cursor.append('text').attr('class', 'cursor-txt').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle'); cursor.append('text').attr('class', 'cursor-txt-hz').attr('font-family', 'Helvetica').style('font-size', '12px').style('text-anchor', 'middle').style('fill', '#D68910'); - overlay.on('mousemove', () => MouseMove(focus)).on('click', () => ClickCompass(focus)); + overlay.on('mousemove', event => MouseMove(event, focus)).on('click', event => ClickCompass(event, focus)); }; exports.MountCompass = MountCompass; \ No newline at end of file diff --git a/dist/helpers/mount.js b/dist/helpers/mount.js index 9f46d783..8b66300a 100644 --- a/dist/helpers/mount.js +++ b/dist/helpers/mount.js @@ -45,13 +45,13 @@ const MountRef = target => { }; exports.MountRef = MountRef; const MountPath = (target, color) => { - const path = target.root.append('g').attr('class', 'line-clip').attr('clip-path', 'url(#clip)').append('path').attr('class', 'line').style('fill', 'none').style('stroke', color).style('stroke-width', 1).on('click', () => (0, _compass.ClickCompass)(target)); + const path = target.root.append('g').attr('class', 'line-clip').attr('clip-path', 'url(#clip)').append('path').attr('class', 'line').style('fill', 'none').style('stroke', color).style('stroke-width', 1).on('click', event => (0, _compass.ClickCompass)(event, target)); return path; }; exports.MountPath = MountPath; const MountComparePath = function (target, color, id) { let alpha = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; - const path = target.root.append('g').attr('class', 'line-clip-compare').attr('id', id).attr('clip-path', 'url(#clip)').append('path').attr('class', 'line').style('fill', 'none').style('stroke', color).style('stroke-opacity', alpha).style('stroke-width', 1).style('stroke-dasharray', '30, 3').on('click', () => (0, _compass.ClickCompass)(target)); + const path = target.root.append('g').attr('class', 'line-clip-compare').attr('id', id).attr('clip-path', 'url(#clip)').append('path').attr('class', 'line').style('fill', 'none').style('stroke', color).style('stroke-opacity', alpha).style('stroke-width', 1).style('stroke-dasharray', '30, 3').on('click', event => (0, _compass.ClickCompass)(event, target)); return path; }; exports.MountComparePath = MountComparePath; diff --git a/dist/helpers/zoom.js b/dist/helpers/zoom.js index db7b105b..17e5315a 100644 --- a/dist/helpers/zoom.js +++ b/dist/helpers/zoom.js @@ -12,10 +12,10 @@ const resetZoom = main => { main.svg.selectAll('.brush').call(main.brush.move, null); }; const MountZoom = (main, zoomed) => { - const zoomedCb = () => zoomed(main); - const resetZoomCb = () => { - d3.event.stopPropagation(); - d3.event.preventDefault(); + const zoomedCb = event => zoomed(event, main); + const resetZoomCb = event => { + event.stopPropagation(); + event.preventDefault(); resetZoom(main); }; main.zoom.on('zoom', zoomedCb); diff --git a/dist/index.js b/dist/index.js index 7682cf64..d6921f75 100644 --- a/dist/index.js +++ b/dist/index.js @@ -604,30 +604,35 @@ class DemoWriteIr extends _react.default.Component { }, onClick: this.onClick('raman') }, "RAMAN"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-uv-vis", variant: "contained", style: { margin: '0 10px 0 10px' }, onClick: this.onClick('uv/vis') }, "UV/VIS"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-hplc", variant: "contained", style: { margin: '0 10px 0 10px' }, onClick: this.onClick('hplc uv/vis') }, "HPLC UV/VIS"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-tga", variant: "contained", style: { margin: '0 10px 0 10px' }, onClick: this.onClick('tga') }, "TGA"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-xrd", variant: "contained", style: { margin: '0 10px 0 10px' }, onClick: this.onClick('xrd') }, "XRD"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-cv", variant: "contained", style: { margin: '0 10px 0 10px' @@ -640,12 +645,14 @@ class DemoWriteIr extends _react.default.Component { }, onClick: this.onClick('cds') }, "CDS"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-sec", variant: "contained", style: { margin: '0 10px 0 10px' }, onClick: this.onClick('sec') }, "SEC"), /*#__PURE__*/_react.default.createElement(_material.Button, { + id: "btn-sod", variant: "contained", style: { margin: '0 10px 0 10px' diff --git a/dist/layer_init.js b/dist/layer_init.js index 0a5889bc..7875bc6d 100644 --- a/dist/layer_init.js +++ b/dist/layer_init.js @@ -60,9 +60,11 @@ class LayerInit extends _react.default.Component { resetInitCommonAct, resetInitMsAct, resetInitNmrAct, - resetInitCommonWithIntergationAct + resetInitCommonWithIntergationAct, + resetDetectorAct } = this.props; resetInitCommonAct(); + resetDetectorAct(); const { layout, features @@ -185,6 +187,7 @@ const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({ resetInitNmrAct: _manager.resetInitNmr, resetInitMsAct: _manager.resetInitMs, resetInitCommonWithIntergationAct: _manager.resetInitCommonWithIntergation, + resetDetectorAct: _manager.resetDetector, updateOperationAct: _submit.updateOperation, updateMetaPeaksAct: _meta.updateMetaPeaks, addOthersAct: _jcamp.addOthers, @@ -217,7 +220,9 @@ LayerInit.propTypes = { onDescriptionChanged: _propTypes.default.func, // eslint-disable-line setAllCurvesAct: _propTypes.default.func.isRequired, - userManualLink: _propTypes.default.object // eslint-disable-line + userManualLink: _propTypes.default.object, + // eslint-disable-line + resetDetectorAct: _propTypes.default.func.isRequired }; var _default = exports.default = (0, _reactRedux.connect)( // eslint-disable-line diff --git a/dist/reducers/index.js b/dist/reducers/index.js index d3f1b5b1..50868a3b 100644 --- a/dist/reducers/index.js +++ b/dist/reducers/index.js @@ -25,6 +25,7 @@ var _reducer_wavelength = _interopRequireDefault(require("./reducer_wavelength") var _reducer_voltammetry = _interopRequireDefault(require("./reducer_voltammetry")); var _reducer_curve = _interopRequireDefault(require("./reducer_curve")); var _reducer_axes = _interopRequireDefault(require("./reducer_axes")); +var _reducer_detector = _interopRequireDefault(require("./reducer_detector")); const rootReducer = (0, _redux.combineReducers)({ threshold: _reducer_threshold.default, editPeak: _reducer_edit_peak.default, @@ -44,6 +45,7 @@ const rootReducer = (0, _redux.combineReducers)({ wavelength: _reducer_wavelength.default, cyclicvolta: _reducer_voltammetry.default, curve: _reducer_curve.default, - axesUnits: _reducer_axes.default + axesUnits: _reducer_axes.default, + detector: _reducer_detector.default }); var _default = exports.default = rootReducer; \ No newline at end of file diff --git a/dist/reducers/reducer_detector.js b/dist/reducers/reducer_detector.js new file mode 100644 index 00000000..db8e3d56 --- /dev/null +++ b/dist/reducers/reducer_detector.js @@ -0,0 +1,52 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _action_type = require("../constants/action_type"); +/* eslint-disable no-case-declarations */ +/* eslint-disable default-param-last */ + +const initialState = { + curves: [{ + curveIdx: 0, + selectedDetector: '' + }] +}; +const findCurveIndex = (curves, targetCurveIdx) => curves.findIndex(curve => curve.curveIdx === targetCurveIdx); +const updateOrAppendCurve = (curves, targetCurveIdx, newCurve) => { + const existingCurveIndex = findCurveIndex(curves, targetCurveIdx); + if (existingCurveIndex !== -1) { + return curves.map((curve, index) => index === existingCurveIndex ? { + ...curve, + ...newCurve + } : curve); + } + return [...curves, newCurve]; +}; +const detectorReducer = function () { + let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + let action = arguments.length > 1 ? arguments[1] : undefined; + switch (action.type) { + case _action_type.SEC.UPDATE_DETECTOR: + const { + curveIdx, + selectedDetector + } = action.payload; + // eslint-disable-next-line max-len + const updatedCurves = updateOrAppendCurve(state.curves, curveIdx, { + curveIdx, + selectedDetector + }); + return { + ...state, + curves: updatedCurves + }; + case _action_type.MANAGER.RESET_DETECTOR: + return initialState; + default: + return state; + } +}; +var _default = exports.default = detectorReducer; \ No newline at end of file diff --git a/package.json b/package.json index 3c97b5a4..09ac5abd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@complat/react-spectra-editor", - "version": "1.0.1", + "version": "1.1.0", "description": "An editor to View and Edit Chemical Spectra data (NMR, IR and MS, CV, UIVIS, XRD).", "repository": { "type": "git", @@ -23,9 +23,7 @@ "babel-plugin-transform-object-rest-spread": "^6.26.0", "browserslist": "^4.21.5", "classnames": "^2.3.2", - "d3": "^5.16.0", - "d3-brush": "3.0.0", - "d3-selection": "^2.0.0", + "d3": "^7.8.5", "d3-tip": "^0.9.1", "jcampconverter": "4.1.0", "ml-savitzky-golay-generalized": "1.1.1", @@ -48,7 +46,8 @@ "test:coverage": "CI=true react-scripts test --env=jsdom --verbose --testPathIgnorePatterns=./src/__tests__/fixtures/ --coverage", "eject": "react-scripts eject", "storybook": "start-storybook -p 3001 -c .storybook", - "buildbook": "build-storybook -c .storybook -o .out" + "buildbook": "build-storybook -c .storybook -o .out", + "e2e": "cypress open" }, "peerDependencies": { "react": "^17.0.2", @@ -65,6 +64,7 @@ "@types/enzyme": "^3.10.13", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "babel-loader": "8.2.5", + "cypress": "^13.6.2", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", "eslint-config-airbnb": "^19.0.4", @@ -90,5 +90,10 @@ ], "publishConfig": { "access": "public" + }, + "jest": { + "transformIgnorePatterns": [ + "/node_modules/(?!d3|d3-array|internmap|delaunator|robust-predicates)" + ] } } diff --git a/src/__tests__/units/components/cmd_bar/01_viewer.test.js b/src/__tests__/units/components/cmd_bar/01_viewer.test.js index 994f026b..34d30f6c 100644 --- a/src/__tests__/units/components/cmd_bar/01_viewer.test.js +++ b/src/__tests__/units/components/cmd_bar/01_viewer.test.js @@ -26,7 +26,7 @@ describe('', () => { it('Render Viewer', async () => { const renderer = - + ; const { queryByTestId } = render(renderer); @@ -38,7 +38,7 @@ describe('', () => { it('Render Viewer in editor only mode', () => { const renderer = - + ; const { queryByTestId } = render(renderer); diff --git a/src/__tests__/units/components/cmd_bar/02_zoom.test.js b/src/__tests__/units/components/cmd_bar/02_zoom.test.js index b7422aef..ec876374 100644 --- a/src/__tests__/units/components/cmd_bar/02_zoom.test.js +++ b/src/__tests__/units/components/cmd_bar/02_zoom.test.js @@ -24,7 +24,7 @@ describe('', () => { it('Render Zoom', async () => { const renderer = - + ; const { queryByTestId } = render(renderer); diff --git a/src/__tests__/units/components/common/comps.test.jsx b/src/__tests__/units/components/common/comps.test.jsx new file mode 100644 index 00000000..fee7f223 --- /dev/null +++ b/src/__tests__/units/components/common/comps.test.jsx @@ -0,0 +1,24 @@ +import { render } from '@testing-library/react'; +import { TabLabel } from "../../../../components/common/comps"; +import '@testing-library/jest-dom'; + +describe('common/comps', () => { + it('.TabLabel()', () => { + const labelStr = 'test label'; + function TestComponent({}) { + return ( +
+ { + TabLabel({tabLabel: 'mytestclass'}, labelStr) + } +
+ ) + } + + const { queryByTestId, queryByText } = render(); + const renderedComponent = queryByTestId('test-div'); + expect(renderedComponent).toBeInTheDocument(); + const renderedLabel = queryByText(labelStr); + expect(renderedLabel).toHaveClass('mytestclass txt-tab-label'); + }); +}); diff --git a/src/__tests__/units/components/common/draw.test.jsx b/src/__tests__/units/components/common/draw.test.jsx index 9a1a46ac..45350ec2 100644 --- a/src/__tests__/units/components/common/draw.test.jsx +++ b/src/__tests__/units/components/common/draw.test.jsx @@ -1,24 +1,187 @@ import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; -import { drawMain } from '../../../../components/common/draw'; +import { drawArrowOnCurve, drawDestroy, drawDisplay, drawLabel, drawMain } from '../../../../components/common/draw'; import { useEffect } from 'react'; +import * as d3 from 'd3'; + describe('common/draw', () => { - it('.drawMain()', () => { - function TestComponent({}) { - useEffect(() => { - drawMain('.testsvg', 100, 100) - }, []); - return ( -
- ) + describe('.drawMain()', () => { + it('d3 draw main svg view box', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100) + }, []); + return ( +
+ ) + } + + const { queryByTestId } = render(); + const renderResult = queryByTestId('testsvg'); + expect(renderResult).toBeInTheDocument(); + const svgElement = document.querySelector('svg'); + expect(svgElement).toHaveClass('d3Svg'); + expect(svgElement).toHaveAttribute('preserveAspectRatio', 'xMinYMin meet'); + expect(svgElement).toHaveAttribute('viewBox', '0 0 100 100'); + }); + }); + + describe('.drawLabel()', () => { + const rootClass = '.testsvg'; + const xLabelText = 'x label'; + const yLabelText = 'y label'; + const cLabelText = 'c label'; + + function drawMyText(hasMarker = false) { + d3.select(rootClass).append('svg').attr('class', 'd3Svg'); + d3.select('.d3Svg').append('text').attr('class', 'xLabel'); + d3.select('.d3Svg').append('text').attr('class', 'yLabel'); + if (hasMarker) { + d3.select('.d3Svg').append('text').attr('class', 'mark-text'); + } } - const { queryByTestId } = render(); - const renderResult = queryByTestId('testsvg'); - expect(renderResult).toBeInTheDocument(); - const svgElement = document.querySelector('svg'); - expect(svgElement).toHaveClass('d3Svg'); - expect(svgElement).toHaveAttribute('preserveAspectRatio', 'xMinYMin meet'); - expect(svgElement).toHaveAttribute('viewBox', '0 0 100 100'); + it('d3 draw only axes label', () => { + function TestComponent({}) { + useEffect(() => { + drawMyText(false); + drawLabel(rootClass, null, xLabelText, yLabelText); + }, []); + return ( +
+ ) + } + + const { queryByText } = render(); + const xLabel = queryByText(xLabelText); + expect(xLabel).toBeInTheDocument(); + expect(xLabel).toHaveClass('xLabel'); + const yLabel = queryByText(yLabelText); + expect(yLabel).toBeInTheDocument(); + expect(yLabel).toHaveClass('yLabel'); + }); + + it('d3 draw labels witg c label', () => { + function TestComponent({}) { + useEffect(() => { + drawMyText(true); + drawLabel(rootClass, cLabelText, xLabelText, yLabelText); + }, []); + return ( +
+ ) + } + + const { queryByText } = render(); + const xLabel = queryByText(xLabelText); + expect(xLabel).toBeInTheDocument(); + expect(xLabel).toHaveClass('xLabel'); + const yLabel = queryByText(yLabelText); + expect(yLabel).toBeInTheDocument(); + expect(yLabel).toHaveClass('yLabel'); + const cLabel = queryByText(cLabelText); + expect(cLabel).toBeInTheDocument(); + expect(cLabel).toHaveClass('mark-text'); + }); + }); + + describe('.drawDisplay()', () => { + it('set display as hidden', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100); + drawDisplay('.testsvg', true); + }, []); + return ( +
+ ) + } + + render(); + const svgElement = document.querySelector('svg'); + expect(svgElement).toHaveStyle('width: 0'); + }); + + it('set display to show', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100); + drawDisplay('.testsvg', false); + }, []); + return ( +
+ ) + } + + render(); + const svgElement = document.querySelector('svg'); + expect(svgElement).toHaveStyle('width: 100%'); + }); + }); + + describe('.drawDestroy()', () => { + it('d3 remove all svg', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100); + drawDestroy('.testsvg'); + }, []); + return ( +
+ ) + } + + render(); + const svgElement = document.querySelector('svg'); + expect(svgElement).not.toBeInTheDocument(); + }); + }); + + describe('.drawArrowOnCurve()', () => { + it('d3 remove all arrows on curves', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100); + d3.select('.d3Svg').append('defs').append('marker'); + drawArrowOnCurve('.testsvg', true); + }, []); + return ( +
+ ) + } + + render(); + const svgElement = document.querySelector('marker'); + expect(svgElement).not.toBeInTheDocument(); + }); + + it('d3 draw arrows on curves', () => { + function TestComponent({}) { + useEffect(() => { + drawMain('.testsvg', 100, 100); + d3.select('.d3Svg').append('defs').append('marker'); + drawArrowOnCurve('.testsvg', false); + }, []); + return ( +
+ ) + } + + render(); + const arrowLeft = document.querySelector('marker'); + expect(arrowLeft).toBeInTheDocument(); + expect(arrowLeft).toHaveAttribute('id', 'arrow-left'); + expect(arrowLeft).toHaveAttribute('viewBox', '0 0 10 10'); + expect(arrowLeft).toHaveAttribute('refX', '5'); + expect(arrowLeft).toHaveAttribute('refY', '5'); + expect(arrowLeft).toHaveAttribute('markerWidth', '6'); + expect(arrowLeft).toHaveAttribute('markerHeight', '6'); + expect(arrowLeft).toHaveAttribute('orient', 'auto'); + expect(arrowLeft).toHaveAttribute('fill', '#00AA0099'); + + const path = arrowLeft.querySelector('path'); + expect(path).toBeInTheDocument(); + expect(path).toHaveAttribute('d', 'M 0 0 L 10 5 L 0 10 z'); + }); }); -}) +}); diff --git a/src/__tests__/units/components/panel/info.test.js b/src/__tests__/units/components/panel/info.test.js index ef04b493..73a71db3 100644 --- a/src/__tests__/units/components/panel/info.test.js +++ b/src/__tests__/units/components/panel/info.test.js @@ -20,10 +20,18 @@ const store = mockStore({ }, simulation: { - } + }, + detector: { + curves: [ + { + curveIdx: 0, + selectedDetector: { name: 'Refractive index', label: 'RI' }, + }, + ], + }, }); const failedStore = mockStore({ - + }); const dispatchMock = () => Promise.resolve({}); store.dispatch = jest.fn(dispatchMock); diff --git a/src/__tests__/units/helpers/mount.test.tsx b/src/__tests__/units/helpers/mount.test.tsx index 4bc224a8..236831cf 100644 --- a/src/__tests__/units/helpers/mount.test.tsx +++ b/src/__tests__/units/helpers/mount.test.tsx @@ -1,7 +1,113 @@ -import { MountTags } from "../../../helpers/mount"; +import { useEffect } from "react"; +import { MountBars, MountPath, MountRef, MountTags } from "../../../helpers/mount"; +import { render } from "@testing-library/react"; +import { drawMain } from "../../../components/common/draw"; +import * as d3 from 'd3'; +import '@testing-library/jest-dom'; -describe('Test mount function for d3', () => { - it('Just dump test, implement more later', () => { - expect(1).toEqual(1) +describe('helpers/mount', () => { + const enum MountType { TAG, BAR, REF, PATH } + function TestComponent({mountType}) { + useEffect(() => { + drawMain('.testsvg', 100, 100) + const target = d3.select('.d3Svg') + switch(mountType) { + case MountType.TAG: + MountTags({ root: target}) + break + case MountType.BAR: + MountBars({ root: target}) + break + case MountType.REF: + MountRef({ root: target}) + break + case MountType.PATH: + MountPath({ root: target}, '#FFFF00') + break + default: + break + } + }, [mountType]) + return ( +
+ ) + } + + describe('.MountTags()', () => { + function validateRendered(element: any) { + expect(element).toHaveAttribute('clip-path', 'url(#clip)') + } + + beforeEach(() => { + render() + }) + + const arrayPaths = [ + 'pPath', 'bpPath', 'bpTxt', 'igbPath', 'igcPath', 'igtPath', 'mpybPath', 'mpyt1Path', 'mpyt2Path', 'mpypPath', 'aucPath', 'peckerPath' + ] + arrayPaths.forEach((path) => { + const pathName = `.${path}-clip` + it(`check render ${pathName}`, () => { + const svgElement = document.querySelector(pathName) + validateRendered(svgElement) + }); + + }) + }) + + describe('.MountBars()', () => { + function validateRendered(element: any) { + expect(element).toHaveAttribute('clip-path', 'url(#clip)') + } + + beforeEach(() => { + render() + }) + + it('check render bars', () => { + const svgElement = document.querySelector('.bars-clip') + validateRendered(svgElement) + }); + }) + + describe('.MountRef()', () => { + function validateRendered(element: any) { + expect(element).toHaveAttribute('clip-path', 'url(#ref-clip)') + } + + beforeEach(() => { + render() + }) + + it('check render ref', () => { + const svgElement = document.querySelector('.ref-clip') + validateRendered(svgElement) + }); + }) + + describe('.MountPath()', () => { + function validateRendered(element: any, attributes: string[], values: string[]) { + attributes.forEach((attr, idx) => { + expect(element).toHaveAttribute(attr, values[idx]) + }) + } + + function validateStyle(element: any, attributes: string[]) { + attributes.forEach((attr) => { + expect(element).toHaveStyle(attr) + }) + } + + beforeEach(() => { + render() + }) + + it('check render path', () => { + const lineClip = document.querySelector('.line-clip') + validateRendered(lineClip, ['clip-path'], ['url(#clip)']) + const path = lineClip?.querySelector('.line') + validateStyle(path, ['fill: none', 'stroke: #FFFF00', 'stroke-width: 1']) + }); }) + }) \ No newline at end of file diff --git a/src/actions/detector.js b/src/actions/detector.js new file mode 100644 index 00000000..7b9bb971 --- /dev/null +++ b/src/actions/detector.js @@ -0,0 +1,11 @@ +/* eslint-disable import/prefer-default-export */ +import { SEC } from '../constants/action_type'; + +const updateDetector = (payload) => ( + { + type: SEC.UPDATE_DETECTOR, + payload, + } +); + +export { updateDetector }; diff --git a/src/actions/manager.js b/src/actions/manager.js index a61f1db9..54d12d46 100644 --- a/src/actions/manager.js +++ b/src/actions/manager.js @@ -35,6 +35,15 @@ const resetInitCommonWithIntergation = (payload) => ( } ); +const resetDetector = () => ({ + type: MANAGER.RESET_DETECTOR, +}); + export { - resetAll, resetInitCommon, resetInitNmr, resetInitMs, resetInitCommonWithIntergation, + resetAll, + resetInitCommon, + resetInitNmr, + resetInitMs, + resetInitCommonWithIntergation, + resetDetector, }; // eslint-disable-line diff --git a/src/components/cmd_bar/04_integration.js b/src/components/cmd_bar/04_integration.js index 315746dc..7b47db49 100644 --- a/src/components/cmd_bar/04_integration.js +++ b/src/components/cmd_bar/04_integration.js @@ -106,6 +106,7 @@ const Integration = ({ className={ classNames( focusStyle(isFocusAddIntgSt, classes), + 'btn-add-inter', ) } disabled={isDisableSt} @@ -127,6 +128,7 @@ const Integration = ({ className={ classNames( focusStyle(isFocusRmIntgSt, classes), + 'btn-remove-inter', ) } disabled={isDisableSt} @@ -148,6 +150,7 @@ const Integration = ({ className={ classNames( focusStyle(isFocusSetRefSt, classes), + 'btn-set-inter-ref', ) } disabled={isDisableSt} diff --git a/src/components/cmd_bar/07_pecker.js b/src/components/cmd_bar/07_pecker.js index 86c83e63..1d062088 100644 --- a/src/components/cmd_bar/07_pecker.js +++ b/src/components/cmd_bar/07_pecker.js @@ -96,7 +96,7 @@ const Pecker = ({ className={ classNames( focusStyle(isFocusAddPeckerSt, classes), - 'btn-sv-bar-addpeak', + 'btn-sv-bar-addpecker', ) } onClick={onSweepPeckerAdd} @@ -115,7 +115,7 @@ const Pecker = ({ className={ classNames( focusStyle(isFocusRmPeckerSt, classes), - 'btn-sv-bar-rmpeak', + 'btn-sv-bar-rmpecker', ) } onClick={onSweepPeckerDELETE} diff --git a/src/components/cmd_bar/index.js b/src/components/cmd_bar/index.js index d8944be0..6c2c8203 100644 --- a/src/components/cmd_bar/index.js +++ b/src/components/cmd_bar/index.js @@ -20,6 +20,7 @@ import Submit from './r04_submit'; import Wavelength from './r07_wavelength_btn'; import Pecker from './07_pecker'; import ChangeAxes from './r08_change_axes'; +import Detector from './r09_detector'; const styles = () => ( Object.assign( @@ -56,6 +57,7 @@ const CmdBar = ({ + ); diff --git a/src/components/cmd_bar/r05_submit_btn.js b/src/components/cmd_bar/r05_submit_btn.js index c53cb4eb..ee6bb317 100644 --- a/src/components/cmd_bar/r05_submit_btn.js +++ b/src/components/cmd_bar/r05_submit_btn.js @@ -28,7 +28,7 @@ const onClickCb = ( operation, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, - cyclicvoltaSt, curveSt, axesUnitsSt, + cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, ) => ( () => { operation({ @@ -49,6 +49,7 @@ const onClickCb = ( cyclicvoltaSt, curveSt, axesUnitsSt, + detectorSt, }); } ); @@ -57,7 +58,7 @@ const BtnSubmit = ({ classes, operation, feature, isAscend, isIntensity, editPeakSt, thresSt, layoutSt, shiftSt, scanSt, forecastSt, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, - waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, + waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, }) => { const peaksEdit = extractPeaksEdit(feature, editPeakSt, thresSt, shiftSt, layoutSt); // const disBtn = peaksEdit.length === 0 || statusSt.btnSubmit || disabled; @@ -80,7 +81,7 @@ const BtnSubmit = ({ operation.value, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, - cyclicvoltaSt, curveSt, axesUnitsSt, + cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, )} > @@ -105,6 +106,7 @@ const mapStateToProps = (state, props) => ( // eslint-disable-line cyclicvoltaSt: state.cyclicvolta, curveSt: state.curve, axesUnitsSt: state.axesUnits, + detectorSt: state.detector, } ); @@ -138,6 +140,7 @@ BtnSubmit.propTypes = { cyclicvoltaSt: PropTypes.object.isRequired, curveSt: PropTypes.object, axesUnitsSt: PropTypes.object.isRequired, + detectorSt: PropTypes.object.isRequired, }; export default compose( diff --git a/src/components/cmd_bar/r09_detector.js b/src/components/cmd_bar/r09_detector.js new file mode 100644 index 00000000..c498d14d --- /dev/null +++ b/src/components/cmd_bar/r09_detector.js @@ -0,0 +1,116 @@ +/* eslint-disable prefer-object-spread, react/jsx-one-expression-per-line, +react/function-component-definition */ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import classNames from 'classnames'; +import { bindActionCreators } from 'redux'; + +import { + FormControl, InputLabel, Select, MenuItem, +} from '@mui/material'; +import withStyles from '@mui/styles/withStyles'; +import { updateDetector } from '../../actions/detector'; +import Format from '../../helpers/format'; +import { commonStyle } from './common'; +import { LIST_DETECTORS } from '../../constants/list_detectors'; + +const styles = () => ( + Object.assign( + { + fieldShift: { + width: 160, + }, + fieldLayout: { + width: 100, + }, + }, + commonStyle, + ) +); + +const detectorSelect = (classes, detectorSt, curveSt, layoutSt, updateDetectorAct) => { + if (!Format.isSECLayout(layoutSt)) { + return ( + + ); + } + + const { curveIdx } = curveSt; + const { curves } = detectorSt; + + const getSelectedDetectorForCurve = (_detectorSt, targetCurveIdx) => { + const targetCurve = curves.find((curve) => curve.curveIdx === targetCurveIdx); + + return targetCurve ? targetCurve.selectedDetector : ''; + }; + + const selectedDetector = getSelectedDetectorForCurve(detectorSt, curveIdx); + + const onChange = (e) => updateDetectorAct({ curveIdx, selectedDetector: e.target.value }); + + return ( + + + Detector + + + + ); +}; + +const Detector = ({ + classes, detectorSt, curveSt, layoutSt, updateDetectorAct, +}) => ( + + { detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct) } + +); + +const mapStateToProps = (state, _props) => ( // eslint-disable-line + { + detectorSt: state.detector, + curveSt: state.curve, + layoutSt: state.layout, + } +); + +const mapDispatchToProps = (dispatch) => ( + bindActionCreators({ + updateDetectorAct: updateDetector, + }, dispatch) +); + +Detector.propTypes = { + classes: PropTypes.object.isRequired, + layoutSt: PropTypes.string.isRequired, + curveSt: PropTypes.object.isRequired, + updateDetectorAct: PropTypes.func.isRequired, + detectorSt: PropTypes.object.isRequired, +}; + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(withStyles(styles)(Detector)); diff --git a/src/components/d3_line/line_focus.js b/src/components/d3_line/line_focus.js index b560b7af..919ac8a4 100644 --- a/src/components/d3_line/line_focus.js +++ b/src/components/d3_line/line_focus.js @@ -225,9 +225,9 @@ class LineFocus { .attr('fill', 'none'); } - onClickTarget(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickTarget(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPeak = true; this.clickUiTargetAct(data, onPeak); } @@ -279,7 +279,7 @@ class LineFocus { .merge(auc) .attr('d', (d) => integCurve(d)) .attr('id', (d) => `auc${itgIdTag(d)}`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#auc${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#auc${itgIdTag(d)}`) @@ -287,7 +287,7 @@ class LineFocus { d3.select(`#auc${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#auc${itgIdTag(d)}`) .attr('stroke', 'none'); d3.select(`#auc${itgIdTag(d)}`) @@ -295,7 +295,7 @@ class LineFocus { d3.select(`#auc${itgIdTag(d)}`) .style('fill-opacity', 0.2); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } drawPeaks(editPeakSt) { @@ -337,23 +337,23 @@ class LineFocus { .merge(mpp) .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y)})`) - .on('mouseover', (d, i, n) => { + .on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); + this.tip.show(tipParams, event.target); }) - .on('mouseout', (d, i, n) => { + .on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); + this.tip.hide(tipParams, event.target); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const ignoreRef = Format.isHplcUvVisLayout(this.layout); if (ignoreRef) { @@ -373,7 +373,7 @@ class LineFocus { .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .text((d) => d.x.toFixed(2)) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y) - 25})`) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } } @@ -445,7 +445,7 @@ class LineFocus { .merge(igbp) .attr('id', (d) => `igbp${itgIdTag(d)}`) .attr('d', (d) => integBar(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -453,7 +453,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -461,7 +461,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const integCurve = (border) => { const { xL, xU } = border; @@ -489,7 +489,7 @@ class LineFocus { .merge(igcp) .attr('id', (d) => `igbc${itgIdTag(d)}`) .attr('d', (d) => integCurve(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -497,7 +497,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -505,7 +505,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); igtp.enter() .append('text') @@ -518,7 +518,7 @@ class LineFocus { .attr('id', (d) => `igtp${itgIdTag(d)}`) .text((d) => calcArea(d, refArea, refFactor, ignoreRef)) .attr('transform', (d) => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -526,7 +526,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -534,7 +534,7 @@ class LineFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } } @@ -601,7 +601,7 @@ class LineFocus { .attr('stroke', (d) => mpyColor(d)) .attr('id', (d) => `mpyb${mpyIdTag(d)}`) .attr('d', (d) => mpyBar(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -611,7 +611,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -622,7 +622,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); mpyt1.enter() .append('text') @@ -635,7 +635,7 @@ class LineFocus { .attr('id', (d) => `mpyt1${mpyIdTag(d)}`) .text((d) => `${calcMpyCenter(d.peaks, shift, d.mpyType).toFixed(3)}`) .attr('transform', (d) => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -645,7 +645,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -656,7 +656,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); mpyt2.enter() .append('text') @@ -669,7 +669,7 @@ class LineFocus { .attr('id', (d) => `mpyt2${mpyIdTag(d)}`) .text((d) => `(${d.mpyType})`) .attr('transform', (d) => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -679,7 +679,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -690,7 +690,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const mpypH = height - dh; const mpypPath = (pk) => ( @@ -714,7 +714,7 @@ class LineFocus { .attr('stroke', (d) => mpyColor(d)) .attr('d', (d) => lineSymbol(mpypPath(d))) .attr('id', (d) => `mpyp${mpyIdTag(d)}`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -724,7 +724,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -735,7 +735,7 @@ class LineFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } drawRef() { diff --git a/src/components/d3_multi/multi_focus.js b/src/components/d3_multi/multi_focus.js index 0942bbeb..0cde0510 100644 --- a/src/components/d3_multi/multi_focus.js +++ b/src/components/d3_multi/multi_focus.js @@ -259,9 +259,9 @@ class MultiFocus { .attr('fill', 'none'); } - onClickTarget(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickTarget(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPeak = true; if (this.layout === LIST_LAYOUT.CYCLIC_VOLTAMMETRY) { const { spectraList } = this.cyclicvoltaSt; @@ -273,9 +273,9 @@ class MultiFocus { } } - onClickPecker(data) { - d3.event.stopPropagation(); - d3.event.preventDefault(); + onClickPecker(event, data) { + event.stopPropagation(); + event.preventDefault(); const onPecker = true; const { spectraList } = this.cyclicvoltaSt; const spectra = spectraList[this.jcampIdx]; @@ -347,7 +347,7 @@ class MultiFocus { .merge(auc) .attr('d', (d) => integCurve(d)) .attr('id', (d) => `auc${itgIdTag(d)}`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#auc${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#auc${itgIdTag(d)}`) @@ -355,7 +355,7 @@ class MultiFocus { d3.select(`#auc${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#auc${itgIdTag(d)}`) .attr('stroke', 'none'); d3.select(`#auc${itgIdTag(d)}`) @@ -363,7 +363,7 @@ class MultiFocus { d3.select(`#auc${itgIdTag(d)}`) .style('fill-opacity', 0.2); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } drawPeaks(editPeakSt) { @@ -404,23 +404,23 @@ class MultiFocus { .merge(mpp) .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y)})`) - .on('mouseover', (d, i, n) => { + .on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); + this.tip.show(tipParams, event.target); }) - .on('mouseout', (d, i, n) => { + .on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); + this.tip.hide(tipParams, event.target); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const ignoreRef = Format.isHplcUvVisLayout(this.layout); if (ignoreRef) { @@ -440,7 +440,7 @@ class MultiFocus { .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .text((d) => d.x.toFixed(2)) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y) - 25})`) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } } @@ -482,23 +482,23 @@ class MultiFocus { .merge(mpp) .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y)})`) - .on('mouseover', (d, i, n) => { + .on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); + this.tip.show(tipParams, event.target); }) - .on('mouseout', (d, i, n) => { + .on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '0.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', '#228B22'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); + this.tip.hide(tipParams, event.target); }) - .on('click', (d) => this.onClickPecker(d)); + .on('click', (event, d) => this.onClickPecker(event, d)); } drawInteg(integationSt) { @@ -586,7 +586,7 @@ class MultiFocus { .merge(igbp) .attr('id', (d) => `igbp${itgIdTag(d)}`) .attr('d', (d) => integBar(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -594,7 +594,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -602,7 +602,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const integCurve = (border) => { const { xL, xU } = border; @@ -630,7 +630,7 @@ class MultiFocus { .merge(igcp) .attr('id', (d) => `igbc${itgIdTag(d)}`) .attr('d', (d) => integCurve(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -638,7 +638,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -646,7 +646,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); igtp.enter() .append('text') @@ -659,7 +659,7 @@ class MultiFocus { .attr('id', (d) => `igtp${itgIdTag(d)}`) .text((d) => calcArea(d, refArea, refFactor, ignoreRef)) .attr('transform', (d) => `translate(${xt((d.xL + d.xU) / 2 - shift)}, ${dh - 12})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', 'blue'); d3.select(`#igbc${itgIdTag(d)}`) @@ -667,7 +667,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { d3.select(`#igbp${itgIdTag(d)}`) .attr('stroke', '#228B22'); d3.select(`#igbc${itgIdTag(d)}`) @@ -675,7 +675,7 @@ class MultiFocus { d3.select(`#igtp${itgIdTag(d)}`) .style('fill', '#228B22'); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } } @@ -768,7 +768,7 @@ class MultiFocus { .attr('stroke', (d) => mpyColor(d)) .attr('id', (d) => `mpyb${mpyIdTag(d)}`) .attr('d', (d) => mpyBar(d)) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -778,7 +778,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -789,7 +789,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); mpyt1.enter() .append('text') @@ -802,7 +802,7 @@ class MultiFocus { .attr('id', (d) => `mpyt1${mpyIdTag(d)}`) .text((d) => `${calcMpyCenter(d.peaks, shift, d.mpyType).toFixed(3)}`) .attr('transform', (d) => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 12})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -812,7 +812,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -823,7 +823,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); mpyt2.enter() .append('text') @@ -836,7 +836,7 @@ class MultiFocus { .attr('id', (d) => `mpyt2${mpyIdTag(d)}`) .text((d) => `(${d.mpyType})`) .attr('transform', (d) => `translate(${xt((d.xExtent.xL + d.xExtent.xU) / 2 - shift)}, ${height - dh + 24})`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -846,7 +846,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -857,7 +857,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); const mpypH = height - dh; const mpypPath = (pk) => ( @@ -881,7 +881,7 @@ class MultiFocus { .attr('stroke', (d) => mpyColor(d)) .attr('d', (d) => lineSymbol(mpypPath(d))) .attr('id', (d) => `mpyp${mpyIdTag(d)}`) - .on('mouseover', (d) => { + .on('mouseover', (event, d) => { d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', 'blue'); d3.selectAll(`#mpyt1${mpyIdTag(d)}`) @@ -891,7 +891,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', 'blue'); }) - .on('mouseout', (d) => { + .on('mouseout', (event, d) => { const dColor = mpyColor(d); d3.selectAll(`#mpyb${mpyIdTag(d)}`) .attr('stroke', dColor); @@ -902,7 +902,7 @@ class MultiFocus { d3.selectAll(`#mpyp${mpyIdTag(d)}`) .attr('stroke', dColor); }) - .on('click', (d) => this.onClickTarget(d)); + .on('click', (event, d) => this.onClickTarget(event, d)); } drawRef() { diff --git a/src/components/d3_rect/rect_focus.js b/src/components/d3_rect/rect_focus.js index c1a70fb7..2caac0da 100644 --- a/src/components/d3_rect/rect_focus.js +++ b/src/components/d3_rect/rect_focus.js @@ -142,21 +142,21 @@ class RectFocus { .attr('height', (d) => this.posHeight(gnd, yt(d.y))) .attr('id', (d) => `mpp${Math.round(1000 * d.x)}`) .attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y)})`) - .on('mouseover', (d, i, n) => { + .on('mouseover', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'blue'); const tipParams = { d, layout: this.layout }; - this.tip.show(tipParams, n[i]); + this.tip.show(tipParams, event.target); }) - .on('mouseout', (d, i, n) => { + .on('mouseout', (event, d) => { d3.select(`#mpp${Math.round(1000 * d.x)}`) .attr('stroke-opacity', '1.0'); d3.select(`#bpt${Math.round(1000 * d.x)}`) .style('fill', 'red'); const tipParams = { d, layout: this.layout }; - this.tip.hide(tipParams, n[i]); + this.tip.hide(tipParams, event.target); }); } diff --git a/src/components/panel/cyclic_voltamery_data.js b/src/components/panel/cyclic_voltamery_data.js index f212e640..95a46ae4 100644 --- a/src/components/panel/cyclic_voltamery_data.js +++ b/src/components/panel/cyclic_voltamery_data.js @@ -154,7 +154,9 @@ const CyclicVoltammetryPanel = ({ )); return ( - + } className={classNames(classes.panelSummary)} diff --git a/src/components/panel/info.js b/src/components/panel/info.js index 778a60ad..1b2e6b66 100644 --- a/src/components/panel/info.js +++ b/src/components/panel/info.js @@ -116,11 +116,26 @@ const aucValue = (integration) => { const InfoPanel = ({ classes, expand, feature, integration, editorOnly, molSvg, descriptions, layoutSt, simulationSt, shiftSt, curveSt, theoryMass, - onExapnd, canChangeDescription, onDescriptionChanged, + onExapnd, canChangeDescription, onDescriptionChanged, detectorSt, }) => { if (!feature) return null; const { title, observeFrequency, solventName } = feature; const { curveIdx } = curveSt; + const { curves } = detectorSt; + + const getSelectedDetectorForCurve = (_detectorSt, targetCurveIdx) => { + const targetCurve = curves.find((curve) => curve.curveIdx === targetCurveIdx); + + return targetCurve ? targetCurve.selectedDetector.name : ''; + }; + + let selectedDetector = getSelectedDetectorForCurve(detectorSt, curveIdx); + + // default detector from jcamp + if (!selectedDetector && feature.detector) { + selectedDetector = feature.detector; + } + const { shifts } = shiftSt; const selectedShift = shifts[curveIdx]; let showSolvName = solventName; @@ -188,6 +203,16 @@ const InfoPanel = ({ ) : null } + { + Format.isSECLayout(layoutSt) + ? ( +
+ Detector: + {selectedDetector} +
+ ) + : null + } { !molSvg ? null @@ -259,6 +284,7 @@ const mapStateToProps = (state, props) => ( // eslint-disable-line simulationSt: state.simulation, shiftSt: state.shift, curveSt: state.curve, + detectorSt: state.detector, } ); @@ -283,6 +309,7 @@ InfoPanel.propTypes = { canChangeDescription: PropTypes.bool.isRequired, onDescriptionChanged: PropTypes.func, theoryMass: PropTypes.string, + detectorSt: PropTypes.object.isRequired, }; export default connect( // eslint-disable-line diff --git a/src/constants/action_type.js b/src/constants/action_type.js index bffa4863..d10ab1f1 100644 --- a/src/constants/action_type.js +++ b/src/constants/action_type.js @@ -27,6 +27,7 @@ const MANAGER = { RESET_INIT_NMR: 'RESET_INIT_NMR', RESET_INIT_MS: 'RESET_INIT_MS', RESET_INIT_COMMON_WITH_INTERGATION: 'RESET_INIT_COMMON_WITH_INTERGATION', + RESET_DETECTOR: 'RESET_DETECTOR', }; const LAYOUT = { @@ -153,8 +154,12 @@ const AXES = { UPDATE_Y_AXIS: 'UPDATE_Y_AXIS', }; +const SEC = { + UPDATE_DETECTOR: 'UPDATE_DETECTOR', +}; + export { THRESHOLD, EDITPEAK, STATUS, MANAGER, LAYOUT, SHIFT, SCAN, UI, FORECAST, SUBMIT, INTEGRATION, MULTIPLICITY, META, - SIMULATION, JCAMP, XRD, CYCLIC_VOLTA_METRY, CURVE, AXES, + SIMULATION, JCAMP, XRD, CYCLIC_VOLTA_METRY, CURVE, AXES, SEC, }; diff --git a/src/constants/list_detectors.js b/src/constants/list_detectors.js new file mode 100644 index 00000000..810ee990 --- /dev/null +++ b/src/constants/list_detectors.js @@ -0,0 +1,17 @@ +const rI = { + name: 'Refractive index', + label: 'RI', +}; + +const uV = { + name: 'Ultraviolet', + label: 'UV', +}; + +const LIST_DETECTORS = [ + rI, uV, +]; + +export { +LIST_DETECTORS, // eslint-disable-line +}; diff --git a/src/helpers/brush.js b/src/helpers/brush.js index 82f33e91..b7748aaf 100644 --- a/src/helpers/brush.js +++ b/src/helpers/brush.js @@ -3,19 +3,19 @@ import * as d3 from 'd3'; import { MouseMove } from './compass'; -const wheeled = (focus) => { +const wheeled = (focus, event) => { const { currentExtent, scrollUiWheelAct } = focus; // WORKAROUND: firefox wheel compatibilty - const wheelEvent = focus.isFirefox ? -d3.event.deltaY : d3.event.wheelDelta; // eslint-disable-line + const wheelEvent = focus.isFirefox ? -event.deltaY : event.wheelDelta; // eslint-disable-line const direction = wheelEvent > 0; scrollUiWheelAct(Object.assign({}, currentExtent, { direction })); }; -const brushed = (focus, isUiAddIntgSt) => { +const brushed = (focus, isUiAddIntgSt, event) => { const { selectUiSweepAct, data, dataPks, brush, w, h, scales, } = focus; - const selection = d3.event.selection && d3.event.selection.reverse(); + const selection = event.selection && event.selection.reverse(); if (!selection) return; let xes = [w, 0].map(scales.x.invert).sort((a, b) => a - b); let yes = [h, 0].map(scales.y.invert).sort((a, b) => a - b); @@ -44,8 +44,8 @@ const MountBrush = (focus, isUiAddIntgSt, isUiNoBrushSt) => { svg.selectAll('.brush').remove(); svg.selectAll('.brushX').remove(); - const brushedCb = () => brushed(focus, isUiAddIntgSt); - const wheeledCb = () => wheeled(focus); + const brushedCb = (event) => brushed(focus, isUiAddIntgSt, event); + const wheeledCb = (event) => wheeled(focus, event); if (isUiNoBrushSt) { const target = isUiAddIntgSt ? brushX : brush; @@ -57,7 +57,7 @@ const MountBrush = (focus, isUiAddIntgSt, isUiNoBrushSt) => { const klass = isUiAddIntgSt ? 'brushX' : 'brush'; root.append('g') .attr('class', klass) - .on('mousemove', () => MouseMove(focus)) + .on('mousemove', (event) => MouseMove(event, focus)) .call(target); } diff --git a/src/helpers/chem.js b/src/helpers/chem.js index 57a0134e..a9290eae 100644 --- a/src/helpers/chem.js +++ b/src/helpers/chem.js @@ -734,7 +734,8 @@ const extrFeaturesCylicVolta = (jcamp, layout, peakUp) => { const lowerThres = Format.isXRDLayout(layout) ? 100 : calcLowerThres(s); const cpo = buildPeakFeature(jcamp, layout, peakUp, s, 100, upperThres, lowerThres); const bnd = getBoundary(s); - return Object.assign({}, base, cpo, bnd); + const detector = Format.isSECLayout(layout) && jcamp.info.$DETECTOR ? jcamp.info.$DETECTOR : ''; + return Object.assign({}, base, cpo, bnd, { detector }); }).filter((r) => r != null); return features; @@ -788,7 +789,7 @@ const ExtractJcamp = (source) => { source, { xy: true, - keepRecordsRegExp: /(\$CSTHRESHOLD|\$CSSCANAUTOTARGET|\$CSSCANEDITTARGET|\$CSSCANCOUNT|\$CSSOLVENTNAME|\$CSSOLVENTVALUE|\$CSSOLVENTX|\$CSCATEGORY|\$CSITAREA|\$CSITFACTOR|\$OBSERVEDINTEGRALS|\$OBSERVEDMULTIPLETS|\$OBSERVEDMULTIPLETSPEAKS|\.SOLVENTNAME|\.OBSERVEFREQUENCY|\$CSSIMULATIONPEAKS|\$CSUPPERTHRESHOLD|\$CSLOWERTHRESHOLD|\$CSCYCLICVOLTAMMETRYDATA|UNITS|SYMBOL|CSAUTOMETADATA)/, // eslint-disable-line + keepRecordsRegExp: /(\$CSTHRESHOLD|\$CSSCANAUTOTARGET|\$CSSCANEDITTARGET|\$CSSCANCOUNT|\$CSSOLVENTNAME|\$CSSOLVENTVALUE|\$CSSOLVENTX|\$CSCATEGORY|\$CSITAREA|\$CSITFACTOR|\$OBSERVEDINTEGRALS|\$OBSERVEDMULTIPLETS|\$OBSERVEDMULTIPLETSPEAKS|\.SOLVENTNAME|\.OBSERVEFREQUENCY|\$CSSIMULATIONPEAKS|\$CSUPPERTHRESHOLD|\$CSLOWERTHRESHOLD|\$CSCYCLICVOLTAMMETRYDATA|UNITS|SYMBOL|CSAUTOMETADATA|\$DETECTOR)/, // eslint-disable-line }, ); const layout = readLayout(jcamp); diff --git a/src/helpers/compass.js b/src/helpers/compass.js index bf80d3ef..91ca6333 100644 --- a/src/helpers/compass.js +++ b/src/helpers/compass.js @@ -8,11 +8,11 @@ const TfRescale = (focus) => { return { xt, yt }; }; -const fetchPt = (focus, xt) => { +const fetchPt = (event, focus, xt) => { // const rawMouseX = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetX // : d3.mouse(focus.root.node())[0]; - const rawMouseX = d3.mouse(focus.root.node())[0]; + const rawMouseX = d3.pointer(event, focus.root.node())[0]; const mouseX = xt.invert(rawMouseX); const bisectDate = d3.bisector((d) => +d.x).left; const dt = focus.data; @@ -22,15 +22,15 @@ const fetchPt = (focus, xt) => { return sortData[idx]; }; -const fetchFreePt = (focus, xt, yt) => { +const fetchFreePt = (event, focus, xt, yt) => { // const rawMouseX = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetX // : d3.mouse(focus.root.node())[0]; // const rawMouseY = focus.isFirefox // WORKAROUND d3.mouse firefox compatibility // ? d3.event.offsetY // : d3.mouse(focus.root.node())[1]; - const rawMouseX = d3.mouse(focus.root.node())[0]; - const rawMouseY = d3.mouse(focus.root.node())[1]; + const rawMouseX = d3.pointer(event, focus.root.node())[0]; + const rawMouseY = d3.pointer(event, focus.root.node())[1]; const mouseX = xt.invert(rawMouseX); const mouseY = yt.invert(rawMouseY); @@ -54,11 +54,11 @@ const fetchFreePt = (focus, xt, yt) => { return selectPoint; }; -const MouseMove = (focus) => { +const MouseMove = (event, focus) => { const { xt, yt } = TfRescale(focus); const { freq, layout, wavelength } = focus; if (Format.isCyclicVoltaLayout(layout)) { - const pt = fetchFreePt(focus, xt, yt); + const pt = fetchFreePt(event, focus, xt, yt); if (pt) { const tx = xt(pt.x); const ty = yt(pt.y); @@ -79,7 +79,7 @@ const MouseMove = (focus) => { } } } else { - const pt = fetchPt(focus, xt); + const pt = fetchPt(event, focus, xt); if (pt) { const tx = xt(pt.x); const ty = yt(pt.y); @@ -97,6 +97,10 @@ const MouseMove = (focus) => { focus.root.select('.cursor-txt-hz') .attr('transform', `translate(${tx},${ty - 30})`) .text(`2Theta: ${pt.x.toExponential(2)}, d-value: ${dValue}`); + } else if (Format.isTGALayout(layout)) { + focus.root.select('.cursor-txt') + .attr('transform', `translate(${tx},${10})`) + .text(`X: ${pt.x.toFixed(3)}, Y: ${pt.y.toFixed(3)}`); } else { focus.root.select('.cursor-txt') .attr('transform', `translate(${tx},${10})`) @@ -114,14 +118,14 @@ const MouseMove = (focus) => { } }; -const ClickCompass = (focus) => { - d3.event.stopPropagation(); - d3.event.preventDefault(); +const ClickCompass = (event, focus) => { + event.stopPropagation(); + event.preventDefault(); const { xt, yt } = TfRescale(focus); - let pt = fetchPt(focus, xt); + let pt = fetchPt(event, focus, xt); const { layout, cyclicvoltaSt, jcampIdx } = focus; if (Format.isCyclicVoltaLayout(layout)) { - pt = fetchFreePt(focus, xt, yt); + pt = fetchFreePt(event, focus, xt, yt); const onPeak = false; if (cyclicvoltaSt) { const { spectraList } = cyclicvoltaSt; @@ -170,8 +174,8 @@ const MountCompass = (focus) => { .style('fill', '#D68910'); overlay - .on('mousemove', () => MouseMove(focus)) - .on('click', () => ClickCompass(focus)); + .on('mousemove', (event) => MouseMove(event, focus)) + .on('click', (event) => ClickCompass(event, focus)); }; export { diff --git a/src/helpers/mount.js b/src/helpers/mount.js index eca1c7da..d91d7a5f 100644 --- a/src/helpers/mount.js +++ b/src/helpers/mount.js @@ -65,7 +65,7 @@ const MountPath = (target, color) => { .style('fill', 'none') .style('stroke', color) .style('stroke-width', 1) - .on('click', () => ClickCompass(target)); + .on('click', (event) => ClickCompass(event, target)); return path; }; @@ -81,7 +81,7 @@ const MountComparePath = (target, color, id, alpha = 1) => { .style('stroke-opacity', alpha) .style('stroke-width', 1) .style('stroke-dasharray', ('30, 3')) - .on('click', () => ClickCompass(target)); + .on('click', (event) => ClickCompass(event, target)); return path; }; diff --git a/src/helpers/zoom.js b/src/helpers/zoom.js index 0411c3dd..2db6bf5e 100644 --- a/src/helpers/zoom.js +++ b/src/helpers/zoom.js @@ -6,10 +6,10 @@ const resetZoom = (main) => { }; const MountZoom = (main, zoomed) => { - const zoomedCb = () => zoomed(main); - const resetZoomCb = () => { - d3.event.stopPropagation(); - d3.event.preventDefault(); + const zoomedCb = (event) => zoomed(event, main); + const resetZoomCb = (event) => { + event.stopPropagation(); + event.preventDefault(); resetZoom(main); }; diff --git a/src/index.js b/src/index.js index ea1f9f2b..db454bda 100644 --- a/src/index.js +++ b/src/index.js @@ -506,6 +506,7 @@ class DemoWriteIr extends React.Component { RAMAN