Explorar el Código

Merge pull request #378 from smiclea/reload-edit

Add cache refresh support to Edit Replica modal
Dorin Paslaru hace 6 años
padre
commit
0d5c912a5f

+ 24 - 8
src/components/molecules/Panel/Panel.jsx

@@ -23,6 +23,7 @@ const Wrapper = styled.div`
   display: flex;
   min-height: 0;
   flex-grow: 1;
+  position: relative;
 `
 const Navigation = styled.div`
   width: 224px;
@@ -49,6 +50,17 @@ const Content = styled.div`
   flex-direction: column;
   min-height: 0;
 `
+const ReloadButton = styled.div`
+  font-size: 10px;
+  color: ${Palette.grayscale[4]};
+  &:hover {
+    color: ${Palette.primary};
+  }
+  cursor: pointer;
+  position: absolute;
+  bottom: 42px;
+  left: 32px;
+`
 
 export type NavigationItem = {
   label: string,
@@ -61,6 +73,7 @@ export type Props = {
   selectedValue: string,
   onChange: (item: NavigationItem) => void,
   style?: any,
+  onReloadClick: () => void,
 }
 
 export const TEST_ID = 'panel'
@@ -76,15 +89,18 @@ class Panel extends React.Component<Props> {
   render() {
     return (
       <Wrapper style={this.props.style}>
-        <Navigation>{this.props.navigationItems.map(item => (
-          <NavigationItemDiv
-            key={item.value}
-            selected={this.props.selectedValue === item.value}
-            onClick={() => { this.handleItemClick(item) }}
-            data-test-id={`${TEST_ID}-navItem-${item.value}`}
-          >{item.label}</NavigationItemDiv>
-        ))}</Navigation>
+        <Navigation>
+          {this.props.navigationItems.map(item => (
+            <NavigationItemDiv
+              key={item.value}
+              selected={this.props.selectedValue === item.value}
+              onClick={() => { this.handleItemClick(item) }}
+              data-test-id={`${TEST_ID}-navItem-${item.value}`}
+            >{item.label}</NavigationItemDiv>
+          ))}
+        </Navigation>
         <Content data-test-id={`${TEST_ID}-content`}>{this.props.content}</Content>
+        <ReloadButton onClick={() => { this.props.onReloadClick() }}>Reload All Replica Options</ReloadButton>
       </Wrapper>
     )
   }

+ 1 - 0
src/components/molecules/Panel/story.jsx

@@ -32,6 +32,7 @@ storiesOf('Panel', module)
         navigationItems={navigationItems}
         selectedValue="network"
         onChange={item => console.log(item, 'clicked')}
+        onReloadClick={() => { }}
       />
     </div>
   ))

+ 29 - 4
src/components/molecules/Panel/test.jsx

@@ -35,27 +35,52 @@ const wrap = (props: Props) => new TW(shallow(
 
 describe('Panel Component', () => {
   it('renders navigation items', () => {
-    let wrapper = wrap({ navigationItems, content, onChange: () => { }, selectedValue: 'navigation2' })
+    let wrapper = wrap({
+      navigationItems,
+      content,
+      onChange: () => { },
+      selectedValue: 'navigation2',
+      onReloadClick: () => { },
+    })
     navigationItems.forEach(i => {
       expect(wrapper.findText(`navItem-${i.value}`)).toBe(i.label)
     })
   })
 
   it('selects the selected value', () => {
-    let wrapper = wrap({ navigationItems, content, onChange: () => { }, selectedValue: 'navigation2' })
+    let wrapper = wrap({
+      navigationItems,
+      content,
+      onChange: () => { },
+      selectedValue: 'navigation2',
+      onReloadClick: () => { },
+
+    })
     expect(wrapper.find('navItem-navigation1').prop('selected')).toBeFalsy()
     expect(wrapper.find('navItem-navigation2').prop('selected')).toBe(true)
   })
 
   it('dispatches onChange', () => {
     let onChange = sinon.spy()
-    let wrapper = wrap({ navigationItems, content, onChange, selectedValue: 'navigation2' })
+    let wrapper = wrap({
+      navigationItems,
+      content,
+      onChange,
+      selectedValue: 'navigation2',
+      onReloadClick: () => { },
+    })
     wrapper.find('navItem-navigation1').simulate('click')
     expect(onChange.called).toBe(true)
   })
 
   it('renders content', () => {
-    let wrapper = wrap({ navigationItems, content, onChange: () => { }, selectedValue: 'navigation2' })
+    let wrapper = wrap({
+      navigationItems,
+      content,
+      onChange: () => { },
+      selectedValue: 'navigation2',
+      onReloadClick: () => { },
+    })
     expect(wrapper.findText('content')).toBe(content)
   })
 })

+ 13 - 2
src/components/organisms/EditReplica/EditReplica.jsx

@@ -79,6 +79,7 @@ type Props = {
   instancesDetailsLoading: boolean,
   networks: Network[],
   networksLoading: boolean,
+  onReloadClick: () => void,
 }
 type State = {
   selectedPanel: string,
@@ -101,18 +102,22 @@ class EditReplica extends React.Component<Props, State> {
   scrollableRef: HTMLElement
 
   componentWillMount() {
+    this.loadData(true)
+  }
+
+  loadData(useCache: boolean) {
     providerStore.loadProviders().then(() => {
       if (this.hasStorageMap()) {
         endpointStore.loadStorage(this.props.destinationEndpoint.id, {})
       }
     })
 
-    providerStore.loadDestinationSchema(this.props.destinationEndpoint.type, this.props.type || 'replica').then(() => {
+    providerStore.loadDestinationSchema(this.props.destinationEndpoint.type, this.props.type || 'replica', useCache).then(() => {
       return providerStore.getOptionsValues({
         optionsType: 'destination',
         endpointId: this.props.destinationEndpoint.id,
         provider: this.props.destinationEndpoint.type,
-        useCache: true,
+        useCache,
       })
     }).then(() => {
       this.loadEnvDestinationOptions()
@@ -195,6 +200,11 @@ class EditReplica extends React.Component<Props, State> {
     this.setState({ selectedPanel: panel })
   }
 
+  handleReload() {
+    this.props.onReloadClick()
+    this.loadData(false)
+  }
+
   handleDestinationFieldChange(field: Field, value: any) {
     let destinationData = { ...this.state.destinationData }
     if (field.type === 'array') {
@@ -452,6 +462,7 @@ class EditReplica extends React.Component<Props, State> {
           content={this.renderContent()}
           onChange={navItem => { this.handlePanelChange(navItem.value) }}
           selectedValue={this.state.selectedPanel}
+          onReloadClick={() => { this.handleReload() }}
         />
       </Modal>
     )

+ 10 - 4
src/components/pages/MigrationDetailsPage/MigrationDetailsPage.jsx

@@ -67,7 +67,7 @@ class MigrationDetailsPage extends React.Component<Props, State> {
     document.title = 'Migration Details'
 
     endpointStore.getEndpoints()
-    this.loadMigrationWithInstances(this.props.match.params.id)
+    this.loadMigrationWithInstances(this.props.match.params.id, true)
     this.pollData()
   }
 
@@ -77,7 +77,7 @@ class MigrationDetailsPage extends React.Component<Props, State> {
     }
 
     endpointStore.getEndpoints()
-    this.loadMigrationWithInstances(newProps.match.params.id)
+    this.loadMigrationWithInstances(newProps.match.params.id, true)
   }
 
   componentWillUnmount() {
@@ -85,7 +85,7 @@ class MigrationDetailsPage extends React.Component<Props, State> {
     clearTimeout(this.pollTimeout)
   }
 
-  loadMigrationWithInstances(migrationId: string) {
+  loadMigrationWithInstances(migrationId: string, cache: boolean) {
     migrationStore.getMigration(migrationId, true).then(() => {
       let details = migrationStore.migrationDetails
       if (!details) {
@@ -94,12 +94,13 @@ class MigrationDetailsPage extends React.Component<Props, State> {
 
       networkStore.loadNetworks(details.destination_endpoint_id, details.destination_environment, {
         quietError: true,
+        useLocalStorage: cache,
       })
       instanceStore.loadInstancesDetails(
         details.origin_endpoint_id,
         // $FlowIgnore
         details.instances.map(n => { return { instance_name: n } }),
-        false, true
+        false, cache
       )
     })
   }
@@ -195,6 +196,10 @@ class MigrationDetailsPage extends React.Component<Props, State> {
     })
   }
 
+  handleEditReplicaReload() {
+    this.loadMigrationWithInstances(this.props.match.params.id, false)
+  }
+
   handleUpdateComplete(redirectTo: string) {
     this.props.history.push(redirectTo)
   }
@@ -222,6 +227,7 @@ class MigrationDetailsPage extends React.Component<Props, State> {
         instancesDetailsLoading={instanceStore.loadingInstancesDetails}
         networks={networkStore.networks}
         networksLoading={networkStore.loading}
+        onReloadClick={() => { this.handleEditReplicaReload() }}
       />
     )
   }

+ 10 - 4
src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.jsx

@@ -80,7 +80,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
   componentDidMount() {
     document.title = 'Replica Details'
 
-    this.loadReplicaWithInstances(this.props.match.params.id)
+    this.loadReplicaWithInstances(this.props.match.params.id, true)
     endpointStore.getEndpoints()
     scheduleStore.getSchedules(this.props.match.params.id)
     this.pollData(true)
@@ -88,7 +88,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
 
   componentWillReceiveProps(newProps: Props) {
     if (newProps.match.params.id !== this.props.match.params.id) {
-      this.loadReplicaWithInstances(newProps.match.params.id)
+      this.loadReplicaWithInstances(newProps.match.params.id, true)
       scheduleStore.getSchedules(newProps.match.params.id)
     }
   }
@@ -99,7 +99,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
     clearTimeout(this.pollTimeout)
   }
 
-  loadReplicaWithInstances(replicaId: string) {
+  loadReplicaWithInstances(replicaId: string, cache: boolean) {
     replicaStore.getReplica(replicaId).then(() => {
       let details = replicaStore.replicaDetails
       if (!details) {
@@ -107,12 +107,13 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
       }
       networkStore.loadNetworks(details.destination_endpoint_id, details.destination_environment, {
         quietError: true,
+        useLocalStorage: cache,
       })
       instanceStore.loadInstancesDetails(
         details.origin_endpoint_id,
         // $FlowIgnore
         details.instances.map(n => { return { instance_name: n } }),
-        false, true
+        false, cache
       )
     })
   }
@@ -301,6 +302,10 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
     })
   }
 
+  handleEditReplicaReload() {
+    this.loadReplicaWithInstances(this.props.match.params.id, false)
+  }
+
   handleUpdateComplete(redirectTo: string) {
     if (!replicaStore.replicaDetails) {
       return
@@ -333,6 +338,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
         instancesDetailsLoading={instanceStore.loadingInstancesDetails}
         networks={networkStore.networks}
         networksLoading={networkStore.loading}
+        onReloadClick={() => { this.handleEditReplicaReload() }}
       />
     )
   }

+ 1 - 1
src/stores/InstanceStore.js

@@ -262,7 +262,7 @@ class InstanceStore {
 
     instancesInfo.sort((a, b) => a.instance_name.localeCompare(b.instance_name))
     let hash = i => `${i.instance_name}-${i.id || endpointId}`
-    if (this.instancesDetails.map(hash).join('_') === instancesInfo.map(hash).join('_')) {
+    if (useLocalStorage && this.instancesDetails.map(hash).join('_') === instancesInfo.map(hash).join('_')) {
       return Promise.resolve()
     }
 

+ 1 - 1
src/stores/NetworkStore.js

@@ -50,7 +50,7 @@ class NetworkStore {
     quietError?: boolean,
   }): Promise<void> {
     let id = `${endpointId}-${btoa(JSON.stringify(environment))}`
-    if (this.cachedId === id) {
+    if (this.cachedId === id && options && options.useLocalStorage) {
       return Promise.resolve()
     }
 

+ 14 - 4
src/stores/ProviderStore.js

@@ -23,13 +23,13 @@ import type { OptionValues } from '../types/Endpoint'
 import type { Field } from '../types/Field'
 import type { Providers } from '../types/Providers'
 
-export const getFieldChangeDestOptions = (options: {
+export const getFieldChangeDestOptions = (config: {
   provider: ?string,
   destSchema: Field[],
   data: any,
   field: ?Field,
 }) => {
-  let { provider, destSchema, data, field } = options
+  let { provider, destSchema, data, field } = config
   let providerWithExtraOptions = configLoader.config.destinationProvidersWithExtraOptions
     .find(p => typeof p !== 'string' && p.name === provider)
   if (!provider || !providerWithExtraOptions || typeof providerWithExtraOptions === 'string' || !providerWithExtraOptions.envRequiredFields) {
@@ -115,13 +115,23 @@ class ProviderStore {
     })
   }
 
-  @action loadDestinationSchema(providerName: string, schemaType: string): Promise<void> {
-    this.destinationSchemaLoading = true
+  destinationSchemaCache: { [string]: Field[] } = {}
+  @action loadDestinationSchema(providerName: string, schemaType: string, cache?: boolean): Promise<void> {
     this.lastDestinationSchemaType = schemaType
 
+    let cacheKey = `${providerName}-${schemaType}`
+    let cacheData = this.destinationSchemaCache[cacheKey]
+    if (cache && cacheData) {
+      this.destinationSchema = [...cacheData]
+      return Promise.resolve()
+    }
+
+    this.destinationSchemaLoading = true
+
     return ProviderSource.loadDestinationSchema(providerName, schemaType).then((fields: Field[]) => {
       this.destinationSchemaLoading = false
       this.destinationSchema = fields
+      this.destinationSchemaCache[cacheKey] = fields
     }).catch(err => {
       this.destinationSchemaLoading = false
       throw err