From d645bf05c2035b1d39678974d1048226d11176c3 Mon Sep 17 00:00:00 2001 From: Thang PHAM Date: Tue, 2 Jul 2024 17:27:40 +0200 Subject: [PATCH] enrich id for the whole query --- package-lock.json | 20 +++++++++++++++----- package.json | 5 ++++- src/redux/slices/Mapping.js | 8 +++++++- src/utils/rqb-utils.ts | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 src/utils/rqb-utils.ts diff --git a/package-lock.json b/package-lock.json index 1a436e8..cf30367 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,14 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.60.0", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.61.1.tgz", + "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", "@reduxjs/toolkit": "^2.2.3", + "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21", "notistack": "^3.0.1", "prop-types": "^15.8.1", @@ -32,6 +34,7 @@ "redux": "^5.0.1", "typeface-roboto": "^1.1.13", "typescript": "5.1.6", + "uuid": "^9.0.1", "yup": "^1.4.0" }, "devDependencies": { @@ -44,6 +47,7 @@ "@types/react": "^18.2.75", "@types/react-dom": "^18.2.24", "@types/react-window": "^1.8.8", + "@types/uuid": "^9.0.8", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^4.2.1", "http-proxy-middleware": "^2.0.6", @@ -2747,9 +2751,10 @@ } }, "node_modules/@gridsuite/commons-ui": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.60.0.tgz", - "integrity": "sha512-jC9pReFbBfLvKJLswWo1bIgQErD+aGrT7JbwY6Ke74aooMNZKiG8Z96hUpG5U06mZS08wlc9DLur7Go5fVU+TA==", + "version": "0.61.1", + "resolved": "file:../commons-ui/gridsuite-commons-ui-0.61.1.tgz", + "integrity": "sha512-vQO6PtWy/ezteY7ByW4/5TsF6OUnIsuBZ94aMK93LqmQCSxJNmbalgiiUJXkYAe2xwPWethqkFg/bkUKh08G/w==", + "license": "MPL-2.0", "dependencies": { "@react-querybuilder/dnd": "^7.2.0", "@react-querybuilder/material": "^7.2.0", @@ -2802,7 +2807,6 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz", "integrity": "sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==", - "peer": true, "peerDependencies": { "react-hook-form": "^7.0.0" } @@ -4926,6 +4930,12 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "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 + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", diff --git a/package.json b/package.json index 7bc416e..9d41bc7 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,14 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.60.0", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.61.1.tgz", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", "@reduxjs/toolkit": "^2.2.3", + "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21", "notistack": "^3.0.1", "prop-types": "^15.8.1", @@ -29,6 +30,7 @@ "redux": "^5.0.1", "typeface-roboto": "^1.1.13", "typescript": "5.1.6", + "uuid": "^9.0.1", "yup": "^1.4.0" }, "overrides": { @@ -81,6 +83,7 @@ "@types/react": "^18.2.75", "@types/react-dom": "^18.2.24", "@types/react-window": "^1.8.8", + "@types/uuid": "^9.0.8", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^4.2.1", "http-proxy-middleware": "^2.0.6", diff --git a/src/redux/slices/Mapping.js b/src/redux/slices/Mapping.js index f5b890f..8e3b1e8 100644 --- a/src/redux/slices/Mapping.js +++ b/src/redux/slices/Mapping.js @@ -29,6 +29,7 @@ import { getExpertFilterEmptyFormData, importExpertRules, } from '@gridsuite/commons-ui'; +import { enrichIdQuery } from '../../utils/rqb-utils'; const initialState = { mappings: [], @@ -78,7 +79,12 @@ const transformMapping = (receivedMapping) => { // filterCounterList.reduce((max, val) => Math.max(max, val), 0) + 1; rule['matches'] = []; if (rule.filter) { - rule['filter']['rules'] = importExpertRules(rule.filter.rules); + rule['filter']['rules'] = importExpertRules( + // RQB need an id for each rule/group to avoid re-create a new component + // even the same input => lost focus while typing + // This solution can be removed when the back-end returns id persisted for each rule in the db (round-trip) + enrichIdQuery(rule.filter.rules) + ); } return rule; }); diff --git a/src/utils/rqb-utils.ts b/src/utils/rqb-utils.ts new file mode 100644 index 0000000..e75d117 --- /dev/null +++ b/src/utils/rqb-utils.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +import { v4 as uuid4 } from 'uuid'; +import { UUID } from 'crypto'; +import { RuleGroupTypeExport, RuleTypeExport } from '@gridsuite/commons-ui'; + +const visitQuery = ( + query: RuleGroupTypeExport, + visitor: (ruleOrGroup: RuleTypeExport | RuleGroupTypeExport) => void +) => { + visitor(query); + const stack = [...query.rules]; + while (stack?.length) { + const ruleOrGroup = stack.shift(); + ruleOrGroup && visitor(ruleOrGroup); + if (ruleOrGroup && 'rules' in ruleOrGroup) { + stack.push(...ruleOrGroup.rules); + } + } + return query; +}; + +const idUpdater = (ruleOrGroup: RuleTypeExport | RuleGroupTypeExport) => { + if (ruleOrGroup && !ruleOrGroup.id) { + ruleOrGroup.id = uuid4() as UUID; + } +}; + +export const enrichIdQuery = (query: RuleGroupTypeExport) => { + return visitQuery(query, idUpdater); +};