diff --git a/lib/eventType.js b/lib/eventType.js
index 1dc8897ea6..029516a712 100644
--- a/lib/eventType.js
+++ b/lib/eventType.js
@@ -1,5 +1,6 @@
module.exports = {
featureCreated : 'feature-created',
featureUpdated : 'feature-updated',
- strategyCreated: 'strategy-created'
+ strategyCreated: 'strategy-created',
+ strategyDeleted: 'strategy-deleted'
};
\ No newline at end of file
diff --git a/lib/strategyApi.js b/lib/strategyApi.js
index ec46c0f411..facc307ebf 100644
--- a/lib/strategyApi.js
+++ b/lib/strategyApi.js
@@ -16,6 +16,18 @@ module.exports = function (app) {
.catch(function () { res.json(404, {error: 'Could not find strategy'}); });
});
+ app.delete('/strategies/:name', function (req, res) {
+ eventStore.create({
+ type: eventType.strategyDeleted,
+ createdBy: req.connection.remoteAddress,
+ data: {
+ name: req.params.name
+ }
+ })
+ .then(function () { res.status(200).end(); })
+ .catch(function () { res.status(500).end(); });
+ });
+
app.post('/strategies', function (req, res) {
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
diff --git a/lib/strategyDb.js b/lib/strategyDb.js
index b8f9f3bcc1..9c23053f5c 100644
--- a/lib/strategyDb.js
+++ b/lib/strategyDb.js
@@ -12,6 +12,15 @@ eventStore.on(eventType.strategyCreated, function (event) {
});
});
+eventStore.on(eventType.strategyDeleted, function (event) {
+ knex('strategies')
+ .where('name', event.data.name)
+ .del()
+ .catch(function (err) {
+ logger.error('Could not delete strategy, error was: ', err);
+ });
+});
+
function getStrategies() {
return knex
.select(STRATEGY_COLUMNS)
diff --git a/public/js/__tests__/Menu-test.js b/public/js/__tests__/components/Menu-test.js
similarity index 80%
rename from public/js/__tests__/Menu-test.js
rename to public/js/__tests__/components/Menu-test.js
index deffe6b9c4..59f8024856 100644
--- a/public/js/__tests__/Menu-test.js
+++ b/public/js/__tests__/components/Menu-test.js
@@ -1,8 +1,8 @@
/** @jsx React.DOM */
-jest.dontMock("../components/Menu");
+jest.dontMock("../../components/Menu");
-var Menu = require("../components/Menu");
+var Menu = require("../../components/Menu");
var React = require("react/addons");
var TestUtils = React.addons.TestUtils;
diff --git a/public/js/__tests__/components/feature/FeatureForm-test.js b/public/js/__tests__/components/feature/FeatureForm-test.js
new file mode 100644
index 0000000000..d42a0c9639
--- /dev/null
+++ b/public/js/__tests__/components/feature/FeatureForm-test.js
@@ -0,0 +1,47 @@
+jest.dontMock("../../../components/feature/FeatureForm");
+
+var React = require("react/addons");
+var TestUtils = React.addons.TestUtils;
+var FeatureForm = require("../../../components/feature/FeatureForm");
+var strategyStore = require("../../../stores/StrategyStore");
+
+describe("FeatureForm", function () {
+ var Component;
+ beforeEach(function() {
+ strategyStore.getStrategies.mockImplementation(function() {
+ return {
+ then: function (callback) {
+ return callback({
+ strategies: [
+ { name: "default"}
+ ]
+ });
+ }
+ };
+ });
+ });
+
+ afterEach(function() {
+ React.unmountComponentAtNode(document.body);
+ });
+
+ describe("new", function () {
+ it("should render empty form", function() {
+ Component = TestUtils .renderIntoDocument();
+ var name = Component.getDOMNode().querySelectorAll("input");
+ expect(name[0].value).toEqual(undefined);
+ });
+ });
+
+ describe("edit", function () {
+ var feature = {name: "Test", strategy: "unknown"};
+
+ it("should show unknown strategy as deleted", function () {
+ Component = TestUtils .renderIntoDocument();
+
+ var strategySelect = Component.getDOMNode().querySelector("select");
+ expect(strategySelect.value).toEqual("unknown (deleted)");
+ });
+ });
+
+});
\ No newline at end of file
diff --git a/public/js/components/feature/FeatureForm.jsx b/public/js/components/feature/FeatureForm.jsx
index 17998506d4..26cb524186 100644
--- a/public/js/components/feature/FeatureForm.jsx
+++ b/public/js/components/feature/FeatureForm.jsx
@@ -1,5 +1,5 @@
var React = require('react');
-var TextInput = require('../form/TextInput');
+var TextInput = require('../form/TextInput');
var strategyStore = require('../../stores/StrategyStore');
var FeatureForm = React.createClass({
@@ -36,20 +36,30 @@ var FeatureForm = React.createClass({
},
setSelectedStrategy: function(name) {
- var selected = this.state.strategyOptions.filter(function(strategy) {
+ var selectedStrategy = this.state.strategyOptions.filter(function(strategy) {
return strategy.name === name;
- });
+ })[0];
+ if(selectedStrategy) {
+ if(selectedStrategy.parametersTemplate) {
+ this.setStrategyParams(selectedStrategy);
+ }
+ } else {
+ var updatedStrategyName = name + " (deleted)";
+ this.setState({
+ currentStrategy: updatedStrategyName,
+ strategyOptions: this.state.strategyOptions.concat([{name: updatedStrategyName}])
+ });
+ }
+ },
+
+ setStrategyParams: function(strategy) {
var requiredParams = [];
var key;
-
- if(selected[0] && selected[0].parametersTemplate) {
- for(key in selected[0].parametersTemplate) {
- requiredParams.push({name: key, value: this.getParameterValue(key)});
- }
+ for(key in strategy.parametersTemplate) {
+ requiredParams.push({name: key, value: this.getParameterValue(key)});
}
this.setState({requiredParams: requiredParams});
-
},
render: function() {
diff --git a/public/js/components/strategy/StrategiesComponent.jsx b/public/js/components/strategy/StrategiesComponent.jsx
index 9fc29a97f0..0df00d17de 100644
--- a/public/js/components/strategy/StrategiesComponent.jsx
+++ b/public/js/components/strategy/StrategiesComponent.jsx
@@ -14,9 +14,16 @@ var StrategiesComponent = React.createClass({
},
componentDidMount: function () {
- strategyStore.getStrategies().then(function(res) {
- this.setState({strategies: res.strategies});
- }.bind(this), this.initError);
+ this.fetchStrategies();
+ },
+
+ fetchStrategies: function(res) {
+ strategyStore.getStrategies()
+ .then(function(res) {
+ this.setState({strategies: res.strategies})
+ }.bind(this))
+ .catch(this.initError);
+
},
initError: function() {
@@ -57,6 +64,12 @@ var StrategiesComponent = React.createClass({
.catch(this.onError);
},
+ onRemove: function(strategy) {
+ strategyStore.removeStrategy(strategy)
+ .then(this.fetchStrategies)
+ .catch(this.onError);
+ },
+
render: function() {
return (
@@ -66,7 +79,7 @@ var StrategiesComponent = React.createClass({
-
+
);
},
diff --git a/public/js/components/strategy/Strategy.jsx b/public/js/components/strategy/Strategy.jsx
index 096a2f099c..b8c383b2e6 100644
--- a/public/js/components/strategy/Strategy.jsx
+++ b/public/js/components/strategy/Strategy.jsx
@@ -5,12 +5,20 @@ var Strategy = React.createClass({
strategy: React.PropTypes.object.isRequired
},
+ onRemove: function(event) {
+ event.preventDefault();
+ if (confirm("Are you sure you want to delete strategy '"+this.props.strategy.name+"'?")) {
+ this.props.onRemove(this.props.strategy);
+ }
+ },
+
render: function() {
return (
-
{this.props.strategy.name}
-
{this.props.strategy.description}
+
{this.props.strategy.name}
+
(remove)
+
{this.props.strategy.description}
);
diff --git a/public/js/components/strategy/StrategyList.jsx b/public/js/components/strategy/StrategyList.jsx
index 261efbe88e..bf148e26fb 100644
--- a/public/js/components/strategy/StrategyList.jsx
+++ b/public/js/components/strategy/StrategyList.jsx
@@ -8,8 +8,8 @@ var StrategyList = React.createClass({
render: function() {
var strategyNodes = this.props.strategies.map(function(strategy) {
- return ;
- });
+ return ;
+ }.bind(this));
return (
{strategyNodes}
);
diff --git a/public/js/stores/StrategyStore.js b/public/js/stores/StrategyStore.js
index 80674d9e38..09388e6e34 100644
--- a/public/js/stores/StrategyStore.js
+++ b/public/js/stores/StrategyStore.js
@@ -14,6 +14,14 @@ var StrategyStore = {
});
},
+ removeStrategy: function (strategy) {
+ return reqwest({
+ url: 'strategies/'+strategy.name,
+ method: 'delete',
+ type: TYPE
+ });
+ },
+
getStrategies: function () {
return reqwest({
url: 'strategies',
diff --git a/test/strategyApiSpec.js b/test/strategyApiSpec.js
index 5da09317ac..78f9cba6aa 100644
--- a/test/strategyApiSpec.js
+++ b/test/strategyApiSpec.js
@@ -44,5 +44,9 @@ describe('The strategy api', function () {
.expect(403, done);
});
-
+ it('deletes a new strategy', function (done) {
+ request
+ .delete('/strategies/deletable')
+ .expect(200, done);
+ });
});
\ No newline at end of file
diff --git a/test/strategyDbMock.js b/test/strategyDbMock.js
index ebc1400c64..148e20620e 100644
--- a/test/strategyDbMock.js
+++ b/test/strategyDbMock.js
@@ -11,6 +11,10 @@ var strategies = [
parametersTemplate: {
emails: "String"
}
+ },
+ {
+ name: "deletable",
+ description: "deletable"
}
];