EndpointList.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. Copyright (C) 2017 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import React, { PropTypes } from 'react';
  15. import Reflux from 'reflux';
  16. import withStyles from 'isomorphic-style-loader/lib/withStyles';
  17. import Location from '../../core/Location';
  18. import Moment from 'react-moment';
  19. import s from './EndpointList.scss';
  20. import AddCloudConnection from '../AddCloudConnection';
  21. import Modal from '../NewModal';
  22. import ConnectionsStore from '../../stores/ConnectionsStore';
  23. import ConnectionsActions from '../../actions/ConnectionsActions';
  24. import TextTruncate from 'react-text-truncate';
  25. import UserIcon from '../UserIcon';
  26. import EndpointUsage from '../EndpointUsage';
  27. import NotificationIcon from '../NotificationIcon';
  28. import ProjectsDropdown from '../ProjectsDropdown';
  29. import MainList from '../MainList';
  30. import Helper from '../Helper';
  31. const title = 'Cloud Endpoints';
  32. const connectionActions = {
  33. delete_action: {
  34. label: "Delete",
  35. action: (item) => {
  36. ConnectionsActions.deleteConnection(item)
  37. },
  38. confirm: true
  39. }
  40. }
  41. const filters = [
  42. {
  43. field: "type",
  44. options: [
  45. { value: null, label: "All" },
  46. { value: "opc", label: "Oracle Cloud" },
  47. { value: "oracle_vm", label: "Oracle VM Server" },
  48. { value: "openstack", label: "Openstack" },
  49. { value: "vmware_vsphere", label: "VMware" }
  50. ]
  51. }
  52. ]
  53. class EndpointList extends Reflux.Component {
  54. constructor(props) {
  55. super(props)
  56. this.store = ConnectionsStore
  57. this.state = {
  58. showModal: false,
  59. showValidationModal: false,
  60. connections: null
  61. }
  62. this.renderItem = this.renderItem.bind(this)
  63. }
  64. static contextTypes = {
  65. onSetTitle: PropTypes.func.isRequired,
  66. };
  67. componentWillMount() {
  68. super.componentWillMount.call(this)
  69. this.context.onSetTitle(title);
  70. if (this.state.connections == null) {
  71. ConnectionsActions.loadConnections()
  72. }
  73. }
  74. connectionDetail(e, item) {
  75. Location.push('/cloud-endpoints/' + item.id + "/")
  76. }
  77. refresh() {
  78. ConnectionsActions.loadConnections()
  79. }
  80. showNewConnectionModal() {
  81. this.setState({ showModal: true })
  82. }
  83. closeModal() {
  84. this.setState({ showModal: false })
  85. }
  86. validateConnection() {
  87. this.setState({ showValidationModal: true })
  88. }
  89. closeValidationModal() {
  90. this.setState({ showValidationModal: false })
  91. }
  92. addHandle() {
  93. }
  94. renderItem(item) {
  95. let createdAt = Helper.getTimeObject(item.created_at)
  96. return (
  97. <div className={"item " + (item.selected ? " selected" : "")} key={"vm_" + item.id}>
  98. <span className="cell cell-icon" onClick={(e) => this.connectionDetail(e, item)}>
  99. <div className={"icon endpoint"}></div>
  100. <span className="details">
  101. <TextTruncate line={1} truncateText="..." text={item.name} />
  102. <span className={s.description}>{item.description == "" ? "N/A" : item.description}</span>
  103. </span>
  104. </span>
  105. <span className="cell">
  106. <div className={s.cloudImage + " icon small-cloud " + item.type}></div>
  107. </span>
  108. <span className={"cell " + s.composite}>
  109. <span className={s.label}>Created</span>
  110. <span className={s.value}>
  111. <Moment fromNow ago date={createdAt} /> ago
  112. </span>
  113. </span>
  114. <span className={"cell " + s.composite}>
  115. <span className={s.label}>Usage</span>
  116. <span className={s.value}>
  117. <EndpointUsage connectionId={item.id} />
  118. </span>
  119. </span>
  120. </div>
  121. )
  122. }
  123. render() {
  124. if ((this.state.connections && this.state.connections.length) || this.state.connections == null) {
  125. return (
  126. <div className={s.root}>
  127. <div className={s.container}>
  128. <div className={s.pageHeader}>
  129. <div className={s.top}>
  130. <h1>{title}</h1>
  131. <div className={s.topActions}>
  132. <ProjectsDropdown />
  133. <button onClick={(e) => this.showNewConnectionModal(e)}>New</button>
  134. <UserIcon />
  135. <NotificationIcon />
  136. </div>
  137. </div>
  138. </div>
  139. <MainList
  140. items={this.state.connections}
  141. actions={connectionActions}
  142. itemName="connection"
  143. renderItem={this.renderItem}
  144. filters={filters}
  145. refresh={this.refresh}
  146. />
  147. </div>
  148. <Modal
  149. isOpen={this.state.showModal}
  150. contentLabel="Add new cloud connection"
  151. onRequestClose={this.closeModal.bind(this)}
  152. >
  153. <AddCloudConnection
  154. closeHandle={(e) => this.closeModal(e)}
  155. addHandle={(e) => this.addHandle(e)}
  156. />
  157. </Modal>
  158. </div>
  159. );
  160. } else {
  161. return (
  162. <div className={s.root}>
  163. <div className={s.container}>
  164. <div className={s.pageHeader}>
  165. <div className={s.top}>
  166. <h1>{title}</h1>
  167. <div className={s.topActions}>
  168. <ProjectsDropdown />
  169. <button onClick={(e) => this.showNewConnectionModal(e)}>New</button>
  170. <UserIcon />
  171. <NotificationIcon />
  172. </div>
  173. </div>
  174. <div className="noResultsLarge">
  175. <span className="icon"></span>
  176. <h3>You don't have any Cloud Endpoints in this project</h3>
  177. <p>A Cloud Endpoint is used for the source<br />
  178. or target of a Replica/Migration
  179. </p>
  180. <button onClick={(e) => this.showNewConnectionModal(e)}>Create an Endpoint</button>
  181. </div>
  182. </div>
  183. </div>
  184. <Modal
  185. isOpen={this.state.showModal}
  186. contentLabel="Add new cloud connection"
  187. onRequestClose={this.closeModal.bind(this)}
  188. >
  189. <AddCloudConnection
  190. closeHandle={(e) => this.closeModal(e)}
  191. addHandle={(e) => this.addHandle(e)}
  192. />
  193. </Modal>
  194. </div>
  195. )
  196. }
  197. }
  198. }
  199. export default withStyles(EndpointList, s);