From 5bc23dd15f80ad3d6b7685135c2034d1019db10b Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 13 May 2026 14:21:10 +0200 Subject: [PATCH] Enable eslint no-explicit-any Enables the eslint rule no-explicit-any --- eslint.config.js | 1 - src/components/configuration/Themes.tsx | 5 +- src/components/events/Events.tsx | 4 +- src/components/events/Series.tsx | 4 +- .../ModalTabsAndPages/DetailsMetadataTab.tsx | 10 ++-- .../EditScheduledEventsEditPage.tsx | 2 +- .../EventDetailsSchedulingTab.tsx | 4 +- .../EventDetailsWorkflowSchedulingTab.tsx | 2 +- .../modals/EditMetadataEventsModal.tsx | 3 +- .../events/partials/modals/EventDetails.tsx | 1 + .../partials/modals/EventDetailsModal.tsx | 1 + .../events/partials/modals/SeriesDetails.tsx | 1 + .../partials/modals/SeriesDetailsModal.tsx | 1 + .../partials/wizards/RenderWorkflowConfig.tsx | 4 +- src/components/recordings/Recordings.tsx | 9 ++-- src/components/shared/DateTimeCell.tsx | 4 +- src/components/shared/DropDown.tsx | 33 +++++++------ src/components/shared/Field.tsx | 2 +- src/components/shared/FilterCell.tsx | 2 +- src/components/shared/MultiValueCell.tsx | 4 +- src/components/shared/Table.tsx | 22 ++++----- src/components/shared/TableFilterProfiles.tsx | 4 +- src/components/shared/TableFilters.tsx | 5 +- src/components/shared/TablePage.tsx | 10 ++-- .../shared/TimeSeriesStatistics.tsx | 40 +++++++++------- .../modals/ResourceDetailsAccessPolicyTab.tsx | 5 +- src/components/shared/wizard/RenderField.tsx | 28 ++++++----- src/components/systems/Jobs.tsx | 5 +- src/components/systems/Servers.tsx | 5 +- src/components/systems/Services.tsx | 6 ++- src/components/users/Acls.tsx | 5 +- src/components/users/Groups.tsx | 5 +- src/components/users/Users.tsx | 5 +- src/slices/eventSlice.ts | 12 ++--- src/slices/seriesSlice.ts | 16 +++---- src/slices/tableSlice.ts | 2 + src/utils/componentStyles.ts | 21 ++++++--- src/utils/dateUtils.ts | 46 +++++++++---------- src/utils/utils.ts | 6 +++ src/utils/validate.ts | 9 ++-- 40 files changed, 200 insertions(+), 154 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 3df3c47f4d..181a15929e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -14,7 +14,6 @@ export default [ "indent": "off", "max-len": "off", "no-tabs": "off", - "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-floating-promises": "off", "@typescript-eslint/no-misused-promises": "off", }, diff --git a/src/components/configuration/Themes.tsx b/src/components/configuration/Themes.tsx index e9dfc07176..a206bb2c59 100644 --- a/src/components/configuration/Themes.tsx +++ b/src/components/configuration/Themes.tsx @@ -1,15 +1,16 @@ import { themesTemplateMap } from "../../configs/tableConfigs/themesTableMap"; import { getTotalThemes } from "../../selectors/themeSelectors"; import { loadThemesIntoTable } from "../../thunks/tableThunks"; -import { fetchThemes } from "../../slices/themeSlice"; +import { fetchThemes, ThemeDetailsType } from "../../slices/themeSlice"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of events */ const Themes = () => { return ( - resource={"themes"} fetchResource={fetchThemes} loadResourceIntoTable={loadThemesIntoTable} diff --git a/src/components/events/Events.tsx b/src/components/events/Events.tsx index 0ade511d14..ad48bdf926 100644 --- a/src/components/events/Events.tsx +++ b/src/components/events/Events.tsx @@ -21,6 +21,7 @@ import { availableHotkeys } from "../../configs/hotkeysConfig"; import { fetchAssetUploadOptions } from "../../thunks/assetsThunks"; import { useAppDispatch, useAppSelector } from "../../store"; import { + Event, fetchEventMetadata, fetchEvents, setShowActions, @@ -32,6 +33,7 @@ import TableActionDropdown from "../shared/TableActionDropdown"; import { fetchAclDefaults } from "../../slices/aclSlice"; import TablePage from "../shared/TablePage"; import SeriesDetailsModal from "./partials/modals/SeriesDetailsModal"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of events @@ -69,7 +71,7 @@ const Events = () => { return ( <> - resource={"events"} fetchResource={fetchEvents} loadResourceIntoTable={loadEventsIntoTable} diff --git a/src/components/events/Series.tsx b/src/components/events/Series.tsx index 819f8c7c2a..e4107e1469 100644 --- a/src/components/events/Series.tsx +++ b/src/components/events/Series.tsx @@ -12,6 +12,7 @@ import { fetchSeries, fetchSeriesMetadata, fetchSeriesThemes, + Series as SeriesRow, showActionsSeries, } from "../../slices/seriesSlice"; import { fetchSeriesDetailsTobiraNew } from "../../slices/seriesSlice"; @@ -22,6 +23,7 @@ import TableActionDropdown from "../shared/TableActionDropdown"; import { fetchAclDefaults } from "../../slices/aclSlice"; import TablePage from "../shared/TablePage"; import SeriesDetailsModal from "./partials/modals/SeriesDetailsModal"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of series @@ -54,7 +56,7 @@ const Series = () => { return ( <> - resource={"series"} fetchResource={fetchSeries} loadResourceIntoTable={loadSeriesIntoTable} diff --git a/src/components/events/partials/ModalTabsAndPages/DetailsMetadataTab.tsx b/src/components/events/partials/ModalTabsAndPages/DetailsMetadataTab.tsx index 58f1eba094..0ec5cc2409 100644 --- a/src/components/events/partials/ModalTabsAndPages/DetailsMetadataTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/DetailsMetadataTab.tsx @@ -40,9 +40,9 @@ const DetailsMetadataTab = ({ metadata: MetadataCatalog[], updateResource: AsyncThunk // (id: string, values: { [key: string]: any }, catalog: MetadataCatalog) => void, + }, object> // (id: string, values: { [key: string]: any }, catalog: MetadataCatalog) => void, editAccessRole: string, formikRef?: React.RefObject | null> header?: ParseKeys @@ -52,7 +52,7 @@ const DetailsMetadataTab = ({ const user = useAppSelector(state => getUserInformation(state)); - const handleSubmit = (values: { [key: string]: any }, catalog: MetadataCatalog) => { + const handleSubmit = (values: InitialValues, catalog: MetadataCatalog) => { dispatch(updateResource({ id: resourceId, values, catalog })) .unwrap() .then(() => { @@ -75,7 +75,7 @@ const DetailsMetadataTab = ({ // set current values of metadata fields as initial values const getInitialValues = (metadataCatalog: MetadataCatalog) => { - const initialValues: { [key: string]: any } = {}; + const initialValues: { [key: string]: MetadataCatalog["fields"][0]["value"] } = {}; // Transform metadata fields and their values provided by backend (saved in redux) metadataCatalog.fields.forEach(field => { @@ -85,7 +85,7 @@ const DetailsMetadataTab = ({ return initialValues; }; - const checkValidity = (formik: FormikProps) => { + const checkValidity = (formik: FormikProps) => { if (formik.dirty && formik.isValid && hasAccess(editAccessRole, user)) { // check if user provided values differ from initial ones return !_.isEqual(formik.values, formik.initialValues); diff --git a/src/components/events/partials/ModalTabsAndPages/EditScheduledEventsEditPage.tsx b/src/components/events/partials/ModalTabsAndPages/EditScheduledEventsEditPage.tsx index f81b06c9a5..baa4fd57ee 100644 --- a/src/components/events/partials/ModalTabsAndPages/EditScheduledEventsEditPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/EditScheduledEventsEditPage.tsx @@ -69,7 +69,7 @@ const EditScheduledEventsEditPage = ({ dispatch(fetchScheduling({ events: formik.values.events, fetchNewScheduling: fetchEventInfos, - setFormikValue: formik.setFieldValue, + setFieldValue: formik.setFieldValue, })); // eslint-disable-next-line react-hooks/exhaustive-deps }, [formik.values.events]); diff --git a/src/components/events/partials/ModalTabsAndPages/EventDetailsSchedulingTab.tsx b/src/components/events/partials/ModalTabsAndPages/EventDetailsSchedulingTab.tsx index 005301990a..755997e381 100644 --- a/src/components/events/partials/ModalTabsAndPages/EventDetailsSchedulingTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/EventDetailsSchedulingTab.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; import _ from "lodash"; import DatePicker from "react-datepicker"; -import { Formik, FormikErrors, FormikProps } from "formik"; +import { Formik, FormikHelpers, FormikProps } from "formik"; import Notifications from "../../../shared/Notifications"; import { getSchedulingConflicts, @@ -142,7 +142,7 @@ const EventDetailsSchedulingTab = ({ }; // changes the inputs in the formik - const changeInputs = (deviceId: Recording["id"], setFieldValue: (field: string, value: any) => Promise>) => { + const changeInputs = (deviceId: Recording["id"], setFieldValue: FormikHelpers["setFieldValue"]) => { setFieldValue("captureAgent", deviceId); setFieldValue("inputs", []); }; diff --git a/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx b/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx index 20dad74e06..232b01c84e 100644 --- a/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx @@ -25,7 +25,7 @@ import ModalContent from "../../../shared/modals/ModalContent"; type InitialValues = { workflowDefinition: string; configuration: { - [key: string]: any; + [key: string]: unknown; } | undefined; } diff --git a/src/components/events/partials/modals/EditMetadataEventsModal.tsx b/src/components/events/partials/modals/EditMetadataEventsModal.tsx index 9bb9773a19..9b14fdf3be 100644 --- a/src/components/events/partials/modals/EditMetadataEventsModal.tsx +++ b/src/components/events/partials/modals/EditMetadataEventsModal.tsx @@ -12,6 +12,7 @@ import RenderMultiField from "../../../shared/wizard/RenderMultiField"; import { getUserInformation } from "../../../../selectors/userInfoSelectors"; import { useAppDispatch, useAppSelector } from "../../../../store"; import { + MetadataField, MetadataFieldSelected, postEditMetadata, updateBulkMetadata, @@ -83,7 +84,7 @@ const EditMetadataEventsModal = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const handleSubmit = (values: { [key: string]: unknown }) => { + const handleSubmit = (values: { [key: string]: MetadataField["value"] }) => { const response = dispatch(updateBulkMetadata({ metadataFields, values })); console.info(response); close(); diff --git a/src/components/events/partials/modals/EventDetails.tsx b/src/components/events/partials/modals/EventDetails.tsx index 92b3da457c..f10ce54f61 100644 --- a/src/components/events/partials/modals/EventDetails.tsx +++ b/src/components/events/partials/modals/EventDetails.tsx @@ -80,6 +80,7 @@ const EventDetails = ({ eventId: string, policyChanged: boolean, setPolicyChanged: (value: boolean) => void, + // eslint-disable-next-line @typescript-eslint/no-explicit-any formikRef: React.RefObject | null> }) => { const { t } = useTranslation(); diff --git a/src/components/events/partials/modals/EventDetailsModal.tsx b/src/components/events/partials/modals/EventDetailsModal.tsx index 314ca8291a..a473e2c8f5 100644 --- a/src/components/events/partials/modals/EventDetailsModal.tsx +++ b/src/components/events/partials/modals/EventDetailsModal.tsx @@ -18,6 +18,7 @@ const EventDetailsModal = () => { // tracks, whether the policies are different to the initial value const [policyChanged, setPolicyChanged] = useState(false); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const formikRef = useRef>(null); const displayEventDetailsModal = useAppSelector(state => showModal(state)); diff --git a/src/components/events/partials/modals/SeriesDetails.tsx b/src/components/events/partials/modals/SeriesDetails.tsx index 323c430f93..e438b10eef 100644 --- a/src/components/events/partials/modals/SeriesDetails.tsx +++ b/src/components/events/partials/modals/SeriesDetails.tsx @@ -51,6 +51,7 @@ const SeriesDetails = ({ seriesId: string policyChanged: boolean setPolicyChanged: (policyChanged: boolean) => void + // eslint-disable-next-line @typescript-eslint/no-explicit-any formikRef: React.RefObject | null> }) => { const { t } = useTranslation(); diff --git a/src/components/events/partials/modals/SeriesDetailsModal.tsx b/src/components/events/partials/modals/SeriesDetailsModal.tsx index 91a6e011a7..771aa41890 100644 --- a/src/components/events/partials/modals/SeriesDetailsModal.tsx +++ b/src/components/events/partials/modals/SeriesDetailsModal.tsx @@ -18,6 +18,7 @@ const SeriesDetailsModal = () => { // tracks, whether the policies are different to the initial value const [policyChanged, setPolicyChanged] = useState(false); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const formikRef = useRef>(null); const displaySeriesDetailsModal = useAppSelector(state => showModal(state)); diff --git a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx index cbff50f703..3fc06d8331 100644 --- a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx +++ b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx @@ -13,7 +13,7 @@ import { FieldSetField } from "../../../../slices/workflowSlice"; * wizard chosen via dropdown. */ interface RequiredFormProps { - configuration?: { [key: string]: any } + configuration?: { [key: string]: unknown } } const RenderWorkflowConfig = ({ @@ -154,7 +154,7 @@ const RenderField = ({ }: { field: FieldSetField, formik: FormikProps, - validate?: (value: any) => string | undefined, + validate?: (value: string) => string | undefined, }) => { // id used for Field and label const uuid = uuidv4(); diff --git a/src/components/recordings/Recordings.tsx b/src/components/recordings/Recordings.tsx index d95e70c27d..fd5e13dc1a 100644 --- a/src/components/recordings/Recordings.tsx +++ b/src/components/recordings/Recordings.tsx @@ -1,18 +1,19 @@ import { recordingsTemplateMap } from "../../configs/tableConfigs/recordingsTableMap"; import { getTotalRecordings } from "../../selectors/recordingSelectors"; import { loadRecordingsIntoTable } from "../../thunks/tableThunks"; -import { fetchRecordings } from "../../slices/recordingSlice"; -import { AsyncThunk } from "@reduxjs/toolkit"; +import { fetchRecordings, Recording } from "../../slices/recordingSlice"; import TablePage from "../shared/TablePage"; +import { GenericAsyncThunk } from "../../utils/utils"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of recordings */ const Recordings = () => { return ( - resource={"recordings"} - fetchResource={fetchRecordings as AsyncThunk} + fetchResource={fetchRecordings as GenericAsyncThunk} loadResourceIntoTable={loadRecordingsIntoTable} getTotalResources={getTotalRecordings} navBarLinks={[ diff --git a/src/components/shared/DateTimeCell.tsx b/src/components/shared/DateTimeCell.tsx index 40b4df03d0..b5aa4dce02 100644 --- a/src/components/shared/DateTimeCell.tsx +++ b/src/components/shared/DateTimeCell.tsx @@ -4,9 +4,9 @@ import { getFilters } from "../../selectors/tableFilterSelectors"; import { AppThunk, useAppDispatch, useAppSelector } from "../../store"; import { renderValidDate } from "../../utils/dateUtils"; import { ParseKeys } from "i18next"; -import { AsyncThunk } from "@reduxjs/toolkit"; import { Resource } from "../../slices/tableSlice"; import ButtonLikeAnchor from "./ButtonLikeAnchor"; +import { GenericAsyncThunk } from "../../utils/utils"; /** * This component renders the start date cells of events in the table view @@ -22,7 +22,7 @@ const DateTimeCell = ({ resource: Resource date: string filterName: string - fetchResource: AsyncThunk + fetchResource: GenericAsyncThunk loadResourceIntoTable: () => AppThunk tooltipText?: ParseKeys }) => { diff --git a/src/components/shared/DropDown.tsx b/src/components/shared/DropDown.tsx index 7e86dae56d..11229cd384 100644 --- a/src/components/shared/DropDown.tsx +++ b/src/components/shared/DropDown.tsx @@ -4,15 +4,15 @@ import { dropDownSpacingTheme, dropDownStyle, } from "../../utils/componentStyles"; -import { GroupBase, MenuListProps, Props, SelectInstance } from "react-select"; +import { GroupBase, MenuListProps, SelectInstance } from "react-select"; import { ParseKeys } from "i18next"; import { FixedSizeList, ListChildComponentProps } from "react-window"; -import AsyncSelect from "react-select/async"; +import AsyncSelect, { AsyncProps } from "react-select/async"; import AsyncCreatableSelect from "react-select/async-creatable"; -export type DropDownOption = { +export type DropDownOption = { label: string, - value: string | number, + value: T | "", order?: number } @@ -20,7 +20,7 @@ export type DropDownOption = { * This component renders a dropdown menu using react-select */ const DropDown = ({ - ref = React.createRef>>(), + ref = React.createRef, boolean, GroupBase>>>(), value, text, options, @@ -41,10 +41,10 @@ const DropDown = ({ customCSS, fetchOptions, }: { - ref?: React.RefObject> | null> + ref?: React.RefObject, boolean, GroupBase>> | null> value: T text: string, - options?: DropDownOption[], + options?: DropDownOption[], required: boolean, handleChange: (option: {value: T, label: string} | null) => void placeholder: string @@ -65,13 +65,13 @@ const DropDown = ({ optionPaddingTop?: number, optionLineHeight?: string }, - fetchOptions?: (inputValue: string) => Promise<{ label: string, value: string }[]> + fetchOptions?: (inputValue: string) => Promise[]> }) => { const { t } = useTranslation(); const selectRef = ref; - const style = dropDownStyle(customCSS ?? {}); + const style = dropDownStyle(customCSS ?? {}); useEffect(() => { // Ensure menu has focus when opened programmatically @@ -87,7 +87,7 @@ const DropDown = ({ }; const formatOptions = ( - unformattedOptions: DropDownOption[], + unformattedOptions: DropDownOption[], required: boolean, ) => { // Translate @@ -130,7 +130,7 @@ const DropDown = ({ /** * Custom component for list virtualization */ - const MenuList = (props: MenuListProps) => { + const MenuList = (props: MenuListProps, false>) => { const { children, maxHeight } = props; console.log("Menu List render"); @@ -159,7 +159,7 @@ const DropDown = ({ return []; }; - const loadOptionsAsync = (inputValue: string, callback: (options: DropDownOption[]) => void) => { + const loadOptionsAsync = (inputValue: string, callback: (options: DropDownOption[]) => void) => { setTimeout(async () => { callback(formatOptions( fetchOptions ? await fetchOptions(inputValue) : filterOptions(inputValue), @@ -170,13 +170,17 @@ const DropDown = ({ const loadOptions = ( _inputValue: string, - callback: (options: DropDownOption[]) => void, + callback: (options: DropDownOption[]) => void, ) => { callback(formatOptions(filterOptions(_inputValue), required)); }; - const commonProps: Props = { + const commonProps: AsyncProps< + DropDownOption, + boolean, + GroupBase> + > = { tabIndex: tabIndex, theme: theme => (dropDownSpacingTheme(theme)), styles: style, @@ -200,7 +204,6 @@ const DropDown = ({ isDisabled: disabled, openMenuOnFocus: openMenuOnFocus, menuPlacement: menuPlacement ?? "auto", - // @ts-expect-error: React-Select typing does not account for the typing of option it itself requires components: { MenuList }, }; diff --git a/src/components/shared/Field.tsx b/src/components/shared/Field.tsx index fccf3e1375..384918cb77 100644 --- a/src/components/shared/Field.tsx +++ b/src/components/shared/Field.tsx @@ -4,7 +4,7 @@ import { FieldAttributes } from "formik/dist/Field"; /** * Wrapper for the Formik Fields */ -export const Field = (props: FieldAttributes) => { +export const Field = (props: FieldAttributes) => { return ( ({ children: ReactNode cellTooltipText?: ParseKeys }[] - fetchResource: AsyncThunk + fetchResource: AsyncThunk loadResourceIntoTable: () => AppThunk, }) => { const dispatch = useAppDispatch(); diff --git a/src/components/shared/MultiValueCell.tsx b/src/components/shared/MultiValueCell.tsx index 3783d30ec1..267d2dd149 100644 --- a/src/components/shared/MultiValueCell.tsx +++ b/src/components/shared/MultiValueCell.tsx @@ -1,10 +1,10 @@ import { getFilters } from "../../selectors/tableFilterSelectors"; import { editFilterValue } from "../../slices/tableFilterSlice"; import { AppThunk, useAppDispatch, useAppSelector } from "../../store"; -import { AsyncThunk } from "@reduxjs/toolkit"; import { ParseKeys } from "i18next"; import { Resource } from "../../slices/tableSlice"; import ButtonLikeAnchor from "./ButtonLikeAnchor"; +import { GenericAsyncThunk } from "../../utils/utils"; /** * This component renders the presenters cells of events in the table view @@ -20,7 +20,7 @@ const MultiValueCell = ({ resource: Resource values: string[] filterName: string - fetchResource: AsyncThunk + fetchResource: GenericAsyncThunk loadResourceIntoTable: () => AppThunk tooltipText?: ParseKeys, }) => { diff --git a/src/components/shared/Table.tsx b/src/components/shared/Table.tsx index 8648c643e4..84cb817859 100644 --- a/src/components/shared/Table.tsx +++ b/src/components/shared/Table.tsx @@ -42,25 +42,25 @@ import ButtonLikeAnchor from "./ButtonLikeAnchor"; import { ModalHandle } from "./modals/Modal"; import { ParseKeys } from "i18next"; import { LuChevronDown, LuChevronLeft, LuChevronRight, LuChevronUp } from "react-icons/lu"; -import { AsyncThunk } from "@reduxjs/toolkit"; import { useLocation } from "react-router"; +import { GenericAsyncThunk } from "../../utils/utils"; const containerPageSize = React.createRef(); -export type TemplateMap = { - [key: string]: ({ row }: { row: any }) => JSX.Element | JSX.Element[] +export type TemplateMap = { + [key: string]: ({ row }: { row: T }) => JSX.Element | JSX.Element[] } /** * This component renders the table in the table views of resources */ -const Table = ({ +const Table = ({ templateMap, fetchResource, loadResourceIntoTable, }: { - templateMap: TemplateMap - fetchResource: AsyncThunk, + templateMap: TemplateMap + fetchResource: GenericAsyncThunk, loadResourceIntoTable: () => AppThunk, }) => { const { t } = useTranslation(); @@ -269,7 +269,7 @@ const TableHeadRows = ({ forceDeselectAll }: { forceDeselectAll: () => unknown } ); }; -const TableBody = ({ templateMap }: { templateMap: TemplateMap }) => { +const TableBody = ({ templateMap }: { templateMap: TemplateMap }) => { const { t } = useTranslation(); const columnCount = useAppSelector(state => getTableColumns(state).length); @@ -300,7 +300,7 @@ const TableBody = ({ templateMap }: { templateMap: TemplateMap }) => { ); }; -const TableRows = ({ templateMap }: { templateMap: TemplateMap }) => { +const TableRows = ({ templateMap }: { templateMap: TemplateMap }) => { const rowKeys = useAppSelector(selectRowIds); return ( @@ -316,11 +316,11 @@ const TableRows = ({ templateMap }: { templateMap: TemplateMap }) => { ); }; -const TableRow = ({ rowKey, templateMap }: { rowKey: string, templateMap: TemplateMap }) => { +const TableRow = ({ rowKey, templateMap }: { rowKey: string, templateMap: TemplateMap }) => { const { t } = useTranslation(); const dispatch = useAppDispatch(); - const row = useAppSelector(state => selectRowById(state, rowKey)); + const row = useAppSelector(state => selectRowById(state, rowKey)) as T; const columns = useAppSelector(state => getTableColumns(state)); const multiSelect = useAppSelector(state => getMultiSelect(state)); @@ -386,7 +386,7 @@ const TableRow = ({ rowKey, templateMap }: { rowKey: string, templateMap: Templa }; // Apply a column template and render corresponding components -const ColumnTemplate = ({ row, column, templateMap }: {row: Row, column: TableColumn, templateMap: TemplateMap}) => { +const ColumnTemplate = ({ row, column, templateMap }: {row: T, column: TableColumn, templateMap: TemplateMap}) => { if (!column.template) { return <>; } diff --git a/src/components/shared/TableFilterProfiles.tsx b/src/components/shared/TableFilterProfiles.tsx index 592cc2b04f..298904a002 100644 --- a/src/components/shared/TableFilterProfiles.tsx +++ b/src/components/shared/TableFilterProfiles.tsx @@ -15,11 +15,11 @@ import { FilterData, loadFilterProfile } from "../../slices/tableFilterSlice"; import { AppThunk, useAppDispatch, useAppSelector } from "../../store"; import { useHotkeys } from "react-hotkeys-hook"; import { availableHotkeys } from "../../configs/hotkeysConfig"; -import { AsyncThunk } from "@reduxjs/toolkit"; import ButtonLikeAnchor from "./ButtonLikeAnchor"; import { ParseKeys } from "i18next"; import { Resource } from "../../slices/tableSlice"; import { LuSettings, LuX } from "react-icons/lu"; +import { GenericAsyncThunk } from "../../utils/utils"; /** * This component renders the table filter profiles in the upper right corner when clicked on settings icon of the @@ -34,7 +34,7 @@ const TableFiltersProfiles = ({ }: { showFilterSettings: boolean, setFilterSettings: (_: boolean) => void, - loadResource: AsyncThunk, + loadResource: GenericAsyncThunk, loadResourceIntoTable: () => AppThunk, resource: Resource, }) => { diff --git a/src/components/shared/TableFilters.tsx b/src/components/shared/TableFilters.tsx index a9473d1f42..548fe3249e 100644 --- a/src/components/shared/TableFilters.tsx +++ b/src/components/shared/TableFilters.tsx @@ -22,9 +22,8 @@ import { useHotkeys } from "react-hotkeys-hook"; import moment from "moment"; import { AppThunk, useAppDispatch, useAppSelector } from "../../store"; import { renderValidDate } from "../../utils/dateUtils"; -import { getCurrentLanguageInformation } from "../../utils/utils"; +import { GenericAsyncThunk, getCurrentLanguageInformation } from "../../utils/utils"; import DropDown from "./DropDown"; -import { AsyncThunk } from "@reduxjs/toolkit"; import ButtonLikeAnchor from "./ButtonLikeAnchor"; import { ParseKeys } from "i18next"; import SearchContainer from "./SearchContainer"; @@ -41,7 +40,7 @@ const TableFilters = ({ loadResourceIntoTable, resource, }: { - loadResource: AsyncThunk, + loadResource: GenericAsyncThunk, loadResourceIntoTable: () => AppThunk, resource: Resource, }) => { diff --git a/src/components/shared/TablePage.tsx b/src/components/shared/TablePage.tsx index 6ef6259489..57ad2c5afa 100644 --- a/src/components/shared/TablePage.tsx +++ b/src/components/shared/TablePage.tsx @@ -5,15 +5,15 @@ import Table, { TemplateMap } from "../shared/Table"; import Notifications from "../shared/Notifications"; import { CreateType, NavBarLink } from "../NavBar"; import { AppThunk, RootState, useAppSelector } from "../../store"; -import { Resource } from "../../slices/tableSlice"; -import { AsyncThunk } from "@reduxjs/toolkit"; +import { Resource, Row } from "../../slices/tableSlice"; import { ParseKeys } from "i18next"; import MainPage from "./MainPage"; +import { GenericAsyncThunk } from "../../utils/utils"; /** * This component renders a generic page with a table */ -const TablePage = ({ +const TablePage = ({ resource, fetchResource, loadResourceIntoTable, @@ -26,14 +26,14 @@ const TablePage = ({ children, }: { resource: Resource - fetchResource: AsyncThunk, + fetchResource: GenericAsyncThunk, loadResourceIntoTable: () => AppThunk, getTotalResources: (state: RootState) => number, navBarLinks: NavBarLink[] navBarCreate?: CreateType navBarChildren?: ReactNode caption: ParseKeys - templateMap: TemplateMap + templateMap: TemplateMap children?: ReactNode }) => { const { t } = useTranslation(); diff --git a/src/components/shared/TimeSeriesStatistics.tsx b/src/components/shared/TimeSeriesStatistics.tsx index 1fa79e6135..b8f74c596d 100644 --- a/src/components/shared/TimeSeriesStatistics.tsx +++ b/src/components/shared/TimeSeriesStatistics.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import moment from "moment"; import { getCurrentLanguageInformation } from "../../utils/utils"; import DatePicker from "react-datepicker"; -import { Formik, FormikErrors } from "formik"; +import { Formik, FormikHelpers } from "formik"; import { Field } from "./Field"; import BarChart from "./BarChart"; import { @@ -20,6 +20,12 @@ import { DataResolution, Statistics, TimeMode } from "../../slices/statisticsSli import { ParseKeys } from "i18next"; import { LuChevronLeft, LuChevronRight, LuDownload } from "react-icons/lu"; +type InitialValues = { + timeMode: TimeMode, + dataResolution: DataResolution, + fromDate: string, + toDate: string, +} /** * This component visualizes statistics with data of type time series @@ -49,7 +55,7 @@ const TimeSeriesStatistics = ({ timeMode: TimeMode, dataResolution: DataResolution, statDescription: string, - onChange: AsyncThunk, + onChange: AsyncThunk, exportUrl: string, exportFileName: (statsTitle: string) => string, totalValue: number, @@ -81,7 +87,7 @@ const TimeSeriesStatistics = ({ // change formik values and get new statistic values from API const change = ( - setFormikValue: (field: string, value: any) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], timeMode: TimeMode, from: string, to: string, @@ -92,9 +98,9 @@ const TimeSeriesStatistics = ({ to = moment(from).clone().endOf(timeMode).format("YYYY-MM-DD"); setStartDatepicker(new Date(from)); setEndDatepicker(new Date(to)); - setFormikValue("fromDate", from); - setFormikValue("toDate", to); - setFormikValue("dataResolution", fixedDataResolutions(timeMode)); + setFieldValue("fromDate", from); + setFieldValue("toDate", to); + setFieldValue("dataResolution", fixedDataResolutions(timeMode)); dataResolution = fixedStatisticDataResolutions(timeMode); } dispatch(onChange({ id: resourceId, providerId, from, to, dataResolution, timeMode })); @@ -103,25 +109,25 @@ const TimeSeriesStatistics = ({ // change time mode in formik and get new values from API const changeTimeMode = ( newTimeMode: TimeMode, - setFormikValue: (field: string, value: any) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], from: string, to: string, dataResolution: DataResolution, ) => { - setFormikValue("timeMode", newTimeMode); - change(setFormikValue, newTimeMode, from, to, dataResolution); + setFieldValue("timeMode", newTimeMode); + change(setFieldValue, newTimeMode, from, to, dataResolution); }; // change custom time granularity in formik and get new values from API const changeGranularity = ( granularity: DataResolution, - setFormikValue: (field: string, value: any) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], timeMode: TimeMode, from: string, to: string, ) => { - setFormikValue("dataResolution", granularity); - change(setFormikValue, timeMode, from, to, granularity); + setFieldValue("dataResolution", granularity); + change(setFieldValue, timeMode, from, to, granularity); }; // format selected time to display as name of timeframe @@ -136,7 +142,7 @@ const TimeSeriesStatistics = ({ // change to and from dates in formik to previous timeframe and get new values from API const selectPrevious = ( - setFormikValue: (field: string, value: any) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], from: string, timeMode: TimeMode, dataResolution: DataResolution, @@ -146,12 +152,12 @@ const TimeSeriesStatistics = ({ .subtract(1, timeMode + "s" as moment.unitOfTime.DurationConstructor) .format("YYYY-MM-DD"); const to = newFrom; - change(setFormikValue, timeMode, newFrom, to, dataResolution); + change(setFieldValue, timeMode, newFrom, to, dataResolution); }; // change to and from dates in formik to next timeframe and get new values from API const selectNext = ( - setFormikValue: (field: string, value: any) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], from: string, timeMode: TimeMode, dataResolution: DataResolution, @@ -161,12 +167,12 @@ const TimeSeriesStatistics = ({ .add(1, timeMode + "s" as moment.unitOfTime.DurationConstructor) .format("YYYY-MM-DD"); const to = newFrom; - change(setFormikValue, timeMode, newFrom, to, dataResolution); + change(setFieldValue, timeMode, newFrom, to, dataResolution); }; return ( /* Initialize form */ - enableReinitialize initialValues={{ timeMode: timeMode, diff --git a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx index a331347696..3d616f1bd8 100644 --- a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx +++ b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx @@ -69,9 +69,10 @@ const ResourceDetailsAccessPolicyTab = ({ header: ParseKeys, policies: TransformedAcl[], policyTemplateId: number, - fetchHasActiveTransactions?: AsyncThunk<{ active: boolean }, string, any> + fetchHasActiveTransactions?: AsyncThunk<{ active: boolean }, string, object> + // eslint-disable-next-line @typescript-eslint/no-explicit-any fetchAccessPolicies: AsyncThunk, - saveNewAccessPolicies: AsyncThunk + saveNewAccessPolicies: AsyncThunk descriptionText: ParseKeys, buttonText: ParseKeys, policyTableHeaderText: ParseKeys, diff --git a/src/components/shared/wizard/RenderField.tsx b/src/components/shared/wizard/RenderField.tsx index 3e031d86af..ee82671612 100644 --- a/src/components/shared/wizard/RenderField.tsx +++ b/src/components/shared/wizard/RenderField.tsx @@ -4,7 +4,7 @@ import DatePicker from "react-datepicker"; import cn from "classnames"; import { getMetadataCollectionFieldName, transformListProvider } from "../../../utils/resourceUtils"; import { getCurrentLanguageInformation } from "../../../utils/utils"; -import DropDown from "../DropDown"; +import DropDown, { DropDownOption } from "../DropDown"; import { parseISO } from "date-fns"; import { FieldProps } from "formik"; import { MetadataField } from "../../../slices/eventSlice"; @@ -32,6 +32,7 @@ const RenderField = ({ const { t } = useTranslation(); // TODO: Figure out how to type a ref that could have multiple types + // eslint-disable-next-line @typescript-eslint/no-explicit-any const editableRef = useRef(null); const [focused, setFocused] = useState(false); const onFocus = () => setFocused(true); @@ -197,17 +198,17 @@ const EditableDateValue = ({ }; // renders editable field for selecting value via dropdown -type EditableSingleSelectProps = ({ - field: FieldProps["field"] +type EditableSingleSelectProps = ({ + field: FieldProps["field"] metadataField: MetadataField text: string form: FieldProps["form"] isFirstField?: boolean, focused: boolean, setFocused: (open: boolean) => void - ref: React.RefObject>> + ref: React.RefObject, boolean, GroupBase>> | null> }) -const EditableSingleSelect = (props: EditableSingleSelectProps) => { +const EditableSingleSelect = (props: EditableSingleSelectProps) => { const { field, metadataField, @@ -341,7 +342,7 @@ const EditableSingleSelectSeries = ({ focused, setFocused, ref, -}: EditableSingleSelectProps) => { +}: EditableSingleSelectProps) => { const [label, setLabel] = useState(""); useEffect(() => { @@ -381,7 +382,7 @@ const EditableSingleSelectSeries = ({ />; }; -const EditableSingleSelectDropDown = ({ +const EditableSingleSelectDropDown = ({ field, metadataField, text, @@ -392,16 +393,19 @@ const EditableSingleSelectDropDown = ({ focused, setFocused, ref, -}: EditableSingleSelectProps & Pick< - Parameters[0], - "options" | "fetchOptions" ->) => { +}: EditableSingleSelectProps & +{ options?: DropDownOption[]; + fetchOptions?: ( + inputValue: string + ) => Promise[]>; + }, +) => { const { t } = useTranslation(); return ( { return ( - resource={"jobs"} fetchResource={fetchJobs} loadResourceIntoTable={loadJobsIntoTable} diff --git a/src/components/systems/Servers.tsx b/src/components/systems/Servers.tsx index ad236feb17..81e65f9443 100644 --- a/src/components/systems/Servers.tsx +++ b/src/components/systems/Servers.tsx @@ -3,16 +3,17 @@ import { getTotalServers } from "../../selectors/serverSelectors"; import { loadServersIntoTable, } from "../../thunks/tableThunks"; -import { fetchServers } from "../../slices/serverSlice"; +import { fetchServers, Server } from "../../slices/serverSlice"; import { systemsLinks } from "./partials/SystemsNavigation"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of servers */ const Servers = () => { return ( - resource={"servers"} fetchResource={fetchServers} loadResourceIntoTable={loadServersIntoTable} diff --git a/src/components/systems/Services.tsx b/src/components/systems/Services.tsx index 1ef9037667..bea51be1ea 100644 --- a/src/components/systems/Services.tsx +++ b/src/components/systems/Services.tsx @@ -3,16 +3,18 @@ import { loadServicesIntoTable, } from "../../thunks/tableThunks"; import { getTotalServices } from "../../selectors/serviceSelector"; -import { fetchServices } from "../../slices/serviceSlice"; +import { fetchServices, Service } from "../../slices/serviceSlice"; import { systemsLinks } from "./partials/SystemsNavigation"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; +import { Server } from "../../slices/serverSlice"; /** * This component renders the table view of services */ const Services = () => { return ( - resource={"services"} fetchResource={fetchServices} loadResourceIntoTable={loadServicesIntoTable} diff --git a/src/components/users/Acls.tsx b/src/components/users/Acls.tsx index d61c40c19b..3522e246ee 100644 --- a/src/components/users/Acls.tsx +++ b/src/components/users/Acls.tsx @@ -3,16 +3,17 @@ import { loadAclsIntoTable, } from "../../thunks/tableThunks"; import { getTotalAcls } from "../../selectors/aclSelectors"; -import { fetchAcls } from "../../slices/aclSlice"; +import { AclResult, fetchAcls } from "../../slices/aclSlice"; import { usersLinks } from "./partials/UsersNavigation"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of acls */ const Acls = () => { return ( - resource={"acls"} fetchResource={fetchAcls} loadResourceIntoTable={loadAclsIntoTable} diff --git a/src/components/users/Groups.tsx b/src/components/users/Groups.tsx index b6da632ae5..253170c320 100644 --- a/src/components/users/Groups.tsx +++ b/src/components/users/Groups.tsx @@ -3,16 +3,17 @@ import { groupsTemplateMap } from "../../configs/tableConfigs/groupsTableMap"; import { loadGroupsIntoTable, } from "../../thunks/tableThunks"; -import { fetchGroups } from "../../slices/groupSlice"; +import { fetchGroups, Group } from "../../slices/groupSlice"; import { usersLinks } from "./partials/UsersNavigation"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of groups */ const Groups = () => { return ( - resource={"groups"} fetchResource={fetchGroups} loadResourceIntoTable={loadGroupsIntoTable} diff --git a/src/components/users/Users.tsx b/src/components/users/Users.tsx index 8a10ebb150..b72fea590f 100644 --- a/src/components/users/Users.tsx +++ b/src/components/users/Users.tsx @@ -3,16 +3,17 @@ import { getTotalUsers } from "../../selectors/userSelectors"; import { loadUsersIntoTable, } from "../../thunks/tableThunks"; -import { fetchUsers } from "../../slices/userSlice"; +import { fetchUsers, User } from "../../slices/userSlice"; import { usersLinks } from "./partials/UsersNavigation"; import TablePage from "../shared/TablePage"; +import { Row } from "../../slices/tableSlice"; /** * This component renders the table view of users */ const Users = () => { return ( - resource={"users"} fetchResource={fetchUsers} loadResourceIntoTable={loadUsersIntoTable} diff --git a/src/slices/eventSlice.ts b/src/slices/eventSlice.ts index bdbe0d9387..4988714ca1 100644 --- a/src/slices/eventSlice.ts +++ b/src/slices/eventSlice.ts @@ -28,7 +28,7 @@ import { TransformedAcl } from "./aclDetailsSlice"; import { TableConfig } from "../configs/tableConfigs/aclsTableConfig"; import { Publication } from "./eventDetailsSlice"; import { createAppAsyncThunk } from "../createAsyncThunkWithTypes"; -import { FormikErrors } from "formik"; +import { FormikHelpers } from "formik"; /** * This file contains redux reducer for actions affecting the state of events @@ -346,13 +346,13 @@ export const updateBulkMetadata = (params: { notFound?: string[], runningWorkflow?: string[], }, - values: { [key: string]: unknown } + values: { [key: string]: MetadataField["value"] } }): AppThunk => dispatch => { const { metadataFields, values } = params; const formData = new URLSearchParams(); formData.append("eventIds", JSON.stringify(metadataFields.merged)); - const metadata : { flavor: string, title: string, fields: any[]}[] = [ + const metadata : { flavor: string, title: string, fields: MetadataField[]}[] = [ { flavor: "dublincore/episode", title: "EVENTS.EVENTS.DETAILS.CATALOG.EPISODE", @@ -714,7 +714,7 @@ export const deleteMultipleEvent = (events: Event[]): AppThunk => dispatch => { export const fetchScheduling = createAppAsyncThunk("events/fetchScheduling", async (params: { events: Event[], fetchNewScheduling: boolean, - setFormikValue: (field: string, value: EditedEvents[]) => Promise> + setFieldValue: FormikHelpers<{ editedEvents: EditedEvents[]; }>["setFieldValue"], }, { getState }) => { type FetchScheduling = { eventId: string, @@ -727,7 +727,7 @@ export const fetchScheduling = createAppAsyncThunk("events/fetchScheduling", asy start: string, // Date string end: string, // Date string }; - const { events, fetchNewScheduling, setFormikValue } = params; + const { events, fetchNewScheduling, setFieldValue } = params; let editedEvents = []; @@ -790,7 +790,7 @@ export const fetchScheduling = createAppAsyncThunk("events/fetchScheduling", asy const responseSeriesOptions = await fetchSeriesOptions(); - setFormikValue("editedEvents", editedEvents); + setFieldValue("editedEvents", editedEvents); return { editedEvents, responseSeriesOptions }; }); diff --git a/src/slices/seriesSlice.ts b/src/slices/seriesSlice.ts index 9d5725c624..53e4aad77f 100644 --- a/src/slices/seriesSlice.ts +++ b/src/slices/seriesSlice.ts @@ -222,10 +222,13 @@ export const postNewSeries = (params: { const access = prepareAccessPolicyRulesForPost(values.policies); // Tobira - const tobira: any = {}; + const tobira: { + parentPagePath?: string + newPages?: { name?: string, pathSegment: string }[] + } = {}; if (values.selectedPage && values.breadcrumbs) { - const existingPages: any[] = []; - const newPages: any[] = []; + const existingPages: TobiraPage[] = []; + const newPages: { name?: string, pathSegment: string }[] = []; values.breadcrumbs.concat(values.selectedPage).forEach(function (page: TobiraPage) { if (page.new) { newPages.push({ @@ -237,9 +240,7 @@ export const postNewSeries = (params: { } }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tobira["parentPagePath"] = existingPages.pop().path; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + tobira.parentPagePath = existingPages.pop()!.path; tobira["newPages"] = newPages; } @@ -249,12 +250,11 @@ export const postNewSeries = (params: { options: unknown, access: typeof access, theme?: number, - tobira?: any + tobira?: typeof tobira } = { metadata: metadata, options: {}, access: access, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment tobira: tobira, }; diff --git a/src/slices/tableSlice.ts b/src/slices/tableSlice.ts index 997aafe23a..eab5132918 100644 --- a/src/slices/tableSlice.ts +++ b/src/slices/tableSlice.ts @@ -77,6 +77,8 @@ export function isSeries(row: Row | Event | Series | Recording | Server | Job | return (row as Series).organizers !== undefined; } +export type Meh = Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType + // TODO: Improve row typing. While this somewhat correctly reflects the current state of our code, it is rather annoying to work with. export type Row = { id: string, // For use with entityAdapter. Directly taken from event/series etc. if available diff --git a/src/utils/componentStyles.ts b/src/utils/componentStyles.ts index 61e1445483..533f725e83 100644 --- a/src/utils/componentStyles.ts +++ b/src/utils/componentStyles.ts @@ -1,18 +1,25 @@ /* this file contains syles as javascript objects for syled components */ -import { StylesConfig, Theme } from "react-select"; +import { GroupBase, StylesConfig, Theme } from "react-select"; +import { DropDownOption } from "../components/shared/DropDown"; // colors const colorDropDownMain = "#aaa"; const colorDropDownNormalFocus = "#5897fb"; const colorDropDownDarkerFocus = "#2a62bc"; -export function dropDownStyle(customCss: { - isMetadataStyle?: boolean, - width?: number | string, - optionPaddingTop?: number, - optionLineHeight?: string, -}): StylesConfig { +export function dropDownStyle( + customCss: { + isMetadataStyle?: boolean, + width?: number | string, + optionPaddingTop?: number, + optionLineHeight?: string, + }, +): StylesConfig< + DropDownOption, + false, + GroupBase> +> { const width = customCss.width ?? 250; return { diff --git a/src/utils/dateUtils.ts b/src/utils/dateUtils.ts index cdb6adff4b..e1f897bbcf 100644 --- a/src/utils/dateUtils.ts +++ b/src/utils/dateUtils.ts @@ -1,6 +1,6 @@ import moment from "moment"; import { makeTwoDigits } from "./utils"; -import { FormikErrors } from "formik"; +import { FormikHelpers } from "formik"; /** * This File contains methods concerning dates @@ -106,7 +106,7 @@ export const calculateDuration = ( const setDuration = ( startDate: Date, endDate: Date, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], ) => { const { durationHours, durationMinutes } = calculateDuration( startDate, @@ -140,7 +140,7 @@ const changeStart = ( minute: string, }, formikValues: RequiredFormikValues, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { const startDate = makeDate(start.date, start.hour, start.minute); @@ -171,7 +171,7 @@ const changeStart = ( export const changeStartDate = ( value: Date, formikValues: RequiredFormikValues & { scheduleStartHour: string, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -191,7 +191,7 @@ export const changeStartDate = ( export const changeStartHour = ( value: string, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -213,7 +213,7 @@ export const changeStartHour = ( export const changeStartMinute = ( value: string, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartHour: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -240,7 +240,7 @@ const changeEnd = ( minute: string, }, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartHour: string, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { const endDate = makeDate( @@ -274,7 +274,7 @@ const changeEnd = ( export const changeEndHour = ( value: string, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartHour: string, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -295,7 +295,7 @@ export const changeEndHour = ( export const changeEndMinute = ( value: string, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartHour: string, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -318,7 +318,7 @@ const changeDuration = ( eventId: string, duration: { hours: string, minutes: string }, formikValues: RequiredFormikValues & { scheduleStartDate: string | number, scheduleStartHour: string, scheduleStartMinute: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { const startDate = makeDate( @@ -353,7 +353,7 @@ export const changeDurationHour = ( scheduleStartMinute: string, scheduleDurationMinutes: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -379,7 +379,7 @@ export const changeDurationMinute = ( scheduleStartMinute: string, scheduleDurationHours: string }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -408,7 +408,7 @@ const changeStartMultiple = ( formikValues: RequiredFormikValues & { scheduleEndDate: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { const startDate = makeDate(start.date, start.hour, start.minute); @@ -454,7 +454,7 @@ export const changeStartDateMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -478,7 +478,7 @@ export const changeStartHourMultiple = ( scheduleStartDate: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -504,7 +504,7 @@ export const changeStartMinuteMultiple = ( scheduleStartDate: string, scheduleStartHour: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -532,7 +532,7 @@ export const changeEndDateMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -580,7 +580,7 @@ const changeEndMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { let endDate = makeDate(formikValues.scheduleStartDate, end.hour, end.minute); @@ -621,7 +621,7 @@ export const changeEndHourMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -647,7 +647,7 @@ export const changeEndMinuteMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -678,7 +678,7 @@ const changeDurationMultiple = ( scheduleStartHour: string, scheduleStartMinute: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { const startDate = makeDate( @@ -718,7 +718,7 @@ export const changeDurationHourMultiple = ( scheduleStartMinute: string, scheduleDurationMinutes: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { @@ -745,7 +745,7 @@ export const changeDurationMinuteMultiple = ( scheduleStartMinute: string, scheduleDurationHours: string, }, - setFieldValue: (field: string, value: string) => Promise>, + setFieldValue: FormikHelpers["setFieldValue"], eventId = "", checkConflicts?: (id: string, startDate: Date, endDate: Date, ca: string) => unknown, ) => { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 178e6d5847..0c0a56bdbe 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -3,6 +3,7 @@ import i18n from "../i18n/i18n"; import { ParseKeys, TFunction } from "i18next"; import { UserInfoState } from "../slices/userInfoSlice"; import { UploadOption } from "../slices/eventSlice"; +import { AsyncThunk } from "@reduxjs/toolkit"; /** * This File contains methods that are needed in more than one places @@ -154,3 +155,8 @@ export const translateOverrideFallback = (asset: UploadOption, t: TFunction, suf export const confirmUnsaved = (t: TFunction) => { return window.confirm(t("CONFIRMATIONS.WARNINGS.UNSAVED_CHANGES")); }; + +// A type for the cases where the component really only cares that it gets +// an async thunk of any sort. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type GenericAsyncThunk = AsyncThunk; diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 9ef13471b9..9cc96329a8 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -1,6 +1,7 @@ import { UploadAssetsTrack } from "./../slices/eventSlice"; import * as Yup from "yup"; import { MetadataCatalog } from "../slices/eventSlice"; +import { AnySchema } from "yup"; /** * This File contains all schemas used for validation with yup in the context of events and series @@ -10,7 +11,7 @@ import { MetadataCatalog } from "../slices/eventSlice"; * Dynamically create a schema for a required metadata field */ export function createMetadataSchema( - schema: { [key: string]: unknown; }, + schema: { [key: string]: AnySchema; }, config: { id: string; required: boolean; type: string; }, ) { const { id, required, type } = config; @@ -21,7 +22,7 @@ export function createMetadataSchema( let validationType: "string" | "array" | "date" = "string"; const validations: { type: string, - params: any[], + params: unknown[], }[] = [ { type: "required", @@ -64,7 +65,7 @@ export function createMetadataSchema( */ export const MetadataSchema = (catalog: MetadataCatalog) => { const schema = catalog.fields.reduce(createMetadataSchema, {}); - const schemaKeyReplace: { [key: string]: any} = {}; + const schemaKeyReplace: { [key: string]: AnySchema} = {}; for (const [key, value] of Object.entries(schema)) { schemaKeyReplace[catalog.flavor + "_" + key] = value; } @@ -236,7 +237,7 @@ export const EditUserSchema = Yup.object().shape({ name: Yup.string().required("Required"), email: Yup.string().email().required("Required"), passwordConfirmation: Yup.string().when("password", { - is: (value: any) => !!value, + is: (value: string) => !!value, then: () => Yup.string() .oneOf([Yup.ref("password"), undefined], "Passwords must match") .required("Required"),