Skip to content

Commit

Permalink
Merge pull request #154 from mageddo/feature/76
Browse files Browse the repository at this point in the history
Switchable environments
  • Loading branch information
mageddo authored Aug 26, 2019
2 parents f49c4ba + 99c06e5 commit 817678f
Show file tree
Hide file tree
Showing 27 changed files with 4,478 additions and 7,997 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/node_modules
2 changes: 1 addition & 1 deletion Dockerfile.builder
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:8.15-jessie AS BUILDER
FROM node:12-alpine AS BUILDER
COPY app /app
WORKDIR /app
ENV PUBLIC_URL=/static
Expand Down
5 changes: 5 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### 2.18.0
* Feature: Multiple environments, now you can setup a group of hostnames and save it to a environment, then you can
create a new environment and switch between them, very useful when working on different contexts switching from QA to PROD,
for example, [see the docs](http://mageddo.github.io/dns-proxy-server/2.18/en/2-features/multiple-environments/)

### 2.17.4
* Clearing cache for resolvers when the config file is saved

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.17.4
2.18.0
11,779 changes: 3,958 additions & 7,821 deletions app/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"jquery": "3.4.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "2.1.8",
"jquery": "3.4.0"
"react-scripts": "3.0.1"
},
"scripts": {
"start": "react-scripts start",
Expand Down
1 change: 1 addition & 0 deletions app/public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ body {
position: fixed!important;
top: 0;
width: 100%;
z-index: 9999;
}

.records-actions .btn {
Expand Down
2 changes: 1 addition & 1 deletion app/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<footer>
<div class="container">
<div style="text-align: center;">
MAGEDDO &copy; 2016 - Licensed by <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
MAGEDDO &copy; 2016-2019 - Licensed by <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
</div>
</div>
</footer>
Expand Down
33 changes: 0 additions & 33 deletions app/src/App.css

This file was deleted.

28 changes: 0 additions & 28 deletions app/src/App.js

This file was deleted.

83 changes: 83 additions & 0 deletions app/src/components/EnvForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react'
import $ from 'jquery';

const createEnvironment = (name, callback) => {
const sanitizedInput = name.replace(/[^a-z0-9\s_-]+/gi, '').trim();

if (!sanitizedInput.length) {
window.$.notify({
title: 'Ops',
message: 'Only letters, numbers, _ and - are allowed in environment name'
}, {
type: 'warning'
});

return;
}

new Promise((resolve, reject) => {
$.ajax('/env/', {
type: 'POST',
contentType: 'application/json',
error: response => {
if (response.status === 200) {
resolve();
return;
}

reject(new Error(`HTTP ${response.status}`));
},
success: () => resolve(),
data: JSON.stringify({
name: sanitizedInput
}),
});
})
.then(
() => {
window.$.notify({
message: `Environment '${sanitizedInput}' created successfully`
}, {
type: 'success'
});

callback(sanitizedInput);
}, response => {
window.$.notify({
title: 'Ops!',
message: 'An error ocurred',
}, {
type: 'danger'
})

console.error('Could not create environment: %o', response);
}
);
}

const EnvForm = ({ onCreate, onCancel }) => {
const textInput = React.createRef();

return (
<div className="input-group">
<input placeholder="my new env..." type="text" className="form-control" ref={textInput} />
<div className="input-group-append">
<button
title="Save"
className="btn btn-info fa fa-save"
type="button"
onClick={ev => createEnvironment(textInput.current.value, onCreate)}
></button>

<button
title="Cancel"
className="btn btn-dark fa fa-times"
onClick={() => onCancel()}
type="button"
></button>
</div>
</div>
)
};

export default EnvForm;
126 changes: 126 additions & 0 deletions app/src/components/EnvPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React from 'react'
import $ from 'jquery';

const DEFAULT_ENV = '';

export default class EnvPicker extends React.PureComponent {
constructor(...args) {
super(...args);

const { env: current = '' } = this.props;

this.state = {
envList: [],
current
};
}

reload() {
return $.ajax({
url: '/env/',
}).then(data => {
console.debug('c=EnvPicker, m=getData, data=%o', data);
this.setState({envList: data});
}, function (err) {
console.error('c=EnvPicker, m=getData, status=error', err);
});
}

deleteCurrent() {
const { state: { current: env } } = this;
console.log('c=EnvPicker, m=deleteCurrent, env=%s', env);

const defer = $.Deferred();

if (env === DEFAULT_ENV) {
const message = 'Deleting default environment is not allowed';

window.$.notify({
title: 'Ops!',
message
}, {
type: 'danger'
});

defer.rejectWith(new Error(message));
return defer.promise();
}

$.ajax('/env/', {
type: 'DELETE',
contentType: 'application/json',
error: ({ status }) => {
if (status === 200) {
defer.resolve();
return;
}

defer.rejectWith(new Error(`HTTP ${status}`));
},
success: () => defer.resolve(),
data: JSON.stringify({
name: env
})
});

return defer.promise();
}

componentDidMount() {
this.reload();
}

handleChanges(ev) {
const { target: { options, selectedIndex } } = ev;
const current = options[selectedIndex].value;

this.setState(
{ current },
() => this.props.onChange(current)
);
}

render() {
const { envList, current } = this.state;
const deleteEnv = () => {
this.deleteCurrent()
.then(() => this.props.onDelete())
.fail(err => console.error('m=render, err=%o', err))
};

console.debug('c=EnvPicker, m=render, env=%s', current);

return (
<div className="input-group">
<select className="form-control"
onChange={ev => this.handleChanges(ev)}
value={current}
name="env"
>
{envList.map(
({ name }, index) => (<option key={name} value={name}>{name.length ? name : 'Default'}</option>)
)}
</select>
<div className="input-group-append">
<button
title="Create new env"
onClick={() => this.props.onToggle()}
className="btn btn-info"
type="button"
>
<span className="fa fa-plus-circle"></span>
</button>
<button
title="Delete selected env"
onClick={deleteEnv}
className="btn btn-danger"
type="button"
>
<span className="fa fa-trash-alt"></span>
</button>
</div>
</div>
)
}
}

Loading

0 comments on commit 817678f

Please sign in to comment.