ソースを参照

Merge pull request #467 from smiclea/wizard-reload

Improve Wizard page reload state preservation
Nashwan Azhari 6 年 前
コミット
b52054bc98

+ 26 - 25
src/components/pages/WizardPage/WizardPage.jsx

@@ -96,7 +96,7 @@ class WizardPage extends React.Component<Props, State> {
   }
   }
 
 
   componentWillMount() {
   componentWillMount() {
-    this.initializeState()
+    this.initializeState(this.props.match)
     this.handleResize()
     this.handleResize()
   }
   }
 
 
@@ -108,11 +108,11 @@ class WizardPage extends React.Component<Props, State> {
   }
   }
 
 
   componentWillReceiveProps(newProps: Props) {
   componentWillReceiveProps(newProps: Props) {
-    if (newProps.location.search === this.props.location.search) {
+    if (newProps.location === this.props.location) {
       return
       return
     }
     }
     wizardStore.clearData()
     wizardStore.clearData()
-    this.initializeState()
+    this.initializeState(newProps.match)
   }
   }
 
 
   componentWillUnmount() {
   componentWillUnmount() {
@@ -182,8 +182,8 @@ class WizardPage extends React.Component<Props, State> {
       source: null,
       source: null,
     })
     })
     wizardStore.clearStorageMap()
     wizardStore.clearStorageMap()
