Browse Source

Svecchiamento sorgenti

Giancarlo 3 years ago
parent
commit
f960bd30a7

+ 0 - 38
README.md

@@ -1,38 +0,0 @@
-[✔] TODO Sulla tabella dei bind aggiungere i campi che di solito si andrebbero ad inserire nei save delle picking list, questo per evitare di mandare save product anche se le informazioni sono le stesse
-
-[✔] TODO Creare il file di log per i barcode non riconosciuti
-
-[✔] TODO Aggiungere la data nel menu a tendina della picking list
-
-[✔] TODO workaround di letture errate dello scanner: se nella picking list viene passato un labelID invece che un barcode, ricava il barcode dalla labelID
-
-[✔] TODO creare la lista dell'etichetta del carrello tramite XLST+XML, aggiungere la colonna quantità nominale, aggiungere l'intestazione sulla tabella con riga orizzontale di separazione
-
-[✔] TODO aggiungere alla fine della picking list, sulla 7" l'elenco delle quantità prelevate e delle quantità mancanti (Anomalie) e trimmare la descrizione che in alcuni casi è molto lunga
-
-[✘] TODO Implementare GetJobStatus
-
-[✘] TODO aggiungere un timetrack dell'operatore che parte da quando da l'ok sulla etichetta da 7" fino all'ultima etichetta
-
-[✘] TODO Parametrizzare nel file LABEL.INI i parametri del BlinkSpecial
-
-[✘] TODO creare la classe wrapper Configuration, serve per leggere più velocemente i parametri dai file INI e nel caso ne manchi uno o l'intero file INI, a creare dei defaults
-
-[✘] TODO dashboard OMLink: aggiungere "display_refresh" con tempo in minuti; aggiungere l'import dei template da omlink di template prima esportati da Findbox
-
-[✘] TODO Background service: ogni minuto controllare che ci siano label con "timestamp di start +37 minuti" libere e resettarle, usare la GetJobsStatus (da implementare)
-
-[✘] TODO verificare se è più veloce mandare l'immagine generata da PHP o l'XSLT+XML
-
-[✘] TODO Subtemplates: da studiare bene che cosa si può fare, lo scopo è far cambiare direttamente all'etichetta il template senza rimandarglielo
-
-[✘] TODO posizionamento: piazzare un etichetta, da API o Findbox impostarne le coordinate XYZ, da questa poi col sistema di triangolazione mappare la posizione delle altre etichette
-
-[✘] TODO Messaggistica JS/HTML: ServiceWorker (libreria SWIVEL)
-
-[✘] TODO ADMIN componenti da utilizzare dal tema AdminTo: bootstrap-inputmask, jquery multiselect, switchery, select2.js, css+js del core del tema
-
-[✘] Stampa WEB: utilizzare NW.JS per un maggior controllo grazie alle API
-
-[✘] Produzione e Dev devono avere classi isolate switchabili così da non impazzire se non è possibile accedere al db remoto del cliente
-

+ 51 - 51
package.json

