Introduced tsconfig.app.json and tsconfig.base.json + Refactored eslint.config.js to the latest structure (#652)

* Introduced tsconfig.app.json and tsconfig.base.json

* yarn.lock

* Introduced tsconfig.app.json, tsconfig.base.jsonfig.

* Refactored eslint.config.js to latest structure

* Returned previous recommended rules.

* More rules

* Force import rules

* Check

* Check

* Cleanup ESLint configuration and plugins

* Cleanup heap: "writable",DD_RUM: "writable" from ESLint configuration

* "scripts" moved to the top of package.json
This commit is contained in:
yuri-sakharov
2026-02-15 19:41:04 +02:00
committed by GitHub
parent 939dd8ac0c
commit c9b8fb7809
79 changed files with 1586 additions and 1887 deletions

View File

@@ -1,163 +1,119 @@
import js from "@eslint/js";
import { defineConfig } from "eslint/config";
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
import tscPlugin from "eslint-plugin-tsc";
import { fileURLToPath } from "url";
import path from "path";
import reactHooks from "eslint-plugin-react-hooks";
import importPlugin from "eslint-plugin-import";
import prettierRecommended from "eslint-plugin-prettier/recommended";
// import tscPlugin from "eslint-plugin-tsc";
const __filename = fileURLToPath(new URL(import.meta.url));
const __dirname = path.dirname(__filename);
export default defineConfig(
{ ignores: ["dist", "node_modules"] },
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
js.configs.recommended,
tseslint.configs.recommendedTypeChecked,
// tsEslint.configs.strictTypeChecked, // The project is not ready yet
// tsEslint.configs.stylisticTypeChecked, // Added for better 2026 coding standards, however the project is not ready yet
importPlugin.flatConfigs.recommended,
importPlugin.flatConfigs.typescript,
react.configs.flat.recommended,
react.configs.flat["jsx-runtime"],
reactHooks.configs.flat.recommended,
prettierRecommended,
export default defineConfig([
{
ignores: ["eslint.config.js"],
files: ["**/*.{ts,tsx}"],
languageOptions: {
globals: {
...globals.browser,
heap: "writable",
DD_RUM: "writable",
...globals.node,
},
parser: tsParser,
parserOptions: {
projectService: true,
projectService: {
allowDefaultProject: ["eslint.config.js"],
},
tsconfigRootDir: import.meta.dirname,
},
},
extends: compat.extends(
"enpitech",
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
),
plugins: {
"@typescript-eslint": typescriptEslint,
tsc: tscPlugin,
react,
},
settings: {
react: {
version: "detect",
react: { version: "detect" },
"import/resolver": {
node: true,
typescript: {
alwaysTryTypes: true,
project: "./tsconfig.json",
},
},
},
// plugins: {
// tsc: tscPlugin,
// },
rules: {
"no-console": [
"error",
{
allow: ["error"],
},
],
"no-alert": "error",
/* ───────── Base Overrides ───────── */
"no-console": ["error", { allow: ["error", "warn"] }],
"no-debugger": "error",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
vars: "all",
args: "after-used",
ignoreRestSiblings: true,
},
],
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "error",
"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "always"],
/* ───────── Import Precision ───────── */
"import/no-duplicates": ["error", { "prefer-inline": true }],
/* ───────── React Precision ───────── */
"no-restricted-properties": [
"error",
{
object: "React",
property: "*",
message: "Using React.* is prohibited.",
},
],
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
"@typescript-eslint/no-unsafe-return": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/consistent-type-assertions": [
"error",
{
assertionStyle: "as",
objectLiteralTypeAssertions: "never",
},
],
"@typescript-eslint/no-restricted-types": [
"error",
{
types: {
"React.FC": {
message:
"Avoid using React.FC. Use import type { FC } from React instead",
},
"React.Node": {
message:
"Avoid using React.Node. Use import type { Node } from React instead",
},
},
"Use named imports instead (e.g. import { useState } from 'react')",
},
],
"no-restricted-imports": [
"error",
{
name: "react",
importNames: ["default", "*"],
message:
"Default and namespace React imports are prohibited. Use specific named imports only (e.g., import { useState, type ReactNode } from 'react').",
allowTypeImports: false,
importNames: ["default"],
message: "Default React imports are prohibited. Use named imports.",
},
],
/* ───────── TypeScript & Verbatim Syntax ───────── */
"@typescript-eslint/consistent-type-imports": [
"error",
{
prefer: "type-imports",
fixStyle: "inline-type-imports",
},
],
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
"tsc/config": ["error", { configFile: "./tsconfig.json" }],
"@typescript-eslint/no-restricted-types": [
"error",
{
types: {
"React.FC": "Use 'import type { FC }' instead.",
"React.ReactNode": "Use 'import type { ReactNode }' instead.",
// FC: "Avoid FC (Functional Component) type; prefer explicit return types.",
},
},
],
},
},
{
files: ["vite.config.ts"],
languageOptions: {
parserOptions: {
project: "./tsconfig.node.json", // point to the tiny tsconfig
},
},
},
{
files: ["**/*.{js,mjs}"],
...tseslint.configs.disableTypeChecked,
languageOptions: {
globals: {
...globals.node,
},
sourceType: "script",
parserOptions: {},
},
files: ["**/.eslintrc.{js,cjs}"],
},
]);
{
files: ["eslint.config.js"],
rules: { "import/no-unresolved": "off" },
}
);

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,25 @@
"type": "module",
"description": "",
"main": "index.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"prepare": "cd .. && husky",
"pre:commit": "lint-staged",
"test": "echo \"Error: no test specified. Please use 'cypress:run' or 'cypress:open' commands\" && exit 1",
"tsc": "tsc",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build",
"lint": "npx eslint src/",
"lint:fix": "npm run lint -- --fix --max-warnings=0",
"prettier": "npx prettier src/ --check",
"prettier:fix": "npm run prettier -- --write",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"cypress:component": "cypress run --component",
"cypress:component:open": "cypress open --component"
},
"dependencies": {
"@tanstack/react-query": "^5.90.11",
"compare-versions": "^6.1.1",
@@ -42,8 +61,9 @@
"babel-plugin-react-compiler": "^1.0.0",
"cypress": "15.10.0",
"eslint": "^9.39.1",
"eslint-config-enpitech": "^1.0.17",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
@@ -59,6 +79,7 @@
"storybook": "10.1.10",
"tailwindcss": "^4.1.17",
"typescript": "^5.9.3",
"typescript-eslint": "^8.55.0",
"vite": "^7.2.4",
"vite-plugin-static-copy": "^3.1.4"
},
@@ -66,25 +87,6 @@
"*.{js,jsx,ts,tsx}": "npm run lint:fix",
"*.{js,jsx,ts,tsx,json,css,md,mdx}": "npm run prettier:fix"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"prepare": "cd .. && husky",
"pre:commit": "lint-staged",
"test": "echo \"Error: no test specified. Please use 'cypress:run' or 'cypress:open' commands\" && exit 1",
"tsc:check": "tsc --noEmit",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build",
"lint": "npx eslint src/",
"lint:fix": "npm run lint -- --fix --max-warnings=0",
"prettier": "npx prettier src/ --check",
"prettier:fix": "npm run prettier -- --write",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"cypress:component": "cypress run --component",
"cypress:component:open": "cypress open --component"
},
"keywords": [],
"author": "",
"license": "Apache-2.0"

