diff --git a/.eslintrc.json b/.eslintrc.json index ead948a7db..4bc0d8de2e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,7 +42,7 @@ "import/no-named-as-default": "off", "max-classes-per-file": "error", "no-useless-escape": "off", - "react/display-name": "warn", + "react/display-name": "error", "react/jsx-no-target-blank": "warn", // https://github.com/standard/eslint-config-standard-with-typescript/issues/248 "react/no-deprecated": "warn", diff --git a/package.json b/package.json index 63e5605456..9428feda44 100644 --- a/package.json +++ b/package.json @@ -183,6 +183,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-jest": "^27.2.1", "eslint-plugin-mocha": "^10.1.0", + "eslint-plugin-prefer-arrow-functions": "^3.1.4", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-sort-class-members": "^1.15.2", "eslint-plugin-unicorn": "^36.0.0", diff --git a/src/.eslintrc.json b/src/.eslintrc.json index 2ff50f91ec..31813b0715 100644 --- a/src/.eslintrc.json +++ b/src/.eslintrc.json @@ -1,5 +1,15 @@ { "rules": { - "no-console": "error" - } + "no-console": "error", + "prefer-arrow-functions/prefer-arrow-functions": [ + "error", + { + "classPropertiesAllowed": false, + "disallowPrototype": false, + "returnStyle": "unchanged", + "singleReturnOnly": false + } + ] + }, + "plugins": ["prefer-arrow-functions"] } diff --git a/src/common/Error/handlers/Reloader.tsx b/src/common/Error/handlers/Reloader.tsx index defc829008..b03298bb44 100644 --- a/src/common/Error/handlers/Reloader.tsx +++ b/src/common/Error/handlers/Reloader.tsx @@ -16,7 +16,7 @@ export const attemptReload = () => { * Set a sessionStorage value with a future expiry date that will prompt self-deletion * even if page session not closed (i.e. tab left open) **/ -function setWithExpiry(key: string, value: string, ttl: number) { +const setWithExpiry = (key: string, value: string, ttl: number) => { const item = { value: value, expiry: new Date().getTime() + ttl, @@ -25,7 +25,7 @@ function setWithExpiry(key: string, value: string, ttl: number) { } /** Get a sessionStorage value with an expiry date, returning value only if not expired */ -function getWithExpiry(key: string): string | null { +const getWithExpiry = (key: string): string | null => { const itemString = window.sessionStorage.getItem(key) if (!itemString) return null diff --git a/src/common/Form/Select.field.tsx b/src/common/Form/Select.field.tsx index 296eb18145..8b522559b6 100644 --- a/src/common/Form/Select.field.tsx +++ b/src/common/Form/Select.field.tsx @@ -20,20 +20,16 @@ interface ISelectFieldProps extends FieldProps { // therefore the following two functions are used for converting to-from string values and field options // depending on select type (e.g. multi) and option selected get value -function getValueFromSelect( +const getValueFromSelect = ( v: ISelectOption | ISelectOption[] | null | undefined, -) { - return v ? (Array.isArray(v) ? v.map((el) => el.value) : v.value) : v -} +) => (v ? (Array.isArray(v) ? v.map((el) => el.value) : v.value) : v) // given current values find the relevant select options -function getValueForSelect( +const getValueForSelect = ( opts: ISelectOption[] = [], v: string | string[] | null | undefined, -) { - function findVal(optVal: string) { - return opts.find((o) => o.value === optVal) - } +) => { + const findVal = (optVal: string) => opts.find((o) => o.value === optVal) return v ? Array.isArray(v) ? v.map((optVal) => findVal(optVal) as ISelectOption) diff --git a/src/common/Form/UnsavedChangesDialog.tsx b/src/common/Form/UnsavedChangesDialog.tsx index 4eb86ce408..629ef4a228 100644 --- a/src/common/Form/UnsavedChangesDialog.tsx +++ b/src/common/Form/UnsavedChangesDialog.tsx @@ -10,7 +10,7 @@ interface IProps { const CONFIRM_DIALOG_MSG = 'You have unsaved changes. Are you sure you want to leave this page?' -const beforeUnload = function (e) { +const beforeUnload = (e) => { e.preventDefault() e.returnValue = CONFIRM_DIALOG_MSG } diff --git a/src/common/isUserVerified.ts b/src/common/isUserVerified.ts index 2b9e80a395..313bdc4e25 100644 --- a/src/common/isUserVerified.ts +++ b/src/common/isUserVerified.ts @@ -1,7 +1,7 @@ import type { AggregationsStore } from 'src/stores/Aggregations/aggregations.store' import { useCommonStores } from '../' -export const isUserVerified = function (userId: string) { +export const isUserVerified = (userId: string) => { const { aggregationsStore } = useCommonStores().stores return isUserVerifiedWithStore(userId, aggregationsStore) } @@ -11,9 +11,7 @@ export const isUserVerified = function (userId: string) { * are not compatible with hooks. * https://reactjs.org/docs/hooks-intro.html */ -export const isUserVerifiedWithStore = function ( +export const isUserVerifiedWithStore = ( userId: string, store: AggregationsStore, -) { - return store.aggregations.users_verified?.[userId] -} +) => store.aggregations.users_verified?.[userId] diff --git a/src/config/config.ts b/src/config/config.ts index a4f42205e3..6aa33e0df2 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -25,7 +25,7 @@ import type { UserRole } from '../models' * @param fallbackValue - optional fallback value * @returns string */ -function _c(property: ConfigurationOption, fallbackValue?: string): string { +const _c = (property: ConfigurationOption, fallbackValue?: string): string => { const configurationSource = ['development', 'test'].includes( process.env.NODE_ENV, ) @@ -43,7 +43,7 @@ export const getConfigurationOption = _c // On dev sites user can override default role const devSiteRole: UserRole = localStorage.getItem('devSiteRole') as UserRole -function getSiteVariant(): siteVariants { +const getSiteVariant = (): siteVariants => { const devSiteVariant: siteVariants = localStorage.getItem( 'devSiteVariant', ) as any diff --git a/src/modules/admin/components/Table/HeadFilter.tsx b/src/modules/admin/components/Table/HeadFilter.tsx index ad945b7cd1..2d4e189e63 100644 --- a/src/modules/admin/components/Table/HeadFilter.tsx +++ b/src/modules/admin/components/Table/HeadFilter.tsx @@ -25,7 +25,7 @@ const Top = styled(Box)` border-bottom: 15px solid white; ` -function HeadFilter(props: Props) { +const HeadFilter = (props: Props) => { const { field, filterOptions, diff --git a/src/modules/admin/components/Table/Table.tsx b/src/modules/admin/components/Table/Table.tsx index 9aced96fad..a253432d1a 100644 --- a/src/modules/admin/components/Table/Table.tsx +++ b/src/modules/admin/components/Table/Table.tsx @@ -58,98 +58,96 @@ const getTHeadThProps: ComponentPropsGetterC = ( } } -function Table(props: ITableProps) { - return ( - <> - {/* Override styles applied in global css */} - - { - const isSortAsc = row.className?.includes('-sort-asc') - const isSortDesc = row.className?.includes('-sort-desc') - const { header, className, toggleSort } = row - return ( - - toggleSort?.(e)} - p={2} - sx={{ - backgroundColor: '#E2EDF7', - borderRadius: '4px', - }} - className={className} - > - {header} - - {isSortAsc && ⬆️} - {isSortDesc && ⬇️} - {props.filterComponent && props.filterComponent({ ...row })} - - ) - }} - TdComponent={(col) => ( - - - - )} - getTdProps={getTdProps} - getTheadThProps={getTHeadThProps} - getTrProps={() => { - return { - style: { - marginTop: '10px', - marginBottom: '10px', - border: '1px solid', - borderRadius: '10px', - display: 'flex', - alignItems: 'center', - padding: '10px', - height: '4rem', - backgroundColor: 'white', +const Table = (props: ITableProps) => ( + <> + {/* Override styles applied in global css */} + + { + const isSortAsc = row.className?.includes('-sort-asc') + const isSortDesc = row.className?.includes('-sort-desc') + const { header, className, toggleSort } = row + return ( + + toggleSort?.(e)} + p={2} + sx={{ + backgroundColor: '#E2EDF7', + borderRadius: '4px', + }} + className={className} + > + {header} + + {isSortAsc && ⬆️} + {isSortDesc && ⬇️} + {props.filterComponent && props.filterComponent({ ...row })} + + ) + }} + TdComponent={(col) => ( + { - return { - style: { - marginTop: '10px', + 'a:hover': { + textDecoration: 'none', }, - } - }} - showPagination={true} - data={props.data} - columns={props.columns} - defaultPageSize={10} - minRows={props.data.length ? 3 : 1} - showPageSizeOptions={true} - sortable - /> - - ) -} + }} + > + + + )} + getTdProps={getTdProps} + getTheadThProps={getTHeadThProps} + getTrProps={() => { + return { + style: { + marginTop: '10px', + marginBottom: '10px', + border: '1px solid', + borderRadius: '10px', + display: 'flex', + alignItems: 'center', + padding: '10px', + height: '4rem', + backgroundColor: 'white', + }, + } + }} + getPaginationProps={() => { + return { + style: { + marginTop: '10px', + }, + } + }} + showPagination={true} + data={props.data} + columns={props.columns} + defaultPageSize={10} + minRows={props.data.length ? 3 : 1} + showPageSizeOptions={true} + sortable + /> + +) export default Table diff --git a/src/modules/admin/components/Table/TableHead.tsx b/src/modules/admin/components/Table/TableHead.tsx index cb40d289bb..a89b554c32 100644 --- a/src/modules/admin/components/Table/TableHead.tsx +++ b/src/modules/admin/components/Table/TableHead.tsx @@ -6,22 +6,20 @@ interface Props { row: any } -function TableHead({ children, row }: Props) { - return ( - - {children} - - ) -} +const TableHead = ({ children, row }: Props) => ( + + {children} + +) export default TableHead diff --git a/src/modules/admin/components/adminUserSearch.tsx b/src/modules/admin/components/adminUserSearch.tsx index 972fc81813..d5d5e4173f 100644 --- a/src/modules/admin/components/adminUserSearch.tsx +++ b/src/modules/admin/components/adminUserSearch.tsx @@ -7,7 +7,7 @@ type Props = { onSearchChange: (text: string) => void } -function AdminUserSearch({ total, onSearchChange }: Props) { +const AdminUserSearch = ({ total, onSearchChange }: Props) => { const theme = useTheme() return ( diff --git a/src/modules/admin/index.tsx b/src/modules/admin/index.tsx index 372129003a..de54a836e2 100644 --- a/src/modules/admin/index.tsx +++ b/src/modules/admin/index.tsx @@ -7,6 +7,16 @@ import { AuthRoute } from 'src/pages/common/AuthRoute' const moduleName = MODULE.ADMIN +/** + * Wraps the research module routing elements with the research module provider + */ +const AdminModuleContainer = () => ( + + + + +) + export const AdminModule: IPageMeta = { moduleName, path: `/${moduleName}`, @@ -15,15 +25,3 @@ export const AdminModule: IPageMeta = { description: 'Admin Home Page', requiredRole: 'admin', } - -/** - * Wraps the research module routing elements with the research module provider - */ -function AdminModuleContainer() { - return ( - - - - - ) -} diff --git a/src/modules/index.ts b/src/modules/index.ts index b942d86e27..463a0bf2bd 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -11,7 +11,7 @@ export enum MODULE { ADMIN = 'admin_v2', } -export function getSupportedModules(): MODULE[] { +export const getSupportedModules = (): MODULE[] => { const envModules: string[] = getConfigurationOption( 'REACT_APP_SUPPORTED_MODULES', @@ -24,6 +24,5 @@ export function getSupportedModules(): MODULE[] { ) } -export function isModuleSupported(MODULE): boolean { - return getSupportedModules().includes(MODULE) -} +export const isModuleSupported = (MODULE): boolean => + getSupportedModules().includes(MODULE) diff --git a/src/modules/profile/SupportedProfileTypesFactory.ts b/src/modules/profile/SupportedProfileTypesFactory.ts index e84200a940..988877d225 100644 --- a/src/modules/profile/SupportedProfileTypesFactory.ts +++ b/src/modules/profile/SupportedProfileTypesFactory.ts @@ -46,7 +46,7 @@ const MemberAndSpace = { }, } -function getProfileTypes(currentTheme?: PlatformTheme) { +const getProfileTypes = (currentTheme?: PlatformTheme) => { const PROFILE_TYPES: IProfileType[] = [ { label: ProfileType.MEMBER, @@ -107,10 +107,10 @@ function getProfileTypes(currentTheme?: PlatformTheme) { return PROFILE_TYPES } -export function SupportedProfileTypesFactory( +export const SupportedProfileTypesFactory = ( configurationString: string, currentTheme?: PlatformTheme, -) { +) => { const supportedProfileTypes = (configurationString || DEFAULT_PROFILE_TYPES) .split(',') .map((s) => s.trim()) diff --git a/src/modules/profile/index.ts b/src/modules/profile/index.ts index 6d751be330..99c3543d97 100644 --- a/src/modules/profile/index.ts +++ b/src/modules/profile/index.ts @@ -2,7 +2,7 @@ import { getConfigurationOption } from '../../config/config' import { SupportedProfileTypesFactory } from './SupportedProfileTypesFactory' import type { PlatformTheme } from '../../themes/types' -export function getSupportedProfileTypes(currentTheme?: PlatformTheme) { +export const getSupportedProfileTypes = (currentTheme?: PlatformTheme) => { const supportedProfileTypes = SupportedProfileTypesFactory( getConfigurationOption('REACT_APP_PLATFORM_PROFILES', ''), currentTheme, diff --git a/src/pages/Academy/Academy.tsx b/src/pages/Academy/Academy.tsx index a5085cdc9e..9773dccd0f 100644 --- a/src/pages/Academy/Academy.tsx +++ b/src/pages/Academy/Academy.tsx @@ -2,14 +2,13 @@ import { Route } from 'react-router' import { useCommonStores } from 'src/index' import ExternalEmbed from 'src/pages/Academy/ExternalEmbed/ExternalEmbed' -export function getFrameSrc(base, path): string { - return `${base}${path +export const getFrameSrc = (base, path): string => + `${base}${path .split('/') .filter((str) => str !== 'academy' && Boolean(str)) .join('/')}` -} -export default function Academy() { +const Academy = () => { const { stores } = useCommonStores() const src = stores.themeStore.currentTheme.academyResource @@ -25,3 +24,5 @@ export default function Academy() { /> ) } + +export default Academy diff --git a/src/pages/Howto/Content/Common/Howto.form.test.skip.tsx b/src/pages/Howto/Content/Common/Howto.form.test.skip.tsx index b3a18522ad..23ef198c37 100644 --- a/src/pages/Howto/Content/Common/Howto.form.test.skip.tsx +++ b/src/pages/Howto/Content/Common/Howto.form.test.skip.tsx @@ -5,17 +5,17 @@ import { Provider } from 'mobx-react' import { HowtoForm } from './Howto.form' declare const window: any -describe('Howto form', function () { +describe('Howto form', () => { let howtoStore let tagsStore let formValues let parentType - beforeAll(function () { + beforeAll(() => { window.confirm = jest.fn(() => true) }) - beforeEach(function () { + beforeEach(() => { howtoStore = { uploadStatus: { Start: false, @@ -46,7 +46,7 @@ describe('Howto form', function () { window.confirm.mockReset() }) - it.skip('should not show the confirm dialog', async function () { + it.skip('should not show the confirm dialog', async () => { let renderResult const navProps: any = {} await waitFor(() => { @@ -76,7 +76,7 @@ describe('Howto form', function () { expect(window.confirm).not.toBeCalled() }) - it.skip('should show the confirm dialog, title change', async function () { + it.skip('should show the confirm dialog, title change', async () => { let renderResult const navProps: any = {} await waitFor(() => { diff --git a/src/pages/Howto/Content/Howto/HowToComments/HowToComments.tsx b/src/pages/Howto/Content/Howto/HowToComments/HowToComments.tsx index c2a6f9074b..16e4343d5d 100644 --- a/src/pages/Howto/Content/Howto/HowToComments/HowToComments.tsx +++ b/src/pages/Howto/Content/Howto/HowToComments/HowToComments.tsx @@ -16,7 +16,7 @@ export const HowToComments = ({ comments }: IProps) => { const [comment, setComment] = useState('') const { stores } = useCommonStores() - async function onSubmit(comment: string) { + const onSubmit = async (comment: string) => { try { const howto = stores.howtoStore.activeHowto await stores.howtoStore.addComment(comment) @@ -49,7 +49,7 @@ export const HowToComments = ({ comments }: IProps) => { } } - async function handleEditRequest() { + const handleEditRequest = async () => { ReactGA.event({ category: 'Comments', action: 'Edit existing comment', @@ -57,7 +57,7 @@ export const HowToComments = ({ comments }: IProps) => { }) } - async function handleDelete(_id: string) { + const handleDelete = async (_id: string) => { // eslint-disable-next-line no-alert const confirmation = window.confirm( 'Are you sure you want to delete this comment?', @@ -80,7 +80,7 @@ export const HowToComments = ({ comments }: IProps) => { } } - async function handleEdit(_id: string, comment: string) { + const handleEdit = async (_id: string, comment: string) => { ReactGA.event({ category: 'Comments', action: 'Update', diff --git a/src/pages/Maps/Content/Controls/transformAvailableFiltersToGroups.tsx b/src/pages/Maps/Content/Controls/transformAvailableFiltersToGroups.tsx index fd25645238..6e6aa806ae 100644 --- a/src/pages/Maps/Content/Controls/transformAvailableFiltersToGroups.tsx +++ b/src/pages/Maps/Content/Controls/transformAvailableFiltersToGroups.tsx @@ -8,8 +8,8 @@ import { transformSpecialistWorkspaceTypeToWorkspace } from './transformSpeciali const ICON_SIZE = 30 -function asOptions(mapStore, items: Array): FilterGroupOption[] { - return (items || []) +const asOptions = (mapStore, items: Array): FilterGroupOption[] => + (items || []) .filter((item) => { return !item.hidden }) @@ -39,7 +39,6 @@ function asOptions(mapStore, items: Array): FilterGroupOption[] { } }) .filter(({ number }) => !!number) -} type FilterGroupOption = { label: string diff --git a/src/pages/Maps/Content/Controls/transformSpecialistWorkspaceTypeToWorkspace.tsx b/src/pages/Maps/Content/Controls/transformSpecialistWorkspaceTypeToWorkspace.tsx index d0847ebb66..3d5dab39d1 100644 --- a/src/pages/Maps/Content/Controls/transformSpecialistWorkspaceTypeToWorkspace.tsx +++ b/src/pages/Maps/Content/Controls/transformSpecialistWorkspaceTypeToWorkspace.tsx @@ -1,9 +1,6 @@ -export function transformSpecialistWorkspaceTypeToWorkspace( +export const transformSpecialistWorkspaceTypeToWorkspace = ( type: string, -): string { - return ['extrusion', 'injection', 'shredder', 'sheetpress', 'mix'].includes( - type, - ) +): string => + ['extrusion', 'injection', 'shredder', 'sheetpress', 'mix'].includes(type) ? 'workspace' : type -} diff --git a/src/pages/Maps/Content/View/Sprites.tsx b/src/pages/Maps/Content/View/Sprites.tsx index b38b3a7275..98ee81ad91 100644 --- a/src/pages/Maps/Content/View/Sprites.tsx +++ b/src/pages/Maps/Content/View/Sprites.tsx @@ -54,7 +54,7 @@ export const createMarkerIcon = (pin: IMapPin, currentTheme: PlatformTheme) => { * to scale cluster depending on value and ensure fits in icon * @param cluster - MarkerCluster passed from creation function */ -function getClusterSizes(cluster: MarkerCluster) { +const getClusterSizes = (cluster: MarkerCluster) => { const count = cluster.getChildCount() const order = Math.round(count).toString().length switch (order) { diff --git a/src/pages/PageList.tsx b/src/pages/PageList.tsx index 022eb79dea..e0af252279 100644 --- a/src/pages/PageList.tsx +++ b/src/pages/PageList.tsx @@ -65,11 +65,10 @@ const TermsPolicy = lazy( () => import(/* webpackChunkName: "terms" */ './policy/terms'), ) -export function getAvailablePageList(supportedModules: MODULE[]): IPageMeta[] { - return COMMUNITY_PAGES.filter((pageItem) => +export const getAvailablePageList = (supportedModules: MODULE[]): IPageMeta[] => + COMMUNITY_PAGES.filter((pageItem) => supportedModules.includes(pageItem.moduleName), ) -} export interface IPageMeta { moduleName: MODULE diff --git a/src/pages/Research/Content/Common/Research.form.tsx b/src/pages/Research/Content/Common/Research.form.tsx index 4697e9d0dc..664fc8765c 100644 --- a/src/pages/Research/Content/Common/Research.form.tsx +++ b/src/pages/Research/Content/Common/Research.form.tsx @@ -48,7 +48,7 @@ const Label = styled.label` display: block; ` -const beforeUnload = function (e) { +const beforeUnload = (e) => { e.preventDefault() e.returnValue = CONFIRM_DIALOG_MSG } diff --git a/src/pages/Research/Content/Common/Update.form.tsx b/src/pages/Research/Content/Common/Update.form.tsx index 891257d9a8..fd1c2a9573 100644 --- a/src/pages/Research/Content/Common/Update.form.tsx +++ b/src/pages/Research/Content/Common/Update.form.tsx @@ -46,7 +46,7 @@ const Label = styled.label` display: block; ` -const beforeUnload = function (e) { +const beforeUnload = (e) => { e.preventDefault() e.returnValue = CONFIRM_DIALOG_MSG } diff --git a/src/pages/Research/Content/ResearchArticle.tsx b/src/pages/Research/Content/ResearchArticle.tsx index fd931b3329..8e7ad40e9c 100644 --- a/src/pages/Research/Content/ResearchArticle.tsx +++ b/src/pages/Research/Content/ResearchArticle.tsx @@ -26,7 +26,7 @@ type IProps = RouteComponentProps<{ slug: string }> const researchCommentUrlRegex = new RegExp(researchCommentUrlPattern) -function areCommentVisible(updateIndex) { +const areCommentVisible = (updateIndex) => { let showComments = false if (researchCommentUrlRegex.test(window.location.hash)) { @@ -211,10 +211,10 @@ const ResearchArticle = observer((props: IProps) => { } }) -function transformToUserComment( +const transformToUserComment = ( comments: IComment[], loggedInUsername, -): UserComment[] { +): UserComment[] => { if (!comments) return [] return comments.map((c) => ({ ...c, diff --git a/src/pages/Research/Content/ResearchComments/ResearchComments.tsx b/src/pages/Research/Content/ResearchComments/ResearchComments.tsx index d6db4c1c67..6a2a33a051 100644 --- a/src/pages/Research/Content/ResearchComments/ResearchComments.tsx +++ b/src/pages/Research/Content/ResearchComments/ResearchComments.tsx @@ -39,7 +39,7 @@ export const ResearchComments = ({ const [viewComments, setViewComments] = useState(!!showComments) const { stores } = useCommonStores() - async function onSubmit(comment: string) { + const onSubmit = async (comment: string) => { try { setLoading(true) await researchStore.addComment(comment, update as IResearch.Update) @@ -65,7 +65,7 @@ export const ResearchComments = ({ } } - async function handleEditRequest() { + const handleEditRequest = async () => { ReactGA.event({ category: 'Comments', action: 'Edit existing comment', @@ -73,7 +73,7 @@ export const ResearchComments = ({ }) } - async function handleDelete(_id: string) { + const handleDelete = async (_id: string) => { // eslint-disable-next-line no-alert const confirmation = window.confirm( 'Are you sure you want to delete this comment?', @@ -96,7 +96,7 @@ export const ResearchComments = ({ } } - async function handleEdit(_id: string, comment: string) { + const handleEdit = async (_id: string, comment: string) => { ReactGA.event({ category: 'Comments', action: 'Update', diff --git a/src/pages/Research/index.tsx b/src/pages/Research/index.tsx index 619e33518e..905029cecc 100644 --- a/src/pages/Research/index.tsx +++ b/src/pages/Research/index.tsx @@ -9,24 +9,10 @@ import { import type { IPageMeta } from '../PageList' import ResearchRoutes from './research.routes' -/** - * Default export format used for integrating with the platform - * @description The research module enables users to share ongoing updates for - * experimental projects - */ -export const ResearchModule: IPageMeta = { - moduleName: MODULE.RESEARCH, - path: '/research', - component: , - title: 'Research', - description: 'Welcome to research', - // requiredRole: 'beta-tester', -} - /** * Wraps the research module routing elements with the research module provider */ -function ResearchModuleContainer() { +const ResearchModuleContainer = () => { const { aggregationsStore } = useCommonStores().stores // Ensure aggregations up-to-date when using any child pages and unsubscribe when leaving @@ -44,3 +30,17 @@ function ResearchModuleContainer() { ) } + +/** + * Default export format used for integrating with the platform + * @description The research module enables users to share ongoing updates for + * experimental projects + */ +export const ResearchModule: IPageMeta = { + moduleName: MODULE.RESEARCH, + path: '/research', + component: , + title: 'Research', + description: 'Welcome to research', + // requiredRole: 'beta-tester', +} diff --git a/src/pages/Research/research.routes.test.tsx b/src/pages/Research/research.routes.test.tsx index 3e0f4cea43..106c7d19c6 100644 --- a/src/pages/Research/research.routes.test.tsx +++ b/src/pages/Research/research.routes.test.tsx @@ -13,21 +13,19 @@ import type { ResearchStore } from 'src/stores/Research/research.store' jest.mock('src/index', () => ({ // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - useCommonStores() { - return { - stores: { - userStore: { - fetchAllVerifiedUsers: jest.fn(), - }, - aggregationsStore: { - aggregations: {}, - }, - researchCategoriesStore: { - allResearchCategories: [], - }, + useCommonStores: () => ({ + stores: { + userStore: { + fetchAllVerifiedUsers: jest.fn(), + }, + aggregationsStore: { + aggregations: {}, }, - } - }, + researchCategoriesStore: { + allResearchCategories: [], + }, + }, + }), })) /** When mocking research routes replace default store methods with below */ @@ -59,9 +57,7 @@ const mockResearchStore = new mockResearchStoreClass() jest.mock('src/stores/Research/research.store', () => ({ // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - useResearchStore() { - return mockResearchStore - }, + useResearchStore: () => mockResearchStore, })) describe('research.routes', () => { @@ -211,9 +207,7 @@ describe('research.routes', () => { jest.doMock('src/pages/Research/Content/Common/Research.form', () => ({ // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - default(props) { - return
{props.parentType} your research
- }, + default: (props) =>
{props.parentType} your research
, })) const wrapper = render( @@ -263,9 +257,7 @@ describe('research.routes', () => { jest.doMock('src/pages/Research/Content/Common/Research.form', () => ({ // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - default(props) { - return
{props.parentType} your research
- }, + default: (props) =>
{props.parentType} your research
, })) const wrapper = render( @@ -319,9 +311,7 @@ describe('research.routes', () => { jest.doMock('src/pages/Research/Content/EditUpdate/index.tsx', () => ({ // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - default() { - return
Edit update within research
- }, + default: () =>
Edit update within research
, })) const wrapper = render( diff --git a/src/pages/Settings/UserBadgeSettings.tsx b/src/pages/Settings/UserBadgeSettings.tsx index 05128c6ca2..615dfcade0 100644 --- a/src/pages/Settings/UserBadgeSettings.tsx +++ b/src/pages/Settings/UserBadgeSettings.tsx @@ -17,7 +17,7 @@ export const UserBadgeSettings = observer((props: { userId: string }) => { const [isLoading, setLoading] = useState(true) const [isSaving, setSaving] = useState(false) - async function fetchUser() { + const fetchUser = async () => { const user = await userStore.getUserProfile(props.userId) if (user && user.badges) { setBadges(user.badges) diff --git a/src/pages/Settings/content/formSections/Focus.section.tsx b/src/pages/Settings/content/formSections/Focus.section.tsx index 40e3b2e6c6..452a2d7d40 100644 --- a/src/pages/Settings/content/formSections/Focus.section.tsx +++ b/src/pages/Settings/content/formSections/Focus.section.tsx @@ -7,7 +7,7 @@ import { CustomRadioField } from './Fields/CustomRadio.field' import { Field } from 'react-final-form' import { useTheme } from '@emotion/react' -function ProfileTypes() { +const ProfileTypes = () => { const theme = useTheme() const profileTypes = getSupportedProfileTypes().filter(({ label }) => Object.keys(theme.badges).includes(label), @@ -62,6 +62,6 @@ function ProfileTypes() { ) } -export function FocusSection() { - return -} +export const FocusSection = () => ( + +) diff --git a/src/pages/User/content/SpaceProfile.tsx b/src/pages/User/content/SpaceProfile.tsx index 03a2fb40bc..632e58d6c6 100644 --- a/src/pages/User/content/SpaceProfile.tsx +++ b/src/pages/User/content/SpaceProfile.tsx @@ -153,8 +153,8 @@ const sliderSettings = { // Comment on 6.05.20 by BG : renderCommitmentBox commented for now, will be reused with #974 -function renderPlasticTypes(plasticTypes: Array) { - function renderIcon(type: string) { +const renderPlasticTypes = (plasticTypes: Array) => { + const renderIcon = (type: string) => { switch (type) { case 'hdpe': return @@ -191,35 +191,31 @@ function renderPlasticTypes(plasticTypes: Array) { ) } -function renderOpeningHours(openingHours: Array) { - return ( -
-

We're open on:

- {openingHours.map((openingObj) => { - return ( - - {openingObj.day}: {openingObj.openFrom} - {openingObj.openTo} - - ) - })} -
- ) -} - -function renderMachineBuilderXp(machineBuilderXp: Array) { - return ( - <> -

We offer the following services:

- {machineBuilderXp.map((machineExperience, index) => { - return ( - - {machineExperience} - - ) - })} - - ) -} +const renderOpeningHours = (openingHours: Array) => ( +
+

We're open on:

+ {openingHours.map((openingObj) => { + return ( + + {openingObj.day}: {openingObj.openFrom} - {openingObj.openTo} + + ) + })} +
+) + +const renderMachineBuilderXp = (machineBuilderXp: Array) => ( + <> +

We offer the following services:

+ {machineBuilderXp.map((machineExperience, index) => { + return ( + + {machineExperience} + + ) + })} + +) export const SpaceProfile = ({ user }: IProps) => { let coverImage = [ diff --git a/src/pages/User/workspace/Workspace.tsx b/src/pages/User/workspace/Workspace.tsx index 3baa677e1f..93e2a623dd 100644 --- a/src/pages/User/workspace/Workspace.tsx +++ b/src/pages/User/workspace/Workspace.tsx @@ -13,7 +13,7 @@ import MemberBadge from 'src/assets/images/badges/pt-member.svg' import type { PlatformTheme } from 'src/themes/types' -function findWordspaceHighlight(workspaceType?: string): string { +const findWordspaceHighlight = (workspaceType?: string): string => { switch (workspaceType) { case ProfileType.WORKSPACE: return WorkspaceHighlight @@ -30,10 +30,10 @@ function findWordspaceHighlight(workspaceType?: string): string { } } -function findWorkspaceBadgeNullable( +const findWorkspaceBadgeNullable = ( workspaceType?: string, useCleanImage?: boolean, -): string | null { +): string | null => { if (!workspaceType) { return null } @@ -53,12 +53,12 @@ function findWorkspaceBadgeNullable( return foundProfileTypeObj.imageSrc || null } -function findWorkspaceBadge( +const findWorkspaceBadge = ( workspaceType?: string, ifCleanImage?: boolean, verifiedUser?: boolean, currentTheme?: PlatformTheme, -): string { +): string => { if (!workspaceType) { return MemberBadge } diff --git a/src/pages/common/DevSiteHeader/DevSiteHeader.tsx b/src/pages/common/DevSiteHeader/DevSiteHeader.tsx index e65081c50d..113f4558fc 100644 --- a/src/pages/common/DevSiteHeader/DevSiteHeader.tsx +++ b/src/pages/common/DevSiteHeader/DevSiteHeader.tsx @@ -88,12 +88,9 @@ const DevSiteHeader = observer(() => { ) }) -function showDevSiteHeader() { - return ( - devSites.some((s) => s.value === SITE) || - window.location?.hostname === 'localhost' - ) -} +const showDevSiteHeader = () => + devSites.some((s) => s.value === SITE) || + window.location?.hostname === 'localhost' const availableThemes = [ { value: 'precious-plastic', label: 'Precious Plastic' }, diff --git a/src/pages/common/Header/Menu/Notifications/NotificationsIcon.tsx b/src/pages/common/Header/Menu/Notifications/NotificationsIcon.tsx index a258b05f68..de4aeae05f 100644 --- a/src/pages/common/Header/Menu/Notifications/NotificationsIcon.tsx +++ b/src/pages/common/Header/Menu/Notifications/NotificationsIcon.tsx @@ -12,32 +12,30 @@ const IconWrapper = styled(Flex)` cursor: pointer; ` -export function NotificationsIcon({ +export const NotificationsIcon = ({ onCLick, isMobileMenuActive, areThereNotifications, -}) { - return ( - <> - - - - - ) -} +}) => ( + <> + + + + +) diff --git a/src/pages/common/Header/getFormattedNotifications.tsx b/src/pages/common/Header/getFormattedNotifications.tsx index fa2a765423..b266f3d83d 100644 --- a/src/pages/common/Header/getFormattedNotifications.tsx +++ b/src/pages/common/Header/getFormattedNotifications.tsx @@ -3,7 +3,9 @@ import { InternalLink } from 'oa-components' import type { INotification } from 'src/models' import { Box } from 'theme-ui' -export function getFormattedNotificationMessage(notification: INotification) { +export const getFormattedNotificationMessage = ( + notification: INotification, +) => { // Some legacy notifications to not have trigger, workaround until data cleaned and caches updated const triggeredBy = notification.triggeredBy || { displayName: 'Anonymous', @@ -85,11 +87,10 @@ export function getFormattedNotificationMessage(notification: INotification) { } } -export function getFormattedNotifications( +export const getFormattedNotifications = ( notificationList: INotification[], -): UserNotificationList { - return notificationList.map((notification) => ({ +): UserNotificationList => + notificationList.map((notification) => ({ type: notification.type, children: getFormattedNotificationMessage(notification), })) -} diff --git a/src/serviceWorkerRegistration.ts b/src/serviceWorkerRegistration.ts index 5b48bab3a8..1b8fc74c3f 100644 --- a/src/serviceWorkerRegistration.ts +++ b/src/serviceWorkerRegistration.ts @@ -21,7 +21,7 @@ interface RegisterSWCallback { handleSWControlling: () => void } -export function register(callback: RegisterSWCallback) { +export const register = (callback: RegisterSWCallback) => { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. const publicUrl = new URL( @@ -55,7 +55,7 @@ export function register(callback: RegisterSWCallback) { * adapted from https://developers.google.com/web/tools/workbox/guides/advanced-recipes * alternate: https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68 */ -function registerValidSW(swUrl: string, callback: RegisterSWCallback) { +const registerValidSW = (swUrl: string, callback: RegisterSWCallback) => { const wb = new Workbox(swUrl) wb.addEventListener('waiting', () => { // only trigger controlling callback if previously waiting sw activated (i.e. not first ever load) @@ -67,7 +67,10 @@ function registerValidSW(swUrl: string, callback: RegisterSWCallback) { wb.register() } -function checkValidServiceWorker(swUrl: string, callback: RegisterSWCallback) { +const checkValidServiceWorker = ( + swUrl: string, + callback: RegisterSWCallback, +) => { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl, { headers: { 'Service-Worker': 'script' }, @@ -97,7 +100,7 @@ function checkValidServiceWorker(swUrl: string, callback: RegisterSWCallback) { }) } -export function unregister() { +export const unregister = () => { if ('serviceWorker' in navigator) { navigator.serviceWorker.ready .then((registration) => { diff --git a/src/stores/Howto/howto.store.test.ts b/src/stores/Howto/howto.store.test.ts index a30f4f02fb..665a1b22e4 100644 --- a/src/stores/Howto/howto.store.test.ts +++ b/src/stores/Howto/howto.store.test.ts @@ -6,7 +6,7 @@ import { FactoryUser } from 'src/test/factories/User' import type { RootStore } from '..' import { HowtoStore } from './howto.store' -async function factory(howtoOverloads: Partial = {}) { +const factory = async (howtoOverloads: Partial = {}) => { const store = new HowtoStore({} as RootStore) const howToItem = FactoryHowto(howtoOverloads) diff --git a/src/stores/Howto/howto.store.tsx b/src/stores/Howto/howto.store.tsx index 402032febc..8966598de1 100644 --- a/src/stores/Howto/howto.store.tsx +++ b/src/stores/Howto/howto.store.tsx @@ -588,13 +588,11 @@ interface IHowToUploadStatus { Complete: boolean } -function getInitialUploadStatus(): IHowToUploadStatus { - return { - Start: false, - Cover: false, - 'Step Images': false, - Files: false, - Database: false, - Complete: false, - } -} +const getInitialUploadStatus = (): IHowToUploadStatus => ({ + Start: false, + Cover: false, + 'Step Images': false, + Files: false, + Database: false, + Complete: false, +}) diff --git a/src/stores/Maps/filter.ts b/src/stores/Maps/filter.ts index 073cc1591e..0b6acfd032 100644 --- a/src/stores/Maps/filter.ts +++ b/src/stores/Maps/filter.ts @@ -2,10 +2,10 @@ import type { IMapPin } from 'src/models/maps.models' // filter pins to include matched pin type or subtype // excluding items which have been marked as deleted=true -export function filterMapPinsByType( +export const filterMapPinsByType = ( mapPins: IMapPin[], filters: Array, -) { +) => { const filterList = new Set(filters) let filteredPins = mapPins diff --git a/src/stores/Maps/generatePins.tsx b/src/stores/Maps/generatePins.tsx index 2db8a10a73..5e7b6a7cc7 100644 --- a/src/stores/Maps/generatePins.tsx +++ b/src/stores/Maps/generatePins.tsx @@ -18,11 +18,8 @@ const MOCK_DB_META = (id?: string) => { } // generate a random date between start and end -function randomDate(start: Date, end: Date) { - return new Date( - start.getTime() + Math.random() * (end.getTime() - start.getTime()), - ) -} +const randomDate = (start: Date, end: Date) => + new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())) export const generatePins = (count: number): Array => { const filters = MAP_GROUPINGS diff --git a/src/stores/Research/research.store.tsx b/src/stores/Research/research.store.tsx index 72c36cc9ce..93bfb0a49b 100644 --- a/src/stores/Research/research.store.tsx +++ b/src/stores/Research/research.store.tsx @@ -675,22 +675,18 @@ export interface IUpdateUploadStatus { Complete: boolean } -function getInitialUpdateUploadStatus(): IUpdateUploadStatus { - return { - Start: false, - Images: false, - Database: false, - Complete: false, - } -} - -function getInitialResearchUploadStatus(): IResearchUploadStatus { - return { - Start: false, - Database: false, - Complete: false, - } -} +const getInitialUpdateUploadStatus = (): IUpdateUploadStatus => ({ + Start: false, + Images: false, + Database: false, + Complete: false, +}) + +const getInitialResearchUploadStatus = (): IResearchUploadStatus => ({ + Start: false, + Database: false, + Complete: false, +}) /** * Export an empty context object to be shared with components diff --git a/src/stores/User/user.store.ts b/src/stores/User/user.store.ts index c371bb9839..852e7694ec 100644 --- a/src/stores/User/user.store.ts +++ b/src/stores/User/user.store.ts @@ -423,7 +423,7 @@ interface IUserUpdateStatus { Complete: boolean } -function getInitialUpdateStatus() { +const getInitialUpdateStatus = () => { const status: IUserUpdateStatus = { Start: false, Complete: false, diff --git a/src/stores/common/mentions/index.ts b/src/stores/common/mentions/index.ts index 5c1be45ab3..5a530cf9dd 100644 --- a/src/stores/common/mentions/index.ts +++ b/src/stores/common/mentions/index.ts @@ -16,13 +16,13 @@ import type { UserStore } from '../../User/user.store' * mentionedUsers: string[], * }> */ -export const changeMentionToUserReference = async function ( +export const changeMentionToUserReference = async ( text: string, userStore: UserStore, ): Promise<{ text: string mentionedUsers: string[] -}> { +}> => { const mentions = text.match(/\B@[​a-z0-9_-]+/g) const mentionedUsers = new Set() @@ -51,8 +51,7 @@ export const changeMentionToUserReference = async function ( return { text, mentionedUsers: Array.from(mentionedUsers) } } -export const changeUserReferenceToPlainText = function (text: string) { - return text +export const changeUserReferenceToPlainText = (text: string) => + text .replace(/@([A-Za-z0-9_-]+)/, '@​$1') .replace(/@@\{([A-Za-z0-9_-]+):([a-z0-9_-]+)}/g, '@$2') -} diff --git a/src/stores/storage.tsx b/src/stores/storage.tsx index 533974ef00..870be53ea6 100644 --- a/src/stores/storage.tsx +++ b/src/stores/storage.tsx @@ -38,7 +38,11 @@ export class Storage { Helper Methods /****************************************************************************** */ -function generateUploadedFileMeta(snapshotMeta, url: string, filetype: string) { +const generateUploadedFileMeta = ( + snapshotMeta, + url: string, + filetype: string, +) => { const fileInfo: IUploadedFileMeta = { downloadUrl: url, contentType: snapshotMeta.contentType, diff --git a/src/themes/common/button.ts b/src/themes/common/button.ts index 7d43c82f36..1ee2753de0 100644 --- a/src/themes/common/button.ts +++ b/src/themes/common/button.ts @@ -10,74 +10,72 @@ const BASE_BUTTON = { border: '2px solid', } -export function getButtons(colors) { - return { - primary: { - ...BASE_BUTTON, - color: colors.black, +export const getButtons = (colors) => ({ + primary: { + ...BASE_BUTTON, + color: colors.black, + bg: colors.yellow.base, + '&:hover': { + bg: colors.yellow.hover, + cursor: 'pointer', + }, + '&[disabled]': { + opacity: 0.5, + cursor: 'not-allowed', + }, + '&[disabled]:hover': { bg: colors.yellow.base, - '&:hover': { - bg: colors.yellow.hover, - cursor: 'pointer', - }, - '&[disabled]': { - opacity: 0.5, - cursor: 'not-allowed', - }, - '&[disabled]:hover': { - bg: colors.yellow.base, - }, }, - secondary: { - ...BASE_BUTTON, - border: '2px solid ' + colors.black, - color: colors.black, + }, + secondary: { + ...BASE_BUTTON, + border: '2px solid ' + colors.black, + color: colors.black, + bg: colors.softblue, + '&:hover': { + bg: colors.white, + cursor: 'pointer', + }, + '&[disabled]': { + opacity: 0.5, + }, + '&[disabled]:hover': { bg: colors.softblue, - '&:hover': { - bg: colors.white, - cursor: 'pointer', - }, - '&[disabled]': { - opacity: 0.5, - }, - '&[disabled]:hover': { - bg: colors.softblue, - }, }, - outline: { - ...BASE_BUTTON, - border: '2px solid ' + colors.black, - color: colors.black, - backgroundColor: 'transparent', - '&:hover': { - backgroundColor: colors.softblue, - cursor: 'pointer', - }, + }, + outline: { + ...BASE_BUTTON, + border: '2px solid ' + colors.black, + color: colors.black, + backgroundColor: 'transparent', + '&:hover': { + backgroundColor: colors.softblue, + cursor: 'pointer', + }, + }, + imageInput: { + border: '2px dashed #e0e0e0', + color: '#e0e0e0', + backgroundColor: 'transparent', + }, + subtle: { + ...BASE_BUTTON, + borderColor: colors.softblue, + color: colors.black, + bg: colors.softblue, + '&:hover': { + bg: colors.offwhite, + borderColor: colors.offwhite, + cursor: 'pointer', }, - imageInput: { - border: '2px dashed #e0e0e0', - color: '#e0e0e0', - backgroundColor: 'transparent', + '&[disabled]': { + opacity: 0.5, }, - subtle: { - ...BASE_BUTTON, - borderColor: colors.softblue, - color: colors.black, + '&[disabled]:hover': { bg: colors.softblue, - '&:hover': { - bg: colors.offwhite, - borderColor: colors.offwhite, - cursor: 'pointer', - }, - '&[disabled]': { - opacity: 0.5, - }, - '&[disabled]:hover': { - bg: colors.softblue, - }, }, - } -} + }, +}) export type ButtonVariants = | 'primary' diff --git a/src/utils/formatters.ts b/src/utils/formatters.ts index aa6cbb41c2..11e5f2a780 100644 --- a/src/utils/formatters.ts +++ b/src/utils/formatters.ts @@ -2,7 +2,10 @@ import { ensureExternalUrl } from './validators' // TODO - we might want to add more formatting for cases where, // e.g. only a username is given for a bazar link -export function formatLink(unformattedLinkString: string, linkType?: string) { +export const formatLink = ( + unformattedLinkString: string, + linkType?: string, +) => { const link = unformattedLinkString if (['forum', 'website', 'social media', 'bazar'].includes(linkType || '')) { diff --git a/src/utils/getLocationData.ts b/src/utils/getLocationData.ts index c24f4d8c60..205b35f7da 100644 --- a/src/utils/getLocationData.ts +++ b/src/utils/getLocationData.ts @@ -1,7 +1,7 @@ import type { ILatLng, ILocation } from 'src/models' /** Retrieve OSM data for a specific lat-lon */ -export async function getLocationData(latlng: ILatLng): Promise { +export const getLocationData = async (latlng: ILatLng): Promise => { const { lat, lng } = latlng const response = await ( await fetch( diff --git a/src/utils/getUserCountry.ts b/src/utils/getUserCountry.ts index 7e4834c836..88c0762a23 100644 --- a/src/utils/getUserCountry.ts +++ b/src/utils/getUserCountry.ts @@ -1,6 +1,6 @@ import type { IUser } from 'src/models/user.models' -export function getUserCountry(user: IUser) { +export const getUserCountry = (user: IUser) => { const userCountry = user.country?.toLowerCase() || user.location?.countryCode?.toLowerCase() || diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 6405f78482..c18a57fa38 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -159,7 +159,5 @@ interface IEditableDoc extends DBDoc { // Convert theme em string to px number export const emStringToPx = (width) => Number(width.replace('em', '')) * 16 -export function randomIntFromInterval(min, max) { - // min and max included - return Math.floor(Math.random() * (max - min + 1) + min) -} +export const randomIntFromInterval = (min, max) => + Math.floor(Math.random() * (max - min + 1) + min) diff --git a/src/utils/seo.tsx b/src/utils/seo.tsx index 8e30630e75..e0b7f66c2d 100644 --- a/src/utils/seo.tsx +++ b/src/utils/seo.tsx @@ -67,7 +67,7 @@ export const SeoTagsUpdateComponent = (update: Partial) => { * Load the default SEO tags for the site (as currently hardcoded into the public index.html file) * TODO - it would be better if these were linked to the active site/deployment/theme in some way */ -function getDefaultSEOTags(): ISEOMeta { +const getDefaultSEOTags = (): ISEOMeta => { const PUBLIC_URL = location.origin return { title: 'Community Platform', @@ -78,13 +78,13 @@ function getDefaultSEOTags(): ISEOMeta { } } -function setMetaName(name: IPlatformMetaName, value: string) { +const setMetaName = (name: IPlatformMetaName, value: string) => { const el = document.querySelector(`meta[name="${name}"]`) if (el) { el.setAttribute('content', value) } } -function setMetaProperty(property: IPlatformMetaProperty, value: string) { +const setMetaProperty = (property: IPlatformMetaProperty, value: string) => { const el = document.querySelector(`meta[property="${property}"]`) if (el) { el.setAttribute('content', value) diff --git a/yarn.lock b/yarn.lock index 8d100c58a9..114d4e41c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16631,6 +16631,15 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-prefer-arrow-functions@npm:^3.1.4": + version: 3.1.4 + resolution: "eslint-plugin-prefer-arrow-functions@npm:3.1.4" + peerDependencies: + eslint: ">=5.0.0" + checksum: 581f1be4ea056d70aad1866ee16a0def7ecece050e03ff3bc2a6695b8bdca3751d6360fcd0e4efccd0068a0e0557b7ab36586a301afa38957acc8c58d293560c + languageName: node + linkType: hard + "eslint-plugin-prettier@npm:^3.4.0": version: 3.4.1 resolution: "eslint-plugin-prettier@npm:3.4.1" @@ -25784,6 +25793,7 @@ __metadata: eslint-plugin-import: ^2.26.0 eslint-plugin-jest: ^27.2.1 eslint-plugin-mocha: ^10.1.0 + eslint-plugin-prefer-arrow-functions: ^3.1.4 eslint-plugin-prettier: ^3.4.0 eslint-plugin-sort-class-members: ^1.15.2 eslint-plugin-unicorn: ^36.0.0