Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

removed lodash imports and dependencies and wrote js equivalents #9116

Open
wants to merge 40 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7f75a18
removed lodash imports and dependencies and wrote js equivalents
SwanandBhuskute Nov 14, 2024
cc88800
enhanced with suggestions
SwanandBhuskute Nov 14, 2024
f13a324
enhanced with suggestions 2
SwanandBhuskute Nov 14, 2024
17931f8
changes done, moved to utils and used tailwind
SwanandBhuskute Nov 15, 2024
de43d86
trying to fixing cypress tests
SwanandBhuskute Nov 15, 2024
1a136f4
trying to build fix 2
SwanandBhuskute Nov 15, 2024
87dbee1
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 21, 2024
e2abfa6
updates on comments, moving debounce and nested code to proper files
SwanandBhuskute Nov 21, 2024
ed43c9c
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 22, 2024
a8950c3
fixing cypress tests
SwanandBhuskute Nov 23, 2024
0d2e876
fixing cypress tests
SwanandBhuskute Nov 23, 2024
7bd57e5
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 25, 2024
e0b6526
fixing tests 2+4
SwanandBhuskute Nov 25, 2024
b3feb64
Merge branch 'develop' into issues/6006/removeLodash
nihal467 Nov 26, 2024
95d2bd8
Merge branch 'develop' into issues/6006/removeLodash
SwanandBhuskute Nov 27, 2024
25ea91b
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 27, 2024
14e3239
Merge branch 'issues/6006/removeLodash' of https://github.com/Swanand…
SwanandBhuskute Nov 27, 2024
9fff886
handling null string
SwanandBhuskute Nov 27, 2024
b029aca
added missing id
SwanandBhuskute Nov 27, 2024
30a9311
fix2
SwanandBhuskute Nov 27, 2024
e478511
Merge branch 'develop' into issues/6006/removeLodash
SwanandBhuskute Nov 27, 2024
4552e02
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 27, 2024
13cf031
Merge branch 'issues/6006/removeLodash' of https://github.com/Swanand…
SwanandBhuskute Nov 27, 2024
07463bc
Merge branch 'develop' into issues/6006/removeLodash
SwanandBhuskute Nov 28, 2024
bf56a6a
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 28, 2024
55a0c4a
Merge branch 'issues/6006/removeLodash' of https://github.com/Swanand…
SwanandBhuskute Nov 28, 2024
8647be9
fixed cypress 4
SwanandBhuskute Nov 28, 2024
598aae4
fixed camel and start case
SwanandBhuskute Nov 28, 2024
eac2760
Merge branch 'develop' into issues/6006/removeLodash
SwanandBhuskute Nov 29, 2024
449d574
added autoCapitalize for accepting any patient name
SwanandBhuskute Nov 29, 2024
2c521a1
Merge branch 'issues/6006/removeLodash' of https://github.com/Swanand…
SwanandBhuskute Nov 29, 2024
1790cd6
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 29, 2024
00e3ced
capitalize
SwanandBhuskute Nov 29, 2024
d3a4d98
added Status using mapping and translations
SwanandBhuskute Nov 30, 2024
8351876
Merge branch 'develop' into issues/6006/removeLodash
SwanandBhuskute Nov 30, 2024
f0ae6b2
removed translations
SwanandBhuskute Nov 30, 2024
b58bd88
Merge branch 'issues/6006/removeLodash' of https://github.com/Swanand…
SwanandBhuskute Nov 30, 2024
e6ec037
added translations for sample-test-result
SwanandBhuskute Nov 30, 2024
07ae5a2
fix
SwanandBhuskute Nov 30, 2024
9a89ca2
Merge branch 'develop' of https://github.com/SwanandBhuskute/care_fe …
SwanandBhuskute Nov 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
"i18next": "^23.16.4",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.2",
"lodash-es": "^4.17.21",
"postcss-loader": "^8.1.1",
"qrcode.react": "^4.1.0",
"raviger": "^4.1.2",
Expand All @@ -108,7 +107,6 @@
"@types/events": "^3.0.3",
"@types/google.maps": "^3.58.1",
"@types/jsdom": "^21.1.7",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-copy-to-clipboard": "^5.0.7",
Expand Down
3 changes: 2 additions & 1 deletion src/Utils/Notifications.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Stack, alert, defaultModules } from "@pnotify/core";
import * as PNotifyMobile from "@pnotify/mobile";
import { camelCase, startCase } from "lodash-es";

import { camelCase, startCase } from "@/Utils/utils";

defaultModules.set(PNotifyMobile, {});

