improve structure

This commit is contained in:
Dennis Eichhorn 2022-08-16 19:09:02 +02:00
parent 5252b76ef3
commit d4c7a05f72
13 changed files with 172 additions and 96 deletions

View File

@ -1,5 +1,6 @@
import { LogLevel } from './LogLevel.js'; import { LogLevel } from './LogLevel.js';
import { Request } from '../Message/Request/Request.js'; import { Request } from '../Message/Request/Request.js';
import { SystemUtils } from '../System/SystemUtils.js';
/** /**
* Logger class. * Logger class.
@ -63,7 +64,7 @@ export class Logger
* *
* @since 1.0.0 * @since 1.0.0
*/ */
interpolate (message, context, level) interpolate (message, context)
{ {
message = typeof message === 'undefined' ? Logger.MSG_FULL : message; message = typeof message === 'undefined' ? Logger.MSG_FULL : message;
@ -89,13 +90,15 @@ export class Logger
*/ */
createContext (message, context, level) createContext (message, context, level)
{ {
context.datetime = (new Date()).toISOString(); context.backtrace = console.trace();
context.version = '1.0.0'; context.datetime = (new Date()).toISOString();
context.os = Request.getOS(); context.version = '1.0.0';
context.browser = Request.getBrowser(); context.os = SystemUtils.getOS();
context.path = window.location.href; context.browser = SystemUtils.getBrowser();
context.level = level; context.path = window.location.href;
context.message = message; context.datetime = (new Date()).toString();
context.level = level;
context.message = message;
return context; return context;
}; };
@ -120,11 +123,11 @@ export class Logger
} }
if (this.ui) { if (this.ui) {
this.writeUi(message, context, level); this.writeUi(message, context);
} }
if (this.remote) { if (this.remote) {
this.writeRemote(message, context, level); this.writeRemote(context);
} }
}; };
@ -133,20 +136,19 @@ export class Logger
* *
* @param {string} message Message to display * @param {string} message Message to display
* @param {Object} [context] Context to put into message * @param {Object} [context] Context to put into message
* @param {string} level Log level
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
writeUi (message, context, level) writeUi (message, context)
{ {
/** global: Notification */ /** global: Notification */
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') { if (Notification.permission !== 'granted' && Notification.permission !== 'denied') {
Notification.requestPermission().then(function (permission) { }); Notification.requestPermission().then(function (permission) { });
} }
const notification = new Notification('Logger', { body: this.interpolate(message, context, level) }); const notification = new Notification('Logger', { body: this.interpolate(message, context) });
setTimeout(notification.close.bind(notification), 4000); setTimeout(notification.close.bind(notification), 4000);
}; };
@ -192,15 +194,13 @@ export class Logger
/** /**
* Create remote log message * Create remote log message
* *
* @param {string} message Message to display
* @param {Object} [context] Context to put into message * @param {Object} [context] Context to put into message
* @param {string} level Log level
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
writeRemote (message, context, level) writeRemote (context)
{ {
const request = new Request(); const request = new Request();
request.setData(context); request.setData(context);

View File

@ -1,7 +1,5 @@
import { Logger } from '../../Log/Logger.js'; import { Logger } from '../../Log/Logger.js';
import { UriFactory } from '../../Uri/UriFactory.js'; import { UriFactory } from '../../Uri/UriFactory.js';
import { BrowserType } from './BrowserType.js';
import { OSType } from './OSType.js';
import { RequestMethod } from './RequestMethod.js'; import { RequestMethod } from './RequestMethod.js';
import { RequestType } from './RequestType.js'; import { RequestType } from './RequestType.js';
@ -85,61 +83,6 @@ export class Request
} }
}; };
/**
* Get browser.
*
* @return {string}
*
* @since 1.0.0
*/
static getBrowser ()
{
/** global: InstallTrigger */
/** global: navigator */
/** global: window */
if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
return BrowserType.OPERA;
} else if (typeof InstallTrigger !== 'undefined') {
return BrowserType.FIREFOX;
} else if (Object.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
return BrowserType.SAFARI;
} else if (/* @cc_on!@ */false || !!document.documentMode) {
return BrowserType.IE;
} else if (!!window.StyleMedia) {
return BrowserType.EDGE;
} else if (!!window.chrome && !!window.chrome.webstore) {
return BrowserType.CHROME;
} else if (((typeof isChrome !== 'undefined' && isChrome)
|| (typeof isOpera !== 'undefined' && isOpera))
&& !!window.CSS
) {
return BrowserType.BLINK;
}
return BrowserType.UNKNOWN;
};
/**
* Get os.
*
* @return {string}
*
* @since 1.0.0
*/
static getOS ()
{
for (const os in OSType) {
if (Object.prototype.hasOwnProperty.call(OSType, os)) {
/** global: navigator */
if (navigator.appVersion.toLowerCase().indexOf(OSType[os]) !== -1) {
return OSType[os];
}
}
}
return OSType.UNKNOWN;
};
/** /**
* Set request method. * Set request method.
* *
@ -378,13 +321,20 @@ export class Request
if (this.xhr.readyState !== 1) { if (this.xhr.readyState !== 1) {
if (this.type === RequestType.FORM_DATA) { if (this.type === RequestType.FORM_DATA) {
let url = this.uri; // GET request doesn't allow body/payload. Therefor we have to put the data into the uri
for (let pair of this.data.entries()) { if (this.method === RequestMethod.GET) {
url += '&' + pair[0] + '=' + pair[1]; let url = this.uri;
} for (let pair of this.data.entries()) {
url += '&' + pair[0] + '=' + pair[1];
}
this.xhr.open(this.method, UriFactory.build(url)); this.xhr.open(this.method, UriFactory.build(url));
} else {
this.xhr.open(this.method, UriFactory.build(this.uri));
}
} else { } else {
console.log(UriFactory.build(this.uri));
this.xhr.open(this.method, UriFactory.build(this.uri)); this.xhr.open(this.method, UriFactory.build(this.uri));
} }
@ -421,11 +371,7 @@ export class Request
} else if (this.type === RequestType.URL_ENCODE) { } else if (this.type === RequestType.URL_ENCODE) {
this.xhr.send(this.queryfy(this.data)); this.xhr.send(this.queryfy(this.data));
} else if (this.type === RequestType.FORM_DATA) { } else if (this.type === RequestType.FORM_DATA) {
if (this.method === RequestMethod.GET) { this.xhr.send(this.data);
this.xhr.send();
} else {
this.xhr.send(this.data);
}
} }
}; };
}; };

View File

@ -56,7 +56,7 @@ General updates can be found in our info section at https://karaka.app/info and
## Tech stack ## Tech stack
* Language: php, js, c++, html, css, markdown, shell script * Language: php, js, c++, html, css, markdown, shell script
* Database: Maria/MySQL, PostgreSQL, MSSQL, SQLite * Database: Maria/MySQL, PostgreSQL, MSSQL/SQLSrv, SQLite
* Webserver: apache2, nginx * Webserver: apache2, nginx
* Cache: Redis, Memcached * Cache: Redis, Memcached

68
System/SystemUtils.js Normal file
View File

@ -0,0 +1,68 @@
import { BrowserType } from './BrowserType.js';
import { OSType } from './OSType.js';
/**
* System utils class.
*
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @since 1.0.0
*/
export class SystemUtils
{
/**
* Get browser.
*
* @return {string}
*
* @since 1.0.0
*/
static getBrowser ()
{
/** global: InstallTrigger */
/** global: navigator */
/** global: window */
if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
return BrowserType.OPERA;
} else if (typeof InstallTrigger !== 'undefined') {
return BrowserType.FIREFOX;
} else if (Object.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
return BrowserType.SAFARI;
} else if (/* @cc_on!@ */false || !!document.documentMode) {
return BrowserType.IE;
} else if (!!window.StyleMedia) {
return BrowserType.EDGE;
} else if (!!window.chrome && !!window.chrome.webstore) {
return BrowserType.CHROME;
} else if (((typeof isChrome !== 'undefined' && isChrome)
|| (typeof isOpera !== 'undefined' && isOpera))
&& !!window.CSS
) {
return BrowserType.BLINK;
}
return BrowserType.UNKNOWN;
};
/**
* Get os.
*
* @return {string}
*
* @since 1.0.0
*/
static getOS ()
{
for (const os in OSType) {
if (Object.prototype.hasOwnProperty.call(OSType, os)) {
/** global: navigator */
if (navigator.appVersion.toLowerCase().indexOf(OSType[os]) !== -1) {
return OSType[os];
}
}
}
return OSType.UNKNOWN;
};
};

