/* Copyright (C) 2017 Cloudbase Solutions SRL This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import React, { PropTypes } from 'react'; import Reflux from 'reflux'; import withStyles from 'isomorphic-style-loader/lib/withStyles'; import Location from '../../core/Location'; import Dropdown from '../NewDropdown'; import UserIcon from '../UserIcon'; import NotificationIcon from '../NotificationIcon'; import SearchBox from '../SearchBox'; import Moment from 'react-moment'; import s from './MigrationList.scss'; import MigrationStore from '../../stores/MigrationStore'; import ProjectStore from '../../stores/MigrationStore'; import MigrationActions from '../../actions/MigrationActions'; import FilteredTable from '../FilteredTable'; import TextTruncate from 'react-text-truncate'; import LoadingIcon from "../LoadingIcon/LoadingIcon"; import ConfirmationDialog from '../ConfirmationDialog' import ProjectsDropdown from '../ProjectsDropdown'; const title = 'Migrations'; const migrationTypes = [ { label: "Replicas", type: "replica" }, { label: "Migrations", type: "migration" }, { label: "All", type: "all" } ] const statusTypes = [ { label: "Running", type: "RUNNING" }, { label: "Error", type: "ERROR" }, { label: "Completed", type: "COMPLETED" }, { label: "All", type: "all" } ] const migrationActions = [ { label: "Execute", value: "execute" }, { label: "Cancel", value: "cancel" }, { label: "Delete", value: "delete" } ] class MigrationList extends Reflux.Component { constructor(props) { super(props) this.store = MigrationStore; this.state = { title: props.type == "migrations" ? "Migrations" : "Replicas", queryText: '', filterType: props.type == "migrations" ? "migration" : "replica", filterStatus: "all", currentProject: "My Project", searchMin: true, filteredData: [], selectedAll: { migration: false, replica: false }, confirmationDialog: { visible: false, message: "Are you sure?", onConfirm: null, onCancel: null } } } static contextTypes = { onSetTitle: PropTypes.func.isRequired }; componentWillReceiveProps(newProps, oldProps) { this.setState({ title: newProps.type == "migrations" ? "Migrations" : "Replicas", filterType: newProps.type == "migrations" ? "migration" : "replica" }) } componentWillMount() { super.componentWillMount.call(this) this.context.onSetTitle(this.state.title); MigrationActions.loadMigrations() this.projects = [ { label: "My Project", value: "Project1" }, { label: "Project 2", value: "Project2" } ] } componentDidMount() { this.setState({ filteredData: this.state.migrations }) // eslint-disable-line react/no-did-mount-set-state } newMigration() { Location.push('/migrations/new') } migrationsSelected() { let count = 0 let total = 0 if (this.state.migrations) { count = this.migrationsSelectedCount() if (this.state.filterType == "all") { total = this.state.migrations.length } else { this.state.migrations.forEach(item => { if (item.type == this.state.filterType) { total++ } }) } } let term = "migration" if (this.state.filterType == "replica") term = "replica" return `${count} of ${total} ${term}(s) selected`; } migrationsSelectedCount() { let count = 0 if (this.state.migrations) { this.state.migrations.forEach((item) => { if (item.selected) { if (this.state.filterType == "all") { count++ } else { if (item.type == this.state.filterType && item.selected) { count++ } } } }) } return count } migrationDetail(e, item) { if (item.type == "migration") { Location.push('/migration/' + item.id + "/") } else { Location.push('/replica/' + item.id + "/") } } checkItem(e, itemRef) { let items = this.state.migrations items.forEach((item) => { if (item == itemRef) { item.selected = !item.selected } }) let selectedAll = this.state.selectedAll selectedAll[this.state.filterType] = false this.setState({ migrations: items, selectedAll: selectedAll }) } checkAll(e) { let items = this.state.migrations let selectedAll = this.state.selectedAll items.forEach((item) => { if (item.type == this.state.filterType) { item.selected = !selectedAll[this.state.filterType] } }) selectedAll[this.state.filterType] = !selectedAll[this.state.filterType] this.setState({ migrations: items, selectedAll: selectedAll }) } searchItem(queryText) { if (queryText.target) { this.setState({queryText: queryText.target.value }) } else { this.setState({queryText: queryText }) } } filterType(e, type) { this.setState({ filterType: type }, () => { this.searchItem({ target: { value: this.state.queryText } }) }) } filterStatus(e, status) { this.setState({ filterStatus: status }, () => { this.searchItem({ target: { value: this.state.queryText } }) }) } filterFn(item, queryText, filterType, filterStatus) { return ( item.name.toLowerCase().indexOf(queryText.toLowerCase()) != -1 && (filterType == "all" || filterType == item.type) && (filterStatus == "all" || filterStatus == item.status) ) } renderSearch(items) { if (items) { let output = items.map((item, index) => { let count = 0 if (item.type == 'replica' && item.executions.length) { item.tasks = item.executions[item.executions.length - 1].tasks } if (!item.tasks) { item.tasks = [] } item.tasks.forEach((task) => { if (task.status != "COMPLETED") count++ }) let tasksRemaining = count + " out of " + item.tasks.length return (
this.checkItem(e, item)} className="checkbox-normal" />
this.migrationDetail(e, item)}>
{/*{item.name ? item.name : "N/A"}*/} {item.status}
this.migrationDetail(e, item)}>
this.migrationDetail(e, item)}> Created {/* this.migrationDetail(e, item)}> Notes */} this.migrationDetail(e, item)}> Tasks remaining {tasksRemaining} {/* Current instance {this.currentInstance(item)} */}
) }) return output } else { return (
Your search returned no results
) } } onProjectChange(project) { // TODO: Move setstate from here //this.setState({ currentProject: project.value }) } onMigrationActionChange(option) { switch (option.value) { case "delete": let deletedItems = [] // we put here the items for deletion this.state.migrations.forEach((item) => { if (item.selected) { if (this.state.filterType == "all") { deletedItems.push(item) } else { if (item.type == this.state.filterType) { deletedItems.push(item) } } } }) this.setState({ confirmationDialog: { visible: true, onConfirm: () => { this.setState({ confirmationDialog: { visible: false }}) deletedItems.forEach(item => { MigrationActions.deleteMigration(item) }) }, onCancel: () => { this.setState({ confirmationDialog: { visible: false }}) } } }) break case "execute": this.state.migrations.forEach((item) => { if (item.selected) { if (this.state.filterType == "all") { MigrationActions.executeReplica(item) } else { if (item.type == this.state.filterType) { MigrationActions.executeReplica(item) } } } }) break case "cancel": this.state.migrations.forEach((item) => { if (item.selected) { if (this.state.filterType == "all") { MigrationActions.cancelMigration(item) } else { if (item.type == this.state.filterType) { MigrationActions.cancelMigration(item) } } } }) break default: break } } currentInstance(migration) { let instance = "N/A" /*migration.vms.forEach((item) => { if (item.selected) { instance = item.name } })*/ return instance } refreshList() { MigrationActions.loadMigrations() } render() { let _this = this let itemStates = statusTypes.map((state, index) => ( _this.filterStatus(e, state.type)} key={"status_" + index} >{state.label} ) ) return (

Coriolis {this.state.title}

{/* this.onProjectChange(e)} placeholder="Select" value={this.state.currentProject} />*/}
this.checkAll()} className="checkbox-normal" />
{itemStates}
this.searchItem(e)} minimize={true} // eslint-disable-line react/jsx-boolean-value onClick={(e) => this.toggleSearch(e)} className={"searchBox " + (this.state.searchMin ? "minimize" : "")} />
{this.migrationsSelected()}
this.onMigrationActionChange(e)} placeholder="More Actions" />
this.renderSearch(e)} >
this.state.confirmationDialog.onConfirm(e)} onCancel={(e) => this.state.confirmationDialog.onCancel(e)} />
); } } export default withStyles(MigrationList, s);