소스 검색

Merge pull request #8 from george-vrancianu/master

Various fixes
Alessandro Pilotti 8 년 전
부모
커밋
1d616c2178

+ 4 - 4
src/components/AddCloudConnection/AddCloudConnection.js

@@ -61,6 +61,9 @@ class AddCloudConnection extends Reflux.Component {
   componentWillMount() {
     super.componentWillMount.call(this)
     this.context.onSetTitle(title);
+    if (this.state.currentCloudData == null) {
+      this.setState({ currentCloudData: {} })
+    }
   }
 
   componentDidMount() {
@@ -326,7 +329,7 @@ class AddCloudConnection extends Reflux.Component {
   }
 
   /**
-   * Checks wether the field is valid. Only goes through validation if field is required
+   * Checks whether the field is valid. Only goes through validation if field is required
    * @param field
    * @returns {boolean}
    */
@@ -490,9 +493,6 @@ class AddCloudConnection extends Reflux.Component {
    * @returns {XML}
    */
   renderCloudFields(cloud) {
-    if (this.state.currentCloudData == null) {
-      this.setState({ currentCloudData: {} })
-    }
     let fields = cloud.endpoint.fields.map(field => this.renderField(field), this)
 
     return (

+ 4 - 2
src/components/App/App.scss

@@ -440,9 +440,8 @@ button {
 :global(.items-list) {
   :global(.item) {
     display: flex;
-    padding: 8px 0;
+    padding: 8px;
     border-bottom: 1px solid $gray-light;
-    padding-left: 16px;
     &:first-child {
       border-top: 1px solid $gray-light;
     }
@@ -698,6 +697,9 @@ button {
   font-size: 16px;
   text-align: center;
   padding: 40px 0;
+  button {
+    margin-top: 24px;
+  }
 }
 :global {
   .noResultsLarge {

+ 1 - 1
src/components/CloudItem/CloudItem.js

@@ -26,7 +26,7 @@ class CloudItem extends Component {
   static propTypes = {
     cloud: PropTypes.object,
     addCredentialsCallback: PropTypes.func,
-    credentialSelected: PropTypes.array,
+    credentialSelected: PropTypes.object,
     callback: PropTypes.func,
     exclude: PropTypes.string,
     selected: PropTypes.bool

+ 6 - 6
src/components/MigrationWizard/MigrationWizard.js

@@ -61,7 +61,7 @@ class MigrationWizard extends Reflux.Component {
   componentWillMount() {
     super.componentWillMount.call(this)
     this.context.onSetTitle(title);
-    if (this.props.wizard_type == "replica") {
+    if (this.props.wizard_type === "replica") {
       WizardActions.updateWizardState({
         migrationType: "replica"
       })
@@ -70,13 +70,13 @@ class MigrationWizard extends Reflux.Component {
 
 
   back() {
-    if (this.state.backCallback != null) {
+    if (typeof this.state.backCallback === "function") {
       this.state.backCallback((e) => this.initBackStep(e))
     } else {
       if (this.state.currentStep != "WizardMigrationType") {
         this.initBackStep()
       } else {
-        if (this.props.wizard_type == "replica") {
+        if (this.props.wizard_type === "replica") {
           Location.push("/replicas")
         } else {
           Location.push("/migrations")
@@ -97,11 +97,11 @@ class MigrationWizard extends Reflux.Component {
   }
 
   next() {
-    if (this.state.currentStep == "WizardSummary") {
+    if (this.state.currentStep === "WizardSummary") {
       this.finish()
     } else if (this.state.valid) {
       // Callback to run before next step
-      if (this.state.nextCallback != null) {
+      if (typeof this.state.nextCallback === "function") {
         this.state.nextCallback((e) => this.initNextStep(e))
       } else {
         this.initNextStep()
@@ -134,7 +134,7 @@ class MigrationWizard extends Reflux.Component {
     MigrationActions.addMigration(newMigration, () => {
       ConnectionsActions.resetSelections()
       WizardActions.newState()
-      if (newMigration.migrationType == "replica") {
+      if (newMigration.migrationType === "replica") {
         Location.push('/replicas')
       } else {
         Location.push('/migrations')

+ 3 - 0
src/components/WizardNetworks/WizardNetworks.scss

@@ -43,6 +43,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
           }
         }
       }
+      &:hover {
+        background: transparent;
+      }
     }
   }
 }

+ 7 - 1
src/components/WizardSchedule/WizardSchedule.scss

@@ -18,7 +18,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 @import '../variables.scss';
 
 .root {
-
+  :global(.items-list) {
+    :global(.item) {
+      &:hover {
+        background: transparent;
+      }
+    }
+  }
 }
 .addScheduleBtn {
   display: block;

+ 6 - 9
src/components/WizardSummary/WizardSummary.js

@@ -34,7 +34,6 @@ class WizardSummary extends Component {
   static propTypes = {
     setWizardState: PropTypes.func,
     summary: PropTypes.object,
-
   }
 
   constructor(props) {
@@ -75,7 +74,8 @@ class WizardSummary extends Component {
             {this.dateTypes.indexOf(item.type) == -1 ? item.type : moment(item.date).format("MMM Do YYYY")}
           </span>
           <span className="cell">
-            {item.hour.label + ":" + item.minute.label + " " + item.tod + " " + item.timezone}
+            {item.type != "Execute Now" &&
+              (item.hour.label + ":" + item.minute.label + " " + item.tod + " " + item.timezone)}
           </span>
         </div>
       ), this)
@@ -86,11 +86,8 @@ class WizardSummary extends Component {
           <TextTruncate line={1} text={vm.name} truncateText="..." />
         </span>
         <span className="cell">
-          {vm.num_cpu} vCPU | {vm.memory_mb} MB RAM
+          {vm.num_cpu} vCPU | {vm.memory_mb} MB RAM {vm.flavor_name && ("| " + vm.flavor_name)}
         </span>
-        {/*            <span className="cell">
-         {vm.status}
-         </span>*/}
       </div>
     ))
 
@@ -130,15 +127,15 @@ class WizardSummary extends Component {
                 <div className={s.row}>
                   <span>Source: <br /> </span>
                   <span>
+                    <TextTruncate line={1} text={this.props.summary.sourceCloud.credential.name} truncateText="..." />
                     <span className={s.cloudBox}>{this.props.summary.sourceCloud.name}</span>
-                    {this.props.summary.sourceCloud.credential.name}
                   </span>
                 </div>
                 <div className={s.row}>
                   <span>Target:</span>
                   <span>
+                    <TextTruncate line={1} text={this.props.summary.targetCloud.credential.name} truncateText="..." />
                     <span className={s.cloudBox}>{this.props.summary.targetCloud.name}</span>
-                    {this.props.summary.targetCloud.credential.name}
                   </span>
                 </div>
               </div>
@@ -161,7 +158,7 @@ class WizardSummary extends Component {
               <h3>
                 Schedule
               </h3>
-              <div className={s.instances + " items-list"}>
+              <div className={s.schedules + " items-list"}>
                 {schedules}
               </div>
             </div>

+ 20 - 4
src/components/WizardSummary/WizardSummary.scss

@@ -70,6 +70,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 .networks {
   :global(.item) {
     color: $black;
+    padding: 8px 0;
     :global(.cell) {
       &:nth-child(1) {
         flex: 10;
@@ -85,6 +86,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
         display: block;
       }
     }
+    &:hover {
+      background: transparent;
+    }
   }
 }
 .cloudBox {
@@ -105,25 +109,37 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 }
 .instances {
   :global(.item) {
+    flex-direction: column;
+    padding: 0px 0px 16px;
+    border: 0 !important;
     :global(.cell){
       &:nth-child(1) {
         color: $black;
-        width:50%;
-        margin-right: 4px;
+        width:100%;
         display: block;
       }
       &:nth-child(2) {
-        width:50%;
+        width:100%;
+        font-size: 80%;
+        padding-top: 4px;
       }
       &:nth-child(3) {
         color: $blue;
         flex: 1;
       }
     }
+    &:hover {
+      background: transparent;
+    }
   }
 }
 .schedules {
-
+  :global(.item) {
+    padding: 8px 0;
+    &:hover {
+      background: transparent;
+    }
+  }
 }
 .migrationType {
   line-height: 20px;

+ 50 - 27
src/components/WizardVms/WizardVms.js

@@ -49,6 +49,9 @@ class WizardVms extends Component {
         }
       })
     }
+
+    this.retryLoadingInstances = this.retryLoadingInstances.bind(this)
+
     this.state = {
       valid,
       queryText: '',
@@ -198,35 +201,55 @@ class WizardVms extends Component {
     }
   }
 
+  retryLoadingInstances() {
+    ConnectionsActions.loadInstances(
+      { id: this.props.data.sourceCloud.credential.id },
+      this.state.page,
+      this.state.queryText,
+      false
+    )
+  }
+
   renderSearch() {
     let _this = this
-    if (this.state.filteredData && this.state.filteredData.length) {
-      let instances = this.state.filteredData.map((item, index) =>
-        <div className="item" key={ "vm_" + index } onClick={ (e) => _this.checkVm(e, item) }>
-          <div className="checkbox-container">
-            <input
-              id={"vm_check_" + index}
-              type="checkbox"
-              checked={this.isSelected(item)}
-              onChange={(e) => _this.checkVm(e, item)}
-              className="checkbox-normal"
-            />
-            <label htmlFor={ "vm_check_" + index }></label>
-          </div>
-          <span className="cell cell-icon">
-            <div className="icon vm"></div>
-            <span className="details">
-              {item.instance_name}
-            </span>
-          </span>
-          <span className="cell">{item.num_cpu} vCPU | {item.memory_mb} MB RAM | {item.flavor_name}</span>
-        </div>
-       )
-      return instances
-    } else if (this.props.data.instances && this.props.data.instances.length == 0) {
-      return <div className="no-results">Your search returned no results</div>
-    } else {
-      return <LoadingIcon padding={64} text="Loading instances.." />
+    switch (this.props.data.instancesLoadState) {
+      case "success":
+        if (this.state.filteredData && this.state.filteredData.length) {
+          let instances = this.state.filteredData.map((item, index) =>
+            <div className="item" key={ "vm_" + index } onClick={ (e) => _this.checkVm(e, item) }>
+              <div className="checkbox-container">
+                <input
+                  id={"vm_check_" + index}
+                  type="checkbox"
+                  checked={this.isSelected(item)}
+                  onChange={(e) => _this.checkVm(e, item)}
+                  className="checkbox-normal"
+                />
+                <label htmlFor={ "vm_check_" + index }></label>
+              </div>
+              <span className="cell cell-icon">
+                <div className="icon vm"></div>
+                <span className="details">
+                  {item.instance_name}
+                </span>
+              </span>
+              <span className="cell">{item.num_cpu} vCPU | {item.memory_mb} MB RAM
+                {item.flavor_name && (" | " + item.flavor_name)}</span>
+            </div>
+          )
+          return instances
+        } else {
+          return <div className="no-results">Your search returned no results</div>
+        }
+      case "error":
+        return (<div className="no-results">
+          An error occurred while searching for instances <br />
+          <button onClick={this.retryLoadingInstances}>Retry</button>
+        </div>)
+      case "loading":
+        return <LoadingIcon padding={64} text="Loading instances.." />
+      default:
+        return <LoadingIcon padding={64} text="Loading instances.." />
     }
   }
 

+ 19 - 5
src/stores/WizardStore/WizardStore.js

@@ -41,6 +41,7 @@ class WizardStore extends Reflux.Store
     schedules: [],
     instances: null,
     selectedInstances: [],
+    instancesLoadState: null,
     vms: null,
     showAdvancedOptions: false,
     destination_environment: {},
@@ -53,11 +54,11 @@ class WizardStore extends Reflux.Store
   constructor() {
     super()
     this.listenables = [WizardActions, ConnectionsActions]
-
-    this.state = Object.assign({}, this.blankState)
+    this.state = this._assignNewState()
   }
 
   onLoadInstances(endpoint, page = 0, queryText = "", cache = true, clearSelection = false) {
+    this.setState({ instancesLoadState: 'loading' })
     if (cache && (this.state.instances && this.state.instances[page * itemsPerPage])) {
       return;
     }
@@ -102,11 +103,11 @@ class WizardStore extends Reflux.Store
       instances[(page * itemsPerPage) + index] = instance
     })
 
-    this.setState({ instances: instances })
+    this.setState({ instances: instances, instancesLoadState: 'success' })
   }
 
   onLoadInstancesFailed() {
-    this.setState({ instances: [] })
+    this.setState({ instances: [], instancesLoadState: 'error' })
   }
 
   onLoadInstanceDetail(endpoint, instance) {
@@ -148,7 +149,7 @@ class WizardStore extends Reflux.Store
   }
 
   onNewState() {
-    this.setState(this.blankState)
+    this.setState(this._assignNewState())
   }
 
   onUpdateWizardState(state, callback = null) {
@@ -156,6 +157,19 @@ class WizardStore extends Reflux.Store
     if (callback) callback()
   }
 
+  _assignNewState() {
+    let newState = {}
+    for (let i in this.blankState) {
+      if (typeof this.blankState[i] === "object" && this.blankState[i] != null &&
+        this.blankState[i].constructor !== Array) {
+        newState[i] = Object.assign({}, this.blankState[i])
+      } else {
+        newState[i] = this.blankState[i]
+      }
+    }
+    return newState
+  }
+
 }
 
 WizardStore.id = "wizardStore"