@ntlab/sipd-tu-bridge-ui 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controller/ui.js +11 -1
- package/index.js +5 -3
- package/package.json +4 -4
- package/public/css/app.css +40 -0
- package/views/security/login.ejs +2 -2
- package/views/slot/errhandler.ejs +1 -1
- package/views/slot/errhandler401.ejs +1 -1
- package/views/slot/errhandler500.ejs +1 -1
- package/views/slot/mainmenu.ejs +2 -2
- package/views/ui/activity.ejs +2 -2
- package/views/ui/bridge.ejs +1 -1
- package/views/ui/bridgehandler.ejs +1 -22
- package/views/ui/error.ejs +78 -0
- package/views/ui/index.ejs +9 -4
- package/views/ui/info.ejs +19 -7
- package/views/ui/queue.ejs +17 -20
- package/views/ui/util.ejs +52 -0
package/controller/ui.js
CHANGED
|
@@ -33,15 +33,17 @@ class UiController extends Controller {
|
|
|
33
33
|
this.addRoute('index', 'get', '/', async (req, res, next) => {
|
|
34
34
|
/** @type {import('..').SipdApi} */
|
|
35
35
|
const api = req.app.api;
|
|
36
|
+
api.counter = await api.getCount();
|
|
36
37
|
for (const bridge of api.bridges) {
|
|
37
38
|
bridge.stat = await bridge.getStats();
|
|
38
39
|
bridge.last = await bridge.getLast();
|
|
39
40
|
bridge.current = await bridge.getCurrent();
|
|
40
41
|
}
|
|
41
|
-
const socketOptions = {
|
|
42
|
+
const socketOptions = {};
|
|
42
43
|
if (req.app.get('root') !== '/') {
|
|
43
44
|
socketOptions.path = req.getPath('/socket.io/');
|
|
44
45
|
}
|
|
46
|
+
socketOptions.reconnection = true;
|
|
45
47
|
res.render('ui/index', {
|
|
46
48
|
socket: {
|
|
47
49
|
url: `${req.getUri({noproto: true})}/ui`,
|
|
@@ -53,6 +55,7 @@ class UiController extends Controller {
|
|
|
53
55
|
const result = {updates: {}};
|
|
54
56
|
/** @type {import('..').SipdApi} */
|
|
55
57
|
const api = req.app.api;
|
|
58
|
+
result.counter = await api.getCount();
|
|
56
59
|
for (const bridge of api.bridges) {
|
|
57
60
|
bridge.stat = await bridge.getStats();
|
|
58
61
|
bridge.last = await bridge.getLast();
|
|
@@ -99,6 +102,13 @@ class UiController extends Controller {
|
|
|
99
102
|
}
|
|
100
103
|
res.json(result);
|
|
101
104
|
});
|
|
105
|
+
this.addRoute('error', 'get', '/error', async (req, res, next) => {
|
|
106
|
+
/** @type {import('..').SipdApi} */
|
|
107
|
+
const api = req.app.api;
|
|
108
|
+
const result = await api.getErrors(req.params.page || req.query.page, req.params.size || req.query.size);
|
|
109
|
+
result.pages = req.app.locals.pager(result.count, result.size, result.page);
|
|
110
|
+
res.json(result);
|
|
111
|
+
});
|
|
102
112
|
this.addRoute('about', 'get', '/about', (req, res, next) => {
|
|
103
113
|
let about;
|
|
104
114
|
if (req.app.about) {
|
package/index.js
CHANGED
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
* @property {object} config Configuration
|
|
36
36
|
* @property {SipdBridge[]} bridges Bridges
|
|
37
37
|
* @property {AuthenticateFunction} authenticate Perform usename and password authentication
|
|
38
|
-
* @property {
|
|
38
|
+
* @property {PagedObjectsPromiseFunction} getQueues Get queues
|
|
39
39
|
* @property {StringPromiseFunction} getActivity Get activity logs
|
|
40
|
+
* @property {ObjectPromiseFunction} getCount Get activity count
|
|
41
|
+
* @property {PagedObjectsPromiseFunction} getErrors Get captured errors
|
|
40
42
|
*/
|
|
41
43
|
|
|
42
44
|
/**
|
|
@@ -71,9 +73,9 @@
|
|
|
71
73
|
*/
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
|
-
*
|
|
76
|
+
* A function which returns paged objects Promise.
|
|
75
77
|
*
|
|
76
|
-
* @callback
|
|
78
|
+
* @callback PagedObjectsPromiseFunction
|
|
77
79
|
* @param {number} page Page number
|
|
78
80
|
* @param {number} size Page size
|
|
79
81
|
* @returns {Promise<object[]>}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ntlab/sipd-tu-bridge-ui",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "SIPD Penatausahaan Bridge Web Interface",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@ntlab/express-controller": "^1.2.0",
|
|
35
35
|
"@ntlab/express-middleware": "^2.4.0",
|
|
36
|
-
"@ntlab/ntjs": "^3.
|
|
36
|
+
"@ntlab/ntjs": "^3.1.0",
|
|
37
37
|
"@ntlab/ntjs-assets": "^2.139.0",
|
|
38
|
-
"@ntlab/ntjs-repo": "^3.0
|
|
39
|
-
"@ntlab/ntlib": "^2.9.
|
|
38
|
+
"@ntlab/ntjs-repo": "^3.1.0",
|
|
39
|
+
"@ntlab/ntlib": "^2.9.1",
|
|
40
40
|
"ejs": "^3.1.10",
|
|
41
41
|
"express": "^5.2.1",
|
|
42
42
|
"express-session": "^1.19.0",
|
package/public/css/app.css
CHANGED
|
@@ -14,3 +14,43 @@ body:not([class]) main, #login-container {
|
|
|
14
14
|
img.logo {
|
|
15
15
|
margin-right: 1em !important;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
@media only screen and (min-width: 1200px) {
|
|
19
|
+
.ui.container.queue-result {
|
|
20
|
+
max-width: 30em;
|
|
21
|
+
}
|
|
22
|
+
.ui.container.err-data {
|
|
23
|
+
max-width: 40em;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@media only screen and (min-width: 992px) and (max-width: 1199.98px) {
|
|
28
|
+
.ui.container.queue-result {
|
|
29
|
+
max-width: 25em;
|
|
30
|
+
}
|
|
31
|
+
.ui.container.err-data {
|
|
32
|
+
max-width: 30em;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@media only screen and (min-width: 768px) and (max-width: 991.98px) {
|
|
37
|
+
.ui.container.queue-result {
|
|
38
|
+
max-width: 20em;
|
|
39
|
+
}
|
|
40
|
+
.ui.container.err-data {
|
|
41
|
+
max-width: 20em;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@media only screen and (max-width: 767.98px) {
|
|
46
|
+
.ui.container.queue-result {
|
|
47
|
+
max-width: 75vw;
|
|
48
|
+
margin-left: 0 !important;
|
|
49
|
+
margin-right: 0 !important;
|
|
50
|
+
}
|
|
51
|
+
.ui.container.err-data {
|
|
52
|
+
max-width: 75vw;
|
|
53
|
+
margin-left: 0 !important;
|
|
54
|
+
margin-right: 0 !important;
|
|
55
|
+
}
|
|
56
|
+
}
|
package/views/security/login.ejs
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
<%_ script.create('JQuery')
|
|
31
31
|
.useDependencies(['JQuery/Util', 'JQuery/FormPost'])
|
|
32
|
-
.
|
|
32
|
+
.add(`
|
|
33
33
|
$.login = function(form) {
|
|
34
34
|
const fp = $.formpost(form, {progress: false, xhr: true});
|
|
35
35
|
const err = fp.errhelper;
|
|
@@ -57,6 +57,6 @@ $.login = function(form) {
|
|
|
57
57
|
form.find('input[name=username]').focus();
|
|
58
58
|
}
|
|
59
59
|
`)
|
|
60
|
-
.
|
|
60
|
+
.addInitializer(`
|
|
61
61
|
$.login($('form.login'));
|
|
62
62
|
`) -%>
|
package/views/slot/mainmenu.ejs
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<%- menu(menus, {mainmenu: true, indentation: 2}) %>
|
|
30
30
|
<%_ script.create('JQuery')
|
|
31
31
|
.useDependencies(['JQuery/Util', 'SemanticUI/Notification', 'SemanticUI/Dialog/Message'])
|
|
32
|
-
.
|
|
32
|
+
.add(`
|
|
33
33
|
$.tasks = {
|
|
34
34
|
about() {
|
|
35
35
|
const self = this;
|
|
@@ -65,6 +65,6 @@ $.tasks = {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
`).
|
|
68
|
+
`).addInitializer(`
|
|
69
69
|
$.tasks.init();
|
|
70
70
|
`) -%>
|
package/views/ui/activity.ejs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<textarea class="activity" rows="30" readonly></textarea>
|
|
3
3
|
</div>
|
|
4
4
|
<%_ script.create('JQuery')
|
|
5
|
-
.
|
|
5
|
+
.add(`
|
|
6
6
|
$.activity = {
|
|
7
7
|
el: $('textarea.activity'),
|
|
8
8
|
url: '${route('Ui', {name: 'activity'})}',
|
|
@@ -29,6 +29,6 @@ $.activity = {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
`)
|
|
32
|
-
.
|
|
32
|
+
.addInitializer(`
|
|
33
33
|
$.activity.load();
|
|
34
34
|
`) -%>
|
package/views/ui/bridge.ejs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%_ script.create('JQuery')
|
|
2
|
-
.
|
|
2
|
+
.add(`
|
|
3
3
|
$.bridge = {
|
|
4
4
|
bridges: {},
|
|
5
5
|
getLog(name) {
|
|
@@ -25,27 +25,6 @@ $.bridge = {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
update() {
|
|
29
|
-
const self = this;
|
|
30
|
-
$.get('${route('Ui', {name: 'updates'})}')
|
|
31
|
-
.done(function(json) {
|
|
32
|
-
if (json.updates) {
|
|
33
|
-
for (const bridge of Object.keys(json.updates)) {
|
|
34
|
-
for (const [k, v] of Object.entries(json.updates[bridge])) {
|
|
35
|
-
$(\`[data-bridge="\${bridge}"] [data-key="\${k}"]\`).each(function() {
|
|
36
|
-
const el = $(this);
|
|
37
|
-
const value = v && v.value !== undefined ? v.value : v;
|
|
38
|
-
if (el.is('input')) {
|
|
39
|
-
el.val(value);
|
|
40
|
-
} else {
|
|
41
|
-
el.html(value ? value : '–');
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
},
|
|
49
28
|
init(bridges) {
|
|
50
29
|
const self = this;
|
|
51
30
|
for (const bridge of bridges) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<h3 class="ui header x-title"></h3>
|
|
2
|
+
<table class="ui selectable celled table">
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th><%= _('#') %></th>
|
|
6
|
+
<th><%= _('Screen') %></th>
|
|
7
|
+
<th><%= _('Error') %></th>
|
|
8
|
+
<th><%= _('Data') %></th>
|
|
9
|
+
</tr>
|
|
10
|
+
</thead>
|
|
11
|
+
</table>
|
|
12
|
+
<%_ script.create('JQuery')
|
|
13
|
+
.useDependencies(['SemanticUI/Loader', 'SemanticUI/Dialog'])
|
|
14
|
+
.add(`
|
|
15
|
+
$.error = $.loader($('div[data-tab="error"] table'), {
|
|
16
|
+
url: '${route('Ui', {name: 'error', page: 'PAGE'})}',
|
|
17
|
+
formatRow(item) {
|
|
18
|
+
return this.toRow(item);
|
|
19
|
+
},
|
|
20
|
+
loaded(json) {
|
|
21
|
+
const self = this;
|
|
22
|
+
if (json.count !== undefined) {
|
|
23
|
+
const counter = $('[data-tab="error"] .label');
|
|
24
|
+
if (json.count) {
|
|
25
|
+
counter.text(json.count).removeClass('hidden');
|
|
26
|
+
} else {
|
|
27
|
+
counter.addClass('hidden');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
$('a.err-img-view').on('click', function(e) {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
const a = $(this);
|
|
33
|
+
const dlg = $.ntdlg.create(
|
|
34
|
+
'err-img-view-dlg',
|
|
35
|
+
a.data('tooltip'),
|
|
36
|
+
\`<img class="ui fluid image" src="\${a.find('img').attr('src')}" style="max-height: 70vh;">\`, {
|
|
37
|
+
size: 'fullscreen',
|
|
38
|
+
buttons: {
|
|
39
|
+
okay: {
|
|
40
|
+
type: 'green approve',
|
|
41
|
+
caption: '<i class="check icon"></i>${_('Ok')}',
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
$.ntdlg.show(dlg);
|
|
47
|
+
});
|
|
48
|
+
if (self.loading) {
|
|
49
|
+
self.loading = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
$.error.toRow = function(data) {
|
|
54
|
+
return $(
|
|
55
|
+
\`<tr><td>\${data.nr}</td>
|
|
56
|
+
<td>\${this.toImg($.toStr(data.image), data.filename)}</td>
|
|
57
|
+
<td>\${$.toStr(data.error)}</td>
|
|
58
|
+
<td><div class="ui scrolling container err-data">\${$.hidePayload($.toStr(data.data))}</div></td>
|
|
59
|
+
</tr>\`);
|
|
60
|
+
}
|
|
61
|
+
$.error.toImg = function(data, alt) {
|
|
62
|
+
if (data) {
|
|
63
|
+
return \`<a href="#" class="err-img-view" data-tooltip="\${alt}" data-position="right center">
|
|
64
|
+
<img class="ui medium rounded bordered image" src="\${data}" alt="\${alt}">
|
|
65
|
+
</a>\`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
$.error.reload = function() {
|
|
69
|
+
const self = this;
|
|
70
|
+
if (!self.loading) {
|
|
71
|
+
self.loading = true;
|
|
72
|
+
self.load();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`)
|
|
76
|
+
.addInitializer(`
|
|
77
|
+
$.error.load();
|
|
78
|
+
`) -%>
|
package/views/ui/index.ejs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<div class="ui top attached stackable tabular menu">
|
|
2
2
|
<a class="item" data-tab="status"><%= _('Status') %></a>
|
|
3
3
|
<a class="item" data-tab="activity"><%= _('Activity') %></a>
|
|
4
|
-
<a class="item" data-tab="queue"><%= _('Queue')
|
|
4
|
+
<a class="item" data-tab="queue"><%= _('Queue') %> <span class="ui hidden tiny label"></span></a>
|
|
5
5
|
<%_ if (api.bridges.length) { -%>
|
|
6
6
|
<a class="item" data-tab="bridge"><%= _('Bridge') %> <span class="ui tiny label"><%= api.bridges.length %></span></a>
|
|
7
7
|
<%_ } -%>
|
|
8
|
+
<a class="item" data-tab="error"><%= _('Error') %> <span class="ui hidden tiny label"></span></a>
|
|
8
9
|
</div>
|
|
9
10
|
<div class="ui bottom attached tab segment" data-tab="status">
|
|
10
11
|
<%- include('status') -%>
|
|
@@ -21,9 +22,13 @@
|
|
|
21
22
|
<%- include('bridge') -%>
|
|
22
23
|
</div>
|
|
23
24
|
<%_ } -%>
|
|
25
|
+
<div class="ui bottom attached tab segment" data-tab="error">
|
|
26
|
+
<%- include('error') -%>
|
|
27
|
+
</div>
|
|
28
|
+
<%- include('util') -%>
|
|
24
29
|
<%_ script.create('JQuery')
|
|
25
30
|
.useDependencies(['SocketIO'])
|
|
26
|
-
.
|
|
31
|
+
.add(`
|
|
27
32
|
$.uiCon = {
|
|
28
33
|
connected: false,
|
|
29
34
|
data: ${s(socket, 1)},
|
|
@@ -55,12 +60,12 @@ $.uiCon = {
|
|
|
55
60
|
})
|
|
56
61
|
.on('queue', function() {
|
|
57
62
|
$.queue.reload();
|
|
58
|
-
$.
|
|
63
|
+
$.uiRefresh();
|
|
59
64
|
});
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
`)
|
|
63
|
-
.
|
|
68
|
+
.addInitializer(`
|
|
64
69
|
$('.menu .item').tab({
|
|
65
70
|
autoTabActivation: window.location.hash ? window.location.hash.substr(1) : true,
|
|
66
71
|
onLoad(path, params, history) {
|
package/views/ui/info.ejs
CHANGED
|
@@ -4,13 +4,25 @@
|
|
|
4
4
|
</div>
|
|
5
5
|
<div class="extra content">
|
|
6
6
|
<div class="ui form">
|
|
7
|
-
<div class="
|
|
8
|
-
<div class="
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
<div class="ui two column stackable grid">
|
|
8
|
+
<div class="column">
|
|
9
|
+
<div class="fields">
|
|
10
|
+
<div class="eight wide field"><label><%= _('Protocol:') %></label></div>
|
|
11
|
+
<div class="eight wide field"><label><%= api.proto %></label></div>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="fields">
|
|
14
|
+
<div class="eight wide field"><label><%= _('Mode:') %></label></div>
|
|
15
|
+
<div class="eight wide field"><label><%= api.mode %></label></div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="column">
|
|
19
|
+
<%_ Object.keys(api.counter).forEach(counter => { -%>
|
|
20
|
+
<div class="fields">
|
|
21
|
+
<div class="eight wide field"><label><%= _(api.counter[counter].label) %></label></div>
|
|
22
|
+
<div class="eight wide field"><label data-counter="<%= counter %>"><%= _(api.counter[counter].value) %></label></div>
|
|
23
|
+
</div>
|
|
24
|
+
<%_ }) -%>
|
|
25
|
+
</div>
|
|
14
26
|
</div>
|
|
15
27
|
</div>
|
|
16
28
|
</div>
|
package/views/ui/queue.ejs
CHANGED
|
@@ -14,14 +14,22 @@
|
|
|
14
14
|
</table>
|
|
15
15
|
<%_ script.create('JQuery')
|
|
16
16
|
.useDependencies('SemanticUI/Loader')
|
|
17
|
-
.
|
|
17
|
+
.add(`
|
|
18
18
|
$.queue = $.loader($('div[data-tab="queue"] table'), {
|
|
19
19
|
url: '${route('Ui', {name: 'queue', page: 'PAGE'})}',
|
|
20
20
|
formatRow(item) {
|
|
21
21
|
return this.toRow(item);
|
|
22
22
|
},
|
|
23
|
-
loaded() {
|
|
23
|
+
loaded(json) {
|
|
24
24
|
const self = this;
|
|
25
|
+
if (json.count !== undefined) {
|
|
26
|
+
const counter = $('[data-tab="queue"] .label');
|
|
27
|
+
if (json.count) {
|
|
28
|
+
counter.text(json.count).removeClass('hidden');
|
|
29
|
+
} else {
|
|
30
|
+
counter.addClass('hidden');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
25
33
|
if (self.loading) {
|
|
26
34
|
self.loading = false;
|
|
27
35
|
}
|
|
@@ -30,25 +38,14 @@ $.queue = $.loader($('div[data-tab="queue"] table'), {
|
|
|
30
38
|
$.queue.toRow = function(data) {
|
|
31
39
|
return $(
|
|
32
40
|
\`<tr><td>\${data.nr}</td>
|
|
33
|
-
<td>\${
|
|
34
|
-
<td>\${
|
|
35
|
-
<td>\${
|
|
41
|
+
<td>\${$.toStr(data.id)}</td>
|
|
42
|
+
<td>\${$.toStr(data.type)}</td>
|
|
43
|
+
<td>\${$.toStr(data.name)}</td>
|
|
36
44
|
<td>\${this.toStatus(data.status)}</td>
|
|
37
|
-
<td>\${
|
|
38
|
-
<td>\${
|
|
45
|
+
<td><div class="ui scrolling container queue-result">\${$.hidePayload($.toStr(data.result))}</div></td>
|
|
46
|
+
<td>\${$.toStr(data.time)}</td>
|
|
39
47
|
</tr>\`);
|
|
40
48
|
}
|
|
41
|
-
$.queue.toStr = function(o) {
|
|
42
|
-
if (
|
|
43
|
-
Array.isArray(o) ||
|
|
44
|
-
typeof o === 'object' && o.constructor.name === 'Object'
|
|
45
|
-
) {
|
|
46
|
-
return JSON.stringify(o);
|
|
47
|
-
} else if (o !== undefined && o !== null) {
|
|
48
|
-
return o.toString();
|
|
49
|
-
}
|
|
50
|
-
return '';
|
|
51
|
-
}
|
|
52
49
|
$.queue.toStatus = function(data) {
|
|
53
50
|
const icon = {
|
|
54
51
|
new: 'pause circle outline',
|
|
@@ -59,7 +56,7 @@ $.queue.toStatus = function(data) {
|
|
|
59
56
|
skipped: 'exclamation',
|
|
60
57
|
}[data];
|
|
61
58
|
return icon ? \`<div data-tooltip="\${data}" data-position="right center"><i class="\${icon} icon"></i></div>\` :
|
|
62
|
-
|
|
59
|
+
$.toStr(data);
|
|
63
60
|
}
|
|
64
61
|
$.queue.reload = function() {
|
|
65
62
|
const self = this;
|
|
@@ -69,6 +66,6 @@ $.queue.reload = function() {
|
|
|
69
66
|
}
|
|
70
67
|
}
|
|
71
68
|
`)
|
|
72
|
-
.
|
|
69
|
+
.addInitializer(`
|
|
73
70
|
$.queue.load();
|
|
74
71
|
`) -%>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<%_ script.create('JQuery')
|
|
2
|
+
.add(`
|
|
3
|
+
$.uiRefresh = function() {
|
|
4
|
+
$.get('${route('Ui', {name: 'updates'})}')
|
|
5
|
+
.done(function(json) {
|
|
6
|
+
if (json.counter) {
|
|
7
|
+
for (const [k, v] of Object.entries(json.counter)) {
|
|
8
|
+
$(\`[data-counter="\${k}"]\`).each(function() {
|
|
9
|
+
const el = $(this);
|
|
10
|
+
const value = v && v.value !== undefined ? v.value : v;
|
|
11
|
+
el.html(value);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (json.updates) {
|
|
16
|
+
for (const bridge of Object.keys(json.updates)) {
|
|
17
|
+
for (const [k, v] of Object.entries(json.updates[bridge])) {
|
|
18
|
+
$(\`[data-bridge="\${bridge}"] [data-key="\${k}"]\`).each(function() {
|
|
19
|
+
const el = $(this);
|
|
20
|
+
const value = v && v.value !== undefined ? v.value : v;
|
|
21
|
+
if (el.is('input')) {
|
|
22
|
+
el.val(value);
|
|
23
|
+
} else {
|
|
24
|
+
el.html(value ? value : '–');
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
$.hidePayload = function(message) {
|
|
33
|
+
if (message) {
|
|
34
|
+
message = message.replace(
|
|
35
|
+
/[A-Za-z0-9\\+\\/\\=\\@\\,]{40,}/g,
|
|
36
|
+
s => \`<i class="comment dots outline icon" data-tooltip="\${s}" data-position="right center"></i>\`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return message;
|
|
40
|
+
}
|
|
41
|
+
$.toStr = function(o) {
|
|
42
|
+
if (
|
|
43
|
+
Array.isArray(o) ||
|
|
44
|
+
typeof o === 'object' && o.constructor.name === 'Object'
|
|
45
|
+
) {
|
|
46
|
+
return JSON.stringify(o);
|
|
47
|
+
} else if (o !== undefined && o !== null) {
|
|
48
|
+
return o.toString();
|
|
49
|
+
}
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
`) -%>
|