View File

@ -118,9 +118,11 @@ export class Form
} }
// don't overwrite existing bind // don't overwrite existing bind
/*
@todo: removed because sometimes it is already bound but bound in a wrong way (e.g. no success is defined)
if (Object.prototype.hasOwnProperty.call(this.forms, id)) { if (Object.prototype.hasOwnProperty.call(this.forms, id)) {
return; return;
} }*/
this.forms[id] = new FormView(id); this.forms[id] = new FormView(id);
const self = this; const self = this;
@ -817,6 +819,12 @@ export class Form
) { ) {
jsOMS.preventAll(event); jsOMS.preventAll(event);
self.submit(self.forms[id], self.forms[id].getSubmit()[elementIndex]); self.submit(self.forms[id], self.forms[id].getSubmit()[elementIndex]);
} else if ((elementIndex = '')) {
// @todo: if table head input field in popups changes -> check if input empty -> deactivate -> checkbox : else activate checkbox
// careful: the same checkbox is used for showing the filter popup. maybe create a separate checkbox, which only handles the highlighting if filter is defined.
// this means popup active highlights filter icon AND different content checkbox also highlights filter
// -> two hiddin checkboxes are necessary (one is already implemented)
// Consider: It might make sense to do this in the Table.js??? Kinda depends on additional functionality together with the form probably.
} }
// remote actions (maybe solvable with callbacks?): // remote actions (maybe solvable with callbacks?):
@ -905,7 +913,10 @@ export class Form
// select first input element (this allows fast consecutive data input) // select first input element (this allows fast consecutive data input)
const firstFormInputElement = form.getFirstInputElement(); const firstFormInputElement = form.getFirstInputElement();
firstFormInputElement.focus();
if (firstFormInputElement !== null) {
firstFormInputElement.focus();
}
}; };
/** /**
@ -950,14 +961,14 @@ export class Form
const self = this; const self = this;
request.setData(data); request.setData(data);
request.setType(RequestType.FORM_DATA); request.setType(RequestType.FORM_DATA); // @todo: consider to allow different request type
request.setUri(action ? action : form.getAction()); request.setUri(action ? action : form.getAction());
request.setMethod(form.getMethod()); request.setMethod(form.getMethod());
request.setSuccess(function (xhr) request.setSuccess(function (xhr)
{ {
window.omsApp.logger.log(xhr.response); window.omsApp.logger.log(xhr.response);
if (xhr.getResponseHeader('content-type') === 'application/octet-stream') { if (xhr.getResponseHeader('content-type').includes('application/octet-stream')) {
const blob = new Blob([xhr.response], { type: 'application/octet-stream' }); const blob = new Blob([xhr.response], { type: 'application/octet-stream' });
const doc = document.createElement('a'); const doc = document.createElement('a');
doc.style = 'display: none'; doc.style = 'display: none';
@ -981,6 +992,17 @@ export class Form
doc.click(); doc.click();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);
document.body.removeChild(doc); document.body.removeChild(doc);
} else if (xhr.getResponseHeader('content-type').includes('text/html')) {
// window.location = UriFactory.build(uri);
document.documentElement.innerHTML = xhr.response;
/* This is not working as it reloads the page ?!
document.open();
document.write(html);
document.close();
*/
window.omsApp.reInit(); // @todo: fix memory leak which most likely exists because of continous binding without removing binds
} else { } else {
try { try {
const o = JSON.parse(xhr.response)[0]; const o = JSON.parse(xhr.response)[0];

View File

@ -134,15 +134,15 @@ export class Tab
if (fragLength > 0 && fragmentString !== '') { if (fragLength > 0 && fragmentString !== '') {
for (let i = 0; i < fragLength; ++i) { for (let i = 0; i < fragLength; ++i) {
const label = e.querySelectorAll('label[for="' + fragments[i] + '"]')[0]; const label = e.querySelector('label[for="' + fragments[i] + '"]');
if (typeof label !== 'undefined') { if (typeof label !== 'undefined' && label !== null) {
label.click(); label.click();
} }
} }
} }
if (e.getElementsByClassName('active').length < 1) { if (e.querySelector('.tab-links').querySelector('.active') === null) {
e.querySelector('label').click(); e.querySelector('.tab-links').querySelector('label').click();
} }
}; };
}; };

