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

Refactor the process of switching a project

With this, changing the project is handled in on place only, the
`PageHeader` component, instead of being handled in every place that
uses `PageHeader` component.
Also, `Wait.for` function is replaced by an improved switch project
promise, which should gain us a small performance boost while waiting
for the project to change.
Sergiu Miclea 8 лет назад
Родитель
Сommit
e4091097fd

+ 15 - 5
src/components/organisms/PageHeader/index.jsx

@@ -60,7 +60,7 @@ const Controls = styled.div`
 
 type Props = {
   title: string,
-  onProjectChange: (project: Project) => void,
+  onProjectChange?: (project: Project) => void,
   onModalOpen?: () => void,
   onModalClose?: () => void,
 }
@@ -85,9 +85,9 @@ class PageHeader extends React.Component<Props, State> {
   }
 
   getCurrentProject() {
-    if (UserStore.user && UserStore.user.project) {
-      // $FlowIssue
-      return ProjectStore.projects.find(p => p.id === UserStore.user.project.id)
+    let project = UserStore.user && UserStore.user.project ? UserStore.user.project : null
+    if (project) {
+      return ProjectStore.projects.find(p => p.id === project.id)
     }
 
     return null
@@ -148,6 +148,16 @@ class PageHeader extends React.Component<Props, State> {
     this.setState({ showChooseProviderModal: !options || !options.autoClose, showEndpointModal: false })
   }
 
+  handleProjectChange(project: Project) {
+    UserStore.switchProject(project.id).then(() => {
+      ProjectStore.getProjects()
+
+      if (this.props.onProjectChange) {
+        this.props.onProjectChange(project)
+      }
+    })
+  }
+
   render() {
     return (
       <Wrapper>
@@ -156,7 +166,7 @@ class PageHeader extends React.Component<Props, State> {
           <Dropdown
             selectedItem={this.getCurrentProject()}
             items={ProjectStore.projects}
-            onChange={this.props.onProjectChange}
+            onChange={project => { this.handleProjectChange(project) }}
             noItemsMessage="Loading..."
             labelField="name"
           />

+ 5 - 14
src/components/pages/EndpointsPage/index.jsx

@@ -28,17 +28,14 @@ import Modal from '../../molecules/Modal'
 import ChooseProvider from '../../organisms/ChooseProvider'
 import Endpoint from '../../organisms/Endpoint'
 import type { Endpoint as EndpointType } from '../../../types/Endpoint'
-import type { Project } from '../../../types/Project'
 
 import endpointImage from './images/endpoint-large.svg'
 
 import ProjectStore from '../../../stores/ProjectStore'
-import UserStore from '../../../stores/UserStore'
 import EndpointStore from '../../../stores/EndpointStore'
 import MigrationStore from '../../../stores/MigrationStore'
 import ReplicaStore from '../../../stores/ReplicaStore'
 import ProviderStore from '../../../stores/ProviderStore'
-import Wait from '../../../utils/Wait'
 import LabelDictionary from '../../../utils/LabelDictionary'
 
 const Wrapper = styled.div``
@@ -103,16 +100,10 @@ class EndpointsPage extends React.Component<{}, State> {
     return { migrationsCount, replicasCount }
   }
 
-  handleProjectChange(project: Project) {
-    // $FlowIssue
-    Wait.for(() => UserStore.user.project.id === project.id, () => {
-      ProjectStore.getProjects()
-      EndpointStore.getEndpoints({ showLoading: true })
-      MigrationStore.getMigrations()
-      ReplicaStore.getReplicas()
-    })
-
-    UserStore.switchProject(project.id)
+  handleProjectChange() {
+    EndpointStore.getEndpoints({ showLoading: true })
+    MigrationStore.getMigrations()
+    ReplicaStore.getReplicas()
   }
 
   handleReloadButtonClick() {
@@ -228,7 +219,7 @@ class EndpointsPage extends React.Component<{}, State> {
           headerComponent={
             <PageHeader
               title="Coriolis Endpoints"
-              onProjectChange={project => { this.handleProjectChange(project) }}
+              onProjectChange={() => { this.handleProjectChange() }}
             />
           }
         />

+ 4 - 13
src/components/pages/MigrationsPage/index.jsx

@@ -25,16 +25,13 @@ import PageHeader from '../../organisms/PageHeader'
 import AlertModal from '../../organisms/AlertModal'
 import MainListItem from '../../molecules/MainListItem'
 import type { MainItem } from '../../../types/MainItem'
-import type { Project } from '../../../types/Project'
 
 import migrationItemImage from './images/migration.svg'
 import migrationLargeImage from './images/migration-large.svg'
 
 import ProjectStore from '../../../stores/ProjectStore'
-import UserStore from '../../../stores/UserStore'
 import MigrationStore from '../../../stores/MigrationStore'
 import EndpointStore from '../../../stores/EndpointStore'
-import Wait from '../../../utils/Wait'
 import NotificationStore from '../../../stores/NotificationStore'
 import { requestPollTimeout } from '../../../config'
 
@@ -95,15 +92,9 @@ class MigrationsPage extends React.Component<{}, State> {
     ]
   }
 
-  handleProjectChange(project: Project) {
-    // $FlowIssue
-    Wait.for(() => UserStore.user.project.id === project.id, () => {
-      ProjectStore.getProjects()
-      EndpointStore.getEndpoints({ showLoading: true })
-      MigrationStore.getMigrations({ showLoading: true })
-    })
-
-    UserStore.switchProject(project.id)
+  handleProjectChange() {
+    EndpointStore.getEndpoints({ showLoading: true })
+    MigrationStore.getMigrations({ showLoading: true })
   }
 
   handleReloadButtonClick() {
@@ -276,7 +267,7 @@ class MigrationsPage extends React.Component<{}, State> {
           headerComponent={
             <PageHeader
               title="Coriolis Migrations"
-              onProjectChange={project => { this.handleProjectChange(project) }}
+              onProjectChange={() => { this.handleProjectChange() }}
               onModalOpen={() => { this.handleModalOpen() }}
               onModalClose={() => { this.handleModalClose() }}
             />

+ 4 - 13
src/components/pages/ReplicasPage/index.jsx

@@ -25,16 +25,13 @@ import PageHeader from '../../organisms/PageHeader'
 import AlertModal from '../../organisms/AlertModal'
 import MainListItem from '../../molecules/MainListItem'
 import type { MainItem } from '../../../types/MainItem'
-import type { Project } from '../../../types/Project'
 
 import replicaItemImage from './images/replica.svg'
 import replicaLargeImage from './images/replica-large.svg'
 
 import ProjectStore from '../../../stores/ProjectStore'
-import UserStore from '../../../stores/UserStore'
 import ReplicaStore from '../../../stores/ReplicaStore'
 import EndpointStore from '../../../stores/EndpointStore'
-import Wait from '../../../utils/Wait'
 import NotificationStore from '../../../stores/NotificationStore'
 import { requestPollTimeout } from '../../../config'
 
@@ -100,15 +97,9 @@ class ReplicasPage extends React.Component<{}, State> {
     return lastExecution
   }
 
-  handleProjectChange(project: Project) {
-    // $FlowIssue
-    Wait.for(() => UserStore.user.project.id === project.id, () => {
-      ProjectStore.getProjects()
-      ReplicaStore.getReplicas()
-      EndpointStore.getEndpoints({ showLoading: true })
-    })
-
-    UserStore.switchProject(project.id)
+  handleProjectChange() {
+    ReplicaStore.getReplicas()
+    EndpointStore.getEndpoints({ showLoading: true })
   }
 
   handleReloadButtonClick() {
@@ -250,7 +241,7 @@ class ReplicasPage extends React.Component<{}, State> {
           headerComponent={
             <PageHeader
               title="Coriolis Replicas"
-              onProjectChange={project => { this.handleProjectChange(project) }}
+              onProjectChange={() => { this.handleProjectChange() }}
               onModalOpen={() => { this.handleModalOpen() }}
               onModalClose={() => { this.handleModalClose() }}
             />

+ 18 - 12
src/stores/UserStore.js

@@ -53,18 +53,19 @@ class UserStore {
 
   @action loginScoped(projectId?: string): Promise<User> {
     return new Promise((resolve) => {
-      if (ProjectStore.projects && ProjectStore.projects.length) {
+      const sourceLoginScoped = () => {
         UserSource.loginScoped(projectId || ProjectStore.projects[0].id).then((user: User) => {
           this.user = { ...user, scoped: true }
           resolve(user)
         })
       }
-      ProjectStore.getProjects().then(() => {
-        UserSource.loginScoped(projectId || ProjectStore.projects[0].id).then((user: User) => {
-          this.user = { ...user, scoped: true }
-          resolve(user)
+      if (ProjectStore.projects && ProjectStore.projects.length) {
+        sourceLoginScoped()
+      } else {
+        ProjectStore.getProjects().then(() => {
+          sourceLoginScoped()
         })
-      })
+      }
     })
   }
 
@@ -93,12 +94,17 @@ class UserStore {
 
   @action switchProject(projectId: string): Promise<void> {
     NotificationStore.notify('Switching projects')
-    return UserSource.switchProject().then(() => {
-      this.loginScoped(projectId)
-    }).catch(reason => {
-      console.error('Error switching projects', reason)
-      NotificationStore.notify('Error switching projects')
-      this.logout()
+    return new Promise((resolve, reject) => {
+      UserSource.switchProject().then(() => {
+        return this.loginScoped(projectId)
+      }).then(() => {
+        resolve()
+      }).catch(reason => {
+        console.error('Error switching projects', reason)
+        NotificationStore.notify('Error switching projects')
+        this.logout()
+        reject()
+      })
     })
   }