Initial commit

This commit is contained in:
zhongjin 2018-09-28 09:23:52 +08:00
commit b3cecc2d9b
19 changed files with 4055 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/node_modules
.idea

7
.npmignore Normal file
View File

@ -0,0 +1,7 @@
Gruntfile.js
tasks
node_modules
widgets/history/lib/js/jquery.sparkline.js
test
.travis.yml
appveyor.yml

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
os:
- linux
language: node_js
node_js:
- '4'
- '8'
- '10'

193
Gruntfile.js Normal file
View File

@ -0,0 +1,193 @@
// To use this file in WebStorm, right click on the file name in the Project Panel (normally left) and select "Open Grunt Console"
/** @namespace __dirname */
/* jshint -W097 */// jshint strict:false
/*jslint node: true */
"use strict";
function getAppName() {
var parts = __dirname.replace(/\\/g, '/').split('/');
return parts[parts.length - 1].split('.')[0].toLowerCase();
}
module.exports = function (grunt) {
var srcDir = __dirname + '/';
var pkg = grunt.file.readJSON('package.json');
var iopackage = grunt.file.readJSON('io-package.json');
var version = (pkg && pkg.version) ? pkg.version : iopackage.common.version;
var appName = getAppName();
// Project configuration.
grunt.initConfig({
pkg: pkg,
replace: {
core: {
options: {
patterns: [
{
match: /var version = *'[\.0-9]*';/g,
replacement: "var version = '" + version + "';"
},
{
match: /"version"\: *"[\.0-9]*",/g,
replacement: '"version": "' + version + '",'
}
]
},
files: [
{
expand: true,
flatten: true,
src: [
srcDir + 'controller.js',
srcDir + 'package.json',
srcDir + 'io-package.json'
],
dest: srcDir
}
]
},
name: {
options: {
patterns: [
{
match: /yunkong2/gi,
replacement: appName
}
]
},
files: [
{
expand: true,
flatten: true,
src: [
srcDir + '*.*',
srcDir + '.travis.yml'
],
dest: srcDir
},
{
expand: true,
flatten: true,
src: [
srcDir + 'admin/*.*',
'!' + srcDir + 'admin/*.png'
],
dest: srcDir + 'admin'
},
{
expand: true,
flatten: true,
src: [
srcDir + 'lib/*.*'
],
dest: srcDir + 'lib'
},
{
expand: true,
flatten: true,
src: [
srcDir + 'example/*.*'
],
dest: srcDir + 'example'
},
{
expand: true,
flatten: true,
src: [
srcDir + 'www/*.*'
],
dest: srcDir + 'www'
}
]
}
},
// Javascript code styler
jscs: require(__dirname + '/tasks/jscs.js'),
// Lint
jshint: require(__dirname + '/tasks/jshint.js'),
http: {
get_hjscs: {
options: {
url: 'https://raw.githubusercontent.com/' + appName + '/' + appName + '.js-controller/master/tasks/jscs.js'
},
dest: 'tasks/jscs.js'
},
get_jshint: {
options: {
url: 'https://raw.githubusercontent.com/' + appName + '/' + appName + '.js-controller/master/tasks/jshint.js'
},
dest: 'tasks/jshint.js'
},
get_gruntfile: {
options: {
url: 'https://raw.githubusercontent.com/' + appName + '/' + appName + '.build/master/adapters/Gruntfile.js'
},
dest: 'Gruntfile.js'
},
get_utilsfile: {
options: {
url: 'https://raw.githubusercontent.com/' + appName + '/' + appName + '.build/master/adapters/utils.js'
},
dest: 'lib/utils.js'
},
get_jscsRules: {
options: {
url: 'https://raw.githubusercontent.com/' + appName + '/' + appName + '.js-controller/master/tasks/jscsRules.js'
},
dest: 'tasks/jscsRules.js'
}
}
});
grunt.registerTask('updateReadme', function () {
var readme = grunt.file.read('README.md');
var pos = readme.indexOf('## Changelog\n');
if (pos != -1) {
var readmeStart = readme.substring(0, pos + '## Changelog\n'.length);
var readmeEnd = readme.substring(pos + '## Changelog\n'.length);
if (readme.indexOf(version) == -1) {
var timestamp = new Date();
var date = timestamp.getFullYear() + '-' +
('0' + (timestamp.getMonth() + 1).toString(10)).slice(-2) + '-' +
('0' + (timestamp.getDate()).toString(10)).slice(-2);
var news = "";
if (iopackage.common.whatsNew) {
for (var i = 0; i < iopackage.common.whatsNew.length; i++) {
if (typeof iopackage.common.whatsNew[i] == 'string') {
news += '* ' + iopackage.common.whatsNew[i] + '\n';
} else {
news += '* ' + iopackage.common.whatsNew[i].en + '\n';
}
}
}
grunt.file.write('README.md', readmeStart + '### ' + version + ' (' + date + ')\n' + (news ? news + '\n\n' : '\n') + readmeEnd);
}
}
});
grunt.loadNpmTasks('grunt-replace');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-jscs');
grunt.loadNpmTasks('grunt-http');
grunt.registerTask('default', [
'http',
'replace:core',
'updateReadme',
'jshint',
'jscs'
]);
grunt.registerTask('p', [
'replace:core',
'updateReadme'
]);
grunt.registerTask('rename', [
'replace:name'
]);
};

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
BSD 3-Clause License
Copyright (c) 2016-2017, bluefox <dogafox@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
README.md Normal file
View File