@@ -1,53 +1,53 @@
 {
-	"name": "omlink",
-	"version": "1.12.1",
-	"codename": "Barricade",
-	"private": true,
-	"description": "OM-Link Engine",
-	"author": "Giancarlo Voci",
-	"scripts": {
-		"clean": "shx --silent rm -rf deploy.tar.gz tmp node_modules ui/admin/node_modules src_minified assets/frontend assets/admin Site.log cfg/*.old ui/*/masterpage.tpl fbtpl *.tgz",
-		"buildDev": "webpack --mode=none --display-error-details",
-		"buildProd": "webpack --mode=production --display-error-details",
-		"watch": "webpack --mode=none --display-error-details --watch",
-		"pack": "npm pack"
-	},
-	"dependencies": {
-		"bootstrap": "^4.3.1",
-		"datatables.net": "^1.10.19",
-		"datatables.net-bs4": "^1.10.19",
-		"datatables.net-buttons": "^1.5.6",
-		"datatables.net-buttons-bs4": "^1.5.6",
-		"datatables.net-responsive": "^2.2.3",
-		"datatables.net-responsive-bs4": "^2.2.3",
-		"datatables.net-select": "^1.3.0",
-		"datatables.net-select-bs4": "^1.3.0",
-		"jquery": "^3.4.1",
-		"popper.js": "^1.15.0"
-	},
-	"devDependencies": {
-		"acorn": "^6.2.1",
-		"clean-webpack-plugin": "^3.0.0",
-		"css-loader": "^2.1.1",
-		"file-loader": "^3.0.1",
-		"html-webpack-plugin": "^3.2.0",
-		"html-webpack-prefix-plugin": "^1.1.0",
-		"mini-css-extract-plugin": "^0.7.0",
-		"node-sass": "^4.12.0",
-		"optimize-css-assets-webpack-plugin": "^5.0.1",
-		"sass-loader": "^7.1.0",
-		"shx": "^0.3.2",
-		"terser-webpack-plugin": "^1.3.0",
-		"url-loader": "^1.1.2",
-		"webpack": "^4.38.0",
-		"webpack-cli": "^3.3.6"
-	},
-	"files": [
-		"index.php",
-		"src",
-		"lib",
-		"cfg/config.bin",
-		"ui/*/*.tpl",
-		"assets"
-	]
+  "name": "omlink",
+  "version": "1.12.1",
+  "codename": "Barricade",
+  "private": true,
+  "description": "OM-Link Engine",
+  "author": "Giancarlo Voci",
+  "scripts": {
+    "clean": "shx --silent rm -rf deploy.tar.gz tmp node_modules ui/admin/node_modules src_minified assets/frontend assets/admin Site.log cfg/*.old ui/*/masterpage.tpl fbtpl *.tgz",
+    "buildDev": "webpack --mode=none",
+    "buildProd": "webpack --mode=production",
+    "watch": "webpack --mode=none --watch",
+    "pack": "npm pack"
+  },
+  "dependencies": {
+    "bootstrap": "^5.1.3",
+    "datatables.net": "^1.11.5",
+    "datatables.net-bs4": "^1.11.5",
+    "datatables.net-buttons": "^2.2.2",
+    "datatables.net-buttons-bs4": "^2.2.2",
+    "datatables.net-responsive": "^2.2.9",
+    "datatables.net-responsive-bs4": "^2.2.9",
+    "datatables.net-select": "^1.3.4",
+    "datatables.net-select-bs4": "^1.3.4",
+    "jquery": "^3.6.0",
+    "popper.js": "^1.15.0"
+  },
+  "devDependencies": {
+    "acorn": "^8.7.0",
+    "clean-webpack-plugin": "^4.0.0",
+    "css-loader": "^6.7.1",
+    "css-minimizer-webpack-plugin": "^3.4.1",
+    "file-loader": "^6.2.0",
+    "html-webpack-plugin": "^5.5.0",
+    "html-webpack-prefix-plugin": "^1.1.0",
+    "mini-css-extract-plugin": "^2.6.0",
+    "sass": "^1.57.1",
+    "sass-loader": "^12.6.0",
+    "shx": "^0.3.4",
+    "terser-webpack-plugin": "^5.3.1",
+    "url-loader": "^4.1.1",
+    "webpack": "^5.71.0",
+    "webpack-cli": "^4.9.2"
+  },
+  "files": [
+    "index.php",
+    "src",
+    "lib",
+    "cfg/config.bin",
+    "ui/*/*.tpl",
+    "assets"
+  ]
 }

+ 174 - 170
src/OpenMind/FindBox/SmartESL.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * @author Giancarlo Voci
  * @date 28/03/2018
