Added support for relative date ranges in segments

This commit is contained in:
Andris Reinman 2016-06-01 16:36:24 +03:00
parent 9bd6db2624
commit a229f80e22
11 changed files with 169 additions and 14 deletions

1
app.js
View file

@ -212,5 +212,4 @@ app.use((err, req, res, next) => {
}); });
}); });
module.exports = app; module.exports = app;

View file

@ -41,6 +41,7 @@ enabled=false
host="localhost" host="localhost"
port=6379 port=6379
db=5 db=5
# password=""
[verp] [verp]
enabled=false enabled=false

View file

@ -32,7 +32,6 @@ app.set('port', port);
let server = http.createServer(app); let server = http.createServer(app);
// Check if database needs upgrading before starting the server // Check if database needs upgrading before starting the server
dbcheck(err => { dbcheck(err => {
if (err) { if (err) {

View file

@ -140,7 +140,9 @@ module.exports.get = (id, callback) => {
case 'number': case 'number':
case 'date': case 'date':
case 'birthday': case 'birthday':
if (rule.value.range) { if (rule.value.relativeRange) {
rule.formatted = (rule.value.start ? rule.value.start + ' days ' + (rule.value.startDirection ? 'after' : 'before') + ' today' : 'today') + ' … ' + (rule.value.end ? rule.value.end + ' days ' + (rule.value.endDirection ? 'after' : 'before') + ' today' : 'today');
} else if (rule.value.range) {
rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || ''); rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || '');
} else { } else {
rule.formatted = rule.value.value || ''; rule.formatted = rule.value.value || '';
@ -294,7 +296,15 @@ module.exports.createRule = (segmentId, rule, callback) => {
case 'date': case 'date':
case 'birthday': case 'birthday':
case 'number': case 'number':
if (rule.range) { if (column.type === 'date' && rule.range === 'relative') {
value = {
relativeRange: true,
start: Number(rule.startRelative) || 0,
startDirection: Number(rule.startDirection) ? 1 : 0,
end: Number(rule.endRelative) || 0,
endDirection: Number(rule.endDirection) ? 1 : 0
};
} else if (rule.range === 'yes') {
value = { value = {
range: true, range: true,
start: rule.start, start: rule.start,
@ -389,7 +399,9 @@ module.exports.getRule = (id, callback) => {
case 'number': case 'number':
case 'date': case 'date':
case 'birthday': case 'birthday':
if (rule.value.range) { if (rule.value.relativeRange) {
rule.formatted = (rule.value.start ? rule.value.start + ' days ' + (rule.value.startDirection ? 'after' : 'before') + ' today' : 'today') + ' … ' + (rule.value.end ? rule.value.end + ' days ' + (rule.value.endDirection ? 'after' : 'before') + ' today' : 'today');
} else if (rule.value.range) {
rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || ''); rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || '');
} else { } else {
rule.formatted = rule.value.value || ''; rule.formatted = rule.value.value || '';
@ -445,7 +457,15 @@ module.exports.updateRule = (id, rule, callback) => {
case 'date': case 'date':
case 'birthday': case 'birthday':
case 'number': case 'number':
if (rule.range) { if (column.type === 'date' && rule.range === 'relative') {
value = {
relativeRange: true,
start: Number(rule.startRelative) || 0,
startDirection: Number(rule.startDirection) ? 1 : 0,
end: Number(rule.endRelative) || 0,
endDirection: Number(rule.endDirection) ? 1 : 0
};
} else if (rule.range === 'yes') {
value = { value = {
range: true, range: true,
start: rule.start, start: rule.start,
@ -527,6 +547,11 @@ module.exports.getQuery = (id, prefix, callback) => {
let query = []; let query = [];
let values = []; let values = [];
let getRelativeDate = (days, direction) => {
let date = new Date(Date.now() + (direction ? 1 : -1) * days * 24 * 3600 * 1000);
return date.toISOString().substr(0, 10);
};
let getDate = (value, nextDay) => { let getDate = (value, nextDay) => {
let parts = value.trim().split(/\D/); let parts = value.trim().split(/\D/);
let year = Number(parts.shift()) || 0; let year = Number(parts.shift()) || 0;
@ -579,7 +604,15 @@ module.exports.getQuery = (id, prefix, callback) => {
} }
break; break;
case 'date': case 'date':
if (rule.value.range) { if (rule.value.relativeRange) {
// start
query.push(prefix + '`' + rule.columnType.column + '` >= ?');
values.push(getDate(getRelativeDate(rule.value.start, rule.value.startDirection)));
// end
query.push(prefix + '`' + rule.columnType.column + '` < ?');
values.push(getDate(getRelativeDate(rule.value.end, rule.value.endDirection), true));
} else if (rule.value.range) {
if (rule.value.start) { if (rule.value.start) {
query.push(prefix + '`' + rule.columnType.column + '` >= ?'); query.push(prefix + '`' + rule.columnType.column + '` >= ?');
values.push(getDate(rule.value.start)); values.push(getDate(rule.value.start));

View file

@ -87,8 +87,10 @@ module.exports.authenticate = (username, password, callback) => {
if (!result) { if (!result) {
return callback(null, false); return callback(null, false);
} }
let user = tools.convertKeys(rows[0]);
return callback(null, { return callback(null, {
id: rows[0].id, id: user.id,
username username
}); });
}); });

14
public/css/mailtrain.css Normal file
View file

@ -0,0 +1,14 @@
.glyphicon.spinning {
animation: spin 1s infinite linear;
-webkit-animation: spin2 1s infinite linear;
}
@keyframes spin {
from { transform: scale(1) rotate(0deg); }
to { transform: scale(1) rotate(360deg); }
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}

View file

@ -263,7 +263,7 @@ router.post('/ajax', (req, res) => {
if (data.scheduled && data.scheduled > new Date()) { if (data.scheduled && data.scheduled > new Date()) {
return 'Scheduled'; return 'Scheduled';
} }
return 'Sending'; return '<span class="glyphicon glyphicon-refresh spinning"></span> Sending';
case 3: case 3:
return 'Finished'; return 'Finished';
case 4: case 4:

View file

@ -229,7 +229,7 @@
</button> </button>
</form> </form>
</div> </div>
<h4>Sending…</h4> <h4><span class="glyphicon glyphicon-refresh spinning"></span> Sending…</h4>
{{/if}} {{/if}}
{{/if}} {{/if}}

View file

@ -19,6 +19,7 @@
<link rel="stylesheet" href="/datepicker/css/bootstrap-datepicker3.css"> <link rel="stylesheet" href="/datepicker/css/bootstrap-datepicker3.css">
<link rel="stylesheet" href="/css/footer.css"> <link rel="stylesheet" href="/css/footer.css">
<link rel="stylesheet" href="/css/mailtrain.css">
{{#if useEditor}} {{#if useEditor}}
<link rel="stylesheet" href="/summernote/summernote.css"> <link rel="stylesheet" href="/summernote/summernote.css">

View file

@ -81,7 +81,7 @@
<label for="value" class="col-sm-2 control-label">Value</label> <label for="value" class="col-sm-2 control-label">Value</label>
<div class="col-sm-10 radio"> <div class="col-sm-10 radio">
<label> <label>
<input type="radio" name="range" value="" {{#unless value.range}} checked {{/unless}}> Use exact match <input type="radio" name="range" value="" {{#unless value.range}} {{#unless value.relativeRange}} checked {{/unless}} {{/unless}}> Use exact match
</label> </label>
</div> </div>
</div> </div>
@ -123,6 +123,59 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 radio">
<label>
<input type="radio" name="range" value="relative" {{#if value.relativeRange}} checked {{/if}}> Use relative range match
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 radio">
<div class="row">
<div class="col-md-1">
<p class="form-control-static">From</p>
</div>
<div class="col-md-4 form-inline">
<div class="input-group">
<input type="number" class="form-control" name="start-relative" placeholder="0" {{#if value.relativeRange}} value="{{value.start}}" {{/if}}>
<div class="input-group-addon">
days
<select name="start-direction">
<option value="0">
before today
</option>
<option value="1" {{#if value.startDirection}} selected {{/if}}>
after today
</option>
</select>
</div>
</div>
</div>
<div class="col-md-1">
<p class="form-control-static text-center">to</p>
</div>
<div class="col-md-4 form-inline">
<div class="input-group">
<input type="number" class="form-control" name="end-relative" placeholder="0" {{#if value.relativeRange}} value="{{value.end}}" {{/if}}>
<div class="input-group-addon">
days
<select name="end-direction">
<option value="0">
before today
</option>
<option value="1" {{#if value.endDirection}} selected {{/if}}>
after today
</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
{{/if}} {{/if}}
{{#if columnTypeBirthday}} {{#if columnTypeBirthday}}

View file

@ -86,7 +86,7 @@
<label for="value" class="col-sm-2 control-label">Value</label> <label for="value" class="col-sm-2 control-label">Value</label>
<div class="col-sm-10 radio"> <div class="col-sm-10 radio">
<label> <label>
<input type="radio" name="range" value="" {{#unless value.range}} checked {{/unless}}> Use exact match <input type="radio" name="range" value="" {{#unless value.range}} {{#unless value.relativeRange}} checked {{/unless}} {{/unless}}> Use exact match
</label> </label>
</div> </div>
</div> </div>
@ -114,7 +114,7 @@
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="input-group date fm-date-generic"> <div class="input-group date fm-date-generic">
<input type="text" class="form-control" name="start" placeholder="YYYY-MM-DD" value="{{value.start}}"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span> <input type="text" class="form-control" name="start" placeholder="YYYY-MM-DD" {{#if value.range}} value="{{value.start}}" {{/if}}><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
</div> </div>
</div> </div>
<div class="col-md-1"> <div class="col-md-1">
@ -122,7 +122,60 @@
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="input-group date fm-date-generic"> <div class="input-group date fm-date-generic">
<input type="text" class="form-control" name="end" placeholder="YYYY-MM-DD" value="{{value.end}}"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span> <input type="text" class="form-control" name="end" placeholder="YYYY-MM-DD" {{#if value.range}} value="{{value.end}}" {{/if}}><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 radio">
<label>
<input type="radio" name="range" value="relative" {{#if value.relativeRange}} checked {{/if}}> Use relative range match
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 radio">
<div class="row">
<div class="col-md-1">
<p class="form-control-static">From</p>
</div>
<div class="col-md-4 form-inline">
<div class="input-group">
<input type="number" class="form-control" name="start-relative" placeholder="0" {{#if value.relativeRange}} value="{{value.start}}" {{/if}}>
<div class="input-group-addon">
days
<select name="start-direction">
<option value="0">
before today
</option>
<option value="1" {{#if value.startDirection}} selected {{/if}}>
after today
</option>
</select>
</div>
</div>
</div>
<div class="col-md-1">
<p class="form-control-static text-center">to</p>
</div>
<div class="col-md-4 form-inline">
<div class="input-group">
<input type="number" class="form-control" name="end-relative" placeholder="0" {{#if value.relativeRange}} value="{{value.end}}" {{/if}}>
<div class="input-group-addon">
days
<select name="end-direction">
<option value="0">
before today
</option>
<option value="1" {{#if value.endDirection}} selected {{/if}}>
after today
</option>
</select>
</div>
</div> </div>
</div> </div>
</div> </div>