Expand Down
55 changes: 55 additions & 0 deletions src/Utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,58 @@ export const fahrenheitToCelsius = (fahrenheit: number) => {
export const keysOf = <T extends object>(obj: T) => {
return Object.keys(obj) as (keyof T)[];
};

// Capitalize the first letter of each word in a string, handling edge cases
export const startCase = (str: string): string => {
if (!str) return "";

return str
.toLowerCase()
.replace(/\s+/g, " ")
.trim()
.split(" ")
SwanandBhuskute marked this conversation as resolved.
Show resolved Hide resolved
.map((word) => (word ? word[0].toUpperCase() + word.slice(1) : ""))
.join(" ");
};
SwanandBhuskute marked this conversation as resolved.
Show resolved Hide resolved

// Converts a string to camelCase format, first word - lowercase and each subsequent word - uppercase letter, with no spaces.
export const camelCase = (str: string) => {
if (!str) return "";
return str
.trim()
.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
.replace(/^[A-Z]/, (c) => c.toLowerCase());
};
SwanandBhuskute marked this conversation as resolved.
Show resolved Hide resolved

export function setNestedValueSafely(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's replace all usages of setNestedValueSafely with proper type-safe change handlers. And not have this helper function altogether.

obj: Record<string, any>,
path: string,
value: any,
) {
const keys = path.split(".");
let current = obj;

for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];

// Protect against prototype pollution by skipping unsafe keys
if (key === "__proto__" || key === "constructor" || key === "prototype") {
continue;
}

// Use Object.create(null) to prevent accidental inheritance from Object prototype
current[key] = current[key] || Object.create(null);
current = current[key];
}

const lastKey = keys[keys.length - 1];