@@ -11,173 +12,176 @@ use Generator;
 
 class SmartESL
 {
-	/** @var FindBoxCoreSystem $core */
-	protected $core;
-
-	/** @var array $labels */
-	protected $labels;
-
-	/** @var array $labelProperties */
-	protected $labelProperties;
-
-	public function __construct(FindBoxCoreSystem $coreL, array $LabelID)
-	{
-		$this->core = $coreL;
-		$this->labels = array_map('strtoupper', $LabelID);
-	}
-
-	/**
-	 * Request to label(s) its properties
-	 *
-	 * @param bool $force request directly to ESL
-	 * @return null|object Details
-	 */
-	public function GetStatus(bool $force = false)
-	{
-		$labels = json_encode($this->labels);
-		//$URI = "/1.0.0/index.php/smartesl.getstatus/3.1.0/";
-		$forceStr = var_export($force, true);
-		$URI = "/1.0.0/index.php/smartesl.getstatus/4.0.0/[{$labels},{$forceStr}]";
-		$ret = $this->core->CallAPI($URI, '');
-		if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
-			// Update current properties
-			$this->labelProperties = $ret['value']['value'];
-			return $this->labelProperties;
-		}
-		return null;
-	}
-
-	/**
-	 * Get label version splitted into the three components major, minor, patch
-	 *
-	 * @return array
-	 */
-	public function GetVersion()
-	{
-		$softVersion = $this->labelProperties[array_keys($this->labelProperties)[0]]['status'];
-		return array_values(array_filter_keys($softVersion, ['soft_major', 'soft_minor', 'soft_patch']));
-	}
-
-	public function AsyncBlinkOff(): Generator
-	{
-		global $f3;
-		return $this->AsyncBlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
-	}
-
-
-	/**
-	 * Blink the label with parameters.
-	 *
-	 * @param int $pattern
-	 * @param int $repeat
-	 * @param int $iter_time
-	 * @param int $iterations
-	 * @param int|0 $ledColor
-	 * @return Generator
-	 */
-	public function AsyncBlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = 0): Generator
-	{
-		$uriParams = json_encode(array_merge(
-			array($this->labels),
-			array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)));
-
-		$URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
-		return $this->core->AsyncCallAPI($URI, $uriParams);
-	}
-
-	public function getData()
-	{
-		return $this->labelProperties[$this->labels[0]]['data'];
-	}
-
-	/**
-	 * Turn off led(s)
-	 */
-	public function BlinkOff()
-	{
-		global $f3;
-		return $this->BlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
-	}
-
-	/**
-	 * Blink the label with parameters.
-	 *
-	 * @param int $pattern
-	 * @param int $repeat
-	 * @param int $iter_time
-	 * @param int $iterations
-	 * @param int|0 $ledColor
-	 * @return array
-	 */
-	public function BlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = 0)
-	{
-		$uriParams = json_encode(array_merge(
-			array($this->labels),
-			array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)));
-
-		$URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
-		return $this->core->CallAPI($URI, $uriParams);
-	}
-
-	public function Display(string $templateId, string $barcode)
-	{
-		$URI = "/1.0.0/index.php/smartesl.display/2.3.0/";
-		$params = json_encode(array(
-			$this->labels[0],
-			$barcode,
-			[],
-			$templateId,
-			1, 1));
-
-		return $this->core->CallAPI($URI, $params);
-	}
-
-	/**
-	 * Set ESL display using displayimage CORE API
-	 *
-	 * @param string $binaryImage
-	 * @param int $pageNum
-	 * @return array
-	 */
-	public function SetPageImage(string $binaryImage, int $pageNum = 1)
-	{
-		$imageb64 = base64_encode($binaryImage);
-		$URI = "/1.0.0/index.php/smartesl.displayimage/1.1.1/";
-
-		$params = json_encode([array_map(function ($label) use ($pageNum, $imageb64) {
-			return [
-				'label_id' => $label,
-				'image' => $imageb64,
-				'page' => $pageNum
-			];
-		}, $this->labels)]);
-
-		return $this->core->CallAPI($URI, $params);
-	}
-
-	/**
-	 * Switch to ESL page $pageNum
-	 *
-	 * @param int $pageNum
-	 * @return array
-	 */
-	public function SwitchPage(int $pageNum = 1)
-	{
-		$URI = "/1.0.0/index.php/smartesl.switchpage/1.1.0/";
-
-		$params = json_encode([array_map(function ($label) use ($pageNum) {
-			return [
-				'label_id' => $label,
-				'page' => $pageNum
-			];
-		}, $this->labels)]);
-
-		return $this->core->CallAPI($URI, $params);
-	}
-
-	public function GetLabelMatch()
-	{
-		$URI = "/1.0.0/index.php/smartesl.getlabelmatch/1.2.0/";
-		return $this->core->CallAPI($URI, json_encode(array($this->labels)));
-	}
-}
+  /** @var FindBoxCoreSystem $core */
+  protected $core;
+
+  /** @var array $labels */
+  protected $labels;
+
+  /** @var array $labelProperties */
+  protected $labelProperties;
+
+  public function __construct(FindBoxCoreSystem $coreL, array $LabelID)
+  {
+    $this->core = $coreL;
+    $this->labels = array_map('strtoupper', $LabelID);
+  }
+
+  /**
+   * Request to label(s) its properties
+   *
+   * @param bool $force request directly to ESL
+   * @return null|array Details
+   */
+  public function GetStatus(bool $force = false)
+  {
+    $labels = json_encode($this->labels);
+    //$URI = "/1.0.0/index.php/smartesl.getstatus/3.1.0/";
+    $forceStr = var_export($force, true);
+    $URI = "/1.0.0/index.php/smartesl.getstatus/4.0.0/[{$labels},{$forceStr}]";
+    $ret = $this->core->CallAPI($URI, '');
+    if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
+      // Update current properties
+      $this->labelProperties = $ret['value']['value'];
+      return $this->labelProperties;
+    }
+    return null;
+  }
+
+  /**
+   * Get label version splitted into the three components major, minor, patch
+   *
+   * @return array
+   */
+  public function GetVersion()
+  {
+    $softVersion = $this->labelProperties[array_keys($this->labelProperties)[0]]['status'];
+    return array_values(array_filter_keys($softVersion, ['soft_major', 'soft_minor', 'soft_patch']));
+  }
+
+  public function AsyncBlinkOff(): Generator
+  {
+    global $f3;
+    return $this->AsyncBlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
+  }
+
+
+  /**
+   * Blink the label with parameters.
+   *
+   * @param int $pattern
+   * @param int $repeat
+   * @param int $iter_time
+   * @param int $iterations
+   * @param int|0 $ledColor
+   * @return Generator
+   */
+  public function AsyncBlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = 0): Generator
+  {
+    $uriParams = json_encode(array_merge(
+      array($this->labels),
+      array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)
+    ));
+
+    $URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
+    return $this->core->AsyncCallAPI($URI, $uriParams);
+  }
+
+  public function getData()
+  {
+    return $this->labelProperties[$this->labels[0]]['data'];
+  }
+
+  /**
+   * Turn off led(s)
+   */
+  public function BlinkOff()
+  {
+    global $f3;
+    return $this->BlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
+  }
+
+  /**
+   * Blink the label with parameters.
+   *
+   * @param int $pattern
+   * @param int $repeat
+   * @param int $iter_time
+   * @param int $iterations
+   * @param int|0 $ledColor
+   * @return array
+   */
+  public function BlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = 0)
+  {
+    $uriParams = json_encode(array_merge(
+      array($this->labels),
+      array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)
+    ));
+
+    $URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
+    return $this->core->CallAPI($URI, $uriParams);
+  }
+
+  public function Display(string $templateId, string $barcode)
+  {
+    $URI = "/1.0.0/index.php/smartesl.display/2.3.0/";
+    $params = json_encode(array(
+      $this->labels[0],
+      $barcode,
+      [],
+      $templateId,
+      1, 1
+    ));
+
+    return $this->core->CallAPI($URI, $params);
+  }
+
+  /**
+   * Set ESL display using displayimage CORE API
+   *
+   * @param string $binaryImage
+   * @param int $pageNum
+   * @return array
+   */
+  public function SetPageImage(string $binaryImage, int $pageNum = 1)
+  {
+    $imageb64 = base64_encode($binaryImage);
+    $URI = "/1.0.0/index.php/smartesl.displayimage/1.1.1/";
+
+    $params = json_encode([array_map(function ($label) use ($pageNum, $imageb64) {
+      return [
+        'label_id' => $label,
+        'image' => $imageb64,
+        'page' => $pageNum
+      ];
+    }, $this->labels)]);
+
+    return $this->core->CallAPI($URI, $params);
+  }
+
+  /**
+   * Switch to ESL page $pageNum
+   *
+   * @param int $pageNum
+   * @return array
+   */
+  public function SwitchPage(int $pageNum = 1)
+  {
+    $URI = "/1.0.0/index.php/smartesl.switchpage/1.1.0/";
+
+    $params = json_encode([array_map(function ($label) use ($pageNum) {
+      return [
+        'label_id' => $label,
+        'page' => $pageNum
+      ];
+    }, $this->labels)]);
+
+    return $this->core->CallAPI($URI, $params);
+  }
+
+  public function GetLabelMatch()
+  {
+    $URI = "/1.0.0/index.php/smartesl.getlabelmatch/1.2.0/";
+    return $this->core->CallAPI($URI, json_encode(array($this->labels)));
+  }
+}

