Intial Commit
This commit is contained in:
80
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrhumanizer.html
generated
vendored
Normal file
80
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrhumanizer.html
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
Copyright (c) 2018 Julian Knight (Totally Information)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- This creates and configures the onscreen elements of the node -->
|
||||
|
||||
|
||||
<!-- First, the content of the edit dialog is defined. -->
|
||||
<script type="text/x-red" data-template-name="humanizer">
|
||||
<!-- data-template-name identifies the node type this is for -->
|
||||
|
||||
<!-- INPUT -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-input"><i class="fa fa-arrow-left"></i> Input variable</label>
|
||||
<input type="text" id="node-input-input" style="width: 70%;" placeholder="varname in msg.payload or empty for all">
|
||||
</div>
|
||||
<!-- NODE NAME - Should always be the last field -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
|
||||
<div class="form-tips" style="font-size:83%">
|
||||
Specify which property on msg.payload to humanize or use msg.payload. <br />
|
||||
The input must be in seconds since the event so +10 is 10 seconds ago.<br />
|
||||
Only integer numbers are allowed.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Next, some simple help text is provided for the node. -->
|
||||
<!-- The first <p> is used as the pop-up tool tip when hovering over pallette -->
|
||||
<script type="text/x-red" data-help-name="humanizer">
|
||||
<p>
|
||||
Humanize timespans in seconds.
|
||||
</p>
|
||||
<p>
|
||||
Uses the humanize functionality in the moment.js library.
|
||||
</p>
|
||||
<p>
|
||||
Input must be in integer seconds.
|
||||
</p>
|
||||
<p>
|
||||
Contributed by <a href="https://github.com/Laro88">Laro88</a>
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<!-- Finally, the node type is registered along with all of its properties -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('humanizer',{
|
||||
category: 'formats', // the palette category
|
||||
color: '#E6E0F8',
|
||||
defaults: {
|
||||
name: {value:''},
|
||||
input: {value:''}
|
||||
},
|
||||
inputs:1, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: 'timer.png', // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||'Humanizer';
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?'node_label_italic':'';
|
||||
}
|
||||
}); // ---- end of RED.nodes.registerType ---- //
|
||||
</script>
|
||||
75
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrhumanizer.js
generated
vendored
Normal file
75
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrhumanizer.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) 2018 Julian Knight (Totally Information)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
// JK Note: This code contributed by (Contributed by Laro88, https://github.com/Laro88)
|
||||
// Tidying done by JK. Also removed dependency on validator which is vastly OTT for just ensuring an integer
|
||||
// 2017-04-13
|
||||
|
||||
// Node for Node-Red that humalizes a timespan msg.payload.[] //TODO whould this be extended to work on Date objects as well and if so how?
|
||||
// It is helpful when working with ui things that informs users of time since last operation etc.
|
||||
|
||||
// require moment.js (must be installed from package.js as a dependency)
|
||||
var moment = require('moment-timezone');
|
||||
|
||||
// Module name must match this nodes html file
|
||||
var moduleName = 'humanizer';
|
||||
|
||||
module.exports = function(RED) {
|
||||
'use strict';
|
||||
|
||||
// The main node definition - most things happen in here
|
||||
function nodeGo(config) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,config);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = config.topic;
|
||||
this.input = config.input || 'payload'; // where to take the input from
|
||||
|
||||
// copy "this" object in case we need it in context of callbacks of other functions.
|
||||
var node = this;
|
||||
|
||||
// respond to inputs....
|
||||
node.on('input', function (msg) {
|
||||
'use strict'; // We will be using eval() so lets get a bit of safety using strict
|
||||
|
||||
//console.log(this.input);
|
||||
var v = msg.payload.hasOwnProperty(this.input) ? msg.payload[this.input] : msg.payload;
|
||||
// JK: Replace validator with native JS INT check, improve warning message
|
||||
//v = v;
|
||||
//if( !validator.isInt(v) ) {
|
||||
if( ! Number.isInteger(v) ) {
|
||||
return node.warn('Invalid input for humanize call, input must be an integer');
|
||||
}
|
||||
|
||||
// JK: Pass seconds to duration - remove *1000 ms conversion
|
||||
var _humanized = moment.duration(v, 'seconds').humanize();
|
||||
if(typeof(msg.payload) == 'object'){
|
||||
msg.payload.humanized = _humanized;
|
||||
}
|
||||
else{
|
||||
msg.payload = {'humanized':_humanized};
|
||||
}
|
||||
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
} // ---- end of nodeGo function ---- //
|
||||
|
||||
// Register the node by name. This must be called before overriding any of the
|
||||
// Node functions.
|
||||
RED.nodes.registerType(moduleName,nodeGo);
|
||||
};
|
||||
290
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrmoment.html
generated
vendored
Normal file
290
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrmoment.html
generated
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
<!--
|
||||
Copyright (c) 2018 Julian Knight (Totally Information)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- This creates and configures the onscreen elements of the node -->
|
||||
|
||||
|
||||
<!-- First, the content of the edit dialog is defined. -->
|
||||
<script type="text/x-red" data-template-name="moment">
|
||||
<!-- data-template-name identifies the node type this is for -->
|
||||
|
||||
<!-- INPUT -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-input"><i class="fa fa-arrow-left"></i> Input from</label>
|
||||
<input type="text" id="node-input-input" style="width: 70%;" placeholder="payload">
|
||||
<input type="hidden" id="node-input-inputType">
|
||||
</div>
|
||||
<!-- INPUT TIMEZONE -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-inTz">Input Timezone</label>
|
||||
<input type="text" id="node-input-inTz" placeholder="[determined by system]" style="width:70%;">
|
||||
</div>
|
||||
<!-- ADJUSTMENT -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-adjAmount"> Adjustment</label>
|
||||
<select id="node-input-adjDir" style="width:4em">
|
||||
<option value="add">+</option>
|
||||
<option value="subtract">-</option>
|
||||
</select>
|
||||
<input type="text" id="node-input-adjAmount" placeholder="0" style="width:25%;">
|
||||
<select id="node-input-adjType" style="width:30%">
|
||||
<option value="days">Days</option>
|
||||
<option value="hours">Hours</option>
|
||||
<option value="weeks">Weeks</option>
|
||||
<option value="months">Months</option>
|
||||
<option value="quarters">Quarters</option>
|
||||
<option value="years">Years</option>
|
||||
<option value="minutes">Minutes</option>
|
||||
<option value="seconds">Seconds</option>
|
||||
<option value="milliseconds">Milliseconds</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- OUTPUT FORMAT -->
|
||||
<br />
|
||||
<div class="form-row">
|
||||
<label for="node-input-format"><i class="fa fa-eye-open"></i> Output Format</label>
|
||||
<input type="text" id="node-input-format" placeholder="ISO8601 (UTC)">
|
||||
</div>
|
||||
<!-- OUTPUT LOCALE -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-locale"><i class="fa fa-flag"></i> Locale</label>
|
||||
<input type="text" id="node-input-locale" placeholder="en">
|
||||
</div>
|
||||
<!-- OUTPUT TIMEZONE -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-outTz">Output Tz</label>
|
||||
<input type="text" id="node-input-outTz" placeholder="[determined by system]" style="width:70%;">
|
||||
</div>
|
||||
<!-- OUTPUT OBJECT -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-output"><i class="fa fa-arrow-right"></i> Output to</label>
|
||||
<input type="text" id="node-input-output" style="width: 70%;" placeholder="payload">
|
||||
<input type="hidden" id="node-input-outputType">
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<!-- TOPIC -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
</div>
|
||||
<!-- NODE NAME - Should always be the last field -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
|
||||
<div class="form-tips" style="font-size:83%">
|
||||
See the info sidebar for formatting details. <br />
|
||||
Use locale and format to change string output.<br />
|
||||
See the info sidebar for several warnings about inputting strings.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Next, some simple help text is provided for the node. -->
|
||||
<!-- The first <p> is used as the pop-up tool tip when hovering over pallette -->
|
||||
<script type="text/x-red" data-help-name="moment">
|
||||
<p>
|
||||
Convert date/time object or string to nicely formatted text or date/time object.
|
||||
</p>
|
||||
<p>
|
||||
Uses the moment.js library. Now updated to use moment-timezone.js for full timezone and DST handling.
|
||||
Also uses moment.parseFormat for string inputs and os-locale for output localisation.
|
||||
This version requires Node v6+.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="https://github.com/TotallyInformation/node-red-contrib-moment">readme file</a> for a change log.
|
||||
</p>
|
||||
|
||||
<h3>Input</h3>
|
||||
<p>
|
||||
If the input property does not exist or is left blank, the current date/time will be assumed.
|
||||
This can be used to add a current timestamp to a flow of any kind easily.
|
||||
</p>
|
||||
<p>Otherwise, the input is processed as follows:</p>
|
||||
<ul>
|
||||
<li>If input is "timestamp" or a JS datetime object or a <a href="http://momentjs.com/docs/#/parsing/">string that Moment.js</a> can resolve
|
||||
(with the help of <a href="https://github.com/gr2m/moment-parseformat">moment.parseFormat</a>). It will be processed as normal.</li>
|
||||
<li>If the input is null, is a blank string or a string that cannot be converted. The output will be an empty string.</li>
|
||||
</ul>
|
||||
|
||||
<h4>String input warnings</h4>
|
||||
<p>
|
||||
Note that parsing date/time strings is a hard problem. moment.parseFormat helps but it isn't magic.
|
||||
We assume that ambiguous input dates such as <code>3/5/05</code> are in EU/UK format <code>dd/mm/yy</code> <i>unless</i>
|
||||
either the input timezone is in <i>America</i> or the locale is set to <i>en_US</i>.
|
||||
</p>
|
||||
|
||||
<h3>Input Timezone</h3>
|
||||
<p>
|
||||
If blank, the node will try to guess. If you have set your host system to a local timezone (e.g. <code>dpkg-reconfigure tzdata</code> on Linux)
|
||||
then by default, input timestamps from the <code>inject</code> node will be in that timezone, otherwise they will be in UTC.
|
||||
You can override this by specifying the full timezone in the format <code>region/location</code>,
|
||||
e.g. <code>Europe/London</code>. Note that spellings are not validated, if it doesn't seem to work, check the valid timezone
|
||||
list built in to moment-timezone.
|
||||
</p>
|
||||
|
||||
<h3>Output</h3>
|
||||
<p>
|
||||
Is a formatted string if the output format is anything other than <code>date</code> or <code>object</code>
|
||||
in which case, the output is a Javascript date object or an object as described below respectively.
|
||||
</p>
|
||||
<p>
|
||||
Output string formatting is controlled by the Locale setting and the output format field.
|
||||
Note that the output Timezone is ignored for ISO8601 output (the default), such output is <i>always</i>
|
||||
in UTC. For other formats, the output will be in the specified timezone which defaults to your host timezone.
|
||||
</p>
|
||||
<p>
|
||||
Specifying different input and output timezones allows you to translated between them.
|
||||
</p>
|
||||
<p>
|
||||
The output msg will pass through the input msg.topic unless it is overridden. If the "Output to" field is changed
|
||||
from the default <code>msg.payload</code>, the input msg.payload will also be passed through.
|
||||
</p>
|
||||
|
||||
<h3>Output String Formatting</h3>
|
||||
<p>
|
||||
May be any <a href="http://momentjs.com/docs/#/displaying/format/">format string
|
||||
allowed by Moment.JS</a> (try <code>LLL</code> for a localised output for example).
|
||||
The formatting additions from moment-timezone are also allowed.<br>
|
||||
In addition, the following (not case sensitive, alternatives in brackets) format strings are also allowed:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>Blank (ISO8601, ISO)</dt>
|
||||
<dd>
|
||||
ISO 8602 format, e.g. "2015-01-28T16:24:48.123Z"<br>
|
||||
Note that ISO8601 formatted output is ALWAYS in UTC ('Z', Zulu time) not
|
||||
local, no matter what output timezone you may specify.
|
||||
</dd>
|
||||
<dt>date (jsDate)</dt>
|
||||
<dd>
|
||||
A Javascript Date object<br>
|
||||
This is the default if the input is a recognised date string
|
||||
</dd>
|
||||
<dt>object</dt>
|
||||
<dd>
|
||||
A Javascript object in the form <code>{years:nnnn, months:n, date:n, hours:n, minutes:n, seconds:n, milliseconds:n}</code>
|
||||
<br>
|
||||
<em>WARNING</em>: moment.js has a bizarre object format where the month is zero-based (0-11) instead of 1-based (1-12) like all the other elements are.
|
||||
I don't currently know why, I've raised an upstream issue but this appears to be a deliberate decision for some strange reason.
|
||||
</dd>
|
||||
<dt>fromNow (timeAgo)</dt>
|
||||
<dd>
|
||||
Human readable output<br />
|
||||
e.g. 30 minutes ago
|
||||
</dd>
|
||||
<dt>calendar (aroundNow)</dt>
|
||||
<dd>
|
||||
Human readable alternative<br />
|
||||
e.g. "Last Monday", "Tomorrow 2:30pm"<br />
|
||||
Note that dates beyond a week from now are output as yyyy-mm-dd
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
Note that with the exception of ISO8601, other formats are in the specified
|
||||
timezone & DST. If not specified, the output timezone/DST is the same as the input.<br />
|
||||
Use an output timezone of <code>UTC</code> to force output to that.
|
||||
</p>
|
||||
<p>
|
||||
If output is shown in the wrong format, such as dates in US mm/dd/yy format, change the
|
||||
output locale. For example, using <code>en_gb</code> will force short dates to output in
|
||||
dd/mm/yy format. The default is <code>en</code> which moment assumes means the USA :-(
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<!-- Finally, the node type is registered along with all of its properties -->
|
||||
<script type="text/javascript">
|
||||
function tzValidate(val) {
|
||||
// auto-correct the entry
|
||||
//$('#node-input-inTz').val( val.replace(/^GMT|UTC/i, 'ETC/GMT') )
|
||||
return true
|
||||
}
|
||||
|
||||
RED.nodes.registerType('moment',{
|
||||
category: 'formats', // the palette category
|
||||
color: '#E6E0F8',
|
||||
defaults: {
|
||||
name: {value:''},
|
||||
topic: {value:''},
|
||||
input: {value:''},
|
||||
inputType: {value:'msg'},
|
||||
inTz: {value:'', validate:tzValidate},
|
||||
adjAmount: {value:0, validate:RED.validators.number()},
|
||||
adjType: {value:'days'},
|
||||
adjDir: {value:'add'},
|
||||
format: {value:''},
|
||||
locale: {value:''},
|
||||
output: {value:''},
|
||||
outputType: {value:'msg'},
|
||||
outTz: {value:'', validate:tzValidate}
|
||||
},
|
||||
inputs:1, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: 'timer.png', // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||this.topic||'Date/Time Formatter';
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?'node_label_italic':'';
|
||||
},
|
||||
oneditprepare: function() {
|
||||
// Make sure we can reference parent this in async fns
|
||||
var _this = this
|
||||
|
||||
if (!this.inputType) {
|
||||
this.inputType = 'msg';
|
||||
}
|
||||
$('#node-input-input').typedInput({
|
||||
default: 'msg',
|
||||
types: ['msg','flow','global','date','str'],
|
||||
typeField: $('#node-input-inputType')
|
||||
});
|
||||
if (!this.outputType) {
|
||||
this.outputType = 'msg';
|
||||
}
|
||||
$('#node-input-output').typedInput({
|
||||
default: 'msg',
|
||||
types: ['msg','flow','global'],
|
||||
typeField: $('#node-input-outputType')
|
||||
});
|
||||
|
||||
// Get host locale and timezone
|
||||
$.getJSON('contribapi/moment',function(data) {
|
||||
// Save to parent object
|
||||
_this.localeData = data
|
||||
|
||||
if ( $('#node-input-inTz').val() === '' ) $('#node-input-inTz').val(data.tz);
|
||||
if ( $('#node-input-outTz').val() === '' ) $('#node-input-outTz').val(data.tz);
|
||||
if ( $('#node-input-locale').val() === '' ) $('#node-input-locale').val(data.locale);
|
||||
});
|
||||
|
||||
// Autocorrect timezone entries
|
||||
$('#node-input-inTz').add('#node-input-outTz').blur( function(){
|
||||
if( this.value === '' ) {
|
||||
// Use saved locale data from parent object as default
|
||||
this.value = _this.localeData.tz
|
||||
} else {
|
||||
// autocorrect common tz errors
|
||||
this.value = this.value.replace(/^GMT|UTC/i, 'ETC/GMT')
|
||||
}
|
||||
})
|
||||
|
||||
} // --- end of oneditprepare --- //
|
||||
}); // ---- end of RED.nodes.registerType ---- //
|
||||
</script>
|
||||
311
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrmoment.js
generated
vendored
Normal file
311
nodered/rootfs/data/node_modules/node-red-contrib-moment/moment/nrmoment.js
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* Copyright (c) 2018 Julian Knight (Totally Information)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
// Node for Node-Red that outputs a nicely formatted string from a date/time
|
||||
// object or string using the moment.js library.
|
||||
|
||||
// require moment.js (must be installed from package.js as a dependency)
|
||||
var moment = require('moment-timezone');
|
||||
var parseFormat = require('moment-parseformat');
|
||||
var osLocale = require('os-locale');
|
||||
var hostTz = moment.tz.guess();
|
||||
var hostLocale = osLocale.sync();
|
||||
|
||||
|
||||
// Module name must match this nodes html file
|
||||
var moduleName = 'moment';
|
||||
|
||||
module.exports = function(RED) {
|
||||
'use strict';
|
||||
|
||||
// The main node definition - most things happen in here
|
||||
function nodeGo(config) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,config);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = config.topic;
|
||||
this.input = config.input || 'payload'; // where to take the input from
|
||||
this.inputType = config.inputType || 'msg'; // msg, flow, global, timestamp or string
|
||||
this.fakeUTC = config.fakeUTC || false; // is the input UTC rather than local date/time?
|
||||
this.adjAmount = config.adjAmount || 0; // number
|
||||
this.adjType = config.adjType || 'days'; // days, hours, etc.
|
||||
this.adjDir = config.adjDir || 'add'; // add or subtract
|
||||
this.format = config.format || ''; // valid moment.js format string
|
||||
this.locale = config.locale || false // valid moment.js locale string
|
||||
this.output = config.output || 'payload'; // where to put the output
|
||||
this.outputType = config.outputType || 'msg'; // msg, flow or global
|
||||
this.inTz = config.inTz || false; // timezone, '' or zone name, e.g. Europe/London
|
||||
this.outTz = config.outTz || this.inTz; // timezone, '' or zone name, e.g. Europe/London
|
||||
|
||||
// copy "this" object in case we need it in context of callbacks of other functions.
|
||||
var node = this;
|
||||
|
||||
// respond to inputs....
|
||||
node.on('input', function (msg) {
|
||||
'use strict'; // We will be using eval() so lets get a bit of safety using strict
|
||||
|
||||
// If the node's topic is set, copy to output msg
|
||||
if ( node.topic !== '' ) {
|
||||
msg.topic = node.topic;
|
||||
} // If nodes topic is blank, the input msg.topic is already there
|
||||
|
||||
// make sure output property is set, if not, assume msg.payload
|
||||
if ( node.output === '' ) {
|
||||
node.output = 'payload';
|
||||
//node.warn('Output field is REQUIRED, currently blank, set to payload');
|
||||
}
|
||||
if ( node.outputType === '' ) {
|
||||
node.outputType = 'msg';
|
||||
node.warn('Output Type field is REQUIRED, currently blank, set to msg');
|
||||
}
|
||||
|
||||
// If the input property is blank, assume NOW as the required timestamp
|
||||
// or make sure that the node's input property actually exists on the input msg
|
||||
var inp = '';
|
||||
// If input is a blank string, use a Date object with Now DT
|
||||
if ( node.input === '' ) {
|
||||
inp = new Date();
|
||||
} else {
|
||||
// Otherwise, check which input type & get the input
|
||||
try {
|
||||
switch ( node.inputType ) {
|
||||
case 'msg':
|
||||
inp = RED.util.getMessageProperty(msg, node.input);
|
||||
break;
|
||||
case 'flow':
|
||||
inp = node.context().flow.get(node.input);
|
||||
break;
|
||||
case 'global':
|
||||
inp = node.context().global.get(node.input);
|
||||
break;
|
||||
case 'date':
|
||||
inp = new Date();
|
||||
break;
|
||||
case 'str':
|
||||
inp = node.input.trim();
|
||||
break;
|
||||
default:
|
||||
inp = new Date();
|
||||
node.warn('Unrecognised Input Type, ' + node.inputType + '. Output has been set to NOW.');
|
||||
}
|
||||
} catch (err) {
|
||||
inp = new Date();
|
||||
node.warn('Input property, ' + node.inputType + '.' + node.input + ', does NOT exist. Output has been set to NOW.');
|
||||
}
|
||||
}
|
||||
// We are going to overwrite the output property without warning or permission!
|
||||
|
||||
// Final check for input being a string (which moment doesn't really want to handle)
|
||||
// NB: moment.js v3 will stop accepting strings. v2.7+ throws a warning.
|
||||
var dtHack = '', inpFmt = '';
|
||||
// @from v3 2018-09-23: If input is `null`, change to empty string
|
||||
if ( inp === null ) inp = '';
|
||||
if ( (typeof inp) === 'string' ) {
|
||||
inp = inp.trim();
|
||||
// Some string input hacks
|
||||
switch (inp.toLowerCase()) {
|
||||
case 'today':
|
||||
inp = new Date();
|
||||
break;
|
||||
case 'yesterday':
|
||||
inp = new Date();
|
||||
dtHack = {days:-1};
|
||||
break;
|
||||
case 'tomorrow':
|
||||
inp = new Date();
|
||||
dtHack = {days:+1};
|
||||
break;
|
||||
default:
|
||||
var prefOrder = {preferredOrder: {'/': 'DMY', '.': 'DMY', '-': 'YMD'} };
|
||||
if ( (node.locale.toLowerCase().replace('-','_') === 'en_US') || (node.inTz.split('/')[0] === 'America') ) {
|
||||
prefOrder = {preferredOrder: {'/': 'MDY', '.': 'DMY', '-': 'YMD'} };
|
||||
}
|
||||
inpFmt = parseFormat(inp, prefOrder);
|
||||
}
|
||||
} else if ( (typeof inp) === 'number' ) {
|
||||
// @from 2017-06-15 IF inp is a number at this point, it needs turning into a date object
|
||||
inp = new Date(inp)
|
||||
}
|
||||
|
||||
// At this point, `inp` SHOULD be a Date object and safe to pass to moment.js
|
||||
|
||||
if ( !node.inTz ) { node.inTz = hostTz; }
|
||||
if ( !node.outTz ) { node.outTz = node.inTz; }
|
||||
// Validate input and output timezones - @since 2.0.4
|
||||
if ( moment.tz.zone(node.inTz) === null ) {
|
||||
// tz invalid, warn and set to UTC
|
||||
node.warn('Moment: Input Timezone Invalid, reset to UTC - see http://momentjs.com/timezone/docs/#/data-loading/')
|
||||
node.inTz = 'UTC'
|
||||
}
|
||||
if ( moment.tz.zone(node.outTz) === null ) {
|
||||
// tz invalid, warn and set to UTC
|
||||
node.warn('Moment: Output Timezone Invalid, reset to UTC - see http://momentjs.com/timezone/docs/#/data-loading/')
|
||||
node.outTz = 'UTC'
|
||||
}
|
||||
|
||||
// Get a Moment.JS date/time - NB: the result might not be
|
||||
// valid since the input might not parse as a date/time
|
||||
var mDT;
|
||||
if ( inpFmt !== '' ) {
|
||||
mDT = moment.tz(inp, inpFmt, true, node.inTz);
|
||||
} else {
|
||||
// @from 2017-06-15 change to momentjs meant having to add null parameter
|
||||
mDT = moment.tz(inp, null, true, node.inTz)
|
||||
}
|
||||
|
||||
// Fallback to JS built-in Date parsing, if not recognized by moment
|
||||
if (!mDT.isValid()) {
|
||||
var dtm = new Date(inp);
|
||||
if (dtm === 'Invalid Date') {
|
||||
node.warn('Unrecognized date string format => ' + inp);
|
||||
}
|
||||
else {
|
||||
mDT = moment(dtm);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the date for input hacks if needed (e.g. input was "yesterday" or "tommorow")
|
||||
if ( dtHack !== '' ) { mDT.add(dtHack); }
|
||||
|
||||
// JK: Added OS locale lookup
|
||||
if ( !node.locale ) { node.locale = hostLocale; }
|
||||
// JK: Add a trap to Jaques44's locale code in case the output locale string is invalid
|
||||
try {
|
||||
// Jacques44 - set locale for localised output formats
|
||||
mDT.locale(node.locale);
|
||||
} catch (err) {
|
||||
node.warn('Locale string invalid - check moment.js for valid strings');
|
||||
}
|
||||
|
||||
// Adjust the input date if required
|
||||
if ( node.adjAmount !== 0 ) {
|
||||
// check if measure is valid
|
||||
if ( isMeasureValid(node.adjType) ) {
|
||||
// NB: moments are mutable so don't need to reassign
|
||||
if ( node.adjDir === 'subtract') {
|
||||
mDT.subtract(node.adjAmount, node.adjType);
|
||||
} else {
|
||||
mDT.add(node.adjAmount, node.adjType);
|
||||
}
|
||||
} else {
|
||||
// it isn't valid so warn and don't adjust
|
||||
node.warn('Adjustment measure type not valid, no adjustment made - check moment.js docs for valid measures (days, hours, etc)');
|
||||
}
|
||||
}
|
||||
|
||||
// ==== NO MORE DATE/TIME CALCULATIONS AFTER HERE ==== //
|
||||
|
||||
// If required, change to the output Timezone
|
||||
if ( node.outTz !== '' ) mDT.tz(node.outTz);
|
||||
|
||||
// Check if the input is a date?
|
||||
if ( ! mDT.isValid() ) {
|
||||
// THIS SHOULD NEVER BE CALLED - it left to catch the occasional error
|
||||
node.warn('The input property was NOT a recognisable date. Output will be a blank string');
|
||||
setOutput(msg, node.outputType, node.output, '');
|
||||
} else {
|
||||
// Handle different format strings. We allow any fmt str that
|
||||
// Moment.JS supports but also some special formats
|
||||
|
||||
// If format not set, assume ISO8601 string if input is a Date otherwise assume Date
|
||||
switch ( node.format.toLowerCase() ) {
|
||||
case '':
|
||||
case 'iso8601':
|
||||
case 'iso':
|
||||
// Default to ISO8601 string
|
||||
setOutput(msg, node.outputType, node.output, mDT.toISOString());
|
||||
break;
|
||||
case 'fromnow':
|
||||
case 'timeago':
|
||||
// We are also going to handle time-from-now (AKA time ago) format
|
||||
setOutput(msg, node.outputType, node.output, mDT.fromNow());
|
||||
break;
|
||||
case 'calendar':
|
||||
case 'aroundnow':
|
||||
// We are also going to handle calendar format (AKA around now)
|
||||
// Force dates >1 week from now to be in ISO instead of US format
|
||||
setOutput(msg, node.outputType, node.output, mDT.calendar(null,{sameElse:'YYYY-MM-DD'}));
|
||||
break;
|
||||
case 'date':
|
||||
case 'jsdate':
|
||||
// we also allow output as a Javascript Date object
|
||||
setOutput(msg, node.outputType, node.output, mDT.toDate());
|
||||
break;
|
||||
case 'object':
|
||||
// we also allow output as a Javascript Date object
|
||||
setOutput(msg, node.outputType, node.output, mDT.toObject());
|
||||
break;
|
||||
default:
|
||||
// or we assume it is a valid format definition ...
|
||||
setOutput(msg, node.outputType, node.output, mDT.format(node.format));
|
||||
}
|
||||
}
|
||||
|
||||
// Send the output message
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
// Tidy up if we need to
|
||||
//node.on('close', function() {
|
||||
// Called when the node is shutdown - eg on redeploy.
|
||||
// Allows ports to be closed, connections dropped etc.
|
||||
// eg: node.client.disconnect();
|
||||
//});
|
||||
|
||||
// Set the appropriate output variable
|
||||
function setOutput(msg, outputType, output, value) {
|
||||
try {
|
||||
switch ( outputType ) {
|
||||
case 'msg':
|
||||
RED.util.setMessageProperty(msg, output, value);
|
||||
break;
|
||||
case 'flow':
|
||||
node.context().flow.set(output, value);
|
||||
break;
|
||||
case 'global':
|
||||
node.context().global.set(output, value);
|
||||
break;
|
||||
default:
|
||||
node.warn('Unrecognised Output Type, ' + outputType + '. No output.');
|
||||
}
|
||||
} catch (err) {
|
||||
node.warn('Output property, ' + outputType + '.' + output + ', cannot be set. No output.', err);
|
||||
}
|
||||
} // --- end of setOutput function --- //
|
||||
|
||||
// Is the date/time adjustment type (measure) valid? See moment.js docs
|
||||
function isMeasureValid(adjType) {
|
||||
var validTypes = ['years','y','quarters','Q','months','M','weeks','w','days','d','hours','h','minutes','m','seconds','s','milliseconds','ms'];
|
||||
//return validTypes.includes(adjType);
|
||||
return validTypes.indexOf(adjType) > -1;
|
||||
} // --- end of isMeasureValid function --- //
|
||||
|
||||
} // ---- end of nodeGo function ---- //
|
||||
|
||||
// Register the node by name. This must be called before overriding any of the
|
||||
// Node functions.
|
||||
RED.nodes.registerType(moduleName,nodeGo);
|
||||
|
||||
// Create API listener: sends the host locale & timezone to the admin ui
|
||||
// NB: uses Express middleware on the admin server
|
||||
RED.httpAdmin.get('/contribapi/moment', RED.auth.needsPermission('moment.read'), function(req,res) {
|
||||
res.json({
|
||||
'tz': hostTz,
|
||||
'locale': hostLocale
|
||||
});
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user