-    wizardStore.setPermalink(wizardStore.data)
-    this.setState({ type: isReplica ? 'replica' : 'migration' })
+    let type = isReplica ? 'replica' : 'migration'
+    this.props.history.replace(`/wizard/${type}`)
   }
   }
 
 
   handleBackClick() {
   handleBackClick() {
@@ -215,7 +215,7 @@ class WizardPage extends React.Component<Props, State> {
   async handleSourceEndpointChange(source: ?EndpointType) {
   async handleSourceEndpointChange(source: ?EndpointType) {
     wizardStore.updateData({ source, selectedInstances: null, networks: null, sourceOptions: null })
     wizardStore.updateData({ source, selectedInstances: null, networks: null, sourceOptions: null })
     wizardStore.clearStorageMap()
     wizardStore.clearStorageMap()
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
 
 
     if (!source) {
     if (!source) {
       return
       return
@@ -236,7 +236,7 @@ class WizardPage extends React.Component<Props, State> {
   async handleTargetEndpointChange(target: EndpointType) {
   async handleTargetEndpointChange(target: EndpointType) {
     wizardStore.updateData({ target, networks: null, destOptions: null })
     wizardStore.updateData({ target, networks: null, destOptions: null })
     wizardStore.clearStorageMap()
     wizardStore.clearStorageMap()
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
     if (this.pages.find(p => p.id === 'storage')) {
     if (this.pages.find(p => p.id === 'storage')) {
       endpointStore.loadStorage(target.id, {})
       endpointStore.loadStorage(target.id, {})
     }
     }
@@ -271,7 +271,7 @@ class WizardPage extends React.Component<Props, State> {
         wizardStore.updateData({ target: endpointStore.endpoints[0] })
         wizardStore.updateData({ target: endpointStore.endpoints[0] })
       }
       }
     }
     }
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
     this.setState({ showNewEndpointModal: false })
     this.setState({ showNewEndpointModal: false })
   }
   }
 
 
@@ -291,7 +291,7 @@ class WizardPage extends React.Component<Props, State> {
     wizardStore.updateData({ networks: null })
     wizardStore.updateData({ networks: null })
     wizardStore.clearStorageMap()
     wizardStore.clearStorageMap()
     wizardStore.toggleInstanceSelection(instance)
     wizardStore.toggleInstanceSelection(instance)
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleInstancePageClick(page: number) {
   handleInstancePageClick(page: number) {
@@ -310,7 +310,7 @@ class WizardPage extends React.Component<Props, State> {
     if (field.type !== 'string' || field.enum) {
     if (field.type !== 'string' || field.enum) {
       this.loadExtraOptions(field, 'destination')
       this.loadExtraOptions(field, 'destination')
     }
     }
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleSourceOptionsChange(field: Field, value: any) {
   handleSourceOptionsChange(field: Field, value: any) {
@@ -319,28 +319,32 @@ class WizardPage extends React.Component<Props, State> {
     if (field.type !== 'string' || field.enum) {
     if (field.type !== 'string' || field.enum) {
       this.loadExtraOptions(field, 'source')
       this.loadExtraOptions(field, 'source')
     }
     }
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleNetworkChange(sourceNic: Nic, targetNetwork: Network, targetSecurityGroups: ?SecurityGroup[]) {
   handleNetworkChange(sourceNic: Nic, targetNetwork: Network, targetSecurityGroups: ?SecurityGroup[]) {
     wizardStore.updateNetworks({ sourceNic, targetNetwork, targetSecurityGroups })
     wizardStore.updateNetworks({ sourceNic, targetNetwork, targetSecurityGroups })
-    wizardStore.setPermalink(wizardStore.data)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleStorageChange(source: Disk, target: StorageBackend, type: 'backend' | 'disk') {
   handleStorageChange(source: Disk, target: StorageBackend, type: 'backend' | 'disk') {
     wizardStore.updateStorage({ source, target, type })
     wizardStore.updateStorage({ source, target, type })
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleAddScheduleClick(schedule: Schedule) {
   handleAddScheduleClick(schedule: Schedule) {
     wizardStore.addSchedule(schedule)
     wizardStore.addSchedule(schedule)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleScheduleChange(scheduleId: string, data: Schedule) {
   handleScheduleChange(scheduleId: string, data: Schedule) {
     wizardStore.updateSchedule(scheduleId, data)
     wizardStore.updateSchedule(scheduleId, data)
+    wizardStore.updateUrlState()
   }
   }
 
 
   handleScheduleRemove(scheduleId: string) {
   handleScheduleRemove(scheduleId: string) {
     wizardStore.removeSchedule(scheduleId)
     wizardStore.removeSchedule(scheduleId)
+    wizardStore.updateUrlState()
   }
   }
 
 
   async handleReloadOptionsClick() {
   async handleReloadOptionsClick() {
@@ -361,9 +365,9 @@ class WizardPage extends React.Component<Props, State> {
     await this.loadExtraOptions(undefined, optionsType, false)
     await this.loadExtraOptions(undefined, optionsType, false)
   }
   }
 
 
-  initializeState() {
-    wizardStore.getDataFromPermalink()
-    let type = this.props.match && this.props.match.params.type
+  initializeState(match: any) {
+    wizardStore.getUrlState()
+    let type = match && match.params && match.params.type
     if (type === 'migration' || type === 'replica') {
     if (type === 'migration' || type === 'replica') {
       this.setState({ type })
       this.setState({ type })
     }
     }
@@ -405,16 +409,13 @@ class WizardPage extends React.Component<Props, State> {
         useCache: true,
         useCache: true,
       })
       })
 
 
-      // Preload source options if data is set from 'Permalink'
-      if (providerStore.sourceOptions.length === 0) {
-        await providerStore.getOptionsValues({
-          optionsType,
-          endpointId: endpoint.id,
-          providerName: endpoint.type,
-          useCache: true,
-        })
-        await this.loadExtraOptions(undefined, optionsType)
-      }
+      await providerStore.getOptionsValues({
+        optionsType,
+        endpointId: endpoint.id,
+        providerName: endpoint.type,
+        useCache: true,
+      })
+      await this.loadExtraOptions(undefined, optionsType)
     }
     }
 
 
     switch (page.id) {
     switch (page.id) {

+ 12 - 7
src/sources/WizardSource.js

@@ -78,19 +78,24 @@ class WizardSource {
     return mainItems.filter(Boolean).map(i => i)
     return mainItems.filter(Boolean).map(i => i)
   }
   }
 
 
-  setPermalink(data: WizardData) {
-    // window.history.replaceState({}, null, `${window.location.href}?d=${btoa(JSON.stringify(data))}`)
-    let exp = /.*?(?:\?|$)/.exec(window.location.href)
-    if (!exp) {
+  setUrlState(data: any) {
+    let locationExp = /.*?(?:\?|$)/.exec(window.location.href)
+    if (!locationExp) {
       return
       return
     }
     }
-    let location = exp[0].replace('?', '')
+    let location = locationExp[0].replace('?', '')
     window.history.replaceState({}, null, `${location}?d=${btoa(JSON.stringify(data))}`)
     window.history.replaceState({}, null, `${location}?d=${btoa(JSON.stringify(data))}`)
   }
   }
 
 
-  getDataFromPermalink() {
+  getUrlState() {
     let dataExpExec = /\?d=(.*)/.exec(window.location.href)
     let dataExpExec = /\?d=(.*)/.exec(window.location.href)
-    return dataExpExec && JSON.parse(atob(dataExpExec[1]))
+    let result = null
+    try {
+      result = dataExpExec && JSON.parse(atob(dataExpExec[1]))
+    } catch (err) {
+      console.error(err)
+    }
+    return result
   }
   }
 }
 }
 
 

+ 11 - 13
src/stores/WizardStore.js

@@ -24,7 +24,7 @@ import type { NetworkMap } from '../types/Network'
 import type { StorageMap } from '../types/Endpoint'
 import type { StorageMap } from '../types/Endpoint'
 import type { Schedule } from '../types/Schedule'
 import type { Schedule } from '../types/Schedule'
 import { wizardPages } from '../constants'
 import { wizardPages } from '../constants'
-import Source from '../sources/WizardSource'
+import source from '../sources/WizardSource'
 
 
 const updateOptions = (oldOptions: ?{ [string]: mixed }, data: { field: Field, value: any }) => {
 const updateOptions = (oldOptions: ?{ [string]: mixed }, data: { field: Field, value: any }) => {
   let options = { ...oldOptions }
   let options = { ...oldOptions }
@@ -141,7 +141,7 @@ class WizardStore {
     this.creatingItem = true
     this.creatingItem = true
 
 
     try {
     try {
-      let item: MainItem = await Source.create(type, data, storageMap)
+      let item: MainItem = await source.create(type, data, storageMap)
       runInAction(() => { this.createdItem = item })
       runInAction(() => { this.createdItem = item })
     } catch (err) {
     } catch (err) {
       throw err
       throw err
@@ -154,27 +154,25 @@ class WizardStore {
     this.creatingItems = true
     this.creatingItems = true
 
 
     try {
     try {
-      let items: MainItem[] = await Source.createMultiple(type, data, storageMap)
+      let items: MainItem[] = await source.createMultiple(type, data, storageMap)
       runInAction(() => { this.createdItems = items })
       runInAction(() => { this.createdItems = items })
     } finally {
     } finally {
       runInAction(() => { this.creatingItems = false })
       runInAction(() => { this.creatingItems = false })
     }
     }
   }
   }
 
 
-  setPermalink(data: WizardData) {
-    Source.setPermalink(data)
+  updateUrlState() {
+    source.setUrlState({ data: this.data, schedules: this.schedules, storageMap: this.storageMap })
   }
   }
 
 
-  @action getDataFromPermalink() {
-    let data = Source.getDataFromPermalink()
-    if (!data) {
+  @action getUrlState() {
+    let state = source.getUrlState()
+    if (!state) {
       return
       return
     }
     }
-
-    this.data = {
-      ...this.data,
-      ...data,
-    }
+    this.data = state.data
+    this.schedules = state.schedules
+    this.storageMap = state.storageMap
   }
   }
 }
 }