2 * STANDARD_RIFT_IO_COPYRIGHT
5 import React from 'react';
6 import Button from 'widgets/button/rw.button.js';
7 import _cloneDeep from 'lodash/cloneDeep';
8 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
9 import Crouton from 'react-crouton';
10 import TextInput from 'widgets/form_controls/textInput.jsx';
11 import 'style/common.scss';
12 import './config.scss';
13 class Account extends React.Component {
17 this.state.account = {};
19 storeListener = (state) => {
21 this.setUp(this.props)
23 state.account && this.setState({account: state.account,accountType: state.accountType, types: state.types, sdnOptions: state.sdnOptions})
25 componentWillMount() {
26 this.props.store.listen(this.storeListener);
27 this.setUp(this.props);
29 componentWillReceiveProps(nextProps) {
30 if(JSON.stringify(nextProps.params) != JSON.stringify(this.props.params)){
31 this.setUp(nextProps);
34 componentWillUnmount() {
35 this.props.store.unlisten(this.storeListener);
38 if(props.params.name != 'create') {
39 this.props.store.viewAccount({type: props.params.type, name: props.params.name});
41 this.props.store.setAccountTemplate(props.params.type);
47 var Account = this.state.account;
48 let AccountType = this.state.accountType;
49 if (Account.name == "") {
50 self.props.flux.actions.global.showNotification("Please give the account a name");
53 var type = Account['account-type'];
54 var params = Account.params;
57 for (var i = 0; i < params.length; i++) {
58 var param = params[i].ref;
59 if (typeof(Account[type]) == 'undefined' || typeof(Account[type][param]) == 'undefined' || Account[type][param] == "") {
60 if (!params[i].optional) {
61 self.props.flux.actions.global.showNotification("Please fill all account details");
68 let nestedParams = Account.nestedParams && Account.nestedParams;
69 if (nestedParams && nestedParams.params) {
70 for (let i = 0; i < nestedParams.params.length; i++) {
71 let nestedParam = nestedParams.params[i].ref;
72 if (typeof(Account[type]) == 'undefined' || typeof(Account[type][nestedParams['container-name']][nestedParam]) == 'undefined' || Account[type][nestedParams['container-name']][nestedParam] == "") {
73 if (!nestedParams.params[i].optional) {
74 self.props.flux.actions.global.showNotification("Please fill all account details");
82 let newAccount = _cloneDeep(removeTrailingWhitespace(Account));
83 delete newAccount.params;
84 newAccount.nestedParams &&
85 newAccount.nestedParams['container-name'] &&
86 delete newAccount[newAccount.nestedParams['container-name']];
87 delete newAccount.nestedParams;
89 this.props.flux.actions.global.showScreenLoader();
90 this.props.store.create(newAccount, AccountType).then(function() {
91 self.props.router.push({pathname:'accounts'});
92 self.props.flux.actions.global.hideScreenLoader.defer();
95 self.props.flux.actions.global.showNotification("There was an error creating your account. Please contact your system administrator.");
96 self.props.flux.actions.global.hideScreenLoader.defer();
102 var Account = this.state.account;
103 let AccountType = this.state.accountType;
104 this.props.flux.actions.global.showScreenLoader();
105 this.props.store.update(Account, AccountType).then(function() {
106 self.props.router.push({pathname:'accounts'});
107 self.props.flux.actions.global.hideScreenLoader();
116 this.props.router.push({pathname:'accounts'});
118 handleDelete = () => {
120 let msg = 'Preparing to delete "' + self.state.account.name + '"' +
121 ' Are you sure you want to delete this ' + self.state.accountType + ' account?"';
122 if (window.confirm(msg)) {
123 this.props.store.delete(self.state.accountType, self.state.account.name).then(function() {
124 self.props.flux.actions.global.hideScreenLoader();
125 self.props.router.push({pathname:'accounts'});
127 // self.props.flux.actions.global.hideScreenLoader.defer();
128 // console.log('Delete Account Fail');
131 self.props.flux.actions.global.hideScreenLoader();
134 handleNameChange(event) {
135 this.props.store.handleNameChange(event);
137 handleAccountTypeChange(node, event) {
138 this.props.store.handleAccountTypeChange(node, event);
140 handleSelectSdnAccount = (e) => {
141 var tmp = this.state.account;
143 tmp['sdn-account'] = e;
145 if(tmp['sdn-account']) {
146 delete tmp['sdn-account'];
151 preventDefault = (e) => {
155 evaluateSubmit = (e) => {
156 if (e.keyCode == 13) {
157 if (this.props.edit) {
169 let {store, ...props} = this.props;
170 // This section builds elements that only show up on the create page.
171 // var name = <label>Name <input type="text" onChange={this.handleNameChange.bind(this)} style={{'textAlign':'left'}} /></label>;
172 var name = <TextInput label="Name" onChange={this.handleNameChange.bind(this)} required={true} />;
174 let selectAccount = null;
175 let resfreshStatus = null;
176 let Account = this.state.account;
177 // AccountType is for the view, not the data account-type value;
178 let AccountType = this.state.accountType;
179 let Types = this.state.types;
180 let isEdit = this.props.params.name != 'create';
182 let cloudResources = Account['cloud-resources-state'] && Account['cloud-resources-state'][Account['account-type']];
183 let cloudResourcesStateHTML = null;
185 // Account Type Radio
186 var selectAccountStack = [];
189 <Button key="0" onClick={this.cancel} className="cancel light" label="Cancel"></Button>,
190 <Button key="1" role="button" onClick={this.create.bind(this)} className="save dark" label="Save" />
192 for (var i = 0; i < Types.length; i++) {
194 var isSelected = (Account['account-type'] == node['account-type']);
195 selectAccountStack.push(
196 <label key={i} className={"accountSelection " + (isSelected ? "accountSelection--isSelected" : "")}>
197 <div className={"accountSelection-overlay" + (isSelected ? "accountSelection-overlay--isSelected" : "")}></div>
198 <div className="accountSelection-imageWrapper">
199 <img src={store.getImage(node['account-type'])}/>
201 <input type="radio" name="account" onChange={this.handleAccountTypeChange.bind(this, node)} defaultChecked={node.name == Types[0].name} value={node['account-type']} />{node.name}
206 <div className="accountForm">
207 <h3 className="accountForm-title">Select Account Type</h3>
208 <div className="select-type accountForm-content" >
218 // This sections builds the parameters for the account details.
219 if (Account.params) {
220 var paramsStack = [];
221 var optionalField = '';
222 for (var i = 0; i < Account.params.length; i++) {
223 var node = Account.params[i];
225 if (Account[Account['account-type']]) {
226 value = Account[Account['account-type']][node.ref]
228 if (this.props.edit && Account.params) {
229 value = Account.params[node.ref];
232 <TextInput key={node.label} className="accountForm-input" label={node.label} required={!node.optional} onChange={this.props.store.handleParamChange(node)} value={value} />
236 <li className="create-fleet-pool accountForm">
237 <h3 className="accountForm-title"> {isEdit ? 'Update' : 'Enter'} Account Details</h3>
238 <div className="accountForm-content">
245 <li className="create-fleet-pool accountForm">
246 <h3 className="accountForm-title"> {isEdit ? 'Update' : 'Enter'}</h3>
247 <label style={{'marginLeft':'17px', color:'#888'}}>No Details Required</label>
252 // This section builds elements that only show up in the edit page.
254 name = <label>{Account.name}</label>;
256 <Button key="2" onClick={this.handleDelete} className="light" label="Remove Account" />,
257 <Button key="3" onClick={this.cancel} className="light" label="Cancel" />,
258 <Button key="4" role="button" onClick={this.update.bind(this)} className="update dark" label="Update" />
260 resfreshStatus = Account['connection-status'] ? (
261 <div className="accountForm">
262 <div className="accountForm-title accountForm-title--edit">
265 <div className="accountForm-content" style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
266 <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
267 <AccountConnectivityStatus status={Account['connection-status'].status} />
268 {Account['connection-status'].status.toUpperCase()}
270 <Button className="refreshList light" onClick={this.props.store.refreshAccount.bind(this, Account.name, AccountType)} label="REFRESH STATUS"></Button>
273 Account['connection-status'].status.toUpperCase() === 'FAILURE' ?
274 displayFailureMessage(Account['connection-status'].details) : null
278 // cloudResourcesStateHTML = (
279 // <div className="accountForm">
280 // <h3 className="accountForm-title">Resources Status</h3>
281 // <div className="accountForm-content" >
284 // cloudResources && props.AccountMeta.resources[Account['account-type']].map(function(r, i) {
288 // {r}: {cloudResources[r]}
291 // }) || 'No Additional Resources'
301 <form className="app-body create Accounts" onSubmit={this.preventDefault} onKeyDown={this.evaluateSubmit}>
302 <div className="noticeSubText noticeSubText_right">
305 <div className="associateSdnAccount accountForm">
306 <h3 className="accountForm-title">Account</h3>
307 <div className="accountForm-content" style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
308 <h4 style={{flex: '1'}}>{name}</h4>
311 <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
312 <img src={store.getImage(Account['account-type'])}/> {props.AccountMeta.labelByType[Account['account-type']]}
322 {cloudResourcesStateHTML}
323 <ol className="flex-row">
326 <div className="form-actions">
335 function displayFailureMessage(msg) {
337 <div className="accountForm-content" style={{maxWidth: '600px'}}>
338 <div style={{paddingBottom: '1rem'}}>Details:</div>
347 class SelectOption extends React.Component {
351 handleOnChange = (e) => {
352 this.props.onChange(JSON.parse(e.target.value));
357 <select className={this.props.className} onChange={this.handleOnChange}>
359 this.props.options.map(function(op, i) {
360 return <option key={i} value={JSON.stringify(op.value)}>{op.label}</option>
368 SelectOption.defaultProps = {
370 onChange: function(e) {
375 function removeTrailingWhitespace(Account) {
376 var type = Account['account-type'];
377 var params = Account.params;
380 for (var i = 0; i < params.length; i++) {
381 var param = params[i].ref;
382 if(typeof(Account[type][param]) == 'string') {
383 Account[type][param] = Account[type][param].trim();
388 let nestedParams = Account.nestedParams;
389 if (nestedParams && nestedParams.params) {
390 for (let i = 0; i < nestedParams.params.length; i++) {
391 let nestedParam = nestedParams.params[i].ref;
392 let nestedParamValue = Account[type][nestedParams['container-name']][nestedParam];
393 if (typeof(nestedParamValue) == 'string') {
394 Account[type][nestedParams['container-name']][nestedParam] = nestedParamValue.trim();
401 export default SkyquakeComponent(Account)