tina4ruby 0.5.2 → 3.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/README.md +434 -544
- data/exe/{tina4 → tina4ruby} +1 -0
- data/lib/tina4/ai.rb +312 -0
- data/lib/tina4/auth.rb +44 -3
- data/lib/tina4/auto_crud.rb +163 -0
- data/lib/tina4/cli.rb +389 -97
- data/lib/tina4/constants.rb +46 -0
- data/lib/tina4/cors.rb +74 -0
- data/lib/tina4/database/sqlite3_adapter.rb +139 -0
- data/lib/tina4/database.rb +144 -7
- data/lib/tina4/debug.rb +4 -79
- data/lib/tina4/dev_admin.rb +1162 -0
- data/lib/tina4/dev_mailbox.rb +191 -0
- data/lib/tina4/dev_reload.rb +9 -9
- data/lib/tina4/drivers/firebird_driver.rb +19 -3
- data/lib/tina4/drivers/mssql_driver.rb +3 -3
- data/lib/tina4/drivers/mysql_driver.rb +4 -4
- data/lib/tina4/drivers/postgres_driver.rb +9 -2
- data/lib/tina4/drivers/sqlite_driver.rb +1 -1
- data/lib/tina4/env.rb +42 -2
- data/lib/tina4/error_overlay.rb +252 -0
- data/lib/tina4/events.rb +90 -0
- data/lib/tina4/field_types.rb +4 -0
- data/lib/tina4/frond.rb +1497 -0
- data/lib/tina4/gallery/auth/meta.json +1 -0
- data/lib/tina4/gallery/auth/src/routes/api/gallery_auth.rb +114 -0
- data/lib/tina4/gallery/database/meta.json +1 -0
- data/lib/tina4/gallery/database/src/routes/api/gallery_db.rb +43 -0
- data/lib/tina4/gallery/error-overlay/meta.json +1 -0
- data/lib/tina4/gallery/error-overlay/src/routes/api/gallery_crash.rb +17 -0
- data/lib/tina4/gallery/orm/meta.json +1 -0
- data/lib/tina4/gallery/orm/src/routes/api/gallery_products.rb +16 -0
- data/lib/tina4/gallery/queue/meta.json +1 -0
- data/lib/tina4/gallery/queue/src/routes/api/gallery_queue.rb +325 -0
- data/lib/tina4/gallery/rest-api/meta.json +1 -0
- data/lib/tina4/gallery/rest-api/src/routes/api/gallery_hello.rb +14 -0
- data/lib/tina4/gallery/templates/meta.json +1 -0
- data/lib/tina4/gallery/templates/src/routes/gallery_page.rb +12 -0
- data/lib/tina4/gallery/templates/src/templates/gallery_page.twig +257 -0
- data/lib/tina4/health.rb +39 -0
- data/lib/tina4/html_element.rb +148 -0
- data/lib/tina4/localization.rb +2 -2
- data/lib/tina4/log.rb +203 -0
- data/lib/tina4/messenger.rb +562 -0
- data/lib/tina4/migration.rb +132 -29
- data/lib/tina4/orm.rb +463 -35
- data/lib/tina4/public/css/tina4.css +178 -1
- data/lib/tina4/public/css/tina4.min.css +1 -2
- data/lib/tina4/public/favicon.ico +0 -0
- data/lib/tina4/public/images/logo.svg +5 -0
- data/lib/tina4/public/images/tina4-logo-icon.webp +0 -0
- data/lib/tina4/public/js/frond.min.js +420 -0
- data/lib/tina4/public/js/tina4-dev-admin.min.js +367 -0
- data/lib/tina4/public/js/tina4.min.js +93 -0
- data/lib/tina4/public/swagger/index.html +90 -0
- data/lib/tina4/public/swagger/oauth2-redirect.html +63 -0
- data/lib/tina4/queue.rb +162 -6
- data/lib/tina4/queue_backends/lite_backend.rb +88 -0
- data/lib/tina4/rack_app.rb +331 -27
- data/lib/tina4/rate_limiter.rb +123 -0
- data/lib/tina4/request.rb +61 -15
- data/lib/tina4/response.rb +54 -24
- data/lib/tina4/response_cache.rb +551 -0
- data/lib/tina4/router.rb +90 -15
- data/lib/tina4/scss_compiler.rb +2 -2
- data/lib/tina4/seeder.rb +56 -61
- data/lib/tina4/service_runner.rb +303 -0
- data/lib/tina4/session.rb +85 -0
- data/lib/tina4/session_handlers/mongo_handler.rb +1 -1
- data/lib/tina4/session_handlers/valkey_handler.rb +43 -0
- data/lib/tina4/shutdown.rb +84 -0
- data/lib/tina4/sql_translation.rb +295 -0
- data/lib/tina4/template.rb +36 -6
- data/lib/tina4/templates/base.twig +2 -2
- data/lib/tina4/templates/errors/302.twig +14 -0
- data/lib/tina4/templates/errors/401.twig +9 -0
- data/lib/tina4/templates/errors/403.twig +22 -15
- data/lib/tina4/templates/errors/404.twig +22 -15
- data/lib/tina4/templates/errors/500.twig +31 -15
- data/lib/tina4/templates/errors/502.twig +9 -0
- data/lib/tina4/templates/errors/503.twig +12 -0
- data/lib/tina4/templates/errors/base.twig +37 -0
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4/webserver.rb +28 -18
- data/lib/tina4.rb +118 -21
- metadata +68 -8
- data/lib/tina4/public/js/tina4.js +0 -134
- data/lib/tina4/public/js/tina4helper.js +0 -387
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
if (typeof define === 'function' && define.amd) {
|
|
3
|
+
define([], factory);
|
|
4
|
+
} else if (typeof module !== 'undefined' && module.exports){
|
|
5
|
+
module.exports = factory();
|
|
6
|
+
} else {
|
|
7
|
+
global.ReconnectingWebSocket = factory();
|
|
8
|
+
}
|
|
9
|
+
})(this, function () {
|
|
10
|
+
if (!('WebSocket' in window)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
function ReconnectingWebSocket(url, protocols, options) {
|
|
14
|
+
var settings = {
|
|
15
|
+
debug: false,
|
|
16
|
+
automaticOpen: true,
|
|
17
|
+
reconnectInterval: 1000,
|
|
18
|
+
maxReconnectInterval: 30000,
|
|
19
|
+
reconnectDecay: 1.5,
|
|
20
|
+
timeoutInterval: 2000,
|
|
21
|
+
maxReconnectAttempts: null,
|
|
22
|
+
binaryType: 'blob'
|
|
23
|
+
}
|
|
24
|
+
if (!options) { options = {}; }
|
|
25
|
+
for (var key in settings) {
|
|
26
|
+
if (typeof options[key] !== 'undefined') {
|
|
27
|
+
this[key] = options[key];
|
|
28
|
+
} else {
|
|
29
|
+
this[key] = settings[key];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
this.url = url;
|
|
33
|
+
this.reconnectAttempts = 0;
|
|
34
|
+
this.readyState = WebSocket.CONNECTING;
|
|
35
|
+
this.protocol = null;
|
|
36
|
+
var self = this;
|
|
37
|
+
var ws;
|
|
38
|
+
var forcedClose = false;
|
|
39
|
+
var timedOut = false;
|
|
40
|
+
var eventTarget = document.createElement('div');
|
|
41
|
+
eventTarget.addEventListener('open', function(event) { self.onopen(event); });
|
|
42
|
+
eventTarget.addEventListener('close', function(event) { self.onclose(event); });
|
|
43
|
+
eventTarget.addEventListener('connecting', function(event) { self.onconnecting(event); });
|
|
44
|
+
eventTarget.addEventListener('message', function(event) { self.onmessage(event); });
|
|
45
|
+
eventTarget.addEventListener('error', function(event) { self.onerror(event); });
|
|
46
|
+
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
|
|
47
|
+
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
|
|
48
|
+
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
|
|
49
|
+
function generateEvent(s, args) {
|
|
50
|
+
var evt = document.createEvent("CustomEvent");
|
|
51
|
+
evt.initCustomEvent(s, false, false, args);
|
|
52
|
+
return evt;
|
|
53
|
+
};
|
|
54
|
+
this.open = function (reconnectAttempt) {
|
|
55
|
+
ws = new WebSocket(self.url, protocols || []);
|
|
56
|
+
ws.binaryType = this.binaryType;
|
|
57
|
+
if (reconnectAttempt) {
|
|
58
|
+
if (this.maxReconnectAttempts && this.reconnectAttempts > this.maxReconnectAttempts) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
eventTarget.dispatchEvent(generateEvent('connecting'));
|
|
63
|
+
this.reconnectAttempts = 0;
|
|
64
|
+
}
|
|
65
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
66
|
+
console.debug('ReconnectingWebSocket', 'attempt-connect', self.url);
|
|
67
|
+
}
|
|
68
|
+
var localWs = ws;
|
|
69
|
+
var timeout = setTimeout(function() {
|
|
70
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
71
|
+
console.debug('ReconnectingWebSocket', 'connection-timeout', self.url);
|
|
72
|
+
}
|
|
73
|
+
timedOut = true;
|
|
74
|
+
localWs.close();
|
|
75
|
+
timedOut = false;
|
|
76
|
+
}, self.timeoutInterval);
|
|
77
|
+
ws.onopen = function(event) {
|
|
78
|
+
clearTimeout(timeout);
|
|
79
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
80
|
+
console.debug('ReconnectingWebSocket', 'onopen', self.url);
|
|
81
|
+
}
|
|
82
|
+
self.protocol = ws.protocol;
|
|
83
|
+
self.readyState = WebSocket.OPEN;
|
|
84
|
+
self.reconnectAttempts = 0;
|
|
85
|
+
var e = generateEvent('open');
|
|
86
|
+
e.isReconnect = reconnectAttempt;
|
|
87
|
+
reconnectAttempt = false;
|
|
88
|
+
eventTarget.dispatchEvent(e);
|
|
89
|
+
};
|
|
90
|
+
ws.onclose = function(event) {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
ws = null;
|
|
93
|
+
if (forcedClose) {
|
|
94
|
+
self.readyState = WebSocket.CLOSED;
|
|
95
|
+
eventTarget.dispatchEvent(generateEvent('close'));
|
|
96
|
+
} else {
|
|
97
|
+
self.readyState = WebSocket.CONNECTING;
|
|
98
|
+
var e = generateEvent('connecting');
|
|
99
|
+
e.code = event.code;
|
|
100
|
+
e.reason = event.reason;
|
|
101
|
+
e.wasClean = event.wasClean;
|
|
102
|
+
eventTarget.dispatchEvent(e);
|
|
103
|
+
if (!reconnectAttempt && !timedOut) {
|
|
104
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
105
|
+
console.debug('ReconnectingWebSocket', 'onclose', self.url);
|
|
106
|
+
}
|
|
107
|
+
eventTarget.dispatchEvent(generateEvent('close'));
|
|
108
|
+
}
|
|
109
|
+
var timeout = self.reconnectInterval * Math.pow(self.reconnectDecay, self.reconnectAttempts);
|
|
110
|
+
setTimeout(function() {
|
|
111
|
+
self.reconnectAttempts++;
|
|
112
|
+
self.open(true);
|
|
113
|
+
}, timeout > self.maxReconnectInterval ? self.maxReconnectInterval : timeout);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
ws.onmessage = function(event) {
|
|
117
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
118
|
+
console.debug('ReconnectingWebSocket', 'onmessage', self.url, event.data);
|
|
119
|
+
}
|
|
120
|
+
var e = generateEvent('message');
|
|
121
|
+
e.data = event.data;
|
|
122
|
+
eventTarget.dispatchEvent(e);
|
|
123
|
+
};
|
|
124
|
+
ws.onerror = function(event) {
|
|
125
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
126
|
+
console.debug('ReconnectingWebSocket', 'onerror', self.url, event);
|
|
127
|
+
}
|
|
128
|
+
eventTarget.dispatchEvent(generateEvent('error'));
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (this.automaticOpen == true) {
|
|
132
|
+
this.open(false);
|
|
133
|
+
}
|
|
134
|
+
this.send = function(data) {
|
|
135
|
+
if (ws) {
|
|
136
|
+
if (self.debug || ReconnectingWebSocket.debugAll) {
|
|
137
|
+
console.debug('ReconnectingWebSocket', 'send', self.url, data);
|
|
138
|
+
}
|
|
139
|
+
return ws.send(data);
|
|
140
|
+
} else {
|
|
141
|
+
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
this.close = function(code, reason) {
|
|
145
|
+
if (typeof code == 'undefined') {
|
|
146
|
+
code = 1000;
|
|
147
|
+
}
|
|
148
|
+
forcedClose = true;
|
|
149
|
+
if (ws) {
|
|
150
|
+
ws.close(code, reason);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
this.refresh = function() {
|
|
154
|
+
if (ws) {
|
|
155
|
+
ws.close();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
ReconnectingWebSocket.prototype.onopen = function(event) {};
|
|
160
|
+
ReconnectingWebSocket.prototype.onclose = function(event) {};
|
|
161
|
+
ReconnectingWebSocket.prototype.onconnecting = function(event) {};
|
|
162
|
+
ReconnectingWebSocket.prototype.onmessage = function(event) {};
|
|
163
|
+
ReconnectingWebSocket.prototype.onerror = function(event) {};
|
|
164
|
+
ReconnectingWebSocket.debugAll = false;
|
|
165
|
+
ReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;
|
|
166
|
+
ReconnectingWebSocket.OPEN = WebSocket.OPEN;
|
|
167
|
+
ReconnectingWebSocket.CLOSING = WebSocket.CLOSING;
|
|
168
|
+
ReconnectingWebSocket.CLOSED = WebSocket.CLOSED;
|
|
169
|
+
return ReconnectingWebSocket;
|
|
170
|
+
});
|
|
171
|
+
var formToken = null;
|
|
172
|
+
function sendRequest(url, request, method, callback) {
|
|
173
|
+
if (url === undefined) url = "";
|
|
174
|
+
if (request === undefined) request = null;
|
|
175
|
+
if (method === undefined) method = 'GET';
|
|
176
|
+
const xhr = new XMLHttpRequest();
|
|
177
|
+
xhr.open(method, url, true);
|
|
178
|
+
if (formToken !== null) {
|
|
179
|
+
xhr.setRequestHeader('Authorization', 'Bearer ' + formToken);
|
|
180
|
+
}
|
|
181
|
+
let isFormData = request instanceof FormData;
|
|
182
|
+
if (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT' || method.toUpperCase() === 'PATCH') {
|
|
183
|
+
if (isFormData) {
|
|
184
|
+
} else if (typeof request === 'object' && request !== null) {
|
|
185
|
+
request = JSON.stringify(request);
|
|
186
|
+
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
|
187
|
+
} else if (typeof request === 'string') {
|
|
188
|
+
xhr.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
xhr.onload = function () {
|
|
192
|
+
let content = xhr.response;
|
|
193
|
+
const freshToken = xhr.getResponseHeader('FreshToken');
|
|
194
|
+
if (freshToken && freshToken !== '') {
|
|
195
|
+
formToken = freshToken;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
content = JSON.parse(content);
|
|
199
|
+
} catch (e) {
|
|
200
|
+
}
|
|
201
|
+
if (typeof callback === 'function') {
|
|
202
|
+
callback(content, xhr.status, xhr);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
xhr.onerror = function () {
|
|
206
|
+
if (typeof callback === 'function') {
|
|
207
|
+
callback(null, xhr.status, xhr);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
xhr.send(request);
|
|
211
|
+
}
|
|
212
|
+
function getFormData(formId) {
|
|
213
|
+
let data = new FormData();
|
|
214
|
+
let elements = document.querySelectorAll("#" + formId + " select, #" + formId + " input, #" + formId + " textarea");
|
|
215
|
+
for (let ie = 0; ie < elements.length; ie++ )
|
|
216
|
+
{
|
|
217
|
+
let element = elements[ie];
|
|
218
|
+
if (element.name === 'formToken' && formToken !== null) {
|
|
219
|
+
element.value = formToken;
|
|
220
|
+
}
|
|
221
|
+
if (element.name) {
|
|
222
|
+
if (element.type === 'file') {
|
|
223
|
+
for (let i = 0; i < element.files.length; i++) {
|
|
224
|
+
let fileData = element.files[i];
|
|
225
|
+
let elementName = element.name;
|
|
226
|
+
if (fileData !== undefined) {
|
|
227
|
+
if (element.files.length > 1 && !elementName.includes('[')) {
|
|
228
|
+
elementName = elementName + '[]';
|
|
229
|
+
}
|
|
230
|
+
data.append(elementName, fileData, fileData.name);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
} else if (element.type === 'checkbox' || element.type === 'radio') {
|
|
234
|
+
if (element.checked) {
|
|
235
|
+
data.append(element.name, element.value)
|
|
236
|
+
} else {
|
|
237
|
+
if (element.type !== 'radio') {
|
|
238
|
+
data.append(element.name, "0")
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
if (element.value === '') {
|
|
243
|
+
element.value = null;
|
|
244
|
+
}
|
|
245
|
+
data.append(element.name, element.value);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return data;
|
|
250
|
+
}
|
|
251
|
+
function handleHtmlData(data, targetElement) {
|
|
252
|
+
if (data === "") return '';
|
|
253
|
+
const parser = new DOMParser();
|
|
254
|
+
const htmlData = parser.parseFromString(data.includes !== undefined && data.includes('<html>') ? data : '<body>'+data+'</body></html>', 'text/html');
|
|
255
|
+
const body = htmlData.querySelector('body');
|
|
256
|
+
const scripts = body.querySelectorAll('script');
|
|
257
|
+
body.querySelectorAll('script').forEach(script => script.remove());
|
|
258
|
+
if (targetElement !== null) {
|
|
259
|
+
if (body.children.length > 0) {
|
|
260
|
+
document.getElementById(targetElement).replaceChildren(...body.children);
|
|
261
|
+
} else {
|
|
262
|
+
document.getElementById(targetElement).replaceChildren(body.innerHTML);
|
|
263
|
+
}
|
|
264
|
+
if (scripts) {
|
|
265
|
+
scripts.forEach(script => {
|
|
266
|
+
const newScript = document.createElement("script");
|
|
267
|
+
newScript.type = 'text/javascript';
|
|
268
|
+
newScript.async = true;
|
|
269
|
+
newScript.textContent = script.innerText;
|
|
270
|
+
document.getElementById(targetElement).append(newScript);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
if (scripts) {
|
|
275
|
+
scripts.forEach(script => {
|
|
276
|
+
const newScript = document.createElement("script");
|
|
277
|
+
newScript.type = 'text/javascript';
|
|
278
|
+
newScript.async = true;
|
|
279
|
+
newScript.textContent = script.innerText;
|
|
280
|
+
document.body.append(newScript);
|
|
281
|
+
console.log(newScript);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return body.innerHTML;
|
|
285
|
+
}
|
|
286
|
+
return '';
|
|
287
|
+
}
|
|
288
|
+
function loadPage(loadURL, targetElement, callback = null) {
|
|
289
|
+
if (targetElement === undefined) targetElement = 'content';
|
|
290
|
+
sendRequest(loadURL, null, "GET", function(data) {
|
|
291
|
+
let processedHTML = '';
|
|
292
|
+
if (document.getElementById(targetElement) !== null) {
|
|
293
|
+
processedHTML = handleHtmlData(data, targetElement);
|
|
294
|
+
} else {
|
|
295
|
+
if (callback) {
|
|
296
|
+
callback(data);
|
|
297
|
+
} else {
|
|
298
|
+
console.log('TINA4 - define targetElement or callback for loadPage', data);
|
|
299
|
+
}
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (callback) {
|
|
303
|
+
callback(processedHTML, data);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function showForm(action, loadURL, targetElement, callback = null) {
|
|
308
|
+
if (targetElement === undefined) targetElement = 'form';
|
|
309
|
+
if (action === 'create') action = 'GET';
|
|
310
|
+
if (action === 'edit') action = 'GET';
|
|
311
|
+
if (action === 'delete') action = 'DELETE';
|
|
312
|
+
sendRequest(loadURL, null, action, function(data) {
|
|
313
|
+
let processedHTML = '';
|
|
314
|
+
if (data.message !== undefined) {
|
|
315
|
+
processedHTML = handleHtmlData ((data.message), targetElement);
|
|
316
|
+
} else {
|
|
317
|
+
if (document.getElementById(targetElement) !== null) {
|
|
318
|
+
processedHTML = handleHtmlData (data, targetElement);
|
|
319
|
+
} else {
|
|
320
|
+
if (callback) {
|
|
321
|
+
callback(data);
|
|
322
|
+
} else {
|
|
323
|
+
console.log('TINA4 - define targetElement or callback for showForm', data);
|
|
324
|
+
}
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (callback) {
|
|
329
|
+
callback(processedHTML);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
function postUrl(url, data, targetElement, callback= null) {
|
|
334
|
+
sendRequest(url, data, 'POST', function(data) {
|
|
335
|
+
let processedHTML = '';
|
|
336
|
+
if (data.message !== undefined) {
|
|
337
|
+
processedHTML = handleHtmlData ((data.message), targetElement);
|
|
338
|
+
} else {
|
|
339
|
+
if (document.getElementById(targetElement) !== null) {
|
|
340
|
+
processedHTML = handleHtmlData (data, targetElement);
|
|
341
|
+
} else {
|
|
342
|
+
if (callback) {
|
|
343
|
+
callback(data);
|
|
344
|
+
} else {
|
|
345
|
+
console.log('TINA4 - define targetElement or callback for postUrl', data);
|
|
346
|
+
}
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (callback) {
|
|
351
|
+
callback(processedHTML,data)
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function saveForm(formId, targetURL, targetElement, callback = null) {
|
|
356
|
+
if (targetElement === undefined) targetElement = 'message';
|
|
357
|
+
let data = getFormData(formId);
|
|
358
|
+
postUrl(targetURL, data, targetElement, callback);
|
|
359
|
+
}
|
|
360
|
+
function postForm(formId, targetURL, targetElement, callback = null){
|
|
361
|
+
saveForm(formId, targetURL, targetElement, callback)
|
|
362
|
+
}
|
|
363
|
+
function submitForm(formId, targetURL, targetElement, callback = null){
|
|
364
|
+
saveForm(formId, targetURL, targetElement, callback)
|
|
365
|
+
}
|
|
366
|
+
function showMessage(message) {
|
|
367
|
+
document.getElementById('message').innerHTML = '<div class="alert alert-info alert-dismissible fade show"><strong>Info</strong> ' + message + '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>';
|
|
368
|
+
}
|
|
369
|
+
function setCookie(name, value, days) {
|
|
370
|
+
let expires = "";
|
|
371
|
+
if (days) {
|
|
372
|
+
let date = new Date();
|
|
373
|
+
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
374
|
+
expires = "; expires=" + date.toUTCString();
|
|
375
|
+
}
|
|
376
|
+
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
|
377
|
+
}
|
|
378
|
+
function getCookie(name) {
|
|
379
|
+
let nameEQ = name + "=";
|
|
380
|
+
let ca = document.cookie.split(';');
|
|
381
|
+
for (let i = 0; i < ca.length; i++) {
|
|
382
|
+
var c = ca[i];
|
|
383
|
+
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
|
384
|
+
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const popupCenter = ({url, title, w, h}) => {
|
|
389
|
+
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
|
|
390
|
+
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
|
|
391
|
+
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
|
392
|
+
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
|
393
|
+
const systemZoom = width / window.screen.availWidth;
|
|
394
|
+
const left = (width - w) / 2 / systemZoom + dualScreenLeft
|
|
395
|
+
const top = (height - h) / 2 / systemZoom + dualScreenTop
|
|
396
|
+
const newWindow = window.open(url, title,
|
|
397
|
+
`
|
|
398
|
+
directories=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,
|
|
399
|
+
width=${w / systemZoom},
|
|
400
|
+
height=${h / systemZoom},
|
|
401
|
+
top=${top},
|
|
402
|
+
left=${left}
|
|
403
|
+
`
|
|
404
|
+
)
|
|
405
|
+
if (window.focus) newWindow.focus();
|
|
406
|
+
return newWindow;
|
|
407
|
+
}
|
|
408
|
+
function openReport(pdfReportPath){
|
|
409
|
+
if (pdfReportPath.indexOf("No data available") < 0){
|
|
410
|
+
open(pdfReportPath, "content", "target=_blank, toolbar=no, scrollbars=yes, resizable=yes, width=800, height=600, top=0, left=0");
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
window.alert("Sorry , unable to print a report according to your selection!");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function getRoute(loadURL, callback) {
|
|
417
|
+
sendRequest(loadURL, null, 'GET', function(data) {
|
|
418
|
+
callback(handleHtmlData (data, null));
|
|
419
|
+
});
|
|
420
|
+
}
|