blob: c91a8599cce97de2e4d3eb427b07ff5f547a3550 [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
define([
"app",
"api",
"react",
"addons/cors/stores",
"addons/cors/resources",
"addons/cors/actions",
'addons/components/react-components.react'
], function (app, FauxtonAPI, React, Stores, Resources, Actions, ReactComponents) {
var corsStore = Stores.corsStore;
var validateOrigin = function (origin) {
if (!Resources.validateCORSDomain(origin)) {
FauxtonAPI.addNotification({
msg: 'Please enter a valid domain, starting with http/https.',
type: 'error',
clear: true
});
return false;
}
return true;
};
var OriginRow = React.createClass({
getInitialState: function () {
return {
edit: false,
updatedOrigin: this.props.origin
};
},
editOrigin: function (event) {
event.preventDefault();
this.setState({edit: !this.state.edit});
},
updateOrigin: function (event) {
event.preventDefault();
if (!validateOrigin(this.state.updatedOrigin)) {
return;
}
this.props.updateOrigin(this.state.updatedOrigin, this.props.origin);
this.setState({edit: false});
},
deleteOrigin: function (event) {
event.preventDefault();
if (!window.confirm('Are you sure you want to delete ' + this.props.origin)) {
return;
}
this.props.deleteOrigin(this.props.origin);
},
onInputChange: function (event) {
this.setState({updatedOrigin: event.target.value});
},
onKeyUp: function (e) {
if (e.keyCode === 13) { //enter key
return this.updateOrigin(e);
}
},
createOriginDisplay: function () {
if (this.state.edit) {
return (
<div className="input-append edit-domain-section">
<input type="text" name="update_origin_domain" onChange={this.onInputChange} onKeyUp={this.onKeyUp} value={this.state.updatedOrigin} />
<button onClick={this.updateOrigin} className="btn btn-primary update-origin"> Update </button>
</div>
);
}
return <div className="js-url url-display">{this.props.origin}</div>;
},
render: function () {
var display = this.createOriginDisplay();
return (
<tr>
<td>
{ display }
</td>
<td width="30">
<span className="fonticon-pencil" onClick={this.editOrigin} title="Click to edit"></span>
</td>
<td width="30">
<span className="fonticon-trash" onClick={this.deleteOrigin} title="Click to delete"></span>
</td>
</tr>
);
}
});
var OriginTable = React.createClass({
createRows: function () {
return _.map(this.props.origins, function (origin, i) {
return <OriginRow
updateOrigin={this.props.updateOrigin}
deleteOrigin={this.props.deleteOrigin}
key={i} origin={origin} />;
}, this);
},
render: function () {
if (!this.props.origins) {
return null;
}
if (!this.props.isVisible || this.props.origins.length === 0) {
return null;
}
var origins = this.createRows();
return (
<table id="origin-domain-table" className="table table-striped">
<tbody>
{origins}
</tbody>
</table>
);
}
});
var OriginInput = React.createClass({
getInitialState: function () {
return {
origin: ''
};
},
onInputChange: function (e) {
this.setState({origin: e.target.value});
},
addOrigin: function (event) {
event.preventDefault();
if (!validateOrigin(this.state.origin)) {
return;
}
var url = Resources.normalizeUrls(this.state.origin);
this.props.addOrigin(url);
this.setState({origin: ''});
},
onKeyUp: function (e) {
if (e.keyCode == 13) { //enter key
return this.addOrigin(e);
}
},
render: function () {
if (!this.props.isVisible) {
return null;
}
return (
<div id="origin-domains-container">
<div className="origin-domains">
<div className="input-append">
<input type="text" name="new_origin_domain" onChange={this.onInputChange} onKeyUp={this.onKeyUp} value={this.state.origin} placeholder="e.g., https://site.com"/>
<button onClick={this.addOrigin} className="btn btn-primary add-domain"> Add </button>
</div>
</div>
</div>
);
}
});
var Origins = React.createClass({
onOriginChange: function (event) {
if (event.target.value === 'all' && this.props.isAllOrigins) {
return; // do nothing if all origins is already selected
}
if (event.target.value === 'selected' && !this.props.isAllOrigins) {
return; // do nothing if specific origins is already selected
}
this.props.originChange(event.target.value === 'all');
},
render: function () {
if (!this.props.corsEnabled) {
return null;
}
return (
<div>
<p><strong> Origin Domains </strong> </p>
<p>Databases will accept requests from these domains: </p>
<label className="radio">
<input type="radio" checked={this.props.isAllOrigins} value="all" onChange={this.onOriginChange} name="all-domains"/> All domains ( * )
</label>
<label className="radio">
<input type="radio" checked={!this.props.isAllOrigins} value="selected" onChange={this.onOriginChange} name="selected-domains"/> Restrict to specific domains
</label>
</div>
);
}
});
var CORSController = React.createClass({
getStoreState: function () {
return {
corsEnabled: corsStore.isEnabled(),
origins: corsStore.getOrigins(),
isAllOrigins: corsStore.isAllOrigins(),
configChanged: corsStore.hasConfigChanged(),
shouldSaveChange: corsStore.shouldSaveChange(),
node: corsStore.getNode(),
isLoading: corsStore.getIsLoading()
};
},
getInitialState: function () {
return this.getStoreState();
},
componentDidMount: function () {
corsStore.on('change', this.onChange, this);
},
componentWillUnmount: function () {
corsStore.off('change', this.onChange);
},
componentDidUpdate: function () {
if (this.state.shouldSaveChange) {
this.save();
}
},
onChange: function () {
this.setState(this.getStoreState());
},
enableCorsChange: function () {
if (this.state.corsEnabled && !_.isEmpty(this.state.origins) ) {
var result = window.confirm(app.i18n.en_US['cors-disable-cors-prompt']);
if (!result) { return; }
}
Actions.toggleEnableCors();
},
save: function () {
Actions.saveCors({
enableCors: this.state.corsEnabled,
origins: this.state.origins,
node: this.state.node
});
},
deleteOrigin: function (origin) {
Actions.deleteOrigin(origin);
},
originChange: function (isAllOrigins) {
if (isAllOrigins && !_.isEmpty(this.state.origins)) {
var result = window.confirm('Are you sure? Switching to all origin domains will overwrite your specific origin domains.');
if (!result) { return; }
}
Actions.originChange(isAllOrigins);
},
addOrigin: function (origin) {
Actions.addOrigin(origin);
},
updateOrigin: function (updatedOrigin, originalOrigin) {
Actions.updateOrigin(updatedOrigin, originalOrigin);
},
methodChange: function (httpMethod) {
Actions.methodChange(httpMethod);
},
render: function () {
var isVisible = _.all([this.state.corsEnabled, !this.state.isAllOrigins]);
var originSettings = (
<div id={this.state.corsEnabled ? 'collapsing-container' : ''}>
<Origins corsEnabled={this.state.corsEnabled} originChange={this.originChange} isAllOrigins={this.state.isAllOrigins}/>
<OriginTable updateOrigin={this.updateOrigin} deleteOrigin={this.deleteOrigin} isVisible={isVisible} origins={this.state.origins} />
<OriginInput addOrigin={this.addOrigin} isVisible={isVisible} />
</div>
);
if (this.state.isLoading) {
originSettings = (<ReactComponents.LoadLines />);
}
return (
<div className="cors-page">
<header id="cors-header">
<p>{app.i18n.en_US['cors-notice']}</p>
</header>
<form id="corsForm" onSubmit={this.save}>
<div className="cors-enable">
{this.state.corsEnabled ? 'Cors is currently enabled.' : 'Cors is currently disabled.'}
<br />
<button
type="button"
className="enable-disable btn btn-small btn-success"
onClick={this.enableCorsChange}
disabled={this.state.isLoading ? 'disabled' : null}
>
{this.state.corsEnabled ? 'Disable CORS' : 'Enable CORS'}
</button>
</div>
{originSettings}
</form>
</div>
);
}
});
return {
CORSController: CORSController,
OriginInput: OriginInput,
Origins: Origins,
OriginTable: OriginTable,
OriginRow: OriginRow
};
});