From 18d27b2f9a578b292a201c20711bec27705110aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 21:12:51 +0000 Subject: [PATCH 1/4] Initial plan From 9a31e1760169f5730ca8e64a0978170c005ce89e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 21:24:13 +0000 Subject: [PATCH 2/4] Fix React bug when editing textbox in search panel Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../sanddance-explorer/src/dialogs/search.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/sanddance-explorer/src/dialogs/search.tsx b/packages/sanddance-explorer/src/dialogs/search.tsx index e8ebd9d97..35cf5addc 100644 --- a/packages/sanddance-explorer/src/dialogs/search.tsx +++ b/packages/sanddance-explorer/src/dialogs/search.tsx @@ -205,26 +205,29 @@ function _Search(_props: Props) { updateExpression(partialEx: Partial, groupIndex: number, index: number) { const groups: InputSearchExpressionGroup[] = [...this.state.groups]; - const group = groups[groupIndex]; - const ex = SandDance.VegaMorphCharts.util.clone(group.expressions[index]); - if (ex.name !== partialEx.name) { + const group = { ...groups[groupIndex] }; + const expressions = [...group.expressions]; + const currentEx = expressions[index]; + if (currentEx.name !== partialEx.name) { //choose an appropriate operator when switching data type - const oldColumn = getColumnWithName(ex.name, this.state.sortedColumns); + const oldColumn = getColumnWithName(currentEx.name, this.state.sortedColumns); const newColumn = getColumnWithName(partialEx.name, this.state.sortedColumns); const oldType = oldColumn && oldColumn.type; const newType = newColumn && newColumn.type; if (oldType !== newType) { const newOperators = getValidOperators(newColumn).map(validOperator => validOperator[0]); //see if old operator is compatible - if (newOperators.indexOf(ex.operator) < 0) { + if (newOperators.indexOf(currentEx.operator) < 0) { //not compatible, so choose "equal" partialEx.operator = '=='; } } } - Object.assign(ex, partialEx); + const ex = { ...currentEx, ...partialEx }; clearExpressionValidation(ex); - group.expressions[index] = ex; + expressions[index] = ex; + group.expressions = expressions; + groups[groupIndex] = group; this.setState({ groups }); } From c510600d94123c5c16a5eec7cb34ee743fdc2228 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 21:27:14 +0000 Subject: [PATCH 3/4] Fix state mutation in addExpression and deleteExpression methods Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../sanddance-explorer/src/dialogs/search.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/sanddance-explorer/src/dialogs/search.tsx b/packages/sanddance-explorer/src/dialogs/search.tsx index 35cf5addc..cfd328bb6 100644 --- a/packages/sanddance-explorer/src/dialogs/search.tsx +++ b/packages/sanddance-explorer/src/dialogs/search.tsx @@ -190,16 +190,19 @@ function _Search(_props: Props) { addExpression(groupIndex: number) { const groups: InputSearchExpressionGroup[] = [...this.state.groups]; - const group = groups[groupIndex]; - const maxKey = group.expressions.reduce((max, p) => p.key > max ? p.key : max, group.expressions[0].key); + const group = { ...groups[groupIndex] }; + const expressions = [...group.expressions]; + const maxKey = expressions.reduce((max, p) => p.key > max ? p.key : max, expressions[0].key); const newEx = this.newExpression(maxKey + 1, '&&'); - group.expressions.push(newEx); - if (group.expressions.length === 2) { + expressions.push(newEx); + if (expressions.length === 2) { newEx.unlocked = true; } else { - group.expressions.forEach(ex => ex.unlocked = false); - newEx.clause = group.expressions[1].clause; + expressions.forEach(ex => ex.unlocked = false); + newEx.clause = expressions[1].clause; } + group.expressions = expressions; + groups[groupIndex] = group; this.setState({ groups }); } @@ -233,13 +236,14 @@ function _Search(_props: Props) { deleteExpression(groupIndex: number, index: number) { const groups: InputSearchExpressionGroup[] = [...this.state.groups]; - const group = groups[groupIndex]; + const group = { ...groups[groupIndex] }; const expressions: InputSearchExpression[] = [...group.expressions]; expressions.splice(index, 1); if (expressions.length === 2) { expressions[1].unlocked = true; } group.expressions = expressions; + groups[groupIndex] = group; this.setState({ groups }); } From e088c0522fd4c22d18b24467bca09f31312e397a Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 16 Oct 2025 16:58:09 -0700 Subject: [PATCH 4/4] npm audit fix --- package-lock.json | 56 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7b893d4c2..9c0029d5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -523,18 +523,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@fluentui/date-time-utilities": { "version": "8.6.9", "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-8.6.9.tgz", @@ -6841,16 +6855,17 @@ } }, "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -12580,10 +12595,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14799,16 +14815,24 @@ "dev": true }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shallow-clone": {