2 * STANDARD_RIFT_IO_COPYRIGHT
5 import React from 'react';
6 import ReactDOM from 'react-dom';
7 import AppHeader from 'widgets/header/header.jsx';
8 import RedundancyStore from './redundancyStore.js';
9 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
10 import SkyquakeRBAC from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
11 import 'style/layout.scss';
12 import {Panel, PanelWrapper} from 'widgets/panel/panel';
13 import {InputCollection, FormSection} from 'widgets/form_controls/formControls.jsx';
15 import TextInput from 'widgets/form_controls/textInput.jsx';
16 import Input from 'widgets/form_controls/input.jsx';
17 import Button, {ButtonGroup} from 'widgets/button/sq-button.jsx';
18 import SelectOption from 'widgets/form_controls/selectOption.jsx';
19 import 'widgets/form_controls/formControls.scss';
20 import imgAdd from '../../node_modules/open-iconic/svg/plus.svg'
21 import imgRemove from '../../node_modules/open-iconic/svg/trash.svg'
22 import _ from 'lodash';
23 import ROLES from 'utils/roleConstants.js';
25 import './redundancy.scss';
26 const PLATFORM = ROLES.PLATFORM;
28 class ConfigDashboard extends React.Component {
31 this.Store = this.props.flux.stores.hasOwnProperty('RedundancyStore') ? this.props.flux.stores.RedundancyStore : this.props.flux.createStore(RedundancyStore, 'RedundancyStore');
32 this.state = this.Store.getState();
33 this.actions = this.state.actions;
35 componentDidUpdate() {
37 componentWillMount() {
38 this.state = this.Store.getState();
39 this.Store.getRedundancy();
40 this.Store.listen(this.updateState);
42 componentWillUnmount() {
43 this.Store.unlisten(this.updateState);
45 updateState = (state) => {
48 updateConfigInput = (containerName, key, e) => {
49 let configData = this.state[containerName];
53 configData[key] = e.target.value;
54 this.actions.handleUpdateConfigInput({[containerName]:configData})
56 updateDnsIpFqdnConfigInput = (e) => {
57 let value = e.target.value;
58 this.actions.handleUpdateConfigInput({'dns-ip-fqdn':value})
60 updateConfig = (e) => {
64 let configData = self.state.configData;
65 let userCredentials = configData['user-credentials'];
66 if (!userCredentials || (userCredentials['username'].trim() == '' ) || (userCredentials['password'].trim() == '' )) {
67 self.props.flux.actions.global.showNotification("Please enter your user credentials");
70 this.Store.updateConfig(configData);
72 evaluateSubmit = (e) => {
73 if (e.keyCode == 13) {
74 if (this.props.isEdit) {
83 failOverDecisionChange = (e) => {
84 let value = e.target.value;
85 value = value.toUpperCase();
86 this.actions.handleFailOverDecisionChange(value);
91 let props = this.props;
92 let state = this.state;
93 let passwordSectionHTML = null;
94 let configData = state.configData;
95 let formButtonsHTML = (
96 <ButtonGroup className="buttonGroup">
97 <Button label="Update" type="submit" onClick={this.updateConfig} />
100 let GeoFailoverDecision = this.state.configData['geographic-failover-decision'];
103 <PanelWrapper onKeyUp={this.evaluateSubmit}
104 className={`SiteAdmin column`} column>
105 <AppHeader nav={[{ name: 'SITES', onClick: this.context.router.push.bind(this, { pathname: '/sites' }) }, { name: 'CONFIG'}, { name: 'STATUS', onClick: this.context.router.push.bind(this, { pathname: '/status' }) }]} />
106 <PanelWrapper onKeyUp={this.evaluateSubmit}
107 className={`SiteAdmin column`} style={{overflow: 'auto'}} column>
109 title="GEOGRAPHIC FAILOVER DECISION"
110 style={{flex: `0 0 ${GeoFailoverDecision != "INDIRECT" ? '150px' : '220px'}`}}
112 <Input className="userInfo-section"
114 onChange={this.failOverDecisionChange}
115 value={GeoFailoverDecision}
116 options={state.failOverDecisionOptions}
119 GeoFailoverDecision != "INDIRECT" ? null :
120 <Input type="text" onChange={self.updateDnsIpFqdnConfigInput.bind(self)} label="DNS FQDN/IP Address" value={state.configData['dns-ip-fqdn']} />
124 GeoFailoverDecision == "DIRECT" ?
126 title="Preferred Failback Site"
127 style={{flex: '0 0 160px'}}
129 <Input type="text" onChange={self.updateConfigInput.bind(self, 'revertive-preference', 'preferred-site-name')} label="Site Name" value={state.configData['revertive-preference'] && state.configData['revertive-preference']['preferred-site-name']} />
134 title="User Credentials"
135 style={{flex: '0 0 250px'}}
137 <Input type="text" onChange={self.updateConfigInput.bind(self, 'user-credentials', 'username')} label="Username" value={state.configData['user-credentials'] && state.configData['user-credentials']['username']}
139 <Input type="password" onChange={self.updateConfigInput.bind(self, 'user-credentials', 'password')} label="Password" value={state.configData['user-credentials'] && state.configData['user-credentials']['password']}
143 title="Polling Configuration"
144 style={{flex: `0 0 ${GeoFailoverDecision != "INDIRECT" ? '390px' : '230px'}`}}
146 <Input type="text" onChange={self.updateConfigInput.bind(self, 'polling-config', 'poll-interval')} label="polling interval (s)" value={state.configData['polling-config'] && state.configData['polling-config']['poll-interval']} />
148 GeoFailoverDecision == "DIRECT" ?
149 <Input type="text" onChange={self.updateConfigInput.bind(self, 'polling-config', 'failover-timeo')} label="Failover Timeout (s)" value={state.configData['polling-config'] && state.configData['polling-config']['failover-timeo']} />
153 GeoFailoverDecision == "DIRECT" ?
154 <Input type="text" onChange={self.updateConfigInput.bind(self, 'polling-config', 'failback-timeo')} label="Failback Timeout (s)" value={state.configData['polling-config'] && state.configData['polling-config']['failback-timeo']} />
157 <Input type="text" onChange={self.updateConfigInput.bind(self,'polling-config', 'no-response-counter')} label="No Response Counter" value={state.configData['polling-config'] && state.configData['polling-config']['no-response-counter']} />
162 <SkyquakeRBAC allow={[PLATFORM.SUPER, PLATFORM.ADMIN]} site={this.state.name} className="rbacButtonGroup">
170 // onClick={this.Store.update.bind(null, Account)}
171 ConfigDashboard.contextTypes = {
172 router: React.PropTypes.object,
173 userProfile: React.PropTypes.object
176 ConfigDashboard.defaultProps = {
181 export default SkyquakeComponent(ConfigDashboard);
184 function isElementInView(el) {
185 var rect = el && el.getBoundingClientRect() || {};
190 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
191 rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
196 // isReadOnly={state.isReadOnly} disabled={state.disabled} onChange={this.disableChange}
198 class isDisabled extends React.Component {
203 let props = this.props;
208 function showInput(e){
209 let target = e.target;
210 if(target.parentElement.classList.contains("addInput")) {
211 target = target.parentElement;
213 target.style.display = 'none';
214 target.parentElement.nextElementSibling.style.display = 'flex';
215 // e.target.parentElement.nextElementSibling.children[1].style.display = 'initial';
217 function hideInput(e){
218 let target = e.target;
219 if(target.parentElement.classList.contains("removeInput")) {
220 target = target.parentElement;
222 target.parentElement.style.display = 'none';
223 target.parentElement.previousElementSibling.children[1].style.display = 'inline';
224 target.previousSibling.value = '';