Просмотр исходного кода

Remove react console warnings from the codebase

To view the warnings, you need to open the developer tools in the
browser and monitor the console output. Some warnings still remain, but
they are caused by the React libraries (like the TransitionGroup) and
not by the codebase.
Sergiu Miclea 2 лет назад
Родитель
Сommit
5e24e185d9

+ 4 - 1
src/components/modules/DashboardModule/DashboardLicence/DashboardLicence.tsx

@@ -168,7 +168,10 @@ class DashboardLicence extends React.Component<Props> {
   componentDidMount() {
     const resetLayout = async () => {
       await ObjectUtils.waitFor(
-        () => !!this.buttonWrapperRef && !!this.licenceLogoRef
+        () => !!this.buttonWrapperRef && !!this.licenceLogoRef,
+        {
+          silent: true,
+        }
       );
       this.resetLayout();
     };

+ 6 - 3
src/components/modules/TransferModule/TaskItem/TaskItem.tsx

@@ -34,7 +34,7 @@ const GlobalStyle = createGlobalStyle`
     transition: height 0.4s ease-in-out;
   }
 `;
-const Wrapper = styled.div<any>`
+const Wrapper = styled.div<{ open: boolean }>`
   cursor: pointer;
   border-bottom: 1px solid white;
   transition: all ${ThemeProps.animations.swift};
@@ -459,8 +459,11 @@ class TaskItem extends React.Component<Props> {
       ? "WARNING"
       : this.props.item.status;
     return (
-      // eslint-disable-next-line react/jsx-props-no-spreading
-      <Wrapper {...this.props}>
+      <Wrapper
+        open={this.props.open}
+        onMouseUp={this.props.onMouseUp}
+        onMouseDown={this.props.onMouseDown}
+      >
         <GlobalStyle />
         {this.renderHeader(status)}
         {this.renderBody(status)}

+ 9 - 11
src/components/modules/TransferModule/TransferDetailsTable/TransferDetailsTable.tsx

@@ -13,29 +13,27 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 import * as React from "react";
-import styled, { createGlobalStyle } from "styled-components";
 import { Collapse } from "react-collapse";
+import styled, { createGlobalStyle } from "styled-components";
 
-import Arrow from "@src/components/ui/Arrow";
-
-import { ThemePalette, ThemeProps } from "@src/components/Theme";
-
+import { EndpointUtils, StorageBackend } from "@src/@types/Endpoint";
 import {
-  TransferNetworkMap,
   isNetworkMapSecurityGroups,
   isNetworkMapSourceDest,
   TransferItem,
+  TransferNetworkMap,
 } from "@src/@types/MainItem";
-import type { Instance, Nic, Disk } from "@src/@types/Instance";
+import { MinionPool } from "@src/@types/MinionPool";
 import { Network, NetworkUtils } from "@src/@types/Network";
+import { ThemePalette, ThemeProps } from "@src/components/Theme";
+import Arrow from "@src/components/ui/Arrow";
 
-import { MinionPool } from "@src/@types/MinionPool";
-import { EndpointUtils, StorageBackend } from "@src/@types/Endpoint";
+import arrowIcon from "./images/arrow.svg";
 import instanceIcon from "./images/instance.svg";
 import networkIcon from "./images/network.svg";
 import storageIcon from "./images/storage.svg";
-import arrowIcon from "./images/arrow.svg";
 
+import type { Instance, Nic, Disk } from "@src/@types/Instance";
 export const GlobalStyle = createGlobalStyle`
   .ReactCollapse--collapse {
     transition: height 0.4s ease-in-out;
@@ -353,7 +351,7 @@ class TransferDetailsTable extends React.Component<Props, State> {
         this.renderRow({
           id: `${
             instance.instance_name || instance.id
-          }-${sourceName}-${destinationKey}`,
+          }-${sourceName}-${destinationKey}-${type}-${disk.size_bytes}`,
           icon: "storage",
           sourceName,
           destinationName,

+ 15 - 13
src/components/modules/WizardModule/WizardOptions/WizardOptions.tsx

@@ -12,29 +12,29 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import * as React from "react";
-import styled from "styled-components";
-import { observer } from "mobx-react";
-import { toJS } from "mobx";
 import autobind from "autobind-decorator";
+import { toJS } from "mobx";
+import { observer } from "mobx-react";
+import * as React from "react";
 import { CSSTransitionGroup } from "react-transition-group";
+import styled from "styled-components";
 
-import configLoader from "@src/utils/Config";
-import ToggleButtonBar from "@src/components/ui/ToggleButtonBar";
+import { MinionPool } from "@src/@types/MinionPool";
+import { ThemePalette, ThemeProps } from "@src/components/Theme";
 import FieldInput from "@src/components/ui/FieldInput";
 import StatusImage from "@src/components/ui/StatusComponents/StatusImage";
-import type { Field } from "@src/@types/Field";
-import type { Instance } from "@src/@types/Instance";
-import type { StorageBackend } from "@src/@types/Endpoint";
-
+import ToggleButtonBar from "@src/components/ui/ToggleButtonBar";
 import { executionOptions, migrationFields } from "@src/constants";
+import { MinionPoolStoreUtils } from "@src/stores/MinionPoolStore";
+import configLoader from "@src/utils/Config";
 import LabelDictionary from "@src/utils/LabelDictionary";
-import { ThemePalette, ThemeProps } from "@src/components/Theme";
 
-import { MinionPool } from "@src/@types/MinionPool";
-import { MinionPoolStoreUtils } from "@src/stores/MinionPoolStore";
 import endpointImage from "./images/endpoint.svg";
 
+import type { Field } from "@src/@types/Field";
+import type { Instance } from "@src/@types/Instance";
+import type { StorageBackend } from "@src/@types/Endpoint";
+
 export const INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS =
   "instance_osmorphing_minion_pool_mappings";
 
@@ -634,7 +634,9 @@ class WizardOptions extends React.Component<Props> {
               key={g.name || 0}
               transitionName={i > 0 ? "field-group-transition" : ""}
               transitionAppear
+              transitionEnterTimeout={250}
               transitionAppearTimeout={250}
+              transitionLeaveTimeout={250}
               in={false}
             >
               <Group>

+ 14 - 14
src/components/smart/DashboardPage/DashboardPage.tsx

@@ -12,25 +12,23 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+import { observer } from "mobx-react";
 import React from "react";
 import styled from "styled-components";
-import { observer } from "mobx-react";
 
-import replicaStore from "@src/stores/ReplicaStore";
-import migrationStore from "@src/stores/MigrationStore";
+import DashboardContent from "@src/components/modules/DashboardModule/DashboardContent";
+import Navigation from "@src/components/modules/NavigationModule/Navigation";
+import MainTemplate from "@src/components/modules/TemplateModule/MainTemplate";
+import PageHeader from "@src/components/smart/PageHeader";
 import endpointStore from "@src/stores/EndpointStore";
-import userStore from "@src/stores/UserStore";
-import projectStore from "@src/stores/ProjectStore";
 import licenceStore from "@src/stores/LicenceStore";
+import migrationStore from "@src/stores/MigrationStore";
 import notificationStore from "@src/stores/NotificationStore";
-
-import MainTemplate from "@src/components/modules/TemplateModule/MainTemplate";
-import Navigation from "@src/components/modules/NavigationModule/Navigation";
-import PageHeader from "@src/components/smart/PageHeader";
-import DashboardContent from "@src/components/modules/DashboardModule/DashboardContent";
-
-import Utils from "@src/utils/ObjectUtils";
+import projectStore from "@src/stores/ProjectStore";
+import replicaStore from "@src/stores/ReplicaStore";
+import userStore from "@src/stores/UserStore";
 import configLoader from "@src/utils/Config";
+import Utils from "@src/utils/ObjectUtils";
 
 const Wrapper = styled.div<any>``;
 
@@ -111,8 +109,10 @@ class ProjectsPage extends React.Component<{ history: any }, State> {
   async loadAdminData(showLoading: boolean) {
     await Utils.waitFor(
       () => Boolean(userStore.loggedUser && userStore.loggedUser.isAdmin),
-      30000,
-      100
+      {
+        timeoutMs: 30000,
+        intervalMs: 100,
+      }
     );
     if (userStore.loggedUser?.isAdmin) {
       userStore.getAllUsers({ skipLog: true, showLoading });

+ 26 - 25
src/components/smart/WizardPage/WizardPage.tsx

@@ -12,30 +12,34 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import React from "react";
-import styled from "styled-components";
 import autobind from "autobind-decorator";
 import { observer } from "mobx-react";
+import React from "react";
+import styled from "styled-components";
 
-import WizardTemplate from "@src/components/modules/TemplateModule/WizardTemplate";
+import { ReplicaItem, TransferItem } from "@src/@types/MainItem";
+import { ProviderTypes } from "@src/@types/Providers";
 import DetailsPageHeader from "@src/components/modules/DetailsModule/DetailsPageHeader";
+import EndpointModal from "@src/components/modules/EndpointModule/EndpointModal";
+import WizardTemplate from "@src/components/modules/TemplateModule/WizardTemplate";
+import { WizardNetworksChangeObject } from "@src/components/modules/WizardModule/WizardNetworks";
 import WizardPageContent from "@src/components/modules/WizardModule/WizardPageContent";
 import Modal from "@src/components/ui/Modal";
-import EndpointModal from "@src/components/modules/EndpointModule/EndpointModal";
-
-import userStore from "@src/stores/UserStore";
-import providerStore, {
-  getFieldChangeOptions,
-} from "@src/stores/ProviderStore";
+import { executionOptions, providerTypes, wizardPages } from "@src/constants";
 import endpointStore from "@src/stores/EndpointStore";
-import wizardStore from "@src/stores/WizardStore";
 import instanceStore from "@src/stores/InstanceStore";
+import minionPoolStore from "@src/stores/MinionPoolStore";
 import networkStore from "@src/stores/NetworkStore";
 import notificationStore from "@src/stores/NotificationStore";
-import scheduleStore from "@src/stores/ScheduleStore";
+import providerStore, {
+  getFieldChangeOptions,
+} from "@src/stores/ProviderStore";
 import replicaStore from "@src/stores/ReplicaStore";
+import scheduleStore from "@src/stores/ScheduleStore";
+import userStore from "@src/stores/UserStore";
+import wizardStore from "@src/stores/WizardStore";
 import KeyboardManager from "@src/utils/KeyboardManager";
-import { wizardPages, executionOptions, providerTypes } from "@src/constants";
+import ObjectUtils from "@src/utils/ObjectUtils";
 
 import type {
   Endpoint as EndpointType,
@@ -45,12 +49,6 @@ import type { Instance, InstanceScript } from "@src/@types/Instance";
 import type { Field } from "@src/@types/Field";
 import type { Schedule } from "@src/@types/Schedule";
 import type { WizardPage as WizardPageType } from "@src/@types/WizardData";
-import ObjectUtils from "@src/utils/ObjectUtils";
-import { ProviderTypes } from "@src/@types/Providers";
-import { TransferItem, ReplicaItem } from "@src/@types/MainItem";
-import minionPoolStore from "@src/stores/MinionPoolStore";
-import { WizardNetworksChangeObject } from "@src/components/modules/WizardModule/WizardNetworks";
-
 const Wrapper = styled.div<any>``;
 
 type Props = {
@@ -150,15 +148,18 @@ class WizardPage extends React.Component<Props, State> {
   }
 
   setTransferItemTitle() {
-    const selectedInstance = wizardStore.data?.selectedInstances?.[0];
-    let title =
-      selectedInstance?.name ||
-      selectedInstance?.instance_name ||
-      selectedInstance?.id;
     if (
-      wizardStore.data?.selectedInstances &&
-      wizardStore.data.selectedInstances.length > 1
+      !wizardStore.data?.selectedInstances ||
+      !wizardStore.data.selectedInstances.length
     ) {
+      return;
+    }
+    const selectedInstance = wizardStore.data.selectedInstances[0];
+    let title =
+      selectedInstance.name ||
+      selectedInstance.instance_name ||
+      selectedInstance.id;
+    if (wizardStore.data.selectedInstances.length > 1) {
       const shouldSeparateVm =
         wizardStore.data.destOptions?.separate_vm ||
         wizardStore.data.destOptions?.separate_vm === undefined;

+ 4 - 3
src/components/ui/TextInput/TextInput.tsx

@@ -14,6 +14,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import * as React from "react";
 import styled, { css } from "styled-components";
+
 import { ThemePalette, ThemeProps } from "@src/components/Theme";
 
 import closeImage from "./images/close.svg";
@@ -134,8 +135,8 @@ const TextInput = (props: Props) => {
     onCloseClick,
     disabled,
     disabledLoading,
-    embedded,
     onInputKeyDown,
+    ...otherProps
   } = props;
   const actualDisabled = disabled || disabledLoading;
   let input: { focus: () => void };
@@ -150,11 +151,11 @@ const TextInput = (props: Props) => {
         value={value}
         onChange={onChange}
         // eslint-disable-next-line react/jsx-props-no-spreading
-        {...props}
+        {...otherProps}
         onKeyDown={onInputKeyDown}
         disabled={actualDisabled}
       />
-      {props.required ? <Required right={embedded ? -24 : -16} /> : null}
+      {props.required ? <Required right={props.embedded ? -24 : -16} /> : null}
       <Close
         show={showClose && value !== "" && value !== undefined}
         onClick={() => {

+ 12 - 4
src/utils/ObjectUtils.ts

@@ -83,18 +83,26 @@ class ObjectUtils {
 
   static async waitFor(
     predicate: () => boolean,
-    timeoutMs = 15000,
-    tryEvery = 1000
+    options?: {
+      timeoutMs?: number;
+      intervalMs?: number;
+      silent?: boolean;
+    }
   ) {
+    const { timeoutMs = 15000, intervalMs = 1000, silent } = options || {};
     const startTime = new Date().getTime();
     const testLoop = async () => {
       if (predicate()) {
         return;
       }
       if (new Date().getTime() - startTime > timeoutMs) {
-        throw new Error(`Timeout: waiting for more than ${timeoutMs} ms`);
+        if (!silent) {
+          throw new Error(`Timeout: waiting for more than ${timeoutMs} ms`);
+        }
+        console.log(`Timeout: waiting for more than ${timeoutMs} ms`);
+        return;
       }
-      await this.wait(tryEvery);
+      await this.wait(intervalMs);
       await testLoop();
     };
     await testLoop();

+ 0 - 40
src/utils/eslint-plugin-coriolis-web/import-no-duplicate-name.js

@@ -1,40 +0,0 @@
-"use strict";
-
-/**
- * @type {import('eslint').Rule.RuleModule}
- */
-module.exports = {
-  meta: {
-    type: "problem",
-    fixable: "code",
-  },
-  create(context) {
-    return {
-      ImportDeclaration(node) {
-        const source = node.source.value;
-        if (typeof source !== "string" || !source.startsWith("@src")) {
-          return;
-        }
-        const lastTwoPathParts = source.split("/").slice(-2);
-        if (lastTwoPathParts.length !== 2) {
-          return;
-        }
-        const [componentFolder, componentName] = lastTwoPathParts;
-        if (componentFolder !== componentName) {
-          return;
-        }
-
-        context.report({
-          node,
-          message: `'${componentName}' name is duplicated in import path.`,
-          fix(fixer) {
-            return fixer.replaceText(
-              node.source,
-              `'${source.replace(new RegExp(`/${componentName}$`), "")}'`
-            );
-          },
-        });
-      },
-    };
-  },
-};

+ 35 - 1
src/utils/eslint-plugin-coriolis-web/index.js

@@ -2,6 +2,40 @@
 
 module.exports = {
   rules: {
-    "import-no-duplicate-name": require("./import-no-duplicate-name"),
+    "import-no-duplicate-name": {
+      meta: {
+        type: "problem",
+        fixable: "code",
+      },
+      create(context) {
+        return {
+          ImportDeclaration(node) {
+            const source = node.source.value;
+            if (typeof source !== "string" || !source.startsWith("@src")) {
+              return;
+            }
+            const lastTwoPathParts = source.split("/").slice(-2);
+            if (lastTwoPathParts.length !== 2) {
+              return;
+            }
+            const [componentFolder, componentName] = lastTwoPathParts;
+            if (componentFolder !== componentName) {
+              return;
+            }
+
+            context.report({
+              node,
+              message: `'${componentName}' name is duplicated in import path.`,
+              fix(fixer) {
+                return fixer.replaceText(
+                  node.source,
+                  `'${source.replace(new RegExp(`/${componentName}$`), "")}'`
+                );
+              },
+            });
+          },
+        };
+      },
+    },
   },
 };