diff --git a/frontend/package.json b/frontend/package.json
index a393e002c4..8772d07fbc 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -3,6 +3,7 @@
"version": "0.1.0",
"license": "BSD-2-Clause",
"private": false,
+ "type": "module",
"dependencies": {
"@hotosm/id": "^2.30.2",
"@hotosm/iso-countries-languages": "^1.1.2",
diff --git a/frontend/src/components/banner/topBanner.tsx b/frontend/src/components/banner/topBanner.tsx
index e1988b8b95..9fffe9d757 100644
--- a/frontend/src/components/banner/topBanner.tsx
+++ b/frontend/src/components/banner/topBanner.tsx
@@ -20,7 +20,7 @@ export function TopBanner() {
return (
<>
{/* @ts-expect-error TS Migrations */}
- {location.pathname === '/' && data.visible && !error && (
+ {location.pathname === '/' && data?.visible && !error && (
& {
loading?: boolean;
};
-export function Button(props: ButtonProps) {
+export const Button = React.forwardRef
((props, ref) => {
const { children, icon, className, loading = false, disabled, ...rest } = props;
return (
@@ -27,13 +27,14 @@ export function Button(props: ButtonProps) {
className={`${className || ''} br1 f5 bn ${disabled || loading ? 'o-50' : 'pointer'}`}
style={{ padding: '.75rem 1.5rem' }}
disabled={disabled || loading}
+ ref={ref}
{...rest}
>
{loading ? : icon && {icon}}
{children}
);
-}
+})
export function FormSubmitButton(
props: React.ButtonHTMLAttributes & {
diff --git a/frontend/src/components/deleteModal/index.jsx b/frontend/src/components/deleteModal/index.jsx
index 4161876ad0..bd2fcf1496 100644
--- a/frontend/src/components/deleteModal/index.jsx
+++ b/frontend/src/components/deleteModal/index.jsx
@@ -7,7 +7,7 @@ import Popup from 'reactjs-popup';
import messages from './messages';
import { fetchLocalJSONAPI } from '../../network/genericJSONRequest';
import { DeleteButton } from '../teamsAndOrgs/management';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { AlertIcon } from '../svgIcons';
const DeleteTrigger = forwardRef((props, ref) => );
diff --git a/frontend/src/components/header/index.tsx b/frontend/src/components/header/index.tsx
index bb269d6914..cc70fe1018 100644
--- a/frontend/src/components/header/index.tsx
+++ b/frontend/src/components/header/index.tsx
@@ -10,7 +10,7 @@ import logo from '../../assets/img/main-logo.svg';
import { ExternalLinkIcon } from '../svgIcons';
import { Dropdown } from '../dropdown';
import { LocaleSelector } from '../localeSelect';
-import { Button, ButtonProps } from '../button.jsx';
+import { Button, ButtonProps } from '../button';
import { UpdateDialog } from './updateDialog';
import { BurgerMenu } from './burgerMenu';
import { TopNavLink } from './NavLink';
@@ -82,8 +82,10 @@ export const Header = () => {
}
};
+ console.log("USERDETAILS", userDetails);
+
const checkUserEmail = () =>
- userDetails.hasOwnProperty('emailAddress') && !userDetails.emailAddress ? (
+ userDetails?.hasOwnProperty('emailAddress') && !userDetails.emailAddress ? (
{(close) => }
@@ -186,7 +188,7 @@ export function getMenuItemsForUser(userDetails: any, organisations?: any) {
}
let filteredMenuItems;
- if (userDetails.username) {
+ if (userDetails?.username) {
filteredMenuItems = menuItems.filter((item) => item.authenticated === true || item.showAlways);
if (
userDetails.role !== 'ADMIN' &&
@@ -273,7 +275,7 @@ export const ActionItems = ({
location: any;
getUserLinks: (role: string) => any;
}) =>
- userDetails.username ? (
+ userDetails?.username ? (
<>
import('./timeline' /* webpackChunkName: "timeline" */));
diff --git a/frontend/src/components/projectDetail/privateProjectError.jsx b/frontend/src/components/projectDetail/privateProjectError.jsx
index fd01c84d7d..c357b8f53d 100644
--- a/frontend/src/components/projectDetail/privateProjectError.jsx
+++ b/frontend/src/components/projectDetail/privateProjectError.jsx
@@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
import messages from './messages';
import { LockIcon } from '../svgIcons';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
const PrivateProjectError = () => {
const navigate = useNavigate();
diff --git a/frontend/src/components/projectDetail/questionsAndComments.jsx b/frontend/src/components/projectDetail/questionsAndComments.jsx
index 07e19a4cb6..64c866b7c7 100644
--- a/frontend/src/components/projectDetail/questionsAndComments.jsx
+++ b/frontend/src/components/projectDetail/questionsAndComments.jsx
@@ -7,7 +7,7 @@ import ReactPlaceholder from 'react-placeholder';
import messages from './messages';
import { RelativeTimeWithUnit } from '../../utils/formattedRelativeTime';
import { PaginatorLine } from '../paginator';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { Alert } from '../alert';
import { MessageStatus } from '../comments/status';
import { UserAvatar } from '../user/avatar';
diff --git a/frontend/src/components/projectEdit/actionsForm.jsx b/frontend/src/components/projectEdit/actionsForm.jsx
index bd5726b3ce..6aecb3ebdc 100644
--- a/frontend/src/components/projectEdit/actionsForm.jsx
+++ b/frontend/src/components/projectEdit/actionsForm.jsx
@@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { Alert } from '../alert';
import { DeleteModal } from '../deleteModal';
import { styleClasses, StateContext } from '../../views/projectEdit';
diff --git a/frontend/src/components/projectEdit/partnersForm.jsx b/frontend/src/components/projectEdit/partnersForm.jsx
index 4cb8ab3b0a..a938520e5b 100644
--- a/frontend/src/components/projectEdit/partnersForm.jsx
+++ b/frontend/src/components/projectEdit/partnersForm.jsx
@@ -12,7 +12,7 @@ import PropTypes from 'prop-types';
import messages from './messages';
import { Alert } from '../alert';
import { ChevronDownIcon, CloseIcon } from '../svgIcons';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { styleClasses } from '../../views/projectEdit';
import { pushToLocalJSONAPI } from '../../network/genericJSONRequest';
import { useAllPartnersQuery } from '../../api/projects';
diff --git a/frontend/src/components/projectEdit/partnersListing.jsx b/frontend/src/components/projectEdit/partnersListing.jsx
index ae9a55f9a5..bc58793656 100644
--- a/frontend/src/components/projectEdit/partnersListing.jsx
+++ b/frontend/src/components/projectEdit/partnersListing.jsx
@@ -14,7 +14,7 @@ import PropTypes from 'prop-types';
import messages from './messages';
import { Alert } from '../alert';
import { BanIcon, CircleMinusIcon, CircleExclamationIcon } from '../svgIcons';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { styleClasses } from '../../views/projectEdit';
import { fetchLocalJSONAPI, pushToLocalJSONAPI } from '../../network/genericJSONRequest';
import { DateCustomInput } from './partnersForm';
diff --git a/frontend/src/components/projectEdit/permissionsBlock.jsx b/frontend/src/components/projectEdit/permissionsBlock.jsx
index 1ceffa080d..b589c015f2 100644
--- a/frontend/src/components/projectEdit/permissionsBlock.jsx
+++ b/frontend/src/components/projectEdit/permissionsBlock.jsx
@@ -1,6 +1,6 @@
import { useContext } from 'react';
import { FormattedMessage } from 'react-intl';
-import messages from './messages.js';
+import messages from './messages';
import { StateContext, styleClasses } from '../../views/projectEdit';
export const PermissionsBlock = ({ permissions, type }) => {
diff --git a/frontend/src/components/projectEdit/teamSelect.jsx b/frontend/src/components/projectEdit/teamSelect.jsx
index 14b9e5ec09..3a97b3fafc 100644
--- a/frontend/src/components/projectEdit/teamSelect.jsx
+++ b/frontend/src/components/projectEdit/teamSelect.jsx
@@ -4,7 +4,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
import messages from './messages';
import commonMessages from '../messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { StateContext } from '../../views/projectEdit';
import { PencilIcon, WasteIcon, ExternalLinkIcon } from '../svgIcons';
import { useFetchWithAbort } from '../../hooks/UseFetch';
diff --git a/frontend/src/components/projects/moreFiltersForm.jsx b/frontend/src/components/projects/moreFiltersForm.jsx
index ab12880cba..90744613d8 100644
--- a/frontend/src/components/projects/moreFiltersForm.jsx
+++ b/frontend/src/components/projects/moreFiltersForm.jsx
@@ -4,7 +4,7 @@ import { useQueryParam, BooleanParam } from 'use-query-params';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { SwitchToggle } from '../formInputs';
import { useTagAPI } from '../../hooks/UseTagAPI';
import { useExploreProjectsQueryParams } from '../../hooks/UseProjectsQueryAPI';
diff --git a/frontend/src/components/projects/partnersFilterSelect.jsx b/frontend/src/components/projects/partnersFilterSelect.jsx
index b5e831b33e..b7c765a07d 100644
--- a/frontend/src/components/projects/partnersFilterSelect.jsx
+++ b/frontend/src/components/projects/partnersFilterSelect.jsx
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
import { DateCustomInput } from '../projectEdit/partnersForm';
import { useAllPartnersQuery } from '../../api/projects';
import messagesFromProjectEdit from '../projectEdit/messages';
-import messages from './messages.js';
+import messages from './messages';
export const PartnersFilterSelect = ({
fieldsetName,
diff --git a/frontend/src/components/taskSelection/action.jsx b/frontend/src/components/taskSelection/action.jsx
index 20fdcf9893..7546971dea 100644
--- a/frontend/src/components/taskSelection/action.jsx
+++ b/frontend/src/components/taskSelection/action.jsx
@@ -10,7 +10,7 @@ import messages from './messages';
import { ProjectInstructions } from './instructions';
import { TasksMap } from './map';
import { HeaderLine } from '../projectDetail/header';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import Portal from '../portal';
import { SidebarIcon } from '../svgIcons';
import { openEditor, getTaskGpxUrl, formatImageryUrl, formatJosmUrl } from '../../utils/openEditor';
diff --git a/frontend/src/components/taskSelection/contributions.jsx b/frontend/src/components/taskSelection/contributions.jsx
index 348e15015d..ebd7cb5d98 100644
--- a/frontend/src/components/taskSelection/contributions.jsx
+++ b/frontend/src/components/taskSelection/contributions.jsx
@@ -4,7 +4,7 @@ import Select from 'react-select';
import ReactPlaceholder from 'react-placeholder';
import { FormattedMessage, useIntl } from 'react-intl';
-import messages from './messages.js';
+import messages from './messages';
import { UserAvatar } from '../user/avatar';
import { CheckCircle } from '../checkCircle';
import { CustomButton } from '../button';
diff --git a/frontend/src/components/taskSelection/extendSession.jsx b/frontend/src/components/taskSelection/extendSession.jsx
index d0fde5c3d1..d6278a8f74 100644
--- a/frontend/src/components/taskSelection/extendSession.jsx
+++ b/frontend/src/components/taskSelection/extendSession.jsx
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import Popup from 'reactjs-popup';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { Alert } from '../alert';
import { pushToLocalJSONAPI } from '../../network/genericJSONRequest';
import messages from './messages';
diff --git a/frontend/src/components/taskSelection/footer.jsx b/frontend/src/components/taskSelection/footer.jsx
index 8e15d03f63..821a4cfc21 100644
--- a/frontend/src/components/taskSelection/footer.jsx
+++ b/frontend/src/components/taskSelection/footer.jsx
@@ -10,7 +10,7 @@ import { openEditor, formatJosmUrl } from '../../utils/openEditor';
import { useFetchLockedTasks } from '../../hooks/UseLockedTasks';
import { pushToLocalJSONAPI, fetchLocalJSONAPI } from '../../network/genericJSONRequest';
import { Dropdown } from '../dropdown';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { Imagery } from './imagery';
import { MappingTypes } from '../mappingTypes';
import { LockedTaskModalContent } from './lockedTasks';
diff --git a/frontend/src/components/taskSelection/lockedTasks.jsx b/frontend/src/components/taskSelection/lockedTasks.jsx
index 562e28611a..584c0766c5 100644
--- a/frontend/src/components/taskSelection/lockedTasks.jsx
+++ b/frontend/src/components/taskSelection/lockedTasks.jsx
@@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { useGetLockedTasks } from '../../hooks/UseLockedTasks';
export function AnotherProjectLock({ projectId, lockedTasksLength, action }) {
diff --git a/frontend/src/components/taskSelection/permissionErrorModal.jsx b/frontend/src/components/taskSelection/permissionErrorModal.jsx
index bd222dca4c..c918985478 100644
--- a/frontend/src/components/taskSelection/permissionErrorModal.jsx
+++ b/frontend/src/components/taskSelection/permissionErrorModal.jsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import messages from './messages';
import { getPermissionErrorMessage } from '../../utils/projectPermissions';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { CloseIcon } from '../svgIcons';
import { TeamBox } from '../teamsAndOrgs/teams';
diff --git a/frontend/src/components/teamsAndOrgs/campaigns.jsx b/frontend/src/components/teamsAndOrgs/campaigns.jsx
index 40448cc051..47427a82ae 100644
--- a/frontend/src/components/teamsAndOrgs/campaigns.jsx
+++ b/frontend/src/components/teamsAndOrgs/campaigns.jsx
@@ -7,7 +7,7 @@ import ReactPlaceholder from 'react-placeholder';
import { nCardPlaceholders } from './campaignsPlaceholder';
import messages from './messages';
import { Management } from './management';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { HashtagIcon } from '../svgIcons';
import { TextField } from '../formInputs';
diff --git a/frontend/src/components/teamsAndOrgs/leaveTeamConfirmationAlert.jsx b/frontend/src/components/teamsAndOrgs/leaveTeamConfirmationAlert.jsx
index 0ef7586252..148e6bb3a7 100644
--- a/frontend/src/components/teamsAndOrgs/leaveTeamConfirmationAlert.jsx
+++ b/frontend/src/components/teamsAndOrgs/leaveTeamConfirmationAlert.jsx
@@ -2,7 +2,7 @@ import { FormattedMessage } from 'react-intl';
import commonMessages from '../../views/messages';
import messages from './messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { styleClasses } from '../../views/projectEdit';
export const LeaveTeamConfirmationAlert = ({ teamName, close, leaveTeam }) => {
diff --git a/frontend/src/components/teamsAndOrgs/members.jsx b/frontend/src/components/teamsAndOrgs/members.jsx
index 6c5cb90e7c..e623668aaa 100644
--- a/frontend/src/components/teamsAndOrgs/members.jsx
+++ b/frontend/src/components/teamsAndOrgs/members.jsx
@@ -7,7 +7,7 @@ import AsyncSelect from 'react-select/async';
import messages from './messages';
import { UserAvatar } from '../user/avatar';
import { EditModeControl } from './editMode';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { SwitchToggle } from '../formInputs';
import { fetchLocalJSONAPI, pushToLocalJSONAPI } from '../../network/genericJSONRequest';
import { Alert } from '../alert';
diff --git a/frontend/src/components/teamsAndOrgs/messageMembers.jsx b/frontend/src/components/teamsAndOrgs/messageMembers.jsx
index 5e3684b2ef..7ed14381b3 100644
--- a/frontend/src/components/teamsAndOrgs/messageMembers.jsx
+++ b/frontend/src/components/teamsAndOrgs/messageMembers.jsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import toast from 'react-hot-toast';
import messages from './messages';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { MessageStatus } from '../comments/status';
import { pushToLocalJSONAPI } from '../../network/genericJSONRequest';
import ReactPlaceholder from 'react-placeholder';
diff --git a/frontend/src/components/teamsAndOrgs/organisations.jsx b/frontend/src/components/teamsAndOrgs/organisations.jsx
index eecaa2f650..743508ce2d 100644
--- a/frontend/src/components/teamsAndOrgs/organisations.jsx
+++ b/frontend/src/components/teamsAndOrgs/organisations.jsx
@@ -13,7 +13,7 @@ import { useUploadImage } from '../../hooks/UseUploadImage';
import { levels } from '../../hooks/UseOrganisationLevel';
import { Management } from './management';
import { InternalLinkIcon, ClipboardIcon } from '../svgIcons';
-import { Button } from '../button.jsx';
+import { Button } from '../button';
import { UserAvatarList } from '../user/avatar';
import { nCardPlaceholders } from './organisationsPlaceholder';
import { Alert } from '../alert';
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index bd4f683436..720e9d82a5 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -8,7 +8,7 @@ import 'react-tooltip/dist/react-tooltip.css'; // Needed by for { Tooltip } from
import App from './App.jsx';
import { store, persistor } from './store';
-import { ConnectedIntl } from './utils/internationalization.jsx';
+import { ConnectedIntl } from './utils/internationalization';
import { register, unregister, onServiceWorkerUpdate } from './serviceWorkerRegistration';
import { ENABLE_SERVICEWORKER, SENTRY_FRONTEND_DSN, ENVIRONMENT } from './config';
diff --git a/frontend/src/utils/geoFileFunctions.js b/frontend/src/utils/geoFileFunctions.js
index ae9b17a784..57e31f5624 100644
--- a/frontend/src/utils/geoFileFunctions.js
+++ b/frontend/src/utils/geoFileFunctions.js
@@ -5,7 +5,7 @@ import { kml } from '@tmcw/togeojson';
import { MAX_FILESIZE } from '../config';
import shpjs from 'shpjs';
-var osmToGeojson = require('osmtogeojson');
+import osmToGeojson from "osmtogeojson";
export const verifyFileSize = (file) => {
if (file.size >= MAX_FILESIZE) {
diff --git a/frontend/src/views/tests/notFound.test.js b/frontend/src/views/tests/notFound.test.js
index 05c643cc89..20131ca30c 100644
--- a/frontend/src/views/tests/notFound.test.js
+++ b/frontend/src/views/tests/notFound.test.js
@@ -2,7 +2,7 @@ import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import { IntlProviders } from '../../utils/testWithIntl';
import messages from '../messages';
-import { NotFound } from '../notFound.jsx';
+import { NotFound } from '../notFound';
describe('Not Found', () => {
it('should display project not found error', () => {
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index ff4041ee12..65d41aee35 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -19,6 +19,7 @@
"jsx": "react-jsx",
/* Linting */
"strict": false,
+ "strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,