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

Merge pull request #113 from smiclea/wizard-permalink

Encode Wizard's state in URL ('Permalink' support)
Dorin Paslaru 8 лет назад
Родитель
Сommit
27de30553d

+ 10 - 0
src/actions/WizardActions.js

@@ -86,6 +86,16 @@ class WizardActions {
   createMultipleFailed(response) {
     return response || true
   }
+
+  setPermalink(data) {
+    WizardSource.setPermalink(data)
+    return data || true
+  }
+
+  getDataFromPermalink() {
+    let data = WizardSource.getDataFromPermalink()
+    return data || true
+  }
 }
 
 export default alt.createActions(WizardActions)

+ 17 - 1
src/components/pages/WizardPage/WizardPage.jsx

@@ -83,6 +83,7 @@ class WizardPage extends React.Component {
   }
 
   componentWillMount() {
+    WizardActions.getDataFromPermalink()
     let type = this.props.match && this.props.match.params.type
     if (type === 'migration' || type === 'replica') {
       this.setState({ type })
@@ -99,10 +100,16 @@ class WizardPage extends React.Component {
 
   loadDataForPage(page) {
     switch (page.id) {
-      case 'source':
+      case 'source': {
         ProviderActions.loadProviders()
         EndpointActions.getEndpoints()
+        // Preload instances if data is set from 'Permalink'
+        let source = WizardStore.getState().data.source
+        if (InstanceStore.getState().instances.length === 0 && source) {
+          InstanceActions.loadInstances(source.id)
+        }
         break
+      }
       case 'options':
         ProviderActions.loadOptionsSchema(this.props.wizardStore.data.target.type, this.state.type)
         break
@@ -271,12 +278,14 @@ class WizardPage extends React.Component {
 
   handleSourceEndpointChange(source) {
     WizardActions.updateData({ source, selectedInstances: null, networks: null })
+    WizardActions.setPermalink(WizardStore.getState().data)
     // Preload instances for 'vms' page
     InstanceActions.loadInstances(source.id)
   }
 
   handleTargetEndpointChange(target) {
     WizardActions.updateData({ target, networks: null, options: null })
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleAddEndpoint(newEndpointType, newEndpointFromSource) {
@@ -295,6 +304,7 @@ class WizardPage extends React.Component {
         WizardActions.updateData({ target: this.props.endpointStore.endpoints[0] })
       }
     }
+    WizardActions.setPermalink(WizardStore.getState().data)
     this.setState({ showNewEndpointModal: false })
   }
 
@@ -317,27 +327,33 @@ class WizardPage extends React.Component {
   handleInstanceClick(instance) {
     WizardActions.updateData({ networks: null })
     WizardActions.toggleInstanceSelection(instance)
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleOptionsChange(field, value) {
     WizardActions.updateData({ networks: null })
     WizardActions.updateOptions({ field, value })
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleNetworkChange(sourceNic, targetNetwork) {
     WizardActions.updateNetworks({ sourceNic, targetNetwork })
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleAddScheduleClick(schedule) {
     WizardActions.addSchedule(schedule)
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleScheduleChange(scheduleId, data) {
     WizardActions.updateSchedule(scheduleId, data)
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   handleScheduleRemove(scheduleId) {
     WizardActions.removeSchedule(scheduleId)
+    WizardActions.setPermalink(WizardStore.getState().data)
   }
 
   render() {

+ 21 - 0
src/sources/WizardSource.js

@@ -101,6 +101,27 @@ class WizardSource {
       })
     })
   }
+
+  static setPermalink(data) {
+    let hashExp = /(#\/wizard\/.*?)(?:\?|$)/
+
+    if (!hashExp.test(window.location.hash)) {
+      return
+    }
+
+    let hash = hashExp.exec(window.location.hash)[1]
+    window.history.replaceState({}, null, `${hash}?d=${btoa(JSON.stringify(data))}`)
+  }
+
+  static getDataFromPermalink() {
+    let dataExp = /\?d=(.*)/
+
+    if (!dataExp.test(window.location.hash)) {
+      return null
+    }
+
+    return JSON.parse(atob(dataExp.exec(window.location.hash)[1]))
+  }
 }
 
 export default WizardSource

+ 12 - 0
src/stores/WizardStore.js

@@ -42,6 +42,7 @@ class WizardStore {
       handleCreateMultiple: WizardActions.CREATE_MULTIPLE,
       handleCreateMultipleSuccess: WizardActions.CREATE_MULTIPLE_SUCCESS,
       handleCreateMultipleFailed: WizardActions.CREATE_MULTIPLE_FAILED,
+      handleGetDataFromPermalink: WizardActions.GET_DATA_FROM_PERMALINK,
     })
   }
 
@@ -145,6 +146,17 @@ class WizardStore {
   handleCreateMultipleFailed() {
     this.creatingItems = false
   }
+
+  handleGetDataFromPermalink(data) {
+    if (data === true) {
+      return
+    }
+
+    this.data = {
+      ...this.data,
+      ...data,
+    }
+  }
 }
 
 export default alt.createStore(WizardStore)