+ 122 - 120
src/OpenMind/System/GDSupport.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * @author Giancarlo Voci
  * @date 21/09/2019
@@ -7,6 +8,7 @@
 
 namespace OpenMind\System;
 
+use GdImage;
 use Picqer\Barcode\BarcodeGeneratorPNG;
 use Picqer\Barcode\Exceptions\BarcodeException;
 
@@ -20,124 +22,124 @@ use Picqer\Barcode\Exceptions\BarcodeException;
  */
 class GDSupport
 {
-	private $image;
-
-	public function __construct()
-	{
-		$this->image = null;
-	}
-
-	/**
-	 * @param array $drawings
-	 * @param string|null $outputPathFile
-	 * @return string if outputPathFile is null, return the image instead to write to file
-	 * @throws BarcodeException
-	 */
-	public function Render(array $drawings, $outputPathFile = NULL): string
-	{
-		foreach($drawings as $gdElement) {
-			$name = key($gdElement);
-			$prop = $gdElement[$name];
-			$color = isset($prop['color']) ? $this->getColor($prop['color']) : NULL;
-			switch ($name) {
-
-				case 'BODY':
-					$this->image = imagecreatetruecolor($prop['w'], $prop['h']);
-					$bgColor = isset($prop['bgcolor']) ? $this->getColor($prop['bgcolor']) : NULL;
-					imageantialias($this->image, false);
-					imagefill($this->image, 0, 0, $bgColor);
-					break;
-
-				case 'TEXT':
-					imagettftext($this->image, $prop['size'], 0, $prop['x'], $prop['y'], $color, $prop['font'], $prop['value']);
-					break;
-
-				case 'TEXTFIT':
-					$fontSizeCalulated = $this->fixTextRect($prop['value'], $prop['font'], $prop['w']);
-					imagettftext($this->image, $fontSizeCalulated, 0, $prop['x'], $prop['y'], $color, $prop['font'], $prop['value']);
-					break;
-
-				case 'FILL':
-					imagefill($this->image, $prop['x'], $prop['y'], $color);
-					break;
-
-				case 'RECT':
-					if (isset($prop['filled']))
-						imagefilledrectangle($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
-					else
-						imagerectangle($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
-					break;
-
-				case 'LINE':
-					if (isset($prop['thickness']))
-						imagesetthickness($this->image, $prop['thickness']);
-
-					imageline($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
-
-					if (isset($prop['thickness']))  // Restore default tickness
-						imagesetthickness($this->image, 1);
-					break;
-
-				case 'PIXEL':
-					imagesetpixel($this->image, $prop['x'], $prop['y'], $color);
-					break;
-
-				case 'ELLIPSE':
-					imagefilledellipse($this->image, $prop['x'], $prop['y'], $prop['w'], $prop['h'], $color);
-					break;
-
-				case 'BARCODE':
-					$bcGen = new BarcodeGeneratorPNG();
-					$bcImg = $bcGen->getBarcode($prop['value'], $prop['type'], $prop['widthFactor'], $prop['h']);
-					$gdBcImg = imagecreatefromstring($bcImg);
-					imagecopy($this->image, $gdBcImg, $prop['x'], $prop['y'], 0, 0, imagesx($gdBcImg), imagesy($gdBcImg));
-					break;
-			}
-		}
-
-		// ESL color fix
-		imagetruecolortopalette($this->image, false, 3);
-		imagefilter($this->image, IMG_FILTER_CONTRAST, -100);
-
-		ob_start();
-		imagepng($this->image, $outputPathFile);
-		$data = ob_get_contents();
-		ob_end_clean();
-		return $data;
-	}
-
-	/**
-	 * @param string $colorStr
-	 * @return false|int
-	 */
-	private function getColor(string $colorStr)
-	{
-		list($r, $g, $b) = sscanf($colorStr, "#%02x%02x%02x");
-		return imagecolorallocate($this->image, $r, $g, $b);
-	}
-
-	private function fixTextRect(string $text, string $font, int $maxWidth): int
-	{
-		$font_size = 0;
-		do {
-			$font_size += 0.1;
-			$p = imagettfbbox($font_size, 0, $font, $text);
-			$txt_width = $p[2] - $p[0];
-		} while ($txt_width <= $maxWidth);
-
-		return $font_size;
-	}
-
-	public function __destruct()
-	{
-		$this->Destroy();
-	}
-
-	public function Destroy()
-	{
-		if ($this->image) {
-			imagedestroy($this->image);
-			$this->image = NULL;
-		}
-	}
+  private $image;
+
+  public function __construct()
+  {
+    $this->image = new GdImage();
+  }
+
+  /**
+   * @param array $drawings
+   * @param string|null $outputPathFile
+   * @return string if outputPathFile is null, return the image instead to write to file
+   * @throws BarcodeException
+   */
+  public function Render(array $drawings, $outputPathFile = NULL): string
+  {
+    foreach ($drawings as $gdElement) {
+      $name = key($gdElement);
+      $prop = $gdElement[$name];
+      $color = isset($prop['color']) ? $this->getColor($prop['color']) : NULL;
+      switch ($name) {
+
+        case 'BODY':
+          $this->image = imagecreatetruecolor($prop['w'], $prop['h']);
+          $bgColor = isset($prop['bgcolor']) ? $this->getColor($prop['bgcolor']) : NULL;
+          imageantialias($this->image, false);
+          imagefill($this->image, 0, 0, $bgColor);
+          break;
+
+        case 'TEXT':
+          imagettftext($this->image, $prop['size'], 0, $prop['x'], $prop['y'], $color, $prop['font'], $prop['value']);
+          break;
+
+        case 'TEXTFIT':
+          $fontSizeCalulated = $this->fixTextRect($prop['value'], $prop['font'], $prop['w']);
+          imagettftext($this->image, $fontSizeCalulated, 0, $prop['x'], $prop['y'], $color, $prop['font'], $prop['value']);
+          break;
+
+        case 'FILL':
+          imagefill($this->image, $prop['x'], $prop['y'], $color);
+          break;
+
+        case 'RECT':
+          if (isset($prop['filled']))
+            imagefilledrectangle($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
+          else
+            imagerectangle($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
+          break;
+
+        case 'LINE':
+          if (isset($prop['thickness']))
+            imagesetthickness($this->image, $prop['thickness']);
+
+          imageline($this->image, $prop['x1'], $prop['y1'], $prop['x2'], $prop['y2'], $color);
+
+          if (isset($prop['thickness']))  // Restore default tickness
+            imagesetthickness($this->image, 1);
+          break;
+
+        case 'PIXEL':
+          imagesetpixel($this->image, $prop['x'], $prop['y'], $color);
+          break;
+
+        case 'ELLIPSE':
+          imagefilledellipse($this->image, $prop['x'], $prop['y'], $prop['w'], $prop['h'], $color);
+          break;
+
+        case 'BARCODE':
+          $bcGen = new BarcodeGeneratorPNG();
+          $bcImg = $bcGen->getBarcode($prop['value'], $prop['type'], $prop['widthFactor'], $prop['h']);
+          $gdBcImg = imagecreatefromstring($bcImg);
+          imagecopy($this->image, $gdBcImg, $prop['x'], $prop['y'], 0, 0, imagesx($gdBcImg), imagesy($gdBcImg));
+          break;
+      }
+    }
+
+    // ESL color fix
+    imagetruecolortopalette($this->image, false, 3);
+    imagefilter($this->image, IMG_FILTER_CONTRAST, -100);
+
+    ob_start();
+    imagepng($this->image, $outputPathFile);
+    $data = ob_get_contents();
+    ob_end_clean();
+    return $data;
+  }
+
+  /**
+   * @param string $colorStr
+   * @return false|int
+   */
+  private function getColor(string $colorStr)
+  {
+    list($r, $g, $b) = sscanf($colorStr, "#%02x%02x%02x");
+    return imagecolorallocate($this->image, $r, $g, $b);
+  }
+
+  private function fixTextRect(string $text, string $font, int $maxWidth): int
+  {
+    $font_size = 0;
+    do {
+      $font_size += 0.1;
+      $p = imagettfbbox($font_size, 0, $font, $text);
+      $txt_width = $p[2] - $p[0];
+    } while ($txt_width <= $maxWidth);
+
+    return $font_size;
+  }
+
+  public function __destruct()
+  {
+    $this->Destroy();
+  }
+
+  public function Destroy()
+  {
+    if ($this->image) {
+      imagedestroy($this->image);
+      $this->image = NULL;
+    }
+  }
 }

+ 1 - 3
ui/admin/assets/js/OMGUtils.js

@@ -16,11 +16,9 @@ export const fetchHeaders = {
  *
  * @param url URL of RESTful api to call
  * @param options the fetch() options
- * @param complete Promise resolve callback
- * @param error Promise reject callback
  * @returns Object {Promise, signal: AbortController}
  */
-export function AjaxReq(url, options, complete, error) {
+export function AjaxReq(url, options) {
 	let fetchSignal = new AbortController();
 	let defaults = {
 		headers: fetchHeaders,

+ 1 - 1
ui/admin/users.js

@@ -1 +1 @@
-alert('ciao mauro');
+alert('ciao');

+ 22 - 14
ui/admin/webpack.config.js

@@ -2,8 +2,8 @@ const path = require("path");
 const TerserJSPlugin = require('terser-webpack-plugin');
 const HtmlPlugin = require("html-webpack-plugin");
 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
-const {CleanWebpackPlugin} = require("clean-webpack-plugin/dist/clean-webpack-plugin");
-const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+const { CleanWebpackPlugin } = require("clean-webpack-plugin/dist/clean-webpack-plugin");
+const OptimizeCSSAssetsPlugin = require('css-minimizer-webpack-plugin');
 const webpack = require("webpack");
 
 function getCurrentProjectname() {
@@ -13,6 +13,9 @@ function getCurrentProjectname() {
 }
 
 module.exports = {
+	stats: {
+		errorDetails: true,
+	},
 	plugins: [
 		new CleanWebpackPlugin(),
 		new HtmlPlugin(
@@ -21,7 +24,7 @@ module.exports = {
 				filename: path.resolve(__dirname, 'masterpage.tpl')
 			}
 		),
-		new MiniCssExtractPlugin({filename: "styles.[contenthash].css"}),
+		new MiniCssExtractPlugin({ filename: "styles.[contenthash].css" }),
 		new webpack.ProvidePlugin({
 			$: 'jquery',
 			jQuery: 'jquery',
@@ -36,32 +39,37 @@ module.exports = {
 				test: /\.(css|scss)$/,
 				// ...use this loaders
 				use: [
-					MiniCssExtractPlugin.loader,
-					"css-loader",
-					"sass-loader"
+					{ loader: MiniCssExtractPlugin.loader },
+					{ loader: "css-loader" },
+					{ loader: "sass-loader" }
 				]
 			},
 			// Import various assets
-			{test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000'}
+			{
+				test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
+				use: [
+					{ loader: 'url-loader', options: '?limit=100000' }
+				]
+			}
 		]
 	},
 	optimization: {
 		minimizer: [
 			new TerserJSPlugin(
 				// Discard Comments
-				{terserOptions: {output: {comments: false}}, parallel: 4}
+				{ terserOptions: { output: { comments: false } }, parallel: 4 }
 			),
 			new OptimizeCSSAssetsPlugin(
 				// Discard Comments
-				{cssProcessorPluginOptions: {preset: ['default', {discardComments: {removeAll: true}}]}}
+				{ cssProcessorPluginOptions: { preset: ['default', { discardComments: { removeAll: true } }] } }
 			)
 		],
 	},
 	entry: "./assets/js/index.js",
 	output:
-		{
-			publicPath: '/' + getCurrentProjectname() + '/assets/admin/',
-			path: path.resolve(__dirname, "../../assets/admin/"),
-			filename: "bundle.[contenthash].js"
-		}
+	{
+		publicPath: '/' + getCurrentProjectname() + '/assets/admin/',
+		path: path.resolve(__dirname, "../../assets/admin/"),
+		filename: "bundle.[contenthash].js"
+	}
 };

+ 1 - 3
ui/frontend/js/OMGUtils.js

@@ -16,11 +16,9 @@ export const fetchHeaders = {
  *
  * @param url URL of RESTful api to call
  * @param options the fetch() options
- * @param complete Promise resolve callback
- * @param error Promise reject callback
  * @returns Object {Promise, signal: AbortController}
  */
-export function AjaxReq(url, options, complete, error) {
+export function AjaxReq(url, options) {
 	let fetchSignal = new AbortController();
 	let defaults = {
 		headers: fetchHeaders,

+ 2 - 2
ui/frontend/js/edittable.js

@@ -101,12 +101,12 @@ function EditTableInit(tableRef, controllerURL) {
 
 	tableBodyRef.on('keydown', 'td', function (e) {
 		// Cancel Edit
-		if (e.keyCode === 27 || e.keyCode === 9) {
+		if (e.code === 27 || e.code === 9) {
 			cancelEdit(this);
 			return false;
 		}
 		// Save Modified Data
-		if (e.keyCode === 13) {
+		if (e.code === 13) {
 			$(this).data('oldvalue', this.innerText);
 
 			let ajaxData = new FormData();

+ 5 - 5
ui/frontend/js/frontend.js

@@ -7,8 +7,8 @@
  */
 
 import './common';
-import {AjaxReq, fetchHeaders} from "./OMGUtils";
-import EditTableInit from "./edittable";
+import { AjaxReq, fetchHeaders } from "./OMGUtils";
+//import EditTableInit from "./edittable";
 
 let CUSTOM_NOTIFY = 0x4000;
 let REFRESH_FILTERS = CUSTOM_NOTIFY + 1;
@@ -35,7 +35,7 @@ function NotificationBuilder(notifications) {
 	} else {
 		let notificationCount = 0;
 		notifications.forEach(function (element) {
-// If notification codes are >CUSTON_NOTIFY means that are special codes to skip in this logic
+			// If notification codes are >CUSTON_NOTIFY means that are special codes to skip in this logic
 			if (element.code > CUSTOM_NOTIFY)
 				return;
 
@@ -55,7 +55,7 @@ ${tplNotify}
 }
 
 function refreshNotificationArea() {
-	fetch(`${BASEURL}/api.system.getserverstatus`, {headers: fetchHeaders})
+	fetch(`${BASEURL}/api.system.getserverstatus`, { headers: fetchHeaders })
 		.then(resp => {
 			if (resp.status === 200)
 				return resp.json();
@@ -68,7 +68,7 @@ function refreshNotificationArea() {
 }
 
 function NotificationDelete(link, code) {
-	fetch(`${BASEURL}/api.system.removenotification/${code}`, {method: "POST"})
+	fetch(`${BASEURL}/api.system.removenotification/${code}`, { method: "POST" })
 		.then(() => {
 			if ((link != null) && (link.length != 0) && (link != '#'))
 				window.location.href = `${BASEURL}${link}`;

+ 17 - 9
webpack.config.js

@@ -2,8 +2,8 @@ const path = require("path");
 const TerserJSPlugin = require('terser-webpack-plugin');
 const HtmlPlugin = require("html-webpack-plugin");
 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
-const {CleanWebpackPlugin} = require("clean-webpack-plugin");
-const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+const { CleanWebpackPlugin } = require("clean-webpack-plugin");
+const OptimizeCSSAssetsPlugin = require('css-minimizer-webpack-plugin');
 const webpack = require("webpack");
 
 function getCurrentProjectname() {
@@ -13,6 +13,9 @@ function getCurrentProjectname() {
 }
 
 module.exports = {
+	stats: {
+		errorDetails: true,
+	},
 	plugins: [
 		new CleanWebpackPlugin(),
 		new HtmlPlugin(
@@ -29,7 +32,7 @@ module.exports = {
 				chunks: ["frontend"]
 			}
 		),
-		new MiniCssExtractPlugin({filename: "styles.[contenthash].css"}),
+		new MiniCssExtractPlugin({ filename: "styles.[contenthash].css" }),
 		new webpack.ProvidePlugin({
 			$: 'jquery',
 			jQuery: 'jquery',
@@ -43,24 +46,29 @@ module.exports = {
 				test: /\.(css|scss)$/,
 				// ...use this loaders
 				use: [
-					MiniCssExtractPlugin.loader,
-					"css-loader",
-					"sass-loader"
+					{ loader: MiniCssExtractPlugin.loader },
+					{ loader: "css-loader" },
+					{ loader: "sass-loader" }
 				]
 			},
 			// Import various assets
-			{test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000'}
+			{
+				test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
+				use: [
+					{ loader: 'url-loader', options: '?limit=100000' }
+				]
+			}
 		]
 	},
 	optimization: {
 		minimizer: [
 			new TerserJSPlugin(
 				// Discard Comments
-				{terserOptions: {output: {comments: false}}, parallel: 4}
+				{ terserOptions: { output: { comments: false } }, parallel: 4 }
 			),
 			new OptimizeCSSAssetsPlugin(
 				// Discard Comments
-				{cssProcessorPluginOptions: {preset: ['default', {discardComments: {removeAll: true}}]}}
+				{ minimizerOptions: { preset: ['default', { discardComments: { removeAll: true } }] } }
 			)
 		],
 	},