From 5d8daa0f53fa7bd300fc3c9c9fac2d926c031f8b Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 14 Mar 2024 17:36:04 -0700 Subject: [PATCH 01/46] feat: add favicon --- web-server/img/favicon.ico | Bin 0 -> 15086 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 web-server/img/favicon.ico diff --git a/web-server/img/favicon.ico b/web-server/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b37befd6ba226aa1d31d8956d09749fde788cb3b GIT binary patch literal 15086 zcmeHO3sh9c8J-msivm8_Wr2O%ecjhCEIvT8A`8A>NL45*Nh7T$=AktbwWLizjmD&n zRP4hf5;d9=ZAFdIU^E8M92Fah+BP9R5_%GiwMk>}1qyfi%`PATMUrFB@tod!&d=<< z^Uwc(^Ud77v-4dD(U1TV7e`QXWRruC1VRYMHJ$e&UAsH=eeAM1dYEi6O_Vuf znrzg^J0tt{mHPy1?lw|6q^rgm*{8SD5YbQO3}a-AG0ka;^g1JYTU z)mB`h;fEV&cx5BXMyfq3E5#y6JugD=ub2(tfSbi>);y#(+mCM zHHa}<@Q$o9|LTv5zT^|C-GAj~&OOAZPT;?Dv3fP^|+8Ep?pK9N~b`u}w zNW@z;lpm3%V182jPi83Ln1?N6!0rk30rxfIzeTWfrs`3(GawEd7EFP#v)JW%HKt#>NI%f%y!>F1h1Y8vd}mG5km?eh~}zup)^(!$)J{ z6X>9lV^j~HzUV)T&*qLeAmJqDu(vaKZ{>rwDdNC{)22nQ`tMsd#xUFuir8;}FE`7d zxO}a`eSq9e_!(A)nPHdQ?tdCq?efn-)&I!C@uVk~#!FLxYx?Fet`76q@ z2C=QO-I9wrQ-+-9VRf(uQQ#Zw>DgDTk3RDmKYHS3NtPzN!h+g8%iJ0g=<3_UC|gZQ zXqN_?02>P9VZj}7csJ{is|QSmjf72tO_Xis6qh!Hb9W(K?`AGFmdb$2fXaZ%fXaZ% zfXaZ%fXaZ%fXaZ%K<5~szJri^t!xOOv<5pf7d4a?U}v?4lr@qdLduD^0k1=m0#@Qz zcmc^*Sjl?e>oN1khk_uq$MqUBrFCd`ul27P4|`9GgQdV)-qXUnTTFeg{ zHy3(9N^EHNkhX2{IMzTjNwq%o)E;OSm-T=72lUW0H1dsO)VTbOOW1oaf%fad{&g?l zxh)pd1w%6m!=Aka-EXsT*~Z$)*Q=<0+bOEw{5NV?`PL=t%wO&n`^S4z*<-QkfMzuw zd-rE``~CwBg6Tcb=6w3BUw2{pgCjlr820tIB1d9#yS63j2Ek{GW5Tp5eMz-nw`1B( zvj&COx_7^(rX}mX5Ry{IvGz`@*#fQbDARzMuBk2i7MkpfO5~;!zH^^81zm*8eStz3 zdJj2n`xIw&@G0ZwJ@40jn684DdT7qv!rv(@wl4>?81vJsk25yTG3L^HaKa&in8(ZX9DKQvv#1M$Qa6>izRn5B<|N?a^vUlG34$w2WEX zyv^sXK%#+;G0~R&*e6kI4^sV>k16IL6&*JEKyIGmsj64{U`%xH{EO+2r-l25q+5Qm zY)8~9LCsqJXr8}XJZT(!+tFY{8UF&glzyJT{@ey ztsjKz0NE5}N4)!C`Oy59@kyyqh#qfpY*=v5w*Kn5%7Ds%%7Dti{|^KH{esT_ZKSlU z#@i579(FOHAnc-snCl4JGAYPcG}kEort^{fo@}3jEoeAc%RUAE*GxVBHw<8{9pE8% zepg~Jd{SDiJ>t5PK+EHc#u^H@zh)@fxzoI$Fb``M6V`hz?_IFZVuHtLp1)!t*4jG^ zE4Ho2J3nLMx{*M0-m094?WezD>oM(~3l!@^#h#I~+o=oHH}{l%#YP`VZKZFkT6ySX;GwH*O%VImTysc#pRzZct(=zj)1BbM9|4 zS^UAFAzhqyYgfF1a>sS3)8*7~MngA8V89Pvzp Date: Thu, 14 Mar 2024 18:52:33 -0600 Subject: [PATCH 02/46] Adding favicon to all pages. Closes #1168 --- webpack.common.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/webpack.common.js b/webpack.common.js index 2b19add79..b7d7ccb23 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -18,6 +18,8 @@ const branch = execSync('git rev-parse --abbrev-ref HEAD') // importing vtk rules for for vtk.js package to work var vtkRules = require('vtk.js/Utilities/config/dependency.js').webpack.core.rules; +const favicon = 'web-server/img/favicon.ico'; + module.exports = { experiments: { // Support the Top Level Await Stage 3 proposal, it makes the module an async module when await is used on the top-level. @@ -85,36 +87,43 @@ module.exports = { new HtmlWebpackPlugin({ template: 'web-server/plugins/slycat-run-command/ui.html', filename: 'ui_run_command.html', + favicon: favicon, chunks: ['ui_run_command'], }), new HtmlWebpackPlugin({ template: 'web-server/plugins/slycat-smb/ui.html', filename: 'ui_smb.html', + favicon: favicon, chunks: ['ui_smb'], }), new HtmlWebpackPlugin({ template: 'web-server/templates/slycat-projects.html', filename: 'slycat_projects.html', + favicon: favicon, chunks: ['slycat_projects'], }), new HtmlWebpackPlugin({ template: 'web-server/templates/slycat-project.html', filename: 'slycat_project.html', + favicon: favicon, chunks: ['slycat_project'], }), new HtmlWebpackPlugin({ template: 'web-server/templates/slycat-page.html', filename: 'slycat_page.html', + favicon: favicon, chunks: ['slycat_page'], }), new HtmlWebpackPlugin({ template: 'web-server/templates/slycat-model-page.html', filename: 'slycat_model.html', + favicon: favicon, chunks: ['slycat_model'], }), new HtmlWebpackPlugin({ template: 'web-server/slycat-login/index.html', filename: 'slycat_login.html', + favicon: favicon, chunks: ['slycat_login'], }), // Copying our documentation manual into the dist folder, from docs/manual/html to dist/docs From 938812164b509cb585ecdd3d726fac62bfdfbed4 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 12:07:26 +0200 Subject: [PATCH 03/46] style: minor typescript warning cleanup --- .../js/Components/ControlsButtonVarOptions.js | 1 - .../slycat-parameter-image/js/Components/Histogram.tsx | 8 ++++---- .../slycat-parameter-image/js/Components/PSHistogram.tsx | 2 +- web-server/plugins/slycat-parameter-image/js/ui.js | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js index f7f38c693..c3b8088dc 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js @@ -19,7 +19,6 @@ import VariableAliasLabels from "components/VariableAliasLabels"; import ScatterplotOptions from "components/ScatterplotOptions"; import VariableRanges from "components/VariableRanges"; import "js/slycat-table-ingestion"; -import ko from "knockout"; import "../../css/controls-button-var-options.css"; import $ from "jquery"; import client from "js/slycat-web-client"; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/Histogram.tsx b/web-server/plugins/slycat-parameter-image/js/Components/Histogram.tsx index 6841ee3f5..74ffb85b9 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/Histogram.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/Histogram.tsx @@ -35,7 +35,7 @@ type HistogramProps = { }, ) => void; handleBackgroundClick: (event: React.MouseEvent) => void; - tickFormatter: (value: number) => string; + tickFormatter: ((value: number, index?: number) => string) | null; }; const Histogram: React.FC = (props) => { @@ -207,13 +207,13 @@ const Histogram: React.FC = (props) => { }) .append("title") .text((bin) => { - const x0 = tickFormatter ? tickFormatter(bin.x0) : bin.x0; - const x1 = tickFormatter ? tickFormatter(bin.x1) : bin.x1; + const x0 = tickFormatter && bin.x0 !== undefined ? tickFormatter(bin.x0) : bin.x0; + const x1 = tickFormatter && bin.x1 !== undefined ? tickFormatter(bin.x1) : bin.x1; return `Count: ${bin.length}\n\nRange: ${x0} (inclusive) to \n${x1} (exclusive, except for last bar)`; }); let x_axis = d3.axisBottom(x_scale).tickSizeOuter(0); - + // Create tick values by combining the x0 and x1 values of each bin. // That way we get a tick at start and end of each bin. let tickValues = [...bins.map((bin) => bin.x0), ...bins.map((bin) => bin.x1)]; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSHistogram.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSHistogram.tsx index 6065902b8..1e4226911 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSHistogram.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSHistogram.tsx @@ -125,7 +125,7 @@ const PSHistogram: React.FC = (props) => { const handleBinClick = ( event: React.MouseEvent, bin: { - range: number[]; + range: (number | undefined)[]; count: number; index: number; bins_length: number; diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 790891c6f..b01da6a3f 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -18,7 +18,6 @@ import bookmark_manager from "js/slycat-bookmark-manager"; import * as dialog from "js/slycat-dialog"; import NoteManager from "./note-manager"; import FilterManager from "./filter-manager"; -// import d3 from "d3"; import URI from "urijs"; import * as chunker from "js/chunker"; import "./parameter-image-scatterplot"; From fe05a5e546c3c79205e2eeb2e493d0437e1c0b43 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 12:22:24 +0200 Subject: [PATCH 04/46] style: prettier --- web-server/js/slycat-table-ingestion-react.js | 200 ++++++++---------- 1 file changed, 87 insertions(+), 113 deletions(-) diff --git a/web-server/js/slycat-table-ingestion-react.js b/web-server/js/slycat-table-ingestion-react.js index a2ba931eb..2fdc617d1 100644 --- a/web-server/js/slycat-table-ingestion-react.js +++ b/web-server/js/slycat-table-ingestion-react.js @@ -1,19 +1,18 @@ import React, { useState } from "react"; export default function SlycatTableIngestion(props) { - // Declare a new UI state variables... // To track which variables are selected // selected is an array, each element corresponds to a variable, with boolean values indicating whether it's selected. - const [selected, setSelected] = useState(props.variables.map((variable, indexVars) => variable.selected)); + const [selected, setSelected] = useState( + props.variables.map((variable, indexVars) => variable.selected), + ); // To track the last selected variable const [lastSelected, setLastSelected] = useState(0); function anyVariablesSelected() { - for(var i = 0; i < selected.length; i++) - { - if( selected[i] ) - { + for (var i = 0; i < selected.length; i++) { + if (selected[i]) { return true; } } @@ -26,60 +25,50 @@ export default function SlycatTableIngestion(props) { function selectAll(e) { let property = e.target.dataset.property; - for(let [index, variableSelected] of selected.entries()) - { - if(variableSelected) - { + for (let [index, variableSelected] of selected.entries()) { + if (variableSelected) { // Find the radio button that needs to be selected based on its name and value attributes - let radio = document.querySelector(`.${props.uniqueID} input[value='${property}'][name='${index}']`); + let radio = document.querySelector( + `.${props.uniqueID} input[value='${property}'][name='${index}']`, + ); // Fire the onChange handler only if radio button is not disabled - if(!radio.disabled) - { - props.onChange({currentTarget: radio}); + if (!radio.disabled) { + props.onChange({ currentTarget: radio }); } } } } function select(event, varIndex) { - if(props.variables[varIndex].disabled) - { + if (props.variables[varIndex].disabled) { return; - } - else if(event.shiftKey) - { + } else if (event.shiftKey) { // Find start and end between lastSelected and currently shift clicked let begin = Math.min(lastSelected, varIndex); let end = Math.max(lastSelected, varIndex); // Set everything in between to selected let newSelected = selected.slice(0); - for(var i = begin; i <= end; i++) - { - if(!props.variables[i].disabled) - { + for (var i = begin; i <= end; i++) { + if (!props.variables[i].disabled) { newSelected[i] = true; } } setSelected(newSelected); // Set current clicked to lastSelected setLastSelected(varIndex); - } - else if(event.ctrlKey || event.metaKey) - { + } else if (event.ctrlKey || event.metaKey) { setLastSelected(varIndex); let newSelected = selected.slice(0); // Invert the selected state, so Ctrl + click will either selecte unselected, or unselect selected. newSelected[varIndex] = !newSelected[varIndex]; setSelected(newSelected); - } - else - { + } else { // Set last selected to current variable setLastSelected(varIndex); // Set all selected to false - let newSelected = selected.map(x => false); + let newSelected = selected.map((x) => false); // Set selected to true on current variable newSelected[varIndex] = true; setSelected(newSelected); @@ -87,109 +76,96 @@ export default function SlycatTableIngestion(props) { } const propertiesItems = props.properties.map((property, indexProps) => { - if(property.type == 'bool') - { + if (property.type == "bool") { return ( - + {property.name} - ); + } else if (property.type == "select") { + return property.values.map((value, indexVals, array) => ( + + {value} + + + )); } - else if(property.type == 'select') - { - return ( - property.values.map((value, indexVals, array) => - ( - - {value} - - - ) - ) - ); - } - }); // Figure out if radio button should be disabled function disabledRadioButton(property, value, variable) { // Check if we have a disabledValue defined for this radio button - let disabledValue = property.disabledValues && property.disabledValues[value] && property.disabledValues[value].indexOf(variable.index) > -1; + let disabledValue = + property.disabledValues && + property.disabledValues[value] && + property.disabledValues[value].indexOf(variable.index) > -1; // Also return disabled if the entire variable is disabled - return variable.disabled || disabledValue ? 'disabled' : false; + return variable.disabled || disabledValue ? "disabled" : false; } const variablesItems = props.variables.map((variable, indexVars, arrayVars) => { return ( - - select(event, indexVars)}> - {variable.name} - - { - props.properties.map((property, indexProps, arrayProps) => { - if(property.type == 'bool') - { + + select(event, indexVars)}> + {variable.name} + + {props.properties.map((property, indexProps, arrayProps) => { + if (property.type == "bool") { return ( - - ); + } else if (property.type == "select") { + return property.values.map((value, indexVals, arrayVals) => ( + + + + )); } - else if(property.type == 'select') - { - return ( - property.values.map((value, indexVals, arrayVals) => - ( - - - - ) - ) - ); - } - }) - } - + })} + ); }); @@ -202,10 +178,8 @@ export default function SlycatTableIngestion(props) { {propertiesItems} - - {variablesItems} - + {variablesItems} ); -} \ No newline at end of file +} From 87b8e911b5491a6ed2f98740b4d094ecfaec8c36 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 12:32:22 +0200 Subject: [PATCH 05/46] style: prettier --- .../js/Components/ControlsButtonVarOptions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js index c3b8088dc..7fe02bcda 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js @@ -132,7 +132,7 @@ class ControlsButtonVarOptions extends React.PureComponent { // Maybe it was deleted. // Let's save to the model's artifact instead. console.log( - "Oops, we have a pointer to project data but can't save to it. Let's save to the model's artifact instead." + "Oops, we have a pointer to project data but can't save to it. Let's save to the model's artifact instead.", ); self.writeAliasesToModelArtifact(); }, @@ -156,11 +156,11 @@ class ControlsButtonVarOptions extends React.PureComponent { }, error: function () { console.log( - "Oops, can't even write aliases to model artifact. Closing dialog and popping up error dialog." + "Oops, can't even write aliases to model artifact. Closing dialog and popping up error dialog.", ); $("#" + self.modalId).modal("hide"); dialog.ajax_error( - "There was an error saving the variable alias labels to the model's artifact." + "There was an error saving the variable alias labels to the model's artifact.", )(); }, }); @@ -659,7 +659,7 @@ const mapStateToProps = (state, ownProps) => { min: value.min, max: value.max, }; - } + }, ); return { From dbb569f91b62fa95be481161cb95f2e33c37920b Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 12:41:43 +0200 Subject: [PATCH 06/46] fix: disable log scale radio button for variables with custom range min of 0 or less. Addresses #960 --- .../js/Components/ControlsButtonVarOptions.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js index 7fe02bcda..b3d8183e6 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js @@ -241,9 +241,12 @@ class ControlsButtonVarOptions extends React.PureComponent { undefined; // Check if variable is greater than zero const isGreaterThanZero = this.props.table_statistics?.[index]?.min > 0; - // If not numeric or not greater than zero, add to disabledLogVariables + // Check if custom axis min variable range is 0 or less + const isCustomAxisMinZeroOrLess = this.props.variableRanges?.[index]?.min <= 0; + // If not numeric or not greater than zero or custom min variablel range is 0 or less, + // add to disabledLogVariables // so we don't allow them for log scales. - if (!isNumericVariable || !isGreaterThanZero) { + if (!isNumericVariable || !isGreaterThanZero || isCustomAxisMinZeroOrLess) { disabledLogVariables.push(index); } } From dd92d15588197371d37713bdffd4c6ac3aa9c440 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 14:05:07 +0200 Subject: [PATCH 07/46] fix: enforce values greater than 0 when editing log scale variables. Addresses #960 --- .../js/Components/ControlsSelection.js | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js index c61c526f4..b5c675434 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js @@ -18,13 +18,17 @@ class ControlsSelection extends React.PureComponent { { className: "btn-primary", label: "Apply" }, ], callback: function (button, valueIn) { - if (button.label === "Apply") { - let userValue = valueIn().trim(); - let numeric = self.props.metadata["column-types"][variableIndex] !== "string"; - let valueValid = userValue.length > 0; - if (valueValid && numeric && isNaN(Number(userValue))) { - valueValid = false; - } + if (button?.label === "Apply") { + const userValue = valueIn().trim(); + const numeric = self.props.metadata["column-types"][variableIndex] !== "string"; + const log_scale_type = self.props.axes_variables_scale?.[variableIndex] == "Log"; + + // Perform validity checks + const fails_length_check = userValue.length <= 0; + const fails_numeric_check = numeric && isNaN(Number(userValue)); + const fails_log_check = log_scale_type && userValue <= 0; + const valueValid = !fails_length_check && !fails_numeric_check && !fails_log_check; + if (valueValid) { self.props.element.trigger("set-value", { selection: self.props.selection, @@ -32,9 +36,13 @@ class ControlsSelection extends React.PureComponent { value: numeric ? userValue : '"' + userValue + '"', }); } else { - let alertText = "Please enter a value."; - if (numeric) { + let alertText; + if (fails_length_check) { + alertText = "Please enter a value."; + } else if (fails_numeric_check) { alertText = "Please enter a numeric value."; + } else if (fails_log_check) { + alertText = "Please enter a value greater than 0."; } self.set_value(variable, variableIndex, userValue, alertText); } @@ -161,7 +169,7 @@ class ControlsSelection extends React.PureComponent { // console.log(`current_selection_pinned is ${current_selection_pinned}`); // Find the unpinned items in the current selection that are visible (i.e, not off axes). const unpinned_selection_not_off_axes = unpinned_selection.filter( - (unpinned_selected_item) => !this._is_off_axes(unpinned_selected_item) + (unpinned_selected_item) => !this._is_off_axes(unpinned_selected_item), ); // console.log(`unpinned_selection_not_off_axes is ${unpinned_selection_not_off_axes}`); // Check if entire unpinned selection is off axes, because we will be @@ -356,6 +364,7 @@ const mapStateToProps = (state, ownProps) => { media_index: state.media_index, xValues: state.derived.xValues, yValues: state.derived.yValues, + axes_variables_scale: state.axesVariables, }; }; From dbc15b8fdeb59976c0846e9399624e3efc3e573e Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Mon, 15 Jul 2024 14:11:17 +0200 Subject: [PATCH 08/46] style: update validation text --- .../slycat-parameter-image/js/Components/ControlsSelection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js index b5c675434..a46d19c77 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsSelection.js @@ -42,7 +42,7 @@ class ControlsSelection extends React.PureComponent { } else if (fails_numeric_check) { alertText = "Please enter a numeric value."; } else if (fails_log_check) { - alertText = "Please enter a value greater than 0."; + alertText = "Please enter a value greater than 0. This variable is on a log scale."; } self.set_value(variable, variableIndex, userValue, alertText); } From 6d5f97be66fdfd5f244f23eae1840e913c46249d Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 17 Jul 2024 21:30:19 +0200 Subject: [PATCH 09/46] fix: adding validation for variable ranges for log scales. Addresses #960 --- web-server/components/VariableRanges.js | 15 +++++++++++---- .../js/Components/ControlsButtonVarOptions.js | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/web-server/components/VariableRanges.js b/web-server/components/VariableRanges.js index 603b46a76..0a57dcd44 100644 --- a/web-server/components/VariableRanges.js +++ b/web-server/components/VariableRanges.js @@ -82,7 +82,8 @@ export default class VariableRanges extends React.Component { `, placement: "bottom", trigger: "hover", - content: "Axis Min must be less than Axis Max.", + content: + "Axis Min must be less than Axis Max. Both must be greater than 0 if this variable is using a log axis scale.", }); // Disabling popover tooltips for valid input fields. $(`.${this.class} .validationPopover.valid`).popover("disable"); @@ -146,7 +147,7 @@ export default class VariableRanges extends React.Component { oppositeNum, !min, oppositeCompare, - index + index, ), }; }; @@ -161,9 +162,15 @@ export default class VariableRanges extends React.Component { return true; } // NaNs are invalid - else if (Number.isNaN(inputNum)) { + if (Number.isNaN(inputNum)) { return false; - } else if (min ? inputNum < compare : inputNum > compare) { + } + // Zero and negative values are invalid for log scales + if (this.props.axesVariablesScale?.[key] === "Log" && inputNum <= 0) { + return false; + } + // Validate if not empty and not NaN and not 0 or less for log scale + if (min ? inputNum < compare : inputNum > compare) { // Save min or max to redux store since it's valid this.props.setVariableRange(key, inputNum, min ? "min" : "max"); return true; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js index b3d8183e6..d8c709184 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js @@ -310,6 +310,7 @@ class ControlsButtonVarOptions extends React.PureComponent { clearVariableRange={this.props.clearVariableRange} inputLabel="Axis" ref={this.variableRangesRef} + axesVariablesScale={this.props.axes_variables_scale} /> Date: Wed, 24 Jul 2024 15:21:29 +0200 Subject: [PATCH 10/46] refactor: remove test attribute and fix type --- .../js/Components/ControlsDropdown.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsDropdown.tsx b/web-server/plugins/slycat-parameter-image/js/Components/ControlsDropdown.tsx index 4937ddf58..42272407e 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsDropdown.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsDropdown.tsx @@ -17,8 +17,8 @@ type SetSelectedFunction = ( state_label: string, key: string, trigger: string, - e?: React.MouseEvent, - props?: Record + e?: React.MouseEvent, + props?: Record, ) => void; interface ControlsDropdownProps { @@ -61,15 +61,14 @@ class ControlsDropdown extends React.Component { default: // Get the set_selected function from the item if it's been set, or use the one passed in from props const set_selected_function = item.set_selected ?? this.props.set_selected; - // There are many times when item.selected is undefined. - // In those cases, we determine selected by looking at what's set in props.selected. - // But in cases where item.selected is already set to true or false, we just go with that value. + // There are many times when item.selected is undefined. + // In those cases, we determine selected by looking at what's set in props.selected. + // But in cases where item.selected is already set to true or false, we just go with that value. // This lets you specify the selected item on the item itself or by passing it as a prop, with the item taking precedence. const selected = item.selected ?? item.key == this.props.selected; return ( - )); - - let dropdown = ( - - -
- {optionItems} -
-
- ); - - return ( - - {this.props.single != true ? ( -
{dropdown}
- ) : ( - {dropdown} - )} -
- ); - } -} - -export default ControlsDropdown; diff --git a/web-server/plugins/slycat-cca/js/components/CCAControlsBar.js b/web-server/plugins/slycat-cca/js/components/CCAControlsBar.js index c1764b0f0..9898973d6 100644 --- a/web-server/plugins/slycat-cca/js/components/CCAControlsBar.js +++ b/web-server/plugins/slycat-cca/js/components/CCAControlsBar.js @@ -2,7 +2,7 @@ import React from "react"; import { connect } from 'react-redux'; import { setVariableSelected, } from '../actions'; import { setColormap, } from 'components/actionsColor'; -import ControlsDropdown from 'components/ControlsDropdownOld'; +import ControlsDropdown from 'components/ControlsDropdown'; import ControlsGroup from 'components/ControlsGroup'; import ControlsButtonDownloadDataTable from 'components/ControlsButtonDownloadDataTable'; import ControlsDropdownColor from 'components/ControlsDropdownColor'; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js index 2877778a8..02ade7cc5 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js @@ -14,7 +14,7 @@ class ControlsThreeD extends React.Component { super(props); } - changeThreeDColorBy = (label, key) => { + changeThreeDColorBy = (key, label) => { this.props.updateThreeDColorBy(this.props.currentFrame.uid, key); }; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js index 50bb4bf5c..285fbb2a3 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js @@ -115,7 +115,7 @@ class ControlsBar extends React.Component { } }; - set_selected = (state_label, key, trigger, e, props) => { + set_selected = (key, state_label, trigger, e, props) => { // This is the legacy way of letting the rest of non-React components that the state changed. Remove once we are converted to React. this.props.element.trigger(trigger, key); }; @@ -377,7 +377,7 @@ class ControlsBar extends React.Component { trigger="xypair_selection_changed" items={this.props.xy_pairs_items} selected={this.props.xy_pair_selected} - set_selected={(state_label, key, trigger, e) => + set_selected={(key, state_label, trigger, e) => this.props.element.trigger(trigger, key) } button_style={button_style} From 4c038c05586355e90cf544cd7cc4c65c0c65d99b Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 31 Jul 2024 15:01:34 +0200 Subject: [PATCH 16/46] refactor: rename component --- .../plugins/slycat-parameter-image/js/parameter-controls.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js index 8d93af35a..830233bad 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js @@ -5,7 +5,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import "jquery-ui"; -import ControlsBar from "./Components/PSControlsBar"; +import PSControlsBar from "./Components/PSControlsBar"; import "bootstrap"; import $ from "jquery"; @@ -120,7 +120,7 @@ $.widget("parameter_image.controls", { const controls_bar_ref = React.createRef(); const controls_bar = ( - Date: Wed, 31 Jul 2024 15:07:55 +0200 Subject: [PATCH 17/46] refactor: linting --- .../slycat-parameter-image/js/Components/PSControlsBar.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js index 285fbb2a3..d1607a96d 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js @@ -303,9 +303,8 @@ class ControlsBar extends React.Component { dispatch={dropdown.dispatch} /> ); - } else { - return false; } + return false; }); // Video and playback controls From a85fc315386c9b5d5355a1290196e2c0d63e710b Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 31 Jul 2024 19:33:40 +0200 Subject: [PATCH 18/46] refactor: rename --- .../js/Components/{PSControlsBar.js => PSControlsBar.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename web-server/plugins/slycat-parameter-image/js/Components/{PSControlsBar.js => PSControlsBar.tsx} (100%) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx similarity index 100% rename from web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.js rename to web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx From 47d598a7f1f79fd2f897065776d41542fa854a74 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 31 Jul 2024 21:22:03 +0200 Subject: [PATCH 19/46] build: install types for bootstrap and uuid --- package-lock.json | 21 ++++++++++++++++++++- package.json | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 723fe55f4..0f490197f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", + "@types/bootstrap": "^4", "@types/core-js": "^2.5.4", "@types/d3": "^3", "@types/d3v7": "npm:@types/d3@^7.4.0", @@ -78,6 +79,7 @@ "@types/react-dom": "^18", "@types/react-test-renderer": "^18", "@types/sinon": "^10.0.0", + "@types/uuid": "^9", "autoprefixer": "^10.1.0", "babel-jest": "^29", "babel-loader": "^9", @@ -3704,6 +3706,17 @@ "@types/node": "*" } }, + "node_modules/@types/bootstrap": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-4.6.6.tgz", + "integrity": "sha512-ca2slWHuPLl0QZCO7nRSsQrnPjE9fxJ+VokXMSlHRv2nlk3tYSHUkWPNOVrCsIv6iwCy8vGQGbyTkRDNjTNejA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jquery": "*", + "popper.js": "^1.14.1" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -4388,6 +4401,13 @@ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", "license": "MIT" }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.5.11", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", @@ -13523,7 +13543,6 @@ "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" diff --git a/package.json b/package.json index d3d776710..2e5067f47 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", + "@types/bootstrap": "^4", "@types/core-js": "^2.5.4", "@types/d3": "^3", "@types/d3v7": "npm:@types/d3@^7.4.0", @@ -88,6 +89,7 @@ "@types/react-dom": "^18", "@types/react-test-renderer": "^18", "@types/sinon": "^10.0.0", + "@types/uuid": "^9", "autoprefixer": "^10.1.0", "babel-jest": "^29", "babel-loader": "^9", From 82173d9ee6ce746789010946344422323587f3a6 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 14 Aug 2024 07:54:21 +0200 Subject: [PATCH 20/46] refactor: convert more of controls to React --- web-server/components/ControlsDropdown.tsx | 20 +-- .../js/Components/PSControlsBar.tsx | 160 +++++++++++++----- .../js/parameter-controls.js | 8 +- .../slycat-parameter-image/js/store.ts | 42 ++++- .../plugins/slycat-parameter-image/js/ui.js | 1 + 5 files changed, 168 insertions(+), 63 deletions(-) diff --git a/web-server/components/ControlsDropdown.tsx b/web-server/components/ControlsDropdown.tsx index dcb805ece..d5c2a4bae 100644 --- a/web-server/components/ControlsDropdown.tsx +++ b/web-server/components/ControlsDropdown.tsx @@ -4,18 +4,18 @@ import React from "react"; -interface IDropdownItems { - key: string; - name: string; - type?: string; - style: {}; +export interface IDropdownItems { + key?: number | string; + name?: string; + type?: "divider" | "header"; + style?: {}; set_selected?: SetSelectedFunction; selected?: boolean; } -type SetSelectedFunction = ( +export type SetSelectedFunction = ( + key: number | string, state_label: string, - key: string, trigger: string, e?: React.MouseEvent, props?: Record, @@ -23,7 +23,7 @@ type SetSelectedFunction = ( interface ControlsDropdownProps { items: IDropdownItems[]; - selected: string; + selected: string | number; set_selected: SetSelectedFunction; state_label: string; trigger: string; @@ -31,7 +31,7 @@ interface ControlsDropdownProps { id: string; title: string; label: string; - single: boolean; + single?: boolean; } /** @@ -73,7 +73,7 @@ class ControlsDropdown extends React.Component { className={"dropdown-item" + (selected ? " active" : "")} onClick={(e) => set_selected_function( - item.key, + item.key!, this.props.state_label, this.props.trigger, e, diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index d1607a96d..f07c316ac 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -23,13 +23,84 @@ import ControlsDropdownColor from "components/ControlsDropdownColor"; import slycat_color_maps from "js/slycat-color-maps"; import { v4 as uuidv4 } from "uuid"; import { toggleShowHistogram, toggleAutoScale } from "../scatterplotSlice"; +import { + RootState, + VariableRangesType, + ActiveFiltersType, + OpenMediaType, + VariableAliasesType, + TableMetadataType, +} from "../store"; +import { IDropdownItems, SetSelectedFunction } from "components/ControlsDropdown"; + +interface PSControlsBarDropdownsType { + id: string; + label: string; + title: string; + state_label: string; + trigger: string; + items: IDropdownItems[]; + selected: number; +} + +interface PSControlsBarAxesVariablesType { + key: number; + name: string; +} + +interface PSControlsBarProps { + auto_scale: boolean; + video_sync: boolean; + variableRanges: VariableRangesType; + active_filters: ActiveFiltersType; + element: JQuery; + selected_simulations: number[]; + open_media: OpenMediaType; + variable_aliases: VariableAliasesType; + dropdowns: PSControlsBarDropdownsType[]; + xy_pairs_items: { key: string; name: string }[]; + xy_pairs_indexes: number[]; + show_histogram: boolean; + metadata: TableMetadataType; + xy_pair_selected: string; + model: any; + axes_variables: PSControlsBarAxesVariablesType[]; + sync_scaling: boolean; + indices: Int32Array; + rating_variables: number[]; + media_columns: number[]; + media_index: number; + hidden_simulations: number[]; + aid: string; + mid: string; + pid: string; + model_name: string; + video_sync_time: number; + colormap: string; + x_index: number; + y_index: number; + v_index: number; + toggleAutoScale: () => void; + toggleShowHistogram: () => void; + setVideoSyncTime: (value: number) => void; + toggleSyncScaling: () => void; + toggleSyncThreeDColorvar: () => void; + setColormap: (colormap: string) => void; +} -class ControlsBar extends React.Component { - constructor(props) { +interface PSControlsBarState { + video_sync: boolean; +} + +class PSControlsBar extends React.Component { + autoScalePopoverSelector: string; + autoScaleId: string; + selection_id: string; + scatterplot_id: string; + constructor(props: PSControlsBarProps) { super(props); this.state = { video_sync: this.props.video_sync, - var_settings: this.props.var_settings, }; this.scatterplot_id = "scatterplot-controls"; this.selection_id = "selection-controls"; @@ -60,15 +131,20 @@ class ControlsBar extends React.Component { // Find any currently active axes limits let active_axes_limits = []; - for (const axis of ["x", "y", "v"]) { - const variableRanges = this.props.variableRanges[this.props[`${axis}_index`]]; - if (variableRanges !== undefined) { - for (const direction of ["min", "max"]) { - if (variableRanges.hasOwnProperty(direction)) { + const variableRangesPerVariable = { + x: this.props.variableRanges[this.props.x_index], + y: this.props.variableRanges[this.props.y_index], + v: this.props.variableRanges[this.props.v_index], + }; + + for (const [key, value] of Object.entries(variableRangesPerVariable)) { + if (value !== undefined) { + for (const direction of ["min", "max"] as const) { + if (value.hasOwnProperty(direction)) { active_axes_limits.push({ - axis: axis, + axis: key, direction: direction, - value: variableRanges[direction], + value: value[direction], }); } } @@ -115,16 +191,16 @@ class ControlsBar extends React.Component { } }; - set_selected = (key, state_label, trigger, e, props) => { + set_selected: SetSelectedFunction = (key, state_label, trigger, e, props) => { // This is the legacy way of letting the rest of non-React components that the state changed. Remove once we are converted to React. this.props.element.trigger(trigger, key); }; - set_auto_scale = (e) => { + set_auto_scale = () => { this.props.toggleAutoScale(); }; - set_video_sync = (e) => { + set_video_sync = () => { this.setState((prevState, props) => { const new_video_sync = !prevState.video_sync; this.props.element.trigger("video-sync", new_video_sync); @@ -132,20 +208,20 @@ class ControlsBar extends React.Component { }); }; - set_video_sync_time = (value) => { + set_video_sync_time = (value: number) => { this.props.setVideoSyncTime(value); this.props.element.trigger("video-sync-time", value); }; - trigger_show_all = (e) => { + trigger_show_all = () => { this.props.element.trigger("show-all"); }; - trigger_close_all = (e) => { + trigger_close_all = () => { this.props.element.trigger("close-all"); }; - trigger_hide_selection = (e) => { + trigger_hide_selection = () => { if (this.props.active_filters.length == 0) { this.props.element.trigger("hide-selection", this.props.selected_simulations); } @@ -159,7 +235,7 @@ class ControlsBar extends React.Component { // } }; - trigger_hide_unselected = (e) => { + trigger_hide_unselected = () => { if (this.props.active_filters.length == 0) { // As of jQuery 1.6.2, single string or numeric argument can be passed without being wrapped in an array. // https://api.jquery.com/trigger/ @@ -168,61 +244,61 @@ class ControlsBar extends React.Component { } }; - trigger_show_unselected = (e) => { + trigger_show_unselected = () => { if (this.props.active_filters.length == 0) { this.props.element.trigger("show-unselected", [this.props.selected_simulations]); } }; - trigger_show_selection = (e) => { + trigger_show_selection = () => { if (this.props.active_filters.length == 0) { this.props.element.trigger("show-selection", [this.props.selected_simulations]); } }; - trigger_pin_selection = (e) => { + trigger_pin_selection = () => { // Passing true along with selection to pin-selection trigger to make it restore the size // and location of pins. We only do this when pinning from the controls menu, per // https://github.com/sandialabs/slycat/issues/1043#issuecomment-954137333 this.props.element.trigger("pin-selection", [this.props.selected_simulations, true]); }; - trigger_select_pinned = (e) => { + trigger_select_pinned = () => { this.props.element.trigger("select-pinned", [this.props.open_media]); }; - trigger_jump_to_start = (e) => { + trigger_jump_to_start = () => { this.props.element.trigger("jump-to-start"); }; - trigger_frame_back = (e) => { + trigger_frame_back = () => { this.props.element.trigger("frame-back"); }; - trigger_play = (e) => { + trigger_play = () => { this.props.element.trigger("play"); }; - trigger_pause = (e) => { + trigger_pause = () => { this.props.element.trigger("pause"); }; - trigger_frame_forward = (e) => { + trigger_frame_forward = () => { this.props.element.trigger("frame-forward"); }; - trigger_jump_to_end = (e) => { + trigger_jump_to_end = () => { this.props.element.trigger("jump-to-end"); }; - get_variable_label(variable) { + get_variable_label(variable: number) { if (this.props.variable_aliases[variable] !== undefined) { return this.props.variable_aliases[variable]; } return this.props.metadata["column-names"][variable]; } - + render() { // Define default button style const button_style = "btn-outline-dark"; @@ -232,8 +308,8 @@ class ControlsBar extends React.Component { dropdown.items = dropdown.items.map((item) => { // Don't try to update variable names for keys less than 0, because those are not // real variables. For example, the "None" first item in the Media Set dropdown. - if (item.key >= 0) { - item.name = this.get_variable_label(item.key); + if (item.key !== undefined && Number(item.key) >= 0) { + item.name = this.get_variable_label(Number(item.key)); } return item; }); @@ -242,7 +318,10 @@ class ControlsBar extends React.Component { // If we have xy_pairs, move them to the bottom of the x and y dropdowns if (this.props.xy_pairs_items.length > 0) { - const move_xy_pairs = (items) => { + const move_xy_pairs = (items: IDropdownItems[] | undefined) => { + if (items === undefined) { + return; + } items.push({ type: "divider" }); items.push({ type: "header", name: "XY Pair" }); this.props.xy_pairs_indexes.forEach((index) => { @@ -251,8 +330,8 @@ class ControlsBar extends React.Component { }); }; - let x_items = _.find(aliased_dropdowns, { id: "x-axis-dropdown" }).items; - let y_items = _.find(aliased_dropdowns, { id: "y-axis-dropdown" }).items; + let x_items = _.find(aliased_dropdowns, { id: "x-axis-dropdown" })?.items; + let y_items = _.find(aliased_dropdowns, { id: "y-axis-dropdown" })?.items; move_xy_pairs(x_items); move_xy_pairs(y_items); } @@ -300,7 +379,6 @@ class ControlsBar extends React.Component { trigger={dropdown.trigger} selected={this.props[dropdown.state_label]} set_selected={this.set_selected} - dispatch={dropdown.dispatch} /> ); } @@ -494,9 +572,9 @@ class ControlsBar extends React.Component { } } -const mapStateToProps = (state, ownProps) => { - let xy_pairs_indexes = []; - let xy_pairs_items = []; +const mapStateToProps = (state: RootState, ownProps) => { + let xy_pairs_indexes: number[] = []; + let xy_pairs_items: { key: string; name: string }[] = []; state.derived.xy_pairs.forEach((xy_pair) => { xy_pairs_indexes.push(xy_pair.x); xy_pairs_indexes.push(xy_pair.y); @@ -515,6 +593,7 @@ const mapStateToProps = (state, ownProps) => { v_index: state.v_index, media_index: state.media_index, media_columns: state.derived.media_columns, + rating_variables: state.derived.rating_variables, open_media: state.open_media, variable_aliases: state.derived.variableAliases, active_filters: state.active_filters, @@ -528,6 +607,7 @@ const mapStateToProps = (state, ownProps) => { colormap: state.colormap, show_histogram: state.scatterplot.show_histogram, auto_scale: state.scatterplot.auto_scale, + metadata: state.derived.table_metadata, }; }; @@ -547,4 +627,4 @@ export default connect( // adding a ref to the connected wrapper component will actually return the instance of the wrapped component. // https://react-redux.js.org/api/connect#forwardref-boolean { forwardRef: true }, -)(ControlsBar); +)(PSControlsBar); diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js index 830233bad..927354a7b 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js @@ -132,9 +132,7 @@ $.widget("parameter_image.controls", { aid={self.options.aid} model={self.options.model} model_name={self.options.model_name} - metadata={self.options.metadata} indices={self.options.indices} - rating_variables={self.options.rating_variables} video_sync={self.options["video-sync"]} /> ); @@ -154,8 +152,8 @@ $.widget("parameter_image.controls", { }, _setOption: function (key, value) { - var self = this; - //console.log("parameter_image.variableswitcher._setOption()", key, value); - this.options[key] = value; + // var self = this; + // console.log("parameter_image.variableswitcher._setOption()", key, value); + // this.options[key] = value; }, }); diff --git a/web-server/plugins/slycat-parameter-image/js/store.ts b/web-server/plugins/slycat-parameter-image/js/store.ts index de6e944e6..667007917 100644 --- a/web-server/plugins/slycat-parameter-image/js/store.ts +++ b/web-server/plugins/slycat-parameter-image/js/store.ts @@ -28,13 +28,13 @@ export type AxesVariablesType = { }; export type VariableRangesType = { - [key: number]: { + [key: string]: { min: number; max: number; }; }; -type VariableAliasesType = { +export type VariableAliasesType = { [key: string]: string; }; @@ -49,7 +49,7 @@ export type ValuesType = | Array | Float64Array; -type XYPairsType = { +export type XYPairsType = { x: number; y: number; label: string; @@ -64,6 +64,7 @@ export type DerivedStateType = { variableAliases: VariableAliasesType; mediaValues: string[]; media_columns: number[]; + rating_variables: number[]; xy_pairs: XYPairsType; // ToDo: Add more specific types for these three_d_colorby_range: {}; @@ -79,6 +80,31 @@ export type TableMetadataType = { "column-types": ColumnTypesType[]; }; +export type OpenMediaType = { + index: number; + media_index: number; + uri: string; + uid: string; + x: number; + y: number; + relx: number; + rely: number; + width: number; + height: number; + current_frame: boolean; + ratio: string; + video?: boolean; + playing?: boolean; + threeD?: boolean; +}[]; + +// Currently we are not storing any details of the filters +// We are just using an empty objects for the type to +// determine how many active filters are there. +// In the future we need to expand this when we convert +// the filter manager to React. +export type ActiveFiltersType = {}[]; + export type RootState = { fontSize: number; fontFamily: string; @@ -102,10 +128,10 @@ export type RootState = { three_d_colorvars: Record; three_d_variable_data_ranges: Record; three_d_variable_user_ranges: Record; - open_media: any[]; + open_media: OpenMediaType; closed_media: any[]; currentFrame: Record; - active_filters: any[]; + active_filters: ActiveFiltersType; sync_scaling: boolean; sync_threeD_colorvar: boolean; x_index: number; @@ -115,6 +141,7 @@ export type RootState = { [SCATTERPLOT_SLICE_NAME]: ScatterplotState; [DATA_SLICE_NAME]: DataState; derived: DerivedStateType; + media_index: number; }; export const initialState: RootState = { @@ -145,15 +172,13 @@ export const initialState: RootState = { closed_media: [], currentFrame: {}, active_filters: [], - hidden_simulations: [], - manually_hidden_simulations: [], sync_scaling: true, sync_threeD_colorvar: true, - selected_simulations: [], x_index: 0, y_index: 1, v_index: 1, video_sync_time: 0, + media_index: -1, [SCATTERPLOT_SLICE_NAME]: { ...scatterplotInitialState }, [DATA_SLICE_NAME]: { ...dataInitialState }, derived: { @@ -165,6 +190,7 @@ export const initialState: RootState = { three_d_colorby_range: {}, three_d_colorby_legends: {}, media_columns: [], + rating_variables: [], xy_pairs: [], table_metadata: { "row-count": 0, diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index b01da6a3f..8eee61859 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -432,6 +432,7 @@ $(document).ready(function () { derived: { variableAliases: variable_aliases, media_columns: image_columns, + rating_variables: rating_columns, xy_pairs: xy_pairs, // Set "embed" to true if the "embed" query parameter is present embed: URI(window.location).query(true).embed !== undefined, From 73bb2102cef93f4ed5f5b0d1f8565bd480494470 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 14 Aug 2024 12:42:35 +0200 Subject: [PATCH 21/46] refactor: move more controls code into react component --- .../js/Components/PSControlsBar.tsx | 127 ++++++++++++++---- .../slycat-parameter-image/js/actions.js | 5 + .../js/parameter-controls.js | 112 +-------------- .../slycat-parameter-image/js/reducers.js | 6 + .../slycat-parameter-image/js/store.ts | 4 +- .../plugins/slycat-parameter-image/js/ui.js | 74 ++-------- 6 files changed, 136 insertions(+), 192 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index f07c316ac..4d9c61f84 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -49,22 +49,21 @@ interface PSControlsBarAxesVariablesType { } interface PSControlsBarProps { + store: any; auto_scale: boolean; - video_sync: boolean; variableRanges: VariableRangesType; active_filters: ActiveFiltersType; element: JQuery; selected_simulations: number[]; open_media: OpenMediaType; variable_aliases: VariableAliasesType; - dropdowns: PSControlsBarDropdownsType[]; xy_pairs_items: { key: string; name: string }[]; xy_pairs_indexes: number[]; show_histogram: boolean; metadata: TableMetadataType; xy_pair_selected: string; model: any; - axes_variables: PSControlsBarAxesVariablesType[]; + axes_variables: number[]; sync_scaling: boolean; indices: Int32Array; rating_variables: number[]; @@ -73,10 +72,14 @@ interface PSControlsBarProps { hidden_simulations: number[]; aid: string; mid: string; - pid: string; model_name: string; + video_sync: boolean; video_sync_time: number; colormap: string; + x_variables: number[]; + y_variables: number[]; + color_variables: number[]; + image_variables: number[]; x_index: number; y_index: number; v_index: number; @@ -298,13 +301,93 @@ class PSControlsBar extends React.Component { + const aliased_dropdowns = _.cloneDeep(dropdowns_data).map((dropdown) => { dropdown.items = dropdown.items.map((item) => { // Don't try to update variable names for keys less than 0, because those are not // real variables. For example, the "None" first item in the Media Set dropdown. @@ -440,7 +523,7 @@ class PSControlsBar extends React.Component + @@ -464,7 +547,7 @@ class PSControlsBar extends React.Component @@ -510,7 +593,7 @@ class PSControlsBar extends React.Component @@ -603,6 +686,7 @@ const mapStateToProps = (state: RootState, ownProps) => { xy_pairs_indexes: xy_pairs_indexes, xy_pair_selected: xy_pair_selected, hidden_simulations: state.data.hidden_simulations, + video_sync: state.video_sync, video_sync_time: state.video_sync_time, colormap: state.colormap, show_histogram: state.scatterplot.show_histogram, @@ -611,20 +695,11 @@ const mapStateToProps = (state: RootState, ownProps) => { }; }; -export default connect( - mapStateToProps, - { - toggleSyncScaling, - toggleSyncThreeDColorvar, - setVideoSyncTime, - setColormap, - toggleShowHistogram, - toggleAutoScale, - }, - null, - // Before fully convering to React and Redux, we need a reference to this - // ControlsBar component so we can set its state from outside React. This option makes it so that - // adding a ref to the connected wrapper component will actually return the instance of the wrapped component. - // https://react-redux.js.org/api/connect#forwardref-boolean - { forwardRef: true }, -)(PSControlsBar); +export default connect(mapStateToProps, { + toggleSyncScaling, + toggleSyncThreeDColorvar, + setVideoSyncTime, + setColormap, + toggleShowHistogram, + toggleAutoScale, +})(PSControlsBar); diff --git a/web-server/plugins/slycat-parameter-image/js/actions.js b/web-server/plugins/slycat-parameter-image/js/actions.js index adb78f08b..390293eba 100644 --- a/web-server/plugins/slycat-parameter-image/js/actions.js +++ b/web-server/plugins/slycat-parameter-image/js/actions.js @@ -40,6 +40,7 @@ export const TOGGLE_SYNC_THREE_D_COLORVAR = "TOGGLE_SYNC_THREE_D_COLORVAR"; export const SET_USER_ROLE = "SET_USER_ROLE"; export const SET_TABLE_STATISTICS = "SET_TABLE_STATISTICS"; export const SET_TABLE_METADATA = "SET_TABLE_METADATA"; +export const SET_VIDEO_SYNC = "SET_VIDEO_SYNC"; export const SET_VIDEO_SYNC_TIME = "SET_VIDEO_SYNC_TIME"; export const SET_SCATTERPLOT_MARGIN = "SET_SCATTERPLOT_MARGIN"; export const SET_COLORMAP = "SET_COLORMAP"; @@ -313,6 +314,10 @@ export function setTableMetadata(table_metadata) { return { type: SET_TABLE_METADATA, table_metadata }; } +export function setVideoSync(video_sync) { + return { type: SET_VIDEO_SYNC, video_sync }; +} + export function setVideoSyncTime(video_sync_time) { return { type: SET_VIDEO_SYNC_TIME, video_sync_time }; } diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js index 927354a7b..158ddd21f 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js @@ -15,125 +15,31 @@ $.widget("parameter_image.controls", { model_name: null, model: null, aid: null, - metadata: null, - table_statistics: null, - "x-variable": null, - "y-variable": null, - "image-variable": null, - "color-variable": null, x_variables: [], y_variables: [], axes_variables: [], image_variables: [], color_variables: [], - rating_variables: [], - category_variables: [], - selection: [], indices: [], - "video-sync": false, - "video-sync-time": 0, }, _create: function () { var self = this; - const x_axis_dropdown_items = []; - for (let x_variable of this.options.x_variables) { - x_axis_dropdown_items.push({ - key: x_variable, - name: self.options.metadata["column-names"][x_variable], - }); - } - - const y_axis_dropdown_items = []; - for (let y_variable of this.options.y_variables) { - y_axis_dropdown_items.push({ - key: y_variable, - name: self.options.metadata["column-names"][y_variable], - }); - } - - const axes_items = []; - for (let axes_variable of this.options.axes_variables) { - axes_items.push({ - key: axes_variable, - name: self.options.metadata["column-names"][axes_variable], - }); - } - - const color_variable_dropdown_items = []; - for (let color_variable of this.options.color_variables) { - color_variable_dropdown_items.push({ - key: color_variable, - name: self.options.metadata["column-names"][color_variable], - }); - } - - const media_variable_dropdown_items = []; - media_variable_dropdown_items.push({ key: -1, name: "None" }); - for (let media_variable of this.options.image_variables) { - media_variable_dropdown_items.push({ - key: media_variable, - name: self.options.metadata["column-names"][media_variable], - }); - } - - const dropdowns = [ - { - id: "x-axis-dropdown", - label: "X", - title: "Change X Axis Variable", - state_label: "x_index", - trigger: "x-selection-changed", - items: x_axis_dropdown_items, - selected: self.options["x-variable"], - }, - { - id: "y-axis-dropdown", - label: "Y", - title: "Change Y Axis Variable", - state_label: "y_index", - trigger: "y-selection-changed", - items: y_axis_dropdown_items, - selected: self.options["y-variable"], - }, - { - id: "color-dropdown", - label: "Point Color", - title: "Change Point Color", - state_label: "v_index", - trigger: "color-selection-changed", - items: color_variable_dropdown_items, - selected: self.options["color-variable"], - }, - { - id: "image-dropdown", - label: "Media", - title: "Change Media Set Variable", - state_label: "media_index", - trigger: "images-selection-changed", - items: media_variable_dropdown_items, - selected: self.options["image-variable"], - }, - ]; - - const controls_bar_ref = React.createRef(); - const controls_bar = ( ); const react_controls_root = createRoot(document.getElementById("react-controls")); @@ -151,9 +57,5 @@ $.widget("parameter_image.controls", { }); }, - _setOption: function (key, value) { - // var self = this; - // console.log("parameter_image.variableswitcher._setOption()", key, value); - // this.options[key] = value; - }, + _setOption: function (key, value) {}, }); diff --git a/web-server/plugins/slycat-parameter-image/js/reducers.js b/web-server/plugins/slycat-parameter-image/js/reducers.js index 3ade0de46..e28ddfd57 100644 --- a/web-server/plugins/slycat-parameter-image/js/reducers.js +++ b/web-server/plugins/slycat-parameter-image/js/reducers.js @@ -41,6 +41,7 @@ import { SET_USER_ROLE, SET_TABLE_STATISTICS, SET_TABLE_METADATA, + SET_VIDEO_SYNC, SET_VIDEO_SYNC_TIME, SET_SCATTERPLOT_MARGIN, SET_COLORMAP, @@ -534,6 +535,11 @@ export default function ps_reducer(state = initialState, action) { }, }); + case SET_VIDEO_SYNC: + return Object.assign({}, state, { + video_sync: action.video_sync, + }); + case SET_VIDEO_SYNC_TIME: return Object.assign({}, state, { video_sync_time: action.video_sync_time, diff --git a/web-server/plugins/slycat-parameter-image/js/store.ts b/web-server/plugins/slycat-parameter-image/js/store.ts index 667007917..b33d2ac2f 100644 --- a/web-server/plugins/slycat-parameter-image/js/store.ts +++ b/web-server/plugins/slycat-parameter-image/js/store.ts @@ -101,7 +101,7 @@ export type OpenMediaType = { // Currently we are not storing any details of the filters // We are just using an empty objects for the type to // determine how many active filters are there. -// In the future we need to expand this when we convert +// In the future we need to expand this when we convert // the filter manager to React. export type ActiveFiltersType = {}[]; @@ -137,6 +137,7 @@ export type RootState = { x_index: number; y_index: number; v_index: number; + video_sync: boolean; video_sync_time: number; [SCATTERPLOT_SLICE_NAME]: ScatterplotState; [DATA_SLICE_NAME]: DataState; @@ -177,6 +178,7 @@ export const initialState: RootState = { x_index: 0, y_index: 1, v_index: 1, + video_sync: false, video_sync_time: 0, media_index: -1, [SCATTERPLOT_SLICE_NAME]: { ...scatterplotInitialState }, diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 8eee61859..47fdf64ce 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -73,6 +73,7 @@ import { setUserRole, setTableStatistics, setTableMetadata, + setVideoSync, setVideoSyncTime, } from "./actions"; @@ -410,7 +411,8 @@ $(document).ready(function () { const legacyBookmarkState = { colormap: bookmark["colormap"], open_media: bookmarked_open_media, - video_sync_time: bookmark["video_sync_time"], + video_sync: bookmark["video-sync"], + video_sync_time: bookmark["video-sync-time"], x_index: x_index, y_index: y_index, v_index: v_index, @@ -1096,30 +1098,19 @@ $(document).ready(function () { bookmark && table_metadata && image_columns !== null && - rating_columns != null && - category_columns != null && - x_index != null && - y_index != null && - images_index !== null && - selected_simulations != null && - hidden_simulations != null && + x_index !== null && + y_index !== null && + selected_simulations !== null && + hidden_simulations !== null && indices && - (open_images !== null) & (video_sync !== null) && - video_sync_time !== null && - threeD_sync !== null && - window.store !== undefined && - table_statistics + window.store !== undefined ) { controls_ready = true; filter_manager.notify_controls_ready(); - var numeric_variables = []; var axes_variables = []; var color_variables = []; for (var i = 0; i < table_metadata["column-count"]; i++) { - if (table_metadata["column-types"][i] != "string") { - numeric_variables.push(i); - } if (image_columns.indexOf(i) == -1 && table_metadata["column-count"] - 1 > i) { axes_variables.push(i); } @@ -1128,37 +1119,17 @@ $(document).ready(function () { } } - var color_variable = table_metadata["column-count"] - 1; - if ("variable-selection" in bookmark) { - color_variable = [bookmark["variable-selection"]]; - } - $("#controls").controls({ mid: model_id, model: model, model_name: window.model_name, aid: "data-table", - metadata: table_metadata, - table_statistics: table_statistics, - // clusters : clusters, x_variables: axes_variables, y_variables: axes_variables, axes_variables: axes_variables, image_variables: image_columns, color_variables: color_variables, - rating_variables: rating_columns, - category_variables: category_columns, - selection: selected_simulations, - // cluster_index : cluster_index, - "x-variable": x_index, - "y-variable": y_index, - "image-variable": images_index, - "color-variable": color_variable, - hidden_simulations: hidden_simulations, indices: indices, - "video-sync": video_sync, - "video-sync-time": video_sync_time, - threeD_sync: threeD_sync, }); // Changing the xypair selection trigger change of x and y variables... @@ -1172,20 +1143,6 @@ $(document).ready(function () { $("#controls").controls("option", "x-variable", xy.x); $("#controls").controls("option", "y-variable", xy.y); }); - // Changing the x variable updates the controls ... - $("#table").bind("x-selection-changed", function (event, variable) { - $("#controls").controls("option", "x-variable", variable); - }); - - // Changing the y variable updates the controls ... - $("#table").bind("y-selection-changed", function (event, variable) { - $("#controls").controls("option", "y-variable", variable); - }); - - // Changing the image variable updates the controls ... - $("#table").bind("images-selection-changed", function (event, variable) { - $("#controls").controls("option", "image-variable", variable); - }); $("#controls").bind("update_axes_ranges", function () { // console.log(`variable-ranges-changed`); @@ -1254,14 +1211,6 @@ $(document).ready(function () { } }); - // Log changes to the cluster variable ... - // $("#controls").bind("cluster-selection-changed", function(event, variable) - // { - // variable = parseInt(variable); - // cluster_selection_changed(variable); - // update_dendrogram(variable); - // }); - // Log changes to the x variable ... $("#controls").bind("x-selection-changed", function (event, variable) { x_selection_changed(variable); @@ -1727,7 +1676,9 @@ $(document).ready(function () { if (hidden_simulations.length > 0) { update_current_colorscale(); $("#table").table("option", "colorscale", colorscale); - // TODO this will result in 2 updates to canvas, one to redraw points accourding to scale and another to color them according to new colorscale. Need to combine this to a single update when converting to canvas. + // TODO this will result in 2 updates to canvas, one to redraw points accourding to scale + // and another to color them according to new colorscale. Need to combine this to a single + // update when converting to canvas. $("#scatterplot").scatterplot("option", { colorscale: colorscale, "auto-scale": auto_scale }); } else { $("#scatterplot").scatterplot("option", "auto-scale", auto_scale); @@ -1746,6 +1697,9 @@ $(document).ready(function () { url: api_root + "events/models/" + model_id + "/video-sync/" + video_sync, }); bookmarker.updateState({ "video-sync": video_sync }); + + // Dispatch update to video_sync in Redux + window.store.dispatch(setVideoSync(video_sync_value)); } function video_sync_time_changed(video_sync_time_value) { From 6f9fbabd2d50b72b8914e4cca1c523e7f7181131 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 4 Sep 2024 15:29:20 -0700 Subject: [PATCH 22/46] refactor: continue work on react conversion of controls --- .../js/Components/PSControlsBar.tsx | 10 +- .../plugins/slycat-parameter-image/js/ui.js | 91 +++++++++---------- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 4d9c61f84..a8fff161f 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -18,6 +18,7 @@ import { toggleSyncThreeDColorvar, setVideoSyncTime, setColormap, + setXIndex, } from "../actions"; import ControlsDropdownColor from "components/ControlsDropdownColor"; import slycat_color_maps from "js/slycat-color-maps"; @@ -41,6 +42,7 @@ interface PSControlsBarDropdownsType { trigger: string; items: IDropdownItems[]; selected: number; + set_selected?: SetSelectedFunction; } interface PSControlsBarAxesVariablesType { @@ -89,6 +91,7 @@ interface PSControlsBarProps { toggleSyncScaling: () => void; toggleSyncThreeDColorvar: () => void; setColormap: (colormap: string) => void; + setXIndex: (value: number) => void; } interface PSControlsBarState { @@ -356,6 +359,10 @@ class PSControlsBar extends React.Component { + this.props.setXIndex(Number(key)); + this.set_selected(key, state_label, trigger, e, props); + }, }, { id: "y-axis-dropdown", @@ -461,7 +468,7 @@ class PSControlsBar extends React.Component ); } @@ -700,6 +707,7 @@ export default connect(mapStateToProps, { toggleSyncThreeDColorvar, setVideoSyncTime, setColormap, + setXIndex, toggleShowHistogram, toggleAutoScale, })(PSControlsBar); diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 47fdf64ce..5868b477d 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -677,10 +677,14 @@ $(document).ready(function () { if (table_metadata["column-types"][i] != "string") x_y_variables.push(i); } - x_index = x_y_variables[0]; - y_index = x_y_variables[1 % x_y_variables.length]; - if ("x-selection" in bookmark) x_index = Number(bookmark["x-selection"]); - if ("y-selection" in bookmark) y_index = Number(bookmark["y-selection"]); + // Set x and y variables accoding to what's in the bookmarked redux state, + // fall back to bookmarked legacy state, then to a sensible default. + x_index = Number(bookmark.state?.x_index ?? bookmark["x-selection"] ?? x_y_variables[0]); + y_index = Number( + bookmark.state?.y_index ?? + bookmark["y-selection"] ?? + x_y_variables[1 % x_y_variables.length], + ); // Wait until the redux store has been created createReduxStorePromise.then(() => { @@ -946,21 +950,6 @@ $(document).ready(function () { $("#controls").controls("option", "selection", selection); }); - // Changing the x variable updates the table ... - $("#controls").bind("x-selection-changed", function (event, variable) { - $("#table").table("option", "x-variable", variable); - }); - - // Changing the y variable updates the table ... - $("#controls").bind("y-selection-changed", function (event, variable) { - $("#table").table("option", "y-variable", variable); - }); - - // Changing the image variable updates the table ... - $("#controls").bind("images-selection-changed", function (event, variable) { - $("#table").table("option", "image-variable", variable); - }); - // Handle table variable selection ... $("#table").bind("variable-selection-changed", function (event, selection) { // Changing the table variable updates the controls ... @@ -969,15 +958,6 @@ $(document).ready(function () { // Handle changes to the table variable selection ... handle_color_variable_change(selection[0]); }); - - // Handle color variable selection ... - $("#controls").bind("color-selection-changed", function (event, variable) { - // Changing the color variable updates the table ... - $("#table").table("option", "variable-selection", [Number(variable)]); - - // Handle changes to the color variable ... - handle_color_variable_change(variable); - }); } } @@ -1058,25 +1038,16 @@ $(document).ready(function () { $("#table").bind("x-selection-changed", function (event, variable) { update_scatterplot_x(variable); }); - $("#controls").bind("x-selection-changed", function (event, variable) { - update_scatterplot_x(variable); - }); // Changing the y variable updates the scatterplot ... $("#table").bind("y-selection-changed", function (event, variable) { update_scatterplot_y(variable); }); - $("#controls").bind("y-selection-changed", function (event, variable) { - update_scatterplot_y(variable); - }); // Changing the images variable updates the scatterplot ... $("#table").bind("images-selection-changed", function (event, variable) { handle_image_variable_change(variable); }); - $("#controls").bind("images-selection-changed", function (event, variable) { - handle_image_variable_change(variable); - }); // Changing the video sync time logs it ... $("#scatterplot").bind("video-sync-time", function (event, video_sync_time) { @@ -1132,6 +1103,42 @@ $(document).ready(function () { indices: indices, }); + // Changing the x variable ... + $("#controls").bind("x-selection-changed", function (event, variable) { + // Update table + $("#table").table("option", "x-variable", variable); + // Update scatterplot + update_scatterplot_x(variable); + // Log changes to the x variable ... + x_selection_changed(variable); + }); + + // Changing the y variable ... + $("#controls").bind("y-selection-changed", function (event, variable) { + // Update table + $("#table").table("option", "y-variable", variable); + // Update scatterplot + update_scatterplot_y(variable); + // Log changes to the y variable ... + y_selection_changed(variable); + }); + + // Changing the image variable ... + $("#controls").bind("images-selection-changed", function (event, variable) { + // Update table + $("#table").table("option", "image-variable", variable); + // Update scatterplot + handle_image_variable_change(variable); + }); + + // Handle color variable selection ... + $("#controls").bind("color-selection-changed", function (event, variable) { + // Changing the color variable updates the table ... + $("#table").table("option", "variable-selection", [Number(variable)]); + // Handle changes to the color variable ... + handle_color_variable_change(variable); + }); + // Changing the xypair selection trigger change of x and y variables... $("#controls").bind("xypair_selection_changed", function (event, xy_pair) { // xy_pair is JSON.stringify'ed, so need to parse it first @@ -1211,16 +1218,6 @@ $(document).ready(function () { } }); - // Log changes to the x variable ... - $("#controls").bind("x-selection-changed", function (event, variable) { - x_selection_changed(variable); - }); - - // Log changes to the y variable ... - $("#controls").bind("y-selection-changed", function (event, variable) { - y_selection_changed(variable); - }); - // Changing the video sync option updates the scatterplot and logs it ... $("#controls").bind("video-sync", function (event, video_sync) { video_sync_option_changed(video_sync); From 615f5b38da3e98d8ef8f7a32ddb434833f6aca67 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 17 Sep 2024 15:24:06 -0700 Subject: [PATCH 23/46] feat: set state for x, y, v, color, media, and xypair changes --- .../js/Components/PSControlsBar.tsx | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index a8fff161f..639e86b7f 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -11,7 +11,6 @@ import ControlsButtonUpdateTable from "./ControlsButtonUpdateTable.jsx"; import ControlsButtonDownloadDataTable from "components/ControlsButtonDownloadDataTable"; import ControlsButtonVarOptions from "./ControlsButtonVarOptions"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; -import _ from "lodash"; import $ from "jquery"; import { toggleSyncScaling, @@ -19,6 +18,9 @@ import { setVideoSyncTime, setColormap, setXIndex, + setYIndex, + setVIndex, + setMediaIndex, } from "../actions"; import ControlsDropdownColor from "components/ControlsDropdownColor"; import slycat_color_maps from "js/slycat-color-maps"; @@ -92,6 +94,9 @@ interface PSControlsBarProps { toggleSyncThreeDColorvar: () => void; setColormap: (colormap: string) => void; setXIndex: (value: number) => void; + setYIndex: (value: number) => void; + setVIndex: (value: number) => void; + setMediaIndex: (value: number) => void; } interface PSControlsBarState { @@ -372,6 +377,10 @@ class PSControlsBar extends React.Component { + this.props.setYIndex(Number(key)); + this.set_selected(key, state_label, trigger, e, props); + }, }, { id: "color-dropdown", @@ -381,6 +390,10 @@ class PSControlsBar extends React.Component { + this.props.setVIndex(Number(key)); + this.set_selected(key, state_label, trigger, e, props); + }, }, { id: "image-dropdown", @@ -390,6 +403,10 @@ class PSControlsBar extends React.Component { + this.props.setMediaIndex(Number(key)); + this.set_selected(key, state_label, trigger, e, props); + }, }, ]; @@ -544,9 +561,30 @@ class PSControlsBar extends React.Component - this.props.element.trigger(trigger, key) - } + set_selected={(key, state_label, trigger, e, props) => { + // Check if key is a string, if so, parse it to get the x and y values + if (typeof key === "string") { + try { + const parsed_key = JSON.parse(key); + if ( + parsed_key && + typeof parsed_key === "object" && + "x" in parsed_key && + "y" in parsed_key + ) { + this.props.setXIndex(Number(parsed_key.x)); + this.props.setYIndex(Number(parsed_key.y)); + this.set_selected(key, state_label, trigger, e, props); + } else { + console.error("Invalid key format:", key); + } + } catch (error) { + console.error("Error parsing key:", error); + } + } else { + console.error("Key is not a string:", key); + } + }} button_style={button_style} /> )} @@ -708,6 +746,9 @@ export default connect(mapStateToProps, { setVideoSyncTime, setColormap, setXIndex, + setYIndex, + setVIndex, + setMediaIndex, toggleShowHistogram, toggleAutoScale, })(PSControlsBar); From f4136e4bc065ee04e6002f8ffaf38c5dda411cbb Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 17 Sep 2024 15:39:00 -0700 Subject: [PATCH 24/46] refactor: fix linting errors --- .../slycat-parameter-image/js/Components/PSControlsBar.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 639e86b7f..c68bf79c2 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -35,6 +35,7 @@ import { TableMetadataType, } from "../store"; import { IDropdownItems, SetSelectedFunction } from "components/ControlsDropdown"; +import _ from "lodash"; interface PSControlsBarDropdownsType { id: string; @@ -97,6 +98,7 @@ interface PSControlsBarProps { setYIndex: (value: number) => void; setVIndex: (value: number) => void; setMediaIndex: (value: number) => void; + [key: string]: any; } interface PSControlsBarState { @@ -599,6 +601,7 @@ class PSControlsBar extends React.Component { +const mapStateToProps = (state: RootState) => { let xy_pairs_indexes: number[] = []; let xy_pairs_items: { key: string; name: string }[] = []; state.derived.xy_pairs.forEach((xy_pair) => { From 1dac97d880a4fe6ffcb6a35fc04caa2d8a1d7f58 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 17 Sep 2024 15:44:09 -0700 Subject: [PATCH 25/46] refactor: remove legacy code --- web-server/plugins/slycat-parameter-image/js/ui.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 5868b477d..500d2ee1d 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -1146,9 +1146,6 @@ $(document).ready(function () { // Trigger x and y selection changes $("#controls").trigger("x-selection-changed", xy.x); $("#controls").trigger("y-selection-changed", xy.y); - // Update x and y variable in controls - $("#controls").controls("option", "x-variable", xy.x); - $("#controls").controls("option", "y-variable", xy.y); }); $("#controls").bind("update_axes_ranges", function () { From 761c60f4d0399c75dbcde58da8aa9aa63eebbae2 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 17 Sep 2024 15:55:04 -0700 Subject: [PATCH 26/46] refactor: move menu height limiting code into react --- .../js/Components/PSControlsBar.tsx | 17 +++++++++++++++++ .../js/parameter-controls.js | 11 ----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index c68bf79c2..6f091de70 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -125,12 +125,29 @@ class PSControlsBar extends React.Component { + $("#controls-pane").on("show.bs.dropdown", function (event) { + // Get all dropdown menus inside this element + let menus = $(".dropdown-menu", this); + // Get the container that holds the model's panes + let container = $(".ui-layout-container").first(); + // Set the max height of each menu to 70px less than the container. + // This prevents the menus from sticking out beyond the page and allows + // them to be scrollable when they are too long. + const containerHeight = container.height(); + if (containerHeight !== undefined) { + menus.css("max-height", `${containerHeight - 70}px`); + } + }); + }; + setAutoScaleTooptip = () => { // console.log(`Initializing popover tooltips. Used for auto scale button.`); diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js index 158ddd21f..bbc71956a 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js @@ -44,17 +44,6 @@ $.widget("parameter_image.controls", { ); const react_controls_root = createRoot(document.getElementById("react-controls")); react_controls_root.render(controls_bar); - - $("#controls-pane").on("show.bs.dropdown", function (event) { - // Get all dropdown menus inside this element - let menus = $(".dropdown-menu", this); - // Get the container that holds the model's panes - let container = $(".ui-layout-container").first(); - // Set the max height of each menu to 70px less than the container. - // This prevents the menus from sticking out beyond the page and allows - // them to be scrollable when they are too long. - menus.css("max-height", container.height() - 70 + "px"); - }); }, _setOption: function (key, value) {}, From 62a45358a9c06bda2be3eec5ff6db7d20ea9cdc0 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 17 Sep 2024 16:04:34 -0700 Subject: [PATCH 27/46] refactor: remove legacy way of setting options in controls --- .../plugins/slycat-parameter-image/js/ui.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 500d2ee1d..36e207e97 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -931,7 +931,7 @@ $(document).ready(function () { y_selection_changed(variable); }); - // Changing the table row selection updates the scatterplot and controls ... + // Changing the table row selection updates the scatterplot... // Log changes to the table row selection ... $("#table").bind("row-selection-changed", function (event, selection) { // The table selection is an array buffer which can't be @@ -941,20 +941,15 @@ $(document).ready(function () { selected_simulations_changed(temp); $("#scatterplot").scatterplot("option", "selection", temp); - $("#controls").controls("option", "selection", temp); }); - // Changing the scatterplot selection updates the table row selection and controls .. + // Changing the scatterplot selection updates the table row selection ... $("#scatterplot").bind("selection-changed", function (event, selection) { $("#table").table("option", "row-selection", selection); - $("#controls").controls("option", "selection", selection); }); // Handle table variable selection ... $("#table").bind("variable-selection-changed", function (event, selection) { - // Changing the table variable updates the controls ... - $("#controls").controls("option", "color-variable", selection[0]); - // Handle changes to the table variable selection ... handle_color_variable_change(selection[0]); }); @@ -1353,8 +1348,6 @@ $(document).ready(function () { let to_select = _.union(pinned_simulations, selected_simulations); selected_simulations_changed(to_select); - $("#scatterplot").scatterplot("option", "selection", to_select); - $("#controls").controls("option", "selection", to_select); $("#table").table("option", "row-selection", to_select); }); @@ -1522,9 +1515,6 @@ $(document).ready(function () { if ($("#scatterplot").data("parameter_image-scatterplot")) $("#scatterplot").scatterplot("option", "hidden_simulations", hidden_simulations); } - - if ($("#controls").data("parameter_image-controls")) - $("#controls").controls("option", "hidden_simulations", hidden_simulations); } function set_custom_color_variable_range() { @@ -1629,7 +1619,6 @@ $(document).ready(function () { // But we do need to let the other non-React components know about the new selection. if (old_selection !== undefined) { $("#scatterplot").scatterplot("option", "selection", _.cloneDeep(selection)); - $("#controls").controls("option", "selection", _.cloneDeep(selection)); $("#table").table("option", "row-selection", _.cloneDeep(selection)); } else { // Dispatch update to selected_simulations in Redux From 0e429da6b405e8dcbbacddbc973c0f0fc0933cfe Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 19 Sep 2024 13:34:43 -0700 Subject: [PATCH 28/46] refactor: move JQuery triggers to Redux dispatch and watch --- web-server/components/ControlsDropdown.tsx | 4 +- .../js/Components/ControlsButtonVarOptions.js | 3 - .../js/Components/PSControlsBar.tsx | 26 ++-- .../js/parameter-image-table.js | 13 +- .../plugins/slycat-parameter-image/js/ui.js | 135 +++++++----------- 5 files changed, 79 insertions(+), 102 deletions(-) diff --git a/web-server/components/ControlsDropdown.tsx b/web-server/components/ControlsDropdown.tsx index d5c2a4bae..9eef53d20 100644 --- a/web-server/components/ControlsDropdown.tsx +++ b/web-server/components/ControlsDropdown.tsx @@ -16,7 +16,7 @@ export interface IDropdownItems { export type SetSelectedFunction = ( key: number | string, state_label: string, - trigger: string, + trigger?: string, e?: React.MouseEvent, props?: Record, ) => void; @@ -26,7 +26,7 @@ interface ControlsDropdownProps { selected: string | number; set_selected: SetSelectedFunction; state_label: string; - trigger: string; + trigger?: string; button_style: string; id: string; title: string; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js index d8c709184..be4bd0647 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonVarOptions.js @@ -104,9 +104,6 @@ class ControlsButtonVarOptions extends React.PureComponent { // Write variable aliases to database if user's role is not 'reader' let self = this; - // Alert other components that axes ranges might have updated - this.props.element.trigger("update_axes_ranges"); - // For users with role 'reader', just close the dialog and stop. if (this.props.userRole == "reader") { $("#" + self.modalId).modal("hide"); diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 6f091de70..428f7cdd2 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -42,7 +42,7 @@ interface PSControlsBarDropdownsType { label: string; title: string; state_label: string; - trigger: string; + trigger?: string; items: IDropdownItems[]; selected: number; set_selected?: SetSelectedFunction; @@ -222,8 +222,17 @@ class PSControlsBar extends React.Component { - // This is the legacy way of letting the rest of non-React components that the state changed. Remove once we are converted to React. - this.props.element.trigger(trigger, key); + // Check if both key and trigger are defined before triggering the event + if (key !== undefined && trigger !== undefined) { + // This is the legacy way of letting the rest of non-React components that the state changed. + //Remove once we are converted to React. + this.props.element.trigger(trigger, key); + } else if (key !== undefined) { + // If key is defined but trigger is not, just log a warning + console.warn(`Trigger not provided for set_selected with key: ${key}`); + } else { + console.error(`Missing key for set_selected`); + } }; set_auto_scale = () => { @@ -380,12 +389,10 @@ class PSControlsBar extends React.Component { this.props.setXIndex(Number(key)); - this.set_selected(key, state_label, trigger, e, props); }, }, { @@ -393,12 +400,10 @@ class PSControlsBar extends React.Component { this.props.setYIndex(Number(key)); - this.set_selected(key, state_label, trigger, e, props); }, }, { @@ -406,12 +411,10 @@ class PSControlsBar extends React.Component { this.props.setVIndex(Number(key)); - this.set_selected(key, state_label, trigger, e, props); }, }, { @@ -419,12 +422,10 @@ class PSControlsBar extends React.Component { this.props.setMediaIndex(Number(key)); - this.set_selected(key, state_label, trigger, e, props); }, }, ]; @@ -577,11 +578,11 @@ class PSControlsBar extends React.Component { // Check if key is a string, if so, parse it to get the x and y values + // and dispatch the values to the redux store if (typeof key === "string") { try { const parsed_key = JSON.parse(key); @@ -593,7 +594,6 @@ class PSControlsBar extends React.Component { window.store.subscribe( watch( @@ -677,7 +682,7 @@ $(document).ready(function () { if (table_metadata["column-types"][i] != "string") x_y_variables.push(i); } - // Set x and y variables accoding to what's in the bookmarked redux state, + // Set x and y variables accoding to what's in the bookmarked redux state, // fall back to bookmarked legacy state, then to a sensible default. x_index = Number(bookmark.state?.x_index ?? bookmark["x-selection"] ?? x_y_variables[0]); y_index = Number( @@ -921,16 +926,6 @@ $(document).ready(function () { variable_sort_changed(variable, order); }); - // Log changes to the x variable ... - $("#table").bind("x-selection-changed", function (event, variable) { - x_selection_changed(variable); - }); - - // Log changes to the y variable ... - $("#table").bind("y-selection-changed", function (event, variable) { - y_selection_changed(variable); - }); - // Changing the table row selection updates the scatterplot... // Log changes to the table row selection ... $("#table").bind("row-selection-changed", function (event, selection) { @@ -947,12 +942,6 @@ $(document).ready(function () { $("#scatterplot").bind("selection-changed", function (event, selection) { $("#table").table("option", "row-selection", selection); }); - - // Handle table variable selection ... - $("#table").bind("variable-selection-changed", function (event, selection) { - // Handle changes to the table variable selection ... - handle_color_variable_change(selection[0]); - }); } } @@ -1098,61 +1087,6 @@ $(document).ready(function () { indices: indices, }); - // Changing the x variable ... - $("#controls").bind("x-selection-changed", function (event, variable) { - // Update table - $("#table").table("option", "x-variable", variable); - // Update scatterplot - update_scatterplot_x(variable); - // Log changes to the x variable ... - x_selection_changed(variable); - }); - - // Changing the y variable ... - $("#controls").bind("y-selection-changed", function (event, variable) { - // Update table - $("#table").table("option", "y-variable", variable); - // Update scatterplot - update_scatterplot_y(variable); - // Log changes to the y variable ... - y_selection_changed(variable); - }); - - // Changing the image variable ... - $("#controls").bind("images-selection-changed", function (event, variable) { - // Update table - $("#table").table("option", "image-variable", variable); - // Update scatterplot - handle_image_variable_change(variable); - }); - - // Handle color variable selection ... - $("#controls").bind("color-selection-changed", function (event, variable) { - // Changing the color variable updates the table ... - $("#table").table("option", "variable-selection", [Number(variable)]); - // Handle changes to the color variable ... - handle_color_variable_change(variable); - }); - - // Changing the xypair selection trigger change of x and y variables... - $("#controls").bind("xypair_selection_changed", function (event, xy_pair) { - // xy_pair is JSON.stringify'ed, so need to parse it first - const xy = JSON.parse(xy_pair); - // Trigger x and y selection changes - $("#controls").trigger("x-selection-changed", xy.x); - $("#controls").trigger("y-selection-changed", xy.y); - }); - - $("#controls").bind("update_axes_ranges", function () { - // console.log(`variable-ranges-changed`); - // Alert scatterplot that it might need to update its axes - $("#scatterplot").scatterplot("update_axes_ranges"); - // Update the color scale - update_current_colorscale(); - $("#table").table("option", "colorscale", colorscale); - $("#scatterplot").scatterplot("option", "colorscale", colorscale); - }); - // Changing the value of a variable updates the database, table, and scatterplot ... $("#controls").bind("set-value", function (event, props) { writeData(props.selection, props.variable, props.value); @@ -1626,19 +1560,32 @@ $(document).ready(function () { } } - function x_selection_changed(variable) { + function x_index_changed(variable) { + // Update legacy table and scatterplot components when x variable changes in Redux. + // These need to be removed when we convert these components to React. + // Update table + $("#table").table("option", "x-variable", variable); + // Update scatterplot + update_scatterplot_x(variable); + + // Log changes to the x variable ... $.ajax({ type: "POST", url: api_root + "events/models/" + model_id + "/select/x/" + variable, }); bookmarker.updateState({ "x-selection": variable }); x_index = Number(variable); - - // Dispatch update to x index in Redux - window.store.dispatch(setXIndex(x_index)); } - function y_selection_changed(variable) { + function y_index_changed(variable) { + // Update legacy table and scatterplot components when y variable changes in Redux. + // These need to be removed when we convert these components to React. + // Update table + $("#table").table("option", "y-variable", variable); + // Update scatterplot + update_scatterplot_y(variable); + + // Log changes to the y variable ... $.ajax({ type: "POST", url: api_root + "events/models/" + model_id + "/select/y/" + variable, @@ -1646,14 +1593,42 @@ $(document).ready(function () { bookmarker.updateState({ "y-selection": variable }); y_index = Number(variable); - // Dispatch update to y index in Redux - window.store.dispatch(setYIndex(y_index)); - // Hide histogram if it's being displayed + // Hide histogram if it's being displayed. + // There is probably a better place to put this. if (window.store.getState().scatterplot.show_histogram) { window.store.dispatch(toggleShowHistogram()); } } + function v_index_changed(variable) { + // Update legacy table and scatterplot components when v variable changes in Redux. + // These need to be removed when we convert these components to React. + // Update table + $("#table").table("option", "variable-selection", [Number(variable)]); + // Handle changes to the color variable ... + handle_color_variable_change(variable); + } + + function media_index_changed(variable) { + // Update legacy table and scatterplot components when media variable changes in Redux. + // These need to be removed when we convert these components to React. + // Update table + $("#table").table("option", "image-variable", variable); + // Update scatterplot + handle_image_variable_change(variable); + } + + function variable_ranges_changed(variable_ranges) { + // Update legacy table and scatterplot components when variable ranges change in Redux. + // These need to be removed when we convert these components to React. + // Alert scatterplot that it might need to update its axes + $("#scatterplot").scatterplot("update_axes_ranges"); + // Update the color scale + update_current_colorscale(); + $("#table").table("option", "colorscale", colorscale); + $("#scatterplot").scatterplot("option", "colorscale", colorscale); + } + function auto_scale_option_changed(auto_scale_value, old_auto_scale_value, objectPath) { auto_scale = auto_scale_value; if (hidden_simulations.length > 0) { From 7a8468e56b3bb12a45a9449d7e51b5113c0c642e Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 19 Sep 2024 14:35:34 -0700 Subject: [PATCH 29/46] refactor: move video_sync out of jquery bind --- .../js/Components/ControlsButtonToggle.tsx | 4 +-- .../js/Components/ControlsThreeD.js | 4 +-- .../js/Components/ControlsVideo.js | 2 +- .../js/Components/PSControlsBar.tsx | 31 +++++++------------ .../plugins/slycat-parameter-image/js/ui.js | 30 +++++++----------- 5 files changed, 27 insertions(+), 44 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonToggle.tsx b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonToggle.tsx index 718ae1f1e..f141660fd 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonToggle.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsButtonToggle.tsx @@ -8,7 +8,7 @@ interface ControlsButtonToggleProps { id: string; title: string; icon: IconProp; - set_active_state(event: React.MouseEvent): void; + toggle_active_state(event: React.MouseEvent): void; } /** @@ -32,7 +32,7 @@ export default class ControlsButtonToggle extends React.PureComponent diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js index 02ade7cc5..b52b597a6 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js @@ -18,7 +18,7 @@ class ControlsThreeD extends React.Component { this.props.updateThreeDColorBy(this.props.currentFrame.uid, key); }; - set_threeD_sync = (e) => { + toggle_threeD_sync = (e) => { this.props.element.trigger("threeD_sync", !window.store.getState().threeD_sync); this.props.toggleThreeDSync(); }; @@ -34,7 +34,7 @@ class ControlsThreeD extends React.Component { title={this.props.threeD_sync ? "Unsync 3D Viewers" : "Sync 3D Viewers"} icon={faCubes} active={this.props.threeD_sync} - set_active_state={this.set_threeD_sync} + toggle_active_state={this.toggle_threeD_sync} button_style={this.props.button_style} /> diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 428f7cdd2..1b2022ef4 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -15,6 +15,7 @@ import $ from "jquery"; import { toggleSyncScaling, toggleSyncThreeDColorvar, + setVideoSync, setVideoSyncTime, setColormap, setXIndex, @@ -101,20 +102,13 @@ interface PSControlsBarProps { [key: string]: any; } -interface PSControlsBarState { - video_sync: boolean; -} - -class PSControlsBar extends React.Component { +class PSControlsBar extends React.Component { autoScalePopoverSelector: string; autoScaleId: string; selection_id: string; scatterplot_id: string; constructor(props: PSControlsBarProps) { super(props); - this.state = { - video_sync: this.props.video_sync, - }; this.scatterplot_id = "scatterplot-controls"; this.selection_id = "selection-controls"; this.autoScaleId = "auto-scale"; @@ -239,12 +233,8 @@ class PSControlsBar extends React.Component { - this.setState((prevState, props) => { - const new_video_sync = !prevState.video_sync; - this.props.element.trigger("video-sync", new_video_sync); - return { video_sync: new_video_sync }; - }); + toggle_video_sync = () => { + this.props.setVideoSync(!this.props.video_sync); }; set_video_sync_time = (value: number) => { @@ -543,12 +533,12 @@ class PSControlsBar extends React.Component @@ -668,8 +658,8 @@ class PSControlsBar extends React.Component { export default connect(mapStateToProps, { toggleSyncScaling, toggleSyncThreeDColorvar, + setVideoSync, setVideoSyncTime, setColormap, setXIndex, diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 00a8db9e4..56bc5de02 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -73,7 +73,6 @@ import { setUserRole, setTableStatistics, setTableMetadata, - setVideoSync, setVideoSyncTime, } from "./actions"; @@ -593,6 +592,7 @@ $(document).ready(function () { { objectPath: "v_index", callback: v_index_changed }, { objectPath: "media_index", callback: media_index_changed }, { objectPath: "variableRanges", callback: variable_ranges_changed }, + { objectPath: "video_sync", callback: video_sync_changed }, ].forEach((subscription) => { window.store.subscribe( watch( @@ -1144,11 +1144,6 @@ $(document).ready(function () { } }); - // Changing the video sync option updates the scatterplot and logs it ... - $("#controls").bind("video-sync", function (event, video_sync) { - video_sync_option_changed(video_sync); - }); - // Changing the 3d sync option updates the scatterplot and logs it ... $("#controls").bind("threeD_sync", function (event, threeD_sync) { threeD_sync_option_changed(threeD_sync); @@ -1629,6 +1624,16 @@ $(document).ready(function () { $("#scatterplot").scatterplot("option", "colorscale", colorscale); } + function video_sync_changed(video_sync_value) { + video_sync = video_sync_value; + $("#scatterplot").scatterplot("option", "video-sync", video_sync); + $.ajax({ + type: "POST", + url: api_root + "events/models/" + model_id + "/video-sync/" + video_sync, + }); + bookmarker.updateState({ "video-sync": video_sync }); + } + function auto_scale_option_changed(auto_scale_value, old_auto_scale_value, objectPath) { auto_scale = auto_scale_value; if (hidden_simulations.length > 0) { @@ -1647,19 +1652,6 @@ $(document).ready(function () { }); } - function video_sync_option_changed(video_sync_value) { - video_sync = video_sync_value; - $("#scatterplot").scatterplot("option", "video-sync", video_sync); - $.ajax({ - type: "POST", - url: api_root + "events/models/" + model_id + "/video-sync/" + video_sync, - }); - bookmarker.updateState({ "video-sync": video_sync }); - - // Dispatch update to video_sync in Redux - window.store.dispatch(setVideoSync(video_sync_value)); - } - function video_sync_time_changed(video_sync_time_value) { video_sync_time = video_sync_time_value; $.ajax({ From 0087dc50c27e30b1f72162c046b1a6985cd58781 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 19 Sep 2024 17:16:59 -0700 Subject: [PATCH 30/46] fix: crash when initially setting current frame to a 3d frame --- .../slycat-parameter-image/js/Components/ControlsThreeD.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js index b52b597a6..f45725dd4 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js @@ -82,7 +82,7 @@ const mapStateToProps = (state) => { // Sort Color By options. // List points data first, then cell data. // Within each, list the items alphabetically. - color_by_items = state.derived.three_d_colorby_options[state.currentFrame.uri]; + color_by_items = _.cloneDeep(state.derived.three_d_colorby_options[state.currentFrame.uri]); // Compare using English locale const locale = "en"; // Make it case and accent insensitive. From 2dc7bcea3ef9f36be3cbb990c649324f3b5479a6 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 19 Sep 2024 17:17:31 -0700 Subject: [PATCH 31/46] refactor: clone passed objects just to be safe --- web-server/plugins/slycat-parameter-image/js/reducers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/reducers.js b/web-server/plugins/slycat-parameter-image/js/reducers.js index e28ddfd57..54db504fd 100644 --- a/web-server/plugins/slycat-parameter-image/js/reducers.js +++ b/web-server/plugins/slycat-parameter-image/js/reducers.js @@ -124,7 +124,7 @@ export default function ps_reducer(state = initialState, action) { case CHANGE_CURRENT_FRAME: return Object.assign({}, state, { - currentFrame: action.currentFrame, + currentFrame: _.cloneDeep(action.currentFrame), }); case CHANGE_THREED_COLORMAP: @@ -148,7 +148,7 @@ export default function ps_reducer(state = initialState, action) { ...state.derived, three_d_colorby_options: { ...state.derived.three_d_colorby_options, - [action.uri]: action.options, + [action.uri]: _.cloneDeep(action.options), }, }, }); From 69c6a8ca55d9783e79e144071771c518e6fedc83 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Thu, 19 Sep 2024 17:18:19 -0700 Subject: [PATCH 32/46] feat: wait for table and scatterplot to be ready before initializing redux event handlers --- .../plugins/slycat-parameter-image/js/ui.js | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 56bc5de02..fe6a777c2 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -181,6 +181,14 @@ $(document).ready(function () { max: undefined, }; + let tableReadyPromise = new Promise((resolve) => { + window.resolveTableReady = resolve; + }); + + let scatterplotReadyPromise = new Promise((resolve) => { + window.resolveScatterplotReady = resolve; + }); + ////////////////////////////////////////////////////////////////////////////////////////// // Setup page layout. ////////////////////////////////////////////////////////////////////////////////////////// @@ -582,27 +590,34 @@ $(document).ready(function () { // Wait until the redux store has been created createReduxStorePromise.then(() => { - // Subscribing to changes in various states - [ - { objectPath: "colormap", callback: selected_colormap_changed }, - { objectPath: "scatterplot.auto_scale", callback: auto_scale_option_changed }, - { objectPath: "data.selected_simulations", callback: selected_simulations_changed }, - { objectPath: "x_index", callback: x_index_changed }, - { objectPath: "y_index", callback: y_index_changed }, - { objectPath: "v_index", callback: v_index_changed }, - { objectPath: "media_index", callback: media_index_changed }, - { objectPath: "variableRanges", callback: variable_ranges_changed }, - { objectPath: "video_sync", callback: video_sync_changed }, - ].forEach((subscription) => { - window.store.subscribe( - watch( - window.store.getState, - subscription.objectPath, - _.isEqual, - )((newVal, oldVal, objectPath) => { - subscription.callback(newVal, oldVal, objectPath); - }), - ); + // Wait for the table and scatterplot to be ready, + // otherwise jquery complains about some of the callbacks + // setting table and scatterplot options before they are ready. + // Once we get rid of the scatterplot and table jquery widgets, + // we can get rid of this. + Promise.all([tableReadyPromise, scatterplotReadyPromise]).then(() => { + // Subscribing to changes in various states + [ + { objectPath: "colormap", callback: selected_colormap_changed }, + { objectPath: "scatterplot.auto_scale", callback: auto_scale_option_changed }, + { objectPath: "data.selected_simulations", callback: selected_simulations_changed }, + { objectPath: "x_index", callback: x_index_changed }, + { objectPath: "y_index", callback: y_index_changed }, + { objectPath: "v_index", callback: v_index_changed }, + { objectPath: "media_index", callback: media_index_changed }, + { objectPath: "variableRanges", callback: variable_ranges_changed }, + { objectPath: "video_sync", callback: video_sync_changed }, + ].forEach((subscription) => { + window.store.subscribe( + watch( + window.store.getState, + subscription.objectPath, + _.isEqual, + )((newVal, oldVal, objectPath) => { + subscription.callback(newVal, oldVal, objectPath); + }), + ); + }); }); // Set size of scatterplot pane in Redux @@ -938,6 +953,9 @@ $(document).ready(function () { $("#scatterplot").scatterplot("option", "selection", temp); }); + // Resolve the tableReadyPromise + window.resolveTableReady(); + // Changing the scatterplot selection updates the table row selection ... $("#scatterplot").bind("selection-changed", function (event, selection) { $("#table").table("option", "row-selection", selection); @@ -1044,6 +1062,8 @@ $(document).ready(function () { $("#table").table("option", "jump_to_simulation", parseInt(index)); video_sync_time_changed(video_sync_time); }); + + window.resolveScatterplotReady(); } } From 69593cec389582eb1a6d63e9c089fa1b81856040 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 12:32:56 -0700 Subject: [PATCH 33/46] fix: remove state mutation bug --- .../plugins/slycat-parameter-image/js/vtk-geometry-viewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js b/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js index 9e3844d27..147daab2e 100644 --- a/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js +++ b/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js @@ -486,7 +486,7 @@ export function load(container, buffer, uri, uid, type) { // Set the camera based on what's in the state let cameraState = window.store.getState().three_d_cameras - ? window.store.getState().three_d_cameras[uid] + ? _.cloneDeep(window.store.getState().three_d_cameras[uid]) : false; if (cameraState) { // console.log('we have state for the camera: ' + cameraState); From 9b44c0e8ef9d89edae165df5c607cf2063fc3950 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 12:44:09 -0700 Subject: [PATCH 34/46] style: prettier formatting --- .../js/vtk-geometry-viewer.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js b/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js index 147daab2e..2032fc9ad 100644 --- a/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js +++ b/web-server/plugins/slycat-parameter-image/js/vtk-geometry-viewer.js @@ -152,7 +152,7 @@ export function load(container, buffer, uri, uid, type) { value: `CellData:${a.getName()}`, type: "Cell", components: a.getNumberOfComponents(), - })) + })), ); // Dispatch update to available color by options to redux store window.store.dispatch(updateThreeDColorByOptions(uri, colorByOptions)); @@ -174,10 +174,10 @@ export function load(container, buffer, uri, uid, type) { const componentRange = array.getRange(componentIndex); // console.log(`Data range for ${uri} colored by ${colorBy} is: ${dataRange[0]} - ${dataRange[1]}`); window.store.dispatch( - adjustThreeDVariableDataRange(`${element.value}:${componentIndex}`, componentRange) + adjustThreeDVariableDataRange(`${element.value}:${componentIndex}`, componentRange), ); window.store.dispatch( - setThreeDColorByRange(uri, `${element.value}:${componentIndex}`, componentRange) + setThreeDColorByRange(uri, `${element.value}:${componentIndex}`, componentRange), ); }); } @@ -213,7 +213,7 @@ export function load(container, buffer, uri, uid, type) { location, colorByArrayName, componentString ? `[${Number(componentString) + 1}]` : "", - uri + uri, ); console.debug(`From this VTP file: %o`, vtpDataRange); const newDataRange = getDataRange(colorBy); @@ -277,23 +277,23 @@ export function load(container, buffer, uri, uid, type) { // each time the following parts of the Redux state change. // Subscribing to changes in three_d_colorvars. window.store.subscribe( - watch(window.store.getState, "three_d_colorvars", _.isEqual)(updateColorByIfChanged) + watch(window.store.getState, "three_d_colorvars", _.isEqual)(updateColorByIfChanged), ); // Subscribing to changes in three_d_variable_data_ranges. window.store.subscribe( watch( window.store.getState, "three_d_variable_data_ranges", - _.isEqual - )(updateColorByIfChanged) + _.isEqual, + )(updateColorByIfChanged), ); // Subscribing to changes in three_d_variable_user_ranges. window.store.subscribe( watch( window.store.getState, "three_d_variable_user_ranges", - _.isEqual - )(updateColorByIfChanged) + _.isEqual, + )(updateColorByIfChanged), ); } @@ -338,7 +338,7 @@ export function load(container, buffer, uri, uid, type) { setSize(); interactor.render(); }, - false + false, ); // ---------------------------------------------------------------------------- @@ -465,7 +465,7 @@ export function load(container, buffer, uri, uid, type) { manipulator.setControl(element.control != undefined ? element.control : false); manipulator.setAlt(element.alt != undefined ? element.alt : false); manipulator.setScrollEnabled( - element.scrollEnabled != undefined ? element.scrollEnabled : false + element.scrollEnabled != undefined ? element.scrollEnabled : false, ); interactorStyle.addMouseManipulator(manipulator); }); From f81ff483aba7d0d6ff0d2b54f0b089cee0ebc32b Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 12:54:28 -0700 Subject: [PATCH 35/46] fix: prevent unintended state mutations --- .../js/parameter-image-scatterplot.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js b/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js index ff874dab0..2a039ea70 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js @@ -597,7 +597,7 @@ $.widget("parameter_image.scatterplot", { const update_media_sizes = () => { // console.group(`update_media_sizes`); // console.debug(`new open_media is %o`, store.getState().open_media); - store.getState().open_media.forEach(function (currentMedia, index, array) { + _.cloneDeep(store.getState().open_media).forEach(function (currentMedia, index, array) { const frames = $(`.media-layer div.image-frame[data-uid=${currentMedia.uid}]`); let differentWidth, differentHeight; // console.debug(`Checking frames %o`, frames); @@ -2253,7 +2253,7 @@ $.widget("parameter_image.scatterplot", { let override = false; if (window.store.getState().sync_scaling) { // Check if there are any open media - const firstOpenMedia = window.store.getState().open_media[0]; + const firstOpenMedia = _.cloneDeep(window.store.getState().open_media[0]); if (firstOpenMedia) { // console.debug(`Overriding default media size to match sync`); imageWidth = imageHeight = firstOpenMedia.width; @@ -3149,7 +3149,7 @@ $.widget("parameter_image.scatterplot", { // Override size if Sync Size is enabled if (window.store.getState().sync_scaling) { // Check if there are any open media - const firstOpenMedia = window.store.getState().open_media[0]; + const firstOpenMedia = _.cloneDeep(window.store.getState().open_media[0]); if (firstOpenMedia) { // console.debug(`Overriding default media size to match sync`); hover_width = hover_height = firstOpenMedia.width; @@ -3411,7 +3411,7 @@ $.widget("parameter_image.scatterplot", { let sync_scaling = window.store.getState().sync_scaling; // Check if there are any open media - const firstOpenMedia = window.store.getState().open_media[0]; + const firstOpenMedia = _.cloneDeep(window.store.getState().open_media[0]); // Override default size if Sync Size is enabled if (sync_scaling && firstOpenMedia) { // console.debug(`Overriding default media size to match sync`); From 8b85b83e0a5fd88a9fb0802d8ae5d75c23c3d0f4 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 13:29:25 -0700 Subject: [PATCH 36/46] fix: prevent state mutations in reducers --- web-server/plugins/slycat-parameter-image/js/reducers.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/reducers.js b/web-server/plugins/slycat-parameter-image/js/reducers.js index 54db504fd..a64e2f7d0 100644 --- a/web-server/plugins/slycat-parameter-image/js/reducers.js +++ b/web-server/plugins/slycat-parameter-image/js/reducers.js @@ -427,13 +427,15 @@ export default function ps_reducer(state = initialState, action) { case UPDATE_CLOSED_MEDIA: // Make sure we can find the uid in current state's open_media array - const open_media_matches = state.open_media.filter((element) => element.uid == action.uid); + const open_media_matches = _.cloneDeep(state.open_media).filter( + (element) => element.uid == action.uid, + ); if (open_media_matches.length) { const open_media = open_media_matches[0]; // If it's 3D media, add its camera params and color by variable if (open_media.threeD) { - open_media.three_d_camera = state.three_d_cameras[open_media.uid]; - open_media.three_d_colorvar = state.three_d_colorvars[open_media.uid]; + open_media.three_d_camera = _.cloneDeep(state.three_d_cameras[open_media.uid]); + open_media.three_d_colorvar = _.cloneDeep(state.three_d_colorvars[open_media.uid]); } // If we don't have an entry for this closed media, just add it. // Otherwise, replace it. From 427dc4a252479e878c36f0c718cbb2ac29c0a3f7 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 13:55:36 -0700 Subject: [PATCH 37/46] refactor: move handling of threeD_sync and video_sync_time events fully into Redux --- .../js/Components/ControlsThreeD.js | 1 - .../js/Components/PSControlsBar.tsx | 1 - .../js/parameter-image-scatterplot.js | 25 +++++++---- .../plugins/slycat-parameter-image/js/ui.js | 43 ++++++------------- 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js index f45725dd4..7514bd107 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js +++ b/web-server/plugins/slycat-parameter-image/js/Components/ControlsThreeD.js @@ -19,7 +19,6 @@ class ControlsThreeD extends React.Component { }; toggle_threeD_sync = (e) => { - this.props.element.trigger("threeD_sync", !window.store.getState().threeD_sync); this.props.toggleThreeDSync(); }; diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 1b2022ef4..22ec0c3e5 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -239,7 +239,6 @@ class PSControlsBar extends React.Component { set_video_sync_time = (value: number) => { this.props.setVideoSyncTime(value); - this.props.element.trigger("video-sync-time", value); }; trigger_show_all = () => { diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js b/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js index 2a039ea70..b841eee08 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-image-scatterplot.js @@ -16,6 +16,7 @@ import { setOpenMedia, setMediaSizePosition, updateClosedMedia, + setVideoSyncTime, } from "./actions"; import $ from "jquery"; import React, { StrictMode } from "react"; @@ -2338,7 +2339,8 @@ $.widget("parameter_image.scatterplot", { // Sync all videos to current video-sync-time self._schedule_update({ update_video_sync_time: true }); } - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); self._sync_open_media(); } @@ -3503,7 +3505,8 @@ $.widget("parameter_image.scatterplot", { // Update and bookmark self._schedule_update({ update_video_sync_time: true }); - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); } else { let video = self._getCurrentFrameVideo(); if (video != null) { @@ -3529,7 +3532,8 @@ $.widget("parameter_image.scatterplot", { // Update and bookmark self._schedule_update({ update_video_sync_time: true }); - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); } else { let video = self._getCurrentFrameVideo(); if (video != null) { @@ -3548,7 +3552,8 @@ $.widget("parameter_image.scatterplot", { firstVideo.currentTime - self.options.frameLength, 0, ); - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); } // Pause all videos @@ -3590,7 +3595,8 @@ $.widget("parameter_image.scatterplot", { ); // Update and bookmark self._schedule_update({ update_video_sync_time: true }); - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); } } else { let video = self._getCurrentFrameVideo(); @@ -3627,7 +3633,8 @@ $.widget("parameter_image.scatterplot", { var firstVideo = videos.get(0); if (firstVideo != undefined) { self.options["video-sync-time"] = firstVideo.currentTime; - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); } videos.each(function (index, video) { @@ -3645,7 +3652,8 @@ $.widget("parameter_image.scatterplot", { self.options["video-sync-time"] = video.currentTime; self.syncing_videos.push(videoUID); video.currentTime = self.options["video-sync-time"]; - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); self._sync_open_media(); } } @@ -3658,7 +3666,8 @@ $.widget("parameter_image.scatterplot", { video.pause(); video.currentTime = time; self.options["video-sync-time"] = time; - self.element.trigger("video-sync-time", self.options["video-sync-time"]); + // Dispatch update to video_sync_time in Redux + window.store.dispatch(setVideoSyncTime(self.options["video-sync-time"])); self._sync_open_media(); } }, diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index fe6a777c2..d13014c4c 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -607,6 +607,8 @@ $(document).ready(function () { { objectPath: "media_index", callback: media_index_changed }, { objectPath: "variableRanges", callback: variable_ranges_changed }, { objectPath: "video_sync", callback: video_sync_changed }, + { objectPath: "threeD_sync", callback: threeD_sync_changed }, + { objectPath: "video_sync_time", callback: video_sync_time_changed }, ].forEach((subscription) => { window.store.subscribe( watch( @@ -1051,11 +1053,6 @@ $(document).ready(function () { handle_image_variable_change(variable); }); - // Changing the video sync time logs it ... - $("#scatterplot").bind("video-sync-time", function (event, video_sync_time) { - video_sync_time_changed(video_sync_time); - }); - // Jumping to simulation ... $("#scatterplot").bind("jump_to_simulation", function (event, index) { // Alerts the table @@ -1164,17 +1161,6 @@ $(document).ready(function () { } }); - // Changing the 3d sync option updates the scatterplot and logs it ... - $("#controls").bind("threeD_sync", function (event, threeD_sync) { - threeD_sync_option_changed(threeD_sync); - }); - - // Changing the video sync time updates the scatterplot and logs it ... - $("#controls").bind("video-sync-time", function (event, video_sync_time) { - $("#scatterplot").scatterplot("option", "video-sync-time", video_sync_time); - video_sync_time_changed(video_sync_time); - }); - // Clicking jump-to-start updates the scatterplot and logs it ... $("#controls").bind("jump-to-start", function (event) { $("#scatterplot").scatterplot("jump_to_start"); @@ -1654,6 +1640,16 @@ $(document).ready(function () { bookmarker.updateState({ "video-sync": video_sync }); } + function threeD_sync_changed(threeD_sync_value) { + threeD_sync = threeD_sync_value; + $("#scatterplot").scatterplot("option", "threeD_sync", threeD_sync); + setSyncCameras(threeD_sync); + $.ajax({ + type: "POST", + url: api_root + "events/models/" + model_id + "/threeD_sync/" + threeD_sync, + }); + } + function auto_scale_option_changed(auto_scale_value, old_auto_scale_value, objectPath) { auto_scale = auto_scale_value; if (hidden_simulations.length > 0) { @@ -1673,25 +1669,14 @@ $(document).ready(function () { } function video_sync_time_changed(video_sync_time_value) { + $("#scatterplot").scatterplot("option", "video-sync-time", video_sync_time_value); + video_sync_time = video_sync_time_value; $.ajax({ type: "POST", url: api_root + "events/models/" + model_id + "/video-sync-time/" + video_sync_time, }); bookmarker.updateState({ "video-sync-time": video_sync_time }); - - // Dispatch update to video_sync_time in Redux - window.store.dispatch(setVideoSyncTime(video_sync_time_value)); - } - - function threeD_sync_option_changed(threeD_sync_value) { - threeD_sync = threeD_sync_value; - $("#scatterplot").scatterplot("option", "threeD_sync", threeD_sync); - setSyncCameras(threeD_sync); - $.ajax({ - type: "POST", - url: api_root + "events/models/" + model_id + "/threeD_sync/" + threeD_sync, - }); } function hidden_simulations_changed() { From 86c1d8172e26ca26236c58604aae04b6dedac30e Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Fri, 20 Sep 2024 14:30:48 -0700 Subject: [PATCH 38/46] refactor: move video control event handling to Redux --- .../js/Components/PSControlsBar.tsx | 12 ++++---- .../plugins/slycat-parameter-image/js/ui.js | 30 ------------------- 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 22ec0c3e5..4e04aff42 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -296,27 +296,27 @@ class PSControlsBar extends React.Component { }; trigger_jump_to_start = () => { - this.props.element.trigger("jump-to-start"); + $("#scatterplot").scatterplot("jump_to_start"); }; trigger_frame_back = () => { - this.props.element.trigger("frame-back"); + $("#scatterplot").scatterplot("frame_back"); }; trigger_play = () => { - this.props.element.trigger("play"); + $("#scatterplot").scatterplot("play"); }; trigger_pause = () => { - this.props.element.trigger("pause"); + $("#scatterplot").scatterplot("pause"); }; trigger_frame_forward = () => { - this.props.element.trigger("frame-forward"); + $("#scatterplot").scatterplot("frame_forward"); }; trigger_jump_to_end = () => { - this.props.element.trigger("jump-to-end"); + $("#scatterplot").scatterplot("jump_to_end"); }; get_variable_label(variable: number) { diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index d13014c4c..8d6b53094 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -1161,36 +1161,6 @@ $(document).ready(function () { } }); - // Clicking jump-to-start updates the scatterplot and logs it ... - $("#controls").bind("jump-to-start", function (event) { - $("#scatterplot").scatterplot("jump_to_start"); - }); - - // Clicking frame-forward updates the scatterplot and logs it ... - $("#controls").bind("frame-forward", function (event) { - $("#scatterplot").scatterplot("frame_forward"); - }); - - // Clicking play updates the scatterplot and logs it ... - $("#controls").bind("play", function (event) { - $("#scatterplot").scatterplot("play"); - }); - - // Clicking pause updates the scatterplot and logs it ... - $("#controls").bind("pause", function (event) { - $("#scatterplot").scatterplot("pause"); - }); - - // Clicking frame-back updates the scatterplot and logs it ... - $("#controls").bind("frame-back", function (event) { - $("#scatterplot").scatterplot("frame_back"); - }); - - // Clicking jump-to-end updates the scatterplot and logs it ... - $("#controls").bind("jump-to-end", function (event) { - $("#scatterplot").scatterplot("jump_to_end"); - }); - // Log changes to hidden selection ... $("#controls").bind("hide-selection", function (event, selection) { for (var i = 0; i < selected_simulations.length; i++) { From 1872448ccf5012a42bc1391e227c7715b3e3c0f0 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Sat, 21 Sep 2024 16:44:53 -0700 Subject: [PATCH 39/46] reafactor: continue to move more controls event handling to redux --- .../js/Components/PSControlsBar.tsx | 60 ++++++-- .../slycat-parameter-image/js/dataSlice.ts | 2 +- .../js/parameter-image-table.js | 1 + .../plugins/slycat-parameter-image/js/ui.js | 144 +++--------------- 4 files changed, 72 insertions(+), 135 deletions(-) diff --git a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx index 4e04aff42..dda7afa13 100644 --- a/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx +++ b/web-server/plugins/slycat-parameter-image/js/Components/PSControlsBar.tsx @@ -23,6 +23,11 @@ import { setVIndex, setMediaIndex, } from "../actions"; +import { + setHiddenSimulations, + setManuallyHiddenSimulations, + setSelectedSimulations, +} from "../dataSlice"; import ControlsDropdownColor from "components/ControlsDropdownColor"; import slycat_color_maps from "js/slycat-color-maps"; import { v4 as uuidv4 } from "uuid"; @@ -218,7 +223,7 @@ class PSControlsBar extends React.Component { set_selected: SetSelectedFunction = (key, state_label, trigger, e, props) => { // Check if both key and trigger are defined before triggering the event if (key !== undefined && trigger !== undefined) { - // This is the legacy way of letting the rest of non-React components that the state changed. + // This is the legacy way of letting the rest of non-React components that the state changed. //Remove once we are converted to React. this.props.element.trigger(trigger, key); } else if (key !== undefined) { @@ -242,16 +247,22 @@ class PSControlsBar extends React.Component { }; trigger_show_all = () => { - this.props.element.trigger("show-all"); + this.props.setHiddenSimulations([]); + this.props.setManuallyHiddenSimulations([]); }; trigger_close_all = () => { - this.props.element.trigger("close-all"); + $("#scatterplot").scatterplot("close_all_simulations"); }; trigger_hide_selection = () => { if (this.props.active_filters.length == 0) { - this.props.element.trigger("hide-selection", this.props.selected_simulations); + const new_hidden_simulations = _.uniq([ + ...this.props.selected_simulations, + ...this.props.hidden_simulations, + ]); + this.props.setHiddenSimulations(new_hidden_simulations); + this.props.setManuallyHiddenSimulations(new_hidden_simulations); } // The to prevent the drop-down from closing when clicking on a disabled item // Unfortunately none of these work to stop the drop-down from closing. Looks like bootstrap's event is fired before this one. @@ -265,34 +276,56 @@ class PSControlsBar extends React.Component { trigger_hide_unselected = () => { if (this.props.active_filters.length == 0) { - // As of jQuery 1.6.2, single string or numeric argument can be passed without being wrapped in an array. - // https://api.jquery.com/trigger/ - // Thus we need to wrap our selection array in another array to pass it. - this.props.element.trigger("hide-unselected", [this.props.selected_simulations]); + let unselected = _.difference(this.props.indices, this.props.selected_simulations); + const new_hidden_simulations = _.uniq([...unselected, ...this.props.hidden_simulations]); + this.props.setHiddenSimulations(new_hidden_simulations); + this.props.setManuallyHiddenSimulations(new_hidden_simulations); } }; trigger_show_unselected = () => { if (this.props.active_filters.length == 0) { - this.props.element.trigger("show-unselected", [this.props.selected_simulations]); + let unselected = _.difference(this.props.indices, this.props.selected_simulations); + // Create a new array with any unselected simulations removed from hidden_simulations + let new_hidden_simulations = _.difference(this.props.hidden_simulations, unselected); + this.props.setHiddenSimulations(new_hidden_simulations); + this.props.setManuallyHiddenSimulations(new_hidden_simulations); } }; trigger_show_selection = () => { if (this.props.active_filters.length == 0) { - this.props.element.trigger("show-selection", [this.props.selected_simulations]); + let new_hidden_simulations = _.difference( + this.props.hidden_simulations, + this.props.selected_simulations, + ); + this.props.setHiddenSimulations(new_hidden_simulations); + this.props.setManuallyHiddenSimulations(new_hidden_simulations); } }; trigger_pin_selection = () => { + const selected_without_hidden = _.difference( + this.props.selected_simulations, + this.props.hidden_simulations, + ); // Passing true along with selection to pin-selection trigger to make it restore the size // and location of pins. We only do this when pinning from the controls menu, per // https://github.com/sandialabs/slycat/issues/1043#issuecomment-954137333 - this.props.element.trigger("pin-selection", [this.props.selected_simulations, true]); + // this.props.element.trigger("pin-selection", [this.props.selected_simulations, true]); + $("#scatterplot").scatterplot("pin", selected_without_hidden, true); }; trigger_select_pinned = () => { - this.props.element.trigger("select-pinned", [this.props.open_media]); + const open_media_indexes = this.props.open_media.map((media) => media.index); + // Remove any hidden simulations from those that are open + const pinned_simulations_without_hidden = _.difference( + open_media_indexes, + this.props.hidden_simulations, + ); + // Merge unhidden pinned simulations with currently selected simulations + const to_select = _.union(pinned_simulations_without_hidden, this.props.selected_simulations); + this.props.setSelectedSimulations(to_select); }; trigger_jump_to_start = () => { @@ -761,4 +794,7 @@ export default connect(mapStateToProps, { setMediaIndex, toggleShowHistogram, toggleAutoScale, + setHiddenSimulations, + setManuallyHiddenSimulations, + setSelectedSimulations, })(PSControlsBar); diff --git a/web-server/plugins/slycat-parameter-image/js/dataSlice.ts b/web-server/plugins/slycat-parameter-image/js/dataSlice.ts index a8c24cd02..59bff735e 100644 --- a/web-server/plugins/slycat-parameter-image/js/dataSlice.ts +++ b/web-server/plugins/slycat-parameter-image/js/dataSlice.ts @@ -45,7 +45,7 @@ export const selectSelectedSimulations = (state: RootState) => export const selectHiddenSimulations = (state: RootState) => state[SLICE_NAME].hidden_simulations; export const selectManuallyHiddenSimulations = (state: RootState) => -state[SLICE_NAME].manually_hidden_simulations; + state[SLICE_NAME].manually_hidden_simulations; export const selectSelectedSimulationsWithoutHidden = createSelector( selectSelectedSimulations, diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-image-table.js b/web-server/plugins/slycat-parameter-image/js/parameter-image-table.js index 7bb63b487..c2ee42a9d 100644 --- a/web-server/plugins/slycat-parameter-image/js/parameter-image-table.js +++ b/web-server/plugins/slycat-parameter-image/js/parameter-image-table.js @@ -428,6 +428,7 @@ $.widget("parameter_image.table", { self._color_variables(self.options["variable-selection"]); } else if (key == "hidden_simulations") { self.options[key] = value; + self.data.hidden_simulations = value; self.data.invalidate(); self.grid.invalidate(); } else if (key == "jump_to_simulation") { diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index 8d6b53094..c08838210 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -59,7 +59,6 @@ import data_reducer, { selectManuallyHiddenSimulations, setSelectedSimulations, setHiddenSimulations, - setManuallyHiddenSimulations, } from "./dataSlice"; import { setXValues, @@ -73,7 +72,6 @@ import { setUserRole, setTableStatistics, setTableMetadata, - setVideoSyncTime, } from "./actions"; import { setSyncCameras } from "./vtk-camera-synchronizer"; @@ -609,6 +607,11 @@ $(document).ready(function () { { objectPath: "video_sync", callback: video_sync_changed }, { objectPath: "threeD_sync", callback: threeD_sync_changed }, { objectPath: "video_sync_time", callback: video_sync_time_changed }, + { objectPath: "data.hidden_simulations", callback: hidden_simulations_changed }, + { + objectPath: "data.manually_hidden_simulations", + callback: manually_hidden_simulations_changed, + }, ].forEach((subscription) => { window.store.subscribe( watch( @@ -1160,115 +1163,6 @@ $(document).ready(function () { }); } }); - - // Log changes to hidden selection ... - $("#controls").bind("hide-selection", function (event, selection) { - for (var i = 0; i < selected_simulations.length; i++) { - if ($.inArray(selected_simulations[i], hidden_simulations) == -1) { - hidden_simulations.push(selected_simulations[i]); - } - } - manually_hidden_simulations = hidden_simulations.slice(); - update_widgets_when_hidden_simulations_change(); - }); - - // Log changes to hidden selection ... - $("#controls").bind("hide-unselected", function (event, selection) { - let unselected = _.difference(indices, selected_simulations); - let visible_unselected = _.difference(unselected, hidden_simulations); - hidden_simulations.push(...visible_unselected); - - // This is the old way of doing this. Seems wrong because we shouldn't - // be unhiding selected simulations when users want to hide unselected. - // This section can be removed once the team agrees this not what we want. - - // // Remove any selected_simulations from hidden_simulations - // for(var i=0; i @@ -662,10 +646,10 @@ class PSControlsBar extends React.Component { indices={this.props.indices} rating_variables={this.props.rating_variables} metadata={this.props.metadata} - element={this.props.element} button_style={button_style} media_columns={this.props.media_columns} media_variable={this.props.media_index} + write_data={this.props.write_data} /> { )} diff --git a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js b/web-server/plugins/slycat-parameter-image/js/parameter-controls.js deleted file mode 100644 index bbc71956a..000000000 --- a/web-server/plugins/slycat-parameter-image/js/parameter-controls.js +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2013, 2018 National Technology and Engineering Solutions of Sandia, LLC . - Under the terms of Contract DE-NA0003525 with National Technology and Engineering - Solutions of Sandia, LLC, the U.S. Government retains certain rights in this software. */ - -import React from "react"; -import { createRoot } from "react-dom/client"; -import "jquery-ui"; -import PSControlsBar from "./Components/PSControlsBar"; -import "bootstrap"; -import $ from "jquery"; - -$.widget("parameter_image.controls", { - options: { - mid: null, - model_name: null, - model: null, - aid: null, - x_variables: [], - y_variables: [], - axes_variables: [], - image_variables: [], - color_variables: [], - indices: [], - }, - - _create: function () { - var self = this; - - const controls_bar = ( - - ); - const react_controls_root = createRoot(document.getElementById("react-controls")); - react_controls_root.render(controls_bar); - }, - - _setOption: function (key, value) {}, -}); diff --git a/web-server/plugins/slycat-parameter-image/js/ui.js b/web-server/plugins/slycat-parameter-image/js/ui.js index c08838210..189df521a 100644 --- a/web-server/plugins/slycat-parameter-image/js/ui.js +++ b/web-server/plugins/slycat-parameter-image/js/ui.js @@ -21,7 +21,6 @@ import FilterManager from "./filter-manager"; import URI from "urijs"; import * as chunker from "js/chunker"; import "./parameter-image-scatterplot"; -import "./parameter-controls"; import "./parameter-image-table"; import $ from "jquery"; import "jquery-ui"; @@ -103,6 +102,10 @@ import { selectAxesVariables, } from "./selectors"; +import React from "react"; +import { createRoot } from "react-dom/client"; +import PSControlsBar from "./Components/PSControlsBar"; + let table_metadata = null; // Wait for document ready @@ -1094,75 +1097,24 @@ $(document).ready(function () { } } - $("#controls").controls({ - mid: model_id, - model: model, - model_name: window.model_name, - aid: "data-table", - x_variables: axes_variables, - y_variables: axes_variables, - axes_variables: axes_variables, - image_variables: image_columns, - color_variables: color_variables, - indices: indices, - }); - - // Changing the value of a variable updates the database, table, and scatterplot ... - $("#controls").bind("set-value", function (event, props) { - writeData(props.selection, props.variable, props.value); - function writeData(selection, variable, value) { - var hyperslices = ""; - var data = "["; - for (var i = 0; i < selection.length; i++) { - if (i > 0) { - hyperslices += "|"; - data += ","; - } - hyperslices += selection[i]; - data += "[" + value + "]"; - } - data += "]"; - var blob = new Blob([data], { type: "text/html" }); - var formdata = new FormData(); - formdata.append("data", blob); - formdata.append("hyperchunks", 0 + "/" + variable + "/" + hyperslices); - - $.ajax({ - type: "PUT", - url: api_root + "models/" + model_id + "/arraysets/data-table/data", - data: formdata, - processData: false, - contentType: false, - success: function (results) { - // Let's pass the edited variable to the table so it knows which column's - // ranked_indices to invalidate - $("#table").table("update_data", variable); - - if (variable == x_index) update_scatterplot_x(variable); - if (variable == y_index) update_scatterplot_y(variable); - - // console.debug(`Loading table statistics after a variable has been edited.`); - load_table_statistics([variable], function (new_table_statistics) { - // Not sure why we wait for new table statistics before calling - // update_v since we don't do that for updating x and y. - // But it's been in the code for very long so I'm leaving it as is. - if (variable == v_index) { - update_v(variable); - } - // Update filter manager with new table statistics - filter_manager.set_table_statistics(new_table_statistics); - // Let filter manager know that a variable has been changed so it can possibly - // update categorical unique values or numeric min/max - // filter_manager.load_unique_categories(); - filter_manager.notify_variable_value_edited(variable); - }); - }, - error: function (jqXHR, textStatus, errorThrown) { - console.log("writing array data error"); - }, - }); - } - }); + const controls_bar = ( + + ); + const react_controls_root = createRoot(document.getElementById("react-controls")); + react_controls_root.render(controls_bar); } } @@ -1170,6 +1122,59 @@ $(document).ready(function () { // Event handlers. ////////////////////////////////////////////////////////////////////////////////////////// + function writeData(selection, variable, value) { + var hyperslices = ""; + var data = "["; + for (var i = 0; i < selection.length; i++) { + if (i > 0) { + hyperslices += "|"; + data += ","; + } + hyperslices += selection[i]; + data += "[" + value + "]"; + } + data += "]"; + var blob = new Blob([data], { type: "text/html" }); + var formdata = new FormData(); + formdata.append("data", blob); + formdata.append("hyperchunks", 0 + "/" + variable + "/" + hyperslices); + + $.ajax({ + type: "PUT", + url: api_root + "models/" + model_id + "/arraysets/data-table/data", + data: formdata, + processData: false, + contentType: false, + success: function (results) { + // Let's pass the edited variable to the table so it knows which column's + // ranked_indices to invalidate + $("#table").table("update_data", variable); + + if (variable == x_index) update_scatterplot_x(variable); + if (variable == y_index) update_scatterplot_y(variable); + + // console.debug(`Loading table statistics after a variable has been edited.`); + load_table_statistics([variable], function (new_table_statistics) { + // Not sure why we wait for new table statistics before calling + // update_v since we don't do that for updating x and y. + // But it's been in the code for very long so I'm leaving it as is. + if (variable == v_index) { + update_v(variable); + } + // Update filter manager with new table statistics + filter_manager.set_table_statistics(new_table_statistics); + // Let filter manager know that a variable has been changed so it can possibly + // update categorical unique values or numeric min/max + // filter_manager.load_unique_categories(); + filter_manager.notify_variable_value_edited(variable); + }); + }, + error: function (jqXHR, textStatus, errorThrown) { + console.log("writing array data error"); + }, + }); + } + function selected_colormap_changed(colormap, oldColormap, objectPath) { update_current_colorscale(); From 62761a073802bf01297efdcc7a00c6d9b008353e Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 24 Sep 2024 07:17:41 -0700 Subject: [PATCH 42/46] build: update security vulnerabilities in npm packages --- package-lock.json | 142 ++++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 75 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f490197f..06eb66657 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4037,30 +4037,10 @@ "@types/d3-zoom": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, "node_modules/@types/express": { @@ -5431,9 +5411,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "license": "MIT", "dependencies": { @@ -5445,7 +5425,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -7295,9 +7275,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -8138,38 +8118,38 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -8198,9 +8178,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true, "license": "MIT" }, @@ -8363,14 +8343,14 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -12401,11 +12381,14 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -12434,9 +12417,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -13276,9 +13259,9 @@ } }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true, "license": "MIT" }, @@ -13837,13 +13820,13 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -14631,9 +14614,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { @@ -14672,6 +14655,16 @@ "dev": true, "license": "MIT" }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -14775,16 +14768,16 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -16160,12 +16153,11 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", @@ -16174,7 +16166,7 @@ "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", From 49cf6e9bbf63e2d6e484a29d8a371a937cd8e974 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 24 Sep 2024 07:20:43 -0700 Subject: [PATCH 43/46] build: upgrade npm packages --- package-lock.json | 968 +++++++++++++++++++++++----------------------- 1 file changed, 486 insertions(+), 482 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06eb66657..f9eb608a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -141,9 +141,9 @@ } }, "node_modules/@babel/cli": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.24.8.tgz", - "integrity": "sha512-isdp+G6DpRyKc+3Gqxy2rjzgF7Zj9K0mzLNnxz+E/fgeag8qT3vVulX4gY9dGO1q0y+0lUv6V3a+uhUzMzrwXg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.25.6.tgz", + "integrity": "sha512-Z+Doemr4VtvSD2SNHTrkiFZ1LX+JI6tyRXAAOb4N9khIuPyoEPmTPJarPm8ljJV1D6bnMQjyHMWTT9NeKbQuXA==", "dev": true, "license": "MIT", "dependencies": { @@ -164,7 +164,7 @@ }, "optionalDependencies": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0" + "chokidar": "^3.6.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -184,30 +184,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", - "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.9", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-module-transforms": "^7.24.9", - "@babel/helpers": "^7.24.8", - "@babel/parser": "^7.24.8", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.9", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -223,9 +223,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.8.tgz", - "integrity": "sha512-nYAikI4XTGokU2QX7Jx+v4rxZKhKivaQaREZjuW3mrJrbdWJ5yUfohnoUULge+zEEaKjPYNxhoRgUKktjXtbwA==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz", + "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==", "dev": true, "license": "MIT", "dependencies": { @@ -242,12 +242,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.9", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -282,12 +282,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.24.8", + "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", @@ -298,19 +298,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/traverse": "^7.25.4", "semver": "^6.3.1" }, "engines": { @@ -321,9 +319,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", - "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", @@ -353,43 +351,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", @@ -417,16 +378,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", - "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -457,14 +417,14 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", - "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-wrap-function": "^7.24.7" + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -474,14 +434,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -516,18 +476,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", @@ -556,28 +504,27 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", - "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "license": "MIT", "dependencies": { - "@babel/helper-function-name": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "license": "MIT", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" @@ -599,10 +546,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -611,13 +561,28 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", - "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -627,12 +592,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", - "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -659,13 +624,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", - "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -828,12 +793,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -843,12 +808,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1000,13 +965,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1047,15 +1012,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", - "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" }, "engines": { "node": ">=6.9.0" @@ -1097,12 +1062,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1112,13 +1077,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", - "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1145,18 +1110,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", - "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", "globals": "^11.1.0" }, "engines": { @@ -1228,6 +1191,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", @@ -1293,14 +1272,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" }, "engines": { "node": ">=6.9.0" @@ -1326,12 +1305,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1405,15 +1384,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", - "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "license": "MIT", "dependencies": { - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -1584,13 +1563,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", - "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1649,17 +1628,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -1733,16 +1712,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", - "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.4.tgz", + "integrity": "sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, @@ -1830,15 +1809,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", - "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-create-class-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-typescript": "^7.24.7" }, "engines": { @@ -1896,13 +1876,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", - "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1912,19 +1892,20 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", - "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-compilation-targets": "^7.24.8", + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", @@ -1945,29 +1926,30 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.24.7", - "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-dotall-regex": "^7.24.7", "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", "@babel/plugin-transform-dynamic-import": "^7.24.7", "@babel/plugin-transform-exponentiation-operator": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.24.7", "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-member-expression-literals": "^7.24.7", "@babel/plugin-transform-modules-amd": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", "@babel/plugin-transform-modules-umd": "^7.24.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-new-target": "^7.24.7", @@ -1978,7 +1960,7 @@ "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-property-literals": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", @@ -1991,10 +1973,10 @@ "@babel/plugin-transform-unicode-escapes": "^7.24.7", "@babel/plugin-transform-unicode-property-regex": "^7.24.7", "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.37.1", "semver": "^6.3.1" @@ -2080,9 +2062,9 @@ "license": "MIT" }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -2092,33 +2074,30 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2127,9 +2106,9 @@ } }, "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.24.8", @@ -2148,14 +2127,14 @@ "license": "MIT" }, "node_modules/@d3fc/d3fc-annotation": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@d3fc/d3fc-annotation/-/d3fc-annotation-3.0.15.tgz", - "integrity": "sha512-GEgZfRxnGFNs1FHg3pyVuEVu2dRhqfRG72GMLiL4RofPGOy2lEr4/9DUeZyXaGF3jBIlTmSgEhC1kSXkMUCI7g==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@d3fc/d3fc-annotation/-/d3fc-annotation-3.0.16.tgz", + "integrity": "sha512-4tA7RHLUbj/i3KqWRqCVDOHi435qBRXbAFrAajVYM2juNzFdX5RCoF3opyXKOFncs339caxgeySGStTVfulO9w==", "license": "MIT", "dependencies": { "@d3fc/d3fc-data-join": "^6.0.3", "@d3fc/d3fc-rebind": "^6.0.1", - "@d3fc/d3fc-series": "^6.1.2", + "@d3fc/d3fc-series": "^6.1.3", "@d3fc/d3fc-shape": "^6.0.1" }, "peerDependencies": { @@ -2195,16 +2174,16 @@ } }, "node_modules/@d3fc/d3fc-chart": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/@d3fc/d3fc-chart/-/d3fc-chart-5.1.8.tgz", - "integrity": "sha512-F9R0My7cgngPnUqrYrujIUzZ0yyBjCkAodcG+3ZXRqEGPitHCO1jPwyRPQQvgrImSmt6/I/i6ciI5Lonn4o6pA==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/@d3fc/d3fc-chart/-/d3fc-chart-5.1.9.tgz", + "integrity": "sha512-xFO9lDUi2wAkjfyWlVZuFwSWEgnk0WOEagR2R9KzQ+uxeg3oZOPzwE+AZbpALyQbjjQ2uIxcOk56xnmnnayk3w==", "license": "MIT", "dependencies": { "@d3fc/d3fc-axis": "^3.0.7", "@d3fc/d3fc-data-join": "^6.0.3", "@d3fc/d3fc-element": "^6.2.0", "@d3fc/d3fc-rebind": "^6.0.1", - "@d3fc/d3fc-series": "^6.1.2" + "@d3fc/d3fc-series": "^6.1.3" }, "peerDependencies": { "d3-scale": "*", @@ -2323,15 +2302,15 @@ } }, "node_modules/@d3fc/d3fc-series": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@d3fc/d3fc-series/-/d3fc-series-6.1.2.tgz", - "integrity": "sha512-IEhFCireGXiC/dIDaa36isjl8vF69uxuFYHasfVqvO3xAU2Ewgsypw3fDeC6EHYSoKFug+HJNSGDhbQRXiYH1Q==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@d3fc/d3fc-series/-/d3fc-series-6.1.3.tgz", + "integrity": "sha512-OSbt60SohTIib1xihX9ufneyJY7s9Feg9hvXVyEBZEBkwNE1NaeesZJ4nkmslu39RWuwsvpK3apL/XuBw7i5WA==", "license": "MIT", "dependencies": { "@d3fc/d3fc-data-join": "^6.0.3", "@d3fc/d3fc-rebind": "^6.0.1", "@d3fc/d3fc-shape": "^6.0.1", - "@d3fc/d3fc-webgl": "^3.2.0" + "@d3fc/d3fc-webgl": "^3.2.1" }, "peerDependencies": { "d3-array": "*", @@ -2363,9 +2342,9 @@ } }, "node_modules/@d3fc/d3fc-webgl": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@d3fc/d3fc-webgl/-/d3fc-webgl-3.2.0.tgz", - "integrity": "sha512-ca0gSeitQYLIT5p3DoWpHS/cdkA/XmVWSHo1WiDMZt6Hwy86HSHwT3EGtTfXKtK1pZELyDvj9syhyRhi0zU5ow==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@d3fc/d3fc-webgl/-/d3fc-webgl-3.2.1.tgz", + "integrity": "sha512-yNYHW/tC05rrJs5fpVM5zdmInL8NH6UP09ZJ2tmKw62ELYHWySV8vuXOVZN3V/3WihPa60p2w23H0Hrp2b5qeg==", "license": "MIT", "dependencies": { "@d3fc/d3fc-rebind": "^6.0.1" @@ -2429,9 +2408,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "license": "MIT", "engines": { @@ -2512,9 +2491,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", "engines": { @@ -2568,14 +2547,14 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -3554,9 +3533,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true, "license": "MIT" }, @@ -3612,31 +3591,31 @@ } }, "node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^2.0.0", + "@sinonjs/commons": "^3.0.1", "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" } }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", "dev": true, "license": "(Unlicense OR Apache-2.0)" }, @@ -4122,9 +4101,9 @@ "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4159,9 +4138,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", "dev": true, "license": "MIT", "dependencies": { @@ -4198,9 +4177,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", + "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", "dev": true, "license": "MIT" }, @@ -4219,12 +4198,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "version": "20.16.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.6.tgz", + "integrity": "sha512-T7PpxM/6yeDE+AdlVysT62BX6/bECZOmQAgiFg5NoBd5MQheZ3tzal7f1wvzfiEcmrcJNRi2zRr2nY2zF+0uqw==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-forge": { @@ -4238,15 +4217,15 @@ } }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", "dev": true, "license": "MIT" }, @@ -4258,9 +4237,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "18.3.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz", + "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4389,9 +4368,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.11", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", - "integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4399,9 +4378,9 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "license": "MIT", "dependencies": { @@ -4673,9 +4652,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -4993,9 +4972,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "funding": [ { "type": "opencollective", @@ -5012,11 +4991,11 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -5153,9 +5132,9 @@ } }, "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", "dev": true, "license": "MIT", "dependencies": { @@ -5277,13 +5256,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5302,24 +5281,27 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -5537,9 +5519,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -5556,9 +5538,9 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -5669,9 +5651,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001643", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", - "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", + "version": "1.0.30001663", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", + "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", "funding": [ { "type": "opencollective", @@ -5747,9 +5729,9 @@ } }, "node_modules/chrono-node": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.7.6.tgz", - "integrity": "sha512-yugKSRLHc6B6kXxm/DwNc94zhaddAjCSO9IOGH3w7NIWNM+gUoLl/2/XLndiw4I+XhU4H2LOhC5Ab2JjS6JWsA==", + "version": "2.7.7", + "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.7.7.tgz", + "integrity": "sha512-p3S7gotuTPu5oqhRL2p1fLwQXGgdQaRTtWR3e8Di9P1Pa9mzkK5DWR5AWBieMUh2ZdOnPgrK+zCrbbtyuA+D/Q==", "license": "MIT", "dependencies": { "dayjs": "^1.10.0" @@ -5775,9 +5757,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true, "license": "MIT" }, @@ -6077,12 +6059,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -6693,15 +6675,15 @@ } }, "node_modules/d3fc": { - "version": "15.2.12", - "resolved": "https://registry.npmjs.org/d3fc/-/d3fc-15.2.12.tgz", - "integrity": "sha512-MOaxN9G+tLvsbiZ/zDzZBOkSA0BKGvKPoMFYA69Qa/K5tpYYd0kNcVyeUaWPbjoc5a0PPH/EykPmijCoFpm2eA==", + "version": "15.2.13", + "resolved": "https://registry.npmjs.org/d3fc/-/d3fc-15.2.13.tgz", + "integrity": "sha512-wfBvY9TcoeV/bRxPjawlzDHS/r2y03STspyZc9ydiz4ANMt+y+ynL9oahTZ4aAbp5JK850VxWNkQ8jaaN/cDYg==", "license": "MIT", "dependencies": { - "@d3fc/d3fc-annotation": "^3.0.15", + "@d3fc/d3fc-annotation": "^3.0.16", "@d3fc/d3fc-axis": "^3.0.7", "@d3fc/d3fc-brush": "^3.0.3", - "@d3fc/d3fc-chart": "^5.1.8", + "@d3fc/d3fc-chart": "^5.1.9", "@d3fc/d3fc-data-join": "^6.0.3", "@d3fc/d3fc-discontinuous-scale": "^4.1.1", "@d3fc/d3fc-element": "^6.2.0", @@ -6713,10 +6695,10 @@ "@d3fc/d3fc-random-data": "^4.0.2", "@d3fc/d3fc-rebind": "^6.0.1", "@d3fc/d3fc-sample": "^5.0.2", - "@d3fc/d3fc-series": "^6.1.2", + "@d3fc/d3fc-series": "^6.1.3", "@d3fc/d3fc-shape": "^6.0.1", "@d3fc/d3fc-technical-indicator": "^8.1.1", - "@d3fc/d3fc-webgl": "^3.2.0", + "@d3fc/d3fc-webgl": "^3.2.1", "@d3fc/d3fc-zoom": "^1.2.0" } }, @@ -6817,9 +6799,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.12", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", - "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", "license": "MIT" }, "node_modules/debounce": { @@ -6830,12 +6812,12 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -7240,9 +7222,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", - "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", + "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==", "license": "ISC" }, "node_modules/emittery": { @@ -7321,9 +7303,9 @@ } }, "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true, "license": "MIT", "bin": { @@ -7548,9 +7530,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" @@ -7573,17 +7555,17 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -7629,9 +7611,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "version": "7.36.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz", + "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==", "dev": true, "license": "MIT", "dependencies": { @@ -8379,14 +8361,13 @@ "license": "MIT" }, "node_modules/find-babel-config": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.1.tgz", - "integrity": "sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.2.tgz", + "integrity": "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg==", "dev": true, "license": "MIT", "dependencies": { - "json5": "^2.2.3", - "path-exists": "^4.0.0" + "json5": "^2.2.3" } }, "node_modules/find-cache-dir": { @@ -8470,9 +8451,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -9314,9 +9295,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -9631,9 +9612,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -12126,9 +12107,9 @@ } }, "node_modules/launch-editor": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", - "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", "dev": true, "license": "MIT", "dependencies": { @@ -12523,9 +12504,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/multicast-dns": { @@ -12616,13 +12597,13 @@ } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@sinonjs/commons": "^3.0.1" } }, "node_modules/no-case": { @@ -13276,9 +13257,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "license": "ISC" }, "node_modules/picomatch": { @@ -13541,9 +13522,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "funding": [ { "type": "opencollective", @@ -13561,8 +13542,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -13632,9 +13613,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { @@ -14125,9 +14106,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -14448,13 +14429,13 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", - "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", + "version": "1.79.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", + "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", + "chokidar": "^4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" }, @@ -14503,6 +14484,36 @@ } } }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", + "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", @@ -14665,13 +14676,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -15053,9 +15057,9 @@ } }, "node_modules/sortablejs": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", - "integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.3.tgz", + "integrity": "sha512-zdK3/kwwAK1cJgy1rwl1YtNTbRmc8qW/+vgXf75A7NHag5of4pyI6uK86ktmQETyWRH7IGaE73uZOOBcGxgqZg==", "license": "MIT" }, "node_modules/source-map": { @@ -15068,9 +15072,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -15421,9 +15425,9 @@ } }, "node_modules/terser": { - "version": "5.31.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", - "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -15567,9 +15571,9 @@ "license": "MIT" }, "node_modules/three": { - "version": "0.166.1", - "resolved": "https://registry.npmjs.org/three/-/three-0.166.1.tgz", - "integrity": "sha512-LtuafkKHHzm61AQA1be2MAYIw1IjmhOUxhBa0prrLpEMWbV7ijvxCRHjSgHPGp2493wLBzwKV46tA9nivLEgKg==", + "version": "0.168.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.168.0.tgz", + "integrity": "sha512-6m6jXtDwMJEK/GGMbAOTSAmxNdzKvvBzgd7q8bE/7Tr6m7PaBh5kKLrN7faWtlglXbzj7sVba48Idwx+NRsZXw==", "license": "MIT" }, "node_modules/three-stl-loader": { @@ -15651,9 +15655,9 @@ "license": "MIT" }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true, "license": "0BSD" }, @@ -15785,9 +15789,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -15815,15 +15819,15 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "license": "MIT", "engines": { "node": ">=4" @@ -15843,9 +15847,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "license": "MIT", "engines": { "node": ">=4" @@ -16117,9 +16121,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -16581,14 +16585,14 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -16597,8 +16601,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" From a6d61d9db7bdb909782646052020b65d8628b191 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 24 Sep 2024 08:10:26 -0700 Subject: [PATCH 44/46] build: update npm packages and fix breaking changes --- package-lock.json | 690 +++++++++++++-------- package.json | 28 +- web-server/plugins/slycat-cca/js/ui.js | 4 +- web-server/plugins/slycat-dac/js/dac-ui.js | 4 +- webpack.dev.js | 47 +- 5 files changed, 479 insertions(+), 294 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9eb608a9..f91c7e1e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@fortawesome/fontawesome-svg-core": "^6", "@fortawesome/free-solid-svg-icons": "^6", "@fortawesome/react-fontawesome": "^0", - "@reduxjs/toolkit": "^1.9.3", + "@reduxjs/toolkit": "^2", "bootstrap": "^4", "buffer": "6.0.3", "chrono-node": "^2.7.5", @@ -26,7 +26,7 @@ "he": "1.2.0", "jquery": "^3", "jquery-knob": "1.2.11", - "jquery-ui": "1.13.2", + "jquery-ui": "^1", "jquery.scrollintoview": "^1.9.4", "knockout": "3.5.1", "knockout-mapping": "2.6.0", @@ -36,11 +36,11 @@ "parse-css-color": "^0.2.1", "react": "^18", "react-dom": "^18", - "react-redux": "^8", - "redux": "^4", + "react-redux": "^9", + "redux": "^5", "redux-logger": "3.0.6", "redux-throttle": "0.1.1", - "redux-thunk": "^2", + "redux-thunk": "^3", "redux-watch": "^1.2.0", "slickgrid": "^3", "stream-browserify": "3.0.0", @@ -86,33 +86,33 @@ "babel-plugin-module-resolver": "^5", "babelify": "^10.0.0", "clean-webpack-plugin": "^4", - "copy-webpack-plugin": "^11", - "css-loader": "^6", + "copy-webpack-plugin": "^12", + "css-loader": "^7", "eslint": "^8", "eslint-plugin-react": "^7.22.0", "file-loader": "^6.2.0", - "html-loader": "^4", + "html-loader": "^5", "html-webpack-plugin": "^5.0.0-beta.4", - "imports-loader": "^4", + "imports-loader": "^5", "jest": "^29", "jest-fetch-mock": "^3.0.1", "less": "^4.0.0", - "less-loader": "^11", + "less-loader": "^12", "node-fetch-polyfill": "^2.0.6", "prettier": "^3", "react-test-renderer": "^18", "sass": "^1", - "sass-loader": "^13", + "sass-loader": "^16", "shader-loader": "^1.3.1", "sinon": "^15", - "style-loader": "^3", + "style-loader": "^4", "typescript": "^5", "url-loader": "^4.1.1", "webpack": "^5.11.1", "webpack-bundle-analyzer": "^4.3.0", "webpack-cli": "^5", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", + "webpack-dev-server": "^5", + "webpack-merge": "^6", "webpack-node-modules-list": "^0.4.1", "whatwg-fetch": "^3.5.0", "worker-loader": "^3.0.7" @@ -3421,6 +3421,63 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", + "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -3540,19 +3597,19 @@ "license": "MIT" }, "node_modules/@reduxjs/toolkit": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", - "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz", + "integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==", "license": "MIT", "dependencies": { - "immer": "^9.0.21", - "redux": "^4.2.1", - "redux-thunk": "^2.4.2", - "reselect": "^4.1.8" + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18", - "react-redux": "^7.2.1 || ^8.0.2" + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "peerDependenciesMeta": { "react": { @@ -3563,6 +3620,12 @@ } } }, + "node_modules/@reduxjs/toolkit/node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -3570,6 +3633,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -4076,16 +4152,6 @@ "@types/node": "*" } }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", - "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4220,6 +4286,7 @@ "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true, "license": "MIT" }, "node_modules/@types/qs": { @@ -4240,6 +4307,7 @@ "version": "18.3.9", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz", "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==", + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4250,7 +4318,7 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/react": "*" @@ -4267,9 +4335,9 @@ } }, "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true, "license": "MIT" }, @@ -5590,6 +5658,22 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -6021,21 +6105,21 @@ } }, "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", + "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", "dev": true, "license": "MIT", "dependencies": { - "fast-glob": "^3.2.11", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", - "globby": "^13.1.1", + "globby": "^14.0.0", "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -6202,9 +6286,9 @@ } }, "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "license": "MIT", "dependencies": { @@ -6218,7 +6302,7 @@ "semver": "^7.5.4" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -6226,7 +6310,7 @@ }, "peerDependencies": { "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" + "webpack": "^5.27.0" }, "peerDependenciesMeta": { "@rspack/core": { @@ -6297,6 +6381,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, "license": "MIT" }, "node_modules/d3": { @@ -6908,17 +6993,34 @@ "node": ">=0.10.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "execa": "^5.0.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-data-property": { @@ -6939,13 +7041,16 @@ } }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-properties": { @@ -7078,19 +7183,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -8522,13 +8614,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true, - "license": "Unlicense" - }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -8746,33 +8831,34 @@ } }, "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, "license": "MIT", "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8928,21 +9014,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -9021,17 +9092,17 @@ "license": "MIT" }, "node_modules/html-loader": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-4.2.0.tgz", - "integrity": "sha512-OxCHD3yt+qwqng2vvcaPApCEvbx+nXWu+v69TYHx1FO8bffHn/JjHtE3TTQZmHjwvnJe4xxzuecetDVBrQR1Zg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", "dev": true, "license": "MIT", "dependencies": { - "html-minifier-terser": "^7.0.0", - "parse5": "^7.0.0" + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -9249,6 +9320,16 @@ "node": ">=10.17.0" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -9319,9 +9400,9 @@ } }, "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "license": "MIT", "funding": { "type": "opencollective", @@ -9405,17 +9486,17 @@ } }, "node_modules/imports-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-4.0.1.tgz", - "integrity": "sha512-ZiY+1xH5fqAJ1Qu1CFv+zw54rvPCC92DdYRDe0IIUboOhbJPLfOPbF/paA2iipelvMwjQUKWydcFOJ7f1+ZFcA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-5.0.0.tgz", + "integrity": "sha512-tXgL8xxZFjOjQLLiE7my00UUQfktg4G8fdpXcZphL0bJWbk9eCxKKFaCwmFRcwyRJQl95GXBL1DoE1rCS/tcPw==", "dev": true, "license": "MIT", "dependencies": { - "source-map": "^0.6.1", + "source-map-js": "^1.0.2", "strip-comments": "^2.0.1" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -9658,16 +9739,16 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9745,6 +9826,25 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -9770,6 +9870,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -10018,16 +10131,19 @@ "license": "MIT" }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { @@ -12154,21 +12270,30 @@ } }, "node_modules/less-loader": { - "version": "11.1.4", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz", - "integrity": "sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", + "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "less": "^3.5.0 || ^4.0.0", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/leven": { @@ -12349,16 +12474,23 @@ } }, "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.12.0.tgz", + "integrity": "sha512-74wDsex5tQDSClVkeK1vtxqYCAgCoXxx+K4NSHzgU/muYVYByFqa+0RnrPO9NM6naWm1+G9JmZ0p6QHhXmeYfA==", "dev": true, - "license": "Unlicense", + "license": "Apache-2.0", "dependencies": { - "fs-monkey": "^1.0.4" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, "engines": { "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, "node_modules/merge-descriptors": { @@ -12930,18 +13062,19 @@ } }, "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, "license": "MIT", "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13031,17 +13164,21 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "dev": true, "license": "MIT", "dependencies": { - "@types/retry": "0.12.0", + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", "retry": "^0.13.1" }, "engines": { - "node": ">=8" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -13247,13 +13384,16 @@ "license": "MIT" }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/picocolors": { @@ -13924,42 +14064,27 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, "license": "MIT" }, "node_modules/react-redux": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", - "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.1", - "@types/hoist-non-react-statics": "^3.3.1", "@types/use-sync-external-store": "^0.0.3", - "hoist-non-react-statics": "^3.3.2", - "react-is": "^18.0.0", "use-sync-external-store": "^1.0.0" }, "peerDependencies": { - "@types/react": "^16.8 || ^17.0 || ^18.0", - "@types/react-dom": "^16.8 || ^17.0 || ^18.0", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0", - "react-native": ">=0.59", - "redux": "^4 || ^5.0.0-beta.0" + "@types/react": "^18.2.25", + "react": "^18.0", + "redux": "^5.0.0" }, "peerDependenciesMeta": { "@types/react": { "optional": true }, - "@types/react-dom": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - }, "redux": { "optional": true } @@ -14033,13 +14158,10 @@ } }, "node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" }, "node_modules/redux-logger": { "version": "3.0.6", @@ -14060,12 +14182,12 @@ } }, "node_modules/redux-thunk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", - "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", "license": "MIT", "peerDependencies": { - "redux": "^4" + "redux": "^5.0.0" } }, "node_modules/redux-watch": { @@ -14242,6 +14364,7 @@ "version": "4.1.8", "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "dev": true, "license": "MIT" }, "node_modules/resolve": { @@ -14335,6 +14458,19 @@ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", "license": "Unlicense" }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -14447,30 +14583,30 @@ } }, "node_modules/sass-loader": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", - "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.2.tgz", + "integrity": "sha512-Ll6iXZ1EYwYT19SqW4mSBb76vSSi8JgzElmzIerhEGgzB5hRjDQIWsPmuk1UrAXkR16KJHqVY0eH+5/uw9Tmfw==", "dev": true, "license": "MIT", "dependencies": { "neo-async": "^2.6.2" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "fibers": ">= 3.1.0", + "@rspack/core": "0.x || 1.x", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "fibers": { + "@rspack/core": { "optional": true }, "node-sass": { @@ -14481,6 +14617,9 @@ }, "sass-embedded": { "optional": true + }, + "webpack": { + "optional": true } } }, @@ -15375,20 +15514,20 @@ } }, "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" + "webpack": "^5.27.0" } }, "node_modules/supports-color": { @@ -15570,6 +15709,19 @@ "dev": true, "license": "MIT" }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/three": { "version": "0.168.0", "resolved": "https://registry.npmjs.org/three/-/three-0.168.0.tgz", @@ -15654,6 +15806,23 @@ "dev": true, "license": "MIT" }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", @@ -15864,6 +16033,19 @@ "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -16331,80 +16513,99 @@ "node": ">= 10.13.0" } }, + "node_modules/webpack-cli/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, "license": "MIT", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", + "memfs": "^4.6.0", "mime-types": "^2.1.31", + "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", + "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", + "express": "^4.19.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", + "html-entities": "^2.4.0", "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { "webpack": { @@ -16415,23 +16616,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webpack-dev-server/node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -16455,18 +16639,18 @@ } }, "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", - "wildcard": "^2.0.0" + "wildcard": "^2.0.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, "node_modules/webpack-node-modules-list": { diff --git a/package.json b/package.json index 2e5067f47..c6c6acc46 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@fortawesome/fontawesome-svg-core": "^6", "@fortawesome/free-solid-svg-icons": "^6", "@fortawesome/react-fontawesome": "^0", - "@reduxjs/toolkit": "^1.9.3", + "@reduxjs/toolkit": "^2", "bootstrap": "^4", "buffer": "6.0.3", "chrono-node": "^2.7.5", @@ -36,7 +36,7 @@ "he": "1.2.0", "jquery": "^3", "jquery-knob": "1.2.11", - "jquery-ui": "1.13.2", + "jquery-ui": "^1", "jquery.scrollintoview": "^1.9.4", "knockout": "3.5.1", "knockout-mapping": "2.6.0", @@ -46,11 +46,11 @@ "parse-css-color": "^0.2.1", "react": "^18", "react-dom": "^18", - "react-redux": "^8", - "redux": "^4", + "react-redux": "^9", + "redux": "^5", "redux-logger": "3.0.6", "redux-throttle": "0.1.1", - "redux-thunk": "^2", + "redux-thunk": "^3", "redux-watch": "^1.2.0", "slickgrid": "^3", "stream-browserify": "3.0.0", @@ -96,33 +96,33 @@ "babel-plugin-module-resolver": "^5", "babelify": "^10.0.0", "clean-webpack-plugin": "^4", - "copy-webpack-plugin": "^11", - "css-loader": "^6", + "copy-webpack-plugin": "^12", + "css-loader": "^7", "eslint": "^8", "eslint-plugin-react": "^7.22.0", "file-loader": "^6.2.0", - "html-loader": "^4", + "html-loader": "^5", "html-webpack-plugin": "^5.0.0-beta.4", - "imports-loader": "^4", + "imports-loader": "^5", "jest": "^29", "jest-fetch-mock": "^3.0.1", "less": "^4.0.0", - "less-loader": "^11", + "less-loader": "^12", "node-fetch-polyfill": "^2.0.6", "prettier": "^3", "react-test-renderer": "^18", "sass": "^1", - "sass-loader": "^13", + "sass-loader": "^16", "shader-loader": "^1.3.1", "sinon": "^15", - "style-loader": "^3", + "style-loader": "^4", "typescript": "^5", "url-loader": "^4.1.1", "webpack": "^5.11.1", "webpack-bundle-analyzer": "^4.3.0", "webpack-cli": "^5", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", + "webpack-dev-server": "^5", + "webpack-merge": "^6", "webpack-node-modules-list": "^0.4.1", "whatwg-fetch": "^3.5.0", "worker-loader": "^3.0.7" diff --git a/web-server/plugins/slycat-cca/js/ui.js b/web-server/plugins/slycat-cca/js/ui.js index 16181c9f6..33467cd62 100644 --- a/web-server/plugins/slycat-cca/js/ui.js +++ b/web-server/plugins/slycat-cca/js/ui.js @@ -34,7 +34,7 @@ import CCATable from "./components/CCATable"; import CCAScatterplot from "./components/CCAScatterplot"; import { Provider } from "react-redux"; -import thunkMiddleware from "redux-thunk"; +import { thunk } from "redux-thunk"; import { createLogger } from "redux-logger"; import { createStore, applyMiddleware } from "redux"; import cca_reducer from "./reducers"; @@ -509,7 +509,7 @@ $(document).ready(function () { // Adding middlewares to redux store const middlewares = []; // Lets us dispatch() functions - middlewares.push(thunkMiddleware); + middlewares.push(thunk); // Neat middleware that logs actions. // Logger must be the last middleware in chain, // otherwise it will log thunk and promise, diff --git a/web-server/plugins/slycat-dac/js/dac-ui.js b/web-server/plugins/slycat-dac/js/dac-ui.js index 8af0cf5b6..ecfe0cabd 100755 --- a/web-server/plugins/slycat-dac/js/dac-ui.js +++ b/web-server/plugins/slycat-dac/js/dac-ui.js @@ -37,7 +37,7 @@ import Selector from "./components/Selector"; import { createStore, applyMiddleware, } from 'redux'; import { Provider, } from 'react-redux'; -import thunkMiddleware from 'redux-thunk'; +import { thunk } from 'redux-thunk'; import { createLogger, } from 'redux-logger'; import dac_reducer from './reducers'; import { @@ -312,7 +312,7 @@ $(document).ready(function() { // Adding middlewares to redux store const middlewares = []; // Lets us dispatch() functions - middlewares.push(thunkMiddleware); + middlewares.push(thunk); // Neat middleware that logs actions. // Logger must be the last middleware in chain, // otherwise it will log thunk and promise, diff --git a/webpack.dev.js b/webpack.dev.js index c9d9bb56f..d6095e280 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -1,46 +1,47 @@ -const { merge } = require('webpack-merge'); -const common = require('./webpack.common.js'); +const { merge } = require("webpack-merge"); +const common = require("./webpack.common.js"); module.exports = merge(common, { - mode: 'development', - devtool: 'eval-source-map', + mode: "development", + devtool: "eval-source-map", devServer: { devMiddleware: { - publicPath: '/', - index: 'slycat_projects.html', + publicPath: "/", + index: "slycat_projects.html", }, // Only compiles on refresh, not on file change. But does not work, complains of running webpack twice. // lazy: true, // Disable live reloading. Useful when trying to run two branches side by side. // inline: false, - + // compress: true, - host: '0.0.0.0', + host: "0.0.0.0", port: 9000, - server: 'https', - proxy: { - '/api': { - target: 'https://haproxy:443', - pathRewrite: {'^/api' : ''}, + server: "https", + proxy: [ + { + context: ["/api"], + target: "https://haproxy:443", + pathRewrite: { "^/api": "" }, secure: false, }, - }, + ], historyApiFallback: { rewrites: [ // { from: /^\/$/, to: '/views/landing.html' }, // { from: /^\/subpage/, to: '/views/subpage.html' }, // If the URL begins with projects/ (note the trailing slash), serve up the single project page - { from: /^\/projects\//, to: '/slycat_project.html' }, + { from: /^\/projects\//, to: "/slycat_project.html" }, // If the URL begins with projects (note no trailing slash), serve up the listing of all projects. // This is for backwards compatibility, since we used to redirect unknown URLs to /projects to give the user // a projects listing. - { from: /^\/projects/, to: '/slycat_projects.html' }, - { from: /^\/models/, to: '/slycat_model.html' }, - { from: /^\/login/, to: '/slycat_login.html' }, - { from: /^\/pages/, to: '/slycat_page.html' }, + { from: /^\/projects/, to: "/slycat_projects.html" }, + { from: /^\/models/, to: "/slycat_model.html" }, + { from: /^\/login/, to: "/slycat_login.html" }, + { from: /^\/pages/, to: "/slycat_page.html" }, // { from: /./, to: '/views/404.html' }, - ] - } - } -}); \ No newline at end of file + ], + }, + }, +}); From 6a85d85070dce2cc762b85ca7a76a471c5377436 Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Tue, 24 Sep 2024 15:53:50 -0700 Subject: [PATCH 45/46] build: update npm packages and fix breaking changes Major upgrade to slickGrid and fixes to legacy code that broke --- package-lock.json | 545 ++-- package.json | 21 +- .../components/{CCATable.js => CCATable.tsx} | 266 +- .../js/components/SlickGridDataProvider.js | 180 +- web-server/plugins/slycat-cca/js/ui.js | 11 +- web-server/plugins/slycat-dac/js/dac-table.js | 2258 ++++++++--------- .../js/parameter-image-table.js | 672 ++--- .../js/ui.js | 12 +- ...mage-table.js => parameter-image-table.ts} | 37 +- .../plugins/slycat-parameter-image/js/ui.js | 18 +- .../js/timeseries-table.js | 734 +++--- .../slycat-timeseries-model/js/timeseries.js | 40 +- .../plugins/slycat-video-swarm/js/vs-table.js | 35 +- 13 files changed, 2405 insertions(+), 2424 deletions(-) rename web-server/plugins/slycat-cca/js/components/{CCATable.js => CCATable.tsx} (50%) rename web-server/plugins/slycat-parameter-image/js/{parameter-image-table.js => parameter-image-table.ts} (97%) diff --git a/package-lock.json b/package-lock.json index f91c7e1e3..9a419e7b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,15 +42,15 @@ "redux-throttle": "0.1.1", "redux-thunk": "^3", "redux-watch": "^1.2.0", - "slickgrid": "^3", + "slickgrid": "^5", "stream-browserify": "3.0.0", "three": "^0", "three-stl-loader": "1.0.6", "three-trackballcontrols": "0.9.0", "urijs": "1.19.11", - "uuid": "^9", - "vtk.js": "^27", - "wslink": "^1", + "uuid": "^10", + "vtk.js": "^32", + "wslink": "^2", "zipinfo.js": "1.0.0" }, "devDependencies": { @@ -70,16 +70,19 @@ "@types/core-js": "^2.5.4", "@types/d3": "^3", "@types/d3v7": "npm:@types/d3@^7.4.0", + "@types/he": "^1.2.3", "@types/jest": "^29", "@types/jquery": "^3.5.5", "@types/jsdom": "^21", "@types/lodash": "^4.14.191", - "@types/node": "^20", + "@types/node": "^22", "@types/react": "^18", "@types/react-dom": "^18", "@types/react-test-renderer": "^18", - "@types/sinon": "^10.0.0", - "@types/uuid": "^9", + "@types/redux-watch": "^1.1.2", + "@types/sinon": "^17", + "@types/sortablejs": "^1.15.8", + "@types/uuid": "^10", "autoprefixer": "^10.1.0", "babel-jest": "^29", "babel-loader": "^9", @@ -88,7 +91,7 @@ "clean-webpack-plugin": "^4", "copy-webpack-plugin": "^12", "css-loader": "^7", - "eslint": "^8", + "eslint": "^9", "eslint-plugin-react": "^7.22.0", "file-loader": "^6.2.0", "html-loader": "^5", @@ -104,7 +107,7 @@ "sass": "^1", "sass-loader": "^16", "shader-loader": "^1.3.1", - "sinon": "^15", + "sinon": "^19", "style-loader": "^4", "typescript": "^5", "url-loader": "^4.1.1", @@ -2417,17 +2420,42 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -2435,7 +2463,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2449,16 +2477,13 @@ "license": "Python-2.0" }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2477,27 +2502,37 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@eslint/js": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@fortawesome/fontawesome-common-types": { @@ -2546,22 +2581,6 @@ "react": ">=16.3" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2576,13 +2595,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -3485,6 +3510,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@msgpack/msgpack": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", + "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==", + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, "node_modules/@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", @@ -3620,12 +3654,6 @@ } } }, - "node_modules/@reduxjs/toolkit/node_modules/reselect": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", - "license": "MIT" - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -4152,6 +4180,13 @@ "@types/node": "*" } }, + "node_modules/@types/he": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.3.tgz", + "integrity": "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4264,9 +4299,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.16.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.6.tgz", - "integrity": "sha512-T7PpxM/6yeDE+AdlVysT62BX6/bECZOmQAgiFg5NoBd5MQheZ3tzal7f1wvzfiEcmrcJNRi2zRr2nY2zF+0uqw==", + "version": "22.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", + "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -4334,6 +4369,13 @@ "@types/react": "*" } }, + "node_modules/@types/redux-watch": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/redux-watch/-/redux-watch-1.1.2.tgz", + "integrity": "sha512-pooK4MLNYmTyfOU7jy/ZmS2mpbSHkEVpWIcK4/BRbaegOnCB4PYA2JY88vBXE2LVkhPM+du1Z+lVzRiewMz6wg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -4375,9 +4417,9 @@ } }, "node_modules/@types/sinon": { - "version": "10.0.20", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", - "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", "dev": true, "license": "MIT", "dependencies": { @@ -4408,6 +4450,13 @@ "@types/node": "*" } }, + "node_modules/@types/sortablejs": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.8.tgz", + "integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -4429,12 +4478,18 @@ "license": "MIT" }, "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true, "license": "MIT" }, + "node_modules/@types/webxr": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz", + "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", @@ -4462,13 +4517,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -5309,6 +5357,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/babel-plugin-module-resolver/node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -7164,9 +7219,9 @@ "license": "MIT" }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -7197,16 +7252,16 @@ } }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dom-converter": { @@ -7647,44 +7702,43 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -7696,10 +7750,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-react": { @@ -7735,19 +7797,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -7814,13 +7863,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7872,9 +7914,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7882,20 +7924,20 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -7931,22 +7973,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7957,19 +7983,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8015,45 +8028,32 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8351,16 +8351,16 @@ "license": "MIT" }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-loader": { @@ -8504,35 +8504,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16" } }, "node_modules/flatted": { @@ -8882,13 +8864,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -12067,12 +12042,12 @@ } }, "node_modules/jquery-ui": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.2.tgz", - "integrity": "sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.0.tgz", + "integrity": "sha512-mPfYKBoRCf0MzaT2cyW5i3IuZ7PfTITaasO5OFLAQxrHuI+ZxruPa+4/K1OMNT8oElLWGtIxc9aRbyw20BKr8g==", "license": "MIT", "dependencies": { - "jquery": ">=1.8.0 <4.0.0" + "jquery": ">=1.12.0 <5.0.0" } }, "node_modules/jquery.scrollintoview": { @@ -12715,23 +12690,23 @@ "license": "MIT" }, "node_modules/nise": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", - "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/text-encoding": "^0.7.2", + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", "just-extend": "^6.2.0", - "path-to-regexp": "^6.2.1" + "path-to-regexp": "^8.1.0" } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", - "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", + "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13377,11 +13352,14 @@ } }, "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.1.0.tgz", + "integrity": "sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/path-type": { "version": "5.0.0", @@ -14361,10 +14339,9 @@ "license": "MIT" }, "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, "node_modules/resolve": { @@ -15089,18 +15066,17 @@ "license": "ISC" }, "node_modules/sinon": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz", - "integrity": "sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==", - "deprecated": "16.1.1", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.3.0", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.4", + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", "supports-color": "^7.2.0" }, "funding": { @@ -15108,6 +15084,16 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", + "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, "node_modules/sinon/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -15164,13 +15150,15 @@ } }, "node_modules/slickgrid": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/slickgrid/-/slickgrid-3.0.4.tgz", - "integrity": "sha512-0CY57mxZWJ5Y9XI29ogC4kIMQmyOIHSbmCefOnFFvVUsaI0yqKHfOC84TtGwCScxQfYWFM4AhvWBrae3ff3YZA==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/slickgrid/-/slickgrid-5.13.0.tgz", + "integrity": "sha512-Xb7SVqlBq8aOkqC2nhjp9z8ML+qMFlboY8BxNZDkzptjsQ5r7UyQsYxGnh7nVug9EkgouVoxicmhLS/bpykx1A==", "license": "MIT", "dependencies": { - "jquery": ">=3.0.0", - "sortablejs": "^1.15.0" + "sortablejs": "^1.15.3" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/sockjs": { @@ -16181,9 +16169,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -16219,12 +16207,13 @@ } }, "node_modules/vtk.js": { - "version": "27.5.0", - "resolved": "https://registry.npmjs.org/vtk.js/-/vtk.js-27.5.0.tgz", - "integrity": "sha512-td2P9TnLPj2Mypyq57BQQPhS2DUuebIhjT0vn8aMn0EWK4Jm9rzHyVg+IKSw1mw7UnIKeE/E5xsd/96rpI1d4w==", + "version": "32.2.0", + "resolved": "https://registry.npmjs.org/vtk.js/-/vtk.js-32.2.0.tgz", + "integrity": "sha512-oA7ciA0rR/jAf4de5gM2lD6zpFjkosoXNoLaBmBA4LF35L9ccCB8c4M1tf3VH1r97Zur8XoSwleRPakGzUgzvA==", "license": "BSD-3-Clause", "dependencies": { - "@babel/runtime": "7.17.9", + "@babel/runtime": "7.22.11", + "@types/webxr": "^0.5.5", "commander": "9.2.0", "d3-scale": "4.0.2", "fast-deep-equal": "^3.1.3", @@ -16247,16 +16236,16 @@ "peerDependencies": { "@babel/preset-env": "^7.17.10", "autoprefixer": "^10.4.7", - "wslink": "^1.1.0" + "wslink": ">=1.1.0 || ^2.0.0" } }, "node_modules/vtk.js/node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz", + "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==", "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -16286,12 +16275,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vtk.js/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT" - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -16984,12 +16967,12 @@ } }, "node_modules/wslink": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/wslink/-/wslink-1.12.4.tgz", - "integrity": "sha512-4AJtHZ0qtBa7zOp0e3R5OJxQ6HY9eo+jDPcjms6E2ChXgQ5D4hlMynFF8mEFXx54+PmLo8f2DMiM9bxN6QTAjg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/wslink/-/wslink-2.2.1.tgz", + "integrity": "sha512-kBhNNW7RtVBY1e6WZJvp/XvYHUkWTJupq1FhG5FAv9f6Do868zsaV+SPM1kD7pcHxF/d8IcmzCP5Ty1m8pIVFQ==", "license": "BSD-3-Clause", "dependencies": { - "json5": "2.2.3" + "@msgpack/msgpack": "^2.8.0" } }, "node_modules/xmlbuilder2": { diff --git a/package.json b/package.json index c6c6acc46..10506887f 100644 --- a/package.json +++ b/package.json @@ -52,15 +52,15 @@ "redux-throttle": "0.1.1", "redux-thunk": "^3", "redux-watch": "^1.2.0", - "slickgrid": "^3", + "slickgrid": "^5", "stream-browserify": "3.0.0", "three": "^0", "three-stl-loader": "1.0.6", "three-trackballcontrols": "0.9.0", "urijs": "1.19.11", - "uuid": "^9", - "vtk.js": "^27", - "wslink": "^1", + "uuid": "^10", + "vtk.js": "^32", + "wslink": "^2", "zipinfo.js": "1.0.0" }, "devDependencies": { @@ -80,16 +80,19 @@ "@types/core-js": "^2.5.4", "@types/d3": "^3", "@types/d3v7": "npm:@types/d3@^7.4.0", + "@types/he": "^1.2.3", "@types/jest": "^29", "@types/jquery": "^3.5.5", "@types/jsdom": "^21", "@types/lodash": "^4.14.191", - "@types/node": "^20", + "@types/node": "^22", "@types/react": "^18", "@types/react-dom": "^18", "@types/react-test-renderer": "^18", - "@types/sinon": "^10.0.0", - "@types/uuid": "^9", + "@types/redux-watch": "^1.1.2", + "@types/sinon": "^17", + "@types/sortablejs": "^1.15.8", + "@types/uuid": "^10", "autoprefixer": "^10.1.0", "babel-jest": "^29", "babel-loader": "^9", @@ -98,7 +101,7 @@ "clean-webpack-plugin": "^4", "copy-webpack-plugin": "^12", "css-loader": "^7", - "eslint": "^8", + "eslint": "^9", "eslint-plugin-react": "^7.22.0", "file-loader": "^6.2.0", "html-loader": "^5", @@ -114,7 +117,7 @@ "sass": "^1", "sass-loader": "^16", "shader-loader": "^1.3.1", - "sinon": "^15", + "sinon": "^19", "style-loader": "^4", "typescript": "^5", "url-loader": "^4.1.1", diff --git a/web-server/plugins/slycat-cca/js/components/CCATable.js b/web-server/plugins/slycat-cca/js/components/CCATable.tsx similarity index 50% rename from web-server/plugins/slycat-cca/js/components/CCATable.js rename to web-server/plugins/slycat-cca/js/components/CCATable.tsx index 467dcda63..5cc7e4b86 100644 --- a/web-server/plugins/slycat-cca/js/components/CCATable.js +++ b/web-server/plugins/slycat-cca/js/components/CCATable.tsx @@ -1,18 +1,15 @@ -import slick_grid_css from "slickgrid/slick.grid.css"; -import slick_default_theme_css from "slickgrid/slick-default-theme.css"; -import slick_headerbuttons_css from "slickgrid/plugins/slick.headerbuttons.css"; -import slick_slycat_theme_css from "css/slick-slycat-theme.css"; - -import "slickgrid/slick.interactions.js"; -import "slickgrid/slick.core"; -import "slickgrid/slick.grid"; -import "slickgrid/plugins/slick.rowselectionmodel"; -import "slickgrid/plugins/slick.headerbuttons"; -import "slickgrid/plugins/slick.autotooltips"; +import { + SlickRowSelectionModel, + SlickAutoTooltips, + SlickGrid, + SlickHeaderButtons, +} from "slickgrid"; +import Sortable from "sortablejs"; +window.Sortable = Sortable; import React from "react"; -import { connect } from 'react-redux'; -import { setVariableSelected, setVariableSorted, setSimulationsSelected } from '../actions'; +import { connect } from "react-redux"; +import { setVariableSelected, setVariableSorted, setSimulationsSelected } from "../actions"; import api_root from "js/slycat-api-root"; import SlickGridDataProvider from "./SlickGridDataProvider"; @@ -28,119 +25,148 @@ class CCATable extends React.Component { this.cca_table = React.createRef(); this.columns = []; - this.columns.push(this.make_column(this.props.metadata["column-count"]-1, "headerSimId", "rowSimId")); - for(var i in this.props.inputs) + this.columns.push( + this.make_column(this.props.metadata["column-count"] - 1, "headerSimId", "rowSimId"), + ); + for (var i in this.props.inputs) this.columns.push(this.make_column(this.props.inputs[i], "headerInput", "rowInput")); - for(var i in this.props.outputs) + for (var i in this.props.outputs) this.columns.push(this.make_column(this.props.outputs[i], "headerOutput", "rowOutput")); - for(var i in this.props.others) + for (var i in this.props.others) this.columns.push(this.make_column(this.props.others[i], "headerOther", "rowOther")); this.data = new SlickGridDataProvider({ - api_root : api_root, - mid : this.props.mid, - aid : this.props.aid, - metadata : this.props.metadata, - sort_column : this.props.sort_variable, - sort_order : this.props.sort_order, - inputs : this.props.inputs, - outputs : this.props.outputs, + api_root: api_root, + mid: this.props.mid, + aid: this.props.aid, + metadata: this.props.metadata, + sort_column: this.props.sort_variable, + sort_order: this.props.sort_order, + inputs: this.props.inputs, + outputs: this.props.outputs, }); } - make_column = (column_index, header_class, cell_class) => - { + make_column = (column_index, header_class, cell_class) => { return { - id : column_index, - field : column_index, - name : this.props.metadata["column-names"][column_index], - sortable : false, - headerCssClass : header_class, - cssClass : cell_class, - formatter : this.cell_formatter, - header : - { - buttons : - [ + id: column_index, + field: column_index, + name: this.props.metadata["column-names"][column_index], + sortable: false, + headerCssClass: header_class, + cssClass: cell_class, + formatter: this.cell_formatter, + header: { + buttons: [ { - cssClass : this.props.sort_variable == column_index ? (this.props.sort_order == "ascending" ? "icon-sort-ascending" : "icon-sort-descending") : "icon-sort-off", - tooltip : this.props.sort_variable == column_index ? (this.props.sort_order == "ascending" ? "Sort descending" : "Sort ascending") : "Sort ascending", - command : this.props.sort_variable == column_index ? (this.props.sort_order == "ascending" ? "sort-descending" : "sort-ascending") : "sort-ascending" - } - ] - } + cssClass: + this.props.sort_variable == column_index + ? this.props.sort_order == "ascending" + ? "icon-sort-ascending" + : "icon-sort-descending" + : "icon-sort-off", + tooltip: + this.props.sort_variable == column_index + ? this.props.sort_order == "ascending" + ? "Sort descending" + : "Sort ascending" + : "Sort ascending", + command: + this.props.sort_variable == column_index + ? this.props.sort_order == "ascending" + ? "sort-descending" + : "sort-ascending" + : "sort-ascending", + }, + ], + }, }; - } - - cell_formatter = (row, cell, value, columnDef, dataContext) => - { - if(columnDef.colormap) - return "
" + this.value_formatter(value) + "
"; - else if(value==null) - return "
" + this.value_formatter(value) + "
"; + }; + + cell_formatter = (row, cell, value, columnDef, dataContext) => { + if (columnDef.colormap) + return ( + "
" + + this.value_formatter(value) + + "
" + ); + else if (value == null) + return ( + "
" + + this.value_formatter(value) + + "
" + ); return this.value_formatter(value); - } + }; - value_formatter = (value) => - { - return value == null ? " " : (value + "").replace(/&/g,"&").replace(//g,">"); - } + value_formatter = (value) => { + return value == null + ? " " + : (value + "").replace(/&/g, "&").replace(//g, ">"); + }; - _color_variable = (variable) => - { + _color_variable = (variable) => { let self = this; var columns = self.grid.getColumns(); - for(var i in columns) - { + for (var i in columns) { var column = columns[i]; - if(this.props.colormap !== null && column.id == variable) - { + if (this.props.colormap !== null && column.id == variable) { // Make a copy of our global colormap, then adjust its domain to match our column-specific data. column.colormap = self.props.colormap.copy(); - var new_domain = [] - var domain_scale = d3.scale.linear().domain([0, column.colormap.range().length]).range([self.props.metadata["column-min"][column.id], self.props.metadata["column-max"][column.id]]); - for(var i in column.colormap.range()) - new_domain.push(domain_scale(i)); + var new_domain = []; + var domain_scale = d3.scale + .linear() + .domain([0, column.colormap.range().length]) + .range([ + self.props.metadata["column-min"][column.id], + self.props.metadata["column-max"][column.id], + ]); + for (var i in column.colormap.range()) new_domain.push(domain_scale(i)); column.colormap.domain(new_domain); column.cssClass = column.cssClass.split(" ")[0] + " highlight"; - } - else - { + } else { column.colormap = null; column.cssClass = column.cssClass.split(" ")[0]; } } self.grid.invalidate(); - } + }; - set_sort = (column, order) => - { + set_sort = (column, order) => { let self = this; // Dispatch setVariableSorted action whenever header is clicked. self.props.setVariableSorted(column); self.data.set_sort(column, order); - self.data.get_indices("sorted", self.props.row_selection, function(sorted_rows) - { + self.data.get_indices("sorted", self.props.row_selection, function (sorted_rows) { self.grid.invalidate(); table_helpers._set_selected_rows_no_trigger(self); }); - } + }; - _array_equal = (a, b) => - { + _array_equal = (a, b) => { return $(a).not(b).length == 0 && $(b).not(a).length == 0; - } + }; componentDidMount() { let self = this; - this.grid = new Slick.Grid(this.cca_table.current, this.data, this.columns, {explicitInitialization : true, enableColumnReorder : false}); + this.grid = new SlickGrid(this.cca_table.current, this.data, this.columns, { + explicitInitialization: true, + enableColumnReorder: false, + }); this.data.onDataLoaded.subscribe(function (e, args) { for (var i = args.from; i <= args.to; i++) { @@ -149,59 +175,50 @@ class CCATable extends React.Component { self.grid.render(); }); - let header_buttons = new Slick.Plugins.HeaderButtons(); - header_buttons.onCommand.subscribe(function(e, args) - { + let header_buttons = new SlickHeaderButtons(); + header_buttons.onCommand.subscribe(function (e, args) { var column = args.column; var button = args.button; var command = args.command; var grid = args.grid; - for(var i in self.columns) - { + for (var i in self.columns) { self.columns[i].header.buttons[0].cssClass = "icon-sort-off"; self.columns[i].header.buttons[0].tooltip = "Sort ascending"; self.columns[i].header.buttons[0].command = "sort-ascending"; grid.updateColumnHeader(self.columns[i].id); } - if(command == "sort-ascending") - { - button.cssClass = 'icon-sort-ascending'; - button.command = 'sort-descending'; - button.tooltip = 'Sort descending'; + if (command == "sort-ascending") { + button.cssClass = "icon-sort-ascending"; + button.command = "sort-descending"; + button.tooltip = "Sort descending"; self.set_sort(column.id, "ascending"); - } - else if(command == "sort-descending") - { - button.cssClass = 'icon-sort-descending'; - button.command = 'sort-ascending'; - button.tooltip = 'Sort ascending'; + } else if (command == "sort-descending") { + button.cssClass = "icon-sort-descending"; + button.command = "sort-ascending"; + button.tooltip = "Sort ascending"; self.set_sort(column.id, "descending"); } }); this.grid.registerPlugin(header_buttons); - this.grid.registerPlugin(new Slick.AutoTooltips({enableForHeaderCells:true})); + this.grid.registerPlugin(new SlickAutoTooltips({ enableForHeaderCells: true })); - this.grid.setSelectionModel(new Slick.RowSelectionModel()); - this.grid.onSelectedRowsChanged.subscribe(function(e, selection) - { - self.data.get_indices("unsorted", selection.rows, function(unsorted_rows) - { + this.grid.setSelectionModel(new SlickRowSelectionModel()); + this.grid.onSelectedRowsChanged.subscribe(function (e, selection) { + self.data.get_indices("unsorted", selection.rows, function (unsorted_rows) { // Need to convert to a normal Array because sometimes unsorted_rows comes back as // an Int32Array, which does not bookmark correctly. let unsorted_rows_array = Array.from(unsorted_rows); self.props.setSimulationsSelected(unsorted_rows_array); }); }); - this.grid.onHeaderClick.subscribe(function (e, args) - { + this.grid.onHeaderClick.subscribe(function (e, args) { // Dispatch setVariableSelected action whenever header is clicked. // When it's the same variable as current, react doesn't update any components // so no need to check for it here. - if (self.props.metadata["column-types"][args.column.id] != "string") - { + if (self.props.metadata["column-types"][args.column.id] != "string") { self.props.setVariableSelected(args.column.field); } }); @@ -215,39 +232,33 @@ class CCATable extends React.Component { componentDidUpdate(prevProps, prevState, snapshot) { // Color variable when selected variable changes - if(prevProps.variable_selection !== this.props.variable_selection) { + if (prevProps.variable_selection !== this.props.variable_selection) { this._color_variable(this.props.variable_selection); } // Color variable when colormap changes - if(prevProps.colormap !== this.props.colormap) { + if (prevProps.colormap !== this.props.colormap) { this._color_variable(this.props.variable_selection); } // Set selected rows when selection changes // First check if props.row_selection changed during this update - if(_.xor(prevProps.row_selection, this.props.row_selection).length > 0) { + if (_.xor(prevProps.row_selection, this.props.row_selection).length > 0) { // Then check if the selected rows aren't already selected in the grid let self = this; - this.data.get_indices("unsorted", this.grid.getSelectedRows(), function(unsorted_rows) - { - if(_.xor(unsorted_rows, self.props.row_selection).length > 0) { + this.data.get_indices("unsorted", this.grid.getSelectedRows(), function (unsorted_rows) { + if (_.xor(unsorted_rows, self.props.row_selection).length > 0) { table_helpers._set_selected_rows_no_trigger(self); } }); } // Resize - if(prevProps.width != this.props.width || prevProps.height != this.props.height) - { + if (prevProps.width != this.props.width || prevProps.height != this.props.height) { this.grid.resizeCanvas(); } } - handle_component_change_transition = () => - { - - } + handle_component_change_transition = () => {}; render() { - return ( @@ -258,7 +269,7 @@ class CCATable extends React.Component { } } -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { mid: state.derived.model_id, inputs: state.derived.input_columns, @@ -272,14 +283,11 @@ const mapStateToProps = state => { variable_selection: state.variable_selected, width: state.derived.table_width, height: state.derived.table_height, - } + }; }; -export default connect( - mapStateToProps, - { - setVariableSelected, - setVariableSorted, - setSimulationsSelected, - } -)(CCATable) \ No newline at end of file +export default connect(mapStateToProps, { + setVariableSelected, + setVariableSorted, + setSimulationsSelected, +})(CCATable); diff --git a/web-server/plugins/slycat-cca/js/components/SlickGridDataProvider.js b/web-server/plugins/slycat-cca/js/components/SlickGridDataProvider.js index 26ec10119..b80d5bddd 100644 --- a/web-server/plugins/slycat-cca/js/components/SlickGridDataProvider.js +++ b/web-server/plugins/slycat-cca/js/components/SlickGridDataProvider.js @@ -1,11 +1,11 @@ import d3 from "d3"; import * as chunker from "js/chunker"; +import { SlickEvent } from "slickgrid"; -var SlickGridDataProvider = function(parameters) -{ +var SlickGridDataProvider = function (parameters) { var self = this; - self.api_root = parameters.api_root + self.api_root = parameters.api_root; self.mid = parameters.mid; self.aid = parameters.aid; self.metadata = parameters.metadata; @@ -20,188 +20,176 @@ var SlickGridDataProvider = function(parameters) self.pages_in_progress = {}; self.page_size = 50; - self.onDataLoaded = new Slick.Event(); + self.onDataLoaded = new SlickEvent(); - self.getLength = function() - { + self.getLength = function () { return self.metadata["row-count"]; - } + }; - self.getItem = function(index) - { + self.getItem = function (index) { var column_begin = 0; var column_end = self.metadata["column-count"]; var page = Math.floor(index / self.page_size); var page_begin = page * self.page_size; - if(self.pages_in_progress[page]) - { + if (self.pages_in_progress[page]) { return null; } - if(!(page in self.pages)) - { + if (!(page in self.pages)) { self.pages_in_progress[page] = true; var row_begin = page_begin; var row_end = (page + 1) * self.page_size; var sort = ""; - if(self.sort_column !== null && self.sort_order !== null) - { + if (self.sort_column !== null && self.sort_order !== null) { var sort_column = "a" + self.sort_column; var sort_order = self.sort_order; - if(sort_order == 'ascending') - { - sort_order = 'asc'; + if (sort_order == "ascending") { + sort_order = "asc"; + } else if (sort_order == "descending") { + sort_order = "desc"; } - else if(sort_order == 'descending') - { - sort_order = 'desc'; - } - if(self.sort_column == self.metadata["column-count"]-1) - sort_column = "index(0)"; + if (self.sort_column == self.metadata["column-count"] - 1) sort_column = "index(0)"; sort = "/order: rank(" + sort_column + ', "' + sort_order + '")'; } - $.ajax( - { - type : "GET", - url : self.api_root + "models/" + self.mid + "/arraysets/" + self.aid + "/data?hyperchunks=0/" + column_begin + ":" + (column_end - 1) + "|index(0)" + sort + "/" + row_begin + ":" + row_end, - success : function(data) - { + $.ajax({ + type: "GET", + url: + self.api_root + + "models/" + + self.mid + + "/arraysets/" + + self.aid + + "/data?hyperchunks=0/" + + column_begin + + ":" + + (column_end - 1) + + "|index(0)" + + sort + + "/" + + row_begin + + ":" + + row_end, + success: function (data) { self.pages[page] = []; - for(var i=0; i < data[0].length; i++) - { + for (var i = 0; i < data[0].length; i++) { var result = {}; - for(var j = column_begin; j != column_end; ++j) - { + for (var j = column_begin; j != column_end; ++j) { result[j] = data[j][i]; } self.pages[page].push(result); } self.pages_in_progress[page] = false; - self.onDataLoaded.notify({from: row_begin, to: row_end}); + self.onDataLoaded.notify({ from: row_begin, to: row_end }); }, - error: function(request, status, reason_phrase) - { + error: function (request, status, reason_phrase) { console.log("error", request, status, reason_phrase); - } + }, }); return null; } return self.pages[page][index - page_begin]; - } + }; - self.getItemMetadata = function(index) - { + self.getItemMetadata = function (index) { var page = Math.floor(index / self.page_size); - if((self.pages_in_progress[page]) || !(page in self.pages)) - { + if (self.pages_in_progress[page] || !(page in self.pages)) { return null; } var row = this.getItem(index); var column_end = self.analysis_columns.length; var cssClasses = ""; - for(var i=0; i != column_end; i++) { - if(row[ self.analysis_columns[i] ]==null) { + for (var i = 0; i != column_end; i++) { + if (row[self.analysis_columns[i]] == null) { cssClasses += "nullRow"; } } - if(cssClasses != "") - return {"cssClasses" : cssClasses}; + if (cssClasses != "") return { cssClasses: cssClasses }; return null; - } + }; - self.set_sort = function(column, order) - { - if(column == self.sort_column && order == self.sort_order) - { + self.set_sort = function (column, order) { + if (column == self.sort_column && order == self.sort_order) { return; } self.sort_column = column; self.sort_order = order; self.pages = {}; - } + }; - self.get_indices = function(direction, rows, callback) - { - if(rows.length == 0) - { + self.get_indices = function (direction, rows, callback) { + if (rows.length == 0) { callback([]); return; } // We have no sort column or order, so just returning the same rows as were asked for since they're in the same order - if(self.sort_column == null || self.sort_order == null) - { + if (self.sort_column == null || self.sort_order == null) { callback(rows); - } - else - { - if(self.ranked_indices[self.sort_column]) - { + } else { + if (self.ranked_indices[self.sort_column]) { // we have data for this column, so figure out what to return var indices = self.ranked_indices[self.sort_column]; // Reverse response indexes for descending sort order - if(self.sort_order == 'descending') - { + if (self.sort_order == "descending") { var plain_array = []; - for(var i=0; i 0) { num_origin_cols = 1 }; - num_editable_cols = editable_columns["attributes"].length; - - // set up slick grid column names (with non-mutable columns) - for (var i = 0; i != num_cols; i++) { - - // set up as non-editable column - grid_columns.push(make_column(i, - metadata[0]["column-names"][include_columns[i]], null, null)); - } - - // set up model origin, if available (also non-mutable) - for (var i = 0; i != num_origin_cols; i++) { - grid_columns.push(make_column(num_cols, - "From Model", null, null)); - } - - // set up editable column names - for (var i = 0; i != num_editable_cols; i++) { - editable_col_types.push(editable_columns["attributes"][i].type); - if (editable_col_types[i] == "freetext") { - - // set up freetext editor - grid_columns.push(make_column(num_cols + num_origin_cols + i, - editable_columns["attributes"][i].name, TextEditor, null)); - - } else { - - // set up categorical editor - grid_columns.push(make_column(num_cols + num_origin_cols + i, - editable_columns["attributes"][i].name, SelectCellEditor, - editable_columns["categories"][i])); - } - } - - // produce new data table with correct columns - var table_data = []; - for (var i = 0; i != num_cols; i++) { - table_data.push(data[0]["data"][include_columns[i]]) - } - - // populate model origin data - for (var i = 0; i != num_origin_cols; i++) { - table_data.push(model_origin); - } - - // populate editable column data - for (var i = 0; i != num_editable_cols; i++) { - table_data.push(editable_columns["data"][i]); - } - - // adjust number of columns to reflect origin column - // (from now on treat origin column the same as any non-mutable data) - num_cols = num_cols + num_origin_cols - - // produce a vector of sequential id for table rows and a zero vector - var row_id = []; - var zero_vec = []; - for (var i = 0; i != num_rows; i++) { - row_id.push(i); - zero_vec.push(0); - } - - // add two columns to data, unique id and selection mode - table_data.push(row_id); - table_data.push(zero_vec); - grid_rows = d3.transpose(table_data); - - // set up slick grid - data_view = new Slick.Data.DataView(); - grid_view = new Slick.Grid("#dac-datapoints-table", data_view, - grid_columns, grid_options); - - // keep track of shift or meta key - grid_view.onClick.subscribe(one_row_selected); - - // set table data (second to last column is ids) - data_view.setItems(grid_rows, num_cols + num_editable_cols); - - // set up row selection - grid_view.setSelectionModel (new Slick.RowSelectionModel()); - //grid_view.onSelectedRowsChanged.subscribe(multiple_rows_selected); - - // helpers for grid to respond to data_view changes - data_view.onRowCountChanged.subscribe(change_rows); - data_view.onRowsChanged.subscribe(change_cols); - - // update meta data function to accommodate multiple selection classes - data_view.getItemMetadata = color_rows(data_view.getItemMetadata); - - // add sorting - grid_view.onSort.subscribe(col_sort); - - // set up initial column filters - columnFilters = init_col_filters; - - // do filtering after something is typed - $(grid_view.getHeaderRow()).delegate(":input", "change keyup", function (e) { - var columnId = $(this).data("columnId"); - if (columnId != null) { - - // get previous row in data index, if it exists - var prev_data_row = null; - if (prev_row_selected != null) { - prev_data_row = convert_row_ids([prev_row_selected])[0]; - } - - // save data filter - columnFilters[columnId] = $.trim($(this).val().toLowerCase()); - - // create regular expression - filter_reg_exp(columnId); - - // filter data - data_view.refresh(); - - // convert previous row selected into new filtered order - if (prev_data_row != null) { +module.setup = function ( + metadata, + data, + include_columns, + editable_columns, + model_origin, + MODEL_NAME, + max_freetext_len, + MAX_NUM_SEL, + USER_SEL_COLORS, + init_sort_order, + init_sort_col, + init_col_filters, +) { + // keep track of number of metadata columns + num_metadata_cols = metadata[0]["column-count"]; + + // set up callback for data download button + var download_button = document.querySelector("#dac-download-table-button"); + download_button.addEventListener("click", download_button_callback); + + // set maximum length of freetext for editable columns + MAX_FREETEXT_LEN = max_freetext_len; + + // set model name + model_name = MODEL_NAME; + + // set maximum number of selections + // (note this cannot exceed 8 for the table, as of 11/25/2019) + max_num_sel = MAX_NUM_SEL; + + // user colors for outputing table + user_sel_colors = USER_SEL_COLORS; + + // get number of rows and total available columns in data table + num_rows = data[0]["data"][0].length; + + // set number of columns to use + num_cols = include_columns.length; + if (model_origin.length > 0) { + num_origin_cols = 1; + } + num_editable_cols = editable_columns["attributes"].length; + + // set up slick grid column names (with non-mutable columns) + for (var i = 0; i != num_cols; i++) { + // set up as non-editable column + grid_columns.push(make_column(i, metadata[0]["column-names"][include_columns[i]], null, null)); + } + + // set up model origin, if available (also non-mutable) + for (var i = 0; i != num_origin_cols; i++) { + grid_columns.push(make_column(num_cols, "From Model", null, null)); + } + + // set up editable column names + for (var i = 0; i != num_editable_cols; i++) { + editable_col_types.push(editable_columns["attributes"][i].type); + if (editable_col_types[i] == "freetext") { + // set up freetext editor + grid_columns.push( + make_column( + num_cols + num_origin_cols + i, + editable_columns["attributes"][i].name, + TextEditor, + null, + ), + ); + } else { + // set up categorical editor + grid_columns.push( + make_column( + num_cols + num_origin_cols + i, + editable_columns["attributes"][i].name, + SelectCellEditor, + editable_columns["categories"][i], + ), + ); + } + } + + // produce new data table with correct columns + var table_data = []; + for (var i = 0; i != num_cols; i++) { + table_data.push(data[0]["data"][include_columns[i]]); + } + + // populate model origin data + for (var i = 0; i != num_origin_cols; i++) { + table_data.push(model_origin); + } + + // populate editable column data + for (var i = 0; i != num_editable_cols; i++) { + table_data.push(editable_columns["data"][i]); + } + + // adjust number of columns to reflect origin column + // (from now on treat origin column the same as any non-mutable data) + num_cols = num_cols + num_origin_cols; + + // produce a vector of sequential id for table rows and a zero vector + var row_id = []; + var zero_vec = []; + for (var i = 0; i != num_rows; i++) { + row_id.push(i); + zero_vec.push(0); + } + + // add two columns to data, unique id and selection mode + table_data.push(row_id); + table_data.push(zero_vec); + grid_rows = d3.transpose(table_data); + + // set up slick grid + data_view = new SlickDataView(); + grid_view = new SlickGrid("#dac-datapoints-table", data_view, grid_columns, grid_options); + + // keep track of shift or meta key + grid_view.onClick.subscribe(one_row_selected); + + // set table data (second to last column is ids) + data_view.setItems(grid_rows, num_cols + num_editable_cols); + + // set up row selection + grid_view.setSelectionModel(new SlickRowSelectionModel()); + //grid_view.onSelectedRowsChanged.subscribe(multiple_rows_selected); + + // helpers for grid to respond to data_view changes + data_view.onRowCountChanged.subscribe(change_rows); + data_view.onRowsChanged.subscribe(change_cols); + + // update meta data function to accommodate multiple selection classes + data_view.getItemMetadataOld = data_view.getItemMetadata; + data_view.getItemMetadata = color_rows(); + + // add sorting + grid_view.onSort.subscribe(col_sort); + + // set up initial column filters + columnFilters = init_col_filters; + + // do filtering after something is typed + $(grid_view.getHeaderRow()).delegate(":input", "change keyup", function (e) { + var columnId = $(this).data("columnId"); + if (columnId != null) { + // get previous row in data index, if it exists + var prev_data_row = null; + if (prev_row_selected != null) { + prev_data_row = convert_row_ids([prev_row_selected])[0]; + } - // check that previous row is still visible - var prev_row_update = data_view.getRowById(prev_data_row); - if (prev_row_update != null) { + // save data filter + columnFilters[columnId] = $.trim($(this).val().toLowerCase()); - // update previous row to filtered order - prev_row_selected = prev_row_update; + // create regular expression + filter_reg_exp(columnId); - } else { + // filter data + data_view.refresh(); - // if previous row is not visible, then un-highlight - unhighlight_prev_row(prev_data_row); - prev_row_selected = null; - } + // convert previous row selected into new filtered order + if (prev_data_row != null) { + // check that previous row is still visible + var prev_row_update = data_view.getRowById(prev_data_row); + if (prev_row_update != null) { + // update previous row to filtered order + prev_row_selected = prev_row_update; + } else { + // if previous row is not visible, then un-highlight + unhighlight_prev_row(prev_data_row); + prev_row_selected = null; } + } - // if not empty color filter orange to indicate use - if (columnFilters[columnId] != "") { - - // color filter orange for valid regular expression - if (columnFiltersRegExpValid[columnId] == true) { - $(this).addClass("bg-warning"); - $(this).removeClass("bg-danger"); - $(this).removeClass("text-white"); - - // for invalid regular expression color red - } else { + // if not empty color filter orange to indicate use + if (columnFilters[columnId] != "") { + // color filter orange for valid regular expression + if (columnFiltersRegExpValid[columnId] == true) { + $(this).addClass("bg-warning"); + $(this).removeClass("bg-danger"); + $(this).removeClass("text-white"); - $(this).addClass("bg-danger"); - $(this).addClass("text-white"); - } + // for invalid regular expression color red } else { - - // empty filter, revert to normal - $(this).removeClass("bg-warning"); - $(this).removeClass("bg-danger"); - $(this).removeClass("text-white"); + $(this).addClass("bg-danger"); + $(this).addClass("text-white"); } + } else { + // empty filter, revert to normal + $(this).removeClass("bg-warning"); + $(this).removeClass("bg-danger"); + $(this).removeClass("text-white"); + } - // update bookmarks - var filterEvent = new CustomEvent("DACFilterChanged", { detail: { - columnFilters: columnFilters} }); - document.body.dispatchEvent(filterEvent); - + // update bookmarks + var filterEvent = new CustomEvent("DACFilterChanged", { + detail: { + columnFilters: columnFilters, + }, + }); + document.body.dispatchEvent(filterEvent); + } + }); + + // add filter to header + grid_view.onHeaderRowCellRendered.subscribe(function (e, args) { + $(args.node).empty(); + + // create regular expressions + filter_reg_exp(args.column.id); + + // check if column filter is empty + var set_bg_warning = ""; + var set_text_warning = ""; + if (columnFilters[args.column.id] !== "") { + set_bg_warning = "bg-warning"; + if (columnFiltersRegExpValid[args.column.id] == false) { + set_bg_warning = "bg-danger"; + set_text_warning = "text-white"; } - }); + } - // add filter to header - grid_view.onHeaderRowCellRendered.subscribe(function(e, args) { - $(args.node).empty(); + $( + '', + ) + .data("columnId", args.column.id) + .val(columnFilters[args.column.id]) + .on("search", function () { + // get previous row in data index, if it exists + var prev_data_row = null; + if (prev_row_selected != null) { + prev_data_row = convert_row_ids([prev_row_selected])[0]; + } - // create regular expressions - filter_reg_exp(args.column.id); + // called when user hits the "x" clear button + columnFilters[args.column.id] = ""; + $(this).removeClass("bg-warning"); + $(this).removeClass("bg-danger"); + data_view.refresh(); - // check if column filter is empty - var set_bg_warning = ""; - var set_text_warning = ""; - if (columnFilters[args.column.id] !== "") { + // update previously selected row + var prev_row_update = data_view.getRowById(prev_data_row); + prev_row_selected = prev_row_update; - set_bg_warning = "bg-warning"; - if (columnFiltersRegExpValid[args.column.id] == false) { - set_bg_warning = "bg-danger"; - set_text_warning = "text-white"; - } + // update bookmarks + var filterEvent = new CustomEvent("DACFilterChanged", { + detail: { + columnFilters: columnFilters, + }, + }); + document.body.dispatchEvent(filterEvent); + }) + .addClass(set_bg_warning) + .addClass(set_text_warning) + .appendTo(args.node); + }); + + // add filters + data_view.setFilter(filter); + + // fit table into container + module.resize(); + + // show selections, if any + module.select_rows(); + + // check for bookmarked sort order + if (init_sort_order != null) { + // check if sort col is valid + if (init_sort_col < num_cols + num_editable_cols) { + // sort by bookmarked column + grid_view.setSortColumn(init_sort_col, init_sort_order); + + // standard ascii compare + // var comparer = function (a,b) { + // return (a[init_sort_col] > b[init_sort_col]) ? 1 : -1; + // } + + // natural sort compare for strings + var comparer = function (a, b) { + if (typeof a[init_sort_col] == "string") { + return a[init_sort_col].localeCompare( + b[init_sort_col], + navigator.languages[0] || navigator.language, + { numeric: true, ignorePunctuation: true }, + ); + } else { + return a[init_sort_col] > b[init_sort_col] ? 1 : -1; } + }; - $('') - .data("columnId", args.column.id) - .val(columnFilters[args.column.id]) - .on('search', function () { - - // get previous row in data index, if it exists - var prev_data_row = null; - if (prev_row_selected != null) { - prev_data_row = convert_row_ids([prev_row_selected])[0]; - } - - // called when user hits the "x" clear button - columnFilters[args.column.id] = ""; - $(this).removeClass("bg-warning"); - $(this).removeClass("bg-danger"); - data_view.refresh(); - - // update previously selected row - var prev_row_update = data_view.getRowById(prev_data_row); - prev_row_selected = prev_row_update; - - // update bookmarks - var filterEvent = new CustomEvent("DACFilterChanged", { detail: { - columnFilters: columnFilters} }); - document.body.dispatchEvent(filterEvent); - - }) - .addClass(set_bg_warning) - .addClass(set_text_warning) - .appendTo(args.node); - }); - - // add filters - data_view.setFilter(filter); - - // fit table into container - module.resize(); - - // show selections, if any - module.select_rows(); - - // check for bookmarked sort order - if (init_sort_order != null) { - - // check if sort col is valid - if (init_sort_col < (num_cols + num_editable_cols)) { - - // sort by bookmarked column - grid_view.setSortColumn(init_sort_col, init_sort_order); - - // standard ascii compare - // var comparer = function (a,b) { - // return (a[init_sort_col] > b[init_sort_col]) ? 1 : -1; - // } - - // natural sort compare for strings - var comparer = function (a,b) { - if (typeof(a[init_sort_col]) == "string") { - return a[init_sort_col].localeCompare(b[init_sort_col], - navigator.languages[0] || navigator.language, - {numeric: true, ignorePunctuation: true}); - } else { - return (a[init_sort_col] > b[init_sort_col]) ? 1 : -1; - } - } - - data_view.sort(comparer, init_sort_order); - } + data_view.sort(comparer, init_sort_order); } - - // jump to current selection (focus then selection 1) - if (selections.focus() != null) { - module.jump_to([selections.focus()]); - } else { - module.jump_to(selections.sel(1)); - }; - -} + } + + // jump to current selection (focus then selection 1) + if (selections.focus() != null) { + module.jump_to([selections.focus()]); + } else { + module.jump_to(selections.sel(1)); + } +}; // make regular expression from filter string -function filter_reg_exp (columnId) -{ - var regExpValid = true; - var filterRegExp = null; - try { - filterRegExp = new RegExp(columnFilters[columnId]); - columnFiltersRegExp[columnId] = filterRegExp; - } catch(e) { - regExpValid = false; - } - columnFiltersRegExpValid[columnId] = regExpValid; +function filter_reg_exp(columnId) { + var regExpValid = true; + var filterRegExp = null; + try { + filterRegExp = new RegExp(columnFilters[columnId]); + columnFiltersRegExp[columnId] = filterRegExp; + } catch (e) { + regExpValid = false; + } + columnFiltersRegExpValid[columnId] = regExpValid; } // check if any column filters are active -module.filters_active = function () -{ - var filters_on = false; - for (var i = 0; i < columnFilters.length; i++) { - if (columnFilters[i] !== "") { - filters_on = true; - } +module.filters_active = function () { + var filters_on = false; + for (var i = 0; i < columnFilters.length; i++) { + if (columnFilters[i] !== "") { + filters_on = true; } + } - return filters_on; -} + return filters_on; +}; // download data table button -var download_button_callback = function () -{ - // get visible data (from filters) - var vis_sel = module.get_filtered_selection(); - - // check that table has at least one row visible - if (vis_sel.length == 0) { - dialog.ajax_error("There are no rows visible in the table. Please relax table filters -- only visible rows can be exported.")("","",""); - return; +var download_button_callback = function () { + // get visible data (from filters) + var vis_sel = module.get_filtered_selection(); + + // check that table has at least one row visible + if (vis_sel.length == 0) { + dialog.ajax_error( + "There are no rows visible in the table. Please relax table filters -- only visible rows can be exported.", + )("", "", ""); + return; + } + + // concatenate all selections + var sel = selections.sel(); + + // intersect visible data and selected data + var filtered_sel = vis_sel.filter((value) => sel.includes(value)); + + // construct model based name for table download + var defaultFilename = model_name + " Metadata_Table.csv"; + defaultFilename = defaultFilename.replace(/ /g, "_"); + + // check if anything is selected + if (filtered_sel.length == 0 && !module.filters_active()) { + // nothing selected: download entire table + write_data_table(vis_sel, defaultFilename); + } else { + // check if dialog is already open + if (!download_dialog_open) { + download_dialog_open = true; + + // something selected, see what user wants to export + openCSVSaveChoiceDialog(filtered_sel, vis_sel, defaultFilename); } - - // concatenate all selections - var sel = selections.sel(); - - // intersect visible data and selected data - var filtered_sel = vis_sel.filter(value => sel.includes(value)); - - // construct model based name for table download - var defaultFilename = model_name + " Metadata_Table.csv"; - defaultFilename = defaultFilename.replace(/ /g,"_"); - - // check if anything is selected - if ((filtered_sel.length == 0) && !module.filters_active()) { - - // nothing selected: download entire table - write_data_table(vis_sel, defaultFilename); - - } else { - - // check if dialog is already open - if (!download_dialog_open) { - - download_dialog_open = true; - - // something selected, see what user wants to export - openCSVSaveChoiceDialog(filtered_sel, vis_sel, defaultFilename); - } - } - } + } +}; // write data table (modified from parameter space model code) -function write_data_table (rows_to_output, defaultFilename) -{ - // convert data table to csv for writing - var csvData = convert_to_csv (rows_to_output); - - module.download_data_table (csvData, defaultFilename); +function write_data_table(rows_to_output, defaultFilename) { + // convert data table to csv for writing + var csvData = convert_to_csv(rows_to_output); + module.download_data_table(csvData, defaultFilename); } // download data table to browser -module.download_data_table = function (csvData, defaultFilename) -{ - - // set up download link - var D = document; - var a = D.createElement("a"); - var strMimeType = "text/plain"; - - //build download link: - a.href = "data:" + strMimeType + ";charset=utf-8," + encodeURIComponent(csvData); - - // opens download dialog - if ('download' in a) { - a.setAttribute("download", defaultFilename); - a.innerHTML = "downloading..."; - D.body.appendChild(a); - setTimeout(function() { - var e = D.createEvent("MouseEvent"); - e.initMouseEvent("click", true, false, window, - 0, 0, 0, 0, 0, false, false, false, false, 0, null); - a.dispatchEvent(e); - D.body.removeChild(a); - }, 66); - return true; - } else { - dialog.ajax_error("Could not download file. Browser incompatibility?")("","",""); - } - +module.download_data_table = function (csvData, defaultFilename) { + // set up download link + var D = document; + var a = D.createElement("a"); + var strMimeType = "text/plain"; + + //build download link: + a.href = "data:" + strMimeType + ";charset=utf-8," + encodeURIComponent(csvData); + + // opens download dialog + if ("download" in a) { + a.setAttribute("download", defaultFilename); + a.innerHTML = "downloading..."; + D.body.appendChild(a); + setTimeout(function () { + var e = D.createEvent("MouseEvent"); + e.initMouseEvent( + "click", + true, + false, + window, + 0, + 0, + 0, + 0, + 0, + false, + false, + false, + false, + 0, + null, + ); + a.dispatchEvent(e); + D.body.removeChild(a); + }, 66); + return true; + } else { + dialog.ajax_error("Could not download file. Browser incompatibility?")("", "", ""); + } }; // generate csv text from data table -function convert_to_csv (rows_to_output) -{ - - // output data in data_view (sorted as desired by user) order - var csv_output = ""; - - // output headers - var headers = module.get_headers(true, true); - csv_output = headers[0].join(","); +function convert_to_csv(rows_to_output) { + // output data in data_view (sorted as desired by user) order + var csv_output = ""; - // look for extra commas/newlines and warn user - var extra_commas_found = headers[1]; - var extra_newlines_found = headers[2]; + // output headers + var headers = module.get_headers(true, true); + csv_output = headers[0].join(","); - // add selection color to header, end line - csv_output += ',User Selection\n' + // look for extra commas/newlines and warn user + var extra_commas_found = headers[1]; + var extra_newlines_found = headers[2]; - var num_vis_rows = grid_view.getDataLength(); + // add selection color to header, end line + csv_output += ",User Selection\n"; - // output data - for (var i = 0; i < num_vis_rows; i++) { + var num_vis_rows = grid_view.getDataLength(); - // get slick grid table data - var item = grid_view.getDataItem(i); + // output data + for (var i = 0; i < num_vis_rows; i++) { + // get slick grid table data + var item = grid_view.getDataItem(i); - // get selection index - var sel_i = item[item.length-2]; + // get selection index + var sel_i = item[item.length - 2]; - // check if data is in the selection - if (rows_to_output.indexOf(sel_i) != -1) { + // check if data is in the selection + if (rows_to_output.indexOf(sel_i) != -1) { + // sanitize row (remove commas) + var csv_row = []; + for (var j = 0; j < num_cols + num_editable_cols; j++) { + var table_entry = String(item[j]); - // sanitize row (remove commas) - var csv_row = []; - for (var j = 0; j < (num_cols + num_editable_cols); j ++) { - - var table_entry = String(item[j]) - - // check for commas for later warning - if (table_entry.indexOf(",") != -1) { - extra_commas_found = true; - } - - // check for newlines for later warning - if (table_entry.search(/\r?\n|\r/) != -1) { - extra_newlines_found = true; - } + // check for commas for later warning + if (table_entry.indexOf(",") != -1) { + extra_commas_found = true; + } - // strip commas/newlines - csv_row.push(table_entry.replace(/, ?/g," ").replace(/\r?\n|\r/g," ").trim()); + // check for newlines for later warning + if (table_entry.search(/\r?\n|\r/) != -1) { + extra_newlines_found = true; + } - } + // strip commas/newlines + csv_row.push( + table_entry + .replace(/, ?/g, " ") + .replace(/\r?\n|\r/g, " ") + .trim(), + ); + } - // add row selection color to last column - csv_row.push(row_sel_color(item)); + // add row selection color to last column + csv_row.push(row_sel_color(item)); - // add row to csv output - csv_output += csv_row + "\n"; - } - } + // add row to csv output + csv_output += csv_row + "\n"; + } + } - // produce warning if extra commas/newlines were detected - if (extra_commas_found || extra_newlines_found) { - dialog.ajax_error("Commas and/or newlines were detected in the table data " + - "text and will be removed in the .csv output file.") - ("","",""); - } + // produce warning if extra commas/newlines were detected + if (extra_commas_found || extra_newlines_found) { + dialog.ajax_error( + "Commas and/or newlines were detected in the table data " + + "text and will be removed in the .csv output file.", + )("", "", ""); + } - return csv_output; + return csv_output; } // returns table headers and checks for extra commas // replaces commas with spaces if replace_commas is true // replaces newlines with spaces if replace_newlines is true -module.get_headers = function (replace_commas, replace_newlines) -{ - - // keep track of extra commas - var extra_commas = false; +module.get_headers = function (replace_commas, replace_newlines) { + // keep track of extra commas + var extra_commas = false; - // keep track of extra newlines - var extra_newlines = false; + // keep track of extra newlines + var extra_newlines = false; - // output headers - var headers = []; - for (var i = 0; i < (num_cols + num_editable_cols); i++) { - var header_name = grid_columns[i].name; + // output headers + var headers = []; + for (var i = 0; i < num_cols + num_editable_cols; i++) { + var header_name = grid_columns[i].name; - // check for commas in column header - if (header_name.indexOf(",") != -1) { - extra_commas = true; - } + // check for commas in column header + if (header_name.indexOf(",") != -1) { + extra_commas = true; + } - // check for newlines - if (header_name.search(/\r?\n|\r/) != -1) { - extra_newlines = true; - } + // check for newlines + if (header_name.search(/\r?\n|\r/) != -1) { + extra_newlines = true; + } - // strip any commas (optional) and add to csv header - if (replace_commas) { - header_name.replace(/, ?/g," "); - } + // strip any commas (optional) and add to csv header + if (replace_commas) { + header_name.replace(/, ?/g, " "); + } - // strip any newlines (optional) and add to csv header - if (replace_newlines) { - header_name.replace(/\r?\n|\r/g," "); - } + // strip any newlines (optional) and add to csv header + if (replace_newlines) { + header_name.replace(/\r?\n|\r/g, " "); + } - // save header - headers.push(header_name.trim()); - } + // save header + headers.push(header_name.trim()); + } - return [headers, extra_commas, extra_newlines]; -} + return [headers, extra_commas, extra_newlines]; +}; // gets user selection color for a row in the table -function row_sel_color (item) -{ - - // convert focus selection to selection-# - var row_sel = selection_type(item); - if (row_sel == 'focus-selection') { - var focus_sel = selections.focus(); - for (var j = 0; j < max_num_sel; j++) { - if (selections.in_sel_x(focus_sel, j+1) != -1) { - row_sel = 'selection-' + (j+1); - break; - } - } - } - - // convert selection-# to user output color - var row_color = ""; - if (row_sel.search("selection-") != -1) { - row_color = user_sel_colors[parseInt(row_sel.charAt(row_sel.length-1))-1]; +function row_sel_color(item) { + // convert focus selection to selection-# + var row_sel = selection_type(item); + if (row_sel == "focus-selection") { + var focus_sel = selections.focus(); + for (var j = 0; j < max_num_sel; j++) { + if (selections.in_sel_x(focus_sel, j + 1) != -1) { + row_sel = "selection-" + (j + 1); + break; + } } + } - return row_color; + // convert selection-# to user output color + var row_color = ""; + if (row_sel.search("selection-") != -1) { + row_color = user_sel_colors[parseInt(row_sel.charAt(row_sel.length - 1)) - 1]; + } + return row_color; } // return table values for a selection -module.selection_values = function (header_cols, rows_to_output, use_data_order) -{ - - // return header values and selection color - var header_vals = [] - var sel_color = [] - - // also return flags indicating if commas/newlines were found - var extra_commas = false; - var extra_newlines = false; - - // go through table rows in table order - var sel_table_order = []; - var num_vis_rows = grid_view.getDataLength(); +module.selection_values = function (header_cols, rows_to_output, use_data_order) { + // return header values and selection color + var header_vals = []; + var sel_color = []; + + // also return flags indicating if commas/newlines were found + var extra_commas = false; + var extra_newlines = false; + + // go through table rows in table order + var sel_table_order = []; + var num_vis_rows = grid_view.getDataLength(); + if (use_data_order) { + num_vis_rows = num_rows; + } + for (var i = 0; i < num_vis_rows; i++) { + // get slick grid table data + var item = null; if (use_data_order) { - num_vis_rows = num_rows; + item = data_view.getItemById(i); + } else { + item = grid_view.getDataItem(i); } - for (var i = 0; i < num_vis_rows; i++) { - - // get slick grid table data - var item = null; - if (use_data_order) { - item = data_view.getItemById(i); - } else { - item = grid_view.getDataItem(i); - } - - // get selection index - var sel_i = item[item.length-2]; - - // check if data is in the selection - if (rows_to_output.indexOf(sel_i) != -1) { - // save selection in table order - sel_table_order.push(sel_i); + // get selection index + var sel_i = item[item.length - 2]; - // get header values - var header_val_j = [] - for (var j = 0; j < header_cols.length; j++) { + // check if data is in the selection + if (rows_to_output.indexOf(sel_i) != -1) { + // save selection in table order + sel_table_order.push(sel_i); - // go through each header in the list - var header_name = String(item[header_cols[j]]); + // get header values + var header_val_j = []; + for (var j = 0; j < header_cols.length; j++) { + // go through each header in the list + var header_name = String(item[header_cols[j]]); - // check for commas for later warning - if (header_name.indexOf(",") != -1) { - extra_commas = true; - } - - // check for newlines for later warning - if (header_name.search(/\r?\n|\r/) != -1) { - extra_newlines = true; - } - - // strip commas and add to header list - header_val_j.push(header_name.replace(/, ?/g, " ") - .replace(/\r?\n|\r/g, " ").trim()); + // check for commas for later warning + if (header_name.indexOf(",") != -1) { + extra_commas = true; + } - } - header_vals.push(header_val_j); + // check for newlines for later warning + if (header_name.search(/\r?\n|\r/) != -1) { + extra_newlines = true; + } - // get selection color - sel_color.push(row_sel_color(item)); + // strip commas and add to header list + header_val_j.push( + header_name + .replace(/, ?/g, " ") + .replace(/\r?\n|\r/g, " ") + .trim(), + ); + } + header_vals.push(header_val_j); - } + // get selection color + sel_color.push(row_sel_color(item)); } + } - return [header_vals, sel_color, sel_table_order, - extra_commas, extra_newlines]; - -} + return [header_vals, sel_color, sel_table_order, extra_commas, extra_newlines]; +}; // opens a dialog to ask user if they want to save selection or whole table // (modified from videoswarm code) -function openCSVSaveChoiceDialog(sel, all_sel, defaultFilename) -{ - // sel contains the filtered selection (both red and blue) - // (always non-empty when called) - - // check if filters have been applied - var filters_applied = module.filters_active(); - - // message to user - var txt = "There are " + sel.length + " selected row(s) visible. What would you like to do?"; - - // if filters have been applied, add cautionary note - if (filters_applied) { - txt = txt + '

Filters ' + - 'have been applied and the entire table may not be visible! To use entire table ' + - 'close this dialog and clear the filters.' - } - - // buttons for dialog - var buttons_save = [ - {className: "btn-light", label:"Cancel"}, - {className: "btn-primary", label:"Save All Visible", icon_class:"fa fa-table"}] - - if (sel.length > 0) { - buttons_save.push({className: "btn-primary", - label:"Save Selected Visible", icon_class:"fa fa-check"}) - }; - - // launch dialog - dialog.dialog( - { - title: "Export Table Data", - message: txt, - buttons: buttons_save, - callback: function(button) - { - // download dialog is complete - download_dialog_open = false; - - if (typeof button !== 'undefined') { - - if(button.label == "Save All Visible") - write_data_table(all_sel, defaultFilename); - - else if(button.label == "Save Selected Visible") - write_data_table(sel, - defaultFilename); - } - }, - }); +function openCSVSaveChoiceDialog(sel, all_sel, defaultFilename) { + // sel contains the filtered selection (both red and blue) + // (always non-empty when called) + + // check if filters have been applied + var filters_applied = module.filters_active(); + + // message to user + var txt = "There are " + sel.length + " selected row(s) visible. What would you like to do?"; + + // if filters have been applied, add cautionary note + if (filters_applied) { + txt = + txt + + '

Filters ' + + "have been applied and the entire table may not be visible! To use entire table " + + "close this dialog and clear the filters."; + } + + // buttons for dialog + var buttons_save = [ + { className: "btn-light", label: "Cancel" }, + { className: "btn-primary", label: "Save All Visible", icon_class: "fa fa-table" }, + ]; + + if (sel.length > 0) { + buttons_save.push({ + className: "btn-primary", + label: "Save Selected Visible", + icon_class: "fa fa-check", + }); + } + + // launch dialog + dialog.dialog({ + title: "Export Table Data", + message: txt, + buttons: buttons_save, + callback: function (button) { + // download dialog is complete + download_dialog_open = false; + + if (typeof button !== "undefined") { + if (button.label == "Save All Visible") write_data_table(all_sel, defaultFilename); + else if (button.label == "Save Selected Visible") write_data_table(sel, defaultFilename); + } + }, + }); } // single row selection function one_row_selected(e, args) { + // pass along shift/meta key information + selections.key_flip(e.shiftKey); - // pass along shift/meta key information - selections.key_flip(e.shiftKey); - - // convert row clicked to data table row - var data_clicked = convert_row_ids([args.row])[0]; - - // check if row is in the subset (and not an editable column) - if (selections.in_subset(data_clicked) && - args.cell < num_cols) { + // convert row clicked to data table row + var data_clicked = convert_row_ids([args.row])[0]; - // keep track of current selection - curr_row_selected = args.row; + // check if row is in the subset (and not an editable column) + if (selections.in_subset(data_clicked) && args.cell < num_cols) { + // keep track of current selection + curr_row_selected = args.row; - // highlight clicked row - highlight_curr_row(); + // highlight clicked row + highlight_curr_row(); - // check for range selection - var range_sel = []; - if (prev_row_selected != null) { - if (selections.shift_key() == true) { - - // get range of data - var range_sel_inds = []; - for (var i = Math.min(args.row, prev_row_selected); - i <= Math.max(args.row, prev_row_selected); i++) { - - range_sel_inds.push(i); - } - - // convert to data ids - range_sel = convert_row_ids(range_sel_inds); - - } + // check for range selection + var range_sel = []; + if (prev_row_selected != null) { + if (selections.shift_key() == true) { + // get range of data + var range_sel_inds = []; + for ( + var i = Math.min(args.row, prev_row_selected); + i <= Math.max(args.row, prev_row_selected); + i++ + ) { + range_sel_inds.push(i); } - // make sure we are in a selection mode - if (selections.sel_type() > 0) { - - // check for range selection - if (range_sel.length > 1) { - - // user selected a range in the table - selections.update_sel_range(range_sel); - - } else { - - // check if row is already selected - // update selection and/or focus - selections.update_sel_focus(data_clicked); - } - - // in zoom or subset mode, we can still do focus/de-focus - } else { - - selections.change_focus(data_clicked); - - } + // convert to data ids + range_sel = convert_row_ids(range_sel_inds); + } + } - // update previous selection - prev_row_selected = curr_row_selected; + // make sure we are in a selection mode + if (selections.sel_type() > 0) { + // check for range selection + if (range_sel.length > 1) { + // user selected a range in the table + selections.update_sel_range(range_sel); + } else { + // check if row is already selected + // update selection and/or focus + selections.update_sel_focus(data_clicked); + } - } + // in zoom or subset mode, we can still do focus/de-focus + } else { + selections.change_focus(data_clicked); + } + // update previous selection + prev_row_selected = curr_row_selected; + } } // highlight the current row by drawing a box around it -function highlight_curr_row() -{ - - // temporarily turn off table rendering - data_view.beginUpdate(); - - // get current row - var curr_data_row = convert_row_ids([curr_row_selected])[0]; - var item = data_view.getItemById(curr_data_row); - var num_cols = item.length; - - // update current row (set to draw box around it -- see select_rows()) - item[num_cols-1] = item[num_cols-1] + 10; +function highlight_curr_row() { + // temporarily turn off table rendering + data_view.beginUpdate(); - // put row back in table - data_view.updateItem(curr_data_row, item); + // get current row + var curr_data_row = convert_row_ids([curr_row_selected])[0]; + var item = data_view.getItemById(curr_data_row); + var num_cols = item.length; - // update previous row - if (prev_row_selected != null) { + // update current row (set to draw box around it -- see select_rows()) + item[num_cols - 1] = item[num_cols - 1] + 10; - // get previous row - var prev_data_row = convert_row_ids([prev_row_selected])[0]; + // put row back in table + data_view.updateItem(curr_data_row, item); - // un-highlight previous row - unhighlight_prev_row(prev_data_row); - - } + // update previous row + if (prev_row_selected != null) { + // get previous row + var prev_data_row = convert_row_ids([prev_row_selected])[0]; - // turn on table rendering - data_view.endUpdate(); + // un-highlight previous row + unhighlight_prev_row(prev_data_row); + } + // turn on table rendering + data_view.endUpdate(); } // update highlight condition for previous selected row -function unhighlight_prev_row(prev_data_row) -{ +function unhighlight_prev_row(prev_data_row) { + // get previous row + var item = data_view.getItemById(prev_data_row); + var num_cols = item.length; - // get previous row - var item = data_view.getItemById(prev_data_row); - var num_cols = item.length; - - // remove box around previous row - item[num_cols-1] = item[num_cols-1] - 10; - - // put row back in table - data_view.updateItem(prev_data_row, item); + // remove box around previous row + item[num_cols - 1] = item[num_cols - 1] - 10; + // put row back in table + data_view.updateItem(prev_data_row, item); } // slick grid row selected on click (for multiple rows) -function multiple_rows_selected (e, args) -{ - - // get rows selected - var rows = grid_view.getSelectedRows(); - - // convert to table ids - var row_ids = convert_row_ids(rows); - - // add selections (unless in zoom mode) - if (selections.sel_type() > 0) { - selections.zero_sel(); - selections.update_sel(row_ids[0]); - } - - // fire selection change event - var selectionEvent = new CustomEvent("DACSelectionsChanged", { detail: { - active_sel: []} }); - document.body.dispatchEvent(selectionEvent); - +function multiple_rows_selected(e, args) { + // get rows selected + var rows = grid_view.getSelectedRows(); + + // convert to table ids + var row_ids = convert_row_ids(rows); + + // add selections (unless in zoom mode) + if (selections.sel_type() > 0) { + selections.zero_sel(); + selections.update_sel(row_ids[0]); + } + + // fire selection change event + var selectionEvent = new CustomEvent("DACSelectionsChanged", { + detail: { + active_sel: [], + }, + }); + document.body.dispatchEvent(selectionEvent); } // converts selected row id to table row id (in case table is sorted) -function convert_row_ids(rows) -{ - - // change grid ids to data ids - var row_ids = []; - for (var i = 0; i < rows.length; i++) { - var item = data_view.getItem(rows[i]); - row_ids.push(item[item.length-2]); - } - - return row_ids; - +function convert_row_ids(rows) { + // change grid ids to data ids + var row_ids = []; + for (var i = 0; i < rows.length; i++) { + var item = data_view.getItem(rows[i]); + row_ids.push(item[item.length - 2]); + } + + return row_ids; } // slick grid change in rows -function change_rows (e, args) -{ - grid_view.updateRowCount(); - grid_view.render(); +function change_rows(e, args) { + grid_view.updateRowCount(); + grid_view.render(); } // slick grid change in columns -function change_cols (e, args) -{ - grid_view.invalidateRows(args.rows); - grid_view.render(); +function change_cols(e, args) { + grid_view.invalidateRows(args.rows); + grid_view.render(); } // slick grid filter using filter in header row -function filter(item) -{ - - // go through each column and check for filter - for (var columnId in columnFilters) { - if (columnId !== undefined && columnFilters[columnId] !== "") { - - // compare item to filter for that column - var c = grid_view.getColumns()[grid_view.getColumnIndex(columnId)]; - - // use regular expression if valid - if (columnFiltersRegExpValid[columnId]) { - if (item[c.field].toString().toLowerCase().search(columnFiltersRegExp[columnId]) == -1) { - return false; - } +function filter(item) { + // go through each column and check for filter + for (var columnId in columnFilters) { + if (columnId !== undefined && columnFilters[columnId] !== "") { + // compare item to filter for that column + var c = grid_view.getColumns()[grid_view.getColumnIndex(columnId)]; + + // use regular expression if valid + if (columnFiltersRegExpValid[columnId]) { + if (item[c.field].toString().toLowerCase().search(columnFiltersRegExp[columnId]) == -1) { + return false; + } // otherwise use string search - } else { - if (item[c.field].toString().toLowerCase().indexOf(columnFilters[columnId]) == -1) { - return false; - } + } else { + if (item[c.field].toString().toLowerCase().indexOf(columnFilters[columnId]) == -1) { + return false; } } } + } - // item passed through all the filters - return true; + // item passed through all the filters + return true; } // request for filtered data selection -module.get_filtered_selection = function () -{ +module.get_filtered_selection = function () { + var filtered_sel = []; - var filtered_sel = []; + // go through grid data and get ids + var num_rows_visible = grid_view.getDataLength(); + for (var i = 0; i < num_rows_visible; i++) { + // get grid item + var item = grid_view.getDataItem(i); - // go through grid data and get ids - var num_rows_visible = grid_view.getDataLength(); - for (var i = 0; i < num_rows_visible; i++) { + // get selection index + var sel_i = item[item.length - 2]; - // get grid item - var item = grid_view.getDataItem(i); + filtered_sel.push(sel_i); + } - // get selection index - var sel_i = item[item.length-2]; - - filtered_sel.push(sel_i); - } - - return filtered_sel; -} + return filtered_sel; +}; // override slick grid meta data method to color rows according to selection -function color_rows(old_metadata) { - - return function(row) { - var item = this.getItem(row); - var meta = old_metadata(row) || {}; - - if (item) { +function color_rows() { + return function (row) { + var item = this.getItem(row); + var meta = this.getItemMetadataOld(row) || {}; - // make sure the "cssClasses" property exists - meta.cssClasses = meta.cssClasses || ''; + if (item) { + // make sure the "cssClasses" property exists + meta.cssClasses = meta.cssClasses || ""; - // get selection css class - meta.cssClasses = selection_type (item); + // get selection css class + meta.cssClasses = selection_type(item); - // set css class for currently clicked item - if (Math.floor(item[item.length-1] / 10) == 1) { - meta.cssClasses += ' clicked'; - } - - } + // set css class for currently clicked item + if (Math.floor(item[item.length - 1] / 10) == 1) { + meta.cssClasses += " clicked"; + } + } - return meta; - } + return meta; + }; } // get selection string for coloring -function selection_type (item) -{ - // selection string to return - var sel_string = ""; - - // get the selection type - var sel_css_type = item[item.length-1] % 10; - - // set css according to selection type - for (var i = 1; i <= max_num_sel; i++) { - if (sel_css_type == i) { - sel_string = 'selection-' + i.toString(); - } - } - - // set css class according to focus and subset - if (sel_css_type > max_num_sel) { +function selection_type(item) { + // selection string to return + var sel_string = ""; - if (sel_css_type == (max_num_sel+1)) { - sel_string = 'focus-selection'; - } else if (sel_css_type == (max_num_sel+2)) { - sel_string = 'not-in-subset'; - } else { - sel_string = 'no-selection'; - } + // get the selection type + var sel_css_type = item[item.length - 1] % 10; + // set css according to selection type + for (var i = 1; i <= max_num_sel; i++) { + if (sel_css_type == i) { + sel_string = "selection-" + i.toString(); } + } + + // set css class according to focus and subset + if (sel_css_type > max_num_sel) { + if (sel_css_type == max_num_sel + 1) { + sel_string = "focus-selection"; + } else if (sel_css_type == max_num_sel + 2) { + sel_string = "not-in-subset"; + } else { + sel_string = "no-selection"; + } + } - return sel_string; + return sel_string; } // slick grid column sort -function col_sort (e, args) -{ - - // get previous row in data index, if it exists - var prev_data_row = null; - if (prev_row_selected != null) { - prev_data_row = convert_row_ids([prev_row_selected])[0]; +function col_sort(e, args) { + // get previous row in data index, if it exists + var prev_data_row = null; + if (prev_row_selected != null) { + prev_data_row = convert_row_ids([prev_row_selected])[0]; + } + + // sort table + // var comparer = function (a,b) { + // return (a[args.sortCol.field] > b[args.sortCol.field]) ? 1 : -1; + // } + + // natural sort compare for strings + var comparer = function (a, b) { + if (typeof a[args.sortCol.field] == "string") { + return a[args.sortCol.field].localeCompare( + b[args.sortCol.field], + navigator.languages[0] || navigator.language, + { numeric: true, ignorePunctuation: true }, + ); + } else { + return a[args.sortCol.field] > b[args.sortCol.field] ? 1 : -1; } - - // sort table - // var comparer = function (a,b) { - // return (a[args.sortCol.field] > b[args.sortCol.field]) ? 1 : -1; - // } - - // natural sort compare for strings - var comparer = function (a,b) { - if (typeof(a[args.sortCol.field]) == "string") { - return a[args.sortCol.field].localeCompare(b[args.sortCol.field], - navigator.languages[0] || navigator.language, - {numeric: true, ignorePunctuation: true}); - } else { - return (a[args.sortCol.field] > b[args.sortCol.field]) ? 1 : -1; - } - } - - data_view.sort(comparer, args.sortAsc); - - // convert previous row selected into new sorted order - if (prev_data_row != null) { - prev_row_selected = data_view.getRowById(prev_data_row); - } - - // table order sort event - var tableOrderEvent = new CustomEvent("DACTableOrderChanged", { detail: { - sort_col: args.sortCol.field, - sort_order: args.sortAsc} }); - document.body.dispatchEvent(tableOrderEvent); - + }; + + data_view.sort(comparer, args.sortAsc); + + // convert previous row selected into new sorted order + if (prev_data_row != null) { + prev_row_selected = data_view.getRowById(prev_data_row); + } + + // table order sort event + var tableOrderEvent = new CustomEvent("DACTableOrderChanged", { + detail: { + sort_col: args.sortCol.field, + sort_order: args.sortAsc, + }, + }); + document.body.dispatchEvent(tableOrderEvent); } // slick grid custom cell editor for text // modified from slick grid text editor function TextEditor(args) { + var $input; + var defaultValue; + var scope = this; + + this.init = function () { + $input = $( + "", + ); + $input.width(args.column.width - SEL_BORDER_WIDTH - 2); + $input.appendTo(args.container); + + $input.bind("keydown.nav", function (e) { + if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) { + e.stopImmediatePropagation(); + } - var $input; - var defaultValue; - var scope = this; - - this.init = function () { - - $input = $(""); - $input.width(args.column.width - SEL_BORDER_WIDTH - 2); - $input.appendTo(args.container); + if (e.keyCode === $.ui.keyCode.ENTER) { + update_freetext_cell($input); + } + }); - $input.bind("keydown.nav", function (e) { + // save results if user clicks off text box + $input.focusout(function () { + update_freetext_cell($input); + }); - if (e.keyCode === $.ui.keyCode.LEFT || - e.keyCode === $.ui.keyCode.RIGHT) { - e.stopImmediatePropagation(); - } + $input.focus(); - if (e.keyCode === $.ui.keyCode.ENTER) { - update_freetext_cell($input); - } - }); + $input.select(); + }; - // save results if user clicks off text box - $input.focusout(function () { - update_freetext_cell($input); - }); + this.destroy = function () { + $input.remove(); + }; - $input.focus(); + this.focus = function () { + $input.focus(); + }; - $input.select(); - }; + this.getValue = function () { + return $input.val(); + }; - this.destroy = function () { - $input.remove(); - }; + this.setValue = function (val) { + $input.val(val); + }; - this.focus = function () { - $input.focus(); - }; + this.loadValue = function (item) { + defaultValue = item[args.column.field] || ""; + $input.val(defaultValue); + $input[0].defaultValue = defaultValue; + $input.select(); + }; - this.getValue = function () { - return $input.val(); - }; + this.serializeValue = function () { + return $input.val(); + }; - this.setValue = function (val) { - $input.val(val); - }; + this.applyValue = function (item, state) { + item[args.column.field] = state; + }; - this.loadValue = function (item) { - defaultValue = item[args.column.field] || ""; - $input.val(defaultValue); - $input[0].defaultValue = defaultValue; - $input.select(); - }; + this.isValueChanged = function () { + return !($input.val() == "" && defaultValue == null) && $input.val() != defaultValue; + }; - this.serializeValue = function () { - return $input.val(); - }; + this.validate = function () { + if (args.column.validator) { + var validationResults = args.column.validator($input.val()); + if (!validationResults.valid) { + return validationResults; + } + } - this.applyValue = function (item, state) { - item[args.column.field] = state; - }; + return { + valid: true, + msg: null, + }; + }; - this.isValueChanged = function () { - return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); - }; + this.init(); +} - this.validate = function () { +// updates free text cell +function update_freetext_cell($input) { + // get cell position + var cell_pos = grid_view.getActiveCell(); + var row_id = cell_pos["row"]; + var col_id = cell_pos["cell"] - num_cols; - if (args.column.validator) { - var validationResults = args.column.validator($input.val()); - if (!validationResults.valid) { - return validationResults; - } - } + // get new value + var cell_val = $input.val(); - return { - valid: true, - msg: null - }; - }; + // update value by in table and database + update_editable_col(row_id, col_id, cell_val); - this.init(); + // reset active cell so no problems with focus + grid_view.resetActiveCell(); } -// updates free text cell -function update_freetext_cell ($input) { +// slick grid custom cell editor for categorical values +// modified from slick grid yes-no-select editor +function SelectCellEditor(args) { + var $select; + var defaultValue; + var scope = this; + this.init = function () { + var opt_values = ["yes", "no"]; + if (args.column.options) { + opt_values = args.column.options; + } - // get cell position - var cell_pos = grid_view.getActiveCell(); - var row_id = cell_pos["row"]; - var col_id = cell_pos["cell"] - num_cols; + var option_str = ""; + for (let i in opt_values) { + option_str += ""; + } - // get new value - var cell_val = $input.val(); + $select = $(""); + $select.width(args.column.width - SEL_BORDER_WIDTH); + $select.appendTo(args.container); - // update value by in table and database - update_editable_col (row_id, col_id, cell_val); + // remove select on change and update database + $select.on("change", function (value) { + // get cell position + var cell_pos = grid_view.getActiveCell(); + var row_id = cell_pos["row"]; + var col_id = cell_pos["cell"] - num_cols; - // reset active cell so no problems with focus - grid_view.resetActiveCell(); + // get new value + var cell_val = $select.val(); -} + // update value by in table and database + update_editable_col(row_id, col_id, cell_val); -// slick grid custom cell editor for categorical values -// modified from slick grid yes-no-select editor -function SelectCellEditor(args) { - var $select; - var defaultValue; - var scope = this; - this.init = function() { - var opt_values = ["yes","no"]; - if(args.column.options){ - opt_values = args.column.options; - } - - var option_str = ""; - for(let i in opt_values ){ - option_str += ""; - } - - $select = $('"); - $select.width(args.column.width - SEL_BORDER_WIDTH); - $select.appendTo(args.container); - - // remove select on change and update database - $select.on("change", function (value) { - - // get cell position - var cell_pos = grid_view.getActiveCell(); - var row_id = cell_pos["row"]; - var col_id = cell_pos["cell"] - num_cols; - - // get new value - var cell_val = $select.val(); - - // update value by in table and database - update_editable_col (row_id, col_id, cell_val); - - // reset active cell so no problems with focus - grid_view.resetActiveCell(); - }); - $select.focus(); - $select.select(); - }; - this.destroy = function() { - $select.remove(); - }; - this.focus = function() { - $select.focus(); - }; - this.loadValue = function(item) { - defaultValue = item[args.column.field]; - $select.val(defaultValue); - }; - this.serializeValue = function() { - if(args.column.options){ - return $select.val(); - }else{ - return ($select.val() == "yes"); - } - }; - this.applyValue = function(item,state) { - item[args.column.field] = state; - }; - this.isValueChanged = function() { - return ($select.val() != defaultValue); - }; - this.validate = function() { - return { - valid: true, - msg: null - }; - }; - this.init(); + // reset active cell so no problems with focus + grid_view.resetActiveCell(); + }); + $select.focus(); + $select.select(); + }; + this.destroy = function () { + $select.remove(); + }; + this.focus = function () { + $select.focus(); + }; + this.loadValue = function (item) { + defaultValue = item[args.column.field]; + $select.val(defaultValue); + }; + this.serializeValue = function () { + if (args.column.options) { + return $select.val(); + } else { + return $select.val() == "yes"; + } + }; + this.applyValue = function (item, state) { + item[args.column.field] = state; + }; + this.isValueChanged = function () { + return $select.val() != defaultValue; + }; + this.validate = function () { + return { + valid: true, + msg: null, + }; + }; + this.init(); } // update click grid cell and editable data in slycat -function update_editable_col(row, col, val) -{ - // get slick grid table data - var item = grid_view.getDataItem(row); - - // adjust row to actual row in stored data - var data_row = item[item.length-2]; - - // temporarily turn off table rendering - data_view.beginUpdate(); - - // update table on server - client.post_sensitive_model_command({ - mid: mid, - type: "DAC", - command: "manage_editable_cols", - parameters: {col_cmd: 'update', col_type: -1, col_name: -1, col_cat: -1, - col_id: col, data_row: data_row, data_val: val}, - success: function(result) { - - if (JSON.parse(result)["error"] === "reader") { - dialog.ajax_error("Access denied. You must be a project writer or " + - "administrator to change the table data.") - ("","",""); - } else { - - // update table on screen - item[num_cols + col] = val; - - // put row back in table - data_view.updateItem(data_row, item); - - } - - // finish update - data_view.endUpdate(); - - // alert scatter plot for update of colors - var editableColEvent = new CustomEvent("DACEditableColChanged", - { detail: num_metadata_cols + col + num_origin_cols}); - document.body.dispatchEvent(editableColEvent); - - }, - error: function () - { - dialog.ajax_error('Server error updating editable column.') - ("","",""); - data_view.endUpdate(); - } - - }); +function update_editable_col(row, col, val) { + // get slick grid table data + var item = grid_view.getDataItem(row); + + // adjust row to actual row in stored data + var data_row = item[item.length - 2]; + + // temporarily turn off table rendering + data_view.beginUpdate(); + + // update table on server + client.post_sensitive_model_command({ + mid: mid, + type: "DAC", + command: "manage_editable_cols", + parameters: { + col_cmd: "update", + col_type: -1, + col_name: -1, + col_cat: -1, + col_id: col, + data_row: data_row, + data_val: val, + }, + success: function (result) { + if (JSON.parse(result)["error"] === "reader") { + dialog.ajax_error( + "Access denied. You must be a project writer or " + + "administrator to change the table data.", + )("", "", ""); + } else { + // update table on screen + item[num_cols + col] = val; + + // put row back in table + data_view.updateItem(data_row, item); + } + // finish update + data_view.endUpdate(); + + // alert scatter plot for update of colors + var editableColEvent = new CustomEvent("DACEditableColChanged", { + detail: num_metadata_cols + col + num_origin_cols, + }); + document.body.dispatchEvent(editableColEvent); + }, + error: function () { + dialog.ajax_error("Server error updating editable column.")("", "", ""); + data_view.endUpdate(); + }, + }); } // resize slick grid if container resizes -module.resize = function() -{ - // get size of container - var width = $("#dac-datapoints-pane").width(); - var height = $("#dac-datapoints-pane").height(); +module.resize = function () { + // get size of container + var width = $("#dac-datapoints-pane").width(); + var height = $("#dac-datapoints-pane").height(); - // set table size to size of container - $("#dac-datapoints-table").width(width); - $("#dac-datapoints-table").height(height); + // set table size to size of container + $("#dac-datapoints-table").width(width); + $("#dac-datapoints-table").height(height); - // re-draw table - grid_view.resizeCanvas(); + // re-draw table + grid_view.resizeCanvas(); - // re-render header - grid_view.setColumns(grid_view.getColumns()) -} + // re-render header + grid_view.setColumns(grid_view.getColumns()); +}; // highlight rows for selections -module.select_rows = function () -{ - - // update selection indices - var new_focus = selections.focus(); - var subset_mask = selections.get_subset(); - - // generate vector of data view with new selections - var sel_vec = []; - for (var i = 0; i != num_rows; i++) { - sel_vec.push(0); - } - - // mark all selections - for (var j = 0; j < max_num_sel; j++) { +module.select_rows = function () { + // update selection indices + var new_focus = selections.focus(); + var subset_mask = selections.get_subset(); + + // generate vector of data view with new selections + var sel_vec = []; + for (var i = 0; i != num_rows; i++) { + sel_vec.push(0); + } + + // mark all selections + for (var j = 0; j < max_num_sel; j++) { + // get selections + var new_sel = selections.sel(j + 1); + + // mark selection j + for (var i = 0; i != new_sel.length; i++) { + sel_vec[new_sel[i]] = j + 1; + } + } - // get selections - var new_sel = selections.sel(j+1); + // mark focus, if present + if (new_focus != null) { + sel_vec[new_focus] = max_num_sel + 1; + } - // mark selection j - for (var i = 0; i != new_sel.length; i++) { - sel_vec[new_sel[i]] = j+1; - } + // mark if not in subset + for (var i = 0; i < subset_mask.length; i++) { + if (!subset_mask[i]) { + sel_vec[i] = max_num_sel + 2; } + } + + // show current selected row + var data_row_selected = null; + if (curr_row_selected != null) { + data_row_selected = convert_row_ids([curr_row_selected])[0]; + sel_vec[data_row_selected] = sel_vec[data_row_selected] + 10; + } + + // temporarily turn off table rendering + data_view.beginUpdate(); + + // update last column of table with new selections + // also get first selected row in grid view (not data view) + for (var i = 0; i != num_rows; i++) { + // get a row + var item = data_view.getItemById(i); + var num_cols = item.length; - // mark focus, if present - if (new_focus != null) { - sel_vec[new_focus] = max_num_sel+1; - } - - // mark if not in subset - for (var i = 0; i < subset_mask.length; i++) { - if (!subset_mask[i]) { - sel_vec[i] = max_num_sel+2; - } - } - - // show current selected row - var data_row_selected = null; - if (curr_row_selected != null) { - data_row_selected = convert_row_ids([curr_row_selected])[0]; - sel_vec[data_row_selected] = sel_vec[data_row_selected] + 10; - } - - // temporarily turn off table rendering - data_view.beginUpdate(); - - // update last column of table with new selections - // also get first selected row in grid view (not data view) - for (var i = 0; i != num_rows; i++) - { - // get a row - var item = data_view.getItemById(i); - var num_cols = item.length; - - // update selection info - item[num_cols-1] = sel_vec[i]; - - // put row back in table - data_view.updateItem(i, item); - } - - // turn table re-draw back on - data_view.endUpdate(); + // update selection info + item[num_cols - 1] = sel_vec[i]; -} + // put row back in table + data_view.updateItem(i, item); + } + + // turn table re-draw back on + data_view.endUpdate(); +}; // jumps to the first row in the provide selection -module.jump_to = function (selection) -{ - - // if selection is empty, nothing is done - if (selection.length > 0) - { - var num_rows = data_view.getLength(); - var first_sel = num_rows - 1; - for (var i = 0; i != num_rows; i++) - { - if (selection.indexOf(i) > -1) { - first_sel = Math.min(first_sel, data_view.getRowById(i)); - } - } - - // now scroll to first selected row - grid_view.scrollRowIntoView(first_sel); - } +module.jump_to = function (selection) { + // if selection is empty, nothing is done + if (selection.length > 0) { + var num_rows = data_view.getLength(); + var first_sel = num_rows - 1; + for (var i = 0; i != num_rows; i++) { + if (selection.indexOf(i) > -1) { + first_sel = Math.min(first_sel, data_view.getRowById(i)); + } + } -} + // now scroll to first selected row + grid_view.scrollRowIntoView(first_sel); + } +}; export default module; diff --git a/web-server/plugins/slycat-parameter-image-plus-model/js/parameter-image-table.js b/web-server/plugins/slycat-parameter-image-plus-model/js/parameter-image-table.js index e291da388..0a516a9be 100644 --- a/web-server/plugins/slycat-parameter-image-plus-model/js/parameter-image-table.js +++ b/web-server/plugins/slycat-parameter-image-plus-model/js/parameter-image-table.js @@ -5,162 +5,232 @@ import api_root from "js/slycat-api-root"; import d3 from "d3"; -import "slickgrid/slick.interactions.js"; -import "slickgrid/slick.core"; -import "slickgrid/slick.grid"; -import "slickgrid/plugins/slick.rowselectionmodel"; -import "slickgrid/plugins/slick.headerbuttons"; -import "slickgrid/plugins/slick.autotooltips"; +import { + SlickRowSelectionModel, + SlickAutoTooltips, + SlickGrid, + SlickEvent, + SlickHeaderButtons, +} from "slickgrid"; +import Sortable from "sortablejs"; +window.Sortable = Sortable; import * as chunker from "js/chunker"; import * as table_helpers from "js/slycat-table-helpers"; -$.widget("parameter_image.table", -{ - options: - { - mid : null, - aid : null, - metadata : null, - statistics : null, - inputs : [], - outputs : [], - others : [], - images : [], - ratings : [], - categories : [], - "row-selection" : [], +$.widget("parameter_image.table", { + options: { + mid: null, + aid: null, + metadata: null, + statistics: null, + inputs: [], + outputs: [], + others: [], + images: [], + ratings: [], + categories: [], + "row-selection": [], "variable-selection": [], - "sort-variable" : null, - "sort-order" : null, - "image-variable" : null, - "x-variable" : null, - "y-variable" : null, - colorscale : null, - hidden_simulations : [], + "sort-variable": null, + "sort-order": null, + "image-variable": null, + "x-variable": null, + "y-variable": null, + colorscale: null, + hidden_simulations: [], }, - _create: function() - { + _create: function () { var self = this; - function value_formatter(value) - { - return value == null ? " " : (value + "").replace(/&/g,"&").replace(//g,">"); + function value_formatter(value) { + return value == null + ? " " + : (value + "").replace(/&/g, "&").replace(//g, ">"); } - function cell_formatter(row, cell, value, columnDef, dataContext) - { - if(columnDef.colorscale) - return "
" + value_formatter(value) + "
"; - else if(value==null) - return "
" + value_formatter(value) + "
"; + function cell_formatter(row, cell, value, columnDef, dataContext) { + if (columnDef.colorscale) + return ( + "
" + + value_formatter(value) + + "
" + ); + else if (value == null) + return ( + "
" + + value_formatter(value) + + "
" + ); return value_formatter(value); } - function editable_cell_formatter(row, cell, value, columnDef, dataContext) - { - if(columnDef.colorscale) - return "
" + value_formatter(value) + "
"; - else if(value==null) - return "
" + value_formatter(value) + "
"; + function editable_cell_formatter(row, cell, value, columnDef, dataContext) { + if (columnDef.colorscale) + return ( + "
" + + value_formatter(value) + + "
" + ); + else if (value == null) + return ( + "
" + + value_formatter(value) + + "
" + ); return value_formatter(value); } - function set_sort(column, order) - { + function set_sort(column, order) { self.data.set_sort(column, order); self.grid.invalidate(); table_helpers._set_selected_rows_no_trigger(self); self.element.trigger("variable-sort-changed", [column, order]); } - function make_column(column_index, header_class, cell_class, formatter) - { + function make_column(column_index, header_class, cell_class, formatter) { var column = { - id : column_index, - field : column_index, - name : self.options.metadata["column-names"][column_index], - toolTip : self.options.metadata["column-names"][column_index], - sortable : false, - headerCssClass : header_class, - cssClass : cell_class, - formatter : formatter, + id: column_index, + field: column_index, + name: self.options.metadata["column-names"][column_index], + toolTip: self.options.metadata["column-names"][column_index], + sortable: false, + headerCssClass: header_class, + cssClass: cell_class, + formatter: formatter, width: 100, - header : - { - buttons : - [ + header: { + buttons: [ { - cssClass : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "icon-sort-ascending" : "icon-sort-descending") : "icon-sort-off", - tooltip : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "Sort descending" : "Sort ascending") : "Sort ascending", - command : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "sort-descending" : "sort-ascending") : "sort-ascending", + cssClass: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "icon-sort-ascending" + : "icon-sort-descending" + : "icon-sort-off", + tooltip: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "Sort descending" + : "Sort ascending" + : "Sort ascending", + command: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "sort-descending" + : "sort-ascending" + : "sort-ascending", }, - ] - } + ], + }, }; // Special options for image columns - if( self.options.images.indexOf(column_index) > -1 ) { + if (self.options.images.indexOf(column_index) > -1) { column.headerCssClass += " headerImage"; - column.header.buttons.push( - { - cssClass : self.options["image-variable"] == column_index ? "icon-image-on" : "icon-image-off", - tooltip : self.options["image-variable"] == column_index ? "Current image variable" : "Set as image variable", - command : self.options["image-variable"] == column_index ? "" : "image-on", - } - ); + column.header.buttons.push({ + cssClass: + self.options["image-variable"] == column_index ? "icon-image-on" : "icon-image-off", + tooltip: + self.options["image-variable"] == column_index + ? "Current image variable" + : "Set as image variable", + command: self.options["image-variable"] == column_index ? "" : "image-on", + }); } // Special options for non-image and non-index columns - else if( self.options.metadata["column-count"]-1 != column_index ) { + else if (self.options.metadata["column-count"] - 1 != column_index) { column.headerCssClass += " headerNumeric"; column.header.buttons.push( { - cssClass : self.options["x-variable"] == column_index ? "icon-x-on" : "icon-x-off", - tooltip : self.options["x-variable"] == column_index ? "Current x variable" : "Set as x variable", - command : self.options["x-variable"] == column_index ? "" : "x-on", + cssClass: self.options["x-variable"] == column_index ? "icon-x-on" : "icon-x-off", + tooltip: + self.options["x-variable"] == column_index + ? "Current x variable" + : "Set as x variable", + command: self.options["x-variable"] == column_index ? "" : "x-on", }, { - cssClass : self.options["y-variable"] == column_index ? "icon-y-on" : "icon-y-off", - tooltip : self.options["y-variable"] == column_index ? "Current y variable" : "Set as y variable", - command : self.options["y-variable"] == column_index ? "" : "y-on", - } + cssClass: self.options["y-variable"] == column_index ? "icon-y-on" : "icon-y-off", + tooltip: + self.options["y-variable"] == column_index + ? "Current y variable" + : "Set as y variable", + command: self.options["y-variable"] == column_index ? "" : "y-on", + }, ); } return column; } self.columns = []; - - self.columns.push(make_column(self.options.metadata["column-count"]-1, "headerSimId", "rowSimId", cell_formatter)); - for(var i in self.options.inputs) - self.columns.push(make_column(self.options.inputs[i], "headerInput", "rowInput", cell_formatter)); - for(var i in self.options.outputs) - self.columns.push(make_column(self.options.outputs[i], "headerOutput", "rowOutput", cell_formatter)); - for(var i in self.options.ratings) - self.columns.push(make_column(self.options.ratings[i], "headerRating", "rowRating", editable_cell_formatter)); - for(var i in self.options.categories) - self.columns.push(make_column(self.options.categories[i], "headerCategory", "rowCategory", editable_cell_formatter)); - for(var i in self.options.others) - self.columns.push(make_column(self.options.others[i], "headerOther", "rowOther", cell_formatter)); + + self.columns.push( + make_column( + self.options.metadata["column-count"] - 1, + "headerSimId", + "rowSimId", + cell_formatter, + ), + ); + for (var i in self.options.inputs) + self.columns.push( + make_column(self.options.inputs[i], "headerInput", "rowInput", cell_formatter), + ); + for (var i in self.options.outputs) + self.columns.push( + make_column(self.options.outputs[i], "headerOutput", "rowOutput", cell_formatter), + ); + for (var i in self.options.ratings) + self.columns.push( + make_column(self.options.ratings[i], "headerRating", "rowRating", editable_cell_formatter), + ); + for (var i in self.options.categories) + self.columns.push( + make_column( + self.options.categories[i], + "headerCategory", + "rowCategory", + editable_cell_formatter, + ), + ); + for (var i in self.options.others) + self.columns.push( + make_column(self.options.others[i], "headerOther", "rowOther", cell_formatter), + ); self.data = new self._data_provider({ - mid : self.options.mid, - aid : self.options.aid, - metadata : self.options.metadata, - sort_column : self.options["sort-variable"], - sort_order : self.options["sort-order"], - inputs : self.options.inputs, - outputs : self.options.outputs, - indexOfIndex : self.options.metadata["column-count"]-1, - hidden_simulations : self.options.hidden_simulations, - }); + mid: self.options.mid, + aid: self.options.aid, + metadata: self.options.metadata, + sort_column: self.options["sort-variable"], + sort_order: self.options["sort-order"], + inputs: self.options.inputs, + outputs: self.options.outputs, + indexOfIndex: self.options.metadata["column-count"] - 1, + hidden_simulations: self.options.hidden_simulations, + }); self.trigger_row_selection = true; - self.grid = new Slick.Grid(self.element, self.data, self.columns, { - explicitInitialization : true, - enableColumnReorder : false, - editable : true, - editCommandHandler : self._editCommandHandler, + self.grid = new SlickGrid(self.element.get(0), self.data, self.columns, { + explicitInitialization: true, + enableColumnReorder: false, + editable: true, + editCommandHandler: self._editCommandHandler, }); self.data.onDataLoaded.subscribe(function (e, args) { @@ -170,17 +240,15 @@ $.widget("parameter_image.table", self.grid.render(); }); - var header_buttons = new Slick.Plugins.HeaderButtons(); - header_buttons.onCommand.subscribe(function(e, args) - { + var header_buttons = new SlickHeaderButtons(); + header_buttons.onCommand.subscribe(function (e, args) { var column = args.column; var button = args.button; var command = args.command; var grid = args.grid; - if(command == "sort-ascending" || command == "sort-descending"){ - for(var i in self.columns) - { + if (command == "sort-ascending" || command == "sort-descending") { + for (var i in self.columns) { self.columns[i].header.buttons[0].cssClass = "icon-sort-off"; self.columns[i].header.buttons[0].tooltip = "Sort ascending"; self.columns[i].header.buttons[0].command = "sort-ascending"; @@ -188,92 +256,82 @@ $.widget("parameter_image.table", } } - if(command == "sort-ascending") - { - button.cssClass = 'icon-sort-ascending'; - button.command = 'sort-descending'; - button.tooltip = 'Sort descending'; + if (command == "sort-ascending") { + button.cssClass = "icon-sort-ascending"; + button.command = "sort-descending"; + button.tooltip = "Sort descending"; set_sort(column.id, "ascending"); - } - else if(command == "sort-descending") - { - button.cssClass = 'icon-sort-descending'; - button.command = 'sort-ascending'; - button.tooltip = 'Sort ascending'; + } else if (command == "sort-descending") { + button.cssClass = "icon-sort-descending"; + button.command = "sort-ascending"; + button.tooltip = "Sort ascending"; set_sort(column.id, "descending"); - } - else if(command == "image-on") - { - for(var i=0; i < self.options.images.length; i++) - { + } else if (command == "image-on") { + for (var i = 0; i < self.options.images.length; i++) { var index = grid.getColumnIndex(self.options.images[i]); self.columns[index].header.buttons[1].cssClass = "icon-image-off"; self.columns[index].header.buttons[1].tooltip = "Set as image variable"; self.columns[index].header.buttons[1].command = "image-on"; grid.updateColumnHeader(self.columns[index].id); } - button.cssClass = 'icon-image-on'; - button.command = ''; - button.tooltip = 'Current image variable'; + button.cssClass = "icon-image-on"; + button.command = ""; + button.tooltip = "Current image variable"; self.element.trigger("images-selection-changed", column.id); - } - else if(command == "x-on") - { - for(var i in self.columns) - { - if(self.options.images.indexOf(self.columns[i].id) == -1 && self.options.metadata["column-count"]-1 != self.columns[i].id){ + } else if (command == "x-on") { + for (var i in self.columns) { + if ( + self.options.images.indexOf(self.columns[i].id) == -1 && + self.options.metadata["column-count"] - 1 != self.columns[i].id + ) { self.columns[i].header.buttons[1].cssClass = "icon-x-off"; self.columns[i].header.buttons[1].tooltip = "Set as x variable"; self.columns[i].header.buttons[1].command = "x-on"; grid.updateColumnHeader(self.columns[i].id); } } - button.cssClass = 'icon-x-on'; - button.command = ''; - button.tooltip = 'Current x variable'; + button.cssClass = "icon-x-on"; + button.command = ""; + button.tooltip = "Current x variable"; self.element.trigger("x-selection-changed", column.id); - } - else if(command == "y-on") - { - for(var i in self.columns) - { - if(self.options.images.indexOf(self.columns[i].id) == -1 && self.options.metadata["column-count"]-1 != self.columns[i].id){ + } else if (command == "y-on") { + for (var i in self.columns) { + if ( + self.options.images.indexOf(self.columns[i].id) == -1 && + self.options.metadata["column-count"] - 1 != self.columns[i].id + ) { self.columns[i].header.buttons[2].cssClass = "icon-y-off"; self.columns[i].header.buttons[2].tooltip = "Set as y variable"; self.columns[i].header.buttons[2].command = "y-on"; grid.updateColumnHeader(self.columns[i].id); } } - button.cssClass = 'icon-y-on'; - button.command = ''; - button.tooltip = 'Current y variable'; + button.cssClass = "icon-y-on"; + button.command = ""; + button.tooltip = "Current y variable"; self.element.trigger("y-selection-changed", column.id); } }); self.grid.registerPlugin(header_buttons); - self.grid.registerPlugin(new Slick.AutoTooltips({enableForHeaderCells:true})); + self.grid.registerPlugin(new SlickAutoTooltips({ enableForHeaderCells: true })); - self.grid.setSelectionModel(new Slick.RowSelectionModel()); - self.grid.onSelectedRowsChanged.subscribe(function(e, selection) - { + self.grid.setSelectionModel(new SlickRowSelectionModel()); + self.grid.onSelectedRowsChanged.subscribe(function (e, selection) { // Don't trigger a selection event unless the selection was changed by user interaction (i.e. not outside callers or changing the sort order). - if(self.trigger_row_selection) - { - self.data.get_indices("unsorted", selection.rows, function(unsorted_rows) - { + if (self.trigger_row_selection) { + self.data.get_indices("unsorted", selection.rows, function (unsorted_rows) { self.options["row-selection"] = unsorted_rows; self.element.trigger("row-selection-changed", [unsorted_rows]); }); } self.trigger_row_selection = true; }); - self.grid.onHeaderClick.subscribe(function (e, args) - { - if( !self._array_equal([args.column.field], self.options["variable-selection"]) && - self.options.images.indexOf(args.column.field) == -1 - ) - { + self.grid.onHeaderClick.subscribe(function (e, args) { + if ( + !self._array_equal([args.column.field], self.options["variable-selection"]) && + self.options.images.indexOf(args.column.field) == -1 + ) { self.options["variable-selection"] = [args.column.field]; self.element.trigger("variable-selection-changed", [self.options["variable-selection"]]); } @@ -286,82 +344,62 @@ $.widget("parameter_image.table", table_helpers._set_selected_rows_no_trigger(self); }, - resize_canvas: function() - { + resize_canvas: function () { var self = this; self.grid.resizeCanvas(); }, - update_data: function() - { + update_data: function () { var self = this; self.data.invalidate(); self.grid.invalidate(); table_helpers._set_selected_rows_no_trigger(self); }, - _setOption: function(key, value) - { + _setOption: function (key, value) { var self = this; - if(key == "row-selection") - { + if (key == "row-selection") { self.options[key] = value; table_helpers._set_selected_rows_no_trigger(self); - } - else if(key == "variable-selection") - { - if(self._array_equal(self.options[key], value)) - return; + } else if (key == "variable-selection") { + if (self._array_equal(self.options[key], value)) return; self.options[key] = value; self._color_variables(value); - } - else if(key == "colorscale") - { + } else if (key == "colorscale") { self.options[key] = value; self._color_variables(self.options["variable-selection"]); - } - else if(key == "x-variable") - { + } else if (key == "x-variable") { self.options[key] = value; self._set_selected_x(); - } - else if(key == "y-variable") - { + } else if (key == "y-variable") { self.options[key] = value; self._set_selected_y(); - } - else if(key == "image-variable") - { + } else if (key == "image-variable") { self.options[key] = value; self._set_selected_image(); - } - else if(key == "metadata") - { + } else if (key == "metadata") { self.options[key] = value; self._color_variables(self.options["variable-selection"]); - } - else if(key == "statistics") - { + } else if (key == "statistics") { self.options[key] = value; self._color_variables(self.options["variable-selection"]); - } - else if(key == "hidden_simulations") - { + } else if (key == "hidden_simulations") { self.options[key] = value; self.data.invalidate(); self.grid.invalidate(); } }, - _set_selected_x: function() - { + _set_selected_x: function () { var self = this; - for(var i in self.columns) - { - if(self.options.images.indexOf(self.columns[i].id) == -1 && self.options.metadata["column-count"]-1 != self.columns[i].id){ - if( self.columns[i].id == self.options["x-variable"]){ + for (var i in self.columns) { + if ( + self.options.images.indexOf(self.columns[i].id) == -1 && + self.options.metadata["column-count"] - 1 != self.columns[i].id + ) { + if (self.columns[i].id == self.options["x-variable"]) { self.columns[i].header.buttons[1].cssClass = "icon-x-on"; self.columns[i].header.buttons[1].tooltip = "Current x variable"; self.columns[i].header.buttons[1].command = ""; @@ -375,13 +413,14 @@ $.widget("parameter_image.table", } }, - _set_selected_y: function() - { + _set_selected_y: function () { var self = this; - for(var i in self.columns) - { - if(self.options.images.indexOf(self.columns[i].id) == -1 && self.options.metadata["column-count"]-1 != self.columns[i].id){ - if( self.columns[i].id == self.options["y-variable"]){ + for (var i in self.columns) { + if ( + self.options.images.indexOf(self.columns[i].id) == -1 && + self.options.metadata["column-count"] - 1 != self.columns[i].id + ) { + if (self.columns[i].id == self.options["y-variable"]) { self.columns[i].header.buttons[2].cssClass = "icon-y-on"; self.columns[i].header.buttons[2].tooltip = "Current y variable"; self.columns[i].header.buttons[2].command = ""; @@ -395,13 +434,11 @@ $.widget("parameter_image.table", } }, - _set_selected_image: function() - { + _set_selected_image: function () { var self = this; - for(var i=0; i < self.options.images.length; i++) - { + for (var i = 0; i < self.options.images.length; i++) { var index = self.grid.getColumnIndex(self.options.images[i]); - if(self.columns[index].id == self.options["image-variable"]){ + if (self.columns[index].id == self.options["image-variable"]) { self.columns[index].header.buttons[1].cssClass = "icon-image-on"; self.columns[index].header.buttons[1].tooltip = "Current image variable"; self.columns[index].header.buttons[1].command = ""; @@ -414,21 +451,16 @@ $.widget("parameter_image.table", } }, - _color_variables: function(variables) - { + _color_variables: function (variables) { var self = this; var columns = self.grid.getColumns(); - for(var i in columns) - { + for (var i in columns) { var column = columns[i]; - if(self.options.colorscale !== null && $.inArray(column.id, variables) != -1) - { + if (self.options.colorscale !== null && $.inArray(column.id, variables) != -1) { column.colorscale = self.options.colorscale; column.cssClass = column.cssClass.split(" ")[0] + " highlight"; - } - else - { + } else { column.colorscale = null; column.cssClass = column.cssClass.split(" ")[0]; } @@ -436,15 +468,14 @@ $.widget("parameter_image.table", self.grid.invalidate(); }, - _editCommandHandler: function (item,column,editCommand) { + _editCommandHandler: function (item, column, editCommand) { console.log("editCommandHandler called"); editCommand.execute(); // To Do: Attempt to save edit and undo it if Ajax call returns error //editCommand.undo(); }, - _data_provider: function(parameters) - { + _data_provider: function (parameters) { var self = this; self.mid = parameters.mid; @@ -463,199 +494,184 @@ $.widget("parameter_image.table", self.pages_in_progress = {}; self.page_size = 50; - self.onDataLoaded = new Slick.Event(); + self.onDataLoaded = new SlickEvent(); - self.getLength = function() - { + self.getLength = function () { return self.metadata["row-count"]; - } + }; - self.getItem = function(index) - { + self.getItem = function (index) { var column_begin = 0; var column_end = self.metadata["column-count"]; var page = Math.floor(index / self.page_size); var page_begin = page * self.page_size; - if(self.pages_in_progress[page]) - { + if (self.pages_in_progress[page]) { return null; } - if(!(page in self.pages)) - { + if (!(page in self.pages)) { self.pages_in_progress[page] = true; var row_begin = page_begin; var row_end = (page + 1) * self.page_size; var sort = ""; - if(self.sort_column !== null && self.sort_order !== null) - { + if (self.sort_column !== null && self.sort_order !== null) { var sort_column = "a" + self.sort_column; var sort_order = self.sort_order; - if(sort_order == 'ascending') - { - sort_order = 'asc'; - } - else if(sort_order == 'descending') - { - sort_order = 'desc'; + if (sort_order == "ascending") { + sort_order = "asc"; + } else if (sort_order == "descending") { + sort_order = "desc"; } - if(self.sort_column == self.metadata["column-count"]-1) - sort_column = "index(0)"; + if (self.sort_column == self.metadata["column-count"] - 1) sort_column = "index(0)"; sort = "/order: rank(" + sort_column + ', "' + sort_order + '")'; } - $.ajax( - { - type : "GET", - url : api_root + "models/" + self.mid + "/arraysets/" + self.aid + "/data?hyperchunks=0/" + column_begin + ":" + (column_end - 1) + "|index(0)" + sort + "/" + row_begin + ":" + row_end, - success : function(data) - { + $.ajax({ + type: "GET", + url: + api_root + + "models/" + + self.mid + + "/arraysets/" + + self.aid + + "/data?hyperchunks=0/" + + column_begin + + ":" + + (column_end - 1) + + "|index(0)" + + sort + + "/" + + row_begin + + ":" + + row_end, + success: function (data) { self.pages[page] = []; - for(var i=0; i < data[0].length; i++) - { + for (var i = 0; i < data[0].length; i++) { var result = {}; - for(var j = column_begin; j != column_end; ++j) - { + for (var j = column_begin; j != column_end; ++j) { result[j] = data[j][i]; } self.pages[page].push(result); } self.pages_in_progress[page] = false; - self.onDataLoaded.notify({from: row_begin, to: row_end}); + self.onDataLoaded.notify({ from: row_begin, to: row_end }); }, - error: function(request, status, reason_phrase) - { + error: function (request, status, reason_phrase) { console.log("error", request, status, reason_phrase); - } + }, }); return null; } return self.pages[page][index - page_begin]; - } + }; - self.getItemMetadata = function(index) - { + self.getItemMetadata = function (index) { var page = Math.floor(index / self.page_size); - if((self.pages_in_progress[page]) || !(page in self.pages)) - { + if (self.pages_in_progress[page] || !(page in self.pages)) { return null; } var row = this.getItem(index); var column_end = self.analysis_columns.length; var cssClasses = ""; - for(var i=0; i != column_end; i++) { - if(row[ self.analysis_columns[i] ]==null) { + for (var i = 0; i != column_end; i++) { + if (row[self.analysis_columns[i]] == null) { cssClasses += "nullRow "; } } - if( $.inArray( row[self.indexOfIndex], self.hidden_simulations ) != -1 ) { + if ($.inArray(row[self.indexOfIndex], self.hidden_simulations) != -1) { cssClasses += "hiddenRow "; } - if(cssClasses != "") - return {"cssClasses" : cssClasses}; + if (cssClasses != "") return { cssClasses: cssClasses }; return null; - } + }; - self.set_sort = function(column, order) - { - if(column == self.sort_column && order == self.sort_order) - return; + self.set_sort = function (column, order) { + if (column == self.sort_column && order == self.sort_order) return; self.sort_column = column; self.sort_order = order; self.pages = {}; - } + }; - self.get_indices = function(direction, rows, callback) - { - if(rows.length == 0) - { + self.get_indices = function (direction, rows, callback) { + if (rows.length == 0) { callback([]); return; } // We have no sort column or order, so just returning the same rows as were asked for since they're in the same order - if(self.sort_column == null || self.sort_order == null) - { + if (self.sort_column == null || self.sort_order == null) { callback(rows); - } - else - { - if(self.ranked_indices[self.sort_column]) - { + } else { + if (self.ranked_indices[self.sort_column]) { // we have data for this column, so figure out what to return var indices = self.ranked_indices[self.sort_column]; // Reverse response indexes for descending sort order - if(self.sort_order == 'descending') - { + if (self.sort_order == "descending") { var plain_array = []; - for(var i=0; i/g,">"); + function value_formatter(value) { + return value == null + ? " " + : (value + "").replace(/&/g, "&").replace(//g, ">"); } - function cell_formatter(row, cell, value, columnDef, dataContext) - { - if(columnDef.colorscale) { - return "
" + value_formatter(value) + "
"; - } - else if(value==null) - return "
" + value_formatter(value) + "
"; + function cell_formatter(row, cell, value, columnDef, dataContext) { + if (columnDef.colorscale) { + return ( + "
" + + value_formatter(value) + + "
" + ); + } else if (value == null) + return ( + "
" + + value_formatter(value) + + "
" + ); return value_formatter(value); } - function make_column(column_index, header_class, cell_class) - { + function make_column(column_index, header_class, cell_class) { var column = { - id : column_index, - field : column_index, - name : self.options.metadata["column-names"][column_index], - sortable : false, - headerCssClass : header_class, - cssClass : cell_class, - formatter : cell_formatter, - header : - { - buttons : - [ + id: column_index, + field: column_index, + name: self.options.metadata["column-names"][column_index], + sortable: false, + headerCssClass: header_class, + cssClass: cell_class, + formatter: cell_formatter, + header: { + buttons: [ { - cssClass : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "icon-sort-ascending" : "icon-sort-descending") : "icon-sort-off", - tooltip : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "Sort descending" : "Sort ascending") : "Sort ascending", - command : self.options["sort-variable"] == column_index ? (self.options["sort-order"] == "ascending" ? "sort-descending" : "sort-ascending") : "sort-ascending" - } - ] - } + cssClass: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "icon-sort-ascending" + : "icon-sort-descending" + : "icon-sort-off", + tooltip: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "Sort descending" + : "Sort ascending" + : "Sort ascending", + command: + self.options["sort-variable"] == column_index + ? self.options["sort-order"] == "ascending" + ? "sort-descending" + : "sort-ascending" + : "sort-ascending", + }, + ], + }, }; // Special options for image columns - if( self.options.image_columns.indexOf(column_index) > -1 ) { + if (self.options.image_columns.indexOf(column_index) > -1) { column.headerCssClass += " headerImage"; } @@ -85,14 +112,14 @@ $.widget("timeseries.table", self.columns = []; var header_class, cell_class; // Last column is added as simid - self.columns.push(make_column(self.options.metadata["column-count"]-1, "headerSimId", "rowSimId")); + self.columns.push( + make_column(self.options.metadata["column-count"] - 1, "headerSimId", "rowSimId"), + ); // rest of columns are added as inputs, except for media columns which are added as other - for(var i = 0; i < self.options.metadata["column-count"]-1; i++) - { + for (var i = 0; i < self.options.metadata["column-count"] - 1; i++) { header_class = "headerInput"; cell_class = "rowInput"; - if(self.options.image_columns.indexOf(i) > -1) - { + if (self.options.image_columns.indexOf(i) > -1) { header_class = "headerOther"; cell_class = "rowOther"; } @@ -100,26 +127,22 @@ $.widget("timeseries.table", } }, - resize_canvas: function() - { + resize_canvas: function () { var self = this; self.grid.resizeCanvas(); }, - _setOption: function(key, value) - { - function set_sort(column, order) - { + _setOption: function (key, value) { + function set_sort(column, order) { self.options["sort-variable"] = column; self.options["sort-order"] = order; - self.data.set_sort(column, order, function(){ - if(self.options["row-selection"].length > 0){ + self.data.set_sort(column, order, function () { + if (self.options["row-selection"].length > 0) { var selectedRows = self.data.getSimulationRowIndexes(self.options["row-selection"]); self.trigger_row_selection = false; self.grid.setSelectedRows(selectedRows); self.grid.resetActiveCell(); - if(selectedRows.length) - self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); + if (selectedRows.length) self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); } }); self.element.trigger("variable-sort-changed", [column, order]); @@ -127,8 +150,7 @@ $.widget("timeseries.table", var self = this; - if(key == "row-selection") - { + if (key == "row-selection") { // Unexpectedly at this point self.options[key] has already been set to value, so this always returns even when the row-selection is unique //if(self._array_equal(self.options[key], value)) // return; @@ -139,40 +161,28 @@ $.widget("timeseries.table", self.trigger_row_selection = false; self.grid.setSelectedRows(selectedRows); self.grid.resetActiveCell(); - if(selectedRows.length) - self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); - } - else if(key == "row-selection-silent") - { + if (selectedRows.length) self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); + } else if (key == "row-selection-silent") { self.options["row-selection"] = value; - } - else if(key == "variable-selection") - { - if(self._array_equal(self.options[key], value)) - return; + } else if (key == "variable-selection") { + if (self._array_equal(self.options[key], value)) return; self.options[key] = value; self._color_variables(value); - } - else if(key == "colorscale") - { + } else if (key == "colorscale") { self.options[key] = value; self._color_variables(self.options["variable-selection"]); - } - else if(key == "selection") - { + } else if (key == "selection") { self.options[key] = value; var data_table_index, waveform_index; var table_filter = []; var waveform_indexes = []; - $.each(value, function(index, node) - { + $.each(value, function (index, node) { data_table_index = node["data-table-index"]; - waveform_index = node["waveform-index"]; + waveform_index = node["waveform-index"]; - if(data_table_index == null) - return; + if (data_table_index == null) return; table_filter.push(data_table_index); waveform_indexes.push(waveform_index); @@ -181,114 +191,107 @@ $.widget("timeseries.table", self.options.waveform_indexes = waveform_indexes; self.options.row_count = table_filter.length; - function initialize_grid(indices){ - + function initialize_grid(indices) { var sorted_table_filter = undefined; var retrieve_table_filter = undefined; - if(indices !== undefined) - { + if (indices !== undefined) { var sorted_rows = []; // Reverse response indexes for descending sort order - if(self.options["sort-order"] == 'descending') - { + if (self.options["sort-order"] == "descending") { var plain_array = []; - for(var i=0; i 1) - sorted_table_filter = Array.apply( [], sorted_rows ); - else - sorted_table_filter = [sorted_rows[0]]; - retrieve_table_filter = sorted_table_filter.slice(0).sort(function (a, b) { return a - b }); + if (sorted_rows.length > 1) sorted_table_filter = Array.apply([], sorted_rows); + else sorted_table_filter = [sorted_rows[0]]; + retrieve_table_filter = sorted_table_filter.slice(0).sort(function (a, b) { + return a - b; + }); } self.data = new self._data_provider({ - api_root : self.options.api_root, - mid : self.options.mid, - aid : self.options.aid, - metadata : self.options.metadata, - sort_column : self.options["sort-variable"], - sort_order : self.options["sort-order"], - table_filter : self.options.table_filter, - row_count : self.options.row_count, - sorted_table_filter : sorted_table_filter, - retrieve_table_filter : retrieve_table_filter - }); + api_root: self.options.api_root, + mid: self.options.mid, + aid: self.options.aid, + metadata: self.options.metadata, + sort_column: self.options["sort-variable"], + sort_order: self.options["sort-order"], + table_filter: self.options.table_filter, + row_count: self.options.row_count, + sorted_table_filter: sorted_table_filter, + retrieve_table_filter: retrieve_table_filter, + }); - if(self.grid) { + if (self.grid) { self.grid.setData(self.data); self.data.setGrid(self.grid); self.grid.invalidate(); - if(self.options["row-selection"].length > 0){ + if (self.options["row-selection"].length > 0) { var selectedRows = self.data.getSimulationRowIndexes(self.options["row-selection"]); self.trigger_row_selection = false; self.grid.setSelectedRows(selectedRows); self.grid.resetActiveCell(); - if(selectedRows.length) - self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); + if (selectedRows.length) self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); } - } - else { + } else { self.trigger_row_selection = true; - self.grid = new Slick.Grid(self.element, self.data, self.columns, {explicitInitialization : true, enableColumnReorder : false}); + self.grid = new SlickGrid(self.element.get(0), self.data, self.columns, { + explicitInitialization: true, + enableColumnReorder: false, + }); self.data.setGrid(self.grid); - var header_buttons = new Slick.Plugins.HeaderButtons(); - header_buttons.onCommand.subscribe(function(e, args) - { + var header_buttons = new SlickHeaderButtons(); + header_buttons.onCommand.subscribe(function (e, args) { var column = args.column; var button = args.button; var command = args.command; var grid = args.grid; - for(var i in self.columns) - { + for (var i in self.columns) { self.columns[i].header.buttons[0].cssClass = "icon-sort-off"; self.columns[i].header.buttons[0].tooltip = "Sort ascending"; self.columns[i].header.buttons[0].command = "sort-ascending"; grid.updateColumnHeader(self.columns[i].id); } - if(command == "sort-ascending") - { - button.cssClass = 'icon-sort-ascending'; - button.command = 'sort-descending'; - button.tooltip = 'Sort descending'; + if (command == "sort-ascending") { + button.cssClass = "icon-sort-ascending"; + button.command = "sort-descending"; + button.tooltip = "Sort descending"; set_sort(column.id, "ascending"); - } - else if(command == "sort-descending") - { - button.cssClass = 'icon-sort-descending'; - button.command = 'sort-ascending'; - button.tooltip = 'Sort ascending'; + } else if (command == "sort-descending") { + button.cssClass = "icon-sort-descending"; + button.command = "sort-ascending"; + button.tooltip = "Sort ascending"; set_sort(column.id, "descending"); } }); self.grid.registerPlugin(header_buttons); - self.grid.registerPlugin(new Slick.AutoTooltips({enableForHeaderCells:true})); + self.grid.registerPlugin(new SlickAutoTooltips({ enableForHeaderCells: true })); - self.grid.setSelectionModel(new Slick.RowSelectionModel()); + self.grid.setSelectionModel(new SlickRowSelectionModel()); - self.grid.onSelectedRowsChanged.subscribe(function(e, selection) - { + self.grid.onSelectedRowsChanged.subscribe(function (e, selection) { // Don't trigger a selection event unless the selection was changed by user interaction (i.e. not outside callers or changing the sort order). - if(self.trigger_row_selection) - { - var waveform_indexes=[]; - for(var i=0; i 0){ + if (self.options["row-selection"].length > 0) { var selectedRows = self.data.getSimulationRowIndexes(self.options["row-selection"]); self.trigger_row_selection = false; self.grid.setSelectedRows(selectedRows); self.grid.resetActiveCell(); - if(selectedRows.length) - self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); + if (selectedRows.length) self.grid.scrollRowToTop(Math.min.apply(Math, selectedRows)); } } @@ -330,52 +334,56 @@ $.widget("timeseries.table", }); } - if(self.options["sort-variable"] !== null && self.options["sort-order"] !== null && self.options.table_filter.length > 0) { + if ( + self.options["sort-variable"] !== null && + self.options["sort-order"] !== null && + self.options.table_filter.length > 0 + ) { // Need to retrieve the sorted_table_filter first because everything else relies on it. - if( self.options["sort-variable"] == self.options.metadata["column-count"]-1 ) - { + if (self.options["sort-variable"] == self.options.metadata["column-count"] - 1) { // we are sorting by the index column, so we can just make the data we need. - initialize_grid( new Int32Array( d3.range(self.options.metadata["row-count"]) ) ); - } - else - { + initialize_grid(new Int32Array(d3.range(self.options.metadata["row-count"]))); + } else { var request = new XMLHttpRequest(); - request.open("GET", self.options.api_root + "models/" + self.options.mid + "/arraysets/" + self.options.aid + "/data?hyperchunks=0/rank(a" + self.options["sort-variable"] + ',"asc")/...&byteorder=' + (chunker.is_little_endian() ? "little" : "big") ); + request.open( + "GET", + self.options.api_root + + "models/" + + self.options.mid + + "/arraysets/" + + self.options.aid + + "/data?hyperchunks=0/rank(a" + + self.options["sort-variable"] + + ',"asc")/...&byteorder=' + + (chunker.is_little_endian() ? "little" : "big"), + ); request.responseType = "arraybuffer"; - request.onload = function(e) - { + request.onload = function (e) { var indices = []; var data = new Int32Array(this.response); // Filtering out every other element in the reponse array, because it's full of extraneous 0 (zeros) for some reason. // Need to figure out why, but this is a fix for now. - for(var i=0; i 1) - self.sorted_table_filter = Array.apply( [], sorted_rows ); - else - self.sorted_table_filter = [sorted_rows[0]]; - self.retrieve_table_filter = self.sorted_table_filter.slice(0).sort(function (a, b) { return a - b }); + self.get_indices("sorted", self.table_filter, function (sorted_rows) { + if (sorted_rows.length > 1) self.sorted_table_filter = Array.apply([], sorted_rows); + else self.sorted_table_filter = [sorted_rows[0]]; + self.retrieve_table_filter = self.sorted_table_filter.slice(0).sort(function (a, b) { + return a - b; + }); self.pages = {}; self.grid.invalidate(); callback(); }); } - } + }; - self.getSimulationRowIndexes = function(simulation_indexes) - { + self.getSimulationRowIndexes = function (simulation_indexes) { var table_filter_index, sorted_table_filter_element, retrieve_table_filter_index; var result = []; - for(var i=0; i -1){ + if (table_filter_index > -1) { sorted_table_filter_element = self.sorted_table_filter[table_filter_index]; - retrieve_table_filter_index = self.retrieve_table_filter.indexOf(sorted_table_filter_element); + retrieve_table_filter_index = self.retrieve_table_filter.indexOf( + sorted_table_filter_element, + ); result.push(retrieve_table_filter_index); } } return result; - } - + }; }, - _array_equal: function(a, b) - { + _array_equal: function (a, b) { return $(a).not(b).length == 0 && $(b).not(a).length == 0; }, -}); \ No newline at end of file +}); diff --git a/web-server/plugins/slycat-timeseries-model/js/timeseries.js b/web-server/plugins/slycat-timeseries-model/js/timeseries.js index 30ffbf8f6..895d5ea46 100644 --- a/web-server/plugins/slycat-timeseries-model/js/timeseries.js +++ b/web-server/plugins/slycat-timeseries-model/js/timeseries.js @@ -4,11 +4,11 @@ import jquery_ui_css from "jquery-ui/themes/base/all.css"; -import slick_grid_css from "slickgrid/slick.grid.css"; -import slick_default_theme_css from "slickgrid/slick-default-theme.css"; -import slick_headerbuttons_css from "slickgrid/plugins/slick.headerbuttons.css"; -import slick_slycat_theme_css from "css/slick-slycat-theme.css"; -import ui_css from "../css/ui.css"; +import "slickgrid/dist/styles/sass/slick.grid.scss"; +import "slickgrid/dist/styles/sass/slick-default-theme.scss"; +import "slickgrid/dist/styles/sass/slick.headerbuttons.scss"; +import "css/slick-slycat-theme.css"; +import "../css/ui.css"; import LoadingPage from "../plugin-components/LoadingPage.tsx"; @@ -41,7 +41,7 @@ export default function initialize_timeseries_model( subscribe, model, clusters, - table_metadata + table_metadata, ) { ko.applyBindings({}, document.querySelector(".slycat-content")); ////////////////////////////////////////////////////////////////////////////////////////// @@ -342,7 +342,7 @@ export default function initialize_timeseries_model( }, error: function (request, status, reason_phrase) { window.alert( - "Error getting color coding values from table-chunker worker: " + reason_phrase + "Error getting color coding values from table-chunker worker: " + reason_phrase, ); }, }); @@ -454,7 +454,7 @@ export default function initialize_timeseries_model( $("#legend-pane").css( "background", - slycat_color_maps.get_background(get_state().controls.colormap).toString() + slycat_color_maps.get_background(get_state().controls.colormap).toString(), ); $("#legend").legend({ @@ -492,7 +492,7 @@ export default function initialize_timeseries_model( .toString(), }); $("#waveform-viewer rect.selectionMask").css({ - "fill": slycat_color_maps.get_background(get_state().controls.colormap), + fill: slycat_color_maps.get_background(get_state().controls.colormap), "fill-opacity": slycat_color_maps.get_opacity(get_state().controls.colormap), }); @@ -575,7 +575,7 @@ export default function initialize_timeseries_model( $("#dendrogram-viewer").dendrogram( "option", "dendrogram_sort_order", - variable == null && order == null ? true : false + variable == null && order == null ? true : false, ); }); @@ -585,7 +585,7 @@ export default function initialize_timeseries_model( $("#controls").controls("option", "color-variable", selected_column[cluster_index]); }); - // Call setup_widgets when table is finished initializing because + // Call setup_widgets when table is finished initializing because // dendrogram waits for table to be ready so it can send it the selected node // and table can render the appropriate rows. setup_widgets(); @@ -664,7 +664,7 @@ export default function initialize_timeseries_model( $("#waveform-viewer").waveformplot("option", "highlight", waveform_indexes); // Update the table row selection ... $("#table").table("option", "row-selection", waveform_indexes); - } + }, ); // Changing the sort order to dendrogram order updates the table ... @@ -689,14 +689,14 @@ export default function initialize_timeseries_model( subscribe( watch_controls_colormap((newVal, oldVal, objectPath) => { selected_colormap_changed(newVal); - }) + }), ); function selected_colormap_changed(newColormap) { // First we change background colors, gradients, and other things that don't require recalculating the colorscale $("#legend-pane").css( "background", - slycat_color_maps.get_background(get_state().controls.colormap).toString() + slycat_color_maps.get_background(get_state().controls.colormap).toString(), ); $("#legend").legend("option", { gradient: slycat_color_maps.get_gradient_data(get_state().controls.colormap), @@ -714,7 +714,7 @@ export default function initialize_timeseries_model( .toString(), }); $("#waveform-viewer rect.selectionMask").css({ - "fill": slycat_color_maps.get_background(get_state().controls.colormap), + fill: slycat_color_maps.get_background(get_state().controls.colormap), "fill-opacity": slycat_color_maps.get_opacity(get_state().controls.colormap), }); @@ -749,7 +749,7 @@ export default function initialize_timeseries_model( function selected_node_changed(parameters) { selected_waveform_indexes[parseInt(cluster_index, 10)] = getWaveformIndexes( - parameters.selection + parameters.selection, ); selected_nodes[cluster_index] = getNodeIndexes(parameters.selection); @@ -760,7 +760,7 @@ export default function initialize_timeseries_model( $("#controls").controls( "option", "selection", - selected_waveform_indexes[parseInt(cluster_index, 10)] + selected_waveform_indexes[parseInt(cluster_index, 10)], ); $("#controls").controls("option", "highlight", selected_simulations); @@ -768,7 +768,7 @@ export default function initialize_timeseries_model( $("#waveform-viewer").waveformplot( "option", "selection", - selected_waveform_indexes[parseInt(cluster_index, 10)] + selected_waveform_indexes[parseInt(cluster_index, 10)], ); $("#waveform-viewer").waveformplot("option", "highlight", selected_simulations); @@ -841,7 +841,7 @@ export default function initialize_timeseries_model( colorscale = slycat_color_maps.get_color_scale( get_state().controls.colormap, selected_column_min[cluster_index], - selected_column_max[cluster_index] + selected_column_max[cluster_index], ); callback(colorscale); } else { @@ -858,7 +858,7 @@ export default function initialize_timeseries_model( uniqueValues = result.unique[0].values[0]; colorscale = slycat_color_maps.get_color_scale_ordinal( get_state().controls.colormap, - uniqueValues + uniqueValues, ); callback(colorscale); }, diff --git a/web-server/plugins/slycat-video-swarm/js/vs-table.js b/web-server/plugins/slycat-video-swarm/js/vs-table.js index d4280366f..ee3c579c1 100644 --- a/web-server/plugins/slycat-video-swarm/js/vs-table.js +++ b/web-server/plugins/slycat-video-swarm/js/vs-table.js @@ -14,22 +14,25 @@ Copyright 2013, Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. */ -import jquery_ui_css from "jquery-ui/themes/base/all.css"; +import "jquery-ui/themes/base/all.css"; import "../css/vs-ui.css"; -import slick_grid_css from "slickgrid/slick.grid.css"; -import slick_default_theme_css from "slickgrid/slick-default-theme.css"; -import slick_headerbuttons_css from "slickgrid/plugins/slick.headerbuttons.css"; -import slick_slycat_theme_css from "css/slick-slycat-theme.css"; +import "slickgrid/dist/styles/sass/slick.grid.scss"; +import "slickgrid/dist/styles/sass/slick-default-theme.scss"; +import "slickgrid/dist/styles/sass/slick.headerbuttons.scss"; +import "css/slick-slycat-theme.css"; import api_root from "js/slycat-api-root"; import d3 from "d3"; import _ from "lodash"; -import "slickgrid/slick.interactions.js"; -import "slickgrid/slick.core"; -import "slickgrid/slick.grid"; -import "slickgrid/plugins/slick.rowselectionmodel"; -import "slickgrid/plugins/slick.headerbuttons"; -import "slickgrid/plugins/slick.autotooltips"; +import { + SlickRowSelectionModel, + SlickAutoTooltips, + SlickGrid, + SlickEvent, + SlickHeaderButtons, +} from "slickgrid"; +import Sortable from "sortablejs"; +window.Sortable = Sortable; import * as chunker from "js/chunker"; import * as table_helpers from "js/slycat-table-helpers"; @@ -124,7 +127,7 @@ $.widget("vs.table", self.trigger_row_selection = true; - self.grid = new Slick.Grid(self.element, self.data, self.columns, {explicitInitialization : true, enableColumnReorder : false}); + self.grid = new SlickGrid(self.element.get(0), self.data, self.columns, {explicitInitialization : true, enableColumnReorder : false}); self.data.onDataLoaded.subscribe(function (e, args) { for (var i = args.from; i <= args.to; i++) { @@ -133,7 +136,7 @@ $.widget("vs.table", self.grid.render(); }); - var header_buttons = new Slick.Plugins.HeaderButtons(); + var header_buttons = new SlickHeaderButtons(); header_buttons.onCommand.subscribe(function(e, args) { var column = args.column; @@ -166,9 +169,9 @@ $.widget("vs.table", }); self.grid.registerPlugin(header_buttons); - self.grid.registerPlugin(new Slick.AutoTooltips({enableForHeaderCells:true})); + self.grid.registerPlugin(new SlickAutoTooltips({enableForHeaderCells:true})); - self.grid.setSelectionModel(new Slick.RowSelectionModel()); + self.grid.setSelectionModel(new SlickRowSelectionModel()); self.grid.onSelectedRowsChanged.subscribe(function(e, selection) { // Don't trigger a selection event unless the selection was changed by user interaction (i.e. not outside callers or changing the sort order). @@ -303,7 +306,7 @@ $.widget("vs.table", self.pages_in_progress = {}; self.page_size = 50; - self.onDataLoaded = new Slick.Event(); + self.onDataLoaded = new SlickEvent(); self.getLength = function() { From 2540bf634f55ba27fabaded0ff65b65c08925c4a Mon Sep 17 00:00:00 2001 From: "Alex M. Sielicki" Date: Wed, 25 Sep 2024 08:47:08 -0700 Subject: [PATCH 46/46] build: update npm packages --- package-lock.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9a419e7b0..ca341f1ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4299,9 +4299,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", - "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "version": "22.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.0.tgz", + "integrity": "sha512-MOdOibwBs6KW1vfqz2uKMlxq5xAfAZ98SZjO8e3XnAbFnTJtAspqhWk7hrdSAs9/Y14ZWMiy7/MxMUzAOadYEw==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -5642,9 +5642,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -5661,8 +5661,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, @@ -16322,9 +16322,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.5",