@frangoteam/fuxa-min 1.2.11 → 1.3.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/api/auth/index.js +141 -3
- package/api/index.js +18 -2
- package/api/jwt-helper.js +3 -1
- package/api/resources/index.js +19 -2
- package/dist/3rdpartylicenses.txt +139 -7
- package/dist/assets/i18n/de.json +10 -0
- package/dist/assets/i18n/en.json +14 -3
- package/dist/assets/i18n/es.json +12 -0
- package/dist/assets/i18n/fr.json +10 -0
- package/dist/assets/i18n/ja.json +15 -6
- package/dist/assets/i18n/ko.json +12 -0
- package/dist/assets/i18n/pt.json +9 -2
- package/dist/assets/i18n/ru.json +11 -0
- package/dist/assets/i18n/sv.json +10 -1
- package/dist/assets/i18n/tr.json +8 -1
- package/dist/assets/i18n/ua.json +9 -2
- package/dist/assets/i18n/zh-cn.json +10 -0
- package/dist/assets/i18n/zh-tw.json +11 -1
- package/dist/index.html +2 -2
- package/dist/main.bafae830903d548e.js +329 -0
- package/dist/polyfills.d7de05f9af2fb559.js +1 -0
- package/dist/{runtime.8ef63094e52a66ba.js → runtime.9136a61a9b98f987.js} +1 -1
- package/dist/{scripts.40b60f02658462e4.js → scripts.d9e6ee984bf6f3b7.js} +1 -1
- package/dist/styles.545e37beb3e671ba.css +1 -0
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.js +8 -2
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.js +12 -12
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.js +14 -10
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.js +8 -2
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.js +24 -20
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.js +8 -2
- package/main.js +35 -17
- package/package.json +10 -5
- package/runtime/devices/adsclient/index.js +1 -1
- package/runtime/devices/ethernetip/index.js +1 -1
- package/runtime/devices/gpio/index.js +1 -1
- package/runtime/devices/odbc/index.js +5 -5
- package/runtime/devices/template/index.js +14 -14
- package/runtime/storage/daqstorage.js +28 -2
- package/runtime/storage/questdb/index.js +224 -0
- package/runtime/utils.js +5 -0
- package/settings.default.js +5 -2
- package/dist/main.92522279642ef880.js +0 -329
- package/dist/polyfills.c8e7db9850a3ad8b.js +0 -1
- package/dist/styles.03cc550382689976.css +0 -1
package/api/auth/index.js
CHANGED
|
@@ -10,12 +10,78 @@ const authJwt = require('../jwt-helper');
|
|
|
10
10
|
var runtime;
|
|
11
11
|
var secretCode;
|
|
12
12
|
var tokenExpiresIn;
|
|
13
|
+
var enableRefreshCookieAuth = false;
|
|
14
|
+
var refreshTokenExpiresIn = '7d';
|
|
15
|
+
const refreshCookieName = 'fuxa_refresh';
|
|
16
|
+
|
|
17
|
+
function parseExpiresToMs(expiresIn) {
|
|
18
|
+
if (expiresIn === undefined || expiresIn === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (typeof expiresIn === 'number') {
|
|
22
|
+
return expiresIn * 1000;
|
|
23
|
+
}
|
|
24
|
+
if (typeof expiresIn !== 'string') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const match = expiresIn.trim().match(/^(\d+)\s*([smhd])?$/i);
|
|
28
|
+
if (!match) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const value = Number(match[1]);
|
|
32
|
+
const unit = (match[2] || 's').toLowerCase();
|
|
33
|
+
const multipliers = { s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
34
|
+
return value * (multipliers[unit] || 1000);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getCookieValue(req, name) {
|
|
38
|
+
const cookieHeader = req.headers.cookie;
|
|
39
|
+
if (!cookieHeader) return null;
|
|
40
|
+
const cookies = cookieHeader.split(';');
|
|
41
|
+
for (const cookie of cookies) {
|
|
42
|
+
const [key, ...rest] = cookie.trim().split('=');
|
|
43
|
+
if (key === name) {
|
|
44
|
+
return decodeURIComponent(rest.join('='));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildAccessToken(user) {
|
|
51
|
+
return jwt.sign({ id: user.username, groups: user.groups }, secretCode, { expiresIn: tokenExpiresIn });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function buildRefreshToken(user) {
|
|
55
|
+
return jwt.sign({ id: user.username, groups: user.groups, type: 'refresh' }, secretCode, { expiresIn: refreshTokenExpiresIn });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function setRefreshCookie(res, token) {
|
|
59
|
+
const maxAge = parseExpiresToMs(refreshTokenExpiresIn);
|
|
60
|
+
const options = {
|
|
61
|
+
httpOnly: true,
|
|
62
|
+
sameSite: 'lax',
|
|
63
|
+
secure: !!runtime?.settings?.https,
|
|
64
|
+
path: '/api/refresh'
|
|
65
|
+
};
|
|
66
|
+
if (maxAge) {
|
|
67
|
+
options.maxAge = maxAge;
|
|
68
|
+
}
|
|
69
|
+
res.cookie(refreshCookieName, token, options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function clearRefreshCookie(res) {
|
|
73
|
+
res.clearCookie(refreshCookieName, { path: '/api/refresh' });
|
|
74
|
+
}
|
|
13
75
|
|
|
14
76
|
module.exports = {
|
|
15
|
-
init: function (_runtime, _secretCode, _tokenExpires) {
|
|
77
|
+
init: function (_runtime, _secretCode, _tokenExpires, _enableRefreshCookieAuth, _refreshTokenExpires) {
|
|
16
78
|
runtime = _runtime;
|
|
17
79
|
secretCode = _secretCode;
|
|
18
80
|
tokenExpiresIn = _tokenExpires;
|
|
81
|
+
enableRefreshCookieAuth = !!_enableRefreshCookieAuth;
|
|
82
|
+
if (_refreshTokenExpires) {
|
|
83
|
+
refreshTokenExpiresIn = _refreshTokenExpires;
|
|
84
|
+
}
|
|
19
85
|
},
|
|
20
86
|
app: function () {
|
|
21
87
|
var authApp = express();
|
|
@@ -35,7 +101,11 @@ module.exports = {
|
|
|
35
101
|
runtime.users.findOne(req.body).then(function (userInfo) {
|
|
36
102
|
if (userInfo && userInfo.length && userInfo[0].password) {
|
|
37
103
|
if (bcrypt.compareSync(req.body.password, userInfo[0].password)) {
|
|
38
|
-
const token =
|
|
104
|
+
const token = buildAccessToken(userInfo[0]);
|
|
105
|
+
if (enableRefreshCookieAuth) {
|
|
106
|
+
const refreshToken = buildRefreshToken(userInfo[0]);
|
|
107
|
+
setRefreshCookie(res, refreshToken);
|
|
108
|
+
}
|
|
39
109
|
res.json({
|
|
40
110
|
status: 'success',
|
|
41
111
|
message: 'user found!!!',
|
|
@@ -66,6 +136,74 @@ module.exports = {
|
|
|
66
136
|
});
|
|
67
137
|
});
|
|
68
138
|
|
|
139
|
+
/**
|
|
140
|
+
* POST Refresh
|
|
141
|
+
* Refresh access token using HttpOnly refresh cookie
|
|
142
|
+
*/
|
|
143
|
+
authApp.post('/api/refresh', async function (req, res, next) {
|
|
144
|
+
if (!runtime?.settings?.secureEnabled || !enableRefreshCookieAuth) {
|
|
145
|
+
return res.status(204).end();
|
|
146
|
+
}
|
|
147
|
+
const refreshToken = getCookieValue(req, refreshCookieName);
|
|
148
|
+
if (!refreshToken) {
|
|
149
|
+
return res.status(401).json({ status: 'error', message: 'Refresh token missing' });
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const decoded = jwt.verify(refreshToken, secretCode);
|
|
153
|
+
if (decoded?.type !== 'refresh') {
|
|
154
|
+
clearRefreshCookie(res);
|
|
155
|
+
return res.status(401).json({ status: 'error', message: 'Invalid refresh token' });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let userData = null;
|
|
159
|
+
try {
|
|
160
|
+
const users = await runtime.users.getUsers({ username: decoded.id });
|
|
161
|
+
if (users && users.length) {
|
|
162
|
+
userData = users[0];
|
|
163
|
+
}
|
|
164
|
+
} catch (err) {
|
|
165
|
+
runtime.logger.error(`api refresh: user lookup failed ${err}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const user = {
|
|
169
|
+
username: decoded.id,
|
|
170
|
+
fullname: userData?.fullname,
|
|
171
|
+
groups: userData?.groups || decoded.groups,
|
|
172
|
+
info: userData?.info
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const newAccessToken = buildAccessToken(user);
|
|
176
|
+
const newRefreshToken = buildRefreshToken(user);
|
|
177
|
+
setRefreshCookie(res, newRefreshToken);
|
|
178
|
+
|
|
179
|
+
res.json({
|
|
180
|
+
status: 'success',
|
|
181
|
+
message: 'token refreshed',
|
|
182
|
+
data: {
|
|
183
|
+
username: user.username,
|
|
184
|
+
fullname: user.fullname,
|
|
185
|
+
groups: user.groups,
|
|
186
|
+
info: user.info,
|
|
187
|
+
token: newAccessToken
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
} catch (err) {
|
|
191
|
+
clearRefreshCookie(res);
|
|
192
|
+
res.status(401).json({ status: 'error', message: 'Invalid refresh token' });
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* POST SignOut
|
|
198
|
+
* Clear refresh cookie
|
|
199
|
+
*/
|
|
200
|
+
authApp.post('/api/signout', function (req, res, next) {
|
|
201
|
+
if (enableRefreshCookieAuth) {
|
|
202
|
+
clearRefreshCookie(res);
|
|
203
|
+
}
|
|
204
|
+
res.status(204).end();
|
|
205
|
+
});
|
|
206
|
+
|
|
69
207
|
return authApp;
|
|
70
208
|
}
|
|
71
|
-
}
|
|
209
|
+
}
|
package/api/index.js
CHANGED
|
@@ -56,7 +56,7 @@ function init(_server, _runtime) {
|
|
|
56
56
|
apiApp.use(usersApi.app());
|
|
57
57
|
alarmsApi.init(runtime, authMiddleware, verifyGroups);
|
|
58
58
|
apiApp.use(alarmsApi.app());
|
|
59
|
-
authApi.init(runtime, authJwt.secretCode, authJwt.tokenExpiresIn);
|
|
59
|
+
authApi.init(runtime, authJwt.secretCode, authJwt.tokenExpiresIn, runtime.settings.enableRefreshCookieAuth, runtime.settings.refreshTokenExpiresIn);
|
|
60
60
|
apiApp.use(authApi.app());
|
|
61
61
|
pluginsApi.init(runtime, authMiddleware, verifyGroups);
|
|
62
62
|
apiApp.use(pluginsApi.app());
|
|
@@ -146,9 +146,15 @@ function init(_server, _runtime) {
|
|
|
146
146
|
if (!req.body.secretCode && runtime.settings.secretCode) {
|
|
147
147
|
req.body.secretCode = runtime.settings.secretCode;
|
|
148
148
|
}
|
|
149
|
+
if (req.body.secureEnabled && !req.body.secretCode) {
|
|
150
|
+
req.body.secretCode = utils.generateSecretCode();
|
|
151
|
+
runtime.logger.warn('Generated random JWT secret because secureEnabled=true and no secretCode was provided.');
|
|
152
|
+
}
|
|
149
153
|
const prevAuth = {
|
|
150
154
|
secureEnabled: runtime.settings.secureEnabled,
|
|
151
155
|
tokenExpiresIn: runtime.settings.tokenExpiresIn,
|
|
156
|
+
enableRefreshCookieAuth: runtime.settings.enableRefreshCookieAuth,
|
|
157
|
+
refreshTokenExpiresIn: runtime.settings.refreshTokenExpiresIn,
|
|
152
158
|
secretCode: runtime.settings.secretCode
|
|
153
159
|
};
|
|
154
160
|
if (req.body.nodeRedEnabled === true &&
|
|
@@ -160,9 +166,11 @@ function init(_server, _runtime) {
|
|
|
160
166
|
mergeUserSettings(req.body);
|
|
161
167
|
if (prevAuth.secureEnabled !== runtime.settings.secureEnabled ||
|
|
162
168
|
prevAuth.tokenExpiresIn !== runtime.settings.tokenExpiresIn ||
|
|
169
|
+
prevAuth.enableRefreshCookieAuth !== runtime.settings.enableRefreshCookieAuth ||
|
|
170
|
+
prevAuth.refreshTokenExpiresIn !== runtime.settings.refreshTokenExpiresIn ||
|
|
163
171
|
prevAuth.secretCode !== runtime.settings.secretCode) {
|
|
164
172
|
authJwt.init(runtime.settings.secureEnabled, runtime.settings.secretCode, runtime.settings.tokenExpiresIn);
|
|
165
|
-
authApi.init(runtime, authJwt.secretCode, authJwt.tokenExpiresIn);
|
|
173
|
+
authApi.init(runtime, authJwt.secretCode, authJwt.tokenExpiresIn, runtime.settings.enableRefreshCookieAuth, runtime.settings.refreshTokenExpiresIn);
|
|
166
174
|
}
|
|
167
175
|
runtime.restart(true).then(function(result) {
|
|
168
176
|
res.end();
|
|
@@ -229,6 +237,12 @@ function mergeUserSettings(settings) {
|
|
|
229
237
|
if (!utils.isNullOrUndefined(settings.nodeRedAuthMode)) {
|
|
230
238
|
runtime.settings.nodeRedAuthMode = settings.nodeRedAuthMode;
|
|
231
239
|
}
|
|
240
|
+
if (!utils.isNullOrUndefined(settings.enableRefreshCookieAuth)) {
|
|
241
|
+
runtime.settings.enableRefreshCookieAuth = settings.enableRefreshCookieAuth;
|
|
242
|
+
}
|
|
243
|
+
if (!utils.isNullOrUndefined(settings.refreshTokenExpiresIn)) {
|
|
244
|
+
runtime.settings.refreshTokenExpiresIn = settings.refreshTokenExpiresIn;
|
|
245
|
+
}
|
|
232
246
|
if (!utils.isNullOrUndefined(settings.nodeRedUnsafeModules)) {
|
|
233
247
|
runtime.settings.nodeRedUnsafeModules = settings.nodeRedUnsafeModules;
|
|
234
248
|
}
|
|
@@ -238,6 +252,8 @@ function mergeUserSettings(settings) {
|
|
|
238
252
|
}
|
|
239
253
|
if (settings.secureEnabled) {
|
|
240
254
|
runtime.settings.tokenExpiresIn = settings.tokenExpiresIn;
|
|
255
|
+
runtime.settings.enableRefreshCookieAuth = settings.enableRefreshCookieAuth;
|
|
256
|
+
runtime.settings.refreshTokenExpiresIn = settings.refreshTokenExpiresIn;
|
|
241
257
|
}
|
|
242
258
|
if (settings.smtp) {
|
|
243
259
|
runtime.settings.smtp = settings.smtp;
|
package/api/jwt-helper.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const jwt = require('jsonwebtoken');
|
|
4
|
+
const utils = require('../runtime/utils');
|
|
4
5
|
|
|
5
6
|
var secureEnabled = false;
|
|
6
|
-
|
|
7
|
+
// Runtime fallback secret used only when no persistent secret is configured.
|
|
8
|
+
var secretCode = utils.generateSecretCode();
|
|
7
9
|
var tokenExpiresIn = 60 * 60; // 60 minutes
|
|
8
10
|
const adminGroups = [-1, 255];
|
|
9
11
|
|
package/api/resources/index.js
CHANGED
|
@@ -275,10 +275,13 @@ module.exports = {
|
|
|
275
275
|
var group = { name: resourcesDirs[i], items: [] };
|
|
276
276
|
var dirPath = path.resolve(runtime.settings.widgetsFileDir, resourcesDirs[i]);
|
|
277
277
|
var wwwSubDir = path.join('_widgets', resourcesDirs[i]);
|
|
278
|
-
var files =
|
|
278
|
+
var files = getFilesRecursive(dirPath, ['.svg']);
|
|
279
279
|
for (var x = 0; x < files.length; x++) {
|
|
280
280
|
var filename = files[x];
|
|
281
|
-
group.items.push({
|
|
281
|
+
group.items.push({
|
|
282
|
+
path: path.join(wwwSubDir, files[x]).split(path.sep).join(path.posix.sep),
|
|
283
|
+
name: filename
|
|
284
|
+
});
|
|
282
285
|
}
|
|
283
286
|
result.groups.push(group);
|
|
284
287
|
}
|
|
@@ -358,3 +361,17 @@ function getFiles(pathDir, extensions) {
|
|
|
358
361
|
.filter((item) => extensions.indexOf(path.extname(item).toLowerCase()) !== -1);
|
|
359
362
|
return filesInDIrectory;
|
|
360
363
|
}
|
|
364
|
+
|
|
365
|
+
function getFilesRecursive(pathDir, extensions, baseDir = pathDir) {
|
|
366
|
+
const entries = fs.readdirSync(pathDir, { withFileTypes: true });
|
|
367
|
+
const files = [];
|
|
368
|
+
for (const entry of entries) {
|
|
369
|
+
const entryPath = path.join(pathDir, entry.name);
|
|
370
|
+
if (entry.isDirectory()) {
|
|
371
|
+
files.push(...getFilesRecursive(entryPath, extensions, baseDir));
|
|
372
|
+
} else if (extensions.indexOf(path.extname(entry.name).toLowerCase()) !== -1) {
|
|
373
|
+
files.push(path.relative(baseDir, entryPath));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return files;
|
|
377
|
+
}
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
@angular/animations
|
|
2
2
|
MIT
|
|
3
|
+
The MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
|
15
|
+
all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
THE SOFTWARE.
|
|
24
|
+
|
|
3
25
|
|
|
4
26
|
@angular/cdk
|
|
5
27
|
MIT
|
|
6
28
|
The MIT License
|
|
7
29
|
|
|
8
|
-
Copyright (c)
|
|
30
|
+
Copyright (c) 2024 Google LLC.
|
|
9
31
|
|
|
10
32
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
33
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -28,18 +50,84 @@ THE SOFTWARE.
|
|
|
28
50
|
|
|
29
51
|
@angular/common
|
|
30
52
|
MIT
|
|
53
|
+
The MIT License
|
|
54
|
+
|
|
55
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
56
|
+
|
|
57
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
58
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
59
|
+
in the Software without restriction, including without limitation the rights
|
|
60
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
61
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
62
|
+
furnished to do so, subject to the following conditions:
|
|
63
|
+
|
|
64
|
+
The above copyright notice and this permission notice shall be included in
|
|
65
|
+
all copies or substantial portions of the Software.
|
|
66
|
+
|
|
67
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
68
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
69
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
70
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
71
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
72
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
73
|
+
THE SOFTWARE.
|
|
74
|
+
|
|
31
75
|
|
|
32
76
|
@angular/core
|
|
33
77
|
MIT
|
|
78
|
+
The MIT License
|
|
79
|
+
|
|
80
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
81
|
+
|
|
82
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
83
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
84
|
+
in the Software without restriction, including without limitation the rights
|
|
85
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
86
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
87
|
+
furnished to do so, subject to the following conditions:
|
|
88
|
+
|
|
89
|
+
The above copyright notice and this permission notice shall be included in
|
|
90
|
+
all copies or substantial portions of the Software.
|
|
91
|
+
|
|
92
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
93
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
94
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
95
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
96
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
97
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
98
|
+
THE SOFTWARE.
|
|
99
|
+
|
|
34
100
|
|
|
35
101
|
@angular/forms
|
|
36
102
|
MIT
|
|
103
|
+
The MIT License
|
|
104
|
+
|
|
105
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
106
|
+
|
|
107
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
108
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
109
|
+
in the Software without restriction, including without limitation the rights
|
|
110
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
111
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
112
|
+
furnished to do so, subject to the following conditions:
|
|
113
|
+
|
|
114
|
+
The above copyright notice and this permission notice shall be included in
|
|
115
|
+
all copies or substantial portions of the Software.
|
|
116
|
+
|
|
117
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
118
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
119
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
120
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
121
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
122
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
123
|
+
THE SOFTWARE.
|
|
124
|
+
|
|
37
125
|
|
|
38
126
|
@angular/material
|
|
39
127
|
MIT
|
|
40
128
|
The MIT License
|
|
41
129
|
|
|
42
|
-
Copyright (c)
|
|
130
|
+
Copyright (c) 2024 Google LLC.
|
|
43
131
|
|
|
44
132
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
45
133
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -64,7 +152,7 @@ THE SOFTWARE.
|
|
|
64
152
|
MIT
|
|
65
153
|
The MIT License
|
|
66
154
|
|
|
67
|
-
Copyright (c)
|
|
155
|
+
Copyright (c) 2024 Google LLC.
|
|
68
156
|
|
|
69
157
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
70
158
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -87,9 +175,53 @@ THE SOFTWARE.
|
|
|
87
175
|
|
|
88
176
|
@angular/platform-browser
|
|
89
177
|
MIT
|
|
178
|
+
The MIT License
|
|
179
|
+
|
|
180
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
181
|
+
|
|
182
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
183
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
184
|
+
in the Software without restriction, including without limitation the rights
|
|
185
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
186
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
187
|
+
furnished to do so, subject to the following conditions:
|
|
188
|
+
|
|
189
|
+
The above copyright notice and this permission notice shall be included in
|
|
190
|
+
all copies or substantial portions of the Software.
|
|
191
|
+
|
|
192
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
193
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
194
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
195
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
196
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
197
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
198
|
+
THE SOFTWARE.
|
|
199
|
+
|
|
90
200
|
|
|
91
201
|
@angular/router
|
|
92
202
|
MIT
|
|
203
|
+
The MIT License
|
|
204
|
+
|
|
205
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
206
|
+
|
|
207
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
208
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
209
|
+
in the Software without restriction, including without limitation the rights
|
|
210
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
211
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
212
|
+
furnished to do so, subject to the following conditions:
|
|
213
|
+
|
|
214
|
+
The above copyright notice and this permission notice shall be included in
|
|
215
|
+
all copies or substantial portions of the Software.
|
|
216
|
+
|
|
217
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
218
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
219
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
220
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
221
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
222
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
223
|
+
THE SOFTWARE.
|
|
224
|
+
|
|
93
225
|
|
|
94
226
|
@babel/runtime
|
|
95
227
|
MIT
|
|
@@ -179,7 +311,7 @@ angular-gridster2
|
|
|
179
311
|
MIT
|
|
180
312
|
MIT License
|
|
181
313
|
|
|
182
|
-
Copyright (c)
|
|
314
|
+
Copyright (c) 2024 Tiberiu Zuld
|
|
183
315
|
|
|
184
316
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
185
317
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -990,7 +1122,7 @@ MIT
|
|
|
990
1122
|
The MIT License (MIT)
|
|
991
1123
|
|
|
992
1124
|
Copyright (c) 2014-2015 bpampuch
|
|
993
|
-
2016-
|
|
1125
|
+
2016-2026 liborm85
|
|
994
1126
|
|
|
995
1127
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
996
1128
|
this software and associated documentation files (the "Software"), to deal in
|
|
@@ -1222,7 +1354,7 @@ socket.io-parser
|
|
|
1222
1354
|
MIT
|
|
1223
1355
|
(The MIT License)
|
|
1224
1356
|
|
|
1225
|
-
Copyright (c) 2014 Guillermo Rauch
|
|
1357
|
+
Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors
|
|
1226
1358
|
|
|
1227
1359
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
1228
1360
|
this software and associated documentation files (the 'Software'), to deal in
|
|
@@ -1316,7 +1448,7 @@ zone.js
|
|
|
1316
1448
|
MIT
|
|
1317
1449
|
The MIT License
|
|
1318
1450
|
|
|
1319
|
-
Copyright (c) 2010-
|
|
1451
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.io/license
|
|
1320
1452
|
|
|
1321
1453
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1322
1454
|
of this software and associated documentation files (the "Software"), to deal
|
package/dist/assets/i18n/de.json
CHANGED
|
@@ -834,6 +834,8 @@
|
|
|
834
834
|
"device.tag-daq-changed": "Wert speichern, wenn geändert",
|
|
835
835
|
"device.tag-daq-interval": "Intervall für Speichern (Sek.)",
|
|
836
836
|
"device.tag-format": "Ziffern formatieren (2 = #.##)",
|
|
837
|
+
|
|
838
|
+
"device.tag-uns-path": "UNS Path",
|
|
837
839
|
"device.tag-scale": "Skalierungsmodus",
|
|
838
840
|
"device.tag-scale-mode-undefined": "Keine Skalierung",
|
|
839
841
|
"device.tag-scale-mode-undefined-tooltip": "Tag-Wert",
|
|
@@ -1240,6 +1242,11 @@
|
|
|
1240
1242
|
"dlg.app-settings-daqstore": "DAQ-Speicher",
|
|
1241
1243
|
"dlg.app-settings-daqstore-type": "Datenbanktyp",
|
|
1242
1244
|
"dlg.app-settings-daqstore-url": "URL",
|
|
1245
|
+
"dlg.app-settings-daqstore-configurl": "Config URL",
|
|
1246
|
+
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",
|
|
1247
|
+
|
|
1248
|
+
"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
|
|
1249
|
+
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
|
|
1243
1250
|
"dlg.app-settings-daqstore-token": "Token",
|
|
1244
1251
|
"dlg.app-settings-daqstore-bucket": "Bucket",
|
|
1245
1252
|
"dlg.app-settings-daqstore-organization": "Organisation",
|
|
@@ -1306,3 +1313,6 @@
|
|
|
1306
1313
|
"msg.report-build-error": "Senden zum Erstellen des Berichts fehlgeschlagen!",
|
|
1307
1314
|
"msg.device-tags-request-result": "Lade {{value}} von {{current}}"
|
|
1308
1315
|
}
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
|
package/dist/assets/i18n/en.json
CHANGED
|
@@ -992,6 +992,7 @@
|
|
|
992
992
|
"device.property-name": "Name",
|
|
993
993
|
"device.property-type": "Type",
|
|
994
994
|
"device.property-polling": "Polling",
|
|
995
|
+
"device.property-polling-warning": "Warning: Low polling intervals may cause high CPU and network load. Use with care.",
|
|
995
996
|
"device.property-enable": "Enable",
|
|
996
997
|
"device.property-subscribe": "Subscribe",
|
|
997
998
|
"device.property-address": "Address (IP or opc.tcp://[server]:[port])",
|
|
@@ -1153,6 +1154,8 @@
|
|
|
1153
1154
|
|
|
1154
1155
|
"device.tag-format": "Format digits (2 = #.##)",
|
|
1155
1156
|
"device.tag-deadband": "Deadband",
|
|
1157
|
+
|
|
1158
|
+
"device.tag-uns-path": "UNS Path",
|
|
1156
1159
|
"device.tag-scale": "Scale Mode / Convertion",
|
|
1157
1160
|
"device.tag-scale-mode-undefined": "No Scaling",
|
|
1158
1161
|
"device.tag-scale-mode-undefined-tooltip": "Tag Value",
|
|
@@ -1811,6 +1814,11 @@
|
|
|
1811
1814
|
"dlg.app-settings-daqstore": "DAQ storage",
|
|
1812
1815
|
"dlg.app-settings-daqstore-type": "Database type",
|
|
1813
1816
|
"dlg.app-settings-daqstore-url": "URL",
|
|
1817
|
+
"dlg.app-settings-daqstore-configurl": "Config URL",
|
|
1818
|
+
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",
|
|
1819
|
+
|
|
1820
|
+
"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
|
|
1821
|
+
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
|
|
1814
1822
|
"dlg.app-settings-daqstore-token": "Token",
|
|
1815
1823
|
"dlg.app-settings-daqstore-bucket": "Bucket",
|
|
1816
1824
|
"dlg.app-settings-daqstore-organization": "Organization",
|
|
@@ -1868,7 +1876,7 @@
|
|
|
1868
1876
|
"msg.alarmproperty-missing-value": "Some values are missing!",
|
|
1869
1877
|
"msg.textproperty-error-exist": "Text-ID exists!",
|
|
1870
1878
|
"msg.textproperty-missing-value": "Some values are missing!",
|
|
1871
|
-
"msg.device-remove": "Would you like to remove Device?",
|
|
1879
|
+
"msg.device-remove": "Would you like to remove Device '{{value}}'?",
|
|
1872
1880
|
"msg.device-tag-remove": "Would you like to remove Tag?",
|
|
1873
1881
|
"msg.device-tag-exist": "Tag name exists!",
|
|
1874
1882
|
"msg.device-tag-invalid-char": "The '@' character is not allowed in tag names!",
|
|
@@ -1884,7 +1892,7 @@
|
|
|
1884
1892
|
"msg.project-load-error": "Unable to read '{{value}}'",
|
|
1885
1893
|
"msg.project": "Would you like to save the Project changes?",
|
|
1886
1894
|
"msg.tags-remove-all": "Would you like to remove all Tags?",
|
|
1887
|
-
"msg.view-remove": "Would you like to remove View '{{value}}'?",
|
|
1895
|
+
"msg.view-remove": "Would you like to remove View '{{value}}' ?",
|
|
1888
1896
|
"msg.chart-remove": "Would you like to remove Chart '{{value}}'?",
|
|
1889
1897
|
"msg.role-remove": "Would you like to remove Role '{{value}}'?",
|
|
1890
1898
|
"msg.graph-remove": "Would you like to remove Bar chart '{{value}}'?",
|
|
@@ -1895,7 +1903,7 @@
|
|
|
1895
1903
|
"msg.sendmail-success": "Mail send successful!",
|
|
1896
1904
|
"msg.sendmail-error": "Mail send failed!",
|
|
1897
1905
|
"msg.users-save-error": "User save failed!",
|
|
1898
|
-
"msg.user-remove": "Would you like to remove User ",
|
|
1906
|
+
"msg.user-remove": "Would you like to remove User '{{value}}'?",
|
|
1899
1907
|
"msg.project-save-success": "Project save successful!",
|
|
1900
1908
|
"msg.project-save-error": "Project save failed!",
|
|
1901
1909
|
"msg.project-format-error": "Project wrong format!",
|
|
@@ -1930,3 +1938,6 @@
|
|
|
1930
1938
|
"msg.operation-unauthorized": "Operation Unauthorized!",
|
|
1931
1939
|
"msg.secret-code-required": "Secret code required to sign authentication tokens"
|
|
1932
1940
|
}
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
|
package/dist/assets/i18n/es.json
CHANGED
|
@@ -544,6 +544,9 @@
|
|
|
544
544
|
"device-tag-dialog-title": "Etiqueta seleccionada",
|
|
545
545
|
|
|
546
546
|
"device.tag-options-title": "Opciones de etiquetas",
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
"device.tag-uns-path": "UNS Path",
|
|
547
550
|
"device.tag-daq-enabled": "Registration Enabled",
|
|
548
551
|
"device.tag-daq-changed": "Guardar valor si cambia",
|
|
549
552
|
"device.tag-daq-interval": "Intervalo para guardar valor (segundos)",
|
|
@@ -736,6 +739,12 @@
|
|
|
736
739
|
"dlg.app-settings-server-port": "Servidor esta escuchando el puerto",
|
|
737
740
|
"dlg.app-settings-alarms-clear": "Borrar todas las alarmas y el historias",
|
|
738
741
|
"dlg.app-settings-auth-token": "Autenticación con token",
|
|
742
|
+
"dlg.app-settings-daqstore-url": "URL",
|
|
743
|
+
"dlg.app-settings-daqstore-configurl": "Config URL",
|
|
744
|
+
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",
|
|
745
|
+
|
|
746
|
+
"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
|
|
747
|
+
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
|
|
739
748
|
"dlg.app-auth-disabled": "Deshabilitado",
|
|
740
749
|
"dlg.app-auth-expiration-15m": "Habilitado con token expira en 15 min.",
|
|
741
750
|
"dlg.app-auth-expiration-1h": "Habilitado con token expira en 1 hora.",
|
|
@@ -774,3 +783,6 @@
|
|
|
774
783
|
"msg.editor-mode-locked": "El editor ya esta abierto!",
|
|
775
784
|
"msg.alarms-clear-success": "Todas las alarmas han sido canceladas!"
|
|
776
785
|
}
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
package/dist/assets/i18n/fr.json
CHANGED
|
@@ -1009,6 +1009,8 @@
|
|
|
1009
1009
|
|
|
1010
1010
|
"device.tag-format": "Format du nombre (2 = #.##)",
|
|
1011
1011
|
"device.tag-deadband": "Zone morte",
|
|
1012
|
+
|
|
1013
|
+
"device.tag-uns-path": "UNS Path",
|
|
1012
1014
|
"device.tag-scale": "Mode mise à l'échelle / Conversion",
|
|
1013
1015
|
"device.tag-scale-mode-undefined": "Pas de mise à l'échelle",
|
|
1014
1016
|
"device.tag-scale-mode-undefined-tooltip": "Valeur du tag",
|
|
@@ -1618,6 +1620,11 @@
|
|
|
1618
1620
|
"dlg.app-settings-daqstore": "Stockage DAQ",
|
|
1619
1621
|
"dlg.app-settings-daqstore-type": "Type de base de données",
|
|
1620
1622
|
"dlg.app-settings-daqstore-url": "URL",
|
|
1623
|
+
"dlg.app-settings-daqstore-configurl": "Config URL",
|
|
1624
|
+
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",
|
|
1625
|
+
|
|
1626
|
+
"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
|
|
1627
|
+
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
|
|
1621
1628
|
"dlg.app-settings-daqstore-token": "Jeton",
|
|
1622
1629
|
"dlg.app-settings-daqstore-bucket": "Seau",
|
|
1623
1630
|
"dlg.app-settings-daqstore-organization": "Organisation",
|
|
@@ -1715,3 +1722,6 @@
|
|
|
1715
1722
|
"msg.texts-text-remove": "Souhaitez-vous supprimer le texte '{{value}}' ?",
|
|
1716
1723
|
"msg.operation-unauthorized": "Opération non autorisée !"
|
|
1717
1724
|
}
|
|
1725
|
+
|
|
1726
|
+
|
|
1727
|
+
|