/*
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);