mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-15 01:16:22 +02:00
codemods
This commit is contained in:
parent
aba95e30cb
commit
0f7c17654a
@ -1,18 +1,19 @@
|
||||
var express = require('express');
|
||||
var favicon = require('serve-favicon');
|
||||
var bodyParser = require('body-parser');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var validator = require('express-validator');
|
||||
var log4js = require('log4js');
|
||||
var logger = require('./lib/logger');
|
||||
var routes = require('./lib/routes');
|
||||
var path = require('path');
|
||||
'use strict';
|
||||
const express = require('express');
|
||||
const favicon = require('serve-favicon');
|
||||
const bodyParser = require('body-parser');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const validator = require('express-validator');
|
||||
const log4js = require('log4js');
|
||||
const logger = require('./lib/logger');
|
||||
const routes = require('./lib/routes');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function(config) {
|
||||
var app = express();
|
||||
var router = express.Router();
|
||||
var baseUriPath = config.baseUriPath || '';
|
||||
var publicFolder = config.publicFolder;
|
||||
const app = express();
|
||||
const router = express.Router();
|
||||
const baseUriPath = config.baseUriPath || '';
|
||||
const publicFolder = config.publicFolder;
|
||||
|
||||
app.set('trust proxy');
|
||||
app.set('port', config.port);
|
||||
|
@ -1,4 +1,5 @@
|
||||
var knex = require('knex');
|
||||
'use strict';
|
||||
const knex = require('knex');
|
||||
|
||||
module.exports = function(databaseConnection) {
|
||||
return knex({
|
||||
|
@ -1,4 +1,5 @@
|
||||
var EVENT_COLUMNS = ['id', 'type', 'created_by', 'created_at', 'data'];
|
||||
'use strict';
|
||||
const EVENT_COLUMNS = ['id', 'type', 'created_by', 'created_at', 'data'];
|
||||
|
||||
module.exports = function(db) {
|
||||
function storeEvent(event) {
|
||||
@ -38,8 +39,8 @@ module.exports = function(db) {
|
||||
|
||||
return {
|
||||
store: storeEvent,
|
||||
getEvents: getEvents,
|
||||
getEventsFilterByName: getEventsFilterByName
|
||||
getEvents,
|
||||
getEventsFilterByName
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,24 +1,17 @@
|
||||
var eventType = require('../eventType');
|
||||
var logger = require('../logger');
|
||||
var NotFoundError = require('../error/NotFoundError');
|
||||
var FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategy_name', 'parameters'];
|
||||
'use strict';
|
||||
const eventType = require('../eventType');
|
||||
const logger = require('../logger');
|
||||
const NotFoundError = require('../error/NotFoundError');
|
||||
const FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategy_name', 'parameters'];
|
||||
|
||||
module.exports = function(db, eventStore) {
|
||||
eventStore.on(eventType.featureCreated, function (event) {
|
||||
return createFeature(event.data);
|
||||
});
|
||||
eventStore.on(eventType.featureCreated, event => createFeature(event.data));
|
||||
|
||||
eventStore.on(eventType.featureUpdated, function (event) {
|
||||
return updateFeature(event.data);
|
||||
});
|
||||
eventStore.on(eventType.featureUpdated, event => updateFeature(event.data));
|
||||
|
||||
eventStore.on(eventType.featureArchived, function (event) {
|
||||
return archiveFeature(event.data);
|
||||
});
|
||||
eventStore.on(eventType.featureArchived, event => archiveFeature(event.data));
|
||||
|
||||
eventStore.on(eventType.featureRevived, function (event) {
|
||||
return reviveFeature(event.data);
|
||||
});
|
||||
eventStore.on(eventType.featureRevived, event => reviveFeature(event.data));
|
||||
|
||||
function getFeatures() {
|
||||
return db
|
||||
@ -33,7 +26,7 @@ module.exports = function(db, eventStore) {
|
||||
return db
|
||||
.first(FEATURE_COLUMNS)
|
||||
.from('features')
|
||||
.where({ name: name })
|
||||
.where({ name })
|
||||
.then(rowToFeature);
|
||||
}
|
||||
|
||||
@ -75,7 +68,7 @@ module.exports = function(db, eventStore) {
|
||||
function createFeature(data) {
|
||||
return db('features')
|
||||
.insert(eventDataToRow(data))
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not insert feature, error was: ', err);
|
||||
});
|
||||
}
|
||||
@ -84,7 +77,7 @@ module.exports = function(db, eventStore) {
|
||||
return db('features')
|
||||
.where({ name: data.name })
|
||||
.update(eventDataToRow(data))
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not update feature, error was: ', err);
|
||||
});
|
||||
}
|
||||
@ -93,7 +86,7 @@ module.exports = function(db, eventStore) {
|
||||
return db('features')
|
||||
.where({ name: data.name })
|
||||
.update({ archived: 1 })
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not archive feature, error was: ', err);
|
||||
});
|
||||
}
|
||||
@ -102,16 +95,16 @@ module.exports = function(db, eventStore) {
|
||||
return db('features')
|
||||
.where({ name: data.name })
|
||||
.update({ archived: 0, enabled: 0 })
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not archive feature, error was: ', err);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
getFeatures: getFeatures,
|
||||
getFeature: getFeature,
|
||||
getArchivedFeatures: getArchivedFeatures,
|
||||
getFeatures,
|
||||
getFeature,
|
||||
getArchivedFeatures,
|
||||
_createFeature: createFeature, // visible for testing
|
||||
_updateFeature: updateFeature // visible for testing
|
||||
};
|
||||
|
@ -1,18 +1,17 @@
|
||||
var eventType = require('../eventType');
|
||||
var logger = require('../logger');
|
||||
var NotFoundError = require('../error/NotFoundError');
|
||||
var STRATEGY_COLUMNS = ['name', 'description', 'parameters_template'];
|
||||
'use strict';
|
||||
const eventType = require('../eventType');
|
||||
const logger = require('../logger');
|
||||
const NotFoundError = require('../error/NotFoundError');
|
||||
const STRATEGY_COLUMNS = ['name', 'description', 'parameters_template'];
|
||||
|
||||
module.exports = function(db, eventStore) {
|
||||
eventStore.on(eventType.strategyCreated, function (event) {
|
||||
return createStrategy(event.data);
|
||||
});
|
||||
eventStore.on(eventType.strategyCreated, event => createStrategy(event.data));
|
||||
|
||||
eventStore.on(eventType.strategyDeleted, function (event) {
|
||||
eventStore.on(eventType.strategyDeleted, event => {
|
||||
db('strategies')
|
||||
.where('name', event.data.name)
|
||||
.del()
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not delete strategy, error was: ', err);
|
||||
});
|
||||
});
|
||||
@ -29,7 +28,7 @@ module.exports = function(db, eventStore) {
|
||||
return db
|
||||
.first(STRATEGY_COLUMNS)
|
||||
.from('strategies')
|
||||
.where({ name: name })
|
||||
.where({ name })
|
||||
.then(rowToStrategy);
|
||||
}
|
||||
|
||||
@ -56,14 +55,14 @@ module.exports = function(db, eventStore) {
|
||||
function createStrategy(data) {
|
||||
db('strategies')
|
||||
.insert(eventDataToRow(data))
|
||||
.catch(function (err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not insert strategy, error was: ', err);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getStrategies: getStrategies,
|
||||
getStrategy: getStrategy,
|
||||
getStrategies,
|
||||
getStrategy,
|
||||
_createStrategy: createStrategy // visible for testing
|
||||
};
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
var util = require('util');
|
||||
'use strict';
|
||||
const util = require('util');
|
||||
|
||||
function NameExistsError(message) {
|
||||
Error.call(this);
|
||||
|
@ -1,4 +1,5 @@
|
||||
var util = require('util');
|
||||
'use strict';
|
||||
const util = require('util');
|
||||
|
||||
function NotFoundError(message) {
|
||||
Error.call(this);
|
||||
|
@ -1,4 +1,5 @@
|
||||
var util = require('util');
|
||||
'use strict';
|
||||
const util = require('util');
|
||||
|
||||
function ValidationError(message) {
|
||||
Error.call(this);
|
||||
|
@ -1,8 +1,9 @@
|
||||
var Promise = require("bluebird");
|
||||
var ValidationError = require('./ValidationError');
|
||||
'use strict';
|
||||
const Promise = require("bluebird");
|
||||
const ValidationError = require('./ValidationError');
|
||||
|
||||
function validateRequest(req) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (req.validationErrors()) {
|
||||
reject(new ValidationError("Invalid syntax"));
|
||||
} else {
|
||||
|
@ -1,12 +1,13 @@
|
||||
var eventType = require('./eventType');
|
||||
var diff = require('deep-diff').diff;
|
||||
'use strict';
|
||||
const eventType = require('./eventType');
|
||||
const diff = require('deep-diff').diff;
|
||||
|
||||
var strategyTypes = [
|
||||
const strategyTypes = [
|
||||
eventType.strategyCreated,
|
||||
eventType.strategyDeleted
|
||||
];
|
||||
|
||||
var featureTypes = [
|
||||
const featureTypes = [
|
||||
eventType.featureCreated,
|
||||
eventType.featureUpdated,
|
||||
eventType.featureArchived,
|
||||
@ -19,15 +20,15 @@ function baseTypeFor(event) {
|
||||
} else if (strategyTypes.indexOf(event.type) !== -1) {
|
||||
return 'strategies';
|
||||
} else {
|
||||
throw new Error('unknown event type: ' + JSON.stringify(event));
|
||||
throw new Error(`unknown event type: ${JSON.stringify(event)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function groupByBaseTypeAndName(events) {
|
||||
var groups = {};
|
||||
const groups = {};
|
||||
|
||||
events.forEach(function (event) {
|
||||
var baseType = baseTypeFor(event);
|
||||
events.forEach(event => {
|
||||
const baseType = baseTypeFor(event);
|
||||
|
||||
groups[baseType] = groups[baseType] || {};
|
||||
groups[baseType][event.data.name] = groups[baseType][event.data.name] || [];
|
||||
@ -39,14 +40,17 @@ function groupByBaseTypeAndName(events) {
|
||||
}
|
||||
|
||||
function eachConsecutiveEvent(events, callback) {
|
||||
var groups = groupByBaseTypeAndName(events);
|
||||
const groups = groupByBaseTypeAndName(events);
|
||||
|
||||
Object.keys(groups).forEach(function (baseType) {
|
||||
var group = groups[baseType];
|
||||
Object.keys(groups).forEach(baseType => {
|
||||
const group = groups[baseType];
|
||||
|
||||
Object.keys(group).forEach(function (name) {
|
||||
var events = group[name];
|
||||
var left, right, i, l;
|
||||
Object.keys(group).forEach(name => {
|
||||
const events = group[name];
|
||||
let left;
|
||||
let right;
|
||||
let i;
|
||||
let l;
|
||||
for (i = 0, l = events.length; i < l; i++) {
|
||||
left = events[i];
|
||||
right = events[i + 1];
|
||||
@ -58,7 +62,7 @@ function eachConsecutiveEvent(events, callback) {
|
||||
}
|
||||
|
||||
function addDiffs(events) {
|
||||
eachConsecutiveEvent(events, function (left, right) {
|
||||
eachConsecutiveEvent(events, (left, right) => {
|
||||
if (right) {
|
||||
left.diffs = diff(right.data, left.data);
|
||||
left.diffs = left.diffs || [];
|
||||
@ -70,5 +74,5 @@ function addDiffs(events) {
|
||||
|
||||
|
||||
module.exports = {
|
||||
addDiffs: addDiffs
|
||||
addDiffs
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
var util = require('util');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
'use strict';
|
||||
const util = require('util');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
function EventStore(eventDb) {
|
||||
this.eventDb = eventDb;
|
||||
@ -8,8 +9,8 @@ function EventStore(eventDb) {
|
||||
util.inherits(EventStore, EventEmitter);
|
||||
|
||||
EventStore.prototype.create = function (event) {
|
||||
var that = this;
|
||||
return this.eventDb.store(event).then(function() {
|
||||
const that = this;
|
||||
return this.eventDb.store(event).then(() => {
|
||||
that.emit(event.type, event);
|
||||
});
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
featureCreated: 'feature-created',
|
||||
featureUpdated: 'feature-updated',
|
||||
|
@ -1,3 +1,4 @@
|
||||
'use strict';
|
||||
function extractUsername(req) {
|
||||
return req.cookies.username || "unknown";
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
var log4js = require('log4js');
|
||||
'use strict';
|
||||
const log4js = require('log4js');
|
||||
|
||||
log4js.clearAppenders();
|
||||
log4js.addAppender(log4js.appenders.console());
|
||||
|
||||
var logger = log4js.getLogger('unleash');
|
||||
const logger = log4js.getLogger('unleash');
|
||||
|
||||
// TODO: make level configurable
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
|
@ -1,17 +1,18 @@
|
||||
var eventDiffer = require('../eventDiffer');
|
||||
'use strict';
|
||||
const eventDiffer = require('../eventDiffer');
|
||||
|
||||
module.exports = function (app, config) {
|
||||
var eventDb = config.eventDb;
|
||||
const eventDb = config.eventDb;
|
||||
|
||||
app.get('/events', function (req, res) {
|
||||
eventDb.getEvents().then(function (events) {
|
||||
app.get('/events', (req, res) => {
|
||||
eventDb.getEvents().then(events => {
|
||||
eventDiffer.addDiffs(events);
|
||||
res.json({ events: events });
|
||||
res.json({ events });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/events/:name', function (req, res) {
|
||||
eventDb.getEventsFilterByName(req.params.name).then(function (events) {
|
||||
app.get('/events/:name', (req, res) => {
|
||||
eventDb.getEventsFilterByName(req.params.name).then(events => {
|
||||
if (events) {
|
||||
eventDiffer.addDiffs(events);
|
||||
res.json(events);
|
||||
|
@ -1,34 +1,33 @@
|
||||
var logger = require('../logger');
|
||||
var eventType = require('../eventType');
|
||||
var ValidationError = require('../error/ValidationError');
|
||||
var validateRequest = require('../error/validateRequest');
|
||||
'use strict';
|
||||
const logger = require('../logger');
|
||||
const eventType = require('../eventType');
|
||||
const ValidationError = require('../error/ValidationError');
|
||||
const validateRequest = require('../error/validateRequest');
|
||||
|
||||
module.exports = function (app, config) {
|
||||
var featureDb = config.featureDb;
|
||||
var eventStore = config.eventStore;
|
||||
const featureDb = config.featureDb;
|
||||
const eventStore = config.eventStore;
|
||||
|
||||
app.get('/archive/features', function (req, res) {
|
||||
featureDb.getArchivedFeatures().then(function (archivedFeatures) {
|
||||
res.json({ 'features': archivedFeatures });
|
||||
app.get('/archive/features', (req, res) => {
|
||||
featureDb.getArchivedFeatures().then(archivedFeatures => {
|
||||
res.json({ features: archivedFeatures });
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/archive/revive', function (req, res) {
|
||||
app.post('/archive/revive', (req, res) => {
|
||||
req.checkBody('name', 'Name is required').notEmpty();
|
||||
|
||||
validateRequest(req)
|
||||
.then(function() {
|
||||
return eventStore.create({
|
||||
type: eventType.featureRevived,
|
||||
createdBy: req.connection.remoteAddress,
|
||||
data: req.body
|
||||
});
|
||||
}).then(function() {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.featureRevived,
|
||||
createdBy: req.connection.remoteAddress,
|
||||
data: req.body
|
||||
})).then(() => {
|
||||
res.status(200).end();
|
||||
}).catch(ValidationError, function() {
|
||||
}).catch(ValidationError, () => {
|
||||
res.status(400).json(req.validationErrors());
|
||||
})
|
||||
.catch(function(err) {
|
||||
.catch(err => {
|
||||
logger.error("Could not revive feature toggle", err);
|
||||
res.status(500).end();
|
||||
});
|
||||
|
@ -1,121 +1,116 @@
|
||||
var Promise = require("bluebird");
|
||||
var logger = require('../logger');
|
||||
var eventType = require('../eventType');
|
||||
var NameExistsError = require('../error/NameExistsError');
|
||||
var NotFoundError = require('../error/NotFoundError');
|
||||
var ValidationError = require('../error/ValidationError');
|
||||
var validateRequest = require('../error/validateRequest');
|
||||
var extractUser = require('../extractUser');
|
||||
'use strict';
|
||||
const Promise = require("bluebird");
|
||||
const logger = require('../logger');
|
||||
const eventType = require('../eventType');
|
||||
const NameExistsError = require('../error/NameExistsError');
|
||||
const NotFoundError = require('../error/NotFoundError');
|
||||
const ValidationError = require('../error/ValidationError');
|
||||
const validateRequest = require('../error/validateRequest');
|
||||
const extractUser = require('../extractUser');
|
||||
|
||||
module.exports = function (app, config) {
|
||||
var featureDb = config.featureDb;
|
||||
var eventStore = config.eventStore;
|
||||
const featureDb = config.featureDb;
|
||||
const eventStore = config.eventStore;
|
||||
|
||||
app.get('/features', function (req, res) {
|
||||
featureDb.getFeatures().then(function (features) {
|
||||
res.json({ features: features });
|
||||
app.get('/features', (req, res) => {
|
||||
featureDb.getFeatures().then(features => {
|
||||
res.json({ features });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/features/:featureName', function (req, res) {
|
||||
app.get('/features/:featureName', (req, res) => {
|
||||
featureDb.getFeature(req.params.featureName)
|
||||
.then(function (feature) {
|
||||
.then(feature => {
|
||||
res.json(feature);
|
||||
})
|
||||
.catch(function () {
|
||||
.catch(() => {
|
||||
res.status(404).json({ error: 'Could not find feature' });
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/features', function (req, res) {
|
||||
app.post('/features', (req, res) => {
|
||||
req.checkBody('name', 'Name is required').notEmpty();
|
||||
req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
|
||||
|
||||
validateRequest(req)
|
||||
.then(validateUniqueName)
|
||||
.then(function() {
|
||||
return eventStore.create({
|
||||
type: eventType.featureCreated,
|
||||
createdBy: extractUser(req),
|
||||
data: req.body
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.featureCreated,
|
||||
createdBy: extractUser(req),
|
||||
data: req.body
|
||||
}))
|
||||
.then(() => {
|
||||
res.status(201).end();
|
||||
})
|
||||
.catch(NameExistsError, function() {
|
||||
.catch(NameExistsError, () => {
|
||||
res.status(403).json([{
|
||||
msg: "A feature named '" + req.body.name + "' already exists. It could be archived."
|
||||
msg: `A feature named '${req.body.name}' already exists. It could be archived.`
|
||||
}]).end();
|
||||
})
|
||||
.catch(ValidationError, function() {
|
||||
.catch(ValidationError, () => {
|
||||
res.status(400).json(req.validationErrors());
|
||||
})
|
||||
.catch(function(err) {
|
||||
.catch(err => {
|
||||
logger.error("Could not create feature toggle", err);
|
||||
res.status(500).end();
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/features/:featureName', function (req, res) {
|
||||
var featureName = req.params.featureName;
|
||||
var userName = extractUser(req);
|
||||
var updatedFeature = req.body;
|
||||
app.put('/features/:featureName', (req, res) => {
|
||||
const featureName = req.params.featureName;
|
||||
const userName = extractUser(req);
|
||||
const updatedFeature = req.body;
|
||||
|
||||
updatedFeature.name = featureName;
|
||||
|
||||
featureDb.getFeature(featureName)
|
||||
.then(function () {
|
||||
return eventStore.create({
|
||||
type: eventType.featureUpdated,
|
||||
createdBy: userName,
|
||||
data: updatedFeature
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.featureUpdated,
|
||||
createdBy: userName,
|
||||
data: updatedFeature
|
||||
}))
|
||||
.then(() => {
|
||||
res.status(200).end();
|
||||
})
|
||||
.catch(NotFoundError, function () {
|
||||
.catch(NotFoundError, () => {
|
||||
res.status(404).end();
|
||||
})
|
||||
.catch(function (err) {
|
||||
logger.error("Could not update feature toggle="+featureName, err);
|
||||
.catch(err => {
|
||||
logger.error(`Could not update feature toggle=${featureName}`, err);
|
||||
res.status(500).end();
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/features/:featureName', function (req, res) {
|
||||
var featureName = req.params.featureName;
|
||||
var userName = extractUser(req);
|
||||
app.delete('/features/:featureName', (req, res) => {
|
||||
const featureName = req.params.featureName;
|
||||
const userName = extractUser(req);
|
||||
|
||||
featureDb.getFeature(featureName)
|
||||
.then(function () {
|
||||
return eventStore.create({
|
||||
type: eventType.featureArchived,
|
||||
createdBy: userName,
|
||||
data: {
|
||||
name: featureName
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.featureArchived,
|
||||
createdBy: userName,
|
||||
data: {
|
||||
name: featureName
|
||||
}
|
||||
}))
|
||||
.then(() => {
|
||||
res.status(200).end();
|
||||
})
|
||||
.catch(NotFoundError, function () {
|
||||
.catch(NotFoundError, () => {
|
||||
res.status(404).end();
|
||||
})
|
||||
.catch(function (err) {
|
||||
logger.error("Could not archive feature="+featureName, err);
|
||||
.catch(err => {
|
||||
logger.error(`Could not archive feature=${featureName}`, err);
|
||||
res.status(500).end();
|
||||
});
|
||||
});
|
||||
|
||||
function validateUniqueName(req) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return new Promise((resolve, reject) => {
|
||||
featureDb.getFeature(req.body.name)
|
||||
.then(function() {
|
||||
.then(() => {
|
||||
reject(new NameExistsError("Feature name already exist"));
|
||||
}, function() {
|
||||
}, () => {
|
||||
resolve(req);
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
var logger = require('../logger');
|
||||
'use strict';
|
||||
const logger = require('../logger');
|
||||
|
||||
module.exports = function (app, config) {
|
||||
app.get('/health', function (req, res) {
|
||||
app.get('/health', (req, res) => {
|
||||
config.db.select(1)
|
||||
.from('features')
|
||||
.then(function() {
|
||||
.then(() => {
|
||||
res.json({ health: 'GOOD' });
|
||||
})
|
||||
.catch(function(err) {
|
||||
.catch(err => {
|
||||
logger.error('Could not select from features, error was: ', err);
|
||||
res.status(500).json({ health: 'BAD' });
|
||||
});
|
||||
|
@ -2,6 +2,8 @@
|
||||
* TODO: we should also inject config and
|
||||
* services to the routes to ease testing.
|
||||
**/
|
||||
'use strict';
|
||||
|
||||
exports.create = function (app, config) {
|
||||
require('./event')(app, config);
|
||||
require('./feature')(app, config);
|
||||
|
@ -1,93 +1,90 @@
|
||||
var Promise = require("bluebird");
|
||||
var eventType = require('../eventType');
|
||||
var logger = require('../logger');
|
||||
var NameExistsError = require('../error/NameExistsError');
|
||||
var ValidationError = require('../error/ValidationError');
|
||||
var NotFoundError = require('../error/NotFoundError');
|
||||
var validateRequest = require('../error/validateRequest');
|
||||
var extractUser = require('../extractUser');
|
||||
'use strict';
|
||||
const Promise = require("bluebird");
|
||||
const eventType = require('../eventType');
|
||||
const logger = require('../logger');
|
||||
const NameExistsError = require('../error/NameExistsError');
|
||||
const ValidationError = require('../error/ValidationError');
|
||||
const NotFoundError = require('../error/NotFoundError');
|
||||
const validateRequest = require('../error/validateRequest');
|
||||
const extractUser = require('../extractUser');
|
||||
|
||||
module.exports = function (app, config) {
|
||||
var strategyDb = config.strategyDb;
|
||||
var eventStore = config.eventStore;
|
||||
const strategyDb = config.strategyDb;
|
||||
const eventStore = config.eventStore;
|
||||
|
||||
app.get('/strategies', function (req, res) {
|
||||
strategyDb.getStrategies().then(function (strategies) {
|
||||
res.json({ strategies: strategies });
|
||||
app.get('/strategies', (req, res) => {
|
||||
strategyDb.getStrategies().then(strategies => {
|
||||
res.json({ strategies });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/strategies/:name', function (req, res) {
|
||||
app.get('/strategies/:name', (req, res) => {
|
||||
strategyDb.getStrategy(req.params.name)
|
||||
.then(function (strategy) {
|
||||
.then(strategy => {
|
||||
res.json(strategy);
|
||||
})
|
||||
.catch(function () {
|
||||
.catch(() => {
|
||||
res.status(404).json({ error: 'Could not find strategy' });
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/strategies/:name', function (req, res) {
|
||||
var strategyName = req.params.name;
|
||||
app.delete('/strategies/:name', (req, res) => {
|
||||
const strategyName = req.params.name;
|
||||
|
||||
strategyDb.getStrategy(strategyName)
|
||||
.then(function() {
|
||||
return eventStore.create({
|
||||
type: eventType.strategyDeleted,
|
||||
createdBy: extractUser(req),
|
||||
data: {
|
||||
name: strategyName
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.strategyDeleted,
|
||||
createdBy: extractUser(req),
|
||||
data: {
|
||||
name: strategyName
|
||||
}
|
||||
}))
|
||||
.then(() => {
|
||||
res.status(200).end();
|
||||
})
|
||||
.catch(NotFoundError, function() {
|
||||
.catch(NotFoundError, () => {
|
||||
res.status(404).end();
|
||||
})
|
||||
.catch(function(err) {
|
||||
logger.error('Could not delete strategy='+strategyName, err);
|
||||
.catch(err => {
|
||||
logger.error(`Could not delete strategy=${strategyName}`, err);
|
||||
res.status(500).end();
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/strategies', function (req, res) {
|
||||
app.post('/strategies', (req, res) => {
|
||||
req.checkBody('name', 'Name is required').notEmpty();
|
||||
req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
|
||||
|
||||
var newStrategy = req.body;
|
||||
const newStrategy = req.body;
|
||||
|
||||
validateRequest(req)
|
||||
.then(validateStrategyName)
|
||||
.then(function() {
|
||||
return eventStore.create({
|
||||
type: eventType.strategyCreated,
|
||||
createdBy: extractUser(req),
|
||||
data: newStrategy
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
.then(() => eventStore.create({
|
||||
type: eventType.strategyCreated,
|
||||
createdBy: extractUser(req),
|
||||
data: newStrategy
|
||||
}))
|
||||
.then(() => {
|
||||
res.status(201).end();
|
||||
})
|
||||
.catch(NameExistsError, function() {
|
||||
res.status(403).json([{ msg: "A strategy named '" + req.body.name + "' already exists." }]).end();
|
||||
.catch(NameExistsError, () => {
|
||||
res.status(403).json([{ msg: `A strategy named '${req.body.name}' already exists.` }]).end();
|
||||
})
|
||||
.catch(ValidationError, function() {
|
||||
.catch(ValidationError, () => {
|
||||
res.status(400).json(req.validationErrors());
|
||||
})
|
||||
.catch(function(err) {
|
||||
.catch(err => {
|
||||
logger.error("Could not create strategy", err);
|
||||
res.status(500).end();
|
||||
});
|
||||
});
|
||||
|
||||
function validateStrategyName(req) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return new Promise((resolve, reject) => {
|
||||
strategyDb.getStrategy(req.body.name)
|
||||
.then(function() {
|
||||
.then(() => {
|
||||
reject(new NameExistsError("Feature name already exist"));
|
||||
}, function() {
|
||||
}, () => {
|
||||
resolve(req);
|
||||
});
|
||||
});
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('001-initial-schema');
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('002-add-description-to-features');
|
||||
|
@ -1,2 +1,3 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('003-add-parameters-template-to-strategies');
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('004-insert-default-strategy');
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('004-insert-default-strategy-event');
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('005-archived-flag-to-features');
|
||||
|
@ -1 +1,2 @@
|
||||
'use strict';
|
||||
module.exports = require('../scripts/migration-runner').create('006-rename-eventtype');
|
||||
|
@ -1,14 +1,15 @@
|
||||
var fs = require('fs');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const util = require('util');
|
||||
const path = require('path');
|
||||
|
||||
var runMigration = function(path, db, callback) {
|
||||
const runMigration = function(path, db, callback) {
|
||||
db.runSql(fs.readFileSync(path, { encoding: 'utf8' }), callback);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
create: function (name) {
|
||||
var format = path.resolve(__dirname, '../migrations/sql/%s.%s.sql');
|
||||
create(name) {
|
||||
const format = path.resolve(__dirname, '../migrations/sql/%s.%s.sql');
|
||||
|
||||
return {
|
||||
up: runMigration.bind(null, util.format(format, name, 'up')),
|
||||
|
@ -1,46 +1,47 @@
|
||||
var logger = require('./lib/logger');
|
||||
var defaultDatabaseUri = process.env.DATABASE_URL;
|
||||
'use strict';
|
||||
const logger = require('./lib/logger');
|
||||
const defaultDatabaseUri = process.env.DATABASE_URL;
|
||||
|
||||
function start(options) {
|
||||
options = options || {};
|
||||
|
||||
var db = require('./lib/db/dbPool')(options.databaseUri || defaultDatabaseUri);
|
||||
const db = require('./lib/db/dbPool')(options.databaseUri || defaultDatabaseUri);
|
||||
// Database dependecies (statefull)
|
||||
var eventDb = require('./lib/db/event')(db);
|
||||
var EventStore = require('./lib/eventStore');
|
||||
var eventStore = new EventStore(eventDb);
|
||||
var featureDb = require('./lib/db/feature')(db, eventStore);
|
||||
var strategyDb = require('./lib/db/strategy')(db, eventStore);
|
||||
const eventDb = require('./lib/db/event')(db);
|
||||
const EventStore = require('./lib/eventStore');
|
||||
const eventStore = new EventStore(eventDb);
|
||||
const featureDb = require('./lib/db/feature')(db, eventStore);
|
||||
const strategyDb = require('./lib/db/strategy')(db, eventStore);
|
||||
|
||||
var config = {
|
||||
const config = {
|
||||
baseUriPath: process.env.BASE_URI_PATH || '',
|
||||
port: process.env.HTTP_PORT || process.env.PORT || 4242,
|
||||
db: db,
|
||||
eventDb: eventDb,
|
||||
eventStore: eventStore,
|
||||
featureDb: featureDb,
|
||||
strategyDb: strategyDb,
|
||||
db,
|
||||
eventDb,
|
||||
eventStore,
|
||||
featureDb,
|
||||
strategyDb,
|
||||
publicFolder: options.publicFolder
|
||||
};
|
||||
|
||||
var app = require('./app')(config);
|
||||
const app = require('./app')(config);
|
||||
|
||||
var server = app.listen(app.get('port'), function() {
|
||||
logger.info('unleash started on ' + app.get('port'));
|
||||
const server = app.listen(app.get('port'), () => {
|
||||
logger.info(`unleash started on ${app.get('port')}`);
|
||||
});
|
||||
|
||||
return {
|
||||
app: app,
|
||||
server: server,
|
||||
config: config
|
||||
app,
|
||||
server,
|
||||
config
|
||||
};
|
||||
}
|
||||
|
||||
process.on('uncaughtException', function(err) {
|
||||
process.on('uncaughtException', err => {
|
||||
logger.error('Uncaught Exception:', err.message);
|
||||
logger.error(err.stack);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
start: start
|
||||
start
|
||||
};
|
||||
|
@ -7,5 +7,5 @@ function getDatabaseUri() {
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getDatabaseUri: getDatabaseUri
|
||||
getDatabaseUri
|
||||
};
|
||||
|
@ -1,15 +1,15 @@
|
||||
'use strict';
|
||||
var request = require('./specHelper').request;
|
||||
const request = require('./specHelper').request;
|
||||
|
||||
describe('The event api', function () {
|
||||
it('returns events', function (done) {
|
||||
describe('The event api', () => {
|
||||
it('returns events', done => {
|
||||
request
|
||||
.get('/events')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('returns events given a name', function (done) {
|
||||
it('returns events given a name', done => {
|
||||
request
|
||||
.get('/events/myname')
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -1,32 +1,32 @@
|
||||
'use strict';
|
||||
var eventDiffer = require('../lib/eventDiffer');
|
||||
var eventType = require('../lib/eventType');
|
||||
var assert = require('assert');
|
||||
const eventDiffer = require('../lib/eventDiffer');
|
||||
const eventType = require('../lib/eventType');
|
||||
const assert = require('assert');
|
||||
|
||||
describe('eventDiffer', function () {
|
||||
it('fails if events include an unknown event type', function () {
|
||||
var events = [
|
||||
describe('eventDiffer', () => {
|
||||
it('fails if events include an unknown event type', () => {
|
||||
const events = [
|
||||
{ type: eventType.featureCreated, data: {} },
|
||||
{ type: 'unknown-type', data: {} }
|
||||
];
|
||||
|
||||
assert.throws(function () {
|
||||
assert.throws(() => {
|
||||
eventDiffer.addDiffs(events);
|
||||
});
|
||||
});
|
||||
|
||||
it('diffs a feature-update event', function () {
|
||||
var name = 'foo';
|
||||
var desc = 'bar';
|
||||
it('diffs a feature-update event', () => {
|
||||
const name = 'foo';
|
||||
const desc = 'bar';
|
||||
|
||||
var events = [
|
||||
const events = [
|
||||
{
|
||||
type: eventType.featureUpdated,
|
||||
data: { name: name, description: desc, strategy: 'default', enabled: true, parameters: { value: 2 } }
|
||||
data: { name, description: desc, strategy: 'default', enabled: true, parameters: { value: 2 } }
|
||||
},
|
||||
{
|
||||
type: eventType.featureCreated,
|
||||
data: { name: name, description: desc, strategy: 'default', enabled: false, parameters: { value: 1 } }
|
||||
data: { name, description: desc, strategy: 'default', enabled: false, parameters: { value: 1 } }
|
||||
}
|
||||
];
|
||||
|
||||
@ -40,8 +40,8 @@ describe('eventDiffer', function () {
|
||||
assert.strictEqual(events[1].diffs, null);
|
||||
});
|
||||
|
||||
it('diffs only against features with the same name', function () {
|
||||
var events = [
|
||||
it('diffs only against features with the same name', () => {
|
||||
const events = [
|
||||
{
|
||||
type: eventType.featureUpdated,
|
||||
data: { name: 'bar', description: 'desc', strategy: 'default', enabled: true, parameters: {} }
|
||||
@ -68,8 +68,8 @@ describe('eventDiffer', function () {
|
||||
assert.strictEqual(events[3].diffs, null);
|
||||
});
|
||||
|
||||
it('sets an empty array of diffs if nothing was changed', function () {
|
||||
var events = [
|
||||
it('sets an empty array of diffs if nothing was changed', () => {
|
||||
const events = [
|
||||
{
|
||||
type: eventType.featureUpdated,
|
||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} }
|
||||
@ -84,8 +84,8 @@ describe('eventDiffer', function () {
|
||||
assert.deepEqual(events[0].diffs, []);
|
||||
});
|
||||
|
||||
it('sets diffs to null if there was nothing to diff against', function () {
|
||||
var events = [
|
||||
it('sets diffs to null if there was nothing to diff against', () => {
|
||||
const events = [
|
||||
{
|
||||
type: eventType.featureUpdated,
|
||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} }
|
||||
|
@ -1,38 +1,38 @@
|
||||
'use strict';
|
||||
var logger = require('../lib/logger');
|
||||
var assert = require('assert');
|
||||
var specHelper = require('./specHelper');
|
||||
var request = specHelper.request;
|
||||
var stringify = function (o) {
|
||||
const logger = require('../lib/logger');
|
||||
const assert = require('assert');
|
||||
const specHelper = require('./specHelper');
|
||||
const request = specHelper.request;
|
||||
const stringify = function (o) {
|
||||
return JSON.stringify(o, null, ' ');
|
||||
};
|
||||
|
||||
describe('The features api', function () {
|
||||
beforeEach(function (done) {
|
||||
describe('The features api', () => {
|
||||
beforeEach(done => {
|
||||
specHelper.db.resetAndSetup()
|
||||
.then(done.bind(null, null))
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('returns three feature toggles', function (done) {
|
||||
it('returns three feature toggles', done => {
|
||||
request
|
||||
.get('/features')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
assert(res.body.features.length === 3, "expected 3 features, got " + stringify(res.body));
|
||||
.end((err, res) => {
|
||||
assert(res.body.features.length === 3, `expected 3 features, got ${stringify(res.body)}`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('gets a feature by name', function (done) {
|
||||
it('gets a feature by name', done => {
|
||||
request
|
||||
.get('/features/featureX')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('cant get feature that dose not exist', function (done) {
|
||||
it('cant get feature that dose not exist', done => {
|
||||
logger.setLevel('FATAL');
|
||||
request
|
||||
.get('/features/myfeature')
|
||||
@ -40,7 +40,7 @@ describe('The features api', function () {
|
||||
.expect(404, done);
|
||||
});
|
||||
|
||||
it('creates new feature toggle', function (done) {
|
||||
it('creates new feature toggle', done => {
|
||||
request
|
||||
.post('/features')
|
||||
.send({ name: 'com.test.feature', enabled: false })
|
||||
@ -48,24 +48,24 @@ describe('The features api', function () {
|
||||
.expect(201, done);
|
||||
});
|
||||
|
||||
it('creates new feature toggle with createdBy', function (done) {
|
||||
it('creates new feature toggle with createdBy', done => {
|
||||
logger.setLevel('FATAL');
|
||||
request
|
||||
.post('/features')
|
||||
.send({ name: 'com.test.Username', enabled: false })
|
||||
.set('Cookie', ['username=ivaosthu'])
|
||||
.set('Content-Type', 'application/json')
|
||||
.end(function() {
|
||||
.end(() => {
|
||||
request
|
||||
.get('/events')
|
||||
.end(function (err, res) {
|
||||
.end((err, res) => {
|
||||
assert.equal(res.body.events[0].createdBy, 'ivaosthu');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('require new feature toggle to have a name', function (done) {
|
||||
it('require new feature toggle to have a name', done => {
|
||||
logger.setLevel('FATAL');
|
||||
request
|
||||
.post('/features')
|
||||
@ -74,7 +74,7 @@ describe('The features api', function () {
|
||||
.expect(400, done);
|
||||
});
|
||||
|
||||
it('can not change status of feature toggle that does not exist', function (done) {
|
||||
it('can not change status of feature toggle that does not exist', done => {
|
||||
logger.setLevel('FATAL');
|
||||
request
|
||||
.put('/features/should-not-exist')
|
||||
@ -83,7 +83,7 @@ describe('The features api', function () {
|
||||
.expect(404, done);
|
||||
});
|
||||
|
||||
it('can change status of feature toggle that does exist', function (done) {
|
||||
it('can change status of feature toggle that does exist', done => {
|
||||
logger.setLevel('FATAL');
|
||||
request
|
||||
.put('/features/featureY')
|
||||
@ -92,19 +92,19 @@ describe('The features api', function () {
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('archives a feature by name', function (done) {
|
||||
it('archives a feature by name', done => {
|
||||
request
|
||||
.delete('/features/featureX')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('can not archive unknown feature', function (done) {
|
||||
it('can not archive unknown feature', done => {
|
||||
request
|
||||
.delete('/features/featureUnknown')
|
||||
.expect(404, done);
|
||||
});
|
||||
|
||||
it('refuses to create a feature with an existing name', function (done) {
|
||||
it('refuses to create a feature with an existing name', done => {
|
||||
request
|
||||
.post('/features')
|
||||
.send({ name: 'featureX' })
|
||||
|
@ -1,30 +1,30 @@
|
||||
'use strict';
|
||||
var assert = require('assert');
|
||||
var specHelper = require('./specHelper');
|
||||
var request = specHelper.request;
|
||||
var stringify = function (o) {
|
||||
const assert = require('assert');
|
||||
const specHelper = require('./specHelper');
|
||||
const request = specHelper.request;
|
||||
const stringify = function (o) {
|
||||
return JSON.stringify(o, null, ' ');
|
||||
};
|
||||
|
||||
describe('The archive features api', function () {
|
||||
beforeEach(function (done) {
|
||||
describe('The archive features api', () => {
|
||||
beforeEach(done => {
|
||||
specHelper.db.resetAndSetup()
|
||||
.then(done.bind(null, null))
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('returns three archived toggles', function (done) {
|
||||
it('returns three archived toggles', done => {
|
||||
request
|
||||
.get('/archive/features')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
assert(res.body.features.length === 3, "expected 3 features, got " + stringify(res.body));
|
||||
.end((err, res) => {
|
||||
assert(res.body.features.length === 3, `expected 3 features, got ${stringify(res.body)}`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('revives a feature by name', function (done) {
|
||||
it('revives a feature by name', done => {
|
||||
request
|
||||
.post('/archive/revive')
|
||||
.send({ name: 'featureArchivedX' })
|
||||
@ -32,7 +32,7 @@ describe('The archive features api', function () {
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('must set name when reviving toggle', function (done) {
|
||||
it('must set name when reviving toggle', done => {
|
||||
request
|
||||
.post('/archive/revive')
|
||||
.expect(400, done);
|
||||
|
@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
var specHelper = require('./specHelper');
|
||||
var request = specHelper.request;
|
||||
const specHelper = require('./specHelper');
|
||||
const request = specHelper.request;
|
||||
|
||||
describe('The routes', function () {
|
||||
describe('healthcheck', function () {
|
||||
it('returns health good', function (done) {
|
||||
describe('The routes', () => {
|
||||
describe('healthcheck', () => {
|
||||
it('returns health good', done => {
|
||||
request.get('/health')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
|
@ -1,23 +1,23 @@
|
||||
'use strict';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
var Promise = require('bluebird');
|
||||
var request = require('supertest');
|
||||
var databaseUri = require('./databaseConfig').getDatabaseUri();
|
||||
var knex = require('../lib/db/dbPool')(databaseUri);
|
||||
var eventDb = require('../lib/db/event')(knex);
|
||||
var EventStore = require('../lib/eventStore');
|
||||
var eventStore = new EventStore(eventDb);
|
||||
var featureDb = require('../lib/db/feature')(knex, eventStore);
|
||||
var strategyDb = require('../lib/db/strategy')(knex, eventStore);
|
||||
const Promise = require('bluebird');
|
||||
let request = require('supertest');
|
||||
const databaseUri = require('./databaseConfig').getDatabaseUri();
|
||||
const knex = require('../lib/db/dbPool')(databaseUri);
|
||||
const eventDb = require('../lib/db/event')(knex);
|
||||
const EventStore = require('../lib/eventStore');
|
||||
const eventStore = new EventStore(eventDb);
|
||||
const featureDb = require('../lib/db/feature')(knex, eventStore);
|
||||
const strategyDb = require('../lib/db/strategy')(knex, eventStore);
|
||||
|
||||
var app = require('../app')({
|
||||
const app = require('../app')({
|
||||
baseUriPath: '',
|
||||
db: knex,
|
||||
eventDb: eventDb,
|
||||
eventStore: eventStore,
|
||||
featureDb: featureDb,
|
||||
strategyDb: strategyDb
|
||||
eventDb,
|
||||
eventStore,
|
||||
featureDb,
|
||||
strategyDb
|
||||
});
|
||||
|
||||
Promise.promisifyAll(request);
|
||||
@ -37,67 +37,63 @@ function createStrategies() {
|
||||
emails: "String"
|
||||
}
|
||||
}
|
||||
], function (strategy) {
|
||||
return strategyDb._createStrategy(strategy);
|
||||
});
|
||||
], strategy => strategyDb._createStrategy(strategy));
|
||||
}
|
||||
|
||||
function createFeatures() {
|
||||
return Promise.map([
|
||||
{
|
||||
"name": "featureX",
|
||||
"description": "the #1 feature",
|
||||
"enabled": true,
|
||||
"strategy": "default"
|
||||
name: "featureX",
|
||||
description: "the #1 feature",
|
||||
enabled: true,
|
||||
strategy: "default"
|
||||
},
|
||||
{
|
||||
"name": "featureY",
|
||||
"description": "soon to be the #1 feature",
|
||||
"enabled": false,
|
||||
"strategy": "baz",
|
||||
"parameters": {
|
||||
"foo": "bar"
|
||||
name: "featureY",
|
||||
description: "soon to be the #1 feature",
|
||||
enabled: false,
|
||||
strategy: "baz",
|
||||
parameters: {
|
||||
foo: "bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "featureZ",
|
||||
"description": "terrible feature",
|
||||
"enabled": true,
|
||||
"strategy": "baz",
|
||||
"parameters": {
|
||||
"foo": "rab"
|
||||
name: "featureZ",
|
||||
description: "terrible feature",
|
||||
enabled: true,
|
||||
strategy: "baz",
|
||||
parameters: {
|
||||
foo: "rab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "featureArchivedX",
|
||||
"description": "the #1 feature",
|
||||
"enabled": true,
|
||||
"archived": true,
|
||||
"strategy": "default"
|
||||
name: "featureArchivedX",
|
||||
description: "the #1 feature",
|
||||
enabled: true,
|
||||
archived: true,
|
||||
strategy: "default"
|
||||
},
|
||||
{
|
||||
"name": "featureArchivedY",
|
||||
"description": "soon to be the #1 feature",
|
||||
"enabled": false,
|
||||
"archived": true,
|
||||
"strategy": "baz",
|
||||
"parameters": {
|
||||
"foo": "bar"
|
||||
name: "featureArchivedY",
|
||||
description: "soon to be the #1 feature",
|
||||
enabled: false,
|
||||
archived: true,
|
||||
strategy: "baz",
|
||||
parameters: {
|
||||
foo: "bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "featureArchivedZ",
|
||||
"description": "terrible feature",
|
||||
"enabled": true,
|
||||
"archived": true,
|
||||
"strategy": "baz",
|
||||
"parameters": {
|
||||
"foo": "rab"
|
||||
name: "featureArchivedZ",
|
||||
description: "terrible feature",
|
||||
enabled: true,
|
||||
archived: true,
|
||||
strategy: "baz",
|
||||
parameters: {
|
||||
foo: "rab"
|
||||
}
|
||||
}
|
||||
], function (feature) {
|
||||
return featureDb._createFeature(feature);
|
||||
});
|
||||
], feature => featureDb._createFeature(feature));
|
||||
}
|
||||
|
||||
function destroyStrategies() {
|
||||
@ -117,11 +113,11 @@ function setupDatabase() {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
request: request,
|
||||
request,
|
||||
db: {
|
||||
reset: resetDatabase,
|
||||
setup: setupDatabase,
|
||||
resetAndSetup: function () {
|
||||
resetAndSetup() {
|
||||
return resetDatabase().then(setupDatabase);
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
'use strict';
|
||||
var specHelper = require('./specHelper');
|
||||
var request = specHelper.request;
|
||||
const specHelper = require('./specHelper');
|
||||
const request = specHelper.request;
|
||||
|
||||
describe('The strategy api', function () {
|
||||
beforeEach(function (done) {
|
||||
describe('The strategy api', () => {
|
||||
beforeEach(done => {
|
||||
specHelper.db.resetAndSetup()
|
||||
.then(done.bind(null, null))
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('gets all strategies', function (done) {
|
||||
it('gets all strategies', done => {
|
||||
request
|
||||
.get('/strategies')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('gets a strategy by name', function (done) {
|
||||
it('gets a strategy by name', done => {
|
||||
request
|
||||
.get('/strategies/default')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('cant get a strategy by name that dose not exist', function (done) {
|
||||
it('cant get a strategy by name that dose not exist', done => {
|
||||
request
|
||||
.get('/strategies/mystrategy')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(404, done);
|
||||
});
|
||||
|
||||
it('creates a new strategy', function (done) {
|
||||
it('creates a new strategy', done => {
|
||||
request
|
||||
.post('/strategies')
|
||||
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.' })
|
||||
@ -38,7 +38,7 @@ describe('The strategy api', function () {
|
||||
.expect(201, done);
|
||||
});
|
||||
|
||||
it('requires new strategies to have a name', function (done) {
|
||||
it('requires new strategies to have a name', done => {
|
||||
request
|
||||
.post('/strategies')
|
||||
.send({ name: '' })
|
||||
@ -46,7 +46,7 @@ describe('The strategy api', function () {
|
||||
.expect(400, done);
|
||||
});
|
||||
|
||||
it('refuses to create a strategy with an existing name', function (done) {
|
||||
it('refuses to create a strategy with an existing name', done => {
|
||||
request
|
||||
.post('/strategies')
|
||||
.send({ name: 'default' })
|
||||
@ -54,13 +54,13 @@ describe('The strategy api', function () {
|
||||
.expect(403, done);
|
||||
});
|
||||
|
||||
it('deletes a new strategy', function (done) {
|
||||
it('deletes a new strategy', done => {
|
||||
request
|
||||
.delete('/strategies/usersWithEmail')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('can\'t delete a strategy that dose not exist', function(done) {
|
||||
it('can\'t delete a strategy that dose not exist', done => {
|
||||
request
|
||||
.delete('/strategies/unknown')
|
||||
.expect(404, done);
|
||||
|
@ -1,3 +1,3 @@
|
||||
'use strict';
|
||||
var unleash = require('unleash-server');
|
||||
const unleash = require('unleash-server');
|
||||
unleash.start({});
|
||||
|
@ -1,7 +1,9 @@
|
||||
// preprocessor.js
|
||||
var ReactTools = require('react-tools');
|
||||
'use strict';
|
||||
|
||||
const ReactTools = require('react-tools');
|
||||
module.exports = {
|
||||
process: function(src) {
|
||||
process(src) {
|
||||
return ReactTools.transform(src);
|
||||
}
|
||||
};
|
||||
|
@ -1,20 +1,21 @@
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Menu = require('./components/Menu');
|
||||
var ErrorMessages = require('./components/ErrorMessages');
|
||||
var initalizer = require('./stores/initalizer');
|
||||
var FeatureToggleStore = require('./stores/FeatureToggleStore');
|
||||
var StrategyStore = require('./stores/StrategyStore');
|
||||
var ArchiveStore = require('./stores/ArchivedToggleStore');
|
||||
var Link = Router.Link;
|
||||
var RouteHandler = Router.RouteHandler;
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Router = require('react-router');
|
||||
const Menu = require('./components/Menu');
|
||||
const ErrorMessages = require('./components/ErrorMessages');
|
||||
const initalizer = require('./stores/initalizer');
|
||||
const FeatureToggleStore = require('./stores/FeatureToggleStore');
|
||||
const StrategyStore = require('./stores/StrategyStore');
|
||||
const ArchiveStore = require('./stores/ArchivedToggleStore');
|
||||
const Link = Router.Link;
|
||||
const RouteHandler = Router.RouteHandler;
|
||||
|
||||
var UnleashApp = React.createClass({
|
||||
const UnleashApp = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.func
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState() {
|
||||
return {
|
||||
features: FeatureToggleStore.getFeatureToggles(),
|
||||
strategies: StrategyStore.getStrategies(),
|
||||
@ -22,40 +23,40 @@ var UnleashApp = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
onFeatureToggleChange: function() {
|
||||
onFeatureToggleChange() {
|
||||
this.setState({
|
||||
features: FeatureToggleStore.getFeatureToggles()
|
||||
});
|
||||
},
|
||||
|
||||
onStrategiesChange: function() {
|
||||
onStrategiesChange() {
|
||||
this.setState({
|
||||
strategies: StrategyStore.getStrategies()
|
||||
});
|
||||
},
|
||||
|
||||
onArchiveChange: function() {
|
||||
onArchiveChange() {
|
||||
this.setState({
|
||||
archivedFeatures: ArchiveStore.getArchivedToggles()
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
componentDidMount() {
|
||||
this.unsubscribeFS = FeatureToggleStore.listen(this.onFeatureToggleChange);
|
||||
this.unsubscribeSS = StrategyStore.listen(this.onStrategiesChange);
|
||||
this.unsubscribeAS = ArchiveStore.listen(this.onArchiveChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
componentWillUnmount() {
|
||||
this.unsubscribeFS();
|
||||
this.unsubscribeSS();
|
||||
this.unsubscribeAS();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
componentWillMount() {
|
||||
initalizer(30);
|
||||
},
|
||||
|
||||
renderLink: function(id, label) {
|
||||
renderLink(id, label) {
|
||||
return (
|
||||
<Link to={id} className="nav-element centerify" activeClassName="nav-active">
|
||||
<span className="topbar-nav-svg-caption caption showbydefault no-break">{label}</span>
|
||||
@ -63,7 +64,7 @@ var UnleashApp = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Menu>
|
||||
|
@ -1,14 +1,16 @@
|
||||
/** @jsx React.DOM */
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.dontMock("../../components/Menu");
|
||||
|
||||
var Menu = require("../../components/Menu");
|
||||
var React = require("react/addons");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
const Menu = require("../../components/Menu");
|
||||
const React = require("react/addons");
|
||||
const TestUtils = React.addons.TestUtils;
|
||||
|
||||
describe('Menu test', function () {
|
||||
it('should include unleash in menu', function () {
|
||||
var Compononent = TestUtils .renderIntoDocument(<Menu />);
|
||||
describe('Menu test', () => {
|
||||
it('should include unleash in menu', () => {
|
||||
const Compononent = TestUtils .renderIntoDocument(<Menu />);
|
||||
expect(Compononent.getDOMNode().textContent).toMatch('unleash');
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,17 @@
|
||||
'use strict';
|
||||
jest.dontMock("../../../components/feature/ArchiveFeatureComponent");
|
||||
jest.mock("../../../stores/FeatureToggleActions");
|
||||
jest.autoMockOff();
|
||||
|
||||
var React = require("react/addons");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var FeatureArchive = require("../../../components/feature/ArchiveFeatureComponent");
|
||||
var FeatureActions = require("../../../stores/FeatureToggleActions");
|
||||
const React = require("react/addons");
|
||||
const TestUtils = React.addons.TestUtils;
|
||||
const FeatureArchive = require("../../../components/feature/ArchiveFeatureComponent");
|
||||
const FeatureActions = require("../../../stores/FeatureToggleActions");
|
||||
|
||||
describe("FeatureForm", function () {
|
||||
var Component;
|
||||
beforeEach(function() {
|
||||
var archivedToggles = [
|
||||
describe("FeatureForm", () => {
|
||||
let Component;
|
||||
beforeEach(() => {
|
||||
const archivedToggles = [
|
||||
{ name: "featureX" },
|
||||
{ name: "featureY" }
|
||||
];
|
||||
@ -19,18 +20,18 @@ describe("FeatureForm", function () {
|
||||
<FeatureArchive archivedFeatures={archivedToggles} />);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(() => {
|
||||
React.unmountComponentAtNode(document.body);
|
||||
});
|
||||
|
||||
it("should render two archived features", function() {
|
||||
var rows = Component.getDOMNode().querySelectorAll("tbody tr");
|
||||
it("should render two archived features", () => {
|
||||
const rows = Component.getDOMNode().querySelectorAll("tbody tr");
|
||||
|
||||
expect(rows.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("should revive archived feature toggle", function() {
|
||||
var button = Component.getDOMNode().querySelector("tbody button");
|
||||
it("should revive archived feature toggle", () => {
|
||||
const button = Component.getDOMNode().querySelector("tbody button");
|
||||
TestUtils.Simulate.click(button);
|
||||
|
||||
jest.runAllTimers();
|
||||
|
@ -1,33 +1,34 @@
|
||||
'use strict';
|
||||
jest.dontMock("../../../components/feature/FeatureForm");
|
||||
|
||||
var React = require("react/addons");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var FeatureForm = require("../../../components/feature/FeatureForm");
|
||||
const React = require("react/addons");
|
||||
const TestUtils = React.addons.TestUtils;
|
||||
const FeatureForm = require("../../../components/feature/FeatureForm");
|
||||
|
||||
describe("FeatureForm", function () {
|
||||
var Component;
|
||||
var strategies = [
|
||||
describe("FeatureForm", () => {
|
||||
let Component;
|
||||
const strategies = [
|
||||
{ name: "default" }
|
||||
];
|
||||
afterEach(function() {
|
||||
afterEach(() => {
|
||||
React.unmountComponentAtNode(document.body);
|
||||
});
|
||||
|
||||
describe("new", function () {
|
||||
it("should render empty form", function() {
|
||||
describe("new", () => {
|
||||
it("should render empty form", () => {
|
||||
Component = TestUtils .renderIntoDocument(<FeatureForm strategies={strategies} />);
|
||||
var name = Component.getDOMNode().querySelectorAll("input");
|
||||
const name = Component.getDOMNode().querySelectorAll("input");
|
||||
expect(name[0].value).toEqual("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("edit", function () {
|
||||
var feature = { name: "Test", strategy: "unknown" };
|
||||
describe("edit", () => {
|
||||
const feature = { name: "Test", strategy: "unknown" };
|
||||
|
||||
it("should show unknown strategy as default", function () {
|
||||
it("should show unknown strategy as default", () => {
|
||||
Component = TestUtils .renderIntoDocument(<FeatureForm feature={feature} strategies={strategies} />);
|
||||
|
||||
var strategySelect = Component.getDOMNode().querySelector("select");
|
||||
const strategySelect = Component.getDOMNode().querySelector("select");
|
||||
expect(strategySelect.value).toEqual("default");
|
||||
});
|
||||
});
|
||||
|
@ -1,56 +1,58 @@
|
||||
'use strict';
|
||||
jest.dontMock("../../../components/feature/FeatureList");
|
||||
jest.dontMock("../../../components/feature/Feature");
|
||||
|
||||
var React = require("react/addons");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var FeatureList = require("../../../components/feature/FeatureList");
|
||||
const React = require("react/addons");
|
||||
const TestUtils = React.addons.TestUtils;
|
||||
const FeatureList = require("../../../components/feature/FeatureList");
|
||||
|
||||
describe("FeatureList", function () {
|
||||
var Component, features;
|
||||
describe("FeatureList", () => {
|
||||
let Component;
|
||||
let features;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
features = [
|
||||
{ name: "featureX", strategy: "other" },
|
||||
{ name: "group.featureY", strategy: "default" }
|
||||
];
|
||||
var strategies=[
|
||||
const strategies=[
|
||||
{ name: "default" }
|
||||
];
|
||||
Component = TestUtils .renderIntoDocument(<FeatureList features={features} strategies={strategies} />);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(() => {
|
||||
React.unmountComponentAtNode(document.body);
|
||||
});
|
||||
|
||||
it("should render all features", function() {
|
||||
var features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
it("should render all features", () => {
|
||||
const features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
expect(features.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("should filter list of features", function() {
|
||||
var filterNode = Component.refs.filter.getDOMNode();
|
||||
it("should filter list of features", () => {
|
||||
const filterNode = Component.refs.filter.getDOMNode();
|
||||
TestUtils.Simulate.change(filterNode, { target: { value: "group" } });
|
||||
|
||||
var features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
const features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
expect(features.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("should filter list of features ignoring case", function() {
|
||||
var filterNode = Component.refs.filter.getDOMNode();
|
||||
it("should filter list of features ignoring case", () => {
|
||||
const filterNode = Component.refs.filter.getDOMNode();
|
||||
TestUtils.Simulate.change(filterNode, { target: { value: "GROUP" } });
|
||||
|
||||
var features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
const features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
expect(features.length).toEqual(1);
|
||||
expect(features[0].textContent).toMatch("group");
|
||||
});
|
||||
|
||||
it("should filter list of features by strategy name", function() {
|
||||
var searchString = "other";
|
||||
var filterNode = Component.refs.filter.getDOMNode();
|
||||
it("should filter list of features by strategy name", () => {
|
||||
const searchString = "other";
|
||||
const filterNode = Component.refs.filter.getDOMNode();
|
||||
TestUtils.Simulate.change(filterNode, { target: { value: searchString } });
|
||||
|
||||
var features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
const features = Component.getDOMNode().querySelectorAll(".feature");
|
||||
expect(features.length).toEqual(1);
|
||||
expect(features[0].textContent).toMatch(searchString);
|
||||
});
|
||||
|
@ -1,11 +1,14 @@
|
||||
'use strict';
|
||||
jest.autoMockOff();
|
||||
jest.dontMock('../../stores/FeatureToggleActions');
|
||||
jest.dontMock('../../stores/FeatureToggleStore');
|
||||
|
||||
describe('FeatureToggleStore', function() {
|
||||
var Actions, Store, toggles;
|
||||
describe('FeatureToggleStore', () => {
|
||||
let Actions;
|
||||
let Store;
|
||||
let toggles;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
Actions = require('../../stores/FeatureToggleActions');
|
||||
Store = require('../../stores/FeatureToggleStore');
|
||||
toggles = [
|
||||
@ -13,11 +16,11 @@ describe('FeatureToggleStore', function() {
|
||||
];
|
||||
});
|
||||
|
||||
it('should be an empty store', function() {
|
||||
it('should be an empty store', () => {
|
||||
expect(Store.getFeatureToggles().length).toBe(0);
|
||||
});
|
||||
|
||||
it('should inititialize the store', function() {
|
||||
it('should inititialize the store', () => {
|
||||
Actions.init.completed(toggles);
|
||||
|
||||
jest.runAllTimers();
|
||||
@ -25,10 +28,10 @@ describe('FeatureToggleStore', function() {
|
||||
expect(Store.getFeatureToggles()[0].name).toEqual("app.feature");
|
||||
});
|
||||
|
||||
it('should add a another toggle', function() {
|
||||
it('should add a another toggle', () => {
|
||||
Actions.init.completed(toggles);
|
||||
|
||||
var newToggle = { name: "app.featureB", enabled: true, strategy: "default" };
|
||||
const newToggle = { name: "app.featureB", enabled: true, strategy: "default" };
|
||||
|
||||
Actions.create.completed(newToggle);
|
||||
|
||||
@ -37,7 +40,7 @@ describe('FeatureToggleStore', function() {
|
||||
expect(Store.getFeatureToggles()[1].name).toEqual("app.featureB");
|
||||
});
|
||||
|
||||
it('should archive toggle', function() {
|
||||
it('should archive toggle', () => {
|
||||
Actions.init.completed(toggles);
|
||||
|
||||
Actions.archive.completed(toggles[0]);
|
||||
@ -46,7 +49,7 @@ describe('FeatureToggleStore', function() {
|
||||
expect(Store.getFeatureToggles().length).toBe(0);
|
||||
});
|
||||
|
||||
it('should keep toggles in sorted order', function() {
|
||||
it('should keep toggles in sorted order', () => {
|
||||
Actions.init.completed([
|
||||
{ name: "A" },
|
||||
{ name: "B" },
|
||||
@ -61,9 +64,9 @@ describe('FeatureToggleStore', function() {
|
||||
expect(Store.getFeatureToggles()[3].name).toEqual("C");
|
||||
});
|
||||
|
||||
it('should update toggle', function() {
|
||||
it('should update toggle', () => {
|
||||
Actions.init.completed(toggles);
|
||||
var toggle = toggles[0];
|
||||
const toggle = toggles[0];
|
||||
|
||||
toggle.enabled = false;
|
||||
Actions.update.completed(toggle);
|
||||
|
@ -1,10 +1,11 @@
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var UserStore = require('./stores/UserStore');
|
||||
var routes = require('./routes');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Router = require('react-router');
|
||||
const UserStore = require('./stores/UserStore');
|
||||
const routes = require('./routes');
|
||||
|
||||
UserStore.init();
|
||||
|
||||
Router.run(routes, function (Handler) {
|
||||
Router.run(routes, Handler => {
|
||||
React.render(<Handler/>, document.getElementById('content'));
|
||||
});
|
||||
|
@ -1,34 +1,35 @@
|
||||
var React = require('react');
|
||||
var Ui = require('./ErrorMessages.ui');
|
||||
var ErrorStore = require('../stores/ErrorStore');
|
||||
var ErrorActions = require('../stores/ErrorActions');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Ui = require('./ErrorMessages.ui');
|
||||
const ErrorStore = require('../stores/ErrorStore');
|
||||
const ErrorActions = require('../stores/ErrorActions');
|
||||
|
||||
var ErrorMessages = React.createClass({
|
||||
getInitialState: function() {
|
||||
const ErrorMessages = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
errors: ErrorStore.getErrors()
|
||||
};
|
||||
},
|
||||
|
||||
onStoreChange: function() {
|
||||
onStoreChange() {
|
||||
this.setState({
|
||||
errors: ErrorStore.getErrors()
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
componentDidMount() {
|
||||
this.unsubscribe = ErrorStore.listen(this.onStoreChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
componentWillUnmount() {
|
||||
this.unsubscribe();
|
||||
},
|
||||
|
||||
onClearErrors: function() {
|
||||
onClearErrors() {
|
||||
ErrorActions.clear();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<Ui errors={this.state.errors} onClearErrors={this.onClearErrors}></Ui>
|
||||
);
|
||||
|
@ -1,14 +1,13 @@
|
||||
var React = require('react');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
|
||||
var ErrorMessages = React.createClass({
|
||||
render: function() {
|
||||
const ErrorMessages = React.createClass({
|
||||
render() {
|
||||
if (!this.props.errors.length) {
|
||||
return <div/>;
|
||||
}
|
||||
|
||||
var errorNodes = this.props.errors.map(function(e, i) {
|
||||
return (<li key={e + i} className="largetext">{e}</li>);
|
||||
});
|
||||
const errorNodes = this.props.errors.map((e, i) => <li key={e + i} className="largetext">{e}</li>);
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
|
@ -1,8 +1,9 @@
|
||||
var React = require('react');
|
||||
var User = require('./User');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const User = require('./User');
|
||||
|
||||
var Menu = React.createClass({
|
||||
render: function() { return (
|
||||
const Menu = React.createClass({
|
||||
render() { return (
|
||||
<div className="topbar mbl">
|
||||
<div className="container">
|
||||
<div className="page">
|
||||
|
@ -1,14 +1,15 @@
|
||||
var React = require('react');
|
||||
var UserStore = require('../stores/UserStore');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const UserStore = require('../stores/UserStore');
|
||||
|
||||
var User = React.createClass({
|
||||
const User = React.createClass({
|
||||
|
||||
onSave: function() {
|
||||
var value = this.refs.username.getDOMNode().value.trim();
|
||||
onSave() {
|
||||
const value = this.refs.username.getDOMNode().value.trim();
|
||||
UserStore.set(value);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="r-pvm">
|
||||
<input type="text" placeholder="username"
|
||||
|
@ -1,13 +1,14 @@
|
||||
var React = require("react");
|
||||
var FeatureActions = require('../../stores/FeatureToggleActions');
|
||||
'use strict';
|
||||
const React = require("react");
|
||||
const FeatureActions = require('../../stores/FeatureToggleActions');
|
||||
|
||||
var ArchiveFeatureComponent = React.createClass({
|
||||
const ArchiveFeatureComponent = React.createClass({
|
||||
|
||||
onRevive: function(item) {
|
||||
onRevive(item) {
|
||||
FeatureActions.revive.triggerPromise(item);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Archived Feature Toggles</h1>
|
||||
@ -27,7 +28,7 @@ var ArchiveFeatureComponent = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderArchivedItem: function(f) {
|
||||
renderArchivedItem(f) {
|
||||
return (
|
||||
<tr key={f.name}>
|
||||
<td>
|
||||
|
@ -1,10 +1,11 @@
|
||||
var React = require('react');
|
||||
var FeatureForm = require('./FeatureForm');
|
||||
var LogEntryList = require('../log/LogEntryList');
|
||||
var eventStore = require('../../stores/EventStore');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const FeatureForm = require('./FeatureForm');
|
||||
const LogEntryList = require('../log/LogEntryList');
|
||||
const eventStore = require('../../stores/EventStore');
|
||||
|
||||
var Feature = React.createClass({
|
||||
getInitialState: function() {
|
||||
const Feature = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
editMode: false,
|
||||
showHistory: false,
|
||||
@ -12,33 +13,33 @@ var Feature = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
handleEventsResponse: function(response) {
|
||||
handleEventsResponse(response) {
|
||||
this.setState({events: response});
|
||||
},
|
||||
|
||||
toggleHistory: function() {
|
||||
toggleHistory() {
|
||||
eventStore.getEventsByName(this.props.feature.name).then(this.handleEventsResponse);
|
||||
this.setState({showHistory: !this.state.showHistory});
|
||||
},
|
||||
|
||||
|
||||
toggleEditMode: function() {
|
||||
toggleEditMode() {
|
||||
this.setState({editMode: !this.state.editMode});
|
||||
},
|
||||
|
||||
saveFeature: function(feature) {
|
||||
saveFeature(feature) {
|
||||
this.props.onChange(feature);
|
||||
this.toggleEditMode();
|
||||
},
|
||||
|
||||
archiveFeature: function() {
|
||||
if (window.confirm("Are you sure you want to delete " + this.props.feature.name + "?")) {
|
||||
archiveFeature() {
|
||||
if (window.confirm(`Are you sure you want to delete ${this.props.feature.name}?`)) {
|
||||
this.props.onArchive(this.props.feature);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
renderEditMode: function() {
|
||||
renderEditMode() {
|
||||
return (
|
||||
<tr>
|
||||
<td colSpan="4" className="pan man no-border">
|
||||
@ -53,7 +54,7 @@ var Feature = React.createClass({
|
||||
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<tbody className="feature">
|
||||
<tr className={this.state.editMode ? "edit bg-lilac-xlt" : ""}>
|
||||
@ -107,11 +108,11 @@ var Feature = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderEmptyRow: function() {
|
||||
renderEmptyRow() {
|
||||
return (<tr />);
|
||||
},
|
||||
|
||||
renderHistory: function() {
|
||||
renderHistory() {
|
||||
return (<tr>
|
||||
<td colSpan="4" className="no-border">
|
||||
<LogEntryList events={this.state.events} />
|
||||
|
@ -1,8 +1,9 @@
|
||||
var React = require('react');
|
||||
var TextInput = require('../form/TextInput');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const TextInput = require('../form/TextInput');
|
||||
|
||||
var FeatureForm = React.createClass({
|
||||
getInitialState: function() {
|
||||
const FeatureForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
strategyOptions: this.props.strategies,
|
||||
requiredParams: [],
|
||||
@ -10,18 +11,18 @@ var FeatureForm = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
componentWillMount() {
|
||||
if(this.props.feature) {
|
||||
this.setSelectedStrategy(this.props.feature.strategy);
|
||||
}
|
||||
},
|
||||
|
||||
onStrategyChange: function(e) {
|
||||
onStrategyChange(e) {
|
||||
this.setSelectedStrategy(e.target.value);
|
||||
this.setState({currentStrategy: e.target.value});
|
||||
},
|
||||
|
||||
getParameterValue: function(name) {
|
||||
getParameterValue(name) {
|
||||
if(this.props.feature && this.props.feature.parameters) {
|
||||
return this.props.feature.parameters[name];
|
||||
} else {
|
||||
@ -29,10 +30,8 @@ var FeatureForm = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
setSelectedStrategy: function(name) {
|
||||
var selectedStrategy = this.props.strategies.filter(function(strategy) {
|
||||
return strategy.name === name;
|
||||
})[0];
|
||||
setSelectedStrategy(name) {
|
||||
const selectedStrategy = this.props.strategies.filter(strategy => strategy.name === name)[0];
|
||||
|
||||
if(selectedStrategy) {
|
||||
this.setStrategyParams(selectedStrategy);
|
||||
@ -44,23 +43,23 @@ var FeatureForm = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
setStrategyParams: function(strategy) {
|
||||
var requiredParams = [];
|
||||
var key;
|
||||
setStrategyParams(strategy) {
|
||||
const requiredParams = [];
|
||||
let key;
|
||||
for(key in strategy.parametersTemplate) {
|
||||
requiredParams.push({name: key, value: this.getParameterValue(key)});
|
||||
}
|
||||
this.setState({requiredParams: requiredParams});
|
||||
this.setState({requiredParams});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var feature = this.props.feature || {
|
||||
render() {
|
||||
const feature = this.props.feature || {
|
||||
name: '',
|
||||
strategy: 'default',
|
||||
enabled: false
|
||||
};
|
||||
|
||||
var idPrefix = this.props.feature ? this.props.feature.name : 'new';
|
||||
const idPrefix = this.props.feature ? this.props.feature.name : 'new';
|
||||
|
||||
return (
|
||||
<div className="bg-lilac-xlt r-pam">
|
||||
@ -70,7 +69,7 @@ var FeatureForm = React.createClass({
|
||||
{this.props.feature ? "" : <legend>Create new toggle</legend>}
|
||||
|
||||
<TextInput
|
||||
id={idPrefix + "-name"}
|
||||
id={`${idPrefix}-name`}
|
||||
name="name"
|
||||
label="Name"
|
||||
value={feature.name}
|
||||
@ -79,7 +78,7 @@ var FeatureForm = React.createClass({
|
||||
placeholder="Toggle name" />
|
||||
|
||||
<TextInput
|
||||
id={idPrefix + "-description"}
|
||||
id={`${idPrefix}-description`}
|
||||
name="description"
|
||||
label="Description"
|
||||
value={feature.description}
|
||||
@ -87,9 +86,9 @@ var FeatureForm = React.createClass({
|
||||
placeholder="Enter description" />
|
||||
|
||||
<div className="formelement">
|
||||
<label htmlFor={idPrefix + "-strategy"}>Strategy</label>
|
||||
<label htmlFor={`${idPrefix}-strategy`}>Strategy</label>
|
||||
<div className="input select">
|
||||
<select id={idPrefix + "-strategy"}
|
||||
<select id={`${idPrefix}-strategy`}
|
||||
ref="strategy"
|
||||
value={this.state.currentStrategy}
|
||||
onChange={this.onStrategyChange}>
|
||||
@ -102,11 +101,11 @@ var FeatureForm = React.createClass({
|
||||
<div className="input">
|
||||
<ul className="inputs-list">
|
||||
<li>
|
||||
<input id={idPrefix + "-active"}
|
||||
<input id={`${idPrefix}-active`}
|
||||
ref="enabled"
|
||||
type="checkbox"
|
||||
defaultChecked={feature.enabled} />
|
||||
<label htmlFor={idPrefix + "-active"}>
|
||||
<label htmlFor={`${idPrefix}-active`}>
|
||||
Active
|
||||
</label>
|
||||
</li>
|
||||
@ -127,32 +126,26 @@ var FeatureForm = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderStrategyOptions: function() {
|
||||
return this.props.strategies.map(function(strategy) {
|
||||
return (
|
||||
<option key={strategy.name} value={strategy.name}>
|
||||
{strategy.name}
|
||||
</option>
|
||||
);
|
||||
}.bind(this));
|
||||
renderStrategyOptions() {
|
||||
return this.props.strategies.map(strategy => <option key={strategy.name} value={strategy.name}>
|
||||
{strategy.name}
|
||||
</option>);
|
||||
},
|
||||
|
||||
renderStrategyProperties: function() {
|
||||
return this.state.requiredParams.map(function(param) {
|
||||
return <TextInput
|
||||
id={"param-" + param.name}
|
||||
key={"param-" + param.name}
|
||||
name={param.name}
|
||||
label={param.name}
|
||||
ref={param.name}
|
||||
value={param.value} />;
|
||||
});
|
||||
renderStrategyProperties() {
|
||||
return this.state.requiredParams.map(param => <TextInput
|
||||
id={`param-${param.name}`}
|
||||
key={`param-${param.name}`}
|
||||
name={param.name}
|
||||
label={param.name}
|
||||
ref={param.name}
|
||||
value={param.value} />);
|
||||
},
|
||||
|
||||
saveFeature: function(e) {
|
||||
saveFeature(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var feature = {
|
||||
const feature = {
|
||||
name: this.refs.name.getValue(),
|
||||
description: this.refs.description.getValue(),
|
||||
strategy: this.state.currentStrategy,
|
||||
@ -163,16 +156,16 @@ var FeatureForm = React.createClass({
|
||||
this.props.onSubmit(feature);
|
||||
},
|
||||
|
||||
cancelFeature: function(e) {
|
||||
cancelFeature(e) {
|
||||
e.preventDefault();
|
||||
this.props.onCancel();
|
||||
},
|
||||
|
||||
getParameters: function() {
|
||||
var parameters = {};
|
||||
this.state.requiredParams.forEach(function(param) {
|
||||
getParameters() {
|
||||
const parameters = {};
|
||||
this.state.requiredParams.forEach(param => {
|
||||
parameters[param.name] = this.refs[param.name].getValue();
|
||||
}.bind(this));
|
||||
});
|
||||
return parameters;
|
||||
}
|
||||
});
|
||||
|
@ -1,39 +1,38 @@
|
||||
var React = require('react');
|
||||
var Feature = require('./Feature');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Feature = require('./Feature');
|
||||
|
||||
var noop = function() {};
|
||||
const noop = function() {};
|
||||
|
||||
var FeatureList = React.createClass({
|
||||
const FeatureList = React.createClass({
|
||||
propTypes: {
|
||||
features: React.PropTypes.array.isRequired,
|
||||
strategies: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
getDefaultProps() {
|
||||
return {
|
||||
onFeatureChanged: noop,
|
||||
onFeatureArchive: noop
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState() {
|
||||
return {
|
||||
filter: undefined
|
||||
};
|
||||
},
|
||||
|
||||
onFilterChange: function(e) {
|
||||
onFilterChange(e) {
|
||||
e.preventDefault();
|
||||
this.setState({filter: e.target.value.trim()});
|
||||
},
|
||||
|
||||
filteredFeatures: function() {
|
||||
filteredFeatures() {
|
||||
if(this.state.filter) {
|
||||
var regex = new RegExp(this.state.filter, "i");
|
||||
const regex = new RegExp(this.state.filter, "i");
|
||||
|
||||
return this.props.features.filter(function(item) {
|
||||
return regex.test(item.name) || regex.test(item.strategy);
|
||||
}.bind(this));
|
||||
return this.props.features.filter(item => regex.test(item.name) || regex.test(item.strategy));
|
||||
|
||||
} else {
|
||||
return this.props.features;
|
||||
@ -41,18 +40,14 @@ var FeatureList = React.createClass({
|
||||
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var featureNodes = this.filteredFeatures().map(function(feature) {
|
||||
return (
|
||||
<Feature
|
||||
key={feature.name}
|
||||
feature={feature}
|
||||
onChange={this.props.onFeatureChanged}
|
||||
onArchive={this.props.onFeatureArchive}
|
||||
strategies={this.props.strategies}
|
||||
/>
|
||||
);
|
||||
}.bind(this));
|
||||
render() {
|
||||
const featureNodes = this.filteredFeatures().map(feature => <Feature
|
||||
key={feature.name}
|
||||
feature={feature}
|
||||
onChange={this.props.onFeatureChanged}
|
||||
onArchive={this.props.onFeatureArchive}
|
||||
strategies={this.props.strategies}
|
||||
/>);
|
||||
|
||||
return (
|
||||
<div className=''>
|
||||
|
@ -1,39 +1,40 @@
|
||||
var React = require('react');
|
||||
var FeatureList = require('./FeatureList');
|
||||
var FeatureForm = require('./FeatureForm');
|
||||
var FeatureActions = require('../../stores/FeatureToggleActions');
|
||||
var ErrorActions = require('../../stores/ErrorActions');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const FeatureList = require('./FeatureList');
|
||||
const FeatureForm = require('./FeatureForm');
|
||||
const FeatureActions = require('../../stores/FeatureToggleActions');
|
||||
const ErrorActions = require('../../stores/ErrorActions');
|
||||
|
||||
var FeatureTogglesComponent = React.createClass({
|
||||
getInitialState: function() {
|
||||
const FeatureTogglesComponent = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
createView: false
|
||||
};
|
||||
},
|
||||
|
||||
updateFeature: function (feature) {
|
||||
updateFeature(feature) {
|
||||
FeatureActions.update.triggerPromise(feature);
|
||||
},
|
||||
|
||||
archiveFeature: function (feature) {
|
||||
archiveFeature(feature) {
|
||||
FeatureActions.archive.triggerPromise(feature);
|
||||
},
|
||||
|
||||
createFeature: function (feature) {
|
||||
createFeature(feature) {
|
||||
FeatureActions.create.triggerPromise(feature)
|
||||
.then(this.cancelNewFeature);
|
||||
},
|
||||
|
||||
newFeature: function() {
|
||||
newFeature() {
|
||||
this.setState({createView: true});
|
||||
},
|
||||
|
||||
cancelNewFeature: function () {
|
||||
cancelNewFeature() {
|
||||
this.setState({createView: false});
|
||||
ErrorActions.clear();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -53,14 +54,14 @@ var FeatureTogglesComponent = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderCreateView: function() {
|
||||
renderCreateView() {
|
||||
return <FeatureForm
|
||||
onCancel={this.cancelNewFeature}
|
||||
onSubmit={this.createFeature}
|
||||
strategies={this.props.strategies} />;
|
||||
},
|
||||
|
||||
renderCreateButton: function() {
|
||||
renderCreateButton() {
|
||||
return <button className="mal" onClick={this.newFeature}>Create feature toggle</button>;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
var React = require('react');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
|
||||
var TextInput = React.createClass({
|
||||
const TextInput = React.createClass({
|
||||
propTypes: {
|
||||
name: React.PropTypes.string.isRequired,
|
||||
label: React.PropTypes.string.isRequired,
|
||||
@ -10,22 +11,22 @@ var TextInput = React.createClass({
|
||||
required: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
getDefaultProps() {
|
||||
return {
|
||||
required: false
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState() {
|
||||
return {};
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
getValue() {
|
||||
return this.refs.input.getDOMNode().value.trim();
|
||||
},
|
||||
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="formelement required">
|
||||
<label htmlFor={this.props.id} className="t4">{this.props.label}</label>
|
||||
|
@ -1,27 +1,28 @@
|
||||
var React = require('react');
|
||||
var LogEntryList = require('./LogEntryList');
|
||||
var eventStore = require('../../stores/EventStore');
|
||||
var ErrorActions = require('../../stores/ErrorActions');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const LogEntryList = require('./LogEntryList');
|
||||
const eventStore = require('../../stores/EventStore');
|
||||
const ErrorActions = require('../../stores/ErrorActions');
|
||||
|
||||
var LogEntriesComponent = React.createClass({
|
||||
getInitialState: function() {
|
||||
const LogEntriesComponent = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
createView: false,
|
||||
events: []
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
eventStore.getEvents().then(function(res) {
|
||||
componentDidMount() {
|
||||
eventStore.getEvents().then(res => {
|
||||
this.setState({events: res.events});
|
||||
}.bind(this), this.initError);
|
||||
}, this.initError);
|
||||
},
|
||||
|
||||
initError: function() {
|
||||
initError() {
|
||||
ErrorActions.error("Could not load events from server");
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Log</h1>
|
||||
|
@ -1,27 +1,28 @@
|
||||
var React = require('react');
|
||||
var moment = require('moment');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const moment = require('moment');
|
||||
|
||||
var DIFF_PREFIXES = {
|
||||
const DIFF_PREFIXES = {
|
||||
A: ' ',
|
||||
E: ' ',
|
||||
D: '-',
|
||||
N: '+'
|
||||
};
|
||||
|
||||
var SPADEN_CLASS = {
|
||||
const SPADEN_CLASS = {
|
||||
A: 'blue', // array edited
|
||||
E: 'blue', // edited
|
||||
D: 'negative', // deleted
|
||||
N: 'positive', // added
|
||||
};
|
||||
|
||||
var LogEntry = React.createClass({
|
||||
const LogEntry = React.createClass({
|
||||
propTypes: {
|
||||
event: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var date = moment(this.props.event.createdAt);
|
||||
render() {
|
||||
const date = moment(this.props.event.createdAt);
|
||||
|
||||
return (
|
||||
<tr>
|
||||
@ -40,19 +41,19 @@ var LogEntry = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderFullEventData: function() {
|
||||
var localEventData = JSON.parse(JSON.stringify(this.props.event.data));
|
||||
renderFullEventData() {
|
||||
const localEventData = JSON.parse(JSON.stringify(this.props.event.data));
|
||||
delete localEventData.description;
|
||||
delete localEventData.name;
|
||||
|
||||
var prettyPrinted = JSON.stringify(localEventData, null, 2);
|
||||
const prettyPrinted = JSON.stringify(localEventData, null, 2);
|
||||
|
||||
return (<code className='JSON smalltext man'>{prettyPrinted}</code>);
|
||||
},
|
||||
|
||||
renderEventDiff: function() {
|
||||
renderEventDiff() {
|
||||
if (!this.props.showFullEvents && this.props.event.diffs) {
|
||||
var changes = this.props.event.diffs.map(this.buildDiff);
|
||||
const changes = this.props.event.diffs.map(this.buildDiff);
|
||||
return (
|
||||
<code className='smalltext man'>{changes.length === 0 ? '(no changes)' : changes}</code>
|
||||
);
|
||||
@ -61,9 +62,9 @@ var LogEntry = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
buildDiff: function(diff, idx) {
|
||||
var change;
|
||||
var key = diff.path.join('.');
|
||||
buildDiff(diff, idx) {
|
||||
let change;
|
||||
const key = diff.path.join('.');
|
||||
|
||||
if (diff.lhs !== undefined && diff.rhs !== undefined) {
|
||||
change = (
|
||||
@ -73,8 +74,8 @@ var LogEntry = React.createClass({
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
var spadenClass = SPADEN_CLASS[diff.kind];
|
||||
var prefix = DIFF_PREFIXES[diff.kind];
|
||||
const spadenClass = SPADEN_CLASS[diff.kind];
|
||||
const prefix = DIFF_PREFIXES[diff.kind];
|
||||
|
||||
change = (<div className={spadenClass}>{prefix} {key}: {JSON.stringify(diff.rhs)}</div>);
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
var React = require('react'),
|
||||
LogEntry = require('./LogEntry');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const LogEntry = require('./LogEntry');
|
||||
|
||||
var LogEntryList = React.createClass({
|
||||
const LogEntryList = React.createClass({
|
||||
propTypes: {
|
||||
events: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState() {
|
||||
return {
|
||||
showFullEvents: false
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var logEntryNodes = this.props.events.map(function(event) {
|
||||
return <LogEntry event={event} key={event.id} showFullEvents={this.state.showFullEvents} />;
|
||||
}.bind(this));
|
||||
render() {
|
||||
const logEntryNodes = this.props.events.map(event => <LogEntry event={event} key={event.id} showFullEvents={this.state.showFullEvents} />);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -48,7 +47,7 @@ var LogEntryList = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
toggleFullEvents: function() {
|
||||
toggleFullEvents() {
|
||||
this.setState({showFullEvents: !this.state.showFullEvents});
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,34 @@
|
||||
var React = require('react');
|
||||
var StrategyList = require('./StrategyList');
|
||||
var StrategyForm = require('./StrategyForm');
|
||||
var StrategyActions = require('../../stores/StrategyActions');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const StrategyList = require('./StrategyList');
|
||||
const StrategyForm = require('./StrategyForm');
|
||||
const StrategyActions = require('../../stores/StrategyActions');
|
||||
|
||||
var StrategiesComponent = React.createClass({
|
||||
getInitialState: function() {
|
||||
const StrategiesComponent = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
createView: false
|
||||
};
|
||||
},
|
||||
|
||||
onNewStrategy: function() {
|
||||
onNewStrategy() {
|
||||
this.setState({createView: true});
|
||||
},
|
||||
|
||||
onCancelNewStrategy: function() {
|
||||
onCancelNewStrategy() {
|
||||
this.setState({createView: false});
|
||||
},
|
||||
|
||||
onSave: function(strategy) {
|
||||
onSave(strategy) {
|
||||
StrategyActions.create.triggerPromise(strategy)
|
||||
.then(this.onCancelNewStrategy);
|
||||
},
|
||||
|
||||
onRemove: function(strategy) {
|
||||
onRemove(strategy) {
|
||||
StrategyActions.remove.triggerPromise(strategy);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Activation Strategies</h1>
|
||||
@ -41,7 +42,7 @@ var StrategiesComponent = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderCreateView: function() {
|
||||
renderCreateView() {
|
||||
return (
|
||||
<StrategyForm
|
||||
onCancelNewStrategy={this.onCancelNewStrategy}
|
||||
@ -49,7 +50,7 @@ var StrategiesComponent = React.createClass({
|
||||
/>);
|
||||
},
|
||||
|
||||
renderCreateButton: function() {
|
||||
renderCreateButton() {
|
||||
return (
|
||||
<button className="mal" onClick={this.onNewStrategy}>
|
||||
Create strategy
|
||||
@ -58,4 +59,4 @@ var StrategiesComponent = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = StrategiesComponent;
|
||||
module.exports = StrategiesComponent;
|
||||
|
@ -1,19 +1,19 @@
|
||||
var React = require('react');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
|
||||
var Strategy = React.createClass({
|
||||
const Strategy = React.createClass({
|
||||
propTypes: {
|
||||
strategy: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
onRemove: function(event) {
|
||||
onRemove(event) {
|
||||
event.preventDefault();
|
||||
if (window.confirm("Are you sure you want to delete strategy '"+
|
||||
this.props.strategy.name+"'?")) {
|
||||
if (window.confirm(`Are you sure you want to delete strategy '${this.props.strategy.name}'?`)) {
|
||||
this.props.onRemove(this.props.strategy);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="line mal">
|
||||
<div className="unit">
|
||||
|
@ -1,32 +1,33 @@
|
||||
var React = require('react');
|
||||
var TextInput = require('../form/TextInput');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const TextInput = require('../form/TextInput');
|
||||
|
||||
var StrategyForm = React.createClass({
|
||||
const StrategyForm = React.createClass({
|
||||
|
||||
getDefaultProps: function() {
|
||||
getDefaultProps() {
|
||||
return {
|
||||
maxParams: 4
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState() {
|
||||
return {
|
||||
parameters: []
|
||||
};
|
||||
},
|
||||
|
||||
onSubmit: function(event) {
|
||||
onSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var strategy = {};
|
||||
const strategy = {};
|
||||
strategy.name = this.refs.name.getValue();
|
||||
strategy.description = this.refs.description.getValue();
|
||||
strategy.parametersTemplate = {};
|
||||
|
||||
var that = this;
|
||||
const that = this;
|
||||
|
||||
this.state.parameters.forEach(function(parameter) {
|
||||
var name = that.refs[parameter.name].getDOMNode().value.trim();
|
||||
this.state.parameters.forEach(parameter => {
|
||||
const name = that.refs[parameter.name].getDOMNode().value.trim();
|
||||
if(name) {
|
||||
strategy.parametersTemplate[name] = "string";
|
||||
}
|
||||
@ -35,27 +36,27 @@ var StrategyForm = React.createClass({
|
||||
this.props.onSave(strategy);
|
||||
},
|
||||
|
||||
onCancel: function(event) {
|
||||
onCancel(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.props.onCancelNewStrategy();
|
||||
},
|
||||
|
||||
onAddParam: function(event) {
|
||||
onAddParam(event) {
|
||||
event.preventDefault();
|
||||
var id = this.state.parameters.length + 1;
|
||||
var params = this.state.parameters.concat([{id:id, name: "param_" + id, label: "Parameter " +id}]);
|
||||
const id = this.state.parameters.length + 1;
|
||||
const params = this.state.parameters.concat([{id, name: `param_${id}`, label: `Parameter ${id}`}]);
|
||||
this.setState({parameters: params});
|
||||
},
|
||||
|
||||
onRemoveParam: function(event) {
|
||||
onRemoveParam(event) {
|
||||
event.preventDefault();
|
||||
var params = this.state.parameters.slice(0, -1);
|
||||
const params = this.state.parameters.slice(0, -1);
|
||||
|
||||
this.setState({parameters: params});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="line r-pam bg-lilac-xlt">
|
||||
<div className="unit r-size1of2">
|
||||
@ -92,41 +93,37 @@ var StrategyForm = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
renderParameters: function() {
|
||||
return this.state.parameters.map(function(param) {
|
||||
return (
|
||||
<div className="formelement" key={param.name}>
|
||||
<label className="t4">{param.label}</label>
|
||||
<div className="input">
|
||||
<div className="line">
|
||||
renderParameters() {
|
||||
return this.state.parameters.map(param => <div className="formelement" key={param.name}>
|
||||
<label className="t4">{param.label}</label>
|
||||
<div className="input">
|
||||
<div className="line">
|
||||
|
||||
<div className="unit size2of3">
|
||||
<input
|
||||
type="text"
|
||||
name={param.name}
|
||||
ref={param.name}
|
||||
placeholder="Parameter name"
|
||||
/>
|
||||
</div>
|
||||
<div className="unit size2of3">
|
||||
<input
|
||||
type="text"
|
||||
name={param.name}
|
||||
ref={param.name}
|
||||
placeholder="Parameter name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="unit size1of3">
|
||||
<select defaultValue="string">
|
||||
<option value="string">string</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="unit size1of3">
|
||||
<select defaultValue="string">
|
||||
<option value="string">string</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
</div>
|
||||
</div>);
|
||||
},
|
||||
|
||||
renderAddLink: function() {
|
||||
renderAddLink() {
|
||||
if(this.state.parameters.length < this.props.maxParams) {
|
||||
return <a href="#add" onClick={this.onAddParam}>+ Add required parameter</a>;
|
||||
}
|
||||
},
|
||||
renderRemoveLink: function() {
|
||||
renderRemoveLink() {
|
||||
if(this.state.parameters.length > 0) {
|
||||
return (
|
||||
<div className="formelement mtn">
|
||||
|
@ -1,15 +1,14 @@
|
||||
var React = require('react'),
|
||||
Strategy = require('./Strategy');
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Strategy = require('./Strategy');
|
||||
|
||||
var StrategyList = React.createClass({
|
||||
const StrategyList = React.createClass({
|
||||
propTypes: {
|
||||
strategies: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var strategyNodes = this.props.strategies.map(function(strategy) {
|
||||
return <Strategy strategy={strategy} key={strategy.name} onRemove={this.props.onRemove} />;
|
||||
}.bind(this));
|
||||
render() {
|
||||
const strategyNodes = this.props.strategies.map(strategy => <Strategy strategy={strategy} key={strategy.name} onRemove={this.props.onRemove} />);
|
||||
return (
|
||||
<div>{strategyNodes}</div>
|
||||
);
|
||||
|
@ -1,14 +1,15 @@
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var UnleashApp = require('./UnleashApp');
|
||||
var LogEntriesComponent = require('./components/log/LogEntriesComponent');
|
||||
var FeatureTogglesComponent = require('./components/feature/FeatureTogglesComponent');
|
||||
var StrategiesComponent = require('./components/strategy/StrategiesComponent');
|
||||
var ArchiveFeatureComponent = require('./components/feature/ArchiveFeatureComponent');
|
||||
var DefaultRoute = Router.DefaultRoute;
|
||||
var Route = Router.Route;
|
||||
'use strict';
|
||||
const React = require('react');
|
||||
const Router = require('react-router');
|
||||
const UnleashApp = require('./UnleashApp');
|
||||
const LogEntriesComponent = require('./components/log/LogEntriesComponent');
|
||||
const FeatureTogglesComponent = require('./components/feature/FeatureTogglesComponent');
|
||||
const StrategiesComponent = require('./components/strategy/StrategiesComponent');
|
||||
const ArchiveFeatureComponent = require('./components/feature/ArchiveFeatureComponent');
|
||||
const DefaultRoute = Router.DefaultRoute;
|
||||
const Route = Router.Route;
|
||||
|
||||
var routes = (
|
||||
const routes = (
|
||||
<Route name="app" path="/" handler={UnleashApp}>
|
||||
<Route name="strategies" handler={StrategiesComponent}/>
|
||||
<Route name="log" handler={LogEntriesComponent}/>
|
||||
|
@ -1,45 +1,44 @@
|
||||
var Reflux = require('reflux');
|
||||
var FeatureActions = require('./FeatureToggleActions');
|
||||
var filter = require('lodash/collection/filter');
|
||||
var sortBy = require('lodash/collection/sortBy');
|
||||
'use strict';
|
||||
const Reflux = require('reflux');
|
||||
const FeatureActions = require('./FeatureToggleActions');
|
||||
const filter = require('lodash/collection/filter');
|
||||
const sortBy = require('lodash/collection/sortBy');
|
||||
|
||||
var _archivedToggles = [];
|
||||
let _archivedToggles = [];
|
||||
|
||||
// Creates a DataStore
|
||||
var FeatureStore = Reflux.createStore({
|
||||
const FeatureStore = Reflux.createStore({
|
||||
|
||||
// Initial setup
|
||||
init: function() {
|
||||
init() {
|
||||
this.listenTo(FeatureActions.initArchive.completed, this.onInit);
|
||||
this.listenTo(FeatureActions.archive.completed, this.onArchive);
|
||||
this.listenTo(FeatureActions.revive.completed, this.onRevive);
|
||||
},
|
||||
|
||||
onInit: function(toggles) {
|
||||
onInit(toggles) {
|
||||
_archivedToggles = toggles;
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
onArchive: function(feature) {
|
||||
var toggles = _archivedToggles.concat([feature]);
|
||||
onArchive(feature) {
|
||||
const toggles = _archivedToggles.concat([feature]);
|
||||
_archivedToggles = sortBy(toggles, 'name');
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
onRevive: function(item) {
|
||||
var newStore = filter(_archivedToggles, function(f) {
|
||||
return f.name !== item.name;
|
||||
});
|
||||
onRevive(item) {
|
||||
const newStore = filter(_archivedToggles, f => f.name !== item.name);
|
||||
|
||||
_archivedToggles = sortBy(newStore, 'name');
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
getArchivedToggles: function() {
|
||||
getArchivedToggles() {
|
||||
return _archivedToggles;
|
||||
},
|
||||
|
||||
initStore: function(archivedToggles) {
|
||||
initStore(archivedToggles) {
|
||||
_archivedToggles = archivedToggles;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
var Reflux = require('reflux');
|
||||
'use strict';
|
||||
const Reflux = require('reflux');
|
||||
|
||||
var ErrorActions = Reflux.createActions([
|
||||
const ErrorActions = Reflux.createActions([
|
||||
"clear",
|
||||
"error"
|
||||
]);
|
||||
|
@ -1,11 +1,12 @@
|
||||
var Reflux = require('reflux');
|
||||
var FeatureActions = require('./FeatureToggleActions');
|
||||
var ErrorActions = require('./ErrorActions');
|
||||
'use strict';
|
||||
const Reflux = require('reflux');
|
||||
const FeatureActions = require('./FeatureToggleActions');
|
||||
const ErrorActions = require('./ErrorActions');
|
||||
|
||||
// Creates a DataStore
|
||||
var FeatureStore = Reflux.createStore({
|
||||
const FeatureStore = Reflux.createStore({
|
||||
// Initial setup
|
||||
init: function() {
|
||||
init() {
|
||||
this.listenTo(FeatureActions.create.failed, this.onError);
|
||||
this.listenTo(FeatureActions.init.failed, this.onError);
|
||||
this.listenTo(FeatureActions.update.failed, this.onError);
|
||||
@ -16,12 +17,12 @@ var FeatureStore = Reflux.createStore({
|
||||
this.errors = [];
|
||||
},
|
||||
|
||||
onError: function (error) {
|
||||
onError(error) {
|
||||
if (this.isClientError(error)) {
|
||||
var errors = JSON.parse(error.responseText);
|
||||
errors.forEach(function(e) {
|
||||
const errors = JSON.parse(error.responseText);
|
||||
errors.forEach(e => {
|
||||
this.addError(e.msg);
|
||||
}.bind(this));
|
||||
});
|
||||
} else if (error.status === 0) {
|
||||
this.addError("server unreachable");
|
||||
} else {
|
||||
@ -29,13 +30,13 @@ var FeatureStore = Reflux.createStore({
|
||||
}
|
||||
},
|
||||
|
||||
onClear: function() {
|
||||
onClear() {
|
||||
this.errors = [];
|
||||
this.trigger([]);
|
||||
},
|
||||
|
||||
addError: function(msg) {
|
||||
var errors = this.errors;
|
||||
addError(msg) {
|
||||
const errors = this.errors;
|
||||
if (errors[errors.length - 1] !== msg) {
|
||||
errors.push(msg);
|
||||
this.errors = errors;
|
||||
@ -43,7 +44,7 @@ var FeatureStore = Reflux.createStore({
|
||||
}
|
||||
},
|
||||
|
||||
isClientError: function(error) {
|
||||
isClientError(error) {
|
||||
try {
|
||||
return error.status >= 400 &&
|
||||
error.status < 500 &&
|
||||
@ -60,7 +61,7 @@ var FeatureStore = Reflux.createStore({
|
||||
return false;
|
||||
},
|
||||
|
||||
getErrors: function() {
|
||||
getErrors() {
|
||||
return this.errors;
|
||||
}
|
||||
});
|
||||
|
@ -1,9 +1,10 @@
|
||||
var reqwest = require('reqwest');
|
||||
'use strict';
|
||||
const reqwest = require('reqwest');
|
||||
|
||||
var TYPE = 'json';
|
||||
const TYPE = 'json';
|
||||
|
||||
var EventStore = {
|
||||
getEvents: function () {
|
||||
const EventStore = {
|
||||
getEvents() {
|
||||
return reqwest({
|
||||
url: 'events',
|
||||
method: 'get',
|
||||
@ -11,9 +12,9 @@ var EventStore = {
|
||||
});
|
||||
},
|
||||
|
||||
getEventsByName: function (name) {
|
||||
getEventsByName(name) {
|
||||
return reqwest({
|
||||
url: 'events/' + name,
|
||||
url: `events/${name}`,
|
||||
method: 'get',
|
||||
type: TYPE
|
||||
});
|
||||
|
@ -1,73 +1,74 @@
|
||||
var Reflux = require("reflux");
|
||||
var Server = require('./FeatureToggleServerFacade');
|
||||
'use strict';
|
||||
const Reflux = require("reflux");
|
||||
const Server = require('./FeatureToggleServerFacade');
|
||||
|
||||
var FeatureToggleActions = Reflux.createActions({
|
||||
'init': { asyncResult: true },
|
||||
'initArchive': { asyncResult: true },
|
||||
'create': { asyncResult: true },
|
||||
'update': { asyncResult: true },
|
||||
'archive': { asyncResult: true },
|
||||
'revive': { asyncResult: true }
|
||||
const FeatureToggleActions = Reflux.createActions({
|
||||
init: { asyncResult: true },
|
||||
initArchive: { asyncResult: true },
|
||||
create: { asyncResult: true },
|
||||
update: { asyncResult: true },
|
||||
archive: { asyncResult: true },
|
||||
revive: { asyncResult: true }
|
||||
});
|
||||
|
||||
FeatureToggleActions.init.listen(function() {
|
||||
Server.getFeatures(function(error, features) {
|
||||
Server.getFeatures((error, features) => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(features);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
FeatureToggleActions.initArchive.listen(function() {
|
||||
Server.getArchivedFeatures(function(error, archivedToggles) {
|
||||
Server.getArchivedFeatures((error, archivedToggles) => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(archivedToggles);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
FeatureToggleActions.create.listen(function(feature) {
|
||||
Server.createFeature(feature, function(error) {
|
||||
Server.createFeature(feature, error => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
FeatureToggleActions.update.listen(function(feature) {
|
||||
Server.updateFeature(feature, function(error) {
|
||||
Server.updateFeature(feature, error => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
FeatureToggleActions.archive.listen(function(feature) {
|
||||
Server.archiveFeature(feature, function(error) {
|
||||
Server.archiveFeature(feature, error => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
FeatureToggleActions.revive.listen(function(feature) {
|
||||
Server.reviveFeature(feature, function(error) {
|
||||
Server.reviveFeature(feature, error => {
|
||||
if (error) {
|
||||
this.failed(error);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = FeatureToggleActions;
|
||||
|
@ -1,94 +1,95 @@
|
||||
var reqwest = require('reqwest');
|
||||
'use strict';
|
||||
const reqwest = require('reqwest');
|
||||
|
||||
var TYPE = 'json';
|
||||
var CONTENT_TYPE = 'application/json';
|
||||
const TYPE = 'json';
|
||||
const CONTENT_TYPE = 'application/json';
|
||||
|
||||
var FeatureToggleServerFacade = {
|
||||
updateFeature: function (feature, cb) {
|
||||
const FeatureToggleServerFacade = {
|
||||
updateFeature(feature, cb) {
|
||||
reqwest({
|
||||
url: 'features/' + feature.name,
|
||||
url: `features/${feature.name}`,
|
||||
method: 'put',
|
||||
type: TYPE,
|
||||
contentType: CONTENT_TYPE,
|
||||
data: JSON.stringify(feature),
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
createFeature: function (feature, cb) {
|
||||
createFeature(feature, cb) {
|
||||
reqwest({
|
||||
url: 'features',
|
||||
method: 'post',
|
||||
type: TYPE,
|
||||
contentType: CONTENT_TYPE,
|
||||
data: JSON.stringify(feature),
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
archiveFeature: function(feature, cb) {
|
||||
archiveFeature(feature, cb) {
|
||||
reqwest({
|
||||
url: 'features/' + feature.name,
|
||||
url: `features/${feature.name}`,
|
||||
method: 'delete',
|
||||
type: TYPE,
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getFeatures: function(cb) {
|
||||
getFeatures(cb) {
|
||||
reqwest({
|
||||
url: 'features',
|
||||
method: 'get',
|
||||
type: TYPE,
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function(data) {
|
||||
success(data) {
|
||||
cb(null, data.features);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getArchivedFeatures: function(cb) {
|
||||
getArchivedFeatures(cb) {
|
||||
reqwest({
|
||||
url: 'archive/features',
|
||||
method: 'get',
|
||||
type: TYPE,
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function(data) {
|
||||
success(data) {
|
||||
cb(null, data.features);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
reviveFeature: function (feature, cb) {
|
||||
reviveFeature(feature, cb) {
|
||||
reqwest({
|
||||
url: 'archive/revive',
|
||||
method: 'post',
|
||||
type: TYPE,
|
||||
contentType: CONTENT_TYPE,
|
||||
data: JSON.stringify(feature),
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
|
@ -1,15 +1,16 @@
|
||||
var Reflux = require('reflux');
|
||||
var FeatureActions = require('./FeatureToggleActions');
|
||||
var filter = require('lodash/collection/filter');
|
||||
var sortBy = require('lodash/collection/sortBy');
|
||||
var findIndex = require('lodash/array/findIndex');
|
||||
'use strict';
|
||||
const Reflux = require('reflux');
|
||||
const FeatureActions = require('./FeatureToggleActions');
|
||||
const filter = require('lodash/collection/filter');
|
||||
const sortBy = require('lodash/collection/sortBy');
|
||||
const findIndex = require('lodash/array/findIndex');
|
||||
|
||||
var _featureToggles = [];
|
||||
let _featureToggles = [];
|
||||
|
||||
var FeatureStore = Reflux.createStore({
|
||||
const FeatureStore = Reflux.createStore({
|
||||
|
||||
// Initial setup
|
||||
init: function() {
|
||||
init() {
|
||||
this.listenTo(FeatureActions.init.completed, this.setToggles);
|
||||
this.listenTo(FeatureActions.create.completed, this.onCreate);
|
||||
this.listenTo(FeatureActions.update.completed, this.onUpdate);
|
||||
@ -17,39 +18,37 @@ var FeatureStore = Reflux.createStore({
|
||||
this.listenTo(FeatureActions.revive.completed, this.onRevive);
|
||||
},
|
||||
|
||||
onCreate: function(feature) {
|
||||
onCreate(feature) {
|
||||
this.setToggles([feature].concat(_featureToggles));
|
||||
},
|
||||
|
||||
setToggles: function(toggles) {
|
||||
setToggles(toggles) {
|
||||
_featureToggles = sortBy(toggles, 'name');
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
onUpdate: function(feature) {
|
||||
var idx = findIndex(_featureToggles, 'name', feature.name);
|
||||
onUpdate(feature) {
|
||||
const idx = findIndex(_featureToggles, 'name', feature.name);
|
||||
_featureToggles[idx] = feature;
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
onArchive: function(feature) {
|
||||
var featureToggles = filter(_featureToggles, function(item) {
|
||||
return item.name !== feature.name;
|
||||
});
|
||||
onArchive(feature) {
|
||||
const featureToggles = filter(_featureToggles, item => item.name !== feature.name);
|
||||
this.setToggles(featureToggles);
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
onRevive: function(item) {
|
||||
onRevive(item) {
|
||||
this.setToggles(_featureToggles.concat([item]));
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
getFeatureToggles: function() {
|
||||
getFeatureToggles() {
|
||||
return _featureToggles;
|
||||
},
|
||||
|
||||
initStore: function(toggles) {
|
||||
initStore(toggles) {
|
||||
_featureToggles = toggles;
|
||||
}
|
||||
});
|
||||
|
@ -1,48 +1,49 @@
|
||||
var reqwest = require('reqwest');
|
||||
'use strict';
|
||||
const reqwest = require('reqwest');
|
||||
|
||||
var TYPE = 'json';
|
||||
var CONTENT_TYPE = 'application/json';
|
||||
const TYPE = 'json';
|
||||
const CONTENT_TYPE = 'application/json';
|
||||
|
||||
var StrategyAPI = {
|
||||
createStrategy: function (strategy, cb) {
|
||||
const StrategyAPI = {
|
||||
createStrategy(strategy, cb) {
|
||||
reqwest({
|
||||
url: 'strategies',
|
||||
method: 'post',
|
||||
type: TYPE,
|
||||
contentType: CONTENT_TYPE,
|
||||
data: JSON.stringify(strategy),
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb(null, strategy);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeStrategy: function (strategy, cb) {
|
||||
removeStrategy(strategy, cb) {
|
||||
reqwest({
|
||||
url: 'strategies/'+strategy.name,
|
||||
url: `strategies/${strategy.name}`,
|
||||
method: 'delete',
|
||||
type: TYPE,
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function() {
|
||||
success() {
|
||||
cb(null, strategy);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getStrategies: function (cb) {
|
||||
getStrategies(cb) {
|
||||
reqwest({
|
||||
url: 'strategies',
|
||||
method: 'get',
|
||||
type: TYPE,
|
||||
error: function(error) {
|
||||
error(error) {
|
||||
cb(error);
|
||||
},
|
||||
success: function(data) {
|
||||
success(data) {
|
||||
cb(null, data.strategies);
|
||||
}
|
||||
});
|
||||
|
@ -1,40 +1,41 @@
|
||||
var Reflux = require("reflux");
|
||||
var StrategyAPI = require('./StrategyAPI');
|
||||
'use strict';
|
||||
const Reflux = require("reflux");
|
||||
const StrategyAPI = require('./StrategyAPI');
|
||||
|
||||
var StrategyActions = Reflux.createActions({
|
||||
'init': { asyncResult: true },
|
||||
'create': { asyncResult: true },
|
||||
'remove': { asyncResult: true },
|
||||
const StrategyActions = Reflux.createActions({
|
||||
init: { asyncResult: true },
|
||||
create: { asyncResult: true },
|
||||
remove: { asyncResult: true },
|
||||
});
|
||||
|
||||
StrategyActions.init.listen(function() {
|
||||
StrategyAPI.getStrategies(function(err, strategies) {
|
||||
StrategyAPI.getStrategies((err, strategies) => {
|
||||
if (err) {
|
||||
this.failed(err);
|
||||
} else {
|
||||
this.completed(strategies);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
StrategyActions.create.listen(function(feature) {
|
||||
StrategyAPI.createStrategy(feature, function(err) {
|
||||
StrategyAPI.createStrategy(feature, err => {
|
||||
if (err) {
|
||||
this.failed(err);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
StrategyActions.remove.listen(function(feature) {
|
||||
StrategyAPI.removeStrategy(feature, function(err) {
|
||||
StrategyAPI.removeStrategy(feature, err => {
|
||||
if (err) {
|
||||
this.failed(err);
|
||||
} else {
|
||||
this.completed(feature);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = StrategyActions;
|
||||
|
@ -1,40 +1,39 @@
|
||||
var Reflux = require('reflux');
|
||||
var StrategyActions = require('./StrategyActions');
|
||||
var filter = require('lodash/collection/filter');
|
||||
'use strict';
|
||||
const Reflux = require('reflux');
|
||||
const StrategyActions = require('./StrategyActions');
|
||||
const filter = require('lodash/collection/filter');
|
||||
|
||||
var _strategies = [];
|
||||
let _strategies = [];
|
||||
|
||||
// Creates a DataStore
|
||||
var StrategyStore = Reflux.createStore({
|
||||
const StrategyStore = Reflux.createStore({
|
||||
|
||||
// Initial setup
|
||||
init: function() {
|
||||
init() {
|
||||
this.listenTo(StrategyActions.init.completed, this.setStrategies);
|
||||
this.listenTo(StrategyActions.create.completed, this.onCreate);
|
||||
this.listenTo(StrategyActions.remove.completed, this.onRemove);
|
||||
},
|
||||
|
||||
onCreate: function(strategy) {
|
||||
onCreate(strategy) {
|
||||
this.setStrategies(_strategies.concat([strategy]));
|
||||
},
|
||||
|
||||
onRemove: function(strategy) {
|
||||
var strategies = filter(_strategies, function(item) {
|
||||
return item.name !== strategy.name;
|
||||
});
|
||||
onRemove(strategy) {
|
||||
const strategies = filter(_strategies, item => item.name !== strategy.name);
|
||||
this.setStrategies(strategies);
|
||||
},
|
||||
|
||||
setStrategies: function(strategies) {
|
||||
setStrategies(strategies) {
|
||||
_strategies = strategies;
|
||||
this.trigger(_strategies);
|
||||
},
|
||||
|
||||
getStrategies: function() {
|
||||
getStrategies() {
|
||||
return _strategies;
|
||||
},
|
||||
|
||||
initStore: function(strategies) {
|
||||
initStore(strategies) {
|
||||
_strategies = strategies;
|
||||
}
|
||||
});
|
||||
|
@ -1,11 +1,12 @@
|
||||
var _username;
|
||||
'use strict';
|
||||
let _username;
|
||||
|
||||
// Ref: http://stackoverflow.com/questions/10730362/get-cookie-by-name
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
const nameEQ = `${name}=`;
|
||||
const ca = document.cookie.split(';');
|
||||
for (let i=0;i < ca.length;i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0)==' ') {
|
||||
c = c.substring(1, c.length);
|
||||
}
|
||||
@ -16,17 +17,17 @@ function readCookie(name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var UserStore = {
|
||||
init: function init() {
|
||||
const UserStore = {
|
||||
init() {
|
||||
_username = readCookie("username");
|
||||
},
|
||||
|
||||
set: function set(username) {
|
||||
set(username) {
|
||||
_username=username;
|
||||
document.cookie="username="+_username+"; expires=Thu, 18 Dec 2099 12:00:00 UTC";
|
||||
document.cookie=`username=${_username}; expires=Thu, 18 Dec 2099 12:00:00 UTC`;
|
||||
},
|
||||
|
||||
get: function get() {
|
||||
get() {
|
||||
return _username;
|
||||
}
|
||||
};
|
||||
|
@ -1,8 +1,9 @@
|
||||
var FeatureToggleActions = require('./FeatureToggleActions');
|
||||
var StrategyActions = require('./StrategyActions');
|
||||
var Timer = require('../utils/Timer');
|
||||
'use strict';
|
||||
const FeatureToggleActions = require('./FeatureToggleActions');
|
||||
const StrategyActions = require('./StrategyActions');
|
||||
const Timer = require('../utils/Timer');
|
||||
|
||||
var _timer;
|
||||
let _timer;
|
||||
|
||||
function load() {
|
||||
FeatureToggleActions.init.triggerPromise();
|
||||
@ -11,7 +12,7 @@ function load() {
|
||||
}
|
||||
|
||||
module.exports = function(pollInterval) {
|
||||
var intervall = pollInterval || 30;
|
||||
const intervall = pollInterval || 30;
|
||||
_timer = new Timer(load, intervall*1000);
|
||||
_timer.start();
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
var Timer = function(cb, interval) {
|
||||
'use strict';
|
||||
const Timer = function(cb, interval) {
|
||||
this.cb = cb;
|
||||
this.interval = interval;
|
||||
this.timerId = null;
|
||||
|
@ -1,8 +1,10 @@
|
||||
// docs: http://webpack.github.io/docs/configuration.html
|
||||
|
||||
var path = require('path');
|
||||
var root = path.normalize(path.join(__dirname, '.'));
|
||||
var jsroot = path.join(path.join(root, 'public'), 'js');
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const root = path.normalize(path.join(__dirname, '.'));
|
||||
const jsroot = path.join(path.join(root, 'public'), 'js');
|
||||
|
||||
module.exports = {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user