Bladeren bron

auto fix eslint errors where possible (#4673)

ianedwards 2 jaren geleden
bovenliggende
commit
67e5ccb846
100 gewijzigde bestanden met toevoegingen van 638 en 700 verwijderingen
  1. 56 106
      dashboard/react-table.d.ts
  2. 3 3
      dashboard/src/assets/GoogleIcon.tsx
  3. 2 2
      dashboard/src/components/AzureCredentialForm.tsx
  4. 2 2
      dashboard/src/components/Breadcrumb.tsx
  5. 1 1
      dashboard/src/components/Button.tsx
  6. 2 2
      dashboard/src/components/CopyToClipboard.tsx
  7. 3 3
      dashboard/src/components/CredentialsForm.tsx
  8. 1 1
      dashboard/src/components/DynamicLink.tsx
  9. 5 5
      dashboard/src/components/ExpandableResource.tsx
  10. 2 2
      dashboard/src/components/GCPCredentialsForm.tsx
  11. 12 12
      dashboard/src/components/GCPProvisionerSettings.tsx
  12. 2 2
      dashboard/src/components/LogQueryModeSelectionToggle.tsx
  13. 4 4
      dashboard/src/components/MultiSaveButton.tsx
  14. 1 1
      dashboard/src/components/OldPlaceholder.tsx
  15. 5 5
      dashboard/src/components/OldTable.tsx
  16. 1 1
      dashboard/src/components/Placeholder.tsx
  17. 17 17
      dashboard/src/components/ProvisionerStatus.tsx
  18. 3 3
      dashboard/src/components/RadioSelector.tsx
  19. 4 4
      dashboard/src/components/ResourceTab.tsx
  20. 2 2
      dashboard/src/components/SearchBar.tsx
  21. 11 13
      dashboard/src/components/Selector.tsx
  22. 1 1
      dashboard/src/components/TitleSection.tsx
  23. 1 1
      dashboard/src/components/date-time-picker/DateTimePicker.tsx
  24. 5 5
      dashboard/src/components/form-components/CheckboxList.tsx
  25. 1 1
      dashboard/src/components/form-components/Heading.tsx
  26. 1 1
      dashboard/src/components/form-components/Helper.tsx
  27. 3 3
      dashboard/src/components/form-components/InputRow.tsx
  28. 17 17
      dashboard/src/components/form-components/KeyValueArray.tsx
  29. 3 3
      dashboard/src/components/form-components/SelectRow.tsx
  30. 1 1
      dashboard/src/components/form-components/TextArea.tsx
  31. 2 1
      dashboard/src/components/form-components/UploadArea.tsx
  32. 15 17
      dashboard/src/components/image-selector/ImageList.tsx
  33. 10 11
      dashboard/src/components/image-selector/ImageSelector.tsx
  34. 8 8
      dashboard/src/components/image-selector/TagList.tsx
  35. 10 10
      dashboard/src/components/porter-form/FormDebugger.tsx
  36. 18 18
      dashboard/src/components/porter-form/PorterForm.tsx
  37. 21 21
      dashboard/src/components/porter-form/PorterFormContextProvider.tsx
  38. 3 3
      dashboard/src/components/porter-form/PorterFormWrapper.tsx
  39. 3 3
      dashboard/src/components/porter-form/field-components/ArrayInput.tsx
  40. 5 5
      dashboard/src/components/porter-form/field-components/Checkbox.tsx
  41. 1 1
      dashboard/src/components/porter-form/field-components/CronInput.tsx
  42. 4 4
      dashboard/src/components/porter-form/field-components/Dictionary.tsx
  43. 3 3
      dashboard/src/components/porter-form/field-components/DictionaryArray.tsx
  44. 3 3
      dashboard/src/components/porter-form/field-components/Input.tsx
  45. 38 40
      dashboard/src/components/porter-form/field-components/KeyValueArray.tsx
  46. 2 2
      dashboard/src/components/porter-form/field-components/MultiSelect.tsx
  47. 6 7
      dashboard/src/components/porter-form/field-components/ResourceList.tsx
  48. 3 3
      dashboard/src/components/porter-form/field-components/Select.tsx
  49. 1 1
      dashboard/src/components/porter-form/field-components/ServiceIPList.tsx
  50. 1 1
      dashboard/src/components/porter-form/field-components/ServiceRow.tsx
  51. 1 1
      dashboard/src/components/porter-form/field-components/TextAreaInput.tsx
  52. 2 2
      dashboard/src/components/porter-form/field-components/UrlLink.tsx
  53. 1 1
      dashboard/src/components/porter-form/field-components/VeleroForm.tsx
  54. 6 6
      dashboard/src/components/porter-form/hooks/useFormField.tsx
  55. 5 5
      dashboard/src/components/porter-form/utils.ts
  56. 3 3
      dashboard/src/components/porter/ExpandableSection.tsx
  57. 6 6
      dashboard/src/components/porter/Filter.tsx
  58. 6 6
      dashboard/src/components/porter/InputSlider.tsx
  59. 2 2
      dashboard/src/components/porter/Pagination.tsx
  60. 1 1
      dashboard/src/components/porter/SearchBar.tsx
  61. 7 7
      dashboard/src/components/repo-selector/ActionConfEditor.tsx
  62. 8 9
      dashboard/src/components/repo-selector/ActionDetails.tsx
  63. 3 3
      dashboard/src/components/repo-selector/BranchList.tsx
  64. 14 18
      dashboard/src/components/repo-selector/BuildpackSelection.tsx
  65. 50 50
      dashboard/src/components/repo-selector/ContentsList.tsx
  66. 8 8
      dashboard/src/components/repo-selector/RepoList.tsx
  67. 2 2
      dashboard/src/main/CurrentError.tsx
  68. 15 15
      dashboard/src/main/auth/ResetPasswordFinalize.tsx
  69. 7 7
      dashboard/src/main/auth/ResetPasswordInit.tsx
  70. 14 14
      dashboard/src/main/home/ModalHandler.tsx
  71. 4 4
      dashboard/src/main/home/NoClusterPlaceholder.tsx
  72. 8 8
      dashboard/src/main/home/add-on-dashboard/ConfigureTemplate.tsx
  73. 4 4
      dashboard/src/main/home/add-on-dashboard/ExpandedTemplate.tsx
  74. 7 7
      dashboard/src/main/home/app-dashboard/app-view/tabs/Webhooks.tsx
  75. 2 2
      dashboard/src/main/home/app-dashboard/build-settings/BranchSelector.tsx
  76. 2 2
      dashboard/src/main/home/app-dashboard/build-settings/ProviderSelector.tsx
  77. 7 7
      dashboard/src/main/home/app-dashboard/build-settings/RepositorySelector.tsx
  78. 2 2
      dashboard/src/main/home/app-dashboard/expanded-app/DeleteApplicationModal.tsx
  79. 4 4
      dashboard/src/main/home/app-dashboard/expanded-app/GHABanner.tsx
  80. 8 8
      dashboard/src/main/home/app-dashboard/expanded-app/metrics/AreaChart.tsx
  81. 1 1
      dashboard/src/main/home/app-dashboard/expanded-app/metrics/MetricsChart.tsx
  82. 3 3
      dashboard/src/main/home/app-dashboard/expanded-app/metrics/StackedAreaChart.tsx
  83. 1 1
      dashboard/src/main/home/app-dashboard/expanded-app/metrics/StatusCodeDataLegend.tsx
  84. 1 1
      dashboard/src/main/home/app-dashboard/expanded-app/metrics/themes/area.tsx
  85. 1 1
      dashboard/src/main/home/app-dashboard/types/buildpack.ts
  86. 1 1
      dashboard/src/main/home/app-dashboard/types/porterApp.ts
  87. 2 2
      dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/AddCustomBuildpack.tsx
  88. 4 4
      dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackCard.tsx
  89. 3 3
      dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackConfigurationModal.tsx
  90. 4 4
      dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackList.tsx
  91. 1 1
      dashboard/src/main/home/app-dashboard/validate-apply/helm/HelmOverrides.tsx
  92. 9 9
      dashboard/src/main/home/cluster-dashboard/DashboardRouter.tsx
  93. 10 10
      dashboard/src/main/home/cluster-dashboard/NamespaceSelector.tsx
  94. 3 3
      dashboard/src/main/home/cluster-dashboard/SortSelector.tsx
  95. 1 1
      dashboard/src/main/home/cluster-dashboard/TagFilter.tsx
  96. 3 3
      dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx
  97. 6 6
      dashboard/src/main/home/cluster-dashboard/chart/Chart.tsx
  98. 16 16
      dashboard/src/main/home/cluster-dashboard/chart/ChartList.tsx
  99. 14 14
      dashboard/src/main/home/cluster-dashboard/chart/JobRunTable.tsx
  100. 16 16
      dashboard/src/main/home/cluster-dashboard/dashboard/ClusterSettings.tsx

+ 56 - 106
dashboard/react-table.d.ts

@@ -1,121 +1,71 @@
 import {
-  UseColumnOrderInstanceProps,
-  UseColumnOrderState,
-  UseExpandedHooks,
-  UseExpandedInstanceProps,
-  UseExpandedOptions,
-  UseExpandedRowProps,
-  UseExpandedState,
-  UseFiltersColumnOptions,
-  UseFiltersColumnProps,
-  UseFiltersInstanceProps,
-  UseFiltersOptions,
-  UseFiltersState,
-  UseGlobalFiltersColumnOptions,
-  UseGlobalFiltersInstanceProps,
-  UseGlobalFiltersOptions,
-  UseGlobalFiltersState,
-  UseGroupByCellProps,
-  UseGroupByColumnOptions,
-  UseGroupByColumnProps,
-  UseGroupByHooks,
-  UseGroupByInstanceProps,
-  UseGroupByOptions,
-  UseGroupByRowProps,
-  UseGroupByState,
-  UsePaginationInstanceProps,
-  UsePaginationOptions,
-  UsePaginationState,
-  UseResizeColumnsColumnOptions,
-  UseResizeColumnsColumnProps,
-  UseResizeColumnsOptions,
-  UseResizeColumnsState,
-  UseRowSelectHooks,
-  UseRowSelectInstanceProps,
-  UseRowSelectOptions,
-  UseRowSelectRowProps,
-  UseRowSelectState,
-  UseRowStateCellProps,
-  UseRowStateInstanceProps,
-  UseRowStateOptions,
-  UseRowStateRowProps,
-  UseRowStateState,
-  UseSortByColumnOptions,
-  UseSortByColumnProps,
-  UseSortByHooks,
-  UseSortByInstanceProps,
-  UseSortByOptions,
-  UseSortByState,
+  type UseColumnOrderInstanceProps,
+  type UseColumnOrderState,
+  type UseExpandedHooks,
+  type UseExpandedInstanceProps,
+  type UseExpandedOptions,
+  type UseExpandedRowProps,
+  type UseExpandedState,
+  type UseFiltersColumnOptions,
+  type UseFiltersColumnProps,
+  type UseFiltersInstanceProps,
+  type UseFiltersOptions,
+  type UseFiltersState,
+  type UseGlobalFiltersColumnOptions,
+  type UseGlobalFiltersInstanceProps,
+  type UseGlobalFiltersOptions,
+  type UseGlobalFiltersState,
+  type UseGroupByCellProps,
+  type UseGroupByColumnOptions,
+  type UseGroupByColumnProps,
+  type UseGroupByHooks,
+  type UseGroupByInstanceProps,
+  type UseGroupByOptions,
+  type UseGroupByRowProps,
+  type UseGroupByState,
+  type UsePaginationInstanceProps,
+  type UsePaginationOptions,
+  type UsePaginationState,
+  type UseResizeColumnsColumnOptions,
+  type UseResizeColumnsColumnProps,
+  type UseResizeColumnsOptions,
+  type UseResizeColumnsState,
+  type UseRowSelectHooks,
+  type UseRowSelectInstanceProps,
+  type UseRowSelectOptions,
+  type UseRowSelectRowProps,
+  type UseRowSelectState,
+  type UseRowStateCellProps,
+  type UseRowStateInstanceProps,
+  type UseRowStateOptions,
+  type UseRowStateRowProps,
+  type UseRowStateState,
+  type UseSortByColumnOptions,
+  type UseSortByColumnProps,
+  type UseSortByHooks,
+  type UseSortByInstanceProps,
+  type UseSortByOptions,
+  type UseSortByState,
 } from "react-table";
 
 declare module "react-table" {
   // take this file as-is, or comment out the sections that don't apply to your plugin configuration
 
-  export interface TableOptions<
+  export type TableOptions<
     D extends object = {}
-  > extends UseExpandedOptions<D>,
-      UseFiltersOptions<D>,
-      UseGlobalFiltersOptions<D>,
-      UseGroupByOptions<D>,
-      UsePaginationOptions<D>,
-      UseResizeColumnsOptions<D>,
-      UseRowSelectOptions<D>,
-      UseRowStateOptions<D>,
-      UseSortByOptions<D>,
-      // note that having Record here allows you to add anything to the options, this matches the spirit of the
-      // underlying js library, but might be cleaner if it's replaced by a more specific type that matches your
-      // feature set, this is a safe default.
-      Record<string, any> {}
+  > = {} & UseExpandedOptions<D> & UseFiltersOptions<D> & UseGlobalFiltersOptions<D> & UseGroupByOptions<D> & UsePaginationOptions<D> & UseResizeColumnsOptions<D> & UseRowSelectOptions<D> & UseRowStateOptions<D> & UseSortByOptions<D> & Record<string, any>
 
-  export interface Hooks<D extends object = {}>
-    extends UseExpandedHooks<D>,
-      UseGroupByHooks<D>,
-      UseRowSelectHooks<D>,
-      UseSortByHooks<D> {}
+  export type Hooks<D extends object = {}> = {} & UseExpandedHooks<D> & UseGroupByHooks<D> & UseRowSelectHooks<D> & UseSortByHooks<D>
 
-  export interface TableInstance<D extends object = {}>
-    extends UseColumnOrderInstanceProps<D>,
-      UseExpandedInstanceProps<D>,
-      UseFiltersInstanceProps<D>,
-      UseGlobalFiltersInstanceProps<D>,
-      UseGroupByInstanceProps<D>,
-      UsePaginationInstanceProps<D>,
-      UseRowSelectInstanceProps<D>,
-      UseRowStateInstanceProps<D>,
-      UseSortByInstanceProps<D> {}
+  export type TableInstance<D extends object = {}> = {} & UseColumnOrderInstanceProps<D> & UseExpandedInstanceProps<D> & UseFiltersInstanceProps<D> & UseGlobalFiltersInstanceProps<D> & UseGroupByInstanceProps<D> & UsePaginationInstanceProps<D> & UseRowSelectInstanceProps<D> & UseRowStateInstanceProps<D> & UseSortByInstanceProps<D>
 
-  export interface TableState<D extends object = {}>
-    extends UseColumnOrderState<D>,
-      UseExpandedState<D>,
-      UseFiltersState<D>,
-      UseGlobalFiltersState<D>,
-      UseGroupByState<D>,
-      UsePaginationState<D>,
-      UseResizeColumnsState<D>,
-      UseRowSelectState<D>,
-      UseRowStateState<D>,
-      UseSortByState<D> {}
+  export type TableState<D extends object = {}> = {} & UseColumnOrderState<D> & UseExpandedState<D> & UseFiltersState<D> & UseGlobalFiltersState<D> & UseGroupByState<D> & UsePaginationState<D> & UseResizeColumnsState<D> & UseRowSelectState<D> & UseRowStateState<D> & UseSortByState<D>
 
-  export interface ColumnInterface<D extends object = {}>
-    extends UseFiltersColumnOptions<D>,
-      UseGlobalFiltersColumnOptions<D>,
-      UseGroupByColumnOptions<D>,
-      UseResizeColumnsColumnOptions<D>,
-      UseSortByColumnOptions<D> {}
+  export type ColumnInterface<D extends object = {}> = {} & UseFiltersColumnOptions<D> & UseGlobalFiltersColumnOptions<D> & UseGroupByColumnOptions<D> & UseResizeColumnsColumnOptions<D> & UseSortByColumnOptions<D>
 
-  export interface ColumnInstance<D extends object = {}>
-    extends UseFiltersColumnProps<D>,
-      UseGroupByColumnProps<D>,
-      UseResizeColumnsColumnProps<D>,
-      UseSortByColumnProps<D> {}
+  export type ColumnInstance<D extends object = {}> = {} & UseFiltersColumnProps<D> & UseGroupByColumnProps<D> & UseResizeColumnsColumnProps<D> & UseSortByColumnProps<D>
 
-  export interface Cell<D extends object = {}, V = any>
-    extends UseGroupByCellProps<D>,
-      UseRowStateCellProps<D> {}
+  export type Cell<D extends object = {}, V = any> = {} & UseGroupByCellProps<D> & UseRowStateCellProps<D>
 
-  export interface Row<D extends object = {}>
-    extends UseExpandedRowProps<D>,
-      UseGroupByRowProps<D>,
-      UseRowSelectRowProps<D>,
-      UseRowStateRowProps<D> {}
+  export type Row<D extends object = {}> = {} & UseExpandedRowProps<D> & UseGroupByRowProps<D> & UseRowSelectRowProps<D> & UseRowStateRowProps<D>
 }

+ 3 - 3
dashboard/src/assets/GoogleIcon.tsx

@@ -65,9 +65,9 @@ export default class GHIcon extends Component<PropsType, StateType> {
         <g
           id="Google-Button"
           stroke="none"
-          stroke-width="1"
+          strokeWidth="1"
           fill="none"
-          fill-rule="evenodd"
+          fillRule="evenodd"
         >
           <g id="9-PATCH" transform="translate(-608.000000, -160.000000)"></g>
           <g
@@ -80,7 +80,7 @@ export default class GHIcon extends Component<PropsType, StateType> {
               filter="url(#filter-1)"
             >
               <g id="button-bg">
-                <use fill="#FFFFFF" fill-rule="evenodd"></use>
+                <use fill="#FFFFFF" fillRule="evenodd"></use>
                 <use fill="none"></use>
                 <use fill="none"></use>
                 <use fill="none"></use>

+ 2 - 2
dashboard/src/components/AzureCredentialForm.tsx

@@ -106,7 +106,7 @@ const AzureCredentialForm: React.FC<Props> = ({ goBack, proceed }) => {
                 Follow our <Link to="https://docs.porter.run/provision/provisioning-on-azure" target="_blank">documentation</Link> to create your service principal and prepare your subscription for use with Porter.
               </Text>
               <Spacer y={1} />
-              <Button onClick={() => setCurrentStep(1)}>
+              <Button onClick={() => { setCurrentStep(1); }}>
                 Continue
               </Button>
             </>,
@@ -162,7 +162,7 @@ const AzureCredentialForm: React.FC<Props> = ({ goBack, proceed }) => {
                 />
               <Spacer y={1} />
               <Container row>
-                  <Button onClick={() => setCurrentStep(0)} color="#222222">Back</Button>
+                  <Button onClick={() => { setCurrentStep(0); }} color="#222222">Back</Button>
                   <Spacer inline x={0.5} />
                   <Button
                     onClick={saveCredentials}

+ 2 - 2
dashboard/src/components/Breadcrumb.tsx

@@ -5,7 +5,7 @@ import styled from "styled-components";
 
 type Props = {
   currentStep: string;
-  steps: { value: string; label: string }[];
+  steps: Array<{ value: string; label: string }>;
   onClickStep?: (step: string) => void;
 };
 
@@ -17,7 +17,7 @@ const Breadcrumb: React.FC<Props> = ({ currentStep, steps, onClickStep }) => {
           <Fragment key={i}>
             <Crumb
               bold={currentStep === step.value}
-              onClick={() => onClickStep && onClickStep(step.value)}
+              onClick={() => { onClickStep && onClickStep(step.value); }}
             >
               {step.label}
             </Crumb>

+ 1 - 1
dashboard/src/components/Button.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
   disabled?: boolean;
   children: React.ReactNode;
   onClick: () => void;

+ 2 - 2
dashboard/src/components/CopyToClipboard.tsx

@@ -1,6 +1,6 @@
 // import ClipboardJS from "clipboard";
 import ClipboardJS from "clipboard";
-import React, { Component, RefObject } from "react";
+import React, { Component, type RefObject } from "react";
 import Tooltip from "@material-ui/core/Tooltip";
 import styled from "styled-components";
 
@@ -72,7 +72,7 @@ export default class CopyToClipboard extends Component<PropsType, StateType> {
   }
 
   componentWillUnmount() {
-    if (this.state.clipboard && this.state.clipboard.destroy) {
+    if (this.state.clipboard?.destroy) {
       this.state.clipboard.destroy();
     }
   }

+ 3 - 3
dashboard/src/components/CredentialsForm.tsx

@@ -131,7 +131,7 @@ const CredentialsForm: React.FC<Props> = ({
           <Br height="34px" />
           <SaveButton
             disabled={!selectedCredentials && true}
-            onClick={() => proceed(selectedCredentials.aws_arn)}
+            onClick={() => { proceed(selectedCredentials.aws_arn); }}
             clearPosition
             text="Continue"
           />
@@ -143,7 +143,7 @@ const CredentialsForm: React.FC<Props> = ({
         <StyledForm>
           {
             awsCredentials.length > 0 && (
-              <CloseButton onClick={() => setShowCreateForm(false)}>
+              <CloseButton onClick={() => { setShowCreateForm(false); }}>
                 <i className="material-icons">close</i>
               </CloseButton>
             )
@@ -151,7 +151,7 @@ const CredentialsForm: React.FC<Props> = ({
           <InputRow
             type="string"
             value={awsAccessKeyID}
-            setValue={(e: string) => setAWSAccessKeyID(e)}
+            setValue={(e: string) => { setAWSAccessKeyID(e); }}
             label="👤 AWS access ID"
             placeholder="ex: AKIAIOSFODNN7EXAMPLE"
             isRequired

+ 1 - 1
dashboard/src/components/DynamicLink.tsx

@@ -1,5 +1,5 @@
 import React from "react";
-import { Link, LinkProps } from "react-router-dom";
+import { Link, type LinkProps } from "react-router-dom";
 
 const DynamicLink: React.FC<LinkProps> = ({ to, children, hasunderline, ...props }) => {
   // It is a simple element with nothing to link to

+ 5 - 5
dashboard/src/components/ExpandableResource.tsx

@@ -20,12 +20,12 @@ const ExpandableResource: React.FC<Props> = (props) => {
   const { currentCluster, currentProject } = useContext(Context);
 
   const onSave = () => {
-    let projID = currentProject.id;
-    let clusterID = currentCluster.id;
-    let config = button.actions[0].delete.context.config;
+    const projID = currentProject.id;
+    const clusterID = currentCluster.id;
+    const config = button.actions[0].delete.context.config;
 
     // TODO: construct the endpoint scope, right now we're just using release scope
-    let uri = `/api/projects/${projID}/clusters/${clusterID}/namespaces/${resource.metadata.namespace}${button.actions[0].delete.relative_uri}`;
+    const uri = `/api/projects/${projID}/clusters/${clusterID}/namespaces/${resource.metadata.namespace}${button.actions[0].delete.relative_uri}`;
 
     // compute the endpoint using button and target context
     baseApi<
@@ -49,7 +49,7 @@ const ExpandableResource: React.FC<Props> = (props) => {
       {}
     )
       .then((res) => {})
-      .catch((err) => console.log(err));
+      .catch((err) => { console.log(err); });
   };
 
   return (

+ 2 - 2
dashboard/src/components/GCPCredentialsForm.tsx

@@ -41,7 +41,7 @@ const GCPCredentialsForm: React.FC<Props> = ({ goBack, proceed }) => {
     gcpIntegration()
 
   }, [detected])
-  interface FailureState {
+  type FailureState = {
     condition: boolean;
     errorMessage: string;
   }
@@ -167,7 +167,7 @@ const GCPCredentialsForm: React.FC<Props> = ({ goBack, proceed }) => {
             <Text size={16}>Upload service account credentials</Text>
             <Spacer y={1} />
             <UploadArea
-              setValue={(x: string) => handleLoadJSON(x)}
+              setValue={(x: string) => { handleLoadJSON(x); }}
               label="🔒 GCP Key Data (JSON)"
               placeholder="Drag a GCP Service Account JSON here, or click to browse."
               width="100%"

+ 12 - 12
dashboard/src/components/GCPProvisionerSettings.tsx

@@ -1,6 +1,6 @@
 import React, { useEffect, useState, useContext } from "react";
 import styled from "styled-components";
-import { RouteComponentProps, withRouter } from "react-router";
+import { type RouteComponentProps, withRouter } from "react-router";
 
 import { OFState } from "main/home/onboarding/state";
 import api from "shared/api";
@@ -23,7 +23,7 @@ import {
   GKEPreflightValues,
   PreflightCheckRequest
 } from "@porter-dev/api-contracts";
-import { ClusterType } from "shared/types";
+import { type ClusterType } from "shared/types";
 import Button from "./porter/Button";
 import Error from "./porter/Error";
 import Spacer from "./porter/Spacer";
@@ -214,7 +214,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
         {
           < Heading >
             <ExpandHeader
-              onClick={() => setIsExpanded(!isExpanded)}
+              onClick={() => { setIsExpanded(!isExpanded); }}
               isExpanded={isExpanded}
             >
               <i className="material-icons">arrow_drop_down</i>
@@ -254,7 +254,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
                 type="string"
                 disabled={isReadOnly}
                 value={clusterNetworking.cidrRange}
-                setValue={(x: string) => setClusterNetworking(new GKENetwork({ ...clusterNetworking, cidrRange: x }))}
+                setValue={(x: string) => { setClusterNetworking(new GKENetwork({ ...clusterNetworking, cidrRange: x })); }}
                 label="VPC CIDR range"
                 placeholder="ex: 10.78.0.0/16"
               />
@@ -277,7 +277,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
                   type="string"
                   disabled={isReadOnly}
                   value={clusterNetworking.controlPlaneCidr}
-                  setValue={(x: string) => setClusterNetworking(new GKENetwork({ ...clusterNetworking, controlPlaneCidr: x }))}
+                  setValue={(x: string) => { setClusterNetworking(new GKENetwork({ ...clusterNetworking, controlPlaneCidr: x })); }}
                   label="Control Plane CIDR range"
                   placeholder="ex: 10.78.0.0/16"
                 />
@@ -286,7 +286,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
                   type="string"
                   disabled={isReadOnly}
                   value={clusterNetworking.podCidr}
-                  setValue={(x: string) => setClusterNetworking(new GKENetwork({ ...clusterNetworking, podCidr: x }))}
+                  setValue={(x: string) => { setClusterNetworking(new GKENetwork({ ...clusterNetworking, podCidr: x })); }}
                   label="Pod CIDR range"
                   placeholder="ex: 10.78.0.0/16"
                 />
@@ -295,7 +295,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
                   type="string"
                   disabled={isReadOnly}
                   value={clusterNetworking.serviceCidr}
-                  setValue={(x: string) => setClusterNetworking(new GKENetwork({ ...clusterNetworking, serviceCidr: x }))}
+                  setValue={(x: string) => { setClusterNetworking(new GKENetwork({ ...clusterNetworking, serviceCidr: x })); }}
                   label="Service CIDR range"
                   placeholder="ex: 10.78.0.0/16"
                 />
@@ -342,7 +342,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
         nodePoolType: GKENodePoolType.GKE_NODE_POOL_TYPE_SYSTEM
       }),
       new GKENodePool({
-        instanceType: instanceType,
+        instanceType,
         minInstances: 1, // TODO: make these customizable before merging
         maxInstances: 10, // TODO: make these customizable before merging
         nodePoolType: GKENodePoolType.GKE_NODE_POOL_TYPE_APPLICATION
@@ -369,9 +369,9 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
         kindValues: {
           case: "gkeKind",
           value: new GKE({
-            clusterName: clusterName,
+            clusterName,
             clusterVersion: clusterVersion || clusterVersionOptions[0].value,
-            region: region,
+            region,
             network: new GKENetwork({
               cidrRange: clusterNetworking.cidrRange,
               controlPlaneCidr: clusterNetworking.controlPlaneCidr,
@@ -416,7 +416,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
     const data = createClusterObj();
 
     if (props.clusterId) {
-      data["cluster"]["clusterId"] = props.clusterId;
+      data.cluster.clusterId = props.clusterId;
     }
 
     try {
@@ -554,7 +554,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
       // Check if any of the preflight checks has a message
       let hasMessage = false;
       let errors = "Preflight Checks Failed : ";
-      for (let check in preflightDataResp?.data?.Msg.preflight_checks) {
+      for (const check in preflightDataResp?.data?.Msg.preflight_checks) {
         if (preflightDataResp?.data?.Msg.preflight_checks[check]?.message) {
           hasMessage = true;
           errors = errors + check + ", "

+ 2 - 2
dashboard/src/components/LogQueryModeSelectionToggle.tsx

@@ -4,7 +4,7 @@ import time from "assets/time.svg";
 import React from "react";
 import styled from "styled-components";
 
-interface LogQueryModeSelectionToggleProps {
+type LogQueryModeSelectionToggleProps = {
   selectedDate?: Date;
   setSelectedDate: (date?: Date) => void;
 }
@@ -32,7 +32,7 @@ const LogQueryModeSelectionToggle = (
         </ToggleOption>
         <ToggleOption
           nudgeLeft
-          onClick={() => props.setSelectedDate(dayjs().toDate())}
+          onClick={() => { props.setSelectedDate(dayjs().toDate()); }}
           selected={!!props.selectedDate}
         >
           <TimeIcon src={time} selected={!!props.selectedDate} />

+ 4 - 4
dashboard/src/components/MultiSaveButton.tsx

@@ -82,12 +82,12 @@ const MultiSaveButton: React.FC<Props> = (props) => {
     if (isDropdownExpanded) {
       return (
         <>
-          <DropdownOverlay onClick={() => setIsDropdownExpanded(false)} />
+          <DropdownOverlay onClick={() => { setIsDropdownExpanded(false); }} />
           <OptionWrapper
             expandTo={props.expandTo || "right"}
             dropdownWidth="400px"
             dropdownMaxHeight="300px"
-            onClick={() => setIsDropdownExpanded(false)}
+            onClick={() => { setIsDropdownExpanded(false); }}
           >
             {renderOptionList()}
           </OptionWrapper>
@@ -102,7 +102,7 @@ const MultiSaveButton: React.FC<Props> = (props) => {
         <Option
           key={i}
           selected={option.text === originalArray[currOptionIndex]?.text}
-          onClick={() => setCurrOptionIndex(i)}
+          onClick={() => { setCurrOptionIndex(i); }}
           lastItem={i === originalArray.length - 1}
         >
           {option.text}
@@ -133,7 +133,7 @@ const MultiSaveButton: React.FC<Props> = (props) => {
         <DropdownButton
           disabled={props.disabled}
           color={props.color || "#5561C0"}
-          onClick={() => setIsDropdownExpanded(!isDropdownExpanded)}
+          onClick={() => { setIsDropdownExpanded(!isDropdownExpanded); }}
         >
           <i className="material-icons expand-icon">
             {isDropdownExpanded ? "expand_less" : "expand_more"}

+ 1 - 1
dashboard/src/components/OldPlaceholder.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
   height?: string;
   minHeight?: string;
   children: React.ReactNode;

+ 5 - 5
dashboard/src/components/OldTable.tsx

@@ -1,8 +1,8 @@
 import React, { useEffect, useState } from "react";
 import styled from "styled-components";
 import {
-  Column,
-  Row,
+  type Column,
+  type Row,
   useGlobalFilter,
   usePagination,
   useTable,
@@ -51,7 +51,7 @@ const GlobalFilter: React.FunctionComponent<any> = ({
 };
 
 export type TableProps = {
-  columns: Column<any>[];
+  columns: Array<Column<any>>;
   data: any[];
   onRowClick?: (row: Row) => void;
   isLoading: boolean;
@@ -158,7 +158,7 @@ const Table: React.FC<TableProps> = ({
               disableHover={disableHover}
               {...row.getRowProps()}
               enablePointer={!!onRowClick}
-              onClick={() => onRowClick && onRowClick(row)}
+              onClick={() => { onRowClick && onRowClick(row); }}
               selected={false}
             >
               {/* TODO: This is actually broken, not sure why but we need the width to be properly setted, this is a temporary solution */}
@@ -247,7 +247,7 @@ const Table: React.FC<TableProps> = ({
               {"<"}
             </PaginationAction>
             <PageCounter>
-              {currentPageIndex + 1} of {pageCount ? pageCount : pageCount + 1}
+              {currentPageIndex + 1} of {pageCount || pageCount + 1}
             </PageCounter>
             <PaginationAction disabled={!canNextPage} onClick={() => {
               nextPage();

+ 1 - 1
dashboard/src/components/Placeholder.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
   height?: string;
   minHeight?: string;
   children: React.ReactNode;

+ 17 - 17
dashboard/src/components/ProvisionerStatus.tsx

@@ -3,13 +3,13 @@ import { integrationList } from "shared/common";
 import styled, { keyframes } from "styled-components";
 import { readableDate } from "shared/string_utils";
 import {
-  Infrastructure,
+  type Infrastructure,
   KindMap,
-  Operation,
-  OperationStatus,
-  OperationType,
-  TFResourceState,
-  TFState,
+  type Operation,
+  type OperationStatus,
+  type OperationType,
+  type TFResourceState,
+  type TFState,
 } from "shared/types";
 import api from "shared/api";
 import Placeholder from "./OldPlaceholder";
@@ -27,7 +27,7 @@ type Props = {
   set_max_width?: boolean;
 };
 
-const nameMap: { [key: string]: string } = {
+const nameMap: Record<string, string> = {
   eks: "Elastic Kubernetes Service (EKS)",
   ecr: "Elastic Container Registry (ECR)",
   doks: "DigitalOcean Kubernetes Service (DOKS)",
@@ -132,7 +132,7 @@ const V1InfraObject: React.FC<V1InfraObjectProps> = ({
   };
 
   const renderErrorSection = () => {
-    let errors: string[] = [];
+    const errors: string[] = [];
     if (infra.status == "destroyed" || infra.status == "deleted") {
       errors.push("This infrastructure was destroyed.");
     }
@@ -154,7 +154,7 @@ const V1InfraObject: React.FC<V1InfraObjectProps> = ({
 
   const renderExpandedContents = () => {
     if (isExpanded) {
-      let errors: string[] = [];
+      const errors: string[] = [];
 
       if (infra.status == "destroyed" || infra.status == "deleted") {
         errors.push("This infrastructure was destroyed.");
@@ -260,7 +260,7 @@ const V2InfraObject: React.FC<V2InfraObjectProps> = ({
         "<token>",
         {},
         {
-          project_id: project_id,
+          project_id,
           infra_id: infra.id,
         }
       )
@@ -281,12 +281,12 @@ const V2InfraObject: React.FC<V2InfraObjectProps> = ({
         "<token>",
         {},
         {
-          project_id: project_id,
+          project_id,
           infra_id: infra.id,
         }
       )
       .then(({ data }) => {
-        let infra = data as Infrastructure;
+        const infra = data as Infrastructure;
 
         if (completed && infra.latest_operation) {
           if (errored) {
@@ -428,7 +428,7 @@ export const OperationDetails: React.FunctionComponent<OperationDetailsProps> =
   const { newWebsocket, openWebsocket, closeWebsocket } = useWebsockets();
 
   const parseOperationWebsocketEvent = (evt: MessageEvent) => {
-    let { status, resource_id, error } = JSON.parse(evt.data);
+    const { status, resource_id, error } = JSON.parse(evt.data);
 
     if (status == "OPERATION_COMPLETED") {
       // if the operation is completed, call the completed handler
@@ -436,7 +436,7 @@ export const OperationDetails: React.FunctionComponent<OperationDetailsProps> =
     } else if (status && resource_id) {
       // if the status and resource_id are defined, add this to the infra state
       setInfraState((curr) => {
-        let currCopy: TFState = {
+        const currCopy: TFState = {
           last_updated: curr.last_updated,
           operation_id: curr.operation_id,
           status: curr.status,
@@ -449,8 +449,8 @@ export const OperationDetails: React.FunctionComponent<OperationDetailsProps> =
         } else {
           currCopy.resources[resource_id] = {
             id: resource_id,
-            status: status,
-            error: error,
+            status,
+            error,
           };
         }
 
@@ -460,7 +460,7 @@ export const OperationDetails: React.FunctionComponent<OperationDetailsProps> =
   };
 
   const setupOperationWebsocket = (websocketID: string) => {
-    let apiPath = `/api/projects/${currentProject.id}/infras/${infra.id}/operations/${infra.latest_operation.id}/state`;
+    const apiPath = `/api/projects/${currentProject.id}/infras/${infra.id}/operations/${infra.latest_operation.id}/state`;
 
     const wsConfig = {
       onopen: () => {

+ 3 - 3
dashboard/src/components/RadioSelector.tsx

@@ -4,7 +4,7 @@ import styled from "styled-components";
 type PropsType = {
   selected: string;
   setSelected: (x: string) => void;
-  options: { value: string; label: string }[];
+  options: Array<{ value: string; label: string }>;
 };
 
 type StateType = {};
@@ -15,11 +15,11 @@ export default class RadioSelector extends Component<PropsType, StateType> {
       <StyledRadioSelector>
         {this.props.options.map(
           (option: { label: string; value: string }, i: number) => {
-            let selected = option.value === this.props.selected;
+            const selected = option.value === this.props.selected;
             return (
               <RadioRow
                 key={option.value}
-                onClick={() => this.props.setSelected(option.value)}
+                onClick={() => { this.props.setSelected(option.value); }}
               >
                 <Indicator selected={selected}>
                   {selected && <Circle />}

+ 4 - 4
dashboard/src/components/ResourceTab.tsx

@@ -59,7 +59,7 @@ export default class ResourceTab extends Component<PropsType, StateType> {
   };
 
   getStatusText = () => {
-    let { status } = this.props;
+    const { status } = this.props;
     if (status.available && status.total) {
       return `${status.available}/${status.total}`;
     } else if (status.label) {
@@ -68,7 +68,7 @@ export default class ResourceTab extends Component<PropsType, StateType> {
   };
 
   renderStatus = () => {
-    let { status } = this.props;
+    const { status } = this.props;
     if (status) {
       return (
         <Status>
@@ -87,7 +87,7 @@ export default class ResourceTab extends Component<PropsType, StateType> {
   };
 
   render() {
-    let {
+    const {
       label,
       name,
       children,
@@ -100,7 +100,7 @@ export default class ResourceTab extends Component<PropsType, StateType> {
     return (
       <StyledResourceTab
         isLast={isLast}
-        onClick={() => handleClick && handleClick()}
+        onClick={() => { handleClick && handleClick(); }}
         roundAllCorners={roundAllCorners}
       >
         <ResourceHeader

+ 2 - 2
dashboard/src/components/SearchBar.tsx

@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
 import Button from "./Button";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
   setSearchFilter: (x: string) => void;
   disabled: boolean;
   prompt?: string;
@@ -47,7 +47,7 @@ const SearchBar: React.FC<Props> = ({
       </SearchBarWrapper>
       <ButtonWrapper disabled={disabled}>
         <Button
-          onClick={() => setSearchFilter(searchInput)}
+          onClick={() => { setSearchFilter(searchInput); }}
           disabled={disabled}
         >
           Search

+ 11 - 13
dashboard/src/components/Selector.tsx

@@ -6,7 +6,7 @@ import Loading from "./Loading";
 export type SelectorPropsType<T> = {
   activeValue: T;
   refreshOptions?: () => void;
-  options: { value: T; label: string; icon?: any }[];
+  options: Array<{ value: T; label: string; icon?: any }>;
   addButton?: boolean;
   setActiveValue: (x: T) => void;
   width: string;
@@ -46,11 +46,9 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
 
   handleClickOutside = (event: any) => {
     if (
-      this.wrapperRef &&
-      this.wrapperRef.current &&
+      this.wrapperRef?.current &&
       !this.wrapperRef.current.contains(event.target) &&
-      this.parentRef &&
-      this.parentRef.current &&
+      this.parentRef?.current &&
       !this.parentRef.current.contains(event.target)
     ) {
       this.setState({ expanded: false });
@@ -63,7 +61,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
   };
 
   renderOptionList = () => {
-    let { options, activeValue } = this.props;
+    const { options, activeValue } = this.props;
     return options.map(
       (option: { value: string; label: string; icon?: any }, i: number) => {
         return (
@@ -71,7 +69,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
             key={i}
             height={this.props.height}
             selected={option.value === activeValue}
-            onClick={() => this.handleOptionClick(option)}
+            onClick={() => { this.handleOptionClick(option); }}
             lastItem={i === options.length - 1}
           >
             {option.icon && (
@@ -119,7 +117,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
                 : this.props.width
             }
             dropdownMaxHeight={this.props.dropdownMaxHeight}
-            onClick={() => this.setState({ expanded: false })}
+            onClick={() => { this.setState({ expanded: false }); }}
           >
             {this.renderDropdownLabel()}
             {this.renderOptionList()}
@@ -132,7 +130,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
   };
 
   getLabel = (value: string): any => {
-    let tgt = this.props.options.find(
+    const tgt = this.props.options.find(
       (element: { value: string; label: string }) => element.value === value
     );
     if (tgt) {
@@ -141,7 +139,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
   };
 
   renderIcon = () => {
-    var icon;
+    let icon;
     this.props.options.forEach((option: any) => {
       if (option.icon && option.value === this.props.activeValue) {
         icon = option.icon;
@@ -159,7 +157,7 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
   };
 
   render() {
-    let { activeValue, isLoading } = this.props;
+    const { activeValue, isLoading } = this.props;
 
     return (
       <StyledSelector width={this.props.width}>
@@ -177,8 +175,8 @@ export default class Selector<T> extends Component<SelectorPropsType<T>, StateTy
           expanded={this.state.expanded}
           width={this.props.width}
           height={this.props.height}
-          onMouseEnter={() => this.setState({ showTooltip: true })}
-          onMouseLeave={() => this.setState({ showTooltip: false })}
+          onMouseEnter={() => { this.setState({ showTooltip: true }); }}
+          onMouseLeave={() => { this.setState({ showTooltip: false }); }}
         >
           {isLoading ?
             <Loading />

+ 1 - 1
dashboard/src/components/TitleSection.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
   children: React.ReactNode;
   icon?: any;
   iconWidth?: string;

+ 1 - 1
dashboard/src/components/date-time-picker/DateTimePicker.tsx

@@ -21,7 +21,7 @@ const DateTimePicker: React.FC<Props> = ({ startDate, setStartDate }) => {
   maxTimeMinDay.setHours(23, 59, 0, 0);
 
   const availableDates = [];
-  let currentDate = new Date(minDate);
+  const currentDate = new Date(minDate);
   while (currentDate <= maxDate) {
     availableDates.push(new Date(currentDate));
     currentDate.setTime(currentDate.getTime() + 24 * 60 * 60 * 1000);

+ 5 - 5
dashboard/src/components/form-components/CheckboxList.tsx

@@ -3,13 +3,13 @@ import styled from "styled-components";
 
 type PropsType = {
   label?: string;
-  options: { disabled?: boolean; value: string; label: string }[];
-  selected: { value: string; label: string }[];
-  setSelected: (x: { value: string; label: string }[]) => void;
+  options: Array<{ disabled?: boolean; value: string; label: string }>;
+  selected: Array<{ value: string; label: string }>;
+  setSelected: (x: Array<{ value: string; label: string }>) => void;
 };
 
 const CheckboxList = ({ label, options, selected, setSelected }: PropsType) => {
-  let onSelectOption = (option: { value: string; label: string }) => {
+  const onSelectOption = (option: { value: string; label: string }) => {
     const tmp = [...selected];
     if (!tmp.includes(option)) {
       setSelected([...tmp, option]);
@@ -26,7 +26,7 @@ const CheckboxList = ({ label, options, selected, setSelected }: PropsType) => {
         return (
           <CheckboxOption
             isLast={i === options.length - 1}
-            onClick={() => onSelectOption(option)}
+            onClick={() => { onSelectOption(option); }}
             key={i}
           >
             <Checkbox checked={selected.includes(option)}>

+ 1 - 1
dashboard/src/components/form-components/Heading.tsx

@@ -10,7 +10,7 @@ export default function Heading(props: {
     <StyledHeading isAtTop={props.isAtTop}>
       {props.children}
       {props.docs && (
-        <a href={props.docs} target="_blank">
+        <a href={props.docs} target="_blank" rel="noreferrer">
           <i className="material-icons">help_outline</i>
         </a>
       )}

+ 1 - 1
dashboard/src/components/form-components/Helper.tsx

@@ -2,7 +2,7 @@ import React from "react";
 import styled from "styled-components";
 
 export const Helper = styled.div<{ color?: string }>`
-  color: ${({ color }) => (color ? color : "#aaaabb")};
+  color: ${({ color }) => (color || "#aaaabb")};
   line-height: 1.6em;
   font-size: 13px;
   margin-bottom: 20px;

+ 3 - 3
dashboard/src/components/form-components/InputRow.tsx

@@ -1,4 +1,4 @@
-import React, { ChangeEvent, Component } from "react";
+import React, { type ChangeEvent, Component } from "react";
 import Tooltip from "@material-ui/core/Tooltip";
 import styled from "styled-components";
 
@@ -36,7 +36,7 @@ export default class InputRow extends Component<PropsType, StateType> {
   };
 
   render() {
-    let { label, value, type, unit, placeholder, width, info } = this.props;
+    const { label, value, type, unit, placeholder, width, info } = this.props;
     return (
       <StyledInputRow className={this.props.className}>
         {(label || info) && (
@@ -69,7 +69,7 @@ export default class InputRow extends Component<PropsType, StateType> {
         <InputWrapper hasError={this.props.hasError} width={width}>
           <Input
             readOnly={this.state.readOnly}
-            onFocus={() => this.setState({ readOnly: false })}
+            onFocus={() => { this.setState({ readOnly: false }); }}
             disabled={this.props.disabled}
             placeholder={placeholder}
             width={width}

+ 17 - 17
dashboard/src/components/form-components/KeyValueArray.tsx

@@ -40,7 +40,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
   };
 
   componentDidMount() {
-    let arr = [] as any[];
+    const arr = [] as any[];
     if (this.props.values) {
       Object.keys(this.props.values).forEach((key: string, i: number) => {
         arr.push({ key, value: this.props.values[key] });
@@ -50,7 +50,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
   }
 
   valuesToObject = () => {
-    let obj = {} as any;
+    const obj = {} as any;
     const rg = /(?:^|[^\\])(\\n)/g;
     const fixNewlines = (s: string) => {
       while (rg.test(s)) {
@@ -87,7 +87,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
             this.state.values.splice(i, 1);
             this.setState({ values: this.state.values });
 
-            let obj = this.valuesToObject();
+            const obj = this.valuesToObject();
             this.props.setValues(obj);
           }}
         >
@@ -129,7 +129,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
                   this.state.values[i].key = e.target.value;
                   this.setState({ values: this.state.values });
 
-                  let obj = this.valuesToObject();
+                  const obj = this.valuesToObject();
                   this.props.setValues(obj);
                 }}
                 disabled={
@@ -156,7 +156,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
                     this.state.values[i].value = e.target.value;
                     this.setState({ values: this.state.values });
 
-                    let obj = this.valuesToObject();
+                    const obj = this.valuesToObject();
                     this.props.setValues(obj);
                   }}
                   disabled={
@@ -179,7 +179,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
     if (this.state.showEnvModal) {
       return (
         <Modal
-          onRequestClose={() => this.setState({ showEnvModal: false })}
+          onRequestClose={() => { this.setState({ showEnvModal: false }); }}
           width="765px"
           height="542px"
         >
@@ -187,7 +187,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
             existingValues={this.props.values}
             namespace={this.props.externalValues?.namespace}
             clusterId={this.props.externalValues?.clusterId}
-            closeModal={() => this.setState({ showEnvModal: false })}
+            closeModal={() => { this.setState({ showEnvModal: false }); }}
             setValues={(values) => {
               const newValues = { ...this.props.values, ...values };
               this.props.setValues(newValues);
@@ -204,13 +204,13 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
     if (this.state.showEditorModal) {
       return (
         <Modal
-          onRequestClose={() => this.setState({ showEditorModal: false })}
+          onRequestClose={() => { this.setState({ showEditorModal: false }); }}
           width="60%"
           height="80%"
         >
           <EnvEditorModal
-            closeModal={() => this.setState({ showEditorModal: false })}
-            setEnvVariables={(envFile: string) => this.readFile(envFile)}
+            closeModal={() => { this.setState({ showEditorModal: false }); }}
+            setEnvVariables={(envFile: string) => { this.readFile(envFile); }}
           />
         </Modal>
       );
@@ -218,14 +218,14 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
   };
 
   readFile = (env: string) => {
-    let envObj = dotenv_parse(env);
+    const envObj = dotenv_parse(env);
     let push = true;
 
-    for (let key in envObj) {
-      for (var i = 0; i < this.state.values.length; i++) {
-        let existingKey = this.state.values[i]["key"];
+    for (const key in envObj) {
+      for (let i = 0; i < this.state.values.length; i++) {
+        const existingKey = this.state.values[i].key;
         if (key === existingKey) {
-          this.state.values[i]["value"] = envObj[key];
+          this.state.values[i].value = envObj[key];
           push = false;
         }
       }
@@ -236,7 +236,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
     }
 
     this.setState({ values: this.state.values }, () => {
-      let obj = this.valuesToObject();
+      const obj = this.valuesToObject();
       this.props.setValues(obj);
     });
   };
@@ -263,7 +263,7 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
               {this.props.externalValues?.namespace && this.props.envLoader && (
                 <LoadButton
                   onClick={() =>
-                    this.setState({ showEnvModal: !this.state.showEnvModal })
+                    { this.setState({ showEnvModal: !this.state.showEnvModal }); }
                   }
                 >
                   <img src={sliders} /> Load from Env Group

+ 3 - 3
dashboard/src/components/form-components/SelectRow.tsx

@@ -1,13 +1,13 @@
 import React, { Component } from "react";
 import styled from "styled-components";
 
-import Selector, { SelectorPropsType } from "../Selector";
+import Selector, { type SelectorPropsType } from "../Selector";
 
 type PropsType<T> = {
   label: string;
   value: T;
   setActiveValue: (x: T) => void;
-  options: { value: T; label: string }[];
+  options: Array<{ value: T; label: string }>;
   displayFlex?: boolean;
   dropdownLabel?: string;
   width?: string;
@@ -25,7 +25,7 @@ export default function SelectRow<T>(props: PropsType<T>) {
       <Wrapper>
         <Label displayFlex={props.displayFlex}>{props.label}</Label>
         {props.doc ? (
-          <a href={props.doc} target="_blank">
+          <a href={props.doc} target="_blank" rel="noreferrer">
             <i className="material-icons">help_outline</i>
           </a>
         ) : null}

+ 1 - 1
dashboard/src/components/form-components/TextArea.tsx

@@ -18,7 +18,7 @@ export default class TextArea extends Component<PropsType, StateType> {
   };
 
   render() {
-    let { label, value, placeholder, width } = this.props;
+    const { label, value, placeholder, width } = this.props;
     return (
       <StyledTextArea>
         <Label>{label}</Label>

+ 2 - 1
dashboard/src/components/form-components/UploadArea.tsx

@@ -19,6 +19,7 @@ export default class UploadArea extends Component<PropsType, StateType> {
   state = {
     fileName: "",
   };
+
   handleChange = (e: any) => {
     this.props.setValue(e.target.value);
   };
@@ -26,7 +27,7 @@ export default class UploadArea extends Component<PropsType, StateType> {
   readFile = (file: File) => {
     const reader = new FileReader();
     reader.onload = async (e) => {
-      let text = e.target?.result as string;
+      const text = e.target?.result as string;
       this.props.setValue(text);
     };
     reader.readAsText(file, "UTF-8");

+ 15 - 17
dashboard/src/components/image-selector/ImageList.tsx

@@ -4,7 +4,7 @@ import styled from "styled-components";
 import api from "shared/api";
 import { integrationList } from "shared/common";
 import { Context } from "shared/Context";
-import { ImageType } from "shared/types";
+import { type ImageType } from "shared/types";
 
 import Loading from "../Loading";
 import TagList from "./TagList";
@@ -51,14 +51,14 @@ export default class ImageList extends Component<PropsType, StateType> {
   // TODO: Try to unhook before unmount
   componentDidMount() {
     const { currentProject, setCurrentError } = this.context;
-    let images = [] as ImageType[];
-    let errors = [] as number[];
+    const images = [] as ImageType[];
+    const errors = [] as number[];
 
     if (!this.props.registry) {
       api
         .getProjectRegistries("<token>", {}, { id: currentProject?.id })
         .then((res) => {
-          let registries = res.data;
+          const registries = res.data;
           if (registries.length === 0) {
             this.setState({ loading: false });
           }
@@ -81,7 +81,7 @@ export default class ImageList extends Component<PropsType, StateType> {
                       a.name > b.name ? 1 : -1
                     );
                     // Loop over found image repositories
-                    let newImg = res.data.map((img: any) => {
+                    const newImg = res.data.map((img: any) => {
                       if (this.props.selectedImageUrl === img.uri) {
                         this.props.setClickedImage({
                           kind: registry.service,
@@ -103,12 +103,10 @@ export default class ImageList extends Component<PropsType, StateType> {
                   .catch((err) => errors.push(1))
                   .finally(() => {
                     if (i == registries.length - 1) {
-                      let error =
+                      const error =
                         errors.reduce((a, b) => {
                           return a + b;
-                        }) == registries.length
-                          ? true
-                          : false;
+                        }) == registries.length;
 
                       this.setState({
                         images,
@@ -143,7 +141,7 @@ export default class ImageList extends Component<PropsType, StateType> {
         .then((res) => {
           res.data.sort((a: any, b: any) => (a.name > b.name ? 1 : -1));
           // Loop over found image repositories
-          let newImg = res.data.map((img: any) => {
+          const newImg = res.data.map((img: any) => {
             if (this.props.selectedImageUrl === img.uri) {
               this.props.setClickedImage({
                 kind: this.props.registry.service,
@@ -168,16 +166,16 @@ export default class ImageList extends Component<PropsType, StateType> {
           });
         })
         .catch((err) =>
-          this.setState({
+          { this.setState({
             loading: false,
             error: true,
-          })
+          }); }
         );
     }
   }
 
   renderImageList = () => {
-    let { images, loading, error } = this.state;
+    const { images, loading, error } = this.state;
 
     if (loading) {
       return (
@@ -193,9 +191,9 @@ export default class ImageList extends Component<PropsType, StateType> {
 
     return images.map((image: ImageType, i: number) => {
       let icon =
-        integrationList[image.kind] && integrationList[image.kind].icon;
+        integrationList[image.kind]?.icon;
       if (!icon) {
-        icon = integrationList["dockerhub"].icon;
+        icon = integrationList.dockerhub.icon;
       }
       return (
         <ImageItem
@@ -215,7 +213,7 @@ export default class ImageList extends Component<PropsType, StateType> {
   };
 
   renderBackButton = () => {
-    let { setSelectedImageUrl, clickedImage, disableImageSelect } = this.props;
+    const { setSelectedImageUrl, clickedImage, disableImageSelect } = this.props;
     if (clickedImage && !disableImageSelect) {
       return (
         <BackButton
@@ -233,7 +231,7 @@ export default class ImageList extends Component<PropsType, StateType> {
   };
 
   renderExpanded = () => {
-    let { selectedTag, selectedImageUrl, setSelectedTag } = this.props;
+    const { selectedTag, selectedImageUrl, setSelectedTag } = this.props;
 
     if (this.props.readOnly && this.props.clickedImage) {
       return (

+ 10 - 11
dashboard/src/components/image-selector/ImageSelector.tsx

@@ -5,7 +5,7 @@ import edit from "assets/edit.svg";
 
 import { integrationList } from "shared/common";
 import { Context } from "shared/Context";
-import { ImageType } from "shared/types";
+import { type ImageType } from "shared/types";
 
 import Loading from "../Loading";
 import ImageList from "./ImageList";
@@ -50,7 +50,7 @@ export default class ImageSelector extends Component<PropsType, StateType> {
   };
 
   renderImageList = () => {
-    let { images, loading, error } = this.state;
+    const { images, loading, error } = this.state;
 
     if (loading) {
       return (
@@ -66,9 +66,9 @@ export default class ImageSelector extends Component<PropsType, StateType> {
 
     return images.map((image: ImageType, i: number) => {
       let icon =
-        integrationList[image.kind] && integrationList[image.kind].icon;
+        integrationList[image.kind]?.icon;
       if (!icon) {
-        icon = integrationList["dockerhub"].icon;
+        icon = integrationList.dockerhub.icon;
       }
       return (
         <ImageItem
@@ -88,16 +88,15 @@ export default class ImageSelector extends Component<PropsType, StateType> {
   };
 
   renderSelected = () => {
-    let { selectedImageUrl, setSelectedImageUrl } = this.props;
-    let { clickedImage } = this.state;
+    const { selectedImageUrl, setSelectedImageUrl } = this.props;
+    const { clickedImage } = this.state;
     let icon = info;
     if (clickedImage) {
       icon = clickedImage.kind;
       icon =
-        integrationList[clickedImage.kind] &&
-        integrationList[clickedImage.kind].icon;
+        integrationList[clickedImage.kind]?.icon;
       if (!icon) {
-        icon = integrationList["dockerhub"].icon;
+        icon = integrationList.dockerhub.icon;
       }
     } else if (selectedImageUrl && selectedImageUrl !== "") {
       icon = edit;
@@ -151,7 +150,7 @@ export default class ImageSelector extends Component<PropsType, StateType> {
             setSelectedImageUrl={this.props.setSelectedImageUrl}
             setSelectedTag={this.props.setSelectedTag}
             setClickedImage={(x: ImageType) =>
-              this.setState({ clickedImage: x })
+              { this.setState({ clickedImage: x }); }
             }
             readOnly
           />
@@ -184,7 +183,7 @@ export default class ImageSelector extends Component<PropsType, StateType> {
             setSelectedImageUrl={this.props.setSelectedImageUrl}
             setSelectedTag={this.props.setSelectedTag}
             setClickedImage={(x: ImageType) =>
-              this.setState({ clickedImage: x })
+              { this.setState({ clickedImage: x }); }
             }
           />
         ) : null}

+ 8 - 8
dashboard/src/components/image-selector/TagList.tsx

@@ -8,7 +8,7 @@ import { Context } from "shared/Context";
 
 import Loading from "../Loading";
 
-var ecrRepoRegex = /(^[a-zA-Z0-9][a-zA-Z0-9-_]*)\.dkr\.ecr(\-fips)?\.([a-zA-Z0-9][a-zA-Z0-9-_]*)\.amazonaws\.com(\.cn)?/gim;
+const ecrRepoRegex = /(^[a-zA-Z0-9][a-zA-Z0-9-_]*)\.dkr\.ecr(\-fips)?\.([a-zA-Z0-9][a-zA-Z0-9-_]*)\.amazonaws\.com(\.cn)?/gim;
 
 type PropsType =
   | {
@@ -45,7 +45,7 @@ export default class TagList extends Component<PropsType, StateType> {
     this.setState({ loading: true });
     const { currentProject } = this.context;
 
-    let splits = this.props.selectedImageUrl.split("/");
+    const splits = this.props.selectedImageUrl.split("/");
     let repoName: string;
 
     if (this.props.selectedImageUrl.includes("pkg.dev")) {
@@ -54,7 +54,7 @@ export default class TagList extends Component<PropsType, StateType> {
       repoName = splits[splits.length - 1];
     }
 
-    let matches = this.props.selectedImageUrl.match(ecrRepoRegex);
+    const matches = this.props.selectedImageUrl.match(ecrRepoRegex);
 
     if (matches) {
       repoName = this.props.selectedImageUrl.split(/\/(.+)/)[1];
@@ -75,8 +75,8 @@ export default class TagList extends Component<PropsType, StateType> {
         // Sort if timestamp is available
         if (res.data.length > 0 && res.data[0].pushed_at) {
           tags = tags.sort((a: any, b: any) => {
-            let d1 = new Date(a.pushed_at);
-            let d2 = new Date(b.pushed_at);
+            const d1 = new Date(a.pushed_at);
+            const d2 = new Date(b.pushed_at);
             return d2.getTime() - d1.getTime();
           });
         }
@@ -99,13 +99,13 @@ export default class TagList extends Component<PropsType, StateType> {
   }
 
   setTag = (tag: string) => {
-    let { selectedTag, setSelectedTag } = this.props;
+    const { selectedTag, setSelectedTag } = this.props;
     setSelectedTag(tag);
     this.setState({ currentTag: tag });
   };
 
   renderTagList = () => {
-    let { tags, loading, error } = this.state;
+    const { tags, loading, error } = this.state;
     if (loading) {
       return (
         <LoadingWrapper>
@@ -124,7 +124,7 @@ export default class TagList extends Component<PropsType, StateType> {
           key={i}
           isSelected={tag === this.state.currentTag}
           lastItem={i === tags.length - 1}
-          onClick={() => this.setTag(tag)}
+          onClick={() => { this.setTag(tag); }}
         >
           <img src={tag_icon} />
           {tag}

+ 10 - 10
dashboard/src/components/porter-form/FormDebugger.tsx

@@ -11,7 +11,7 @@ import "ace-builds/src-noconflict/mode-text";
 
 import Heading from "../form-components/Heading";
 import Helper from "../form-components/Helper";
-import { ChartType } from "shared/types";
+import { type ChartType } from "shared/types";
 
 type PropsType = {
   goBack: () => void;
@@ -78,7 +78,7 @@ export default class FormDebugger extends Component<PropsType, StateType> {
             mode="yaml"
             value={this.state.rawYaml}
             theme="porter"
-            onChange={(e: string) => this.setState({ rawYaml: e })}
+            onChange={(e: string) => { this.setState({ rawYaml: e }); }}
             name="codeEditor"
             editorProps={{ $blockScrolling: true }}
             height="450px"
@@ -99,30 +99,30 @@ export default class FormDebugger extends Component<PropsType, StateType> {
           label="Show form state debugger"
           checked={this.state.showStateDebugger}
           toggle={() =>
-            this.setState({ showStateDebugger: !this.state.showStateDebugger })
+            { this.setState({ showStateDebugger: !this.state.showStateDebugger }); }
           }
         />
         <CheckboxRow
           label="Read-only"
           checked={this.state.isReadOnly}
           toggle={() =>
-            this.setState({
+            { this.setState({
               isReadOnly: !this.state.isReadOnly,
-            })
+            }); }
           }
         />
         <CheckboxRow
           label="Include non-form dummy tabs"
           checked={this.state.showBonusTabs}
           toggle={() =>
-            this.setState({ showBonusTabs: !this.state.showBonusTabs })
+            { this.setState({ showBonusTabs: !this.state.showBonusTabs }); }
           }
         />
         <CheckboxRow
           label="checkbox_a"
           checked={this.state.checkbox_a}
           toggle={() =>
-            this.setState({
+            { this.setState({
               checkbox_a: !this.state.checkbox_a,
 
               // Override the form value for checkbox_a
@@ -132,14 +132,14 @@ export default class FormDebugger extends Component<PropsType, StateType> {
                   value: !this.state.checkbox_a,
                 },
               },
-            })
+            }); }
           }
         />
         <InputRow
           type="string"
           value={this.state.input_a}
           setValue={(x: string) =>
-            this.setState({
+            { this.setState({
               input_a: x,
 
               // Override the form value for input_a
@@ -149,7 +149,7 @@ export default class FormDebugger extends Component<PropsType, StateType> {
                   value: x,
                 },
               },
-            })
+            }); }
           }
           label={"input_a"}
           placeholder="ex: override text"

+ 18 - 18
dashboard/src/components/porter-form/PorterForm.tsx

@@ -1,22 +1,22 @@
 import React, { useContext } from "react";
 import {
-  ArrayInputField,
-  CheckboxField,
-  CronField,
-  FormField,
-  InjectedProps,
-  InputField,
-  KeyValueArrayField,
-  ResourceListField,
-  Section,
-  SelectField,
-  ServiceIPListField,
-  TextAreaField,
-  UrlLinkField,
-  DictionaryField,
-  DictionaryArrayField,
+  type ArrayInputField,
+  type CheckboxField,
+  type CronField,
+  type FormField,
+  type InjectedProps,
+  type InputField,
+  type KeyValueArrayField,
+  type ResourceListField,
+  type Section,
+  type SelectField,
+  type ServiceIPListField,
+  type TextAreaField,
+  type UrlLinkField,
+  type DictionaryField,
+  type DictionaryArrayField,
 } from "./types";
-import TabRegion, { TabOption } from "../TabRegion";
+import TabRegion, { type TabOption } from "../TabRegion";
 import Heading from "../form-components/Heading";
 import Helper from "../form-components/Helper";
 import Input from "./field-components/Input";
@@ -37,7 +37,7 @@ import Button from "components/porter/Button";
 import DictionaryArray from "./field-components/DictionaryArray";
 import Dictionary from "./field-components/Dictionary";
 
-interface Props {
+type Props = {
   leftTabOptions?: TabOption[];
   rightTabOptions?: TabOption[];
   renderTabContents?: (
@@ -135,7 +135,7 @@ const PorterForm: React.FC<Props> = (props) => {
   };
 
   const getTabOptions = (): TabOption[] => {
-    let options = (props.leftTabOptions || [])
+    const options = (props.leftTabOptions || [])
       .concat(
         formData?.tabs?.map((tab) => {
           if (props.isLaunch && tab?.settings?.omitFromLaunch) {

+ 21 - 21
dashboard/src/components/porter-form/PorterFormContextProvider.tsx

@@ -1,19 +1,19 @@
 import React, { createContext, useContext, useReducer } from "react";
 import {
-  GetFinalVariablesFunction,
-  GetMetadataFunction,
-  PorterFormAction,
-  PorterFormData,
-  PorterFormState,
-  PorterFormValidationInfo,
-  PorterFormVariableList,
+  type GetFinalVariablesFunction,
+  type GetMetadataFunction,
+  type PorterFormAction,
+  type PorterFormData,
+  type PorterFormState,
+  type PorterFormValidationInfo,
+  type PorterFormVariableList,
 } from "./types";
 import {
-  ShowIf,
-  ShowIfAnd,
-  ShowIfIs,
-  ShowIfNot,
-  ShowIfOr,
+  type ShowIf,
+  type ShowIfAnd,
+  type ShowIfIs,
+  type ShowIfNot,
+  type ShowIfOr,
 } from "../../shared/types";
 import { getFinalVariablesForStringInput } from "./field-components/Input";
 import {
@@ -25,7 +25,7 @@ import { getFinalVariablesForArrayInput } from "./field-components/ArrayInput";
 import { getFinalVariablesForCheckbox } from "./field-components/Checkbox";
 import { getFinalVariablesForSelect } from "./field-components/Select";
 
-export interface BaseProps {
+export type BaseProps = {
   rawFormData: PorterFormData;
   initialVariables?: PorterFormVariableList;
   overrideVariables?: PorterFormVariableList;
@@ -34,22 +34,22 @@ export interface BaseProps {
   doDebug?: boolean;
 }
 
-export interface PropsWithMetadata extends BaseProps {
+export type PropsWithMetadata = {
   onSubmit: (
     data: { vars: PorterFormVariableList; metadata: PorterFormVariableList },
     cb?: () => void
   ) => void;
   includeMetadata: true;
-}
+} & BaseProps
 
-export interface PropsWithoutMetadata extends BaseProps {
+export type PropsWithoutMetadata = {
   onSubmit: (vars: PorterFormVariableList, cb?: () => void) => void;
   includeMetadata: false;
-}
+} & BaseProps
 
 export type Props = PropsWithMetadata | PropsWithoutMetadata;
 
-interface ContextProps {
+type ContextProps = {
   formData: PorterFormData;
   formState: PorterFormState;
   onSubmit: (cb?: () => void) => void;
@@ -192,7 +192,7 @@ export const PorterFormContextProvider: React.FC<Props> = (props) => {
             return;
           if (
             field.required &&
-            (field.settings?.default || (field.value && field.value[0]))
+            (field.settings?.default || (field.value?.[0]))
           ) {
             ret[`${i}-${j}-${k}`] = {
               validated: true,
@@ -221,7 +221,7 @@ export const PorterFormContextProvider: React.FC<Props> = (props) => {
     if (!vals) {
       return false;
     }
-    if (typeof vals == "string") {
+    if (typeof vals === "string") {
       return !!variables[vals];
     }
     if ((vals as ShowIfIs).is) {
@@ -532,7 +532,7 @@ export const PorterFormContextProvider: React.FC<Props> = (props) => {
   return (
     <Provider
       value={{
-        formData: formData,
+        formData,
         formState: state,
         dispatchAction: dispatch,
         isReadOnly: props.isReadOnly,

+ 3 - 3
dashboard/src/components/porter-form/PorterFormWrapper.tsx

@@ -1,7 +1,7 @@
 import React, { useEffect, useState } from "react";
 
 import PorterForm from "./PorterForm";
-import { InjectedProps, PorterFormData } from "./types";
+import { type InjectedProps, type PorterFormData } from "./types";
 import { PorterFormContextProvider } from "./PorterFormContextProvider";
 import _ from "lodash";
 
@@ -11,8 +11,8 @@ type PropsType = {
   isReadOnly?: boolean;
   onSubmit?: (values: any, cb?: () => void) => void;
   renderTabContents?: (currentTab: string, submitValues?: any) => any;
-  leftTabOptions?: { value: string; label: string }[];
-  rightTabOptions?: { value: string; label: string }[];
+  leftTabOptions?: Array<{ value: string; label: string }>;
+  rightTabOptions?: Array<{ value: string; label: string }>;
   saveButtonText?: string;
   isInModal?: boolean;
   color?: string;

+ 3 - 3
dashboard/src/components/porter-form/field-components/ArrayInput.tsx

@@ -1,9 +1,9 @@
 import React from "react";
 import styled from "styled-components";
 import {
-  ArrayInputField,
-  ArrayInputFieldState,
-  GetFinalVariablesFunction,
+  type ArrayInputField,
+  type ArrayInputFieldState,
+  type GetFinalVariablesFunction,
 } from "../types";
 import useFormField from "../hooks/useFormField";
 import { hasSetValue } from "../utils";

+ 5 - 5
dashboard/src/components/porter-form/field-components/Checkbox.tsx

@@ -1,15 +1,15 @@
 import React from "react";
 import {
-  CheckboxField,
-  CheckboxFieldState,
-  GetFinalVariablesFunction,
+  type CheckboxField,
+  type CheckboxFieldState,
+  type GetFinalVariablesFunction,
 } from "../types";
 import CheckboxRow from "../../form-components/CheckboxRow";
 import useFormField from "../hooks/useFormField";
 
-interface Props extends CheckboxField {
+type Props = {
   id: string;
-}
+} & CheckboxField
 
 const Checkbox: React.FC<Props> = ({
   id,

+ 1 - 1
dashboard/src/components/porter-form/field-components/CronInput.tsx

@@ -1,7 +1,7 @@
 import InputRow from "components/form-components/InputRow";
 import React from "react";
 import useFormField from "../hooks/useFormField";
-import { CronField } from "../types";
+import { type CronField } from "../types";
 import { hasSetValue } from "../utils";
 import { isValidCron } from "cron-validator";
 import CronParser from "cronstrue";

+ 4 - 4
dashboard/src/components/porter-form/field-components/Dictionary.tsx

@@ -2,9 +2,9 @@ import React, { useEffect } from "react";
 import InputRow from "../../form-components/InputRow";
 import useFormField from "../hooks/useFormField";
 import {
-  GetFinalVariablesFunction,
-  DictionaryField,
-  DictionaryFieldState,
+  type GetFinalVariablesFunction,
+  type DictionaryField,
+  type DictionaryFieldState,
 } from "../types";
 import DictionaryEditor from "components/porter/DictionaryEditor";
 import { hasSetValue } from "../utils";
@@ -28,7 +28,7 @@ const Dictionary: React.FC<DictionaryField> = (props) => {
 
   return (
     <DictionaryEditor
-      value={props?.value && props.value[0]}
+      value={props?.value?.[0]}
       onChange={(x: any) => {
         setVars((vars) => {
           return {

+ 3 - 3
dashboard/src/components/porter-form/field-components/DictionaryArray.tsx

@@ -1,9 +1,9 @@
 import React from "react";
 import styled from "styled-components";
 import {
-  DictionaryArrayField,
-  DictionaryArrayFieldState,
-  GetFinalVariablesFunction,
+  type DictionaryArrayField,
+  type DictionaryArrayFieldState,
+  type GetFinalVariablesFunction,
 } from "../types";
 import useFormField from "../hooks/useFormField";
 import { hasSetValue } from "../utils";

+ 3 - 3
dashboard/src/components/porter-form/field-components/Input.tsx

@@ -2,9 +2,9 @@ import React from "react";
 import InputRow from "../../form-components/InputRow";
 import useFormField from "../hooks/useFormField";
 import {
-  GetFinalVariablesFunction,
-  InputField,
-  StringInputFieldState,
+  type GetFinalVariablesFunction,
+  type InputField,
+  type StringInputFieldState,
 } from "../types";
 import { hasSetValue } from "../utils";
 

+ 38 - 40
dashboard/src/components/porter-form/field-components/KeyValueArray.tsx

@@ -1,11 +1,11 @@
 import React, { useContext, useEffect, useState } from "react";
 import {
-  GetFinalVariablesFunction,
-  GetMetadataFunction,
-  KeyValueArrayField,
-  KeyValueArrayFieldState,
-  PartialEnvGroup,
-  PopulatedEnvGroup,
+  type GetFinalVariablesFunction,
+  type GetMetadataFunction,
+  type KeyValueArrayField,
+  type KeyValueArrayFieldState,
+  type PartialEnvGroup,
+  type PopulatedEnvGroup,
 } from "../types";
 import sliders from "../../../assets/sliders.svg";
 import upload from "../../../assets/upload.svg";
@@ -23,9 +23,9 @@ import api from "shared/api";
 import { Context } from "shared/Context";
 import { dotenv_parse } from "shared/string_utils";
 
-interface Props extends KeyValueArrayField {
+type Props = {
   id: string;
-}
+} & KeyValueArrayField
 
 const KeyValueArray: React.FC<Props> = (props) => {
   const { state, setState, variables } = useFormField<KeyValueArrayFieldState>(
@@ -134,14 +134,14 @@ const KeyValueArray: React.FC<Props> = (props) => {
   };
 
   const readFile = (env: string) => {
-    let envObj = parseEnv(env, null);
+    const envObj = parseEnv(env, null);
     let push = true;
 
-    for (let key in envObj) {
-      for (var i = 0; i < state.values.length; i++) {
-        let existingKey = state.values[i]["key"];
+    for (const key in envObj) {
+      for (let i = 0; i < state.values.length; i++) {
+        const existingKey = state.values[i].key;
         if (key === existingKey) {
-          state.values[i]["value"] = envObj[key];
+          state.values[i].value = envObj[key];
           push = false;
         }
       }
@@ -161,20 +161,20 @@ const KeyValueArray: React.FC<Props> = (props) => {
       return (
         <Modal
           onRequestClose={() =>
-            setState(() => {
+            { setState(() => {
               return { showEditorModal: false };
-            })
+            }); }
           }
           width="60%"
           height="80%"
         >
           <EnvEditorModal
             closeModal={() =>
-              setState(() => {
+              { setState(() => {
                 return { showEditorModal: false };
-              })
+              }); }
             }
-            setEnvVariables={(envFile: string) => readFile(envFile)}
+            setEnvVariables={(envFile: string) => { readFile(envFile); }}
           />
         </Modal>
       );
@@ -182,9 +182,9 @@ const KeyValueArray: React.FC<Props> = (props) => {
   };
 
   const getProcessedValues = (
-    objectArray: { key: string; value: string }[]
+    objectArray: Array<{ key: string; value: string }>
   ): any => {
-    let obj = {} as any;
+    const obj = {} as any;
     objectArray?.forEach(({ key, value }) => {
       obj[key] = value;
     });
@@ -196,9 +196,9 @@ const KeyValueArray: React.FC<Props> = (props) => {
       return (
         <Modal
           onRequestClose={() =>
-            setState(() => {
+            { setState(() => {
               return { showEnvModal: false };
-            })
+            }); }
           }
           width="800px"
           height="542px"
@@ -211,11 +211,11 @@ const KeyValueArray: React.FC<Props> = (props) => {
             namespace={variables.namespace}
             clusterId={variables.clusterId}
             closeModal={() =>
-              setState(() => {
+              { setState(() => {
                 return {
                   showEnvModal: false,
                 };
-              })
+              }); }
             }
             setSyncedEnvGroups={(value) => {
               setState((prev) => {
@@ -227,10 +227,10 @@ const KeyValueArray: React.FC<Props> = (props) => {
             setValues={(values) => {
               setState((prev) => {
                 // Transform array to object similar on what we receive from setValues
-                const prevValues = prev.values.reduce((acc, currentValue) => {
+                const prevValues = prev.values.reduce<Record<string, string>>((acc, currentValue) => {
                   acc[currentValue.key] = currentValue.value;
                   return acc;
-                }, {} as Record<string, string>);
+                }, {});
 
                 // Deconstruct the two records/objects inside one to merge their values (this will override the old duped vars too)
                 // and convert the new object back to an array usable for the component
@@ -414,11 +414,11 @@ const KeyValueArray: React.FC<Props> = (props) => {
             {variables.namespace && props.envLoader && (
               <LoadButton
                 onClick={() =>
-                  setState((prev) => {
+                  { setState((prev) => {
                     return {
                       showEnvModal: !prev.showEnvModal,
                     };
-                  })
+                  }); }
                 }
               >
                 <img src={sliders} /> Load from Env Group
@@ -499,7 +499,7 @@ export const getFinalVariablesForKeyValueArray: GetFinalVariablesFunction = (
   };
 
   if (props.variable.includes("env")) {
-    let obj = {
+    const obj = {
       normal: {},
     } as any;
 
@@ -537,7 +537,7 @@ export const getFinalVariablesForKeyValueArray: GetFinalVariablesFunction = (
       [variable]: obj,
     };
   } else {
-    let obj = {} as any;
+    const obj = {} as any;
 
     state.values.forEach((entry: any, i: number) => {
       if (isNumber(entry.value)) {
@@ -552,12 +552,10 @@ export const getFinalVariablesForKeyValueArray: GetFinalVariablesFunction = (
   }
 };
 
-type KeyValueArrayMetadata = {
-  [variable: string]: {
-    added: { name: string }[];
-    deleted: { name: string }[];
-  };
-};
+type KeyValueArrayMetadata = Record<string, {
+    added: Array<{ name: string }>;
+    deleted: Array<{ name: string }>;
+  }>;
 
 export const getMetadata: GetMetadataFunction<KeyValueArrayMetadata> = (
   vars,
@@ -571,11 +569,11 @@ export const getMetadata: GetMetadataFunction<KeyValueArrayMetadata> = (
     };
   }
 
-  const originalSyncedEnvGroups: { name: string }[] =
+  const originalSyncedEnvGroups: Array<{ name: string }> =
     props.value[0]?.synced || [];
   const currSynced = state?.synced_env_groups || [];
 
-  let obj: KeyValueArrayMetadata[""] = {
+  const obj: KeyValueArrayMetadata[""] = {
     added: [],
     deleted: [],
   };
@@ -614,10 +612,10 @@ const ExpandableEnvGroup: React.FC<{
             </EventInformation>
           </ContentContainer>
           <ActionContainer>
-            <ActionButton onClick={() => onDelete()}>
+            <ActionButton onClick={() => { onDelete(); }}>
               <span className="material-icons">delete</span>
             </ActionButton>
-            <ActionButton onClick={() => setIsExpanded((prev) => !prev)}>
+            <ActionButton onClick={() => { setIsExpanded((prev) => !prev); }}>
               <i className="material-icons">
                 {isExpanded ? "arrow_drop_up" : "arrow_drop_down"}
               </i>

+ 2 - 2
dashboard/src/components/porter-form/field-components/MultiSelect.tsx

@@ -4,12 +4,12 @@ import styled from "styled-components";
 type PropsType = {};
 
 type StateType = {
-  options: { label: string; value: string }[];
+  options: Array<{ label: string; value: string }>;
 };
 
 export default class MultiSelect extends Component<PropsType, StateType> {
   state = {
-    options: [] as { label: string; value: string }[],
+    options: [] as Array<{ label: string; value: string }>,
   };
 
   renderOptions = () => {};

+ 6 - 7
dashboard/src/components/porter-form/field-components/ResourceList.tsx

@@ -1,5 +1,5 @@
 import React, { useEffect, useContext, useState } from "react";
-import { ResourceListField } from "../types";
+import { type ResourceListField } from "../types";
 import { Context } from "shared/Context";
 import { useWebsockets } from "shared/hooks/useWebsockets";
 import ExpandableResource from "../../ExpandableResource";
@@ -34,18 +34,18 @@ const ResourceList: React.FC<ResourceListField> = (props) => {
       return () => { };
     }
 
-    let { group, version, resource } = props.context.config;
+    const { group, version, resource } = props.context.config;
     let apiEndpoint = `/api/projects/${currentProject.id}/clusters/${currentCluster.id}/namespaces/${formState?.variables?.namespace}/releases/${formState?.variables?.currentChart?.name}/0/form_stream?`;
     apiEndpoint += `resource=${resource}&group=${group}&version=${version}`;
 
     const wsConfig = {
       onmessage(evt: MessageEvent) {
-        let { data, kind } = JSON.parse(evt.data);
+        const { data, kind } = JSON.parse(evt.data);
 
         // parse for name and label, which uniquely identify a resource
-        for (let [key] of Object.entries(data)) {
+        for (const [key] of Object.entries(data)) {
           // check the name and label in the value
-          let { name, label } = data[key][0];
+          const { name, label } = data[key][0];
 
           // attempt to find a corresponding name and label in the current array
           let foundMatch = false;
@@ -98,8 +98,7 @@ const ResourceList: React.FC<ResourceListField> = (props) => {
             <ExpandableResource
               key={i}
               button={
-                props?.settings?.options &&
-                props?.settings?.options["resource-button"]
+                props?.settings?.options?.["resource-button"]
               }
               resource={resource}
               isLast={i === resourceList.length - 1}

+ 3 - 3
dashboard/src/components/porter-form/field-components/Select.tsx

@@ -1,8 +1,8 @@
 import React, { useContext } from "react";
 import {
-  GetFinalVariablesFunction,
-  SelectField,
-  SelectFieldState,
+  type GetFinalVariablesFunction,
+  type SelectField,
+  type SelectFieldState,
 } from "../types";
 import Selector from "../../Selector";
 import styled from "styled-components";

+ 1 - 1
dashboard/src/components/porter-form/field-components/ServiceIPList.tsx

@@ -1,5 +1,5 @@
 import React from "react";
-import { ServiceIPListField } from "../types";
+import { type ServiceIPListField } from "../types";
 import ServiceRow from "./ServiceRow";
 import styled from "styled-components";
 

+ 1 - 1
dashboard/src/components/porter-form/field-components/ServiceRow.tsx

@@ -20,7 +20,7 @@ const getIcon = (type: string) => {
   if (hardcodedIcons[type]) {
     return hardcodedIcons[type];
   }
-  return hardcodedIcons["web"];
+  return hardcodedIcons.web;
 }
 
 export default class ServiceRow extends Component<PropsType, StateType> {

+ 1 - 1
dashboard/src/components/porter-form/field-components/TextAreaInput.tsx

@@ -2,7 +2,7 @@ import { Tooltip } from "@material-ui/core";
 import React from "react";
 import styled from "styled-components";
 import useFormField from "../hooks/useFormField";
-import { StringInputFieldState, TextAreaField } from "../types";
+import { type StringInputFieldState, type TextAreaField } from "../types";
 import { hasSetValue } from "../utils";
 
 const TextAreaInput: React.FC<TextAreaField> = (props) => {

+ 2 - 2
dashboard/src/components/porter-form/field-components/UrlLink.tsx

@@ -1,7 +1,7 @@
 import { get } from "lodash";
 import React from "react";
 import styled from "styled-components";
-import { UrlLinkField } from "../types";
+import { type UrlLinkField } from "../types";
 import { hasSetValue } from "../utils";
 
 const populate = (str: string, obj: unknown) => {
@@ -49,7 +49,7 @@ const UrlLink = (props: UrlLinkField) => {
     <>
       <Label>{label}</Label>
       <StyledServiceRow>
-        <a href={populatedUrl} target="_blank">
+        <a href={populatedUrl} target="_blank" rel="noreferrer">
           <i className="material-icons-outlined">link</i>
           {populatedUrl}
         </a>

+ 1 - 1
dashboard/src/components/porter-form/field-components/VeleroForm.tsx

@@ -36,7 +36,7 @@ export default class VeleroForm extends Component<PropsType, StateType> {
           type="text"
           width="300px"
           value={this.state.name}
-          setValue={(x: string) => this.setState({ name: x })}
+          setValue={(x: string) => { this.setState({ name: x }); }}
           label="Name"
         />
         <MultiSelect />

+ 6 - 6
dashboard/src/components/porter-form/hooks/useFormField.tsx

@@ -1,15 +1,15 @@
 import { useContext, useEffect } from "react";
 import { PorterFormContext } from "../PorterFormContextProvider";
 import {
-  PorterFormFieldFieldState,
-  PorterFormFieldValidationState,
-  PorterFormVariableList,
+  type PorterFormFieldFieldState,
+  type PorterFormFieldValidationState,
+  type PorterFormVariableList,
 } from "../types";
 
-interface FormFieldData<T> {
+type FormFieldData<T> = {
   state: T;
   variables: PorterFormVariableList;
-  validation: { [key: string]: PorterFormFieldValidationState };
+  validation: Record<string, PorterFormFieldValidationState>;
   setState: (setFunc: (prev: T) => Partial<T>) => void;
   setVars: (
     setFunc: (vars: PorterFormVariableList) => PorterFormVariableList
@@ -21,7 +21,7 @@ interface FormFieldData<T> {
   ) => void;
 }
 
-interface Options<T> {
+type Options<T> = {
   initState?: T | (() => T);
   initValidation?: Partial<PorterFormFieldValidationState>;
   initVars?: PorterFormVariableList;

+ 5 - 5
dashboard/src/components/porter-form/utils.ts

@@ -1,20 +1,20 @@
 import { merge, unionBy } from "lodash";
 import { KeyValueType } from "main/home/cluster-dashboard/env-groups/EnvGroupArray";
-import { GenericInputField } from "./types";
+import { type GenericInputField } from "./types";
 
 export const hasSetValue = (field: GenericInputField) => {
   return field.value && field.value.length != 0 && field.value[0] != null;
 };
 
 export const fillWithDeletedVariables = (
-  originalValues: {
+  originalValues: Array<{
     key: string;
     value: string;
-  }[],
-  newValues: {
+  }>,
+  newValues: Array<{
     key: string;
     value: string;
-  }[]
+  }>
 ) => {
   const filledArray = originalValues.map((originalVal) => {
     const foundNewValue = newValues.find(

+ 3 - 3
dashboard/src/components/porter/ExpandableSection.tsx

@@ -44,7 +44,7 @@ const ExpandableSection: React.FC<Props> = ({
           {copy ?
             (
               <CopyWrapper>
-                <ExpandButton onClick={() => setIsExpanded(!isExpanded)}>
+                <ExpandButton onClick={() => { setIsExpanded(!isExpanded); }}>
                   {isExpanded ? collapseText : expandText}
                 </ExpandButton>
                 <CopyToClipboard
@@ -59,7 +59,7 @@ const ExpandableSection: React.FC<Props> = ({
               </CopyWrapper>
             ) :
             (
-              <ExpandButton onClick={() => setIsExpanded(!isExpanded)}>
+              <ExpandButton onClick={() => { setIsExpanded(!isExpanded); }}>
                 {isExpanded ? collapseText : expandText}
               </ExpandButton>
             )
@@ -68,7 +68,7 @@ const ExpandableSection: React.FC<Props> = ({
       ) : (
         <HeaderRow
           isExpanded={isExpanded}
-          onClick={() => setIsExpanded(!isExpanded)}
+          onClick={() => { setIsExpanded(!isExpanded); }}
           color={color}
         >
           {!noWrapper && <i className="material-icons">arrow_drop_down</i>}

+ 6 - 6
dashboard/src/components/porter/Filter.tsx

@@ -4,7 +4,7 @@ import Select from "./Select";
 import Spacer from "./Spacer";
 
 import filter from "assets/filter.svg";
-import { GenericFilter, FilterName } from "main/home/app-dashboard/expanded-app/logs/types";
+import { type GenericFilter, type FilterName } from "main/home/app-dashboard/expanded-app/logs/types";
 
 type Props = {
   filters: GenericFilter[];
@@ -19,9 +19,9 @@ const Filter: React.FC<Props> = ({
 
   const filterLabelString = useMemo(() => {
     let filterString = "";
-    const serviceName = selectedFilterValues["service_name"];
-    const podName = selectedFilterValues["pod_name"];
-    const revision = selectedFilterValues["revision"];
+    const serviceName = selectedFilterValues.service_name;
+    const podName = selectedFilterValues.pod_name;
+    const revision = selectedFilterValues.revision;
 
     if (serviceName && serviceName !== "all") {
       filterString += serviceName;
@@ -39,7 +39,7 @@ const Filter: React.FC<Props> = ({
 
   return (
     <Relative>
-      <StyledFilter onClick={() => setIsExpanded(!isExpanded)}>
+      <StyledFilter onClick={() => { setIsExpanded(!isExpanded); }}>
         <img src={filter} />
         Filter
         {filterLabelString !== "" && (
@@ -50,7 +50,7 @@ const Filter: React.FC<Props> = ({
           </>
         )}
       </StyledFilter>
-      <CloseOverlay onClick={() => setIsExpanded(false)} isExpanded={isExpanded} />
+      <CloseOverlay onClick={() => { setIsExpanded(false); }} isExpanded={isExpanded} />
       <Dropdown isExpanded={isExpanded}>
         {filters.map((filter: GenericFilter, i: number) => {
           return (

+ 6 - 6
dashboard/src/components/porter/InputSlider.tsx

@@ -1,5 +1,5 @@
 import React, { useEffect, useState } from 'react';
-import Slider, { Mark } from '@material-ui/core/Slider';
+import Slider, { type Mark } from '@material-ui/core/Slider';
 import Tooltip from '@material-ui/core/Tooltip';
 import Typography from '@material-ui/core/Typography';
 import styled from 'styled-components';
@@ -66,9 +66,9 @@ const InputSlider: React.FC<InputSliderProps> = ({
       label: max.toString(),
     },
   ];
-  var isExceedingLimit = false;
-  var displayOptimalText = false;
-  //Optimal Marks only give useful information to user if they are using more than 2 nodes
+  let isExceedingLimit = false;
+  let displayOptimalText = false;
+  // Optimal Marks only give useful information to user if they are using more than 2 nodes
   // if (optimal != 0 && nodeCount && nodeCount > 2) {
   //   marks.push({
   //     value: optimal,
@@ -162,7 +162,7 @@ const InputSlider: React.FC<InputSliderProps> = ({
                 valueLabelDisplay={smartLimit && Number(value) > smartLimit ? "off" : "auto"}
                 disabled={disabled}
                 marks={marks}
-                step={(step ? step : 1)}
+                step={(step || 1)}
                 style={{
                   color: disabled ? "gray" : color,
                 }}
@@ -251,7 +251,7 @@ const MaxedOutToolTip = withStyles(theme => ({
 
 const StyledSlider = withStyles({
   root: {
-    height: '8px', //height of the track
+    height: '8px', // height of the track
   },
   mark: {
     backgroundColor: '#fff',  // mark color

+ 2 - 2
dashboard/src/components/porter/Pagination.tsx

@@ -21,7 +21,7 @@ const Pagination: React.FC<Props> = ({
       <Text color="helper">Viewing page {page} out of {totalPages}</Text>
       <Container row>
         <Button 
-          onClick={() => setPage(page - 1)} 
+          onClick={() => { setPage(page - 1); }} 
           disabled={page === 1}
           height="20px"
           color="fg"
@@ -31,7 +31,7 @@ const Pagination: React.FC<Props> = ({
         </Button>
         <Spacer inline x={0.5} />
         <Button 
-          onClick={() => setPage(page + 1)}
+          onClick={() => { setPage(page + 1); }}
           disabled={page === totalPages}
           height="20px"
           color="fg"

+ 1 - 1
dashboard/src/components/porter/SearchBar.tsx

@@ -56,7 +56,7 @@ const SearchBar: React.FC<Props> = ({
         <Icon src={search} />
         <Input
           value={value}
-          onChange={e => setValue(e.target.value)}
+          onChange={e => { setValue(e.target.value); }}
           placeholder={placeholder}
           type={type || "text"}
           autoFocus={autoFocus}

+ 7 - 7
dashboard/src/components/repo-selector/ActionConfEditor.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import styled from "styled-components";
 
-import { ActionConfigType } from "shared/types";
+import { type ActionConfigType } from "shared/types";
 
 import RepoList from "./RepoList";
 import BranchList from "./BranchList";
@@ -43,7 +43,7 @@ const ActionConfEditor: React.FC<Props> = (props) => {
       <ExpandedWrapperAlt>
         <RepoList
           actionConfig={actionConfig}
-          setActionConfig={(x: ActionConfigType) => setActionConfig(x)}
+          setActionConfig={(x: ActionConfigType) => { setActionConfig(x); }}
           readOnly={false}
         />
       </ExpandedWrapperAlt>
@@ -54,7 +54,7 @@ const ActionConfEditor: React.FC<Props> = (props) => {
         <ExpandedWrapperAlt>
           <BranchList
             actionConfig={actionConfig}
-            setBranch={(branch: string) => setBranch(branch)}
+            setBranch={(branch: string) => { setBranch(branch); }}
           />
         </ExpandedWrapperAlt>
         <Br />
@@ -89,10 +89,10 @@ const ActionConfEditor: React.FC<Props> = (props) => {
           procfilePath={props.procfilePath}
           folderPath={props.folderPath}
           setActionConfig={setActionConfig}
-          setDockerfilePath={(x: string) => props.setDockerfilePath(x)}
-          setProcfilePath={(x: string) => props.setProcfilePath(x)}
-          setProcfileProcess={(x: string) => props.setProcfileProcess(x)}
-          setFolderPath={(x: string) => props.setFolderPath(x)}
+          setDockerfilePath={(x: string) => { props.setDockerfilePath(x); }}
+          setProcfilePath={(x: string) => { props.setProcfilePath(x); }}
+          setProcfileProcess={(x: string) => { props.setProcfileProcess(x); }}
+          setFolderPath={(x: string) => { props.setFolderPath(x); }}
         />
         <Br />
         <BackButton

+ 8 - 9
dashboard/src/components/repo-selector/ActionDetails.tsx

@@ -5,7 +5,7 @@ import { integrationList } from "shared/common";
 import { Context } from "shared/Context";
 import api from "shared/api";
 import Loading from "components/Loading";
-import { ActionConfigType } from "../../shared/types";
+import { type ActionConfigType } from "../../shared/types";
 import InputRow from "../form-components/InputRow";
 import Heading from "components/form-components/Heading";
 import { BuildpackSelection } from "./BuildpackSelection";
@@ -59,7 +59,7 @@ const ActionDetails: React.FC<PropsType> = (props) => {
           setSelectedRegistry(res.data[0]);
         }
       })
-      .catch((err: any) => console.log(err));
+      .catch((err: any) => { console.log(err); });
   }, [currentProject]);
 
   const renderIntegrationList = () => {
@@ -73,11 +73,10 @@ const ActionDetails: React.FC<PropsType> = (props) => {
 
     return registries.map((registry: any, i: number) => {
       let icon =
-        integrationList[registry?.service] &&
         integrationList[registry?.service]?.icon;
 
       if (!icon) {
-        icon = integrationList["dockerhub"]?.icon;
+        icon = integrationList.dockerhub?.icon;
       }
 
       return (
@@ -85,7 +84,7 @@ const ActionDetails: React.FC<PropsType> = (props) => {
           key={i}
           isSelected={selectedRegistry && registry.id === selectedRegistry?.id}
           lastItem={i === registries?.length - 1}
-          onClick={() => setSelectedRegistry(registry)}
+          onClick={() => { setSelectedRegistry(registry); }}
         >
           <img src={icon && icon} />
           {registry.url}
@@ -96,7 +95,7 @@ const ActionDetails: React.FC<PropsType> = (props) => {
 
   const renderRegistrySection = () => {
     if (!registries || registries.length === 0 || registries.length === 1) {
-      return;
+      
     } else {
       return (
         <>
@@ -143,9 +142,9 @@ const ActionDetails: React.FC<PropsType> = (props) => {
         type="text"
         width="100%"
         setValue={(value) =>
-          typeof value === "string" && dockerfilePath
+          { typeof value === "string" && dockerfilePath
             ? setFolderPath(value)
-            : typeof value === "string" && setProcfilePath(value)
+            : typeof value === "string" && setProcfilePath(value); }
         }
         value={
           dockerfilePath
@@ -163,7 +162,7 @@ const ActionDetails: React.FC<PropsType> = (props) => {
         <>
           <Heading>
             <ExpandHeader
-              onClick={() => setShowBuildpacksConfig((prev) => !prev)}
+              onClick={() => { setShowBuildpacksConfig((prev) => !prev); }}
               isExpanded={showBuildpacksConfig}
             >
               Buildpacks settings

+ 3 - 3
dashboard/src/components/repo-selector/BranchList.tsx

@@ -4,7 +4,7 @@ import branch_icon from "assets/branch.png";
 
 import api from "../../shared/api";
 import { Context } from "../../shared/Context";
-import { ActionConfigType } from "../../shared/types";
+import { type ActionConfigType } from "../../shared/types";
 
 import Loading from "../Loading";
 import SearchBar from "../SearchBar";
@@ -100,7 +100,7 @@ const BranchList: React.FC<Props> = ({
       return <LoadingWrapper>Error loading branches</LoadingWrapper>;
     }
 
-    let results =
+    const results =
       searchFilter != null
         ? branches
             .filter((branch) => {
@@ -125,7 +125,7 @@ const BranchList: React.FC<Props> = ({
         <BranchName
           key={i}
           lastItem={i === branches.length - 1}
-          onClick={() => setBranch(branch)}
+          onClick={() => { setBranch(branch); }}
         >
           <img src={branch_icon} alt={"branch icon"} />
           {branch}

+ 14 - 18
dashboard/src/components/repo-selector/BuildpackSelection.tsx

@@ -6,7 +6,7 @@ import Loading from "components/Loading";
 import React, { useContext, useEffect, useMemo, useState } from "react";
 import api from "shared/api";
 import { Context } from "shared/Context";
-import { ActionConfigType } from "shared/types";
+import { type ActionConfigType } from "shared/types";
 import styled, { keyframes } from "styled-components";
 
 const DEFAULT_BUILDER_NAME = "heroku";
@@ -16,17 +16,13 @@ const DEFAULT_HEROKU_STACK = "heroku/buildpacks:20";
 type BuildConfig = {
   builder: string;
   buildpacks: string[];
-  config: null | {
-    [key: string]: string;
-  };
+  config: null | Record<string, string>;
 };
 
 type Buildpack = {
   name: string;
   buildpack: string;
-  config: {
-    [key: string]: string;
-  };
+  config: Record<string, string>;
 };
 
 type DetectedBuildpack = {
@@ -59,7 +55,7 @@ export const BuildpackSelection: React.FC<{
   );
 
   useEffect(() => {
-    let buildConfig: BuildConfig = {} as BuildConfig;
+    const buildConfig: BuildConfig = {} as BuildConfig;
     buildConfig.builder = selectedStack;
     buildConfig.buildpacks = selectedBuildpacks?.map((buildpack) => {
       return buildpack.buildpack;
@@ -69,13 +65,13 @@ export const BuildpackSelection: React.FC<{
     }
   }, [selectedBuilder, selectedStack, selectedBuildpacks]);
 
-  const detectBuildpack = () => {
+  const detectBuildpack = async () => {
     if (actionConfig.kind === "gitlab") {
-      return api.detectGitlabBuildpack<DetectBuildpackResponse>(
+      return await api.detectGitlabBuildpack<DetectBuildpackResponse>(
         "<token>",
         {
           repo_path: actionConfig.git_repo,
-          branch: branch,
+          branch,
           dir: folderPath || ".",
         },
         {
@@ -85,7 +81,7 @@ export const BuildpackSelection: React.FC<{
       );
     }
 
-    return api.detectBuildpack<DetectBuildpackResponse>(
+    return await api.detectBuildpack<DetectBuildpackResponse>(
       "<token>",
       {
         dir: folderPath || ".",
@@ -96,7 +92,7 @@ export const BuildpackSelection: React.FC<{
         kind: "github",
         owner: actionConfig.git_repo.split("/")[0],
         name: actionConfig.git_repo.split("/")[1],
-        branch: branch,
+        branch,
       }
     );
   };
@@ -219,14 +215,14 @@ export const BuildpackSelection: React.FC<{
           <ActionContainer>
             {action === "add" && (
               <ActionButton
-                onClick={() => handleAddBuildpack(buildpack.buildpack)}
+                onClick={() => { handleAddBuildpack(buildpack.buildpack); }}
               >
                 <span className="material-icons-outlined">add</span>
               </ActionButton>
             )}
             {action === "remove" && (
               <ActionButton
-                onClick={() => handleRemoveBuildpack(buildpack.buildpack)}
+                onClick={() => { handleRemoveBuildpack(buildpack.buildpack); }}
               >
                 <span className="material-icons">delete</span>
               </ActionButton>
@@ -297,7 +293,7 @@ export const BuildpackSelection: React.FC<{
           value={selectedBuilder}
           width="100%"
           options={builderOptions}
-          setActiveValue={(option) => handleSelectBuilder(option)}
+          setActiveValue={(option) => { handleSelectBuilder(option); }}
           label="Select a builder"
         />
 
@@ -305,7 +301,7 @@ export const BuildpackSelection: React.FC<{
           value={selectedStack}
           width="100%"
           options={stackOptions}
-          setActiveValue={(option) => setSelectedStack(option)}
+          setActiveValue={(option) => { setSelectedStack(option); }}
           label="Select your stack"
         />
         <Helper>
@@ -367,7 +363,7 @@ export const AddCustomBuildpackForm: React.FC<{
         </EventInformation>
       </ContentContainer>
       <ActionContainer>
-        <ActionButton onClick={() => handleAddCustomBuildpack()}>
+        <ActionButton onClick={() => { handleAddCustomBuildpack(); }}>
           <span className="material-icons-outlined">add</span>
         </ActionButton>
       </ActionContainer>

+ 50 - 50
dashboard/src/components/repo-selector/ContentsList.tsx

@@ -7,11 +7,11 @@ import close from "assets/close.png";
 
 import api from "../../shared/api";
 import { Context } from "../../shared/Context";
-import { ActionConfigType, FileType } from "../../shared/types";
+import { type ActionConfigType, type FileType } from "../../shared/types";
 
 import Loading from "../Loading";
 
-interface AutoBuildpack {
+type AutoBuildpack = {
   name?: string;
   valid: boolean;
 }
@@ -60,20 +60,20 @@ export default class ContentsList extends Component<PropsType, StateType> {
   }
 
   setSubdirectory = (x: string) => {
-    this.setState({ currentDir: x }, () => this.updateContents());
+    this.setState({ currentDir: x }, () => { this.updateContents(); });
   };
 
-  fetchContents = () => {
-    let { currentProject } = this.context;
+  fetchContents = async () => {
+    const { currentProject } = this.context;
     const { actionConfig, branch } = this.props;
 
     if (actionConfig.kind === "gitlab") {
-      return api
+      return await api
         .getGitlabFolderContent(
           "<token>",
           {
             repo_path: actionConfig.git_repo,
-            branch: branch,
+            branch,
             dir: this.state.currentDir || "./",
           },
           {
@@ -92,7 +92,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
           };
         });
     }
-    return api.getBranchContents(
+    return await api.getBranchContents(
       "<token>",
       { dir: this.state.currentDir || "./" },
       {
@@ -101,17 +101,17 @@ export default class ContentsList extends Component<PropsType, StateType> {
         kind: "github",
         owner: actionConfig.git_repo.split("/")[0],
         name: actionConfig.git_repo.split("/")[1],
-        branch: branch,
+        branch,
       }
     );
   };
 
-  detectBuildpacks = () => {
-    let { currentProject } = this.context;
-    let { actionConfig, branch } = this.props;
+  detectBuildpacks = async () => {
+    const { currentProject } = this.context;
+    const { actionConfig, branch } = this.props;
 
     if (actionConfig.kind === "github") {
-      return api.detectBuildpack(
+      return await api.detectBuildpack(
         "<token>",
         {
           dir: this.state.currentDir || ".",
@@ -122,16 +122,16 @@ export default class ContentsList extends Component<PropsType, StateType> {
           kind: "github",
           owner: actionConfig.git_repo.split("/")[0],
           name: actionConfig.git_repo.split("/")[1],
-          branch: branch,
+          branch,
         }
       );
     }
 
-    return api.detectGitlabBuildpack(
+    return await api.detectGitlabBuildpack(
       "<token>",
       {
         repo_path: actionConfig.git_repo,
-        branch: branch,
+        branch,
         dir: this.state.currentDir || ".",
       },
       {
@@ -141,11 +141,11 @@ export default class ContentsList extends Component<PropsType, StateType> {
     );
   };
 
-  fetchProcfileContent = (procfilePath: string) => {
-    let { currentProject } = this.context;
-    let { actionConfig, branch } = this.props;
+  fetchProcfileContent = async (procfilePath: string) => {
+    const { currentProject } = this.context;
+    const { actionConfig, branch } = this.props;
     if (actionConfig.kind === "github") {
-      return api.getProcfileContents(
+      return await api.getProcfileContents(
         "<token>",
         {
           path: procfilePath,
@@ -156,16 +156,16 @@ export default class ContentsList extends Component<PropsType, StateType> {
           kind: "github",
           owner: actionConfig.git_repo.split("/")[0],
           name: actionConfig.git_repo.split("/")[1],
-          branch: branch,
+          branch,
         }
       );
     }
 
-    return api.getGitlabProcfileContents(
+    return await api.getGitlabProcfileContents(
       "<token>",
       {
         repo_path: actionConfig.git_repo,
-        branch: branch,
+        branch,
         path: procfilePath,
       },
       {
@@ -179,8 +179,8 @@ export default class ContentsList extends Component<PropsType, StateType> {
     // Get branch contents
     this.fetchContents()
       .then((res) => {
-        let files = [] as FileType[];
-        let folders = [] as FileType[];
+        const files = [] as FileType[];
+        const folders = [] as FileType[];
         res.data.map((x: FileType, i: number) => {
           x.type === "dir" ? folders.push(x) : files.push(x);
         });
@@ -191,7 +191,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
         files.sort((a: FileType, b: FileType) => {
           return a.path < b.path ? 1 : 0;
         });
-        let contents = folders.concat(files);
+        const contents = folders.concat(files);
 
         this.setState({ contents, loading: false, error: false });
       })
@@ -216,7 +216,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
         });
       });
 
-    let ppath =
+    const ppath =
       this.props.procfilePath ||
       `${this.state.currentDir ? this.state.currentDir : "."}/Procfile`;
     this.fetchProcfileContent(ppath)
@@ -229,7 +229,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
   };
 
   renderContentList = () => {
-    let { contents, loading, error } = this.state;
+    const { contents, loading, error } = this.state;
     if (loading) {
       return (
         <LoadingWrapper>
@@ -240,15 +240,15 @@ export default class ContentsList extends Component<PropsType, StateType> {
       return <LoadingWrapper>Error loading repo contents.</LoadingWrapper>;
     }
     return contents.map((item: FileType, i: number) => {
-      let splits = item.path.split("/");
-      let fileName = splits[splits.length - 1];
+      const splits = item.path.split("/");
+      const fileName = splits[splits.length - 1];
       if (item.type === "dir") {
         return (
           <Item
             key={i}
             isSelected={item.path === this.state.currentDir}
             lastItem={i === contents.length - 1}
-            onClick={() => this.setSubdirectory(item.path)}
+            onClick={() => { this.setSubdirectory(item.path); }}
           >
             <img src={folder} />
             {fileName}
@@ -262,7 +262,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
             key={i}
             lastItem={i === contents.length - 1}
             isADocker
-            onClick={() => this.props.setDockerfilePath(item.path)}
+            onClick={() => { this.props.setDockerfilePath(item.path); }}
           >
             <img src={file} />
             {fileName}
@@ -281,7 +281,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
 
   renderJumpToParent = () => {
     if (this.state.currentDir !== "") {
-      let splits = this.state.currentDir.split("/");
+      const splits = this.state.currentDir.split("/");
       let subdir = "";
       if (splits.length !== 1) {
         subdir = this.state.currentDir.replace(splits[splits.length - 1], "");
@@ -291,7 +291,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
       }
 
       return (
-        <Item lastItem={false} onClick={() => this.setSubdirectory(subdir)}>
+        <Item lastItem={false} onClick={() => { this.setSubdirectory(subdir); }}>
           <BackLabel>..</BackLabel>
         </Item>
       );
@@ -314,10 +314,10 @@ export default class ContentsList extends Component<PropsType, StateType> {
       return;
     }
 
-    let dockerfiles = [] as string[];
+    const dockerfiles = [] as string[];
     this.state.contents.forEach((item: FileType, i: number) => {
-      let splits = item.path.split("/");
-      let fileName = splits[splits.length - 1];
+      const splits = item.path.split("/");
+      const fileName = splits[splits.length - 1];
       if (fileName.includes("Dockerfile")) {
         dockerfiles.push(fileName);
       }
@@ -338,7 +338,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
 
   renderOverlay = () => {
     if (this.props.procfilePath) {
-      let processes = this.state.processes
+      const processes = this.state.processes
         ? Object.keys(this.state.processes)
         : [];
       if (this.state.processes == null) {
@@ -361,17 +361,17 @@ export default class ContentsList extends Component<PropsType, StateType> {
         <Overlay>
           <BgOverlay
             onClick={() =>
-              this.setState({ dockerfiles: [] }, () => {
+              { this.setState({ dockerfiles: [] }, () => {
                 this.props.setFolderPath("");
                 this.props.setProcfilePath("");
-              })
+              }); }
             }
           />
           <CloseButton
             onClick={() =>
-              this.setState({ dockerfiles: [] }, () => {
+              { this.setState({ dockerfiles: [] }, () => {
                 this.props.setProcfilePath("");
-              })
+              }); }
             }
           >
             <CloseButtonImg src={close} />
@@ -408,8 +408,8 @@ export default class ContentsList extends Component<PropsType, StateType> {
     if (this.state.dockerfiles.length > 0 && !this.props.dockerfilePath) {
       return (
         <Overlay>
-          <BgOverlay onClick={() => this.setState({ dockerfiles: [] })} />
-          <CloseButton onClick={() => this.setState({ dockerfiles: [] })}>
+          <BgOverlay onClick={() => { this.setState({ dockerfiles: [] }); }} />
+          <CloseButton onClick={() => { this.setState({ dockerfiles: [] }); }}>
             <CloseButtonImg src={close} />
           </CloseButton>
           <Label>
@@ -422,9 +422,9 @@ export default class ContentsList extends Component<PropsType, StateType> {
                 <Row
                   key={i}
                   onClick={() =>
-                    this.props.setDockerfilePath(
+                    { this.props.setDockerfilePath(
                       `${this.state.currentDir || "."}/${dockerfile}`
-                    )
+                    ); }
                   }
                   isLast={this.state.dockerfiles.length - 1 === i}
                 >
@@ -457,10 +457,10 @@ export default class ContentsList extends Component<PropsType, StateType> {
     ) {
       return (
         <Overlay>
-          <BgOverlay onClick={() => this.props.setDockerfilePath("")} />
+          <BgOverlay onClick={() => { this.props.setDockerfilePath(""); }} />
           <CloseButton
             onClick={() =>
-              this.props.setFolderPath(this.state.currentDir || "./")
+              { this.props.setFolderPath(this.state.currentDir || "./"); }
             }
           >
             <CloseButtonImg src={close} />
@@ -480,7 +480,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
             </ConfirmButton>
             <ConfirmButton
               onClick={() =>
-                this.props.setFolderPath(this.state.currentDir || "./")
+                { this.props.setFolderPath(this.state.currentDir || "./"); }
               }
             >
               No
@@ -501,7 +501,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
               <b>{this.state.autoBuildpack.name}</b> buildpack was{" "}
               <a
                 href="https://docs.porter.run/deploying-applications/deploying-from-github/selecting-application-and-build-method#customizing-buildpacks"
-                target="_blank"
+                target="_blank" rel="noreferrer"
               >
                 detected automatically
               </a>

+ 8 - 8
dashboard/src/components/repo-selector/RepoList.tsx

@@ -3,7 +3,7 @@ import styled from "styled-components";
 import github from "assets/github-white.png";
 
 import api from "shared/api";
-import { ActionConfigType, RepoType } from "shared/types";
+import { type ActionConfigType, type RepoType } from "shared/types";
 import { Context } from "shared/Context";
 
 import Loading from "../Loading";
@@ -106,7 +106,7 @@ const RepoList: React.FC<Props> = ({
   const loadGithubRepos = async (repoId: number) => {
     try {
       const res = await api.getGitRepoList<
-        { FullName: string; Kind: "github" }[]
+        Array<{ FullName: string; Kind: "github" }>
       >("<token>", {}, { project_id: currentProject.id, git_repo_id: repoId });
 
       const repos = res.data.map((repo) => ({ ...repo, GHRepoID: repoId }));
@@ -132,11 +132,11 @@ const RepoList: React.FC<Props> = ({
     } catch (error) { }
   };
 
-  const loadRepos = (provider: any) => {
+  const loadRepos = async (provider: any) => {
     if (provider.provider === "github") {
-      return loadGithubRepos(provider.installation_id);
+      return await loadGithubRepos(provider.installation_id);
     } else {
-      return loadGitlabRepos(provider.integration_id);
+      return await loadGitlabRepos(provider.integration_id);
     }
   };
 
@@ -240,7 +240,7 @@ const RepoList: React.FC<Props> = ({
     }
 
     // show 10 most recently used repos if user hasn't searched anything yet
-    let results =
+    const results =
       searchFilter != null
         ? repos
           .filter((repo: RepoType) => {
@@ -271,7 +271,7 @@ const RepoList: React.FC<Props> = ({
             key={i}
             isSelected={repo.FullName === selectedRepo}
             lastItem={i === repos.length - 1}
-            onClick={() => setRepo(repo)}
+            onClick={() => { setRepo(repo); }}
             readOnly={readOnly}
             disabled={shouldDisable}
           >
@@ -417,7 +417,7 @@ const ProviderSelector = (props: {
         <ProviderSelectorStyles.Icon className={icon} />
 
         <ProviderSelectorStyles.Button
-          onClick={() => setIsOpen((prev) => !prev)}
+          onClick={() => { setIsOpen((prev) => !prev); }}
         >
           {currentValue?.name || currentValue?.instance_url}
         </ProviderSelectorStyles.Button>

+ 2 - 2
dashboard/src/main/CurrentError.tsx

@@ -42,7 +42,7 @@ export default class CurrentError extends Component<PropsType, StateType> {
         return (
           <StyledCurrentError>
             <ErrorText>Error: {currentError}</ErrorText>
-            <ExpandButton onClick={() => this.setState({ expanded: true })}>
+            <ExpandButton onClick={() => { this.setState({ expanded: true }); }}>
               <i className="material-icons">launch</i>
             </ExpandButton>
             <CloseButton
@@ -65,7 +65,7 @@ export default class CurrentError extends Component<PropsType, StateType> {
           <ExpandedError>
             Porter encountered an error. Full error log:
             <CodeBlock>{currentError}</CodeBlock>
-            <ExpandButtonAlt onClick={() => this.setState({ expanded: false })}>
+            <ExpandButtonAlt onClick={() => { this.setState({ expanded: false }); }}>
               <i className="material-icons">remove</i>
             </ExpandButtonAlt>
             <CloseButtonAlt

+ 15 - 15
dashboard/src/main/auth/ResetPasswordFinalize.tsx

@@ -1,4 +1,4 @@
-import React, { ChangeEvent, Component } from "react";
+import React, { type ChangeEvent, Component } from "react";
 import styled from "styled-components";
 import logo from "assets/logo.png";
 
@@ -36,11 +36,11 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   };
 
   componentDidMount() {
-    let urlParams = new URLSearchParams(window.location.search);
+    const urlParams = new URLSearchParams(window.location.search);
 
-    let emailFromParam = urlParams.get("email");
-    let tokenFromParams = urlParams.get("token");
-    let tokenIDFromParams = urlParams.get("token_id");
+    const emailFromParam = urlParams.get("email");
+    const tokenFromParams = urlParams.get("token");
+    const tokenIDFromParams = urlParams.get("token_id");
 
     api
       .createPasswordResetVerify(
@@ -55,7 +55,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
       .then(() => {
         this.setState({ loading: false });
       })
-      .catch((err) => this.setState({ loading: false, tokenError: true }));
+      .catch((err) => { this.setState({ loading: false, tokenError: true }); });
 
     document.addEventListener("keydown", this.handleKeyDown);
 
@@ -71,7 +71,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   }
 
   renderPasswordError = () => {
-    let { passwordError } = this.state;
+    const { passwordError } = this.state;
     if (passwordError) {
       return (
         <ErrorHelper>
@@ -83,16 +83,16 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   };
 
   handleResetPasswordFinalize = (): void => {
-    let { email, token, token_id, password } = this.state;
+    const { email, token, token_id, password } = this.state;
 
     // Call reset password
     api
       .createPasswordResetFinalize(
         "",
         {
-          email: email,
-          token: token,
-          token_id: token_id,
+          email,
+          token,
+          token_id,
           new_password: password,
         },
         {}
@@ -105,11 +105,11 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
           window.location.href = "/login";
         }, 2000);
       })
-      .catch((err) => this.setState({ tokenError: true }));
+      .catch((err) => { this.setState({ tokenError: true }); });
   };
 
   render() {
-    let {
+    const {
       password,
       passwordError,
       submitted,
@@ -125,10 +125,10 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
             placeholder="Password"
             value={password}
             onChange={(e: ChangeEvent<HTMLInputElement>) =>
-              this.setState({
+              { this.setState({
                 password: e.target.value,
                 passwordError: false,
-              })
+              }); }
             }
             valid={!passwordError}
           />

+ 7 - 7
dashboard/src/main/auth/ResetPasswordInit.tsx

@@ -1,4 +1,4 @@
-import React, { ChangeEvent, Component } from "react";
+import React, { type ChangeEvent, Component } from "react";
 import styled from "styled-components";
 import logo from "assets/logo.png";
 
@@ -34,7 +34,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   }
 
   renderEmailError = () => {
-    let { emailError } = this.state;
+    const { emailError } = this.state;
     if (emailError) {
       return (
         <ErrorHelper>
@@ -46,7 +46,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   };
 
   handleResetPasswordInit = (): void => {
-    let { email } = this.state;
+    const { email } = this.state;
 
     // Check for valid input
     if (!emailRegex.test(email)) {
@@ -57,7 +57,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
         .createPasswordReset(
           "",
           {
-            email: email,
+            email,
           },
           {}
         )
@@ -69,7 +69,7 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
   };
 
   render() {
-    let { email, emailError, submitted } = this.state;
+    const { email, emailError, submitted } = this.state;
 
     let formSection = (
       <div>
@@ -79,10 +79,10 @@ export default class ResetPasswordInit extends Component<PropsType, StateType> {
             placeholder="Email"
             value={email}
             onChange={(e: ChangeEvent<HTMLInputElement>) =>
-              this.setState({
+              { this.setState({
                 email: e.target.value,
                 emailError: false,
-              })
+              }); }
             }
             valid={!emailError}
           />

+ 14 - 14
dashboard/src/main/home/ModalHandler.tsx

@@ -15,7 +15,7 @@ import RedirectToOnboardingModal from "./modals/RedirectToOnboardingModal";
 
 import UsageWarningModal from "./modals/UsageWarningModal";
 import api from "shared/api";
-import { AxiosError } from "axios";
+import { type AxiosError } from "axios";
 import SkipOnboardingModal from "./modals/SkipProvisioningModal";
 import ConnectToDatabaseInstructionsModal from "./modals/ConnectToDatabaseInstructionsModal";
 
@@ -101,7 +101,7 @@ const ModalHandler: React.FC<{
 
       {modal === "ClusterInstructionsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="650px"
           title="Connecting to an Existing Cluster"
@@ -114,19 +114,19 @@ const ModalHandler: React.FC<{
       {isAuth("cluster", "", ["get", "delete"]) &&
         modal === "UpdateClusterModal" && (
           <Modal
-            onRequestClose={() => setCurrentModal(null, null)}
+            onRequestClose={() => { setCurrentModal(null, null); }}
             width="600px"
             height="275px"
             title="Delete cluster"
           >
             <UpdateClusterModal
-              setRefreshClusters={(x: boolean) => setRefreshClusters(x)}
+              setRefreshClusters={(x: boolean) => { setRefreshClusters(x); }}
             />
           </Modal>
         )}
       {modal === "IntegrationsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="380px"
           title="Add a New Integration"
@@ -136,7 +136,7 @@ const ModalHandler: React.FC<{
       )}
       {modal === "IntegrationsInstructionsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="650px"
           title="Connecting to an Image Registry"
@@ -147,7 +147,7 @@ const ModalHandler: React.FC<{
       {isAuth("namespace", "", ["get", "create"]) &&
         modal === "NamespaceModal" && (
           <Modal
-            onRequestClose={() => setCurrentModal(null, null)}
+            onRequestClose={() => { setCurrentModal(null, null); }}
             width="600px"
             height="220px"
             title="Add namespace"
@@ -158,7 +158,7 @@ const ModalHandler: React.FC<{
       {isAuth("namespace", "", ["get", "delete"]) &&
         modal === "DeleteNamespaceModal" && (
           <Modal
-            onRequestClose={() => setCurrentModal(null, null)}
+            onRequestClose={() => { setCurrentModal(null, null); }}
             width="700px"
             height="280px"
             title="Delete Namespace"
@@ -169,7 +169,7 @@ const ModalHandler: React.FC<{
 
       {modal === "EditInviteOrCollaboratorModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="600px"
           height="250px"
         >
@@ -178,7 +178,7 @@ const ModalHandler: React.FC<{
       )}
       {modal === "AccountSettingsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="480px"
           title="Account Settings"
@@ -189,7 +189,7 @@ const ModalHandler: React.FC<{
 
       {modal === "PreviewEnvSettingsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="440px"
           title="Preview Environment Settings"
@@ -200,7 +200,7 @@ const ModalHandler: React.FC<{
 
       {modal === "UsageWarningModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="760px"
           height="530px"
           title="Usage Warning"
@@ -211,7 +211,7 @@ const ModalHandler: React.FC<{
 
       {modal === "SkipOnboardingModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="600px"
           height="240px"
           title="Would you like to skip project setup?"
@@ -221,7 +221,7 @@ const ModalHandler: React.FC<{
       )}
       {modal === "ConnectToDatabaseInstructionsModal" && (
         <Modal
-          onRequestClose={() => setCurrentModal(null, null)}
+          onRequestClose={() => { setCurrentModal(null, null); }}
           width="600px"
           height="350px"
           title="Connecting to the Database"

+ 4 - 4
dashboard/src/main/home/NoClusterPlaceholder.tsx

@@ -1,6 +1,6 @@
 import React, { Component } from "react";
 import styled from "styled-components";
-import { RouteComponentProps, withRouter } from "react-router";
+import { type RouteComponentProps, withRouter } from "react-router";
 
 import { pushFiltered } from "shared/routing";
 
@@ -14,7 +14,7 @@ class NoClusterPlaceholder extends Component<PropsType, StateType> {
   state = {};
 
   render() {
-    let { setCurrentModal, currentProject } = this.context;
+    const { setCurrentModal, currentProject } = this.context;
 
     return (
       <StyledNoClusterPlaceholder>
@@ -33,9 +33,9 @@ class NoClusterPlaceholder extends Component<PropsType, StateType> {
         2.{" "}
         <A
           onClick={() =>
-            pushFiltered(this.props, "/dashboard", ["project_id"], {
+            { pushFiltered(this.props, "/dashboard", ["project_id"], {
               tab: "create-cluster",
-            })
+            }); }
           }
         >
           Create a new cluster

+ 8 - 8
dashboard/src/main/home/add-on-dashboard/ConfigureTemplate.tsx

@@ -18,7 +18,7 @@ import PorterFormWrapper from "components/porter-form/PorterFormWrapper";
 import Placeholder from "components/Placeholder";
 import Button from "components/porter/Button";
 import { generateSlug } from "random-word-slugs";
-import { RouteComponentProps, withRouter } from "react-router";
+import { type RouteComponentProps, withRouter } from "react-router";
 import Error from "components/porter/Error";
 
 type Props = RouteComponentProps & {
@@ -71,8 +71,8 @@ const ConfigureTemplate: React.FC<Props> = ({
   const deployAddOn = async (wildcard?: any) => {
     setButtonStatus("loading");
     
-    let values: any = {};
-    for (let key in wildcard) {
+    const values: any = {};
+    for (const key in wildcard) {
       _.set(values, key, wildcard[key]);
     }
     api
@@ -81,7 +81,7 @@ const ConfigureTemplate: React.FC<Props> = ({
         {
           template_name: currentTemplate.name,
           template_version: "latest",
-          values: values,
+          values,
           name,
         },
         {
@@ -95,21 +95,21 @@ const ConfigureTemplate: React.FC<Props> = ({
         window.analytics?.track("Deployed Add-on", {
           name: currentTemplate.name,
           namespace: "default",
-          values: values,
+          values,
         });
         waitForHelmRelease();
       })
       .catch((err) => {
-        let parsedErr = err?.response?.data?.error;
+        const parsedErr = err?.response?.data?.error;
         err = parsedErr || err.message || JSON.stringify(err);
         setButtonStatus(err);
         window.analytics?.track("Failed to Deploy Add-on", {
           name: currentTemplate.name,
           namespace: "default",
-          values: values,
+          values,
           error: err,
         });
-        return;
+        
       });
   };
 

+ 4 - 4
dashboard/src/main/home/add-on-dashboard/ExpandedTemplate.tsx

@@ -33,7 +33,7 @@ const ExpandedTemplate: React.FC<Props> = ({
   const [keywords, setKeywords] = useState<any[]>([]);
   const getTemplateInfo = async () => {
     setIsLoading(true);
-    let params = {
+    const params = {
       repo_url: capabilities?.default_addon_helm_repo_url,
     };
 
@@ -43,8 +43,8 @@ const ExpandedTemplate: React.FC<Props> = ({
       version: currentTemplate.currentVersion,
     })
       .then((res) => {
-        let { form, values, markdown, metadata } = res.data;
-        let keywords = metadata.keywords;
+        const { form, values, markdown, metadata } = res.data;
+        const keywords = metadata.keywords;
         setForm(form);
         setValues(values);
         setMarkdown(markdown);
@@ -89,7 +89,7 @@ const ExpandedTemplate: React.FC<Props> = ({
 
         </Container>
 
-        <Button onClick={() => proceed(form)}>
+        <Button onClick={() => { proceed(form); }}>
           <AddI className="material-icons">add</AddI>
           Deploy add-on
         </Button>

+ 7 - 7
dashboard/src/main/home/app-dashboard/app-view/tabs/Webhooks.tsx

@@ -10,7 +10,7 @@ import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 
 import api from "shared/api";
-import { AppEventWebhook } from "shared/types";
+import { type AppEventWebhook } from "shared/types";
 import { url } from "inspector";
 
 type Webhook = {
@@ -52,9 +52,9 @@ const Webhooks: React.FC<Props> = ({
       "<token>",
       {},
       { 
-        projectId: projectId,
-        deploymentTargetId: deploymentTargetId,
-        appName: appName,
+        projectId,
+        deploymentTargetId,
+        appName,
        },
     )
     .then(({ data:  { app_event_webhooks } }) =>  {
@@ -90,9 +90,9 @@ const Webhooks: React.FC<Props> = ({
       })
       },
       { 
-        projectId: projectId,
-        deploymentTargetId: deploymentTargetId,
-        appName: appName,
+        projectId,
+        deploymentTargetId,
+        appName,
        },
     )
     .then(() => {

+ 2 - 2
dashboard/src/main/home/app-dashboard/build-settings/BranchSelector.tsx

@@ -72,7 +72,7 @@ const BranchSelector: React.FC<Props> = ({
       return <LoadingWrapper>Error loading branches</LoadingWrapper>;
     }
 
-    let results =
+    const results =
       searchFilter != null
         ? branches
           .filter((branch) => {
@@ -97,7 +97,7 @@ const BranchSelector: React.FC<Props> = ({
         <BranchName
           key={i}
           lastItem={i === branches.length - 1}
-          onClick={() => setBranch(branch)}
+          onClick={() => { setBranch(branch); }}
         >
           <img src={branch_icon} alt={"branch icon"} />
           {branch}

+ 2 - 2
dashboard/src/main/home/app-dashboard/build-settings/ProviderSelector.tsx

@@ -3,7 +3,7 @@ import React, { useRef, useState } from "react";
 import { useOutsideAlerter } from "shared/hooks/useOutsideAlerter";
 import styled from "styled-components";
 
-interface Props {
+type Props = {
     values: any[];
     currentValue: any;
     onChange: (provider: any) => void;
@@ -34,7 +34,7 @@ const ProviderSelector: React.FC<Props> = ({
                 <ProviderSelectorStyles.Icon className={icon} />
 
                 <ProviderSelectorStyles.Button
-                    onClick={() => setIsOpen((prev) => !prev)}
+                    onClick={() => { setIsOpen((prev) => !prev); }}
                 >
                     {currentValue?.name || currentValue?.instance_url}
                 </ProviderSelectorStyles.Button>

+ 7 - 7
dashboard/src/main/home/app-dashboard/build-settings/RepositorySelector.tsx

@@ -3,14 +3,14 @@ import styled from "styled-components";
 import github from "assets/github-white.png";
 
 import api from "shared/api";
-import { RepoType } from "shared/types";
+import { type RepoType } from "shared/types";
 import { Context } from "shared/Context";
 
 import DynamicLink from "components/DynamicLink";
 import Loading from "components/Loading";
 import SearchBar from "components/SearchBar";
 import ProviderSelector from "./ProviderSelector";
-import { PorterApp } from "../types/porterApp";
+import { type PorterApp } from "../types/porterApp";
 
 type Props = {
   readOnly: boolean;
@@ -89,7 +89,7 @@ const RepositorySelector: React.FC<Props> = ({
   const loadGithubRepos = async (repoId: number) => {
     try {
       const res = await api.getGitRepoList<
-        { FullName: string; Kind: "github" }[]
+        Array<{ FullName: string; Kind: "github" }>
       >("<token>", {}, { project_id: currentProject.id, git_repo_id: repoId });
 
       const repos = res.data.map((repo) => ({ ...repo, GHRepoID: repoId }));
@@ -97,8 +97,8 @@ const RepositorySelector: React.FC<Props> = ({
     } catch (error) { }
   };
 
-  const loadRepos = (provider: any) => {
-    return loadGithubRepos(provider.installation_id);
+  const loadRepos = async (provider: any) => {
+    return await loadGithubRepos(provider.installation_id);
   };
 
   useEffect(() => {
@@ -169,7 +169,7 @@ const RepositorySelector: React.FC<Props> = ({
     }
 
     // show 10 most recently used repos if user hasn't searched anything yet
-    let results =
+    const results =
       searchFilter != null
         ? repos
           .filter((repo: RepoType) => {
@@ -197,7 +197,7 @@ const RepositorySelector: React.FC<Props> = ({
             key={i}
             isSelected={repo.FullName === git_repo_name}
             lastItem={i === repos.length - 1}
-            onClick={() => setRepo(repo)}
+            onClick={() => { setRepo(repo); }}
             readOnly={readOnly}
             disabled={false}
           >

+ 2 - 2
dashboard/src/main/home/app-dashboard/expanded-app/DeleteApplicationModal.tsx

@@ -35,7 +35,7 @@ const GithubActionModal: React.FC<Props> = ({
         <Spacer y={0.5} />
         <Checkbox
           checked={deleteGithubWorkflow}
-          toggleChecked={() => setDeleteGithubWorkflow(!deleteGithubWorkflow)}
+          toggleChecked={() => { setDeleteGithubWorkflow(!deleteGithubWorkflow); }}
         >
           <Text color="helper">
             Upon deletion, open a PR to remove this application's associated CI
@@ -57,7 +57,7 @@ const GithubActionModal: React.FC<Props> = ({
       <Spacer y={0.5} />
       {renderDeleteGithubWorkflowText()}
       <Button
-        onClick={() => deleteApplication(deleteGithubWorkflow)}
+        onClick={() => { deleteApplication(deleteGithubWorkflow); }}
         color="#b91133"
         status={loading ? "loading" : ""}
         loadingText="Deleting..."

+ 4 - 4
dashboard/src/main/home/app-dashboard/expanded-app/GHABanner.tsx

@@ -39,7 +39,7 @@ const GHABanner: React.FC<Props> = ({
             <Banner
               type="warning"
               suffix={
-                <RefreshButton onClick={() => window.location.reload()}>
+                <RefreshButton onClick={() => { window.location.reload(); }}>
                   <img src={refresh} /> Refresh
                 </RefreshButton>
               }
@@ -58,7 +58,7 @@ const GHABanner: React.FC<Props> = ({
             <Banner
               type="warning"
               suffix={
-                <RefreshButton onClick={() => window.location.reload()}>
+                <RefreshButton onClick={() => { window.location.reload(); }}>
                   <img src={refresh} /> Refresh
                 </RefreshButton>
               }
@@ -66,7 +66,7 @@ const GHABanner: React.FC<Props> = ({
               Your application will not be available until you add the Porter workflow to your branch.
               <Spacer inline width="5px" />
               <Link
-                onClick={() => setShowGHAModal(true)}
+                onClick={() => { setShowGHAModal(true); }}
                 target="_blank"
                 hasunderline
               >
@@ -78,7 +78,7 @@ const GHABanner: React.FC<Props> = ({
       </StyledGHABanner>
       {showGHAModal && (
         <GithubActionModal
-          closeModal={() => setShowGHAModal(false)}
+          closeModal={() => { setShowGHAModal(false); }}
           githubAppInstallationID={gitRepoId}
           githubRepoOwner={repoName.split("/")[0]}
           githubRepoName={repoName.split("/")[1]}

+ 8 - 8
dashboard/src/main/home/app-dashboard/expanded-app/metrics/AreaChart.tsx

@@ -14,11 +14,11 @@ import { localPoint } from "@visx/event";
 import { LinearGradient } from "@visx/gradient";
 import { bisector, extent, max } from "d3-array";
 import { timeFormat } from "d3-time-format";
-import { NormalizedMetricsData } from "../../../cluster-dashboard/expanded-chart/metrics/types";
+import { type NormalizedMetricsData } from "../../../cluster-dashboard/expanded-chart/metrics/types";
 import { AggregatedDataColors } from "../../../cluster-dashboard/expanded-chart/metrics/utils";
 import { ColorTheme } from "./utils";
 
-var globalData: NormalizedMetricsData[];
+let globalData: NormalizedMetricsData[];
 
 // util
 const formatDate = timeFormat("%H:%M:%S %b %d, '%y");
@@ -27,7 +27,7 @@ const hourFormat = timeFormat("%H:%M");
 const dayFormat = timeFormat("%b %d");
 
 // map resolutions to formats
-const formats: { [range: string]: (date: Date) => string } = {
+const formats: Record<string, (date: Date) => string> = {
     "1H": hourFormat,
     "6H": hourFormat,
     "1D": hourFormat,
@@ -122,8 +122,8 @@ const AreaChart: React.FunctionComponent<AreaProps> = ({
     );
 
     const getAggregatedDataTooltip = (x0: Date) => {
-        let aggregatedTooltipData: Record<string, NormalizedMetricsData> = {};
-        for (let [key, values] of Object.entries(aggregatedData)) {
+        const aggregatedTooltipData: Record<string, NormalizedMetricsData> = {};
+        for (const [key, values] of Object.entries(aggregatedData)) {
             const index = bisectDate(values, x0, 1);
             const d0 = values[index - 1];
             const d1 = values[index];
@@ -198,9 +198,9 @@ const AreaChart: React.FunctionComponent<AreaProps> = ({
             const container: SVGSVGElement = svgContainer.current;
 
             let point = container.createSVGPoint();
-            // @ts-ignore
+            // @ts-expect-error
             point.x = (event as any)?.clientX || 0;
-            // @ts-ignore
+            // @ts-expect-error
             point.y = (event as any)?.clientY || 0;
             point = point?.matrixTransform(container.getScreenCTM().inverse());
 
@@ -364,7 +364,7 @@ const AreaChart: React.FunctionComponent<AreaProps> = ({
                     onTouchStart={handleTooltip}
                     onTouchMove={handleTooltip}
                     onMouseMove={handleTooltip}
-                    onMouseLeave={() => hideTooltip()}
+                    onMouseLeave={() => { hideTooltip(); }}
                 />
                 {tooltipData && (
                     <g>

+ 1 - 1
dashboard/src/main/home/app-dashboard/expanded-app/metrics/MetricsChart.tsx

@@ -7,7 +7,7 @@ import StatusCodeDataLegend from "./StatusCodeDataLegend";
 import AreaChart from "./AreaChart";
 import StackedAreaChart from "./StackedAreaChart";
 import Loading from "components/Loading";
-import { AggregatedMetric, Metric, NginxStatusMetric, isNginxMetric } from "./types";
+import { type AggregatedMetric, type Metric, type NginxStatusMetric, isNginxMetric } from "./types";
 
 type PropsType = {
     metric: Metric;

+ 3 - 3
dashboard/src/main/home/app-dashboard/expanded-app/metrics/StackedAreaChart.tsx

@@ -11,9 +11,9 @@ import { timeFormat } from "d3-time-format";
 
 import { ColorTheme } from "./utils";
 import { default as areaTheme } from "./themes/area";
-import { NormalizedNginxStatusMetricsData } from "../../../cluster-dashboard/expanded-chart/metrics/types";
+import { type NormalizedNginxStatusMetricsData } from "../../../cluster-dashboard/expanded-chart/metrics/types";
 
-var globalData: NormalizedNginxStatusMetricsData[];
+let globalData: NormalizedNginxStatusMetricsData[];
 
 // util
 const formatDate = timeFormat("%H:%M:%S %b %d, '%y");
@@ -25,7 +25,7 @@ const dateScaleConfig = { type: 'point' } as const;
 const yScaleConfig = { type: 'linear' } as const;
 
 // map resolutions to formats
-const formats: { [range: string]: (date: Date) => string } = {
+const formats: Record<string, (date: Date) => string> = {
     "1H": hourFormat,
     "6H": hourFormat,
     "1D": hourFormat,

+ 1 - 1
dashboard/src/main/home/app-dashboard/expanded-app/metrics/StatusCodeDataLegend.tsx

@@ -3,7 +3,7 @@ import styled from "styled-components";
 import chroma from "chroma-js";
 import { StatusCodeDataColors } from "./utils";
 
-interface StatusCodeDataLegendProps {}
+type StatusCodeDataLegendProps = {}
 
 const StatusCodeDataLegend = ({ }: StatusCodeDataLegendProps) => {
   const statusCodes = ["1xx", "2xx", "3xx", "4xx", "5xx"];

+ 1 - 1
dashboard/src/main/home/app-dashboard/expanded-app/metrics/themes/area.tsx

@@ -1,6 +1,6 @@
 import { buildChartTheme, grayColors } from '@visx/xychart';
 
-let chart = buildChartTheme({
+const chart = buildChartTheme({
     backgroundColor: '#222',
     colors: [
         "#4B4F7C", // gray (1xx)

+ 1 - 1
dashboard/src/main/home/app-dashboard/types/buildpack.ts

@@ -27,7 +27,7 @@ export const DEFAULT_BUILDER_NAME = "heroku";
 export const DEFAULT_PAKETO_STACK = "paketobuildpacks/builder-jammy-full:latest";
 export const DEFAULT_HEROKU_STACK = "heroku/buildpacks:20";
 
-export const BUILDPACK_TO_NAME: { [key: string]: string } = {
+export const BUILDPACK_TO_NAME: Record<string, string> = {
   "heroku/nodejs": "NodeJS",
   "heroku/python": "Python",
   "heroku/java": "Java",

+ 1 - 1
dashboard/src/main/home/app-dashboard/types/porterApp.ts

@@ -1,4 +1,4 @@
-export interface PorterApp {
+export type PorterApp = {
     name: string;
     git_branch: string;
     git_repo_id: number;

+ 2 - 2
dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/AddCustomBuildpack.tsx

@@ -1,5 +1,5 @@
 import InputRow from "components/form-components/InputRow";
-import { Buildpack } from "main/home/app-dashboard/types/buildpack";
+import { type Buildpack } from "main/home/app-dashboard/types/buildpack";
 import React, { useState } from "react";
 import styled, { keyframes } from "styled-components";
 
@@ -56,7 +56,7 @@ const AddCustomBuildpack: React.FC<{
         </EventInformation>
       </ContentContainer>
       <ActionContainer>
-        <ActionButton onClick={() => handleAddCustomBuildpack()} type="button">
+        <ActionButton onClick={() => { handleAddCustomBuildpack(); }} type="button">
           <span className="material-icons-outlined">add</span>
         </ActionButton>
       </ActionContainer>

+ 4 - 4
dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackCard.tsx

@@ -2,9 +2,9 @@ import React, { useMemo } from "react";
 import { DeviconsNameList } from "assets/devicons-name-list";
 import styled, { keyframes } from "styled-components";
 import { Draggable } from "react-beautiful-dnd";
-import { Buildpack } from "main/home/app-dashboard/types/buildpack";
+import { type Buildpack } from "main/home/app-dashboard/types/buildpack";
 
-interface Props {
+type Props = {
   buildpack: Buildpack;
   action: "add" | "remove";
   onClickFn: (buildpack: string) => void;
@@ -59,7 +59,7 @@ const BuildpackCard: React.FC<Props> = ({
             </EventInformation>
           </ContentContainer>
           <ActionContainer>
-            <ActionButton onClick={() => onClickFn(buildpack.buildpack)}>
+            <ActionButton onClick={() => { onClickFn(buildpack.buildpack); }}>
               <span className="material-icons">
                 {action === "remove" ? "delete" : "add"}
               </span>
@@ -77,7 +77,7 @@ const BuildpackCard: React.FC<Props> = ({
         </EventInformation>
       </ContentContainer>
       <ActionContainer>
-        <ActionButton onClick={() => onClickFn(buildpack.buildpack)}>
+        <ActionButton onClick={() => { onClickFn(buildpack.buildpack); }}>
           <span className="material-icons">
             {action === "remove" ? "delete" : "add"}
           </span>

+ 3 - 3
dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackConfigurationModal.tsx

@@ -6,10 +6,10 @@ import AddCustomBuildpackComponent from "./AddCustomBuildpack";
 import Button from "components/porter/Button";
 import Modal from "components/porter/Modal";
 import styled from "styled-components";
-import { Buildpack } from "main/home/app-dashboard/types/buildpack";
+import { type Buildpack } from "main/home/app-dashboard/types/buildpack";
 import {  useFieldArray, useFormContext } from "react-hook-form";
-import { PorterAppFormData } from "lib/porter-apps";
-import { BuildOptions } from "lib/porter-apps/build";
+import { type PorterAppFormData } from "lib/porter-apps";
+import { type BuildOptions } from "lib/porter-apps/build";
 
 type Props = {
   build: BuildOptions & {

+ 4 - 4
dashboard/src/main/home/app-dashboard/validate-apply/build-settings/buildpacks/BuildpackList.tsx

@@ -5,13 +5,13 @@ import Text from "components/porter/Text";
 import Loading from "components/Loading";
 import Error from "components/porter/Error";
 import { Droppable, DragDropContext } from "react-beautiful-dnd";
-import { Buildpack } from "main/home/app-dashboard/types/buildpack";
+import { type Buildpack } from "main/home/app-dashboard/types/buildpack";
 import { useFieldArray, useFormContext } from "react-hook-form";
-import { PorterAppFormData } from "lib/porter-apps";
-import { BuildOptions } from "lib/porter-apps/build";
+import { type PorterAppFormData } from "lib/porter-apps";
+import { type BuildOptions } from "lib/porter-apps/build";
 import Container from "components/porter/Container";
 
-interface Props {
+type Props = {
   build: BuildOptions & {
     method: "pack";
   };

+ 1 - 1
dashboard/src/main/home/app-dashboard/validate-apply/helm/HelmOverrides.tsx

@@ -6,7 +6,7 @@ import YamlEditor from "components/YamlEditor";
 import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 import {useFormContext} from "react-hook-form";
-import {PorterAppFormData} from "lib/porter-apps";
+import {type PorterAppFormData} from "lib/porter-apps";
 
 type PropsType = {
   projectId: number;

+ 9 - 9
dashboard/src/main/home/cluster-dashboard/DashboardRouter.tsx

@@ -1,16 +1,16 @@
 import React, { useState, useContext, useEffect } from "react";
 import styled from "styled-components";
 import loadable from "@loadable/component";
-import { RouteComponentProps, withRouter } from "react-router";
+import { type RouteComponentProps, withRouter } from "react-router";
 import { Route, Switch } from "react-router-dom";
 
 import api from "shared/api";
 import { Context } from "shared/Context";
-import { WithAuthProps, withAuth } from "shared/auth/AuthorizationHoc";
-import { ClusterType } from "shared/types";
+import { type WithAuthProps, withAuth } from "shared/auth/AuthorizationHoc";
+import { type ClusterType } from "shared/types";
 import {
   getQueryParam,
-  PorterUrl,
+  type PorterUrl,
   pushQueryParams,
 } from "shared/routing";
 
@@ -24,16 +24,16 @@ import ExpandedEnvGroupDashboard from "./env-groups/ExpandedEnvGroupDashboard";
 import EnvGroupDashboard from "./env-groups/EnvGroupDashboard";
 
 const LazyPreviewEnvironmentsRoutes = loadable(
-  // @ts-ignore
-  () => import("./preview-environments/routes.tsx"),
+  // @ts-expect-error
+  async () => await import("./preview-environments/routes.tsx"),
   {
     fallback: <Loading />,
   }
 );
 
 const LazyStackRoutes = loadable(
-  // @ts-ignore
-  () => import("./stacks/routes.tsx"),
+  // @ts-expect-error
+  async () => await import("./stacks/routes.tsx"),
   {
     fallback: <Loading />,
   }
@@ -84,7 +84,7 @@ const DashboardRouter: React.FC<Props> = ({
   // Reset namespace filter and close expanded chart on cluster change
   useEffect(() => {
     let namespace = "default";
-    let localStorageNamespace = localStorage.getItem(
+    const localStorageNamespace = localStorage.getItem(
       `${currentProject.id}-${currentCluster.id}-namespace`
     );
     if (localStorageNamespace) {

+ 10 - 10
dashboard/src/main/home/cluster-dashboard/NamespaceSelector.tsx

@@ -14,7 +14,7 @@ type Props = {
 };
 
 type StateType = {
-  namespaceOptions: { label: string; value: string }[];
+  namespaceOptions: Array<{ label: string; value: string }>;
 };
 
 // TODO: fix update to unmounted component
@@ -23,12 +23,12 @@ export const NamespaceSelector: React.FunctionComponent<Props> = ({
   namespace,
 }) => {
   const context = useContext(Context);
-  let _isMounted = true;
+  const _isMounted = true;
   const [namespaceOptions, setNamespaceOptions] = useState<
-    {
+    Array<{
       label: string;
       value: string;
-    }[]
+    }>
   >([]);
   const [defaultNamespace, setDefaultNamespace] = useState<string>(
     localStorage.getItem(
@@ -37,7 +37,7 @@ export const NamespaceSelector: React.FunctionComponent<Props> = ({
   );
 
   const updateOptions = () => {
-    let { currentCluster, currentProject } = context;
+    const { currentCluster, currentProject } = context;
 
     api
       .getNamespaces(
@@ -50,13 +50,13 @@ export const NamespaceSelector: React.FunctionComponent<Props> = ({
       )
       .then((res) => {
         if (_isMounted) {
-          let namespaceOptions: { label: string; value: string }[] = [
+          const namespaceOptions: Array<{ label: string; value: string }> = [
             // { label: "All", value: "ALL" },
           ];
 
           // Set namespace from URL if specified
-          let queryString = window.location.search;
-          let urlParams = new URLSearchParams(queryString);
+          const queryString = window.location.search;
+          const urlParams = new URLSearchParams(queryString);
           let urlNamespace = urlParams.get("namespace");
           if (urlNamespace === "ALL") {
             urlNamespace = "ALL";
@@ -105,8 +105,8 @@ export const NamespaceSelector: React.FunctionComponent<Props> = ({
   };
 
   useEffect(() => {
-    let urlParams = new URLSearchParams(window.location.search);
-    let urlNamespace = urlParams.get("namespace");
+    const urlParams = new URLSearchParams(window.location.search);
+    const urlNamespace = urlParams.get("namespace");
     if (
       urlNamespace === "" ||
       defaultNamespace === "" ||

+ 3 - 3
dashboard/src/main/home/cluster-dashboard/SortSelector.tsx

@@ -13,7 +13,7 @@ type PropsType = {
 };
 
 type StateType = {
-  sortOptions: { label: string; value: string }[];
+  sortOptions: Array<{ label: string; value: string }>;
 };
 
 // TODO: fix update to unmounted component
@@ -24,7 +24,7 @@ export default class SortSelector extends Component<PropsType, StateType> {
       { label: "Oldest", value: "Oldest" },
       { label: "Alphabetical", value: "Alphabetical" },
       { label: "Next Run", value: "Next Run" },
-    ] as { label: string; value: string }[],
+    ] as Array<{ label: string; value: string }>,
   };
 
   getSortOptions() {
@@ -49,7 +49,7 @@ export default class SortSelector extends Component<PropsType, StateType> {
       <StyledSortSelector>
         <RadioFilter
           selected={this.props.sortType}
-          setSelected={(sortType: any) => this.props.setSortType(sortType)}
+          setSelected={(sortType: any) => { this.props.setSortType(sortType); }}
           options={this.getSortOptions()}
           name="Sort"
           icon={sort}

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/TagFilter.tsx

@@ -40,7 +40,7 @@ const TagFilter = ({ onSelect }: { onSelect: (tag: any) => void }) => {
           label: tag.name,
         }))
       )}
-      setSelected={(newVal: any) => setSelectedTag(newVal)}
+      setSelected={(newVal: any) => { setSelectedTag(newVal); }}
       name="Tag"
       icon={tag}
     />

+ 3 - 3
dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx

@@ -1,16 +1,16 @@
 import React, { useContext, useState, useEffect } from "react";
 import styled from "styled-components";
-import { RouteComponentProps, withRouter } from "react-router";
+import { type RouteComponentProps, withRouter } from "react-router";
 
 import web from "assets/web.png";
 
 import { Context } from "shared/Context";
 import { JobStatusType } from "shared/types";
-import { withAuth, WithAuthProps } from "shared/auth/AuthorizationHoc";
+import { withAuth, type WithAuthProps } from "shared/auth/AuthorizationHoc";
 import {
   pushQueryParams,
   pushFiltered,
-  PorterUrl,
+  type PorterUrl,
 } from "shared/routing";
 
 import { NamespaceSelector } from "../NamespaceSelector";

+ 6 - 6
dashboard/src/main/home/cluster-dashboard/chart/Chart.tsx

@@ -9,9 +9,9 @@ import styled from "styled-components";
 import { useHistory, useLocation, useRouteMatch } from "react-router";
 
 import {
-  ChartType,
+  type ChartType,
   JobStatusType,
-  JobStatusWithTimeType,
+  type JobStatusWithTimeType,
   StorageType,
 } from "shared/types";
 import { Context } from "shared/Context";
@@ -100,7 +100,7 @@ const Chart: React.FunctionComponent<Props> = ({
   }, [chart]);
 
   const filteredControllers = useMemo(() => {
-    let tmpControllers: any = {};
+    const tmpControllers: any = {};
     chartControllers.forEach((uid: any) => {
       if (!controllers[uid]) {
         return;
@@ -117,10 +117,10 @@ const Chart: React.FunctionComponent<Props> = ({
     });
   }
 
-  // @ts-ignore
+  // @ts-expect-error
   const rtf = new Intl.DateTimeFormat("en", {
     localeMatcher: "best fit", // other values: "lookup"
-    // @ts-ignore
+    // @ts-expect-error
     dateStyle: "full",
     timeStyle: "long",
   });
@@ -136,7 +136,7 @@ const Chart: React.FunctionComponent<Props> = ({
       }/${chart.name}`;
 
     const newParams = {
-      // @ts-ignore
+      // @ts-expect-error
       project_id: params.project_id,
       closeChartRedirectUrl,
     };

+ 16 - 16
dashboard/src/main/home/cluster-dashboard/chart/ChartList.tsx

@@ -5,13 +5,13 @@ import _ from "lodash";
 import { Context } from "shared/Context";
 import api from "shared/api";
 import {
-  ChartType,
-  ClusterType,
+  type ChartType,
+  type ClusterType,
   JobStatusType,
-  JobStatusWithTimeType,
+  type JobStatusWithTimeType,
   StorageType,
 } from "shared/types";
-import { PorterUrl } from "shared/routing";
+import { type PorterUrl } from "shared/routing";
 
 import Chart from "./Chart";
 import Loading from "components/Loading";
@@ -33,9 +33,9 @@ type Props = {
   noPlaceholder?: boolean;
 };
 
-interface JobStatusWithTimeAndVersion extends JobStatusWithTimeType {
+type JobStatusWithTimeAndVersion = {
   resource_version: number;
-}
+} & JobStatusWithTimeType
 
 const ChartList: React.FunctionComponent<Props> = ({
   lastRunStatus,
@@ -92,7 +92,7 @@ const ChartList: React.FunctionComponent<Props> = ({
         {
           id: currentProject.id,
           cluster_id: currentCluster.id,
-          namespace: namespace,
+          namespace,
         }
       );
       const charts = res.data || [];
@@ -120,7 +120,7 @@ const ChartList: React.FunctionComponent<Props> = ({
         console.log(`connected to websocket: ${websocketID}`);
       },
       onmessage: (evt: MessageEvent) => {
-        let event = JSON.parse(evt.data);
+        const event = JSON.parse(evt.data);
         const newChart: ChartType = event.Object;
         const isSameChart = (chart: ChartType) =>
           getChartKey(chart.name, chart.namespace) ===
@@ -168,7 +168,7 @@ const ChartList: React.FunctionComponent<Props> = ({
   };
 
   const setupControllerWebsocket = (kind: string) => {
-    let { currentCluster, currentProject } = context;
+    const { currentCluster, currentProject } = context;
     const apiPath = `/api/projects/${currentProject.id}/clusters/${currentCluster.id}/${kind}/status`;
 
     const wsConfig = {
@@ -176,8 +176,8 @@ const ChartList: React.FunctionComponent<Props> = ({
         console.log(`connected to websocket: ${kind}`);
       },
       onmessage: (evt: MessageEvent) => {
-        let event = JSON.parse(evt.data);
-        let object = event?.Object;
+        const event = JSON.parse(evt.data);
+        const object = event?.Object;
 
         if (!object?.metadata?.kind) {
           return;
@@ -205,12 +205,12 @@ const ChartList: React.FunctionComponent<Props> = ({
   };
 
   const setupControllerWebsockets = (controllers: string[]) => {
-    controllers.map((kind) => setupControllerWebsocket(kind));
+    controllers.map((kind) => { setupControllerWebsocket(kind); });
   };
 
   const setupJobWebsocket = (websocketID: string) => {
     const kind = "job";
-    let { currentCluster, currentProject } = context;
+    const { currentCluster, currentProject } = context;
     const apiPath = `/api/projects/${currentProject.id}/clusters/${currentCluster.id}/${kind}/status`;
 
     const wsConfig = {
@@ -218,13 +218,13 @@ const ChartList: React.FunctionComponent<Props> = ({
         console.log(`connected to websocket: ${websocketID}`);
       },
       onmessage: (evt: MessageEvent) => {
-        let event = JSON.parse(evt.data);
+        const event = JSON.parse(evt.data);
 
         if (event.event_type === "DELETE") {
           return;
         }
 
-        let object = event.Object;
+        const object = event.Object;
 
         if (_.get(object.metadata, ["annotations", "helm.sh/hook"])) {
           return;
@@ -297,7 +297,7 @@ const ChartList: React.FunctionComponent<Props> = ({
     setupJobWebsocket(jobWebsocketID);
 
     return () => {
-      controllers.map((controller) => closeWebsocket(controller));
+      controllers.map((controller) => { closeWebsocket(controller); });
       closeWebsocket(jobWebsocketID);
     };
   }, [context.currentCluster]);

+ 14 - 14
dashboard/src/main/home/cluster-dashboard/chart/JobRunTable.tsx

@@ -2,10 +2,10 @@ import DynamicLink from "components/DynamicLink";
 import Loading from "components/Loading";
 import Table from "components/OldTable";
 import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
-import { CellProps, Column, Row } from "react-table";
+import { type CellProps, type Column, Row } from "react-table";
 import api from "shared/api";
 import { Context } from "shared/Context";
-import { NewWebsocketOptions, useWebsockets } from "shared/hooks/useWebsockets";
+import { type NewWebsocketOptions, useWebsockets } from "shared/hooks/useWebsockets";
 import { useRouting } from "shared/routing";
 import { relativeDate, timeFrom } from "shared/string_utils";
 import styled from "styled-components";
@@ -97,7 +97,7 @@ const JobRunTable: React.FC<Props> = ({
     };
   }, []);
 
-  const columns = useMemo<Column<JobRun>[]>(
+  const columns = useMemo<Array<Column<JobRun>>>(
     () => [
       {
         Header: "Namespace / Name",
@@ -278,7 +278,7 @@ const JobRunTable: React.FC<Props> = ({
     return (
       <ErrorWrapper>
         Couldn't retrieve jobs, please try again.{" "}
-        <RetryButton onClick={() => getJobRuns()}>Retry</RetryButton>
+        <RetryButton onClick={() => { getJobRuns(); }}>Retry</RetryButton>
       </ErrorWrapper>
     );
   }
@@ -381,14 +381,14 @@ type JobRun = {
       "helm.sh/revision": string;
       "meta.helm.sh/release-name": string;
     };
-    ownerReferences: {
+    ownerReferences: Array<{
       apiVersion: string;
       kind: string;
       name: string;
       uid: string;
       controller: boolean;
       blockOwnerDeletion: boolean;
-    }[];
+    }>;
     managedFields: unknown[];
   };
   spec: {
@@ -414,11 +414,11 @@ type JobRun = {
         };
       };
       spec: {
-        containers: {
+        containers: Array<{
           name: string;
           image: string;
           command: string[];
-          env?: {
+          env?: Array<{
             [key: string]: unknown;
             name: string;
             value?: string;
@@ -426,7 +426,7 @@ type JobRun = {
               secretKeyRef?: { name: string; key: string };
               configMapKeyRef?: { name: string; key: string };
             };
-          }[];
+          }>;
           resources: {
             [key: string]: unknown;
             limits: { [key: string]: unknown; memory: string };
@@ -435,7 +435,7 @@ type JobRun = {
           terminationMessagePath: string;
           terminationMessagePolicy: string;
           imagePullPolicy: string;
-        }[];
+        }>;
 
         restartPolicy: string;
         terminationGracePeriodSeconds: number;
@@ -443,25 +443,25 @@ type JobRun = {
         shareProcessNamespace: boolean;
         securityContext: unknown;
         schedulerName: string;
-        tolerations: {
+        tolerations: Array<{
           [key: string]: unknown;
           key: string;
           operator: string;
           value: string;
           effect: string;
-        }[];
+        }>;
       };
     };
   };
   status: {
     [key: string]: unknown;
-    conditions: {
+    conditions: Array<{
       [key: string]: unknown;
       type: string;
       status: string;
       lastProbeTime: string;
       lastTransitionTime: string;
-    }[];
+    }>;
     startTime: string;
     completionTime: string | undefined | null;
     succeeded?: number;

+ 16 - 16
dashboard/src/main/home/cluster-dashboard/dashboard/ClusterSettings.tsx

@@ -8,8 +8,8 @@ import api from "shared/api";
 import CheckboxRow from "components/form-components/CheckboxRow";
 import Loading from "components/Loading";
 import CopyToClipboard from "components/CopyToClipboard";
-import { DetailedIngressError } from "shared/types";
-import { RouteComponentProps } from "react-router";
+import { type DetailedIngressError } from "shared/types";
+import { type RouteComponentProps } from "react-router";
 import {stringifiedDNSRecordType} from "utils/ip";
 
 type Props = RouteComponentProps & {
@@ -47,7 +47,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
   );
   const [previewEnvsLoading, setPreviewEnvsLoading] = useState(false);
 
-  let rotateCredentials = () => {
+  const rotateCredentials = () => {
     api
       .overwriteAWSIntegration(
         "<token>",
@@ -69,7 +69,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       });
   };
 
-  let updateClusterName = () => {
+  const updateClusterName = () => {
     api
       .updateCluster(
         "<token>",
@@ -90,7 +90,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       });
   };
 
-  let updateAgentIntegrationEnabled = () => {
+  const updateAgentIntegrationEnabled = () => {
     setAgentLoading(true);
 
     api
@@ -113,7 +113,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       });
   };
 
-  let updatePreviewEnvironmentsEnabled = () => {
+  const updatePreviewEnvironmentsEnabled = () => {
     setPreviewEnvsLoading(true);
 
     api
@@ -185,7 +185,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
           <InputRow
             type="text"
             value={accessKeyId}
-            setValue={(x: string) => setAccessKeyId(x)}
+            setValue={(x: string) => { setAccessKeyId(x); }}
             label="👤 AWS Access ID"
             placeholder="ex: AKIAIOSFODNN7EXAMPLE"
             width="100%"
@@ -194,7 +194,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
           <InputRow
             type="password"
             value={secretKey}
-            setValue={(x: string) => setSecretKey(x)}
+            setValue={(x: string) => { setSecretKey(x); }}
             label="🔒 AWS Secret Key"
             placeholder="○ ○ ○ ○ ○ ○ ○ ○ ○"
             width="100%"
@@ -212,7 +212,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
           <Helper>
             Rotate the credentials that Porter uses to connect to the cluster.
           </Helper>
-          <Button color="#616FEEcc" onClick={() => setStartRotateCreds(true)}>
+          <Button color="#616FEEcc" onClick={() => { setStartRotateCreds(true); }}>
             Rotate credentials
           </Button>
         </div>
@@ -220,13 +220,13 @@ const ClusterSettings: React.FC<Props> = (props) => {
     }
   }
 
-  let overrideAWSClusterNameSection =
+  const overrideAWSClusterNameSection =
     currentCluster?.aws_integration_id &&
       currentCluster?.aws_integration_id != 0 ? (
       <InputRow
         type="text"
         value={newAWSClusterID}
-        setValue={(x: string) => setNewAWSClusterID(x)}
+        setValue={(x: string) => { setNewAWSClusterID(x); }}
         label="AWS Cluster ID"
         placeholder="ex: my-awesome-cluster"
         width="100%"
@@ -240,7 +240,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       <InputRow
         type="text"
         value={newClusterName}
-        setValue={(x: string) => setNewClusterName(x)}
+        setValue={(x: string) => { setNewClusterName(x); }}
         label="Cluster Name"
         placeholder="ex: my-awesome-cluster"
         width="100%"
@@ -252,7 +252,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       </Button>
     </div>
   );
-  let configureUrl = (
+  const configureUrl = (
     ingressIp: string | undefined,
     ingressError: DetailedIngressError
   ) => {
@@ -293,7 +293,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
       <Heading>Enable agent</Heading>
       <CheckboxRow
         label={"Allow the Porter agent to be installed on the cluster"}
-        toggle={() => setEnableAgent(!enableAgent)}
+        toggle={() => { setEnableAgent(!enableAgent); }}
         checked={enableAgent}
       />
       <Button color="#616FEEcc" onClick={updateAgentIntegrationEnabled}>
@@ -317,7 +317,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
           <Heading>Enable preview environments</Heading>
           <CheckboxRow
             label={"Create preview environments on this cluster"}
-            toggle={() => setEnablePreviewEnvs(!enablePreviewEnvs)}
+            toggle={() => { setEnablePreviewEnvs(!enablePreviewEnvs); }}
             checked={enablePreviewEnvs}
           />
           <Button color="#616FEEcc" onClick={updatePreviewEnvironmentsEnabled}>
@@ -367,7 +367,7 @@ const ClusterSettings: React.FC<Props> = (props) => {
               : currentCluster.status == "UPDATING"
           }
           color="#b91133"
-          onClick={() => setCurrentModal("UpdateClusterModal")}
+          onClick={() => { setCurrentModal("UpdateClusterModal"); }}
         >
           Delete cluster
         </Button>

Some files were not shown because too many files changed in this diff