Procházet zdrojové kódy

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 před 2 roky
rodič
revize
5e24e185d9

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

@@ -168,7 +168,10 @@ class DashboardLicence extends React.Component<Props> {
   componentDidMount() {
   componentDidMount() {
     const resetLayout = async () => {
     const resetLayout = async () => {
       await ObjectUtils.waitFor(
       await ObjectUtils.waitFor(
-        () => !!this.buttonWrapperRef && !!this.licenceLogoRef
+        () => !!this.buttonWrapperRef && !!this.licenceLogoRef,
+        {
+          silent: true,
+        }
       );
       );
       this.resetLayout();
       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;
     transition: height 0.4s ease-in-out;
   }
   }
 `;
 `;
-const Wrapper = styled.div<any>`
+const Wrapper = styled.div<{ open: boolean }>`
   cursor: pointer;
   cursor: pointer;
   border-bottom: 1px solid white;
   border-bottom: 1px solid white;
   transition: all ${ThemeProps.animations.swift};
   transition: all ${ThemeProps.animations.swift};
@@ -459,8 +459,11 @@ class TaskItem extends React.Component<Props> {
       ? "WARNING"
       ? "WARNING"
       : this.props.item.status;
       : this.props.item.status;
     return (
     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 />
         <GlobalStyle />
         {this.renderHeader(status)}
         {this.renderHeader(status)}
         {this.renderBody(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 * as React from "react";
-import styled, { createGlobalStyle } from "styled-components";
 import { Collapse } from "react-collapse";
 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 {
 import {
-  TransferNetworkMap,
   isNetworkMapSecurityGroups,
   isNetworkMapSecurityGroups,
   isNetworkMapSourceDest,
   isNetworkMapSourceDest,
   TransferItem,
   TransferItem,
+  TransferNetworkMap,
 } from "@src/@types/MainItem";
 } 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 { 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 instanceIcon from "./images/instance.svg";
 import networkIcon from "./images/network.svg";
 import networkIcon from "./images/network.svg";
 import storageIcon from "./images/storage.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`
 export const GlobalStyle = createGlobalStyle`
   .ReactCollapse--collapse {
   .ReactCollapse--collapse {
     transition: height 0.4s ease-in-out;
     transition: height 0.4s ease-in-out;
@@ -353,7 +351,7 @@ class TransferDetailsTable extends React.Component<Props, State> {
         this.renderRow({
         this.renderRow({
           id: `${
           id: `${
             instance.instance_name || instance.id
             instance.instance_name || instance.id
-          }-${sourceName}-${destinationKey}`,
+          }-${sourceName}-${destinationKey}-${type}-${disk.size_bytes}`,
           icon: "storage",
           icon: "storage",
           sourceName,
           sourceName,
           destinationName,
           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/>.
 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 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 { 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 FieldInput from "@src/components/ui/FieldInput";
 import StatusImage from "@src/components/ui/StatusComponents/StatusImage";
 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 { executionOptions, migrationFields } from "@src/constants";
+import { MinionPoolStoreUtils } from "@src/stores/MinionPoolStore";
+import configLoader from "@src/utils/Config";
 import LabelDictionary from "@src/utils/LabelDictionary";
 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 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 =
 export const INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS =
   "instance_osmorphing_minion_pool_mappings";
   "instance_osmorphing_minion_pool_mappings";
 
 
@@ -634,7 +634,9 @@ class WizardOptions extends React.Component<Props> {
               key={g.name || 0}
               key={g.name || 0}
               transitionName={i > 0 ? "field-group-transition" : ""}
               transitionName={i > 0 ? "field-group-transition" : ""}
               transitionAppear
               transitionAppear
+              transitionEnterTimeout={250}
               transitionAppearTimeout={250}
               transitionAppearTimeout={250}
+              transitionLeaveTimeout={250}
               in={false}
               in={false}
             >
             >
               <Group>
               <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/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+import { observer } from "mobx-react";
 import React from "react";
 import React from "react";
 import styled from "styled-components";
 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 endpointStore from "@src/stores/EndpointStore";
-import userStore from "@src/stores/UserStore";
-import projectStore from "@src/stores/ProjectStore";
 import licenceStore from "@src/stores/LicenceStore";
 import licenceStore from "@src/stores/LicenceStore";
+import migrationStore from "@src/stores/MigrationStore";
 import notificationStore from "@src/stores/NotificationStore";
 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 configLoader from "@src/utils/Config";
+import Utils from "@src/utils/ObjectUtils";
 
 
 const Wrapper = styled.div<any>``;
 const Wrapper = styled.div<any>``;
 
 
@@ -111,8 +109,10 @@ class ProjectsPage extends React.Component<{ history: any }, State> {
   async loadAdminData(showLoading: boolean) {
   async loadAdminData(showLoading: boolean) {
     await Utils.waitFor(
     await Utils.waitFor(
       () => Boolean(userStore.loggedUser && userStore.loggedUser.isAdmin),
       () => Boolean(userStore.loggedUser && userStore.loggedUser.isAdmin),
-      30000,
-      100
+      {
+        timeoutMs: 30000,
+        intervalMs: 100,
+      }
     );
     );
     if (userStore.loggedUser?.isAdmin) {
     if (userStore.loggedUser?.isAdmin) {
       userStore.getAllUsers({ skipLog: true, showLoading });
       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/>.
 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 autobind from "autobind-decorator";
 import { observer } from "mobx-react";
 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 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 WizardPageContent from "@src/components/modules/WizardModule/WizardPageContent";
 import Modal from "@src/components/ui/Modal";
 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 endpointStore from "@src/stores/EndpointStore";
-import wizardStore from "@src/stores/WizardStore";
 import instanceStore from "@src/stores/InstanceStore";
 import instanceStore from "@src/stores/InstanceStore";
+import minionPoolStore from "@src/stores/MinionPoolStore";
 import networkStore from "@src/stores/NetworkStore";
 import networkStore from "@src/stores/NetworkStore";
 import notificationStore from "@src/stores/NotificationStore";
 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 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 KeyboardManager from "@src/utils/KeyboardManager";
-import { wizardPages, executionOptions, providerTypes } from "@src/constants";
+import ObjectUtils from "@src/utils/ObjectUtils";
 
 
 import type {
 import type {
   Endpoint as EndpointType,
   Endpoint as EndpointType,
@@ -45,12 +49,6 @@ import type { Instance, InstanceScript } from "@src/@types/Instance";
 import type { Field } from "@src/@types/Field";
 import type { Field } from "@src/@types/Field";
 import type { Schedule } from "@src/@types/Schedule";
 import type { Schedule } from "@src/@types/Schedule";
 import type { WizardPage as WizardPageType } from "@src/@types/WizardData";
 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>``;
 const Wrapper = styled.div<any>``;
 
 
 type Props = {
 type Props = {
@@ -150,15 +148,18 @@ class WizardPage extends React.Component<Props, State> {
   }
   }
 
 
   setTransferItemTitle() {
   setTransferItemTitle() {
-    const selectedInstance = wizardStore.data?.selectedInstances?.[0];
-    let title =
-      selectedInstance?.name ||
-      selectedInstance?.instance_name ||
-      selectedInstance?.id;
     if (
     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 =
       const shouldSeparateVm =
         wizardStore.data.destOptions?.separate_vm ||
         wizardStore.data.destOptions?.separate_vm ||
         wizardStore.data.destOptions?.separate_vm === undefined;
         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 * as React from "react";
 import styled, { css } from "styled-components";
 import styled, { css } from "styled-components";
+
 import { ThemePalette, ThemeProps } from "@src/components/Theme";
 import { ThemePalette, ThemeProps } from "@src/components/Theme";
 
 
 import closeImage from "./images/close.svg";
 import closeImage from "./images/close.svg";
@@ -134,8 +135,8 @@ const TextInput = (props: Props) => {
     onCloseClick,
     onCloseClick,
     disabled,
     disabled,
     disabledLoading,
     disabledLoading,
-    embedded,
     onInputKeyDown,
     onInputKeyDown,
+    ...otherProps
   } = props;
   } = props;
   const actualDisabled = disabled || disabledLoading;
   const actualDisabled = disabled || disabledLoading;
   let input: { focus: () => void };
   let input: { focus: () => void };
@@ -150,11 +151,11 @@ const TextInput = (props: Props) => {
         value={value}
         value={value}
         onChange={onChange}
         onChange={onChange}
         // eslint-disable-next-line react/jsx-props-no-spreading
         // eslint-disable-next-line react/jsx-props-no-spreading
-        {...props}
+        {...otherProps}
         onKeyDown={onInputKeyDown}
         onKeyDown={onInputKeyDown}
         disabled={actualDisabled}
         disabled={actualDisabled}
       />
       />
-      {props.required ? <Required right={embedded ? -24 : -16} /> : null}
+      {props.required ? <Required right={props.embedded ? -24 : -16} /> : null}
       <Close
       <Close
         show={showClose && value !== "" && value !== undefined}
         show={showClose && value !== "" && value !== undefined}
         onClick={() => {
         onClick={() => {

+ 12 - 4
src/utils/ObjectUtils.ts

@@ -83,18 +83,26 @@ class ObjectUtils {
 
 
   static async waitFor(
   static async waitFor(
     predicate: () => boolean,
     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 startTime = new Date().getTime();
     const testLoop = async () => {
     const testLoop = async () => {
       if (predicate()) {
       if (predicate()) {
         return;
         return;
       }
       }
       if (new Date().getTime() - startTime > timeoutMs) {
       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();
     };
     };
     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 = {
 module.exports = {
   rules: {
   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}$`), "")}'`
+                );
+              },
+            });
+          },
+        };
+      },
+    },
   },
   },
 };
 };