Added support for relative date ranges in segments
This commit is contained in:
parent
9bd6db2624
commit
a229f80e22
11 changed files with 169 additions and 14 deletions
1
app.js
1
app.js
|
@ -212,5 +212,4 @@ app.use((err, req, res, next) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|
|
@ -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
|
||||||
|
|
1
index.js
1
index.js
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
14
public/css/mailtrain.css
Normal 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); }
|
||||||
|
}
|
|
@ -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:
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue