tina4-python 0.2.122__py3-none-any.whl
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.
- tina4_python/Auth.py +222 -0
- tina4_python/Constant.py +43 -0
- tina4_python/Database.py +591 -0
- tina4_python/DatabaseResult.py +107 -0
- tina4_python/DatabaseTypes.py +15 -0
- tina4_python/Debug.py +126 -0
- tina4_python/Env.py +37 -0
- tina4_python/Localization.py +42 -0
- tina4_python/Messages.py +30 -0
- tina4_python/MiddleWare.py +90 -0
- tina4_python/Migration.py +107 -0
- tina4_python/ORM.py +639 -0
- tina4_python/Queue.py +615 -0
- tina4_python/Request.py +19 -0
- tina4_python/Response.py +121 -0
- tina4_python/Router.py +423 -0
- tina4_python/Session.py +342 -0
- tina4_python/ShellColors.py +20 -0
- tina4_python/Swagger.py +228 -0
- tina4_python/Template.py +107 -0
- tina4_python/Webserver.py +429 -0
- tina4_python/Websocket.py +49 -0
- tina4_python/__init__.py +392 -0
- tina4_python/messages.pot +83 -0
- tina4_python/public/css/readme.md +0 -0
- tina4_python/public/favicon.ico +0 -0
- tina4_python/public/images/403.png +0 -0
- tina4_python/public/images/404.png +0 -0
- tina4_python/public/images/500.png +0 -0
- tina4_python/public/images/logo.png +0 -0
- tina4_python/public/images/readme.md +0 -0
- tina4_python/public/js/readme.md +0 -0
- tina4_python/public/js/reconnecting-websocket.js +365 -0
- tina4_python/public/js/tina4helper.js +397 -0
- tina4_python/public/swagger/index.html +90 -0
- tina4_python/public/swagger/oauth2-redirect.html +63 -0
- tina4_python/templates/errors/403.twig +10 -0
- tina4_python/templates/errors/404.twig +10 -0
- tina4_python/templates/errors/500.twig +11 -0
- tina4_python/templates/readme.md +1 -0
- tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/en/LC_MESSAGES/messages.po +80 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.po +84 -0
- tina4_python-0.2.122.dist-info/METADATA +465 -0
- tina4_python-0.2.122.dist-info/RECORD +47 -0
- tina4_python-0.2.122.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
var formToken = null;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sends an http request
|
|
5
|
+
* @param url
|
|
6
|
+
* @param request
|
|
7
|
+
* @param method
|
|
8
|
+
* @param callback
|
|
9
|
+
*/
|
|
10
|
+
function sendRequest (url, request, method, callback) {
|
|
11
|
+
if (url === undefined) {
|
|
12
|
+
url = "";
|
|
13
|
+
}
|
|
14
|
+
if (request === undefined) {
|
|
15
|
+
request = null;
|
|
16
|
+
}
|
|
17
|
+
if (method === undefined) {
|
|
18
|
+
method = 'GET';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//Inject the new token
|
|
22
|
+
if (formToken !== null) {
|
|
23
|
+
const regex = /formToken=(.*)/gm;
|
|
24
|
+
const subst = `formToken=${formToken}`;
|
|
25
|
+
url = url.replace(regex, subst);
|
|
26
|
+
if (url.indexOf('formToken') === -1) {
|
|
27
|
+
if (url.indexOf('?') === -1) {
|
|
28
|
+
url += '?formToken='+formToken;
|
|
29
|
+
} else {
|
|
30
|
+
url += '&formToken='+formToken;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const xhr = new XMLHttpRequest();
|
|
36
|
+
xhr.open(method, url, true);
|
|
37
|
+
|
|
38
|
+
xhr.onreadystatechange = function () {
|
|
39
|
+
if (xhr.readyState === 4 && xhr.status === 200) {
|
|
40
|
+
let content = xhr.response;
|
|
41
|
+
|
|
42
|
+
if (xhr.getResponseHeader('FreshToken') !== '' && xhr.getResponseHeader('FreshToken') !== null) {
|
|
43
|
+
formToken = xhr.getResponseHeader('FreshToken');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
content = JSON.parse(content);
|
|
48
|
+
callback(content);
|
|
49
|
+
} catch (exception) {
|
|
50
|
+
callback (content);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
} else if (xhr.status !== 200) {
|
|
54
|
+
let content = xhr.response;
|
|
55
|
+
console.log('An unexpected response occurred while sending request',url, content, xhr.status, xhr.readyState, xhr, xhr.getResponseHeader('Location'));
|
|
56
|
+
callback(xhr.status+" An error occurred, see the console")
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (method === 'POST') {
|
|
61
|
+
xhr.send(request);
|
|
62
|
+
} else {
|
|
63
|
+
xhr.send(null);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets form data based on a form Id
|
|
69
|
+
* @param formId
|
|
70
|
+
* @returns {FormData}
|
|
71
|
+
*/
|
|
72
|
+
function getFormData(formId) {
|
|
73
|
+
let data = new FormData();
|
|
74
|
+
let elements = document.querySelectorAll("#" + formId + " select, #" + formId + " input, #" + formId + " textarea");
|
|
75
|
+
for (let ie = 0; ie < elements.length; ie++ )
|
|
76
|
+
{
|
|
77
|
+
let element = elements[ie];
|
|
78
|
+
//refresh the token
|
|
79
|
+
if (element.name === 'formToken' && formToken !== null) {
|
|
80
|
+
element.value = formToken;
|
|
81
|
+
}
|
|
82
|
+
if (element.name) {
|
|
83
|
+
if (element.type === 'file') {
|
|
84
|
+
for (let i = 0; i < element.files.length; i++) {
|
|
85
|
+
let fileData = element.files[i];
|
|
86
|
+
let elementName = element.name;
|
|
87
|
+
if (fileData !== undefined) {
|
|
88
|
+
if (element.files.length > 1 && !elementName.includes('[')) {
|
|
89
|
+
elementName = elementName + '[]';
|
|
90
|
+
}
|
|
91
|
+
data.append(elementName, fileData, fileData.name);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} else if (element.type === 'checkbox' || element.type === 'radio') {
|
|
95
|
+
if (element.checked) {
|
|
96
|
+
data.append(element.name, element.value)
|
|
97
|
+
} else {
|
|
98
|
+
if (element.type !== 'radio') {
|
|
99
|
+
data.append(element.name, "0")
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
if (element.value === '') {
|
|
104
|
+
element.value = null;
|
|
105
|
+
}
|
|
106
|
+
data.append(element.name, element.value);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Handles the data returned from a request
|
|
115
|
+
* @param data
|
|
116
|
+
* @param targetElement
|
|
117
|
+
*/
|
|
118
|
+
function handleHtmlData(data, targetElement) {
|
|
119
|
+
//Strip out the scripts
|
|
120
|
+
if (data === "") return '';
|
|
121
|
+
const parser = new DOMParser();
|
|
122
|
+
const htmlData = parser.parseFromString(data.includes !== undefined && data.includes('<html>') ? data : '<body>'+data+'</body></html>', 'text/html');
|
|
123
|
+
const body = htmlData.querySelector('body');
|
|
124
|
+
const scripts = body.querySelectorAll('script');
|
|
125
|
+
// remove the script tags
|
|
126
|
+
body.querySelectorAll('script').forEach(script => script.remove());
|
|
127
|
+
|
|
128
|
+
if (targetElement !== null) {
|
|
129
|
+
if (body.children.length > 0) {
|
|
130
|
+
document.getElementById(targetElement).replaceChildren(...body.children);
|
|
131
|
+
} else {
|
|
132
|
+
document.getElementById(targetElement).replaceChildren(body.innerHTML);
|
|
133
|
+
}
|
|
134
|
+
if (scripts) {
|
|
135
|
+
scripts.forEach(script => {
|
|
136
|
+
const newScript = document.createElement("script");
|
|
137
|
+
newScript.type = 'text/javascript';
|
|
138
|
+
newScript.async = true;
|
|
139
|
+
newScript.textContent = script.innerText;
|
|
140
|
+
document.getElementById(targetElement).append(newScript);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
if (scripts) {
|
|
145
|
+
scripts.forEach(script => {
|
|
146
|
+
const newScript = document.createElement("script");
|
|
147
|
+
newScript.type = 'text/javascript';
|
|
148
|
+
newScript.async = true;
|
|
149
|
+
newScript.textContent = script.innerText;
|
|
150
|
+
document.body.append(newScript);
|
|
151
|
+
console.log(newScript);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return body.innerHTML;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return '';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Loads a page to a target html element
|
|
163
|
+
* @param loadURL
|
|
164
|
+
* @param targetElement
|
|
165
|
+
* @param callback
|
|
166
|
+
* @callback
|
|
167
|
+
*/
|
|
168
|
+
function loadPage(loadURL, targetElement, callback = null) {
|
|
169
|
+
if (targetElement === undefined) targetElement = 'content';
|
|
170
|
+
sendRequest(loadURL, null, "GET", function(data) {
|
|
171
|
+
let processedHTML = '';
|
|
172
|
+
if (document.getElementById(targetElement) !== null) {
|
|
173
|
+
processedHTML = handleHtmlData(data, targetElement);
|
|
174
|
+
} else {
|
|
175
|
+
if (callback) {
|
|
176
|
+
callback(data);
|
|
177
|
+
} else {
|
|
178
|
+
console.log('TINA4 - define targetElement or callback for loadPage', data);
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (callback) {
|
|
184
|
+
callback(processedHTML, data);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Shows a form from a URL in a target html element
|
|
191
|
+
* @param action
|
|
192
|
+
* @param loadURL
|
|
193
|
+
* @param targetElement
|
|
194
|
+
* @param callback
|
|
195
|
+
*/
|
|
196
|
+
function showForm(action, loadURL, targetElement, callback = null) {
|
|
197
|
+
if (targetElement === undefined) targetElement = 'form';
|
|
198
|
+
|
|
199
|
+
if (action === 'create') action = 'GET';
|
|
200
|
+
if (action === 'edit') action = 'GET';
|
|
201
|
+
if (action === 'delete') action = 'DELETE';
|
|
202
|
+
|
|
203
|
+
sendRequest(loadURL, null, action, function(data) {
|
|
204
|
+
let processedHTML = '';
|
|
205
|
+
if (data.message !== undefined) {
|
|
206
|
+
processedHTML = handleHtmlData ((data.message), targetElement);
|
|
207
|
+
} else {
|
|
208
|
+
if (document.getElementById(targetElement) !== null) {
|
|
209
|
+
processedHTML = handleHtmlData (data, targetElement);
|
|
210
|
+
} else {
|
|
211
|
+
if (callback) {
|
|
212
|
+
callback(data);
|
|
213
|
+
} else {
|
|
214
|
+
console.log('TINA4 - define targetElement or callback for showForm', data);
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (callback) {
|
|
221
|
+
callback(processedHTML);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Post URL posts data to a specific url
|
|
228
|
+
* @param url
|
|
229
|
+
* @param data
|
|
230
|
+
* @param targetElement
|
|
231
|
+
* @param callback
|
|
232
|
+
*/
|
|
233
|
+
function postUrl(url, data, targetElement, callback= null) {
|
|
234
|
+
sendRequest(url, data, 'POST', function(data) {
|
|
235
|
+
let processedHTML = '';
|
|
236
|
+
if (data.message !== undefined) {
|
|
237
|
+
processedHTML = handleHtmlData ((data.message), targetElement);
|
|
238
|
+
} else {
|
|
239
|
+
if (document.getElementById(targetElement) !== null) {
|
|
240
|
+
processedHTML = handleHtmlData (data, targetElement);
|
|
241
|
+
} else {
|
|
242
|
+
if (callback) {
|
|
243
|
+
callback(data);
|
|
244
|
+
} else {
|
|
245
|
+
console.log('TINA4 - define targetElement or callback for postUrl', data);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (callback) {
|
|
252
|
+
callback(processedHTML,data)
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Saves a form to a POST end point
|
|
259
|
+
* @param formId
|
|
260
|
+
* @param targetURL
|
|
261
|
+
* @param targetElement
|
|
262
|
+
* @param callback - optional
|
|
263
|
+
*/
|
|
264
|
+
function saveForm(formId, targetURL, targetElement, callback = null) {
|
|
265
|
+
if (targetElement === undefined) targetElement = 'message';
|
|
266
|
+
//compile a data model
|
|
267
|
+
let data = getFormData(formId);
|
|
268
|
+
|
|
269
|
+
postUrl(targetURL, data, targetElement, callback);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Alias of saveForm
|
|
274
|
+
* @param formId
|
|
275
|
+
* @param targetURL
|
|
276
|
+
* @param targetElement
|
|
277
|
+
* @param callback
|
|
278
|
+
*/
|
|
279
|
+
function postForm(formId, targetURL, targetElement, callback = null){
|
|
280
|
+
saveForm(formId, targetURL, targetElement, callback)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Alias of saveForm
|
|
285
|
+
* @param formId
|
|
286
|
+
* @param targetURL
|
|
287
|
+
* @param targetElement
|
|
288
|
+
* @param callback
|
|
289
|
+
*/
|
|
290
|
+
function submitForm(formId, targetURL, targetElement, callback = null){
|
|
291
|
+
saveForm(formId, targetURL, targetElement, callback)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Shows a message
|
|
296
|
+
* @param message
|
|
297
|
+
* @param alertType
|
|
298
|
+
* @param element
|
|
299
|
+
*/
|
|
300
|
+
function showMessage(message, alertType, element) {
|
|
301
|
+
if (alertType === undefined) {
|
|
302
|
+
alertType = 'info';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (!element) {
|
|
306
|
+
element = "message";
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
document.getElementById(element).innerHTML = '<div class="alert alert-' + alertType + ' alert-dismissible fade show" role="alert"><strong>Info</strong> ' + message + '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button></div>';
|
|
310
|
+
|
|
311
|
+
// Function to close alert after 10 seconds with a slide-up effect.
|
|
312
|
+
$(".alert").delay(10000).slideUp(200, function() {
|
|
313
|
+
$(this).alert('close');
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Set cookie
|
|
319
|
+
* @param name
|
|
320
|
+
* @param value
|
|
321
|
+
* @param days
|
|
322
|
+
*/
|
|
323
|
+
function setCookie(name, value, days) {
|
|
324
|
+
let expires = "";
|
|
325
|
+
if (days) {
|
|
326
|
+
let date = new Date();
|
|
327
|
+
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
328
|
+
expires = "; expires=" + date.toUTCString();
|
|
329
|
+
}
|
|
330
|
+
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Get cookie
|
|
335
|
+
* @param name
|
|
336
|
+
* @returns {null|string}
|
|
337
|
+
*/
|
|
338
|
+
function getCookie(name) {
|
|
339
|
+
let nameEQ = name + "=";
|
|
340
|
+
let ca = document.cookie.split(';');
|
|
341
|
+
for (let i = 0; i < ca.length; i++) {
|
|
342
|
+
var c = ca[i];
|
|
343
|
+
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
|
344
|
+
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
345
|
+
}
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//https://stackoverflow.com/questions/4068373/center-a-popup-window-on-screen
|
|
350
|
+
const popupCenter = ({url, title, w, h}) => {
|
|
351
|
+
// Fixes dual-screen position Most browsers Firefox
|
|
352
|
+
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
|
|
353
|
+
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
|
|
354
|
+
|
|
355
|
+
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
|
356
|
+
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
|
357
|
+
|
|
358
|
+
const systemZoom = width / window.screen.availWidth;
|
|
359
|
+
const left = (width - w) / 2 / systemZoom + dualScreenLeft
|
|
360
|
+
const top = (height - h) / 2 / systemZoom + dualScreenTop
|
|
361
|
+
const newWindow = window.open(url, title,
|
|
362
|
+
`
|
|
363
|
+
directories=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,
|
|
364
|
+
width=${w / systemZoom},
|
|
365
|
+
height=${h / systemZoom},
|
|
366
|
+
top=${top},
|
|
367
|
+
left=${left}
|
|
368
|
+
`
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if (window.focus) newWindow.focus();
|
|
372
|
+
return newWindow;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Opens a popup window
|
|
377
|
+
* @param pdfReportPath
|
|
378
|
+
*/
|
|
379
|
+
function openReport(pdfReportPath){
|
|
380
|
+
if (pdfReportPath.indexOf("No data available") < 0){
|
|
381
|
+
open(pdfReportPath, "content", "target=_blank, toolbar=no, scrollbars=yes, resizable=yes, width=800, height=600, top=0, left=0");
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
window.alert("Sorry , unable to print a report according to your selection!");
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Does a GET request to an end point
|
|
390
|
+
* @param loadURL
|
|
391
|
+
* @param callback
|
|
392
|
+
*/
|
|
393
|
+
function getRoute(loadURL, callback) {
|
|
394
|
+
sendRequest(loadURL, null, 'GET', function(data) {
|
|
395
|
+
callback(handleHtmlData (data, null));
|
|
396
|
+
});
|
|
397
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Swagger UI</title>
|
|
6
|
+
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700"
|
|
7
|
+
rel="stylesheet">
|
|
8
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui.min.css" integrity="sha512-+9UD8YSD9GF7FzOH38L9S6y56aYNx3R4dYbOCgvTJ2ZHpJScsahNdaMQJU/8osUiz9FPu0YZ8wdKf4evUbsGSg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
9
|
+
<style>
|
|
10
|
+
html {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
overflow: -moz-scrollbars-vertical;
|
|
13
|
+
overflow-y: scroll;
|
|
14
|
+
}
|
|
15
|
+
*,
|
|
16
|
+
*:before,
|
|
17
|
+
*:after {
|
|
18
|
+
box-sizing: inherit;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
body {
|
|
22
|
+
margin: 0;
|
|
23
|
+
background: #fafafa;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
26
|
+
</head>
|
|
27
|
+
|
|
28
|
+
<body>
|
|
29
|
+
|
|
30
|
+
<svg style="position:absolute;width:0;height:0"
|
|
31
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
32
|
+
<defs>
|
|
33
|
+
<symbol id="unlocked" viewBox="0 0 20 20">
|
|
34
|
+
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
|
35
|
+
</symbol>
|
|
36
|
+
|
|
37
|
+
<symbol id="locked" viewBox="0 0 20 20">
|
|
38
|
+
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
|
39
|
+
</symbol>
|
|
40
|
+
|
|
41
|
+
<symbol id="close" viewBox="0 0 20 20">
|
|
42
|
+
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
|
43
|
+
</symbol>
|
|
44
|
+
|
|
45
|
+
<symbol id="large-arrow" viewBox="0 0 20 20">
|
|
46
|
+
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
|
47
|
+
</symbol>
|
|
48
|
+
|
|
49
|
+
<symbol id="large-arrow-down" viewBox="0 0 20 20">
|
|
50
|
+
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
|
51
|
+
</symbol>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
<symbol id="jump-to" viewBox="0 0 24 24">
|
|
55
|
+
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
|
56
|
+
</symbol>
|
|
57
|
+
|
|
58
|
+
<symbol id="expand" viewBox="0 0 24 24">
|
|
59
|
+
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
|
60
|
+
</symbol>
|
|
61
|
+
|
|
62
|
+
</defs>
|
|
63
|
+
</svg>
|
|
64
|
+
|
|
65
|
+
<div id="swagger-ui"></div>
|
|
66
|
+
|
|
67
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-bundle.js" integrity="sha512-mVvFSCxt0sK0FeL8C7n8BcHh10quzdwfxQbjRaw9pRdKNNep3YQusJS5e2/q4GYt4Ma5yWXSJraoQzXPgZd2EQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
68
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-standalone-preset.min.js" integrity="sha512-UrYi+60Ci3WWWcoDXbMmzpoi1xpERbwjPGij6wTh8fXl81qNdioNNHExr9ttnBebKF0ZbVnPlTPlw+zECUK1Xw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
69
|
+
<script>
|
|
70
|
+
window.onload = function () {
|
|
71
|
+
|
|
72
|
+
// Build a system
|
|
73
|
+
const ui = SwaggerUIBundle({
|
|
74
|
+
url: "{SWAGGER_ROUTE}/swagger.json",
|
|
75
|
+
dom_id: '#swagger-ui',
|
|
76
|
+
deepLinking: true,
|
|
77
|
+
presets: [
|
|
78
|
+
SwaggerUIBundle.presets.apis
|
|
79
|
+
],
|
|
80
|
+
plugins: [
|
|
81
|
+
SwaggerUIBundle.plugins.DownloadUrl
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
window.ui = ui
|
|
86
|
+
}
|
|
87
|
+
</script>
|
|
88
|
+
</body>
|
|
89
|
+
|
|
90
|
+
</html>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<body onload="run()">
|
|
4
|
+
</body>
|
|
5
|
+
</html>
|
|
6
|
+
<script>
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
function run() {
|
|
10
|
+
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
|
11
|
+
var sentState = oauth2.state;
|
|
12
|
+
var redirectUrl = oauth2.redirectUrl;
|
|
13
|
+
var isValid, qp, arr;
|
|
14
|
+
|
|
15
|
+
if (/code|token|error/.test(window.location.hash)) {
|
|
16
|
+
qp = window.location.hash.substring(1);
|
|
17
|
+
} else {
|
|
18
|
+
qp = location.search.substring(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
arr = qp.split("&")
|
|
22
|
+
arr.forEach(function (v, i, _arr) {
|
|
23
|
+
_arr[i] = '"' + v.replace('=', '":"') + '"';
|
|
24
|
+
})
|
|
25
|
+
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
|
26
|
+
function (key, value) {
|
|
27
|
+
return key === "" ? value : decodeURIComponent(value)
|
|
28
|
+
}
|
|
29
|
+
) : {}
|
|
30
|
+
|
|
31
|
+
isValid = qp.state === sentState
|
|
32
|
+
|
|
33
|
+
if ((
|
|
34
|
+
oauth2.auth.schema.get("flow") === "accessCode" ||
|
|
35
|
+
oauth2.auth.schema.get("flow") === "authorizationCode"
|
|
36
|
+
) && !oauth2.auth.code) {
|
|
37
|
+
if (!isValid) {
|
|
38
|
+
oauth2.errCb({
|
|
39
|
+
authId: oauth2.auth.name,
|
|
40
|
+
source: "auth",
|
|
41
|
+
level: "warning",
|
|
42
|
+
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (qp.code) {
|
|
47
|
+
delete oauth2.state;
|
|
48
|
+
oauth2.auth.code = qp.code;
|
|
49
|
+
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
|
50
|
+
} else {
|
|
51
|
+
oauth2.errCb({
|
|
52
|
+
authId: oauth2.auth.name,
|
|
53
|
+
source: "auth",
|
|
54
|
+
level: "error",
|
|
55
|
+
message: "Authorization failed: no accessCode received from the server"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
|
60
|
+
}
|
|
61
|
+
window.close();
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>403 Error - {{ server.REQUEST_URI }}</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body style="text-align: center">
|
|
7
|
+
<h2>Well this is really amazing, you must have hit this end point up incorrectly {{ server.url }}!</h2>
|
|
8
|
+
<img src="{{ baseURL }}/images/403.png" alt="403 Error - {{ server.url }}">
|
|
9
|
+
</body>
|
|
10
|
+
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>404 Error - {{ server.url }}</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body style="text-align: center">
|
|
7
|
+
<h2>Well this is really amazing, we haven't created any content for {{ server.url }}!</h2>
|
|
8
|
+
<img src="{{ baseURL }}/images/404.png" alt="404 Error - {{ server.url }}">
|
|
9
|
+
</body>
|
|
10
|
+
</html>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>500 Error - {{ server.url }}</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body style="text-align: center">
|
|
7
|
+
<h2>Oops, somebody pushed some code that broke stuff on {{ server.url }}!</h2>
|
|
8
|
+
<img src="{{ baseURL }}/images/500.png" alt="500 Error - {{ server.url }}">
|
|
9
|
+
<pre>{{ error_message }}</pre>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
### Use the templates folder to store your twig files
|
|
Binary file
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# English translations for Tin4Python.
|
|
2
|
+
# This file is distributed under the same license as the Tin4Python project.
|
|
3
|
+
msgid ""
|
|
4
|
+
msgstr ""
|
|
5
|
+
"Project-Id-Version: PROJECT VERSION\n"
|
|
6
|
+
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
|
7
|
+
"POT-Creation-Date: 2024-02-14 17:55+0200\n"
|
|
8
|
+
"PO-Revision-Date: 2024-02-14 17:56+0200\n"
|
|
9
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
10
|
+
"Language: en\n"
|
|
11
|
+
"Language-Team: en <LL@li.org>\n"
|
|
12
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=utf-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Generated-By: Babel 2.13.1\n"
|
|
17
|
+
|
|
18
|
+
#: tina4_python/Messages.py:5
|
|
19
|
+
msgid "Debug: {message}"
|
|
20
|
+
msgstr "Debug: {message}"
|
|
21
|
+
|
|
22
|
+
#: tina4_python/Messages.py:6
|
|
23
|
+
msgid "Warning: {message}"
|
|
24
|
+
msgstr "Warning: {message}"
|
|
25
|
+
|
|
26
|
+
#: tina4_python/Messages.py:7
|
|
27
|
+
msgid "Error: {message}"
|
|
28
|
+
msgstr "Error: {message}"
|
|
29
|
+
|
|
30
|
+
#: tina4_python/Messages.py:8
|
|
31
|
+
msgid "Info: {message}"
|
|
32
|
+
msgstr "Info: {message}"
|
|
33
|
+
|
|
34
|
+
#: tina4_python/Messages.py:12
|
|
35
|
+
msgid "Matching: {matching}"
|
|
36
|
+
msgstr "Matching: {matching}"
|
|
37
|
+
|
|
38
|
+
#: tina4_python/Messages.py:13
|
|
39
|
+
msgid "Variables: {variables}"
|
|
40
|
+
msgstr "Variables: {variables}"
|
|
41
|
+
|
|
42
|
+
#: tina4_python/Messages.py:14
|
|
43
|
+
msgid "Root Path {root_path} {url}"
|
|
44
|
+
msgstr "Root Path {root_path} {url}"
|
|
45
|
+
|
|
46
|
+
#: tina4_python/Messages.py:15
|
|
47
|
+
msgid "Attempting to serve static file: {static_file}"
|
|
48
|
+
msgstr "Attempting to serve static file: {static_file}"
|
|
49
|
+
|
|
50
|
+
#: tina4_python/Messages.py:16
|
|
51
|
+
msgid "Attempting to serve CSS file: {css_file}"
|
|
52
|
+
msgstr "Attempting to serve CSS file: {css_file}"
|
|
53
|
+
|
|
54
|
+
#: tina4_python/Messages.py:17
|
|
55
|
+
msgid "Attempting to serve image file: {image_file}"
|
|
56
|
+
msgstr "Attempting to serve image file: {image_file}"
|
|
57
|
+
|
|
58
|
+
#: tina4_python/__init__.py:14
|
|
59
|
+
msgid "Assuming root path: {root_path}, library path: {library_path}"
|
|
60
|
+
msgstr "Assuming root path: {root_path}, library path: {library_path}"
|
|
61
|
+
|
|
62
|
+
#: tina4_python/__init__.py:15
|
|
63
|
+
msgid "Load all things"
|
|
64
|
+
msgstr "Load all things"
|
|
65
|
+
|
|
66
|
+
#: tina4_python/__init__.py:16
|
|
67
|
+
msgid "Server started http://{host_name}:{port}"
|
|
68
|
+
msgstr "Server started http://{host_name}:{port}"
|
|
69
|
+
|
|
70
|
+
#: tina4_python/__init__.py:17
|
|
71
|
+
msgid "Server stopped."
|
|
72
|
+
msgstr "Server stopped."
|
|
73
|
+
|
|
74
|
+
#: tina4_python/__init__.py:18
|
|
75
|
+
msgid "Starting webserver on {port}"
|
|
76
|
+
msgstr "Starting webserver on {port}"
|
|
77
|
+
|
|
78
|
+
#: tina4_python/__init__.py:19
|
|
79
|
+
msgid "Entry point name ... {name}"
|
|
80
|
+
msgstr "Entry point name ... {name}"
|
|
Binary file
|