Skip to content

ERA-11293 [Part 3: React 19] #1280

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

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 12 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,29 @@
"postcss-normalize": "^13.0.1",
"postcss-preset-env": "^10.1.5",
"prompts": "^2.4.2",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react": "^19.1.0",
"react-app-polyfill": "^3.0.0",
"react-bootstrap": "2.10.9",
"react-collapsible": "^2.10.0",
"react-datepicker": "^7.5.0",
"react-datepicker": "^8.3.0",
"react-debounce-render": "^8.0.2",
"react-dev-utils": "^12.0.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.1.2",
"react-dom": "^19.1.0",
"react-error-boundary": "^5.0.0",
"react-fast-compare": "^3.2.2",
"react-flip-toolkit": "^7.2.4",
"react-ga4": "^2.1.0",
"react-i18next": "^15.1.2",
"react-infinite-scroller": "^1.2.6",
"react-js-pagination": "^3.0.3",
"react-pin-field": "^3.1.5",
"react-pin-field": "^4.0.2",
"react-redux": "^9.1.2",
"react-refresh": "^0.17.0",
"react-router-dom": "^7.0.1",
"react-select": "^5.8.3",
"react-spinners": "^0.15.0",
"react-to-print": "^3.0.2",
"react-toastify": "^10.0.6",
"react-to-print": "^3.0.6",
"react-toastify": "^11.0.5",
"react-window": "^1.8.10",
"redux": "^5.0.1",
"redux-persist": "^5.10.0",
Expand Down Expand Up @@ -128,11 +127,11 @@
"devDependencies": {
"@babel/eslint-parser": "^7.27.0",
"@babel/runtime": "^7.27.0",
"@testing-library/dom": "^8.1.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^13.0.16",
"@testing-library/user-event": "^14.6.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-react": "^7.12.4",
"eslint-plugin-react-hooks": "^5.2.0",
Expand All @@ -145,7 +144,7 @@
"socket.io-mock": "^1.3.2",
"stylelint": "^16.17.0",
"stylelint-config-css-modules": "^4.4.0",
"stylelint-config-standard": "^37.0.0",
"stylelint-config-standard": "^38.0.0",
"stylelint-scss": "^6.11.1",
"undici": "5.0.0"
},
Expand Down
12 changes: 1 addition & 11 deletions src/AddAttachmentButton/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo, useCallback, useContext, useRef, useState } from 'react';
import Button from 'react-bootstrap/Button';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

import { TrackerContext } from '../utils/analytics';
Expand Down Expand Up @@ -36,7 +35,7 @@ const ATTACHMENT_FILE_TYPES_ACCEPTED = [
'.wmv'
];