View File

@@ -1,3 +1,5 @@
import { type QueryFunctionContext } from "@tanstack/react-query";
import type {
Chart,
ChartVersion,
@@ -5,7 +7,6 @@ import type {
ReleaseHealthStatus,
ReleaseRevision,
} from "../data/types";
import { type QueryFunctionContext } from "@tanstack/react-query";
interface ClustersResponse {
AuthInfo: string;

View File

@@ -1,13 +1,15 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import apiService from "./apiService";
import type {
K8sResource,
K8sResourceList,
KubectlContexts,
} from "./interfaces";
import apiService from "./apiService";
// Get list of kubectl contexts configured locally
// @ts-expect-error unused
function useGetKubectlContexts(options?: UseQueryOptions<KubectlContexts>) {
return useQuery<KubectlContexts>({
queryKey: ["k8s", "contexts"],
@@ -21,6 +23,7 @@ function useGetKubectlContexts(options?: UseQueryOptions<KubectlContexts>) {
}
// Get resources information
// @ts-expect-error unused
function useGetK8sResource(
kind: string,
name: string,
@@ -39,6 +42,7 @@ function useGetK8sResource(
}
// Get list of resources
// @ts-expect-error unused
function useGetK8sResourceList(
kind: string,
options?: UseQueryOptions<K8sResourceList>
@@ -55,6 +59,7 @@ function useGetK8sResourceList(
}
// Get describe text for kubernetes resource
// @ts-expect-error unused
function useGetK8sResourceDescribe(
kind: string,
name: string,

View File

@@ -4,8 +4,9 @@ import {
useMutation,
useQuery,
} from "@tanstack/react-query";
import type { ApplicationStatus } from "./interfaces";
import apiService from "./apiService";
import type { ApplicationStatus } from "./interfaces";
// Shuts down the Helm Dashboard application
export function useShutdownHelmDashboard(

View File

@@ -4,12 +4,14 @@ import {
useQuery,
type UseQueryOptions,
} from "@tanstack/react-query";
import type { ChartVersion, Release } from "../data/types";
import type { LatestChartVersion } from "./interfaces";
import apiService from "./apiService";
import { getVersionManifestFormData } from "./shared";
import { isNewerVersion } from "../utils";
import apiService from "./apiService";
import type { LatestChartVersion } from "./interfaces";
import { getVersionManifestFormData } from "./shared";
export const HD_RESOURCE_CONDITION_TYPE = "hdHealth"; // it's our custom condition type, only one exists
export function useGetInstalledReleases(context: string) {

View File

@@ -4,8 +4,9 @@ import {
useMutation,
useQuery,
} from "@tanstack/react-query";
import type { HelmRepositories } from "./interfaces";
import apiService from "./apiService";
import type { HelmRepositories } from "./interfaces";
// Get list of Helm repositories
export function useGetRepositories(

View File

@@ -7,11 +7,16 @@ import {
useMutation,
useQuery,
} from "@tanstack/react-query";
import type { ScanResults, ScannersList } from "./interfaces";
import { ScanResult } from "./interfaces";
import apiService from "./apiService";
import {
type ScanResult,
type ScanResults,
type ScannersList,
} from "./interfaces";
// Get list of discovered scanners
// @ts-expect-error unused
function useGetDiscoveredScanners(options?: UseQueryOptions<ScannersList>) {
return useQuery<ScannersList>({
queryKey: ["scanners"],
@@ -25,6 +30,7 @@ function useGetDiscoveredScanners(options?: UseQueryOptions<ScannersList>) {
}
// Scan manifests using all applicable scanners
// @ts-expect-error unused
function useScanManifests(
manifest: string,
options?: UseMutationOptions<ScanResults, Error, string>
@@ -46,6 +52,7 @@ function useScanManifests(
}
// Scan specified k8s resource in cluster
// @ts-expect-error unused
function useScanK8sResource(
kind: string,
namespace: string,

View File

@@ -1,4 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import apiService from "./apiService";
export const getVersionManifestFormData = ({

View File

@@ -1,18 +1,20 @@
import Header from "./layout/Header";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { type FC, useState, lazy } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { HashRouter, Outlet, Route, Routes, useParams } from "react-router";
import apiService from "./API/apiService";
import ErrorFallback from "./components/ErrorFallback";
import GlobalErrorModal from "./components/modal/GlobalErrorModal";
import { AppContextProvider } from "./context/AppContext";
import {
ErrorModalContext,
type ErrorAlert,
} from "./context/ErrorModalContext";
import Header from "./layout/Header";
import Installed from "./pages/Installed";
import RepositoryPage from "./pages/Repository";
import Revision from "./pages/Revision";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import type { FC } from "react";
import { useState, lazy } from "react";
import type { ErrorAlert } from "./context/ErrorModalContext";
import { ErrorModalContext } from "./context/ErrorModalContext";
import GlobalErrorModal from "./components/modal/GlobalErrorModal";
import { AppContextProvider } from "./context/AppContext";
import apiService from "./API/apiService";
import { ErrorBoundary } from "react-error-boundary";
import ErrorFallback from "./components/ErrorFallback";
const DocsPage = lazy(() => import("./pages/DocsPage"));

View File

@@ -15,6 +15,7 @@
*/
import type { Meta } from "@storybook/react-vite";
import Badge from "./Badge";
// We set the metadata for the story.

View File

@@ -1,4 +1,5 @@
import { mount } from "cypress/react";
import { Button } from "./common/Button/Button";
describe("Button component tests", () => {

View File

@@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import Button from "./Button";
const meta = {

View File

@@ -1,8 +1,10 @@
import { AppContextProvider } from "../context/AppContext";
import ClustersList from "./ClustersList";
import { BrowserRouter } from "react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter } from "react-router";
import { AppContextProvider } from "../context/AppContext";
import type { Release } from "../data/types";
import ClustersList from "./ClustersList";
import { DeploymentStatus } from "./common/StatusLabel";
type ClustersListProps = {

View File

@@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import ClustersList from "./ClustersList";
const meta = {

View File

@@ -1,11 +1,12 @@
import { useEffect, useEffectEvent, useMemo } from "react";
import type { Cluster, Release } from "../data/types";
import apiService from "../API/apiService";
import { useQuery } from "@tanstack/react-query";
import useCustomSearchParams from "../hooks/useCustomSearchParams";
import { useAppContext } from "../context/AppContext";
import { useEffect, useEffectEvent, useMemo } from "react";
import { v4 as uuidv4 } from "uuid";
import apiService from "../API/apiService";
import { useAppContext } from "../context/AppContext";
import type { Cluster, Release } from "../data/types";
import useCustomSearchParams from "../hooks/useCustomSearchParams";
type ClustersListProps = {
onClusterChange: (clusterName: string) => void;
selectedCluster: string;

View File

@@ -1,7 +1,8 @@
import ErrorFallback from "./ErrorFallback";
import { mount } from "cypress/react";
import { ErrorBoundary } from "react-error-boundary";
import { useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import ErrorFallback from "./ErrorFallback";
/**
* Component tests for ErrorFallback

View File

@@ -1,9 +1,11 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import ErrorFallback from "./ErrorFallback";
import { useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import Button from "../Button";
import ErrorFallback from "./ErrorFallback";
const meta = {
title: "Components/ErrorFallback",
component: ErrorFallback,

View File

@@ -1,6 +1,7 @@
import type { FallbackProps } from "react-error-boundary";
import GlobalErrorModal from "../modal/GlobalErrorModal";
import { useDevLogger } from "../../hooks/useDevLogger";
import GlobalErrorModal from "../modal/GlobalErrorModal";
/**
* Error fallback component for React Error Boundary

View File

@@ -1,5 +1,6 @@
import { HD_RESOURCE_CONDITION_TYPE } from "../../API/releases";
import { Tooltip } from "flowbite-react";
import { HD_RESOURCE_CONDITION_TYPE } from "../../API/releases";
import type { ReleaseHealthStatus } from "../../data/types";
interface Props {

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import InstalledPackageCard from "./InstalledPackageCard";
const meta = {

View File

@@ -1,22 +1,24 @@
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import type { Release, ReleaseHealthStatus } from "../../data/types";
import { BsArrowUpCircleFill, BsPlusCircleFill } from "react-icons/bs";
import { useInView } from "react-intersection-observer";
import apiService from "../../API/apiService";
import type { LatestChartVersion } from "../../API/interfaces";
import { useGetApplicationStatus } from "../../API/other";
import { useGetLatestVersion } from "../../API/releases";
import HelmGrayIcon from "../../assets/helm-gray-50.svg";
import type { Release, ReleaseHealthStatus } from "../../data/types";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import { getAge } from "../../timeUtils";
import { isNewerVersion } from "../../utils";
import StatusLabel, {
DeploymentStatus,
getStatusColor,
} from "../common/StatusLabel";
import { useQuery } from "@tanstack/react-query";
import apiService from "../../API/apiService";
import HealthStatus from "./HealthStatus";
import HelmGrayIcon from "../../assets/helm-gray-50.svg";
import Spinner from "../Spinner";
import { useGetLatestVersion } from "../../API/releases";
import { isNewerVersion } from "../../utils";
import type { LatestChartVersion } from "../../API/interfaces";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import { useInView } from "react-intersection-observer";
import { useGetApplicationStatus } from "../../API/other";
import HealthStatus from "./HealthStatus";
type InstalledPackageCardProps = {
release: Release;

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import InstalledPackagesHeader from "./InstalledPackagesHeader";
const meta = {

View File

@@ -1,6 +1,7 @@
import type { Dispatch, SetStateAction } from "react";
import HeaderLogo from "../../assets/packges-header.svg";
import type { Release } from "../../data/types";
import type { Dispatch, SetStateAction } from "react";
type InstalledPackagesHeaderProps = {
filteredReleases?: Release[];

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import InstalledPackagesList from "./InstalledPackagesList";
const meta = {

View File

@@ -1,6 +1,7 @@
import InstalledPackageCard from "./InstalledPackageCard";
import type { Release } from "../../data/types";
import InstalledPackageCard from "./InstalledPackageCard";
type InstalledPackagesListProps = {
filteredReleases: Release[];
};

View File

@@ -1,4 +1,6 @@
import { type ReactNode } from "react";
import { NavLink, useLocation, useParams } from "react-router";
import { useAppContext } from "../context/AppContext";
const LinkWithSearchParams = ({
@@ -9,7 +11,7 @@ const LinkWithSearchParams = ({
end?: boolean;
exclude?: string[];
className?: string;
children: React.ReactNode;
children: ReactNode;
}) => {
const { search } = useLocation();
const { context = "" } = useParams();

View File

@@ -8,6 +8,7 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { action } from "storybook/actions";
import SelectMenu, { SelectMenuItem } from "./SelectMenu";
const meta = {

View File

@@ -1,4 +1,5 @@
import type { StoryFn, Meta } from "@storybook/react-vite";
import ShutDownButton from "./ShutDownButton";
const meta = {

View File

@@ -1,7 +1,9 @@
import { BsPower } from "react-icons/bs";
import Modal from "./modal/Modal";
import { useShutdownHelmDashboard } from "../API/other";
import Modal from "./modal/Modal";
function ShutDownButton() {
const { mutate: signOut, status } = useShutdownHelmDashboard();

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import Tabs from "./Tabs";
const meta = {

View File

@@ -1,4 +1,5 @@
import type { ReactNode } from "react";
import useCustomSearchParams from "../hooks/useCustomSearchParams";
export interface Tab {

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import TabsBar from "./TabsBar";
const meta = {

View File

@@ -5,6 +5,7 @@
*/
import type { Meta } from "@storybook/react-vite";
import TextInput from "./TextInput";
const meta = {

View File

@@ -1,5 +1,4 @@
import type { HTMLAttributes } from "react";
import { type ReactElement, cloneElement } from "react";
import { cloneElement, type HTMLAttributes, type ReactElement } from "react";
export default function Tooltip({
id,

View File

@@ -1,4 +1,5 @@
import type { Meta, StoryFn } from "@storybook/react-vite";
import { Troubleshoot } from "./Troubleshoot";
const meta = {

View File

@@ -1,7 +1,8 @@
import type { Meta } from "@storybook/react-vite";
import { action } from "storybook/actions";
import DropDown from "./DropDown";
import { BsSlack, BsGithub } from "react-icons/bs";
import { action } from "storybook/actions";
import DropDown from "./DropDown";
const meta = {
/* 👇 The title prop is optional.

View File

@@ -1,5 +1,5 @@
import type { ReactNode } from "react";
import { Fragment, useEffect, useRef, useState } from "react";
import { type ReactNode, Fragment, useEffect, useRef, useState } from "react";
import ArrowDownIcon from "../../assets/arrow-down-icon.svg";
export type DropDownItem = {

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import StatusLabel, { DeploymentStatus } from "./StatusLabel";
const meta = {

View File

@@ -1,4 +1,5 @@
import type { StoryFn, Meta } from "@storybook/react-vite";
import AddRepositoryModal from "./AddRepositoryModal";
const meta = {

View File

@@ -1,12 +1,14 @@
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import Modal from "./Modal";
import Spinner from "../Spinner";
import apiService from "../../API/apiService";
import { useAppContext } from "../../context/AppContext";
import useAlertError from "../../hooks/useAlertError";
import useCustomSearchParams from "../../hooks/useCustomSearchParams";
import { useAppContext } from "../../context/AppContext";
import { useQueryClient } from "@tanstack/react-query";
import apiService from "../../API/apiService";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import Spinner from "../Spinner";
import Modal from "./Modal";
interface FormKeys {
name: string;

View File

@@ -1,5 +1,6 @@
import { action } from "storybook/actions";
import type { Meta } from "@storybook/react-vite";
import { action } from "storybook/actions";
import ErrorModal from "./ErrorModal";
const meta = {

View File

@@ -1,7 +1,8 @@
import hljs from "highlight.js/lib/core";
import Spinner from "../../Spinner";
import yaml from "highlight.js/lib/languages/yaml";
import Spinner from "../../Spinner";
hljs.registerLanguage("yaml", yaml);
export const ChartValues = ({

View File

@@ -1,5 +1,6 @@
import { useState, useEffect } from "react";
import { useParams } from "react-router";
import useDebounce from "../../../hooks/useDebounce";
export const GeneralDetails = ({

View File

@@ -1,4 +1,4 @@
import { useParams } from "react-router";
import { useMutation } from "@tanstack/react-query";
import {
useEffect,
useEffectEvent,
@@ -7,27 +7,29 @@ import {
lazy,
Suspense,
} from "react";
import type { VersionData } from "../../../API/releases";
import { useParams } from "react-router";
import apiService from "../../../API/apiService";
import type { LatestChartVersion } from "../../../API/interfaces";
import {
type VersionData,
useChartReleaseValues,
useGetReleaseManifest,
useGetVersions,
useVersionData,
} from "../../../API/releases";
import Modal, { ModalButtonStyle } from "../Modal";
import { GeneralDetails } from "./GeneralDetails";
import { useMutation } from "@tanstack/react-query";
import useNavigateWithSearchParams from "../../../hooks/useNavigateWithSearchParams";
import { VersionToInstall } from "./VersionToInstall";
import { isNoneEmptyArray } from "../../../utils";
import useCustomSearchParams from "../../../hooks/useCustomSearchParams";
import { useChartRepoValues } from "../../../API/repositories";
import { useDiffData } from "../../../API/shared";
import type { InstallChartModalProps } from "../../../data/types";
import apiService from "../../../API/apiService";
import { InstallUpgradeTitle } from "./InstallUpgradeTitle";
import type { LatestChartVersion } from "../../../API/interfaces";
import useCustomSearchParams from "../../../hooks/useCustomSearchParams";
import useNavigateWithSearchParams from "../../../hooks/useNavigateWithSearchParams";
import { isNoneEmptyArray } from "../../../utils";
import Spinner from "../../Spinner";
import Modal, { ModalButtonStyle } from "../Modal";
import { GeneralDetails } from "./GeneralDetails";
import { VersionToInstall } from "./VersionToInstall";
import { InstallUpgradeTitle } from "./InstallUpgradeTitle";
const DefinedValues = lazy(() => import("./DefinedValues"));
const ManifestDiff = lazy(() => import("./ManifestDiff"));

View File

@@ -1,4 +1,4 @@
import { useParams } from "react-router";
import { useMutation } from "@tanstack/react-query";
import {
lazy,
Suspense,
@@ -7,20 +7,22 @@ import {
useMemo,
useState,
} from "react";
import { useParams } from "react-router";
import apiService from "../../../API/apiService";
import type { LatestChartVersion } from "../../../API/interfaces";
import { useGetVersions, useVersionData } from "../../../API/releases";
import Modal, { ModalButtonStyle } from "../Modal";
import { GeneralDetails } from "./GeneralDetails";
import { useMutation } from "@tanstack/react-query";
import { useChartRepoValues } from "../../../API/repositories";
import useNavigateWithSearchParams from "../../../hooks/useNavigateWithSearchParams";
import { VersionToInstall } from "./VersionToInstall";
import { isNoneEmptyArray } from "../../../utils";
import { useDiffData } from "../../../API/shared";
import type { InstallChartModalProps } from "../../../data/types";
import apiService from "../../../API/apiService";
import { InstallUpgradeTitle } from "./InstallUpgradeTitle";
import type { LatestChartVersion } from "../../../API/interfaces";
import useNavigateWithSearchParams from "../../../hooks/useNavigateWithSearchParams";
import { isNoneEmptyArray } from "../../../utils";
import Spinner from "../../Spinner";
import Modal, { ModalButtonStyle } from "../Modal";
import { GeneralDetails } from "./GeneralDetails";
import { InstallUpgradeTitle } from "./InstallUpgradeTitle";
import { VersionToInstall } from "./VersionToInstall";
const DefinedValues = lazy(() => import("./DefinedValues"));
const ManifestDiff = lazy(() => import("./ManifestDiff"));

View File

@@ -1,10 +1,10 @@
import { Diff2HtmlUI } from "diff2html/lib/ui/js/diff2html-ui-base";
import hljs from "highlight.js/lib/core";
import yaml from "highlight.js/lib/languages/yaml";
import { useEffect, useRef } from "react";
import Spinner from "../../Spinner";
import { diffConfiguration } from "../../../utils";
import Spinner from "../../Spinner";
hljs.registerLanguage("yaml", yaml);

View File

@@ -1,4 +1,5 @@
import { useEffect, useState } from "react";
import useDebounce from "../../../hooks/useDebounce";
export const UserDefinedValues = ({

View File

@@ -1,8 +1,12 @@
import type { FC } from "react";
import { useMemo, useState } from "react";
import type { GroupBase, SingleValueProps } from "react-select";
import Select, { components } from "react-select";
import { type FC, useMemo, useState } from "react";
import { BsCheck2 } from "react-icons/bs";
import Select, {
type GroupBase,
type SingleValueProps,
type OptionProps,
components,
} from "react-select";
import type { NonEmptyArray } from "../../../data/types";
interface Version {
@@ -92,7 +96,10 @@ export const VersionToInstall: FC<{
}}
value={selectedOption ?? initOpt}
components={{
SingleValue: ({ children, ...props }) => {
SingleValue: ({
children,
...props
}: SpecificSingleValueProps) => {
const OriginalSingleValue =
components.SingleValue as FC<SpecificSingleValueProps>;
@@ -105,7 +112,15 @@ export const VersionToInstall: FC<{
</OriginalSingleValue>
);
},
Option: ({ children, innerProps, data }) => (
Option: ({
children,
innerProps,
data,
}: OptionProps<
VersionOptionType,
false,
GroupBase<VersionOptionType>
>) => (
<div
className={
"flex items-center py-2 pr-2 pl-4 text-green-700 hover:bg-blue-100"

View File

@@ -1,7 +1,7 @@
import { action } from "storybook/actions";
import type { StoryObj, StoryFn, Meta } from "@storybook/react-vite";
import type { ModalAction } from "./Modal";
import Modal, { ModalButtonStyle } from "./Modal";
import { action } from "storybook/actions";
import Modal, { type ModalAction, ModalButtonStyle } from "./Modal";
const meta = {
/* 👇 The title prop is optional.

View File

@@ -1,5 +1,6 @@
import type { PropsWithChildren, ReactNode } from "react";
import { createPortal } from "react-dom";
import Spinner from "../Spinner";
export enum ModalButtonStyle {

View File

@@ -1,4 +1,5 @@
import type { Meta } from "@storybook/react-vite";
import ChartViewer from "./ChartViewer";
//👇 This default export determines where your story goes in the story list

View File

@@ -1,4 +1,5 @@
import { useState } from "react";
import type { Chart } from "../../data/types";
import { InstallRepoChartModal } from "../modal/InstallChartModal/InstallRepoChartModal";

View File

@@ -1,4 +1,5 @@
import type { StoryFn, Meta } from "@storybook/react-vite";
import RepositoriesList from "./RepositoriesList";
const meta = {

View File

@@ -1,6 +1,6 @@
import AddRepositoryModal from "../modal/AddRepositoryModal";
import type { Repository } from "../../data/types";
import useCustomSearchParams from "../../hooks/useCustomSearchParams";
import AddRepositoryModal from "../modal/AddRepositoryModal";
type RepositoriesListProps = {
selectedRepository: Repository | undefined;

View File

@@ -1,4 +1,5 @@
import type { StoryFn, Meta } from "@storybook/react-vite";
import RepositoryViewer from "./RepositoryViewer";
const meta = {

View File

@@ -1,13 +1,15 @@
import { BsTrash3, BsArrowRepeat } from "react-icons/bs";
import type { Chart, Repository } from "../../data/types";
import ChartViewer from "./ChartViewer";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import apiService from "../../API/apiService";
import Spinner from "../Spinner";
import { useUpdateRepo } from "../../API/repositories";
import { useEffect, useMemo, useState } from "react";
import { BsTrash3, BsArrowRepeat } from "react-icons/bs";
import { useNavigate } from "react-router";
import apiService from "../../API/apiService";
import { useUpdateRepo } from "../../API/repositories";
import { useAppContext } from "../../context/AppContext";
import type { Chart, Repository } from "../../data/types";
import Spinner from "../Spinner";
import ChartViewer from "./ChartViewer";
type RepositoryViewerProps = {
repository: Repository | undefined;
@@ -40,8 +42,6 @@ function RepositoryViewer({ repository }: RepositoryViewerProps) {
});
const removeRepository = async () => {
//this is expected
//eslint-disable-next-line no-alert
if (confirm("Confirm removing repository?")) {
try {
setIsRemove(true);

View File

@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from "react";
import { type UseQueryResult, useMutation } from "@tanstack/react-query";
import { Diff2HtmlUI } from "diff2html/lib/ui/js/diff2html-ui-slim.js";
import { useEffect, useRef, useState } from "react";
import {
BsPencil,
BsTrash3,
@@ -9,9 +9,9 @@ import {
BsArrowUp,
BsCheckCircle,
} from "react-icons/bs";
import type { ReleaseRevision } from "../../data/types";
import StatusLabel, { DeploymentStatus } from "../common/StatusLabel";
import { useNavigate, useParams, useSearchParams } from "react-router";
import apiService from "../../API/apiService";
import {
useGetReleaseInfoByType,
useGetLatestVersion,
@@ -19,19 +19,18 @@ import {
useRollbackRelease,
useTestRelease,
} from "../../API/releases";
import RevisionDiff from "./RevisionDiff";
import RevisionResource from "./RevisionResource";
import Tabs from "../Tabs";
import { type UseQueryResult, useMutation } from "@tanstack/react-query";
import type { ReleaseRevision } from "../../data/types";
import useAlertError from "../../hooks/useAlertError";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import { diffConfiguration, isNewerVersion } from "../../utils";
import Button from "../Button";
import StatusLabel, { DeploymentStatus } from "../common/StatusLabel";
import { InstallReleaseChartModal } from "../modal/InstallChartModal/InstallReleaseChartModal";
import Modal, { ModalButtonStyle } from "../modal/Modal";
import Spinner from "../Spinner";
import useAlertError from "../../hooks/useAlertError";
import Button from "../Button";
import { InstallReleaseChartModal } from "../modal/InstallChartModal/InstallReleaseChartModal";
import { diffConfiguration, isNewerVersion } from "../../utils";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import apiService from "../../API/apiService";
import Tabs from "../Tabs";
import RevisionDiff from "./RevisionDiff";
import RevisionResource from "./RevisionResource";
type RevisionTagProps = {
caption: string;

View File

@@ -1,14 +1,14 @@
import type { ChangeEvent } from "react";
import { useMemo, useState, useRef, useEffect } from "react";
import { Diff2HtmlUI } from "diff2html/lib/ui/js/diff2html-ui-slim.js";
import { useGetReleaseInfoByType } from "../../API/releases";
import { useParams } from "react-router";
import useCustomSearchParams from "../../hooks/useCustomSearchParams";
import parse from "html-react-parser";
import hljs from "highlight.js/lib/core";
import yaml from "highlight.js/lib/languages/yaml";
import Spinner from "../Spinner";
import parse from "html-react-parser";
import { type ChangeEvent, useMemo, useState, useRef, useEffect } from "react";
import { useParams } from "react-router";
import { useGetReleaseInfoByType } from "../../API/releases";
import useCustomSearchParams from "../../hooks/useCustomSearchParams";
import { diffConfiguration } from "../../utils";
import Spinner from "../Spinner";
hljs.registerLanguage("yaml", yaml);
@@ -39,7 +39,7 @@ function RevisionDiff({
"user-defined": userDefinedValue,
} = searchParams;
//@ts-ignore
//@ts-expect-error useRef need to find elegant way for it
const diffElement = useRef<HTMLElement>({});
const handleChanged = (e: ChangeEvent<HTMLInputElement>) => {
@@ -136,7 +136,7 @@ function RevisionDiff({
return (
<div>
<div className="mb-3 flex w-full flex-row items-center justify-between rounded-sm border border-gray-200 border-revision bg-white p-2">
<div className="mb-3 flex w-full flex-row items-center justify-between rounded-sm border border-revision bg-white p-2">
<div className="flex items-center">
<input
checked={viewMode === "view"}
@@ -226,7 +226,7 @@ function RevisionDiff({
)}
<div
className="relative w-full bg-white font-sf-mono leading-5"
//@ts-ignore
//@ts-expect-error ref
ref={diffElement}
></div>
</div>

View File

@@ -1,18 +1,21 @@
import { useMemo, useState } from "react";
import { useParams } from "react-router";
import hljs from "highlight.js/lib/core";
import yaml from "highlight.js/lib/languages/yaml";
import { useMemo, useState } from "react";
import { RiExternalLinkLine } from "react-icons/ri";
import Drawer from "react-modern-drawer";
import { useParams } from "react-router";
import type { StructuredResources } from "../../API/releases";
import { useGetResourceDescription, useGetResources } from "../../API/releases";
import {
type StructuredResources,
useGetResourceDescription,
useGetResources,
} from "../../API/releases";
import closeIcon from "../../assets/close.png";
import Drawer from "react-modern-drawer";
import "react-modern-drawer/dist/index.css";
import Button from "../Button";
import Badge, { getBadgeType } from "../Badge";
import Button from "../Button";
import Spinner from "../Spinner";
import { Troubleshoot } from "../Troubleshoot";

View File

@@ -1,12 +1,12 @@
import { compare } from "compare-versions";
import { DateTime } from "luxon";
import { BsArrowDownRight, BsArrowUpRight } from "react-icons/bs";
import { useParams } from "react-router";
import { compare } from "compare-versions";
import type { ReleaseRevision } from "../../data/types";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import { getAge } from "../../timeUtils";
import StatusLabel from "../common/StatusLabel";
import useNavigateWithSearchParams from "../../hooks/useNavigateWithSearchParams";
import { DateTime } from "luxon";
type RevisionsListProps = {
releaseRevisions: ReleaseRevision[];

View File

@@ -1,5 +1,4 @@
import type { ReactNode } from "react";
import { createContext, useState, useContext } from "react";
import { type ReactNode, createContext, useState, useContext } from "react";
export interface AppContextData {
selectedRepo: string;

View File

@@ -1,4 +1,5 @@
import { useContext } from "react";
import { ErrorModalContext } from "../context/ErrorModalContext";
function useAlertError() {

View File

@@ -4,6 +4,7 @@ import {
useNavigate,
useParams,
} from "react-router";
import { useAppContext } from "../context/AppContext";
const useNavigateWithSearchParams = () => {

View File

@@ -1,19 +1,20 @@
import { useLocation } from "react-router";
import LogoHeader from "../assets/logo-header.svg";
import DropDown from "../components/common/DropDown";
import WatcherIcon from "../assets/k8s-watcher.svg";
import ShutDownButton from "../components/ShutDownButton";
import { useEffect, useEffectEvent } from "react";
import {
BsArrowRepeat,
BsBoxArrowUpRight,
BsBraces,
BsGithub,
} from "react-icons/bs";
import { useGetApplicationStatus } from "../API/other";
import LinkWithSearchParams from "../components/LinkWithSearchParams";
import { useLocation } from "react-router";
import apiService from "../API/apiService";
import { useGetApplicationStatus } from "../API/other";
import WatcherIcon from "../assets/k8s-watcher.svg";
import LogoHeader from "../assets/logo-header.svg";
import DropDown from "../components/common/DropDown";
import LinkWithSearchParams from "../components/LinkWithSearchParams";
import ShutDownButton from "../components/ShutDownButton";
import { useAppContext } from "../context/AppContext";
import { useEffect, useEffectEvent } from "react";
import { isNewerVersion } from "../utils";
export default function Header() {

View File

@@ -1,7 +1,9 @@
import { initThemeMode } from "flowbite-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { ThemeInit } from "../.flowbite-react/init";
import App from "./App";
import "./index.css";

View File

@@ -1,4 +1,5 @@
import SwaggerUI from "swagger-ui-react";
import "swagger-ui-react/swagger-ui.css";
import openapi from "../../public/openapi.json";

View File

@@ -1,13 +1,14 @@
import { useEffect, useEffectEvent, useMemo, useState } from "react";
import { useParams, useNavigate } from "react-router";
import { useGetInstalledReleases } from "../API/releases";
import ClustersList from "../components/ClustersList";
import InstalledPackagesHeader from "../components/InstalledPackages/InstalledPackagesHeader";
import InstalledPackagesList from "../components/InstalledPackages/InstalledPackagesList";
import ClustersList from "../components/ClustersList";
import { useGetInstalledReleases } from "../API/releases";
import { useEffect, useEffectEvent, useMemo, useState } from "react";
import Spinner from "../components/Spinner";
import useAlertError from "../hooks/useAlertError";
import { useParams, useNavigate } from "react-router";
import useCustomSearchParams from "../hooks/useCustomSearchParams";
import type { Release } from "../data/types";
import useAlertError from "../hooks/useAlertError";
import useCustomSearchParams from "../hooks/useCustomSearchParams";
function Installed() {
const { searchParamsObject } = useCustomSearchParams();

View File

@@ -1,11 +1,11 @@
import { useMemo, useEffect, useCallback } from "react";
import { type NavigateOptions, useParams } from "react-router";
import { useGetRepositories } from "../API/repositories";
import RepositoriesList from "../components/repository/RepositoriesList";
import RepositoryViewer from "../components/repository/RepositoryViewer";
import type { Repository } from "../data/types";
import { useGetRepositories } from "../API/repositories";
import { type NavigateOptions, useParams } from "react-router";
import { useAppContext } from "../context/AppContext";
import type { Repository } from "../data/types";
import useNavigateWithSearchParams from "../hooks/useNavigateWithSearchParams";
function RepositoryPage() {

View File

@@ -1,10 +1,11 @@
import { useQuery } from "@tanstack/react-query";
import { useMemo, Suspense, lazy } from "react";
import { useParams } from "react-router";
import RevisionsList from "../components/revision/RevisionsList";
import type { ReleaseRevision } from "../data/types";
import { useQuery } from "@tanstack/react-query";
import apiService from "../API/apiService";
import RevisionsList from "../components/revision/RevisionsList";
import Spinner from "../components/Spinner";
import type { ReleaseRevision } from "../data/types";
const RevisionDetails = lazy(
() => import("../components/revision/RevisionDetails")

View File

@@ -1,5 +1,9 @@
import type { DateTimeMaybeValid } from "luxon";
import { DateTime, type DurationLikeObject } from "luxon";
import {
DateTime,
type DurationLikeObject,
type DateTimeMaybeValid,
} from "luxon";
import type { ReleaseRevision } from "./data/types";
export function getAge(obj1: ReleaseRevision, obj2?: ReleaseRevision) {

View File

@@ -1,5 +1,5 @@
import type { Diff2HtmlUIConfig } from "diff2html/lib/ui/js/diff2html-ui-base";
import type { NonEmptyArray } from "./data/types";
import { type Diff2HtmlUIConfig } from "diff2html/lib/ui/js/diff2html-ui-base";
import { type NonEmptyArray } from "./data/types";
export const isNewerVersion = (oldVer: string, newVer: string) => {
if (oldVer && oldVer[0] === "v") {

View File

@@ -1 +1,20 @@
/// <reference types="vite/client" />
interface Window {
heap?: {
push: (args: unknown[]) => void;
appid?: string;
config?: Record<string, unknown>;
track: (name: string, props?: Record<string, unknown>) => void;
addEventProperties: (props: Record<string, unknown>) => void;
[key: string]: unknown;
};
DD_RUM?: {
q: unknown[];
onReady: (callback: () => void) => void;
init: (options: Record<string, unknown>) => void;
};
}
declare const heap: NonNullable<Window["heap"]>;
declare const DD_RUM: NonNullable<Window["DD_RUM"]>;

View File

@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"allowJs": false
},
"include": [
"src",
"public/static",
".flowbite-react/**/*",
".storybook/**/*.ts",
"public/analytics.js",
"cypress"
]
}

View File

@@ -0,0 +1,32 @@
{
"compilerOptions": {
/* Basic Options */
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"useDefineForClassFields": true,
"jsx": "react-jsx",
/* Strictness */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
/* Modern Module Handling */
"verbatimModuleSyntax": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
/* Build & Performance */
"composite": true,
"incremental": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"noEmit": true
}
}

View File

@@ -1,27 +1,7 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src",
"public/static",
".storybook/**/*.ts",
"public/analytics.js",
"cypress"
],
"references": [{ "path": "./tsconfig.node.json" }]
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -1,11 +1,8 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"strict": true
"module": "NodeNext",
"moduleResolution": "NodeNext"
},
"include": ["vite.config.ts", "cypress.config.ts"]
}

File diff suppressed because it is too large Load Diff