// Final key assignment, ensuring no prototype pollution vulnerability
if (
lastKey !== "__proto__" &&
lastKey !== "constructor" &&
lastKey !== "prototype"
) {
current[lastKey] = value;
}
}
SwanandBhuskute marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 3 additions & 4 deletions src/components/Common/ExcelFIleDragAndDrop.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { forIn } from "lodash-es";
import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import * as XLSX from "xlsx";
Expand Down Expand Up @@ -68,9 +67,9 @@ export default function ExcelFileDragAndDrop({
const data = XLSX.utils.sheet_to_json(worksheet, { defval: "" });
//converts the date to string
data.forEach((row: any) => {
forIn(row, (value: any, key: string) => {
if (value instanceof Date) {
row[key] = value.toISOString().split("T")[0];
Object.keys(row).forEach((key) => {
if (row[key] instanceof Date) {
row[key] = row[key].toISOString().split("T")[0];
}
});
});
Expand Down
21 changes: 10 additions & 11 deletions src/components/Facility/Investigations/Reports/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import _ from "lodash";
import { useCallback, useReducer, useState } from "react";
import { useTranslation } from "react-i18next";

Expand Down Expand Up @@ -179,16 +178,16 @@ const InvestigationReports = ({ id }: any) => {
),
);

const investigationList = _.chain(data)
.flatMap((i) => i?.data?.results)
.compact()
.flatten()
.map((i) => ({
...i,
name: `${i.name} ${i.groups[0].name && " | " + i.groups[0].name} `,
}))
.unionBy("external_id")
.value();
const investigationList = Array.from(
data
.flatMap((i) => i?.data?.results || [])
.map((i) => ({
...i,
name: `${i.name} ${i.groups[0].name ? " | " + i.groups[0].name : ""}`,
}))
.reduce((map, item) => map.set(item.external_id, item), new Map())
.values(),
);

dispatch({ type: "set_investigations", payload: investigationList });
dispatch({
Expand Down
81 changes: 59 additions & 22 deletions src/components/Facility/Investigations/Reports/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,67 @@
import _ from "lodash";
import { findIndex, memoize } from "lodash-es";

import { InvestigationResponse } from "@/components/Facility/Investigations/Reports/types";

const memoize = <T extends (...args: any[]) => any>(fn: T): T => {
const cache = new Map<string, ReturnType<T>>();
const MAX_CACHE_SIZE = 1000;
return ((...args: Parameters<T>): ReturnType<T> => {
const key = args
.map((arg) =>
typeof arg === "object"
? arg instanceof Date
? arg.getTime().toString()
: JSON.stringify(Object.entries(arg).sort())
: String(arg),
)
.join("|");
if (!cache.has(key)) {
if (cache.size >= MAX_CACHE_SIZE) {
const firstKey: any = cache.keys().next().value;
cache.delete(firstKey);
}
cache.set(key, fn(...args));
}
return cache.get(key)!;
}) as T;
};

export const transformData = memoize((data: InvestigationResponse) => {
const sessions = _.chain(data)
.map((value: any) => {
return {
...value.session_object,
facility_name: value.consultation_object?.facility_name,
facility_id: value.consultation_object?.facility,
};
})
.uniqBy("session_external_id")
.orderBy("session_created_date", "desc")
.value();
const groupByInvestigation = _.chain(data)
.groupBy("investigation_object.external_id")
.values()
.value();
const sessions = Array.from(
new Map(
data.map((value: any) => [
value.session_object.session_external_id,
{
...value.session_object,
facility_name: value.consultation_object?.facility_name,
facility_id: value.consultation_object?.facility,
},
]),
).values(),
).sort(
(a, b) =>
new Date(b.session_created_date).getTime() -
new Date(a.session_created_date).getTime(),
);

const groupByInvestigation = Object.values(
data.reduce(
(acc, value: any) => {
const key = value.investigation_object.external_id;
if (!acc[key]) acc[key] = [];
acc[key].push(value);
return acc;
},
{} as { [key: string]: any[] },
),
);

const sessionMap = new Map(
sessions.map((session, index) => [session.session_external_id, index]),
);
const reqData = groupByInvestigation.map((value: any) => {
const sessionValues = Array.from({ length: sessions.length });
value.forEach((val: any) => {
const sessionIndex = findIndex(sessions, [
"session_external_id",
val.session_object.session_external_id,
]);
const sessionIndex =
sessionMap.get(val.session_object.session_external_id) ?? -1;
if (sessionIndex > -1) {
sessionValues[sessionIndex] = {
min: val.investigation_object.min_value,
Expand Down Expand Up @@ -58,6 +94,7 @@ export const transformData = memoize((data: InvestigationResponse) => {
sessionValues,
};
});

return { sessions, data: reqData };
});

Expand Down
29 changes: 17 additions & 12 deletions src/components/Facility/Investigations/ShowInvestigation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import _ from "lodash";
import { set } from "lodash-es";
import { useCallback, useReducer } from "react";
import { useTranslation } from "react-i18next";

Expand All @@ -11,6 +9,7 @@ import * as Notification from "@/Utils/Notifications";
import routes from "@/Utils/request/api";
import request from "@/Utils/request/request";
import useQuery from "@/Utils/request/useQuery";
import { setNestedValueSafely } from "@/Utils/utils";

const initialState = {
changedFields: {},
Expand Down Expand Up @@ -93,7 +92,9 @@ export default function ShowInvestigation(props: ShowInvestigationProps) {

const handleValueChange = (value: any, name: string) => {
const changedFields = { ...state.changedFields };
set(changedFields, name, value);

setNestedValueSafely(changedFields, name, value);

dispatch({ type: "set_changed_fields", changedFields });
};

Expand Down Expand Up @@ -151,15 +152,19 @@ export default function ShowInvestigation(props: ShowInvestigationProps) {
};

const handleUpdateCancel = useCallback(() => {
const changedValues = _.chain(state.initialValues)
.map((val: any, _key: string) => ({
id: val?.id,
initialValue: val?.notes || val?.value || null,
value: val?.value || null,
notes: val?.notes || null,
}))
.reduce((acc: any, cur: any) => ({ ...acc, [cur.id]: cur }), {})
.value();
const changedValues = Object.keys(state.initialValues).reduce(
(acc: any, key: any) => {
const val = state.initialValues[key];
acc[key] = {
id: val?.id,
initialValue: val?.notes || val?.value || null,
value: val?.value || null,
notes: val?.notes || null,
};
return acc;
},
{},
);
dispatch({ type: "set_changed_fields", changedFields: changedValues });
}, [state.initialValues]);

Expand Down
21 changes: 19 additions & 2 deletions src/components/Facility/Investigations/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { set } from "lodash-es";
import { useState } from "react";

import { SelectFormField } from "@/components/Form/FormFields/SelectFormField";
Expand Down Expand Up @@ -60,7 +59,25 @@

const handleValueChange = (value: any, name: string) => {
const form = { ...state };
set(form, name, value);
const keys = name.split(".");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SwanandBhuskute This seems like a usage of setNestedValueSafely


// Validate keys to prevent prototype pollution - coderabbit suggested
if (
keys.some((key) =>
["__proto__", "constructor", "prototype"].includes(key),
)
) {
console.error("Invalid object key detected");
SwanandBhuskute marked this conversation as resolved.
Show resolved Hide resolved
return;
}

let current = form;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!current[key]) current[key] = {};
current = current[key];
}
current[keys[keys.length - 1]] = value;

Check warning

Code scanning / CodeQL

Prototype-polluting function Medium

The property chain
here
is recursively assigned to
current
without guarding against prototype pollution.
dispatch({ type: "set_form", form });
};

Expand Down
Loading
Loading