View File

@ -67,6 +67,17 @@ export class GeneralUI
const length = e.length; const length = e.length;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
/*
@todo: bad solution, probably needs to be more navigation specific
const link = UriFactory.buildAbsolute(
e[i].getAttribute('href') !== null ? e[i].getAttribute('href') : e[i].getAttribute('data-href')
);
if (jsOMS.rtrim(link, '/') !== window.location.origin && window.location.href.startsWith(link)) {
jsOMS.addClass(e[i], 'active');
}
*/
if (e[i].getAttribute('data-action') !== null) { if (e[i].getAttribute('data-action') !== null) {
continue; continue;
} }
@ -86,10 +97,10 @@ export class GeneralUI
} }
jsOMS.preventAll(event); jsOMS.preventAll(event);
history.pushState(null, null, window.location);
let uri = this.getAttribute('data-href'); let uri = this.getAttribute('data-href');
uri = uri === null ? this.getAttribute('href') : uri; uri = uri === null ? this.getAttribute('href') : uri;
history.pushState({}, null, UriFactory.build(uri));
if (this.getAttribute('target') === '_blank' if (this.getAttribute('target') === '_blank'
|| this.getAttribute(['data-target']) === '_blank' || this.getAttribute(['data-target']) === '_blank'
@ -97,7 +108,23 @@ export class GeneralUI
) { ) {
window.open(UriFactory.build(uri), '_blank'); window.open(UriFactory.build(uri), '_blank');
} else { } else {
window.location = UriFactory.build(uri); // window.location = UriFactory.build(uri);
fetch(UriFactory.build(uri))
.then((response) => response.text())
.then((html) => {
document.documentElement.innerHTML = html;
/* This is not working as it reloads the page ?!
document.open();
document.write(html);
document.close();
*/
window.omsApp.reInit(); // @todo: fix memory leak which most likely exists because of continous binding without removing binds
})
.catch((error) => {
console.warn(error);
});
} }
}); });
} }