@ -0,0 +1,53 @@
![Logo](admin/vis-history.png)
yunkong2.vis-history
============
[![NPM version](http://img.shields.io/npm/v/yunkong2.vis-history.svg)](https://www.npmjs.com/package/yunkong2.vis-history)
[![Downloads](https://img.shields.io/npm/dm/yunkong2.vis-history.svg)](https://www.npmjs.com/package/yunkong2.vis-history)
[![NPM](https://nodei.co/npm/yunkong2.vis-history.png?downloads=true)](https://nodei.co/npm/yunkong2.vis-history/)
![Screenshot](img/widgets.png)
Widgets, that can work with history data. Of course for that is some of the History Adapters are required: sql, history or influx (or something else).
Sparklines can be shown only for non-binary data, because of aggregation.
For sparklines is used the [jquery plugin](http://omnipotent.net/jquery.sparkline/), that was written by Gareth Watts and released under the New BSD License.
## Changelog
### 0.2.7 (2017-05-29)
- (Apollon77) small fixes on Title (http://forum.yunkong2.net/viewtopic.php?f=23&t=3111&start=20#p68971) and getHistory parameters
### 0.2.6 (2017-03-02)
- (bluefox) small fix for empty values
### 0.2.5 (2017-01-13)
- (bluefox) make http links "clickable" in the list
### 0.2.4 (2016-10-09)
- (bluefox) support of new custom schema
### 0.2.3 (2016-09-22)
- (bluefox) fixed JS error
### 0.2.2 (2016-08-22)
- (bluefox) add units and suffix
### 0.2.1 (2016-07-09)
- (bluefox) typo
### 0.2.0 (2016-07-09)
- (bluefox) fix max line settings
- (bluefox) add 'none' time selector
### 0.1.1 (2016-06-13)
- (bluefox) change default style to vis-style-green-gray
### 0.1.0 (2016-06-13)
- (bluefox) initial checkin
## License
Copyright (c) 2016 bluefox
BSD-3-Clause

BIN
admin/vis-history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/widgets.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

96
io-package.json Normal file
View File

@ -0,0 +1,96 @@
{
"common": {
"name": "vis-history",
"version": "0.2.7",
"title": "yunkong2 Visualisation - history Widgets",
"news": {
"0.2.7": {
"en": "small fixes",
"de": "Kleine Fixes",
"ru": "small fixes"
},
"0.2.6": {
"en": "small fix for empty values",
"de": "Kleines Fix für null Werte",
"ru": "Патч для null значений"
},
"0.2.5": {
"en": "make http links clickable in the list",
"de": "Erlaube http links als Werte",
"ru": "Возможность иметь HTTP линки, как значения"
},
"0.2.4": {
"en": "support of new custom schema",
"de": "Unterstützung von Custom-Schema",
"ru": "Поддержка новой Custom-cхемы"
},
"0.2.3": {
"en": "fix JS error",
"de": "JS Fehler korrigiert",
"ru": "Исправлена JS ошибка"
},
"0.2.2": {
"en": "add units and suffix",
"de": "add units and suffix",
"ru": "add units and suffix"
},
"0.2.1": {
"en": "fix typo",
"de": "fix typo",
"ru": "fix typo"
},
"0.2.0": {
"en": "fix max line settings\nadd 'none' time selector",
"de": "fix max line settings\nadd 'none' time selector",
"ru": "fix max line settings\nadd 'none' time selector"
},
"0.1.1": {
"en": "change default style to vis-style-green-gray",
"de": "change default style to vis-style-green-gray",
"ru": "change default style to vis-style-green-gray"
},
"0.1.0": {
"en": "initial commit",
"de": "initial commit",
"ru": "initial commit"
}
},
"desc": {
"en": "history Widgets for yunkong2.vis",
"de": "history Widgets für yunkong2.vis",
"ru": "history Widgets для yunkong2.vis"
},
"platform": "Javascript/Node.js",
"icon": "vis-history.png",
"enabled": true,
"mode": "once",
"extIcon": "https://raw.githubusercontent.com/yunkong2/yunkong2.vis-history/master/admin/vis-history.png",
"keywords": [
"history",
"vis",
"GUI",
"graphical",
"scada"
],
"readme": "https://git.spacen.net/yunkong2/yunkong2.vis-history/blob/master/README.md",
"authors": [
"Pmant <patrickmo@gmx.de>"
],
"localLink": "%web_protocol%://%ip%:%web_port%/vis/edit.html",
"license": "BSD-3-Clause",
"dependencies": [
"vis"
],
"onlyWWW": true,
"singleton": true,
"type": "visualization-widgets",
"noConfig": true,
"restartAdapters": [
"vis"
]
},
"native": {
"dependencies": []
},
"instanceObjects": []
}

45
package.json Normal file
View File

@ -0,0 +1,45 @@
{
"name": "yunkong2.vis-history",
"description": "history Widgets for yunkong2.vis",
"version": "0.2.7",
"author": {
"name": "bluefox",
"email": "dogafox@gmail.com"
},
"contributors": [
"bluefox <dogafox@gmail.com>"
],
"homepage": "https://git.spacen.net/yunkong2/yunkong2.vis-history",
"repository": {
"type": "git",
"url": "https://git.spacen.net/yunkong2/yunkong2.vis-history"
},
"licenses": [
{
"type": "BSD-3-Clause",
"url": "https://git.spacen.net/yunkong2/yunkong2.vis-history/blob/master/LICENSE"
}
],
"keywords": [
"yunkong2",
"GUI",
"history"
],
"devDependencies": {
"grunt": "^1.0.1",
"grunt-replace": "^1.0.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-jscs": "^3.0.1",
"grunt-http": "^2.2.0",
"mocha": "^4.1.0",
"chai": "^4.1.2"
},
"bugs": {
"url": "https://git.spacen.net/yunkong2/yunkong2.vis-history/issues"
},
"main": "widgets/history.html",
"scripts": {
"test": "node node_modules/mocha/bin/mocha --exit"
},
"license": "MIT"
}

17
tasks/jscs.js Normal file
View File

@ -0,0 +1,17 @@
var srcDir = __dirname + "/../";
module.exports = {
all: {
src: [
srcDir + "*.js",
srcDir + "lib/*.js",
srcDir + "adapter/example/*.js",
srcDir + "tasks/**/*.js",
srcDir + "www/**/*.js",
'!' + srcDir + "www/lib/**/*.js",
'!' + srcDir + 'node_modules/**/*.js',
'!' + srcDir + 'adapter/*/node_modules/**/*.js'
],
options: require('./jscsRules.js')
}
};

36
tasks/jscsRules.js Normal file
View File

@ -0,0 +1,36 @@
module.exports = {
force: true,
"requireCurlyBraces": ["else", "for", "while", "do", "try", "catch"], /*"if",*/
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"requireSpaceBeforeBlockStatements": true,
"requireParenthesesAroundIIFE": true,
"disallowSpacesInFunctionDeclaration": {"beforeOpeningRoundBrace": true},
"disallowSpacesInNamedFunctionExpression": {"beforeOpeningRoundBrace": true},
"requireSpacesInFunctionExpression": {"beforeOpeningCurlyBrace": true},
"requireSpacesInAnonymousFunctionExpression": {"beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true},
"requireSpacesInNamedFunctionExpression": {"beforeOpeningCurlyBrace": true},
"requireSpacesInFunctionDeclaration": {"beforeOpeningCurlyBrace": true},
"disallowMultipleVarDecl": true,
"requireBlocksOnNewline": true,
"disallowEmptyBlocks": true,
"disallowSpacesInsideObjectBrackets": true,
"disallowSpacesInsideArrayBrackets": true,
"disallowSpaceAfterObjectKeys": true,
"disallowSpacesInsideParentheses": true,
"requireCommaBeforeLineBreak": true,
//"requireAlignedObjectValues": "all",
"requireOperatorBeforeLineBreak": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
// "disallowLeftStickedOperators": ["?", "+", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
// "requireRightStickedOperators": ["!"],
// "requireSpaceAfterBinaryOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
//"disallowSpaceAfterBinaryOperators": [","],
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"requireSpaceAfterBinaryOperators": ["?", ">", ",", ">=", "<=", "<", "+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
//"validateIndentation": 4,
//"validateQuoteMarks": { "mark": "\"", "escape": true },
"disallowMixedSpacesAndTabs": true,
"disallowKeywordsOnNewLine": ["else", "catch"]
};

17
tasks/jshint.js Normal file
View File

@ -0,0 +1,17 @@
var srcDir = __dirname + "/../";
module.exports = {
options: {
force: true
},
all: [
srcDir + "*.js",
srcDir + "lib/*.js",
srcDir + "adapter/example/*.js",
srcDir + "tasks/**/*.js",
srcDir + "www/**/*.js",
'!' + srcDir + "www/lib/**/*.js",
'!' + srcDir + 'node_modules/**/*.js',
'!' + srcDir + 'adapter/*/node_modules/**/*.js'
]
};

91
test/testPackageFiles.js Normal file
View File

@ -0,0 +1,91 @@
/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs = require('fs');
describe('Test package.json and io-package.json', function() {
it('Test package files', function (done) {
console.log();
var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
var ioPackage = JSON.parse(fileContentIOPackage);
var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
var npmPackage = JSON.parse(fileContentNPMPackage);
expect(ioPackage).to.be.an('object');
expect(npmPackage).to.be.an('object');
expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;
expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);
if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
console.log();
}
expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;
if (ioPackage.common.name.indexOf('template') !== 0) {
if (Array.isArray(ioPackage.common.authors)) {
expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
if (ioPackage.common.authors.length === 1) {
expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
}
}
else {
expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
}
}
else {
console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
console.log();
}
expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
console.log('WARNING: titleLang is not existing in io-package.json. Please add');
console.log();
}
if (
ioPackage.common.title.indexOf('yunkong2') !== -1 ||
ioPackage.common.title.indexOf('yunkong2') !== -1 ||
ioPackage.common.title.indexOf('adapter') !== -1 ||
ioPackage.common.title.indexOf('Adapter') !== -1
) {
console.log('WARNING: title contains Adapter or yunkong2. It is clear anyway, that it is adapter for yunkong2.');
console.log();
}
if (ioPackage.common.name.indexOf('vis-') !== 0) {
if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
console.log('WARNING: Admin3 support is missing! Please add it');
console.log();
}
if (ioPackage.common.materialize) {
expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
}
}
var licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
if (fileContentReadme.indexOf('## Changelog') === -1) {
console.log('Warning: The README.md should have a section ## Changelog');
console.log();
}
expect((licenseFileExists || fileContentReadme.indexOf('## License') !== -1), 'A LICENSE must exist as LICENSE file or as part of the README.md').to.be.true;
if (!licenseFileExists) {
console.log('Warning: The License should also exist as LICENSE file');
console.log();
}
if (fileContentReadme.indexOf('## License') === -1) {
console.log('Warning: The README.md should also have a section ## License to be shown in Admin3');
console.log();
}
done();
});
});

410
widgets/history.html Normal file
View File

@ -0,0 +1,410 @@
<!--
yunkong2.vis history widgets
version: "0.2.6"
Copyright 2016 bluefox<dogafox@gmail.com>
-->
<script type="text/javascript" src="widgets/history/lib/js/jquery.sparkline.min.js"></script>
<script type="text/javascript">
'use strict';
if (vis.editMode) {
// Add words for basic widgets
$.extend(true, systemDictionary, {
"format_date": {"en": "Dateformat", "de": "Datumformat", "ru": "Формат даты"},
"format_date_tooltip": {
"en": "Dateformat",
"de": "Datumformat",
"ru": "Формат даты"
},
"1 second": {"en": "1 second", "de": "1 Sekunde", "ru": "1 секунда"},
"10 seconds": {"en": "10 seconds", "de": "10 Sekunden", "ru": "10 секунд"},
"30 seconds": {"en": "30 seconds", "de": "30 Sekunden", "ru": "30 секунд"},
"1 minute": {"en": "1 minute", "de": "1 Minute", "ru": "1 минута"},
"2 minutes": {"en": "2 minutes", "de": "2 Minuten", "ru": "2 минуты"},
"5 minutes": {"en": "5 minutes", "de": "5 Minuten", "ru": "5 минут"},
"10 minutes": {"en": "10 minutes", "de": "10 Minuten", "ru": "10 минут"},
"30 minutes": {"en": "30 minutes", "de": "30 Minuten", "ru": "30 минут"},
"1 hour": {"en": "1 hour", "de": "1 Stunde", "ru": "1 час"},
"2 hours": {"en": "2 hours", "de": "2 Stunden", "ru": "2 часа"},
"4 hours": {"en": "4 hours", "de": "4 Stunden", "ru": "4 часа"},
"8 hours": {"en": "8 hours", "de": "8 Stunden", "ru": "8 часов"},
"12 hours": {"en": "12 hours", "de": "12 Stunden", "ru": "12 часов"},
"24 hours": {"en": "24 hours", "de": "24 Stunden", "ru": "24 часа"},
"instance": {"en": "history instance", "de": "Historyinstanz", "ru": "Экземпляр"},
"group_advanced": {"en": "Advanced", "de": "Erweitert", "ru": "Дополнительно"},
"max_lines": {"en": "Max. event amount", "de": "max. Ereignisse", "ru": "Макс. кол-во событий"},
"time_interval_min": {"en": "Not older than", "de": "Nicht älter als", "ru": "Не позже чем"},
"timeAsInterval": {"en": "Time as interval", "de": "Zeit als Intervall", "ru": "Время, как интервал"},
"inverseOrder": {"en": "Inverse order", "de": "Reihenfolge invertieren", "ru": "Обратный порядок"},
"group_columns": {"en": "Columns", "de": "Spalten", "ru": "Колонки"},
"table_attr": {"en": "Table CSS style", "de": "CSS Stil - Tabelle", "ru": "Таблица - CSS стиль"},
"header_attr": {"en": "Header CSS style", "de": "CSS Stil - Beschriftung", "ru": "Заголовок - CSS стиль"},
"time_name": {"en": "Time - name", "de": "Zeit - Name", "ru": "Время - имя"},
"time_hide": {"en": "Time - hide", "de": "Zeit - nicht zeigen", "ru": "Время - скрыть"},
"time_width": {"en": "Time - width", "de": "Zeit - Breite", "ru": "Время - ширина"},
"time_attr": {"en": "Time - CSS style", "de": "Zeit - CSS Stil", "ru": "Время - CSS стиль"},
"time_unit": {"en": "Time - suffix", "de": "Zeit - Suffix", "ru": "Время - суффикс"},
"val_name": {"en": "Val- name", "de": "Wert - Name", "ru": "Значение - имя"},
"val_hide": {"en": "Val - hide", "de": "Wert - nicht zeigen", "ru": "Значение - скрыть"},
"val_width": {"en": "Val - width", "de": "Wert - Breite", "ru": "Значение - ширина"},
"val_attr": {"en": "Val - CSS style", "de": "Wert - CSS Stil", "ru": "Значение - CSS стиль"},
"val_unit": {"en": "Val - units", "de": "Wert - Einheit", "ru": "Значение - единицы"},
"from_name": {"en": "From - name", "de": "Von - Name", "ru": "От - имя"},
"from_hide": {"en": "From - hide", "de": "Von - nicht zeigen", "ru": "От - скрыть"},
"from_width": {"en": "From - width", "de": "Von - Breite", "ru": "От - ширина"},
"from_attr": {"en": "From - CSS style", "de": "Von - CSS Stil", "ru": "От - CSS стиль"},
"from_unit": {"en": "From - suffix", "de": "Von - Suffix", "ru": "От - суффикс"},
"average": {"en": "average", "de": "Mittelwert", "ru": "среднее"},
"total": {"en": "total", "de": "Summe", "ru": "сумма"},
"line": {"en": "line", "de": "Linie", "ru": "Линия"},
"aggregate": {"en": "Aggregation", "de": "Aggregation", "ru": "Аггрегирование"},
"chartType": {"en": "chartType", "de": "Charttyp", "ru": "Тип графика"},
"points": {"en": "points", "de": "Anzahl Werten", "ru": "Кол-во точек"},
"time_interval": {"en": "Time interval", "de": "Zeitintervall", "ru": "Интервал"},
"group_line": {"en": "Line", "de": "Linie-Chart", "ru": "Линия"},
"lineColor": {"en": "Line color", "de": "Linie-Farbe", "ru": "Цвет линии"},
"fillColor": {"en": "Fill color", "de": "Füllfarbe", "ru": "Цвет заливки"},
"lineWidth": {"en": "Line width", "de": "Liniendicke", "ru": "Ширина линии"},
"group_bar": {"en": "Bar", "de": "Bar-Chart", "ru": "Столбцы"},
"barColor": {"en": "Positive color", "de": "Positivfarbe", "ru": "Цвет положительных столбцов"},
"negBarColor": {"en": "negative color", "de": "Negativfarbe", "ru": "Цвет отрицательных столбцов"},
"zeroColor": {"en": "Zero color", "de": "0-Farbe", "ru": "Цвер нулевых значений"},
"barSpacing": {"en": "Bar's spacing", "de": "Abstand", "ru": "Расстояние между столбцами"},
"disableTooltips": {"en": "Hide tooltips", "de": "Kein Tooltips", "ru": "Нет подсказки"},
"history": {"en": "history", "de": "history", "ru": "history"}
});
}
vis.binds.history = {
version: "0.2.6",
showVersion: function () {
if (vis.binds.history.version) {
console.log('Version vis-history: ' + vis.binds.history.version);
vis.binds.history.version = null;
}
},
updateWidgets: [],
updateIntervalTimer: null,
startIntervalUpdate: function () {
if (vis.editMode) return;
if (vis.binds.history.updateWidgets.length && !vis.binds.history.updateIntervalTimer) {
vis.binds.history.updateIntervalTimer = setInterval(vis.binds.history.updateInterval, 30000);
} else if (!vis.binds.history.updateWidgets.length && vis.binds.history.updateIntervalTimer) {
clearInterval(vis.binds.history.updateIntervalTimer);
vis.binds.history.updateIntervalTimer = null;
}
},
updateInterval: function () {
for (var wid = 0; wid < vis.binds.history.updateWidgets.length; wid++) {
vis.binds.history.eventList.update($('#' + vis.binds.history.updateWidgets[wid]).find('.vis-widget-body'));
}
},
eventList: {
intervals: {
'1 second': 1000,
'10 seconds': 10000,
'30 seconds': 30000,
'1 minute': 60000,
'2 minutes': 120000,
'5 minutes': 300000,
'10 minutes': 600000,
'30 minutes': 1800000,
'1 hour': 3600000,
'2 hours': 7200000,
'4 hours': 14400000,
'8 hours': 28800000,
'12 hours': 43200000,
'24 hours': 86400000
},
header: function (data) {
var text = data.title ? '<div style="text-align: center; width: 100%;' + (data.title_attr || '') + '">' + data.title + '</div>' : '';
text += '<table class="vis-no-spaces">\n';
var table_attr = (data.table_attr || '');
var attrTime = (data.time_width ? 'width: ' + data.time_width + 'px;' : '');
var attrVal = (data.val_width ? 'width: ' + data.val_width + 'px;' : '');
var attrFrom = (data.from_width ? 'width: ' + data.from_width + 'px;' : '');
if ((!data.time_hide && data.time_name) ||
(!data.val_hide && data.val_name) ||
(!data.from_hide && data.from_name)) {
text += '<tr style="' + (data.header_attr || '') + ';' + table_attr + '">';
if (!data.time_hide) text += '<th style="' + attrTime + table_attr + '">' + (data.time_name || '') + '</th>';
if (!data.val_hide) text += '<th style="' + attrVal + table_attr + '">' + (data.val_name || '') + '</th>';
if (!data.from_hide) text += '<th style="' + attrFrom + table_attr + '">' + (data.from_name || '') + '</th>';
attrTime = '';
attrVal = '';
attrFrom = '';
}
return {text: text, attrTime: attrTime, attrVal: attrVal, attrFrom: attrFrom, table_attr: table_attr};
},
renderLine: function (header, data, result, line) {
var resLine = result[line] || {val: '&nbsp;', from: '&nbsp;'};
var text = '<tr style="' + header.table_attr + '">';
var time;
if (resLine.ts) {
time = data.timeAsInterval ? vis.binds.basic.getTimeInterval(resLine.ts) : vis.binds.basic.formatDate(resLine.ts, data.format_date);
} else {
time = '&nbsp;';
}
if (time !== '&nbsp;' && data.time_unit) time += data.time_unit;
if (data.val_unit && resLine.val !== '&nbsp;' && resLine.val !== null && resLine.val !== undefined && resLine.val !== '') resLine.val += data.val_unit;
if (data.from_unit && resLine.from !== '&nbsp;' && resLine.from !== null && resLine.from !== undefined && resLine.from !== '') resLine.from += data.from_unit;
if (!data.time_hide) text += '<td style="' + header.attrTime + (data.time_attr || '') + ';' + header.table_attr + '">' + time + '</td>';
if (!data.val_hide) {
if (resLine.val && typeof resLine.val === 'string' && resLine.val.match(/https?:\/\//)) resLine.val = '<a href="' + resLine.val + '" target="eventList">' + resLine.val.split('/').pop() + '</a>';
text += '<td style="' + header.attrVal + (data.val_attr || '') + ';' + header.table_attr + '">' + resLine.val + '</td>';
}
if (!data.from_hide) text += '<td style="' + header.attrFrom + (data.from_attr || '') + ';' + header.table_attr + '">' + (resLine.from || '') + '</td>';
text += '</tr>\n';
return text;
},
update: function ($div) {
var data = $div.data('options');
if (!data.oid || !data.instance) {
var header = vis.binds.history.eventList.header(data);
if (data.max_lines) {
for (var e = 0; e < data.max_lines; e++) {
header.text += vis.binds.history.eventList.renderLine(header, data, [], e);
}
}
header.text += '</table>';
$div.html(header.text);
} else {
vis.getHistory(data.oid, {
instance: data.instance,
count: parseInt(data.max_lines, 10) || 10,
aggregate: 'none',
from: !data.from_hide,
start: vis.binds.history.eventList.intervals[data.time_interval_min] ? new Date().getTime() - vis.binds.history.eventList.intervals[data.time_interval_min] : undefined,
timeout: 2000
}, function (err, result) {
var e;
if (err) console.log(err);
if (result && result.length) {
var header = vis.binds.history.eventList.header(data);
var cnt = 0;
if (data.inverseOrder) {
for (e = 0; e < result.length; e++) {
header.text += vis.binds.history.eventList.renderLine(header, data, result, e);
if (data.max_lines && ++cnt >= data.max_lines) break;
}
} else {
for (e = result.length - 1; e >= 0; e--) {
header.text += vis.binds.history.eventList.renderLine(header, data, result, e);
if (data.max_lines && ++cnt >= data.max_lines) break;
}
}
if (data.max_lines) {
for (e = result.length; e < data.max_lines; e++) {
header.text += vis.binds.history.eventList.renderLine(header, data, result, e);
}
}
header.text += '</table>';
$div.html(header.text);
} else {
var header = vis.binds.history.eventList.header(data);
header.text += '<tr><td colspan="3">' + (err || _('no data')) + '</td></tr>';
if (data.max_lines) {
for (e = 1; e < data.max_lines; e++) {
header.text += vis.binds.history.eventList.renderLine(header, data, [], e);
}
}
header.text += '</table>';
$div.html(header.text);
}
});
}
},
init: function (el, view, data) {
var $div = $(el);
var _data = {};
for (var s in data) {
if (s[0] !== '_' && data.hasOwnProperty(s) && typeof data[s] !== 'object' && typeof data[s] !== 'function') {
_data[s] = data[s];
}
}
data = null;
$div.data('options', _data);
if (_data.oid && _data.instance) {
if (_data.timeAsInterval && vis.binds.history.updateWidgets.indexOf(_data.wid) === -1) {
vis.binds.history.updateWidgets.push(_data.wid);
vis.binds.history.startIntervalUpdate();
}
vis.states.bind(_data.oid + '.val', function () {
vis.binds.history.eventList.update($div);
});
}
vis.binds.history.eventList.update($div);
}
},
sparkLine: {
update: function ($div) {
var data = $div.data('options');
if (!data.oid || !data.instance) {
$div.sparkline([0,0], {
width: $div.width(),
height: $div.height(),
lineColor: data.lineColor,
fillColor: data.fillColor,
chartRangeMin: data.min === '' || data.min === null || data.min === 'undefined' ? undefined : parseFloat(data.min),
chartRangeMax: data.max === '' || data.max === null || data.max === 'undefined' ? undefined : parseFloat(data.max),
lineWidth: parseInt(data.lineWidth, 10) || 1
});
} else {
vis.getHistory(data.oid, {
instance: data.instance,
count: parseInt(data.points, 10) || 10,
step: parseInt(data.time_interval_min, 10) || 60000,
aggregate: data.aggregate || 'average',
start: vis.binds.history.eventList.intervals[data.time_interval] ? new Date().getTime() - vis.binds.history.eventList.intervals[data.time_interval] : undefined,
end: new Date().getTime() + 5000,
timeout: 2000
}, function (err, result) {
var data = $div.data('options');
if (err) console.log(err);
if (result && result.length) {
var values = [];
for (var i = 0; i < result.length; i++) {
values.push(result[i].val)
}
var barWidth = $div.width() / result.length - (parseFloat(data.barSpacing) || 1);
$div.sparkline(values, {
type: data.chartType || 'line',
width: $div.width(),
height: $div.height(),
lineColor: data.lineColor || undefined,
barColor: data.barColor || undefined,
negBarColor: data.negBarColor || undefined,
zeroColor: data.zeroColor || undefined,
fillColor: data.fillColor || undefined,
barWidth: barWidth,
disableTooltips: data.disableTooltips || undefined,
barSpacing: parseFloat(data.barSpacing) || 1,
chartRangeMin: data.min === '' || data.min === null || data.min === 'undefined' ? undefined : parseFloat(data.min),
chartRangeMax: data.max === '' || data.max === null || data.max === 'undefined' ? undefined : parseFloat(data.max),
lineWidth: parseInt(data.lineWidth, 10) || 1
});
} else {
$div.sparkline([0,0], {
width: $div.width(),
height: $div.height(),
lineColor: data.lineColor || undefined,
fillColor: data.fillColor || undefined,
chartRangeMin: data.min === '' || data.min === null || data.min === 'undefined' ? undefined : parseFloat(data.min),
chartRangeMax: data.max === '' || data.max === null || data.max === 'undefined' ? undefined : parseFloat(data.max),
lineWidth: parseInt(data.lineWidth, 10) || 1
});
}
});
}
},
init: function (el, view, data) {
var $div = $(el);
var _data = {};
for (var s in data) {
if (s[0] !== '_' && data.hasOwnProperty(s) && typeof data[s] !== 'object' && typeof data[s] !== 'function') {
_data[s] = data[s];
}
}
data = null;
$div.data('options', _data);
if (_data.oid && _data.instance) {
vis.states.bind(_data.oid + '.val', function () {
vis.binds.history.sparkLine.update($div);
});
// update every x seconds
if (!vis.editMode) {
$div.data('timer', setInterval(function () {
vis.binds.history.sparkLine.update($div);
}, parseInt(vis.binds.history.eventList.intervals[_data.time_interval] / (parseInt(_data.points, 10) || 10), 10)));
}
}
vis.binds.history.sparkLine.update($div);
}
}
};
if (vis.editMode) {
vis.binds.history.onHidChanged = function (widgetID, view, newId, fields) {
var obj = vis.objects[newId];
if (!obj || !obj.common) return null;
var changed = [];
var actualInstance = vis.views[view].widgets[widgetID].data.instance;
// Check if actual instance still in options
var firstInstance = '';
var found = false;
var custom = obj.common.custom || obj.common.history;
for (var h in custom) {
if (!custom.hasOwnProperty(h)) continue;
if (custom[h].enabled) {
if (firstInstance === '') firstInstance = h;
if (h === actualInstance) {
found = true;
break;
}
}
}
if (!found) {
changed.push('instance');
vis.views[view].widgets[widgetID].data.instance = firstInstance;
}
return changed.length ? changed : null;
};
}
vis.binds.history.showVersion();
</script>
<script id="tplHistoryEventList"
type="text/ejs"
class="vis-tpl"
data-vis-set="history"
data-vis-name="Event list"
data-vis-type="history"
data-vis-prev='<img src="widgets/history/img/Prev_tplHistoryEventList.png"></img>'
data-vis-attrs="oid/hid/onHidChanged;instance/history;"
data-vis-attrs0="group.advanced;max_lines[6]/slider,1,100,1;time_interval_min/select,none,1 second,10 seconds,30 seconds,1 minute,2 minutes,5 minutes,10 minutes,30 minutes,1 hour,2 hours,4 hours,8 hours,12 hours,24 hours;"
data-vis-attrs1="format_date[hh:mm:ss.sss]/auto,YYYY.MM.DD hh:mm:ss,DD.MM.YYYY hh:mm:ss,YYYY.MM.DD,DD.MM.YYYY,YYYY/MM/DD hh:mm:ss,YYYY/MM/DD,hh:mm:ss;timeAsInterval/checkbox;inverseOrder/checkbox;"
data-vis-attrs2="group.columns;table_attr;header_attr;"
data-vis-attrs3="time_name[Time];time_hide/checkbox;time_width[100]/slider,0,300,1;time_attr;time_unit;"
data-vis-attrs4="val_name[Value];val_hide/checkbox;val_width/slider,0,300,1;val_attr[text-align: center§];val_unit;"
data-vis-attrs5="from_name[Form];from_hide[true]/checkbox;from_width/slider,0,300,1;from_attr;from_unit;"
data-vis-attrs6="class[vis-style-green-gray]/hidden"
>
<div class="vis-widget <%== this.data.attr('class') %>" style="overflow: hidden; width: 210px; height: 170px;" id="<%= this.data.attr('wid') %>">
<div class="vis-widget-body" <%= (el) -> vis.binds.history.eventList.init(el, this.view, this.data) %>></div>
</div>
</script>
<script id="tplHistorySparkLIne"
type="text/ejs"
class="vis-tpl"
data-vis-set="history"
data-vis-name="Sparkline"
data-vis-type="history"
data-vis-update-style="true"
data-vis-prev='<img src="widgets/history/img/Prev_tplHistorySparkLine.png"></img>'
data-vis-attrs="oid/hid/onHidChanged;instance/history;aggregate[average]/select,average,min,max,total;chartType[line]/select,line,bar;"
data-vis-attrs0="points[20]/slider,1,100,1;time_interval[10 minutes]/select,1 second,10 seconds,30 seconds,1 minute,2 minutes,5 minutes,10 minutes,30 minutes,1 hour,2 hours,4 hours,8 hours,12 hours,24 hours;;min;max;disableTooltips/checkbox;"
data-vis-attrs1="group.line;lineColor/color;fillColor/color;lineWidth/slider,1,10,1;"
data-vis-attrs2="group.bar;barColor/color;negBarColor/color;zeroColor/color;min;max;barSpacing/slider,1,10,1;"
>
<div class="vis-widget <%== this.data.attr('class') %>" style="overflow: hidden; width: 210px; height: 170px;" id="<%= this.data.attr('wid') %>">
<div class="vis-widget-body" <%= (el) -> vis.binds.history.sparkLine.init(el, this.view, this.data) %>></div>
</div>
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long