diff --git a/CHANGELOG.md b/CHANGELOG.md index e2e1809d..f896363b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,6 @@ All notable changes to this project will be documented in this file. - Fix data fetching bug + tests - Refactored screen layout commands. - Moved list components (search and checkboxes) around. -- Replaced lodash functions with native ones. - Aligned environment variable names. - Aligned with v. 2.6.0. diff --git a/assets/admin/components/playlist/playlist-campaign-manager.jsx b/assets/admin/components/playlist/playlist-campaign-manager.jsx index b80c3998..b8cb387a 100644 --- a/assets/admin/components/playlist/playlist-campaign-manager.jsx +++ b/assets/admin/components/playlist/playlist-campaign-manager.jsx @@ -16,6 +16,7 @@ import { usePutV2PlaylistsByIdMutation, usePostV2PlaylistsMutation, } from "../../../shared/redux/enhanced-api.ts"; +import { set } from "lodash/object"; /** * The shared manager component. @@ -280,7 +281,7 @@ function PlaylistCampaignManager({ */ const handleInput = ({ target }) => { const localFormStateObject = { ...formStateObject }; - localFormStateObject[target.id] = target.value; + set(localFormStateObject, target.id, target.value); setFormStateObject(localFormStateObject); }; diff --git a/assets/admin/components/screen/screen-manager.jsx b/assets/admin/components/screen/screen-manager.jsx index 8e4a28a1..bdb4f1c9 100644 --- a/assets/admin/components/screen/screen-manager.jsx +++ b/assets/admin/components/screen/screen-manager.jsx @@ -11,6 +11,7 @@ import { displayError, } from "../util/list/toast-component/display-toast"; import idFromUrl from "../util/helpers/id-from-url"; +import { set } from "lodash/object"; /** * The screen manager component. @@ -95,7 +96,7 @@ function ScreenManager({ const handleInput = ({ target }) => { let localFormStateObject = { ...formStateObject }; localFormStateObject = JSON.parse(JSON.stringify(localFormStateObject)); - localFormStateObject[target.id] = target.value; + set(localFormStateObject, target.id, target.value); setFormStateObject(localFormStateObject); }; diff --git a/assets/admin/components/slide/content/contacts/contact-form.jsx b/assets/admin/components/slide/content/contacts/contact-form.jsx index 764c4bb9..6e9ab015 100644 --- a/assets/admin/components/slide/content/contacts/contact-form.jsx +++ b/assets/admin/components/slide/content/contacts/contact-form.jsx @@ -2,6 +2,7 @@ import { Col, Row } from "react-bootstrap"; import { useTranslation } from "react-i18next"; import FileSelector from "../file-selector"; import FormInput from "../../../util/forms/form-input"; +import { set } from "lodash/object"; /** * Contact form. @@ -27,7 +28,7 @@ function ContactForm({ */ const onInput = ({ target }) => { const localContact = { ...contact }; - localContact[target.name] = target.value; + set(localContact, target.name, target.value); onChange(localContact); }; diff --git a/assets/admin/components/slide/content/feed-selector.jsx b/assets/admin/components/slide/content/feed-selector.jsx index ccd9491e..15ea1bfd 100644 --- a/assets/admin/components/slide/content/feed-selector.jsx +++ b/assets/admin/components/slide/content/feed-selector.jsx @@ -12,6 +12,7 @@ import ContentForm from "./content-form"; import MultiselectFromEndpoint from "./multiselect-from-endpoint"; import PosterSelectorV1 from "./poster/poster-selector-v1"; import PosterSelectorV2 from "./poster/poster-selector-v2"; +import { set } from "lodash/object"; /** * Feed selector. @@ -99,12 +100,12 @@ function FeedSelector({ const configuration = { ...value.configuration }; if (target !== null) { - configuration[target.id] = target.value; + set(configuration, target.id, target.value); } if (targets !== null) { targets.forEach(({ id, value: targetValue }) => { - configuration[id] = targetValue; + set(configuration, id, targetValue); }); } diff --git a/assets/admin/components/slide/slide-manager.jsx b/assets/admin/components/slide/slide-manager.jsx index 63e20dd4..4ff80438 100644 --- a/assets/admin/components/slide/slide-manager.jsx +++ b/assets/admin/components/slide/slide-manager.jsx @@ -19,6 +19,7 @@ import { } from "../util/list/toast-component/display-toast"; import idFromUrl from "../util/helpers/id-from-url"; import localStorageKeys from "../util/local-storage-keys"; +import { get, set } from "lodash/object"; /** * The slide manager component. @@ -153,7 +154,7 @@ function SlideManager({ */ const handleInput = ({ target }) => { const localFormStateObject = { ...formStateObject }; - localFormStateObject[target.id] = target.value; + set(localFormStateObject, target.id, target.value); setFormStateObject(localFormStateObject); }; @@ -206,7 +207,7 @@ function SlideManager({ const value = target.type === "number" ? target.valueAsNumber : target.value; const localFormStateObject = { ...formStateObject }; - localFormStateObject.content[target.id] = value; + set(localFormStateObject.content, target.id, value); setFormStateObject(localFormStateObject); }; @@ -351,12 +352,12 @@ function SlideManager({ // It is an already added temp file. if (entry.tempId) { newField.push(entry.tempId); - localMediaData[entry.tempId] = entry; + set(localMediaData, entry.tempId, entry); } // It is a new temp file. else { if (!Array.isArray(localFormStateObject.content[fieldId])) { - localFormStateObject.content[fieldId] = []; + set(localFormStateObject.content, fieldId, []); } // Create a tempId for the media. @@ -367,7 +368,7 @@ function SlideManager({ const newEntry = { ...entry }; newEntry.tempId = tempId; - localMediaData[tempId] = newEntry; + set(localMediaData, tempId, newEntry); } } // Previously selected file. @@ -381,7 +382,7 @@ function SlideManager({ if ( !Object.prototype.hasOwnProperty.call(localMediaData, entry["@id"]) ) { - localMediaData[entry["@id"]] = entry; + set(localMediaData, entry["@id"], entry); localFormStateObject.media.push(entry["@id"]); } @@ -389,8 +390,10 @@ function SlideManager({ }); } - localFormStateObject.content[fieldId] = newField; - localFormStateObject.media = [...new Set([...localFormStateObject.media])]; + set(localFormStateObject.content, fieldId, newField); + set(localFormStateObject, "media", [ + ...new Set([...localFormStateObject.media]), + ]); setFormStateObject(localFormStateObject); setMediaData(localMediaData); @@ -402,7 +405,7 @@ function SlideManager({ // Setup submittingMedia list. mediaFields.forEach((fieldName) => { - const fieldData = formStateObject.content[fieldName]; + const fieldData = get(formStateObject.content, fieldName); if (fieldData) { if (Array.isArray(fieldData)) { @@ -552,10 +555,14 @@ function SlideManager({ newFormStateObject.media.push(savedMediaData["@id"]); // Replace TEMP-- id with real id. - newFormStateObject.content[submittedMedia.fieldName] = - newFormStateObject.content[submittedMedia.fieldName].map((mediaId) => - mediaId === submittedMedia.tempId ? savedMediaData["@id"] : mediaId, - ); + set( + newFormStateObject.content, + submittedMedia.fieldName, + get(newFormStateObject.content, submittedMedia.fieldName).map( + (mediaId) => + mediaId === submittedMedia.tempId ? savedMediaData["@id"] : mediaId, + ), + ); const newMediaData = { ...mediaData }; newMediaData[savedMediaData["@id"]] = savedMediaData; diff --git a/assets/admin/components/util/table/table-body.jsx b/assets/admin/components/util/table/table-body.jsx index 25162e8f..53030afe 100644 --- a/assets/admin/components/util/table/table-body.jsx +++ b/assets/admin/components/util/table/table-body.jsx @@ -1,5 +1,6 @@ import { Fragment } from "react"; import useModal from "../../../context/modal-context/modal-context-hook"; +import { get } from "lodash/object"; /** * @param {object} props The props. @@ -22,7 +23,7 @@ function TableBody({ columns, data }) { return column.content(item); } - let cellData = item[column.path]; + let cellData = get(item, column.path); if (column.dataFunction) { cellData = column.dataFunction(cellData); diff --git a/assets/client/data-sync/pull-strategy.js b/assets/client/data-sync/pull-strategy.js index ca1b96d2..1d0dfd60 100644 --- a/assets/client/data-sync/pull-strategy.js +++ b/assets/client/data-sync/pull-strategy.js @@ -1,6 +1,7 @@ import isPublished from "../util/isPublished"; import logger from "../logger/logger"; import ApiHelper from "./api-helper"; +import { cloneDeep } from "lodash"; /** * PullStrategy. @@ -135,7 +136,7 @@ class PullStrategy { async getSlidesForRegions(regions) { return new Promise((resolve, reject) => { const promises = []; - const regionData = structuredClone(regions); + const regionData = cloneDeep(regions); // @TODO: Fix eslint-raised issues. // eslint-disable-next-line guard-for-in,no-restricted-syntax @@ -199,7 +200,7 @@ class PullStrategy { return; } - const newScreen = structuredClone(screen); + const newScreen = cloneDeep(screen); newScreen.hasActiveCampaign = false; @@ -303,7 +304,7 @@ class PullStrategy { const dataEntrySlidesData = dataEntryPlaylist.slidesData; for (const slideKey of Object.keys(dataEntrySlidesData)) { - const slide = structuredClone(dataEntrySlidesData[slideKey]); + const slide = cloneDeep(dataEntrySlidesData[slideKey]); let previousSlide = null; @@ -314,7 +315,7 @@ class PullStrategy { this.lastestScreenData.regionData[regionKey][playlistKey] .slidesData[slideKey] ) { - previousSlide = structuredClone( + previousSlide = cloneDeep( this.lastestScreenData.regionData[regionKey][playlistKey] .slidesData[slideKey], ); diff --git a/assets/client/service/schedule-service.js b/assets/client/service/schedule-service.js index 7cdfdfbe..23b56757 100644 --- a/assets/client/service/schedule-service.js +++ b/assets/client/service/schedule-service.js @@ -5,6 +5,7 @@ import isPublished from "../util/isPublished"; import logger from "../logger/logger"; import ClientConfigLoader from "../util/client-config-loader.js"; import ScheduleUtils from "../util/schedule"; +import { cloneDeep } from "lodash"; /** * ScheduleService. @@ -213,7 +214,7 @@ class ScheduleService { return; } - const newSlide = structuredClone(slide); + const newSlide = cloneDeep(slide); // Execution id is the product of region, playlist and slide id, to ensure uniqueness in the client. const executionId = Md5(regionId + playlist["@id"] + slide["@id"]); diff --git a/assets/tests/template/template-calendar.spec.js b/assets/tests/template/template-calendar.spec.js index 815d909c..34b0a158 100644 --- a/assets/tests/template/template-calendar.spec.js +++ b/assets/tests/template/template-calendar.spec.js @@ -10,11 +10,6 @@ const fixTime = async (page) => { await page.clock.install({ time: newDate }); }; -const fixTimeToNow = async (page) => { - const newDate = new Date(); - await page.clock.install({ time: newDate }); -}; - test("calendar-0-multiple-days: ui tests", async ({ page }) => { await fixTime(page); @@ -236,7 +231,7 @@ test("calendar-0-single-booking: ui tests", async ({ page }) => { }); test("calendar-1-single-booking: ui tests", async ({ page }) => { - await fixTimeToNow(page); + await fixTime(page); await page.goto("/template/calendar-1-single-booking"); await expect(page.getByText("Ledigt")).toHaveCount(1); await expect(page.getByText("Ledigt")).toBeVisible(); diff --git a/package-lock.json b/package-lock.json index 2ae4c9f6..1d5c4ee9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "html-react-parser": "^1.3.0", "i18next": "^21.6.14", "jwt-decode": "^3.1.2", + "lodash": "^4.17.23", "pino": "^9.1.0", "qrcode": "^1.5.4", "query-string": "^7.1.1", @@ -184,6 +185,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1060,6 +1062,7 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz", "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", "license": "MIT", + "peer": true, "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" @@ -1226,6 +1229,7 @@ "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "^0.2.36" }, @@ -1718,6 +1722,7 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -1765,9 +1770,9 @@ "license": "MIT" }, "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -2360,6 +2365,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.14.0.tgz", "integrity": "sha512-nm0VWVA1Vq/jaKY3wyRXViL/kf78yMdH7qETpv4qZXDQLU+pdWV3IGoRTQTKESc7d8L1wL/2uCeByLNUJfrSIw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2582,6 +2588,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.14.0.tgz", "integrity": "sha512-rsjFH0Vd/4UbDsjwMLay7oz72VVu1r35t8ofAzy5587jn5JAjflaZs05XbRRMD2imUTK41dyajVSh8CqSnDEJw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2687,6 +2694,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.14.0.tgz", "integrity": "sha512-qQBVKqzU4ZVjRn8W0UbdfE4LaaIgcIWHOMrNnJ+PutrRzQ6ZzhmD/kRONvRWBfG9z3DU7pSKGwVYSR2hztsGuQ==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2701,6 +2709,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.14.0.tgz", "integrity": "sha512-xrZmqI5jl4yMeAsu8p8gVP9S3An5h2MBi8BQHNnZmpyzkUrlpd40vlT6u13SWIqVi5ZWhBZ6U3rL7mkVLZuRKg==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", @@ -2915,6 +2924,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3210,6 +3220,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", @@ -3614,6 +3625,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3960,6 +3972,7 @@ "devOptional": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -4481,6 +4494,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.17.2" } @@ -5024,9 +5038,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -5870,6 +5884,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -6013,6 +6028,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", "license": "MIT", + "peer": true, "dependencies": { "orderedmap": "^2.0.0" } @@ -6042,6 +6058,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-transform": "^1.0.0", @@ -6090,6 +6107,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.4.tgz", "integrity": "sha512-WkKgnyjNncri03Gjaz3IFWvCAE94XoiEgvtr0/r2Xw7R8/IjK3sKLSiDoCHWcsXSAinVaKlGRZDvMCsF1kbzjA==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -6187,6 +6205,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -6240,6 +6259,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6342,8 +6362,7 @@ "version": "19.1.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz", "integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", @@ -6453,13 +6472,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", - "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.0", - "react-router": "6.30.1" + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" }, "engines": { "node": ">=14.0.0" @@ -6470,12 +6489,12 @@ } }, "node_modules/react-router-dom/node_modules/react-router": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", - "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.0" + "@remix-run/router": "1.23.2" }, "engines": { "node": ">=14.0.0" @@ -6594,7 +6613,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/reftools": { "version": "1.1.9", @@ -6815,6 +6835,7 @@ "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -7382,6 +7403,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7437,6 +7459,7 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7560,6 +7583,7 @@ "resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.0.12.tgz", "integrity": "sha512-Gr40FRnE98FwPJcMwcJgBwP6U7Qxw/VEtDsFdFjvGUTdgI/tTmF7z7dbVo/ajItM54G+Zo9w5BIrUmat6MbuWQ==", "license": "MIT", + "peer": true, "dependencies": { "fdir": "^6.4.6", "lightningcss": "^1.30.1", @@ -7693,6 +7717,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/package.json b/package.json index dc9054b1..7602e6fc 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "html-react-parser": "^1.3.0", "i18next": "^21.6.14", "jwt-decode": "^3.1.2", + "lodash": "^4.17.23", "pino": "^9.1.0", "qrcode": "^1.5.4", "query-string": "^7.1.1",