const AddAttachmentButton = ({ className, onAddAttachments }) => {
const AddAttachmentButton = ({ className = '', onAddAttachments }) => {
const fileInputRef = useRef();
const { t } = useTranslation('details-view');

Expand Down Expand Up @@ -111,13 +110,4 @@ const AddAttachmentButton = ({ className, onAddAttachments }) => {
</>;
};

AddAttachmentButton.defaultProps = {
className: '',
};

AddAttachmentButton.propTypes = {
className: PropTypes.string,
onAddAttachments: PropTypes.func.isRequired,
};

export default memo(AddAttachmentButton);
5 changes: 0 additions & 5 deletions src/AddItemButton/AddItemModal/AddPatrolTab/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { memo, useCallback, useContext, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

Expand Down Expand Up @@ -62,8 +61,4 @@ const AddPatrolTab = ({ onHideModal }) => {
</>;
};

AddPatrolTab.propTypes = {
onHideModal: PropTypes.func.isRequired,
};

export default memo(AddPatrolTab);
20 changes: 3 additions & 17 deletions src/AddItemButton/AddItemModal/TypesList/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import React from 'react';

import EventTypeListItem from '../../../EventTypeListItem';

Expand All @@ -17,7 +16,7 @@ const CategoryList = ({ category, onClickType, showTitle }) => <div>
</ul>
</div>;

const TypesList = ({ filterText, onClickType, typesByCategory }, ref) => {
const TypesList = ({ filterText, onClickType, ref, typesByCategory }) => {
Copy link
Preview

Copilot AI Apr 22, 2025

Choose a reason for hiding this comment

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

Avoid using 'ref' as a regular prop name since it conflicts with the reserved React ref. Consider renaming it to a more descriptive term if ref forwarding is not required.

Suggested change
const TypesList = ({ filterText, onClickType, ref, typesByCategory }) => {
const TypesList = ({ filterText, onClickType, containerRef, typesByCategory }) => {

Copilot uses AI. Check for mistakes.

const filterTextLowerCase = filterText.toLowerCase();

const filteredCategories = typesByCategory.reduce((accumulator, category) => {
Expand Down Expand Up @@ -46,17 +45,4 @@ const TypesList = ({ filterText, onClickType, typesByCategory }, ref) => {
</div>;
};

const TypesListForwardRef = forwardRef(TypesList);

TypesListForwardRef.propTypes = {
filterText: PropTypes.string.isRequired,
onClickType: PropTypes.func.isRequired,
typesByCategory: PropTypes.arrayOf(PropTypes.shape({
display: PropTypes.string,
id: PropTypes.string,
types: PropTypes.array,
value: PropTypes.string,
})).isRequired,
};

export default TypesListForwardRef;
export default TypesList;
6 changes: 0 additions & 6 deletions src/AddItemButton/AddItemModal/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo, useCallback, useContext, useEffect, useState } from 'react';
import Modal from 'react-bootstrap/Modal';
import PropTypes from 'prop-types';
import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';
import { useSelector } from 'react-redux';
Expand Down Expand Up @@ -79,9 +78,4 @@ const AddItemModal = ({ onHide, show, ...restProps }) => {
</Modal>;
};

AddItemModal.propTypes = {
onHide: PropTypes.func.isRequired,
show: PropTypes.bool.isRequired,
};

export default memo(AddItemModal);
12 changes: 1 addition & 11 deletions src/AddNoteButton/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useCallback, useContext, memo } from 'react';
import Button from 'react-bootstrap/Button';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

import { TrackerContext } from '../utils/analytics';

import { ReactComponent as NoteIcon } from '../common/images/icons/note.svg';

const AddNoteButton = ({ className, onAddNote, ...rest }) => {
const AddNoteButton = ({ className = '', onAddNote, ...rest }) => {
const analytics = useContext(TrackerContext);
const { t } = useTranslation('details-view');

Expand All @@ -29,13 +28,4 @@ const AddNoteButton = ({ className, onAddNote, ...rest }) => {
</Button>;
};

AddNoteButton.defaultProps = {
className: '',
};

AddNoteButton.propTypes = {
className: PropTypes.string,
onAddNote: PropTypes.func.isRequired,
};

export default memo(AddNoteButton);
7 changes: 0 additions & 7 deletions src/AddToIncidentModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { memo, useEffect, useRef, useState } from 'react';
import Button from 'react-bootstrap/Button';
import InfiniteScroll from 'react-infinite-scroller';
import Modal from 'react-bootstrap/Modal';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

Expand Down Expand Up @@ -113,10 +112,4 @@ const AddToIncidentModal = ({ id, onAddToExistingIncident, onAddToNewIncident })
</>;
};

AddToIncidentModal.propTypes = {
id: PropTypes.string.isRequired,
onAddToExistingIncident: PropTypes.func.isRequired,
onAddToNewIncident: PropTypes.func.isRequired,
};

export default memo(AddToIncidentModal);
5 changes: 0 additions & 5 deletions src/AddToPatrolModal/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo, useRef, useEffect, useState, useReducer, useMemo, useCallback, useContext } from 'react';
import axios from 'axios';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
Expand Down Expand Up @@ -208,7 +207,3 @@ const AddToPatrolModal = (props) => {
const mapStateToProps = ({ data: { patrolStore } }) => ({ patrolStore });

export default connect(mapStateToProps, { removeModal: id => removeModal(id), updatePatrolStore: patrols => updatePatrolStore(patrols) })(memo(AddToPatrolModal));

AddToPatrolModal.propTypes = {
onAddToPatrol: PropTypes.func.isRequired,
};
3 changes: 0 additions & 3 deletions src/AlertsModal/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo, useState } from 'react';
import Modal from 'react-bootstrap/Modal';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

import { DAS_HOST } from '../constants';
Expand Down Expand Up @@ -35,6 +34,4 @@ const AlertsModal = ({ title }) => {
</>;
};

AlertsModal.propTypes = { title: PropTypes.string.isRequired };

export default memo(AlertsModal);
11 changes: 1 addition & 10 deletions src/AnalyzerLayerList/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { memo, useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Checkmark from '../Checkmark';
import Collapsible from 'react-collapsible';
Expand Down Expand Up @@ -29,7 +28,7 @@ const AnalyzerLayerList = memo(({
hiddenAnalyzerIDs,
hideAnalyzers,
showAnalyzers,
map,
map = {},
mapLayerFilter
}) => {
const { t } = useTranslation('layers', { keyPrefix: 'layerList' });
Expand Down Expand Up @@ -147,11 +146,3 @@ const mapStateToProps = (state) => ({
});

export default connect(mapStateToProps, { hideAnalyzers, showAnalyzers })(AnalyzerLayerList);

AnalyzerLayerList.defaultProps = {
map: {},
};

AnalyzerLayerList.propTypes = {
map: PropTypes.object,
};
58 changes: 24 additions & 34 deletions src/CheckableList/index.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
import React, { memo } from 'react';
import PropTypes from 'prop-types';

import CheckMark from '../Checkmark';
import { hashCode } from '../utils/string';

const CheckableList = (props) => {
const { items, itemProps, onCheckClick, itemFullyChecked, itemPartiallyChecked, itemComponent: ItemComponent, className } = props;
return <ul className={className}>
{items.map((item) => {
const fullyChecked = itemFullyChecked(item);
const partiallyChecked = itemPartiallyChecked(item);
const onClick = () => onCheckClick(item);
import CheckMark from '../Checkmark';

return <li key={item.id || hashCode(item.toString())}>
<CheckMark fullyChecked={fullyChecked} partiallyChecked={partiallyChecked} onClick={onClick} />
<ItemComponent {...item} {...itemProps} />
</li>;
})}
</ul>;
const CheckableList = ({
className,
itemComponent: ItemComponent,
itemFullyChecked,
itemPartiallyChecked = null,
itemProps = {},
items,
onCheckClick = null,
}) => <ul className={className}>
{items.map((item) => {
const fullyChecked = itemFullyChecked(item);
const partiallyChecked = itemPartiallyChecked?.(item);

};
return <li key={item.id || hashCode(item.toString())}>
<CheckMark
fullyChecked={fullyChecked}
onClick={() => onCheckClick?.(item)}
partiallyChecked={partiallyChecked}
/>

export default memo(CheckableList);
<ItemComponent {...item} {...itemProps} />
</li>;
})}
</ul>;

CheckableList.defaultProps = {
itemPartiallyChecked() {
return false;
},
onCheckClick() {
},
itemProps: {},
};

CheckableList.propTypes = {
itemFullyChecked: PropTypes.func.isRequired,
itemPartiallyChecked: PropTypes.func,
itemComponent: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
items: PropTypes.array.isRequired,
onCheckClick: PropTypes.func,
itemProps: PropTypes.object,
};
export default memo(CheckableList);
12 changes: 0 additions & 12 deletions src/CheckboxList/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo } from 'react';
import { InputGroup } from 'react-bootstrap';
import PropTypes from 'prop-types';

import * as styles from './styles.module.scss';

Expand All @@ -15,15 +14,4 @@ const CheckboxList = ({ onItemChange, options, values }) => {
</InputGroup>;
};

CheckboxList.propTypes = {
values: PropTypes.arrayOf(PropTypes.string),
options: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
}).isRequired,
),
onItemChange: PropTypes.func.isRequired,
};

export default memo(CheckboxList);
12 changes: 1 addition & 11 deletions src/Checkmark/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

import { ReactComponent as CheckIcon } from '../common/images/icons/check.svg';

import * as styles from './styles.module.scss';

const CheckMark = ({ fullyChecked, partiallyChecked, ...restProps }) => {
const CheckMark = ({ fullyChecked, partiallyChecked = false, ...restProps }) => {
const { t } = useTranslation('components', { keyPrefix: 'checkMark' });

return <CheckIcon
Expand All @@ -16,13 +15,4 @@ const CheckMark = ({ fullyChecked, partiallyChecked, ...restProps }) => {
/>;
};

CheckMark.defaultProps = {
partiallyChecked: false,
};

CheckMark.propTypes = {
fullyChecked: PropTypes.bool.isRequired,
partiallyChecked: PropTypes.bool,
};

export default memo(CheckMark);
5 changes: 1 addition & 4 deletions src/ClustersLayer/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { memo, useCallback, useContext, useMemo, useRef } from 'react';
import { featureCollection } from '@turf/turf';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';

import { addNewClusterMarkers, getRenderedClustersData, removeOldClusterMarkers } from './utils';
Expand Down Expand Up @@ -102,6 +101,4 @@ const ClustersLayer = ({ onShowClusterSelectPopup }) => {
return null;
};

ClustersLayer.propTypes = { onShowClusterSelectPopup: PropTypes.func.isRequired };

export default memo(ClustersLayer);
export default memo(ClustersLayer);
Loading