View File

@ -174,6 +174,17 @@ export class UriFactory
return url; return url;
}; };
static buildAbsolute (uri, toMatch = null)
{
if (uri.startsWith('/')) {
return UriFactory.build(window.location.origin + uri, toMatch);
} else if (uri.indexOf('://') === -1) {
return UriFactory.build(window.location.origin + '/' + uri, toMatch);
}
return uri;
};
/** /**
* Build uri * Build uri
* *

View File

@ -644,7 +644,7 @@
throw new Error('callback param is required'); throw new Error('callback param is required');
} }
if (!showdown.helper.isfunction (callback)) { if (!showdown.helper.isFunction (callback)) {
throw new Error('callback param must be a function/closure'); throw new Error('callback param must be a function/closure');
} }
@ -826,7 +826,7 @@
showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) { showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
'use strict'; 'use strict';
if (!showdown.helper.isfunction (replacement)) { if (!showdown.helper.isFunction (replacement)) {
var repStr = replacement; var repStr = replacement;
replacement = function () { replacement = function () {
return repStr; return repStr;

View File

@ -135,6 +135,7 @@
{ {
event.preventDefault(); event.preventDefault();
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.stopPropagation();
event.cancelBubble = true; event.cancelBubble = true;
}; };

View File

@ -331,6 +331,7 @@
{ {
event.preventDefault(); event.preventDefault();
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.stopPropagation();
event.cancelBubble = true; event.cancelBubble = true;
return false; return false;