Skip to content

Commit

Permalink
Merge pull request #1260 from Arnei/eslint-any
Browse files Browse the repository at this point in the history
Enforce eslint no-explicit-any
  • Loading branch information
geichelberger authored Apr 26, 2024
2 parents c84a20e + 9979eac commit 2b2d5eb
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 73 deletions.
4 changes: 0 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ module.exports = {
extends: [
"@opencast/eslint-config-ts-react",
],
rules: {
// Currently 120 warnings.
"@typescript-eslint/no-explicit-any": "off",
},
overrides: [
{
files: ["./*.js"],
Expand Down
25 changes: 21 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,15 @@ export const init = async () => {
// Get settings from URL query.
const urlParams = new URLSearchParams(window.location.search);

const rawUrlSettings = {};
type UrlSettings = {
[key: string]: string | UrlSettings;
}

const rawUrlSettings: UrlSettings = {};
urlParams.forEach((value, key) => {
// Create empty objects for full path (if the key contains ".") and set
// the value at the end.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let obj: { [k: string]: any; } = rawUrlSettings;
if (key.startsWith("opencast.") || key === "allowedCallbackPrefixes") {
return;
Expand Down Expand Up @@ -232,9 +237,11 @@ const loadContextSettings = async () => {
* `srcDescription` is just a string for error messages specifying where `obj`
* comes from.
* */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const validate = (obj: Record<string, any> | null, allowParse: boolean, src: string, sourceDescription: string) => {
// Validates `obj` with `schema`. `path` is the current path used for error
// messages.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const validate = (schema: any, obj: Record<string, any> | null, path: string) => {
if (typeof schema === "function") {
return validateValue(schema, obj, path);
Expand All @@ -246,7 +253,9 @@ const validate = (obj: Record<string, any> | null, allowParse: boolean, src: str
// Validate a settings value with a validation function. Returns the final
// value of the setting or `null` if it should be ignored.
const validateValue = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validation: (arg0: any, arg1: boolean, arg2: string) => any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: Record<string, any> | null,
path: string
) => {
Expand All @@ -264,9 +273,11 @@ const validate = (obj: Record<string, any> | null, allowParse: boolean, src: str

// Validate a settings object/namespace. `schema` and `obj` need to be
// objects.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const validateObj = (schema: any, obj: Record<string, any> | null, path: string) => {
// We iterate through all keys of the given settings object, checking if
// each key is valid and recursively validating the value of that key.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const out: { [k: string]: any; } = {};
for (const key in obj) {
const newPath = path ? `${path}.${key}` : key;
Expand Down Expand Up @@ -294,11 +305,13 @@ const validate = (obj: Record<string, any> | null, allowParse: boolean, src: str

// Validation functions for different types.
const types = {
"string": (v: any, _allowParse: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"string": (v: string, _allowParse: any) => {
if (typeof v !== "string") {
throw new Error("is not a string, but should be");
}
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"boolean": (v: string, allowParse: any) => {
if (typeof v === "boolean") {
return;
Expand All @@ -316,7 +329,8 @@ const types = {
throw new Error("is not a boolean");
}
},
"array": (v: any, _allowParse: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"array": (v: string | [], _allowParse: any) => {
if (!Array.isArray(v)) {
throw new Error("is not an array, but should be");
}
Expand All @@ -326,7 +340,8 @@ const types = {
}
}
},
"map": (v: any, _allowParse: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"map": (v: { [k: string]: string }, _allowParse: any) => {
for (const key in v) {
if (typeof key !== "string") {
throw new Error("is not a string, but should be");
Expand All @@ -336,6 +351,7 @@ const types = {
}
}
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"objectsWithinObjects": (v: any, _allowParse: any) => {
for (const catalogName in v) {
if (typeof catalogName !== "string") {
Expand Down Expand Up @@ -405,4 +421,5 @@ const merge = (a: iSettings, b: iSettings) => {
return deepmerge(a, b, { arrayMerge });
};
merge.all = (array: object[]) => deepmerge.all(array, { arrayMerge });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const arrayMerge = (_destinationArray: any, sourceArray: any, _options: any) => sourceArray;
32 changes: 20 additions & 12 deletions src/cssStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import emotionNormalize from "emotion-normalize";
import { checkFlexGapSupport } from "./util/utilityFunctions";
import { createTheme } from "@mui/material/styles";
import { Theme, useTheme } from "./themes";
import { StylesConfig } from "react-select";

/**
* An emotion component that inserts styles globally
Expand Down Expand Up @@ -212,9 +213,16 @@ export const errorBoxStyle = (errorStatus: boolean, theme: Theme) => {
);
};

export function selectFieldStyle(theme: Theme) {
type MyOptionType = {
label: string;
value: string;
};

type IsMulti = false;

export function selectFieldStyle(theme: Theme): StylesConfig<MyOptionType, IsMulti> {
return {
control: (provided: any, state: any) => ({
control: (provided, state) => ({
...provided,
background: theme.menu_background,
...(state.isFocused && { borderColor: theme.metadata_highlight }),
Expand All @@ -224,52 +232,52 @@ export function selectFieldStyle(theme: Theme) {
boxShadow: `0 0 0 1px ${theme.metadata_highlight}`,
},
}),
menu: (provided: any) => ({
menu: provided => ({
...provided,
background: theme.menu_background,
outline: theme.dropdown_border,
// kill the gap
marginTop: 0,
}),
singleValue: (provided: any) => ({
singleValue: provided => ({
...provided,
color: theme.text,
}),
multiValue: (provided: any) => ({
multiValue: provided => ({
...provided,
color: theme.inverted_text,
background: theme.multiValue,
cursor: "default",
}),
multiValueLabel: (provided: any) => ({
multiValueLabel: provided => ({
...provided,
color: theme.inverted_text,
}),
option: (provided: any, state: any) => ({
option: (provided, state) => ({
...provided,
background: state.isFocused ? theme.focused : theme.menu_background
&& state.isSelected ? theme.selected : theme.menu_background,
...(state.isFocused && { color: theme.focus_text }),
color: state.isFocused ? theme.focus_text : theme.text
&& state.isSelected ? theme.selected_text : theme.text,
}),
placeholder: (provided: any) => ({
placeholder: provided => ({
...provided,
color: theme.text,
}),
clearIndicator: (provided: any) => ({
clearIndicator: provided => ({
...provided,
color: theme.indicator_color,
}),
dropdownIndicator: (provided: any) => ({
dropdownIndicator: provided => ({
...provided,
color: theme.indicator_color,
}),
valueContainer: (provided: any) => ({
valueContainer: provided => ({
...provided,
cursor: "text",
}),
input: (provided: any) => ({
input: provided => ({
...provided,
color: theme.text,
}),
Expand Down
1 change: 1 addition & 0 deletions src/import-png.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Must declare module to be able to serve static images
declare module "*.png" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const value: any;
export default value;
}
32 changes: 25 additions & 7 deletions src/main/Metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,11 @@ const Metadata: React.FC = () => {
* @param input
* @param output
*/
const helperHandleArrays = (library: any[] | null, input: any, output: any[]) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const helperHandleArrays = (library: any[] | null, input: string, output: any[]) => {
// If the value is hid inside an array, we need to extract it
if (Array.isArray(input)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
input.forEach((subArray: any) => {
output.push(helperHandleArrays(library, subArray, output));
});
Expand All @@ -233,6 +235,7 @@ const Metadata: React.FC = () => {
* @param catalogs
*/
const getInitialValues = (catalogs: Catalog[]) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const initValues: { [n: string]: any; } = {};

catalogs.forEach((catalog: Catalog, catalogIndex: number) => {
Expand All @@ -244,9 +247,11 @@ const Metadata: React.FC = () => {
// Since react-select creates different values
if (field.collection) {
const library = generateReactSelectLibrary(field);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let searchValue: any = field.value;

if (Array.isArray(searchValue)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result: any[] = [];
helperHandleArrays(library, field.value, result);
searchValue = result;
Expand All @@ -270,13 +275,13 @@ const Metadata: React.FC = () => {
* Validator for required fields
* @param value
*/
const required = (value: any) => (value ? undefined : t("metadata.validation.required"));
const required = (value: string) => (value ? undefined : t("metadata.validation.required"));

/**
* Validator for the duration field
* @param value
*/
const duration = (value: any) => {
const duration = (value: string) => {
const re = /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/;
return re.test(value) ? undefined : t("metadata.validation.duration-format");
};
Expand All @@ -285,15 +290,15 @@ const Metadata: React.FC = () => {
* Validator for the date time fields
* @param date
*/
const dateTimeValidator = (date: any) => {
const dateTimeValidator = (date: Date | string) => {
// Empty field is valid value in Opencast
if (!date) {
return undefined;
}

let dt = undefined;
if (Object.prototype.toString.call(date) === "[object Date]") {
dt = LuxonDateTime.fromJSDate(date);
dt = LuxonDateTime.fromJSDate(date as Date);
}
if (typeof date === "string") {
dt = LuxonDateTime.fromISO(date);
Expand Down Expand Up @@ -337,6 +342,7 @@ const Metadata: React.FC = () => {
* @param value value for the field
* @param fieldId String of the form "catalog{catalogIndex}.name"
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const submitSingleField = (value: any, fieldId: string) => {
const catalogIndexString = fieldId.substring(
fieldId.indexOf("g") + 1,
Expand Down Expand Up @@ -366,7 +372,11 @@ const Metadata: React.FC = () => {
* @param e
* @param input
*/
const blurWithSubmit = (e: any, input: any) => {
const blurWithSubmit = (
e: React.FocusEvent<HTMLInputElement, Element> | React.FocusEvent<HTMLTextAreaElement, Element>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
input: any
) => {
input.onBlur(e);
submitSingleField(input.value, input.name);
};
Expand All @@ -377,12 +387,15 @@ const Metadata: React.FC = () => {
* @param field
* @param value
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parseValue = (field: MetadataField | null, value: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let returnValue: any = value;

// Parse values out react-multi-select and put them in an array
if (Array.isArray(value)) {
returnValue = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value.forEach((subValue: any) => {
returnValue.push(parseValue(null, subValue)); // Pass field as null to avoid each value into an array later on
});
Expand Down Expand Up @@ -423,12 +436,14 @@ const Metadata: React.FC = () => {
* Saves values in redux state and sends them to Opencast
* @param values
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const onSubmit = (values: { [x: string]: { [x: string]: any; }; }) => {
// For each submitted value, get the catalog it belongs to
Object.keys(values).forEach((formCatalogName: string) => {
const catalogIndex = parseInt(formCatalogName.replace("catalog", ""));

// For each field in the submitted values
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Object.keys(values[formCatalogName]).forEach((formFieldName: any) => {
// Find the corresponding field index in the redux catalog
for (let fieldIndex = 0; fieldIndex < catalogs[catalogIndex].fields.length; fieldIndex++) {
Expand Down Expand Up @@ -460,7 +475,8 @@ const Metadata: React.FC = () => {
const generateReactSelectLibrary = (field: MetadataField) => {
if (field.collection) {
// For whatever reason react-select uses "value" as their key, which is not at all confusing
const library: [{ value: any, label: any, submitValue: any; }] =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const library: [{ value: any, label: string, submitValue: any; }] =
[{ value: "", label: "No value", submitValue: "" }];
Object.entries(field.collection).forEach(([key, value]) => {
// // Parse License
Expand Down Expand Up @@ -502,6 +518,7 @@ const Metadata: React.FC = () => {
* @param field
* @param input
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const generateComponent = (field: MetadataField, input: any) => {
input.id = input.name;
if (field.collection) {
Expand Down Expand Up @@ -602,6 +619,7 @@ const Metadata: React.FC = () => {
* can"t handle empty string as a value (which is what Opencast uses to
* represent no date/time)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const generateComponentWithModifiedInput = (field: MetadataField, input: FieldInputProps<any, HTMLElement>) => {
if ((field.type === "date" || field.type === "time") && input.value === "") {
const { value, ...other } = input;
Expand Down
10 changes: 8 additions & 2 deletions src/main/SubtitleSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { selectSubtitles, setSelectedSubtitleId, setSubtitle } from "../redux/su
import { useAppDispatch, useAppSelector } from "../redux/store";
import { setIsDisplayEditView } from "../redux/subtitleSlice";
import { LuPlus } from "react-icons/lu";
import { Form } from "react-final-form";
import { withTypes } from "react-final-form";
import { Select } from "mui-rff";
import { useState } from "react";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -211,6 +211,12 @@ const SubtitleAddButton: React.FC<{

const [isPlusDisplay, setIsPlusDisplay] = useState(true);

// Form types
interface FormSubmitValues {
selectedSubtitle: string;
}
const { Form } = withTypes<FormSubmitValues>();

// Parse language data into a format the dropdown understands
const selectData = () => {
const data = [];
Expand All @@ -222,7 +228,7 @@ const SubtitleAddButton: React.FC<{
return data;
};

const onSubmit = (values: { selectedSubtitle: any; }) => {
const onSubmit = (values: FormSubmitValues) => {
// Create new subtitle for the given language
const id = values.selectedSubtitle;
const relatedSubtitle = subtitlesForDropdown.find(tag => tag.id === id);
Expand Down
Loading

0 comments on commit 2b2d5eb

Please sign in to comment.