Merge branch 'master' into feat_schedules_holidays

This commit is contained in:
Matteo Gheza 2021-04-28 17:44:52 +02:00 committed by GitHub
commit 44ce5862df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 1583 additions and 1207 deletions

View File

@ -6,7 +6,10 @@ on:
- master
- 'releases/**'
- 'feat_**'
- staging
- production
pull_request:
workflow_dispatch:
jobs:
tests:
@ -155,3 +158,95 @@ jobs:
with:
name: webpack_dist_${{ github.run_id }}
path: server/resources/dist
staging_deployment:
if: github.event.ref == 'refs/heads/staging'
needs: tests
runs-on: ubuntu-latest
environment: staging
name: Deploy to staging
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: mbstring, intl
ini-values: post_max_size=256M, log_errors = on, error_reporting = 32767, error_log = /tmp/php.log
coverage: xdebug, pcov
- name: Setup NodeJS
uses: actions/setup-node@v1
with:
node-version: '12'
- name: Deploy
run: |
ls
sudo wget -O deployment.phar https://github.com/dg/ftp-deployment/releases/download/v3.4.0/deployment.phar
echo '<?php $remotes = [ "staging" => [ "remote" => "${{ secrets.DEPLOY_URL }}", "sentry_env" => "staging" ] ]; ?>' > deployment_remotes.php
cat deployment_remotes.php
ls
php deployment.phar deployment.php --section staging
php -r 'require("deployment_remotes.php");'
cat deployment.log | grep "After-jobs:" ; exit $?
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: deploy_php_log_${{ github.run_id }}
path: /tmp/php.log
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: deploy_log_${{ github.run_id }}
path: deployment.log
production_deployment:
if: github.event.ref == 'refs/heads/production'
needs: tests
runs-on: ubuntu-latest
environment: production
name: Deploy to production
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: mbstring, intl
ini-values: post_max_size=256M, log_errors = on, error_reporting = 32767, error_log = /tmp/php.log
coverage: xdebug, pcov
- name: Setup NodeJS
uses: actions/setup-node@v1
with:
node-version: '12'
- name: Deploy
run: |
ls
sudo wget -O deployment.phar https://github.com/dg/ftp-deployment/releases/download/v3.4.0/deployment.phar
echo '<?php $remotes = [ "production" => [ "remote" => "${{ secrets.DEPLOY_URL }}", "sentry_env" => "prod" ] ]; ?>' > deployment_remotes.php
cat deployment_remotes.php
ls
php deployment.phar deployment.php --section production
php -r 'require("deployment_remotes.php");'
cat deployment.log | grep "After-jobs:" ; exit $?
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: deploy_php_log_${{ github.run_id }}
path: /tmp/php.log
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: deploy_log_${{ github.run_id }}
path: deployment.log

3
.gitignore vendored
View File

@ -524,4 +524,5 @@ deployment_remotes.php
adminer.php
/server/resources/images/logo.png
/server/resources/images/owner.png
/server/resources/images/owner.png
/server/resources/images/map_cache

View File

@ -1,4 +1,4 @@
FROM trafex/alpine-nginx-php7:latest AS webserver
FROM trafex/alpine-nginx-php7:1.10.0 AS webserver
LABEL maintainer="matteo@matteogheza.it"
LABEL version="1.0"
@ -16,4 +16,4 @@ RUN composer install --no-dev --optimize-autoloader --no-interaction --no-progre
#RUN echo "@reboot cd /var/www/html/install && php install.php config" > /etc/crontabs/root
USER nobody
EXPOSE 8080
EXPOSE 8080

View File

@ -1,4 +1,5 @@
# allerta-vvf
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/82dfdf3d37b1418ca004d712580d3385)](https://app.codacy.com/gh/allerta-vvf/allerta-vvf?utm_source=github.com&utm_medium=referral&utm_content=allerta-vvf/allerta-vvf&utm_campaign=Badge_Grade_Settings)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fallerta-vvf%2Fallerta-vvf.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fallerta-vvf%2Fallerta-vvf?ref=badge_shield) ![PHP Code Testing](https://github.com/allerta-vvf/allerta-vvf/workflows/PHP%20Code%20Testing/badge.svg) ![Languages count](https://img.shields.io/github/languages/count/allerta-vvf/allerta-vvf) ![Top language](https://img.shields.io/github/languages/top/allerta-vvf/allerta-vvf) ![GitHub issues](https://img.shields.io/github/issues-raw/allerta-vvf/allerta-vvf) ![GitHub pull requests](https://img.shields.io/github/issues-pr-raw/allerta-vvf/allerta-vvf) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=allerta-vvf/allerta-vvf)](https://dependabot.com) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/allerta-vvf/allerta-vvf)
**Coming soon, stay tuned!** :thumbsup:

View File

@ -11,6 +11,8 @@ $baseConfig = [
resources/src
resources/node_modules
resources/webpack*
resources/images/logo.png
resources/images/owner.png
cypress
debug_storage/exception*
debug_storage/*.log
@ -75,7 +77,7 @@ foreach ($remotes as $key => $value) {
$config[$key]["before"] = [];
} else {
$env = isset($config[$key]["sentry_env"]) ? $config[$key]["sentry_env"] : "prod";
$config[$key]["before"][] = "local: cd server/resources && npm i && npm run prod -- --env sentry_environment=".$env;
$config[$key]["before"][] = "local: cd server/resources && npm i && npm run prod -- --env sentryEnvironment=".$env;
}
if(isset($value["after"]) && $value["after"] === false){
$config[$key]["after"] = [];

View File

@ -217,7 +217,7 @@ $routeInfo = $dispatcher->dispatch($httpMethod, $uri);
function responseApi($content, $status_code=200)
{
global $responseFormat, $responseFormatType;
global $responseFormat;
if($status_code !== 200) {
http_response_code($status_code);
}

View File

@ -51,7 +51,7 @@ class InlinekeyboardCommand extends UserCommand
{
$chat_id = $this->getMessage()->getChat()->getId();
$switch_element = mt_rand(0, 9) < 5 ? 'true' : 'false';
$switch_element = random_int(0, 9) < 5 ? 'true' : 'false';
$inline_keyboard = new InlineKeyboard(
[

View File

@ -92,7 +92,7 @@ class KeyboardCommand extends UserCommand
);
//Return a random keyboard.
//$keyboard = $keyboards[mt_rand(0, count($keyboards) - 1)]
//$keyboard = $keyboards[random_int(0, count($keyboards) - 1)]
$keyboard = $keyboards[4]
->setResizeKeyboard(true)
->setOneTimeKeyboard(true)

View File

@ -57,13 +57,6 @@ class StartCommand extends SystemCommand
$chat_id = $message->getChat()->getId();
$keyboard = new Keyboard(
['7', '8', '9'],
['4', '5', '6'],
['1', '2', '3'],
[' ', '0', ' ']
);
$text = 'Hi there!' . PHP_EOL . 'Type /help to see all commands!';
$data = [

View File

@ -2,9 +2,15 @@
"name": "allerta-vvf/allerta-vvf",
"description": "Un software di allertamento per i vvf",
"type": "project",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/allerta-vvf/tiny-html-minifier"
}
],
"require": {
"twig/twig": "^3.2.1",
"delight-im/auth": "^8.2.2",
"delight-im/auth": "^8.3.0",
"ulrichsg/getopt-php": "^3.4.0",
"nikic/fast-route": "^2.0@dev",
"spatie/array-to-xml": "^2.16",
@ -12,7 +18,9 @@
"brick/phonenumber": "^0.2.2",
"sentry/sdk": "^3.1",
"maximebf/debugbar": "^1.16",
"azuyalabs/yasumi": "^2.3"
"azuyalabs/yasumi": "^2.3",
"ministryofweb/php-osm-tiles": "^2.0",
"jenstornell/tiny-html-minifier": "dev-master"
},
"license": "GPL-3.0-or-later",
"authors": [

214
server/composer.lock generated
View File

@ -189,16 +189,16 @@
},
{
"name": "delight-im/auth",
"version": "v8.2.2",
"version": "v8.3.0",
"source": {
"type": "git",
"url": "https://github.com/delight-im/PHP-Auth.git",
"reference": "729c76668fa638769ab834c904d50696686797e9"
"reference": "7bce546defa2bec75485d4bf1d68b72cf311c489"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/delight-im/PHP-Auth/zipball/729c76668fa638769ab834c904d50696686797e9",
"reference": "729c76668fa638769ab834c904d50696686797e9",
"url": "https://api.github.com/repos/delight-im/PHP-Auth/zipball/7bce546defa2bec75485d4bf1d68b72cf311c489",
"reference": "7bce546defa2bec75485d4bf1d68b72cf311c489",
"shasum": ""
},
"require": {
@ -228,9 +228,9 @@
],
"support": {
"issues": "https://github.com/delight-im/PHP-Auth/issues",
"source": "https://github.com/delight-im/PHP-Auth/tree/v8.2.2"
"source": "https://github.com/delight-im/PHP-Auth/tree/v8.3.0"
},
"time": "2020-09-30T18:40:54+00:00"
"time": "2021-04-21T14:39:10+00:00"
},
{
"name": "delight-im/base64",
@ -463,16 +463,16 @@
},
{
"name": "giggsey/libphonenumber-for-php",
"version": "8.12.20",
"version": "8.12.21",
"source": {
"type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
"reference": "743585979ef96f2be123518c0a58083cf678bd47"
"reference": "272b8123ba7f1b7975620c6389e7206281b4a3ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/743585979ef96f2be123518c0a58083cf678bd47",
"reference": "743585979ef96f2be123518c0a58083cf678bd47",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/272b8123ba7f1b7975620c6389e7206281b4a3ce",
"reference": "272b8123ba7f1b7975620c6389e7206281b4a3ce",
"shasum": ""
},
"require": {
@ -532,7 +532,7 @@
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
"source": "https://github.com/giggsey/libphonenumber-for-php"
},
"time": "2021-03-17T11:05:55+00:00"
"time": "2021-04-06T08:37:32+00:00"
},
{
"name": "giggsey/locale",
@ -644,16 +644,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.8.1",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "35ea11d335fd638b5882ff1725228b3d35496ab1"
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1",
"reference": "35ea11d335fd638b5882ff1725228b3d35496ab1",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
"shasum": ""
},
"require": {
@ -713,9 +713,9 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/1.8.1"
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
},
"time": "2021-03-21T16:25:00+00:00"
"time": "2021-04-26T09:17:50+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
@ -830,6 +830,47 @@
},
"time": "2021-02-22T10:52:38+00:00"
},
{
"name": "jenstornell/tiny-html-minifier",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/allerta-vvf/tiny-html-minifier.git",
"reference": "5e997f570fe637a4c1c996bdcc8f9beaa26940a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/allerta-vvf/tiny-html-minifier/zipball/5e997f570fe637a4c1c996bdcc8f9beaa26940a2",
"reference": "5e997f570fe637a4c1c996bdcc8f9beaa26940a2",
"shasum": ""
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"Minifier\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Jens Törnell",
"email": "webblayout@gmail.com"
}
],
"description": "Minify HTML in PHP with just a single class",
"keywords": [
"html",
"minifier",
"minify"
],
"support": {
"source": "https://github.com/allerta-vvf/tiny-html-minifier/tree/master"
},
"time": "2021-04-27T22:20:43+00:00"
},
{
"name": "maximebf/debugbar",
"version": "v1.16.5",
@ -895,32 +936,85 @@
},
"time": "2020-12-07T11:07:24+00:00"
},
{
"name": "ministryofweb/php-osm-tiles",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/ministryofweb/php-osm-tiles.git",
"reference": "e0fc28ffbe5afc75f2ae40a834a1792cf3d725bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ministryofweb/php-osm-tiles/zipball/e0fc28ffbe5afc75f2ae40a834a1792cf3d725bf",
"reference": "e0fc28ffbe5afc75f2ae40a834a1792cf3d725bf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.13",
"friendsofphp/php-cs-fixer": "^2.18",
"jakub-onderka/php-console-highlighter": "^0.4",
"jakub-onderka/php-parallel-lint": "^1.0",
"phpmd/phpmd": "^2.9",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"MinistryOfWeb\\OsmTiles\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A library to convert map tile numbers to coordinates and vice versa.",
"keywords": [
"OpenStreetMap",
"coordinate",
"geographic",
"location",
"maptile",
"osm",
"tile"
],
"support": {
"issues": "https://github.com/ministryofweb/php-osm-tiles/issues",
"source": "https://github.com/ministryofweb/php-osm-tiles/tree/2.0.0"
},
"time": "2021-03-09T07:50:25+00:00"
},
{
"name": "nikic/fast-route",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "7723b1dcb0084baaa1f36df25d5720b7b85b62d6"
"reference": "b5543adef5e16738471a52fdf55ff802edf1141d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/7723b1dcb0084baaa1f36df25d5720b7b85b62d6",
"reference": "7723b1dcb0084baaa1f36df25d5720b7b85b62d6",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5543adef5e16738471a52fdf55ff802edf1141d",
"reference": "b5543adef5e16738471a52fdf55ff802edf1141d",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
"php": ">=7.4.0"
},
"require-dev": {
"doctrine/coding-standard": "^6.0 || ^7.0",
"phpbench/phpbench": "^0.16.9",
"doctrine/coding-standard": "^9.0",
"phpbench/phpbench": "^1.0@beta",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^7.5 || ^8.5"
"phpunit/phpunit": "^9.5"
},
"default-branch": true,
"type": "library",
@ -956,7 +1050,7 @@
"issues": "https://github.com/nikic/FastRoute/issues",
"source": "https://github.com/nikic/FastRoute/tree/master"
},
"time": "2020-09-28T10:21:28+00:00"
"time": "2021-04-27T09:57:16+00:00"
},
{
"name": "php-http/client-common",
@ -1709,16 +1803,16 @@
},
{
"name": "sentry/sentry",
"version": "3.2.0",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "899b0de58c1e01feb54829b3094af74252aff385"
"reference": "fb4f83e6e2d718d1e5fbfe3a20cced83f47f040f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/899b0de58c1e01feb54829b3094af74252aff385",
"reference": "899b0de58c1e01feb54829b3094af74252aff385",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/fb4f83e6e2d718d1e5fbfe3a20cced83f47f040f",
"reference": "fb4f83e6e2d718d1e5fbfe3a20cced83f47f040f",
"shasum": ""
},
"require": {
@ -1797,7 +1891,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/3.2.0"
"source": "https://github.com/getsentry/sentry-php/tree/3.2.1"
},
"funding": [
{
@ -1809,7 +1903,7 @@
"type": "custom"
}
],
"time": "2021-03-03T11:54:34+00:00"
"time": "2021-04-06T07:55:41+00:00"
},
{
"name": "spatie/array-to-xml",
@ -1877,16 +1971,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.2.0",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665"
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": ""
},
"require": {
@ -1895,7 +1989,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1924,7 +2018,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/master"
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"funding": [
{
@ -1940,7 +2034,7 @@
"type": "tidelift"
}
],
"time": "2020-09-07T11:33:47+00:00"
"time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/http-client",
@ -2030,16 +2124,16 @@
},
{
"name": "symfony/http-client-contracts",
"version": "v2.3.1",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client-contracts.git",
"reference": "41db680a15018f9c1d4b23516059633ce280ca33"
"reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/41db680a15018f9c1d4b23516059633ce280ca33",
"reference": "41db680a15018f9c1d4b23516059633ce280ca33",
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/7e82f6084d7cae521a75ef2cb5c9457bbda785f4",
"reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4",
"shasum": ""
},
"require": {
@ -2050,9 +2144,8 @@
},
"type": "library",
"extra": {
"branch-version": "2.3",
"branch-alias": {
"dev-main": "2.3-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -2089,7 +2182,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/http-client-contracts/tree/v2.3.1"
"source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0"
},
"funding": [
{
@ -2105,7 +2198,7 @@
"type": "tidelift"
}
],
"time": "2020-10-14T17:08:19+00:00"
"time": "2021-04-11T23:07:08+00:00"
},
{
"name": "symfony/options-resolver",
@ -2578,21 +2671,21 @@
},
{
"name": "symfony/service-contracts",
"version": "v2.2.0",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.0"
"psr/container": "^1.1"
},
"suggest": {
"symfony/service-implementation": ""
@ -2600,7 +2693,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -2637,7 +2730,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/master"
"source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
},
"funding": [
{
@ -2653,7 +2746,7 @@
"type": "tidelift"
}
],
"time": "2020-09-07T11:33:47+00:00"
"time": "2021-04-01T10:43:52+00:00"
},
{
"name": "symfony/var-dumper",
@ -2914,16 +3007,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.5.8",
"version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "9d583721a7157ee997f235f327de038e7ea6dac4"
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4",
"reference": "9d583721a7157ee997f235f327de038e7ea6dac4",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
"shasum": ""
},
"require": {
@ -2966,13 +3059,14 @@
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2020-10-23T02:01:07+00:00"
"time": "2021-04-09T00:54:41+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"nikic/fast-route": 20
"nikic/fast-route": 20,
"jenstornell/tiny-html-minifier": 20
},
"prefer-stable": false,
"prefer-lowest": false,

View File

@ -1,6 +1,8 @@
<?php
require_once 'vendor/autoload.php';
use DebugBar\StandardDebugBar;
use MinistryOfWeb\OsmTiles\Converter;
use MinistryOfWeb\OsmTiles\LatLng;
if(!file_exists("config.php") && !file_exists("../../config.php")) {
header('Location: install/install.php');
@ -193,12 +195,66 @@ class tools
header("data: ".$response_data);
header("Content-type: application/json");
if(!is_null($debugbar)) $debugbar->sendDataInHeaders(true);
if(isset($_GET["old_data"]) && $_GET["old_data"] !== $response_data){
if(isset($_GET["oldData"]) && $_GET["oldData"] !== $response_data){
print($json_response);
} else {
print("{}");
}
}
public function convertMapAddress($lat, $lng, $zoom){
$converter = new Converter();
$point = new LatLng($lat, $lng);
$tile = $converter->toTile($point, $zoom);
$tile_servers = ["a", "b", "c"];
$tileServer = $tile_servers[array_rand($tile_servers)];
return sprintf("https://{$tileServer}.tile.openstreetmap.org/{$zoom}/%d/%d.png", $tile->getX(), $tile->getY());
}
public function cachePreviewMap($filename, $lat, $lng, $zoom=16){
$url = $this->convertMapAddress($lat, $lng, $zoom);
$options = ['http' => [
'user_agent' => 'AllertaVVF dev version (cached map previews generator)'
]];
$context = stream_context_create($options);
$data = file_get_contents($url, false, $context);
try {
if (!file_exists('resources/images/map_cache')) {
mkdir('resources/images/map_cache', 0755, true);
}
$filePath = "resources/images/map_cache/".$filename.".png";
file_put_contents($filePath, $data);
if(extension_loaded('gd')){
$img = imagecreatefrompng($filePath);
$marker = imagecreatefromgif("resources/images/marker.gif");
$textcolor = imagecolorallocate($img, 0, 0, 0);
imagestring($img, 5, 0, 236, ' OpenStreetMap contributors', $textcolor);
imagecopy($img, $marker, 120, 87, 0, 0, 25, 41);
imagepng($img, $filePath);
imagedestroy($img);
}
} catch (\Throwable $th) {
return false;
}
}
public function checkPlaceParam($place){
if(preg_match('/[+-]?\d+([.]\d+)?[;][+-]?\d+([.]\d+)?/', $place)){
$lat = explode(";", $place)[0];
$lng = explode(";", $place)[1];
$mapImageID = \Delight\Auth\Auth::createUuid();
$this->cachePreviewMap($mapImageID, $lat, $lng);
$place = $place . "#" . $mapImageID;
}
return $place;
}
}
class database
@ -246,10 +302,10 @@ class database
}
if($this->load_from_file) {
if(file_exists($this->options_cache_file)/* && time()-@filemtime($this->options_cache_file) < 604800*/) {
$this->options = unserialize(file_get_contents($this->options_cache_file), ['allowed_classes' => false]);
$this->options = json_decode(file_get_contents($this->options_cache_file), true);
} else {
$this->options = $this->exec("SELECT * FROM `%PREFIX%_options` WHERE `enabled` = 1", true);
file_put_contents($this->options_cache_file, serialize($this->options));
file_put_contents($this->options_cache_file, json_encode($this->options));
}
} else {
$this->options = $this->exec("SELECT * FROM `%PREFIX%_options` WHERE `enabled` = 1", true);
@ -450,10 +506,16 @@ class user
return $name;
}
public function hidden()
public function hidden($user = null)
{
$profiles = $this->database->exec("SELECT `name` FROM `%PREFIX%_profiles` WHERE hidden = 1;", true);
return $profiles;
if(is_null($user)){
$user = $this->auth->getUserId();
}
$result = $this->database->exec("SELECT `hidden` FROM `%PREFIX%_profiles` WHERE id = :id;", true, [":id" => $user]);
if(isset($result[0]) && isset($result[0]["hidden"])){
return boolval($result[0]["hidden"]);
}
return false;
}
public function available($name)
@ -471,7 +533,7 @@ class user
return array("autenticated" => $this->authenticated(), "id" => $this->auth->getUserId(), "name" => $this->name(), "full_viewer" => $this->requireRole(Role::FULL_VIEWER), "tester" => $this->requireRole(Role::TESTER), "developer" => $this->requireRole(Role::DEVELOPER));
}
public function login($name, $password, $remember_me, $twofa=null)
public function login($name, $password, $remember_me)
{
$this->tools->profiler_start("Login");
if(!empty($name)) {
@ -545,16 +607,18 @@ class user
if(is_null($editor)){
$editor = $changed;
}
if($this->database->get_option("log_save_ip")){
$ip = $this->tools->get_ip();
} else {
$ip = null;
if(!$this->hidden($editor)){
if($this->database->get_option("log_save_ip")){
$ip = $this->tools->get_ip();
} else {
$ip = null;
}
$source_type = defined("REQUEST_USING_API") ? "api" : "web";
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? mb_strimwidth($_SERVER['HTTP_USER_AGENT'], 0, 200, "...") : null;
$params = [":action" => $action, ":changed" => $changed, ":editor" => $editor, ":timestamp" => $timestamp, ":ip" => $ip, "source_type" => $source_type, "user_agent" => $user_agent];
$sql = "INSERT INTO `%PREFIX%_log` (`id`, `action`, `changed`, `editor`, `timestamp`, `ip`, `source_type`, `user_agent`) VALUES (NULL, :action, :changed, :editor, :timestamp, :ip, :source_type, :user_agent)";
$this->database->exec($sql, false, $params);
}
$source_type = defined("REQUEST_USING_API") ? "api" : "web";
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? mb_strimwidth($_SERVER['HTTP_USER_AGENT'], 0, 200, "...") : null;
$params = [":action" => $action, ":changed" => $changed, ":editor" => $editor, ":timestamp" => $timestamp, ":ip" => $ip, "source_type" => $source_type, "user_agent" => $user_agent];
$sql = "INSERT INTO `%PREFIX%_log` (`id`, `action`, `changed`, `editor`, `timestamp`, `ip`, `source_type`, `user_agent`) VALUES (NULL, :action, :changed, :editor, :timestamp, :ip, :source_type, :user_agent)";
$this->database->exec($sql, false, $params);
$this->tools->profiler_stop();
}
@ -573,6 +637,8 @@ class user
public function add_user($email, $name, $username, $password, $phone_number, $birthday, $chief, $driver, $hidden, $disabled, $inserted_by)
{
//TODO: save birthday in db
bdump($birthday);
$this->tools->profiler_start("Add user");
$userId = $this->auth->admin()->createUserWithUniqueUsername($email, $password, $username);
if($userId) {
@ -755,7 +821,7 @@ class translations
} else {
$client_languages = explode(",", $client_languages);
$tmp_languages = [];
foreach($client_languages as $key=>$language){
foreach($client_languages as $language){
if(strpos($language, ';') == false) {
$tmp_languages[$language] = 1;
} else {
@ -877,6 +943,7 @@ function init_class($enableDebugger=true, $headers=true)
global $webpack_manifest_path;
$error = error_get_last();
if ($error) {
bdump($webpack_manifest_path);
require("error_page.php");
show_error_page(500);
}

View File

@ -12,7 +12,7 @@ function customErrorHandler(int $errNo, string $errMsg, string $file, int $line)
"file" => $file,
"line" => $line
];
$output_status = "error";
var_dump($output);
}
error_reporting(-1);
set_error_handler('customErrorHandler');

View File

@ -6,6 +6,6 @@
},
"experimentalStudio": true,
"chromeWebSecurity": false,
"defaultCommandTimeout": 20000,
"requestTimeout": 30000
"defaultCommandTimeout": 40000,
"requestTimeout": 60000
}

View File

@ -1 +1 @@
[{"place_id":257830288,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":44882,"boundingbox":["45.2042549","46.3548531","9.8362928","10.842675"],"lat":"45.77958045","lon":"10.4258729694612","display_name":"Brescia, Lombardy, Italy","class":"boundary","type":"administrative","importance":0.7354640205264362,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"},{"place_id":257390216,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":45144,"boundingbox":["45.4807171","45.5899752","10.1470684","10.3002186"],"lat":"45.5398022","lon":"10.2200214","display_name":"Brescia, Lombardy, Italy","class":"boundary","type":"administrative","importance":0.7271074461208031,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"},{"place_id":54063101,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":4553822557,"boundingbox":["45.5273342","45.5373342","10.2078404","10.2178404"],"lat":"45.5323342","lon":"10.2128404","display_name":"Brescia, Piazzale Stazione, Centro Storico Sud, Zona Centro, Brescia, Lombardy, 25122, Italy","class":"railway","type":"station","importance":0.48614554653236075,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//transport_train_station2.p.20.png"},{"place_id":23143065,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":2409443276,"boundingbox":["44.4687976","44.4688976","8.6048681","8.6049681"],"lat":"44.4688476","lon":"8.6049181","display_name":"Brescia, Urbe, Savona, Liguria, 17048, Italy","class":"place","type":"isolated_dwelling","importance":0.29999999999999993},{"place_id":197395200,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":474271843,"boundingbox":["20.5751086","20.5752334","-103.3814379","-103.3805205"],"lat":"20.5751086","lon":"-103.3808414","display_name":"Brescia, Tlaquepaque, San Pedro Tlaquepaque, Jalisco, 45602, Mexico","class":"highway","type":"living_street","importance":0.19999999999999998}]
[{"place_id":257830288,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":44882,"boundingbox":["45.2042549","46.3548531","9.8362928","10.842675"],"lat":"45.77958045","lon":"10.4258729694612","display_name":"Brescia, Lombardia, Italia","class":"boundary","type":"administrative","importance":0.7354640205264362,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"},{"place_id":257390216,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":45144,"boundingbox":["45.4807171","45.5899752","10.1470684","10.3002186"],"lat":"45.5398022","lon":"10.2200214","display_name":"Brescia, Lombardia, Italia","class":"boundary","type":"administrative","importance":0.7271074461208031,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"},{"place_id":54063101,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":4553822557,"boundingbox":["45.5273342","45.5373342","10.2078404","10.2178404"],"lat":"45.5323342","lon":"10.2128404","display_name":"Brescia, Piazzale Stazione, Centro Storico Sud, Zona Centro, Brescia, Lombardia, 25122, Italia","class":"railway","type":"station","importance":0.48614554653236075,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//transport_train_station2.p.20.png"},{"place_id":23143065,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":2409443276,"boundingbox":["44.4687976","44.4688976","8.6048681","8.6049681"],"lat":"44.4688476","lon":"8.6049181","display_name":"Brescia, Urbe, Savona, Liguria, 17048, Italia","class":"place","type":"isolated_dwelling","importance":0.29999999999999993},{"place_id":163311426,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":307938666,"boundingbox":["-29.9019023","-29.9008417","-71.2670192","-71.2669167"],"lat":"-29.9014479","lon":"-71.2669709","display_name":"Brescia, Condominio Capri, La Serena, Provincia de Elqui, Coquimbo Region, 17000000, Cile","class":"highway","type":"residential","importance":0.19999999999999998}]

View File

@ -15,8 +15,8 @@ describe("Service management", () => {
cy.stub(win, 'prompt').returns('test');
}
});
cy.get('.form-control').clear();
cy.get('.form-control').type('07/12/2020');
cy.get('#date-picker').clear();
cy.get('#date-picker').type('07/12/2020');
cy.window().then(win => win.$('.datepicker').remove());
cy.get('#progressivo').clear();
cy.get('#progressivo').type('1234/5');
@ -32,11 +32,11 @@ describe("Service management", () => {
cy.get('.crew-9').check();
cy.get('#addr').clear();
cy.get('#addr').type('brescia');
cy.get('.btn').click();
cy.get('#search_button').click();
cy.get('#search').click();
cy.get('.results-list > :nth-child(1) > a').click();
cy.get('#notes').click();
cy.get('.types').select('add_new');
cy.get('#types').select('add_new');
cy.wait('@ajax_add_type');
cy.get('[type="submit"]').click();
cy.wait('@ajax_services');
@ -58,8 +58,7 @@ describe("Service management", () => {
it('Edit service', function() {
cy.visit("/services.php");
cy.wait('@ajax_services');
cy.get('#row-0 > .dtr-control').click();
cy.get('.dtr-details a[data-action="edit"]').click();
cy.get('.dtr-details a[data-action="edit"]').first().click();
cy.get('#progressivo').clear();
cy.get('#progressivo').type('4321/5');
cy.get('.chief-11').uncheck();
@ -70,7 +69,7 @@ describe("Service management", () => {
cy.get('.crew-5').check();
cy.get('#addr').clear();
cy.get('#addr').type('milano');
cy.get('.btn').click();
cy.get('#search_button').click();
cy.get('.results-list > :nth-child(1) > a').click();
cy.get('[type="submit"]').click();
cy.wait('@ajax_services');
@ -92,8 +91,7 @@ describe("Service management", () => {
it('Delete Service', function() {
cy.visit("/services.php");
cy.wait('@ajax_services');
cy.get('#row-0 > .dtr-control').click();
cy.get('.dtr-details a[data-action="delete"]').click();
cy.get('.dtr-details a[data-action="delete"]').first().click();
cy.get('#remove').click();
cy.wait('@ajax_services');
cy.visit("/log.php");

View File

@ -9,8 +9,8 @@ describe("Training management", () => {
cy.stub(win, 'prompt').returns('test')
}
});
cy.get('.form-control').clear();
cy.get('.form-control').type('07/12/2020');
cy.get('#date-picker').clear();
cy.get('#date-picker').type('07/12/2020');
cy.window().then(win => win.$('.datepicker').remove());
cy.get('#name').clear();
cy.get('#name').type('Test Training');
@ -25,7 +25,7 @@ describe("Training management", () => {
cy.get('.crew-6').check();
cy.get('#addr').clear();
cy.get('#addr').type('brescia');
cy.get('.btn').click();
cy.get('#search_button').click();
cy.get('#search').click();
cy.get('.results-list > :nth-child(1) > a').click();
cy.get('[type="submit"]').click();
@ -42,8 +42,7 @@ describe("Training management", () => {
it('Edit Training', function() {
cy.visit("/trainings.php");
cy.wait('@ajax_trainings');
cy.get('#row-0 > .dtr-control').click();
cy.get('.dtr-details a[data-action="edit"]').click();
cy.get('.dtr-details a[data-action="edit"]').first().click();
cy.get('#name').clear();
cy.get('#name').type('Training 1 test');
cy.get('.chief-5').uncheck();
@ -54,7 +53,7 @@ describe("Training management", () => {
cy.get('.crew-8').check();
cy.get('#addr').clear();
cy.get('#addr').type('milano');
cy.get('.btn').click();
cy.get('#search_button').click();
cy.get('.results-list > :nth-child(1) > a').click();
cy.get('[type="submit"]').click();
cy.wait('@ajax_trainings');
@ -68,8 +67,7 @@ describe("Training management", () => {
it('Delete Training', function() {
cy.visit("/trainings.php");
cy.wait('@ajax_trainings');
cy.get('#row-0 > .dtr-control').click();
cy.get('.dtr-details a[data-action="delete"]').click();
cy.get('.dtr-details a[data-action="delete"]').first().click();
cy.get('#remove').click();
cy.wait('@ajax_trainings');
cy.visit("/log.php");

View File

@ -1,5 +1,5 @@
Cypress.on('uncaught:exception', (err, runnable) => {
// for some reasons, the test fails without this in cartain conditions...
// for some reasons, the test fails without this in certain conditions...
return false
})
@ -8,13 +8,6 @@ Cypress.Commands.add("login", (username="admin", password="correcthorsebatteryst
cy.setCookie("forceLanguage", "en");
cy.setCookie('disableServiceWorkerInstallation', '1');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_add_type.php').as('ajax_add_type');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_change_availability.php').as('ajax_change_availability');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_list.php').as('ajax_list');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_log.php').as('ajax_log');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_services.php').as('ajax_services');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_trainings.php').as('ajax_trainings');
cy.visit("/");
cy.get("input[name='name']")
.clear()
@ -45,4 +38,10 @@ beforeEach(() => {
cy.intercept('https://a.tile.openstreetmap.org/*/*/*.png', { fixture: 'map_frame_A.png' });
cy.intercept('https://b.tile.openstreetmap.org/*/*/*.png', { fixture: 'map_frame_B.png' });
cy.intercept('https://c.tile.openstreetmap.org/*/*/*.png', { fixture: 'map_frame_C.png' });
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_add_type.php**').as('ajax_add_type');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_change_availability.php**').as('ajax_change_availability');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_list.php**').as('ajax_list');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_log.php**').as('ajax_log');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_services.php**').as('ajax_services');
cy.intercept(Cypress.config('baseUrl')+'resources/ajax/ajax_trainings.php**').as('ajax_trainings');
});

View File

@ -7,7 +7,8 @@ if($tools->validate_form("mod", "add")) {
if($tools->validate_form(['date', 'code', 'beginning', 'end', 'place', 'notes', 'type', 'token'])) {
if($_POST["token"] == $_SESSION['token']) {
bdump("adding service");
$crud->add_service($_POST["date"], $_POST["code"], $_POST["beginning"], $_POST["end"], $_POST["chief"][0], $tools->extract_unique($_POST["drivers"]), $tools->extract_unique($_POST["crew"]), $_POST["place"], $_POST["notes"], $_POST["type"], $tools->extract_unique([$_POST["chief"],$_POST["drivers"],$_POST["crew"]]), $user->name());
$place = $tools->checkPlaceParam($_POST["place"]);
$crud->add_service($_POST["date"], $_POST["code"], $_POST["beginning"], $_POST["end"], $_POST["chief"][0], $tools->extract_unique($_POST["drivers"]), $tools->extract_unique($_POST["crew"]), $place, $_POST["notes"], $_POST["type"], $tools->extract_unique([$_POST["chief"],$_POST["drivers"],$_POST["crew"]]), $user->name());
$tools->redirect("services.php");
} else {
debug(); //TODO: remove debug info
@ -20,7 +21,8 @@ if($tools->validate_form("mod", "add")) {
if($_POST["token"] == $_SESSION['token']) {
bdump($_POST);
bdump("editing service");
$crud->edit_service($_POST["id"], $_POST["date"], $_POST["code"], $_POST["beginning"], $_POST["end"], $_POST["chief"][0], $tools->extract_unique($_POST["drivers"]), $tools->extract_unique($_POST["crew"]), $_POST["place"], $_POST["notes"], $_POST["type"], $tools->extract_unique([$_POST["chief"],$_POST["drivers"],$_POST["crew"]]), $user->name());
$place = $tools->checkPlaceParam($_POST["place"]);
$crud->edit_service($_POST["id"], $_POST["date"], $_POST["code"], $_POST["beginning"], $_POST["end"], $_POST["chief"][0], $tools->extract_unique($_POST["drivers"]), $tools->extract_unique($_POST["crew"]), $place, $_POST["notes"], $_POST["type"], $tools->extract_unique([$_POST["chief"],$_POST["drivers"],$_POST["crew"]]), $user->name());
$tools->redirect("services.php");
} else {
debug();
@ -30,10 +32,10 @@ if($tools->validate_form("mod", "add")) {
}
} elseif($tools->validate_form("mod", "delete")) {
bdump("removing service");
if($tools->validate_form(['id', 'increment', 'token'])) {
if($tools->validate_form(['id', 'token'])) {
if($_POST["token"] == $_SESSION['token']) {
bdump("removing service");
$crud->remove_service($_POST["id"], $_POST["increment"]);
$crud->remove_service($_POST["id"]);
$tools->redirect("services.php");
} else {
echo("1");
@ -62,11 +64,6 @@ if($tools->validate_form("mod", "add")) {
} else {
$values = [];
}
if(isset($_GET["increment"])) {
$increment = $_GET["increment"];
} else {
$increment = "";
}
if($modalità=="edit" || $modalità=="delete") {
if(empty($id)) {
echo("<pre>"); var_dump($_POST); echo("</pre>");
@ -74,7 +71,7 @@ if($tools->validate_form("mod", "add")) {
echo("<pre>"); var_dump($_POST); echo("</pre>");
}
}
loadtemplate('edit_service.html', ['service' => ['id' => $id, 'token' => $_SESSION['token'], 'modalità' => $modalità, 'crew' => $crew, 'types' => $types], 'values' => $values, 'increment' => $increment, 'title' => ucfirst($modalità) . ' '.ucfirst(t("service", false))]);
loadtemplate('edit_service.html', ['service' => ['id' => $id, 'token' => $_SESSION['token'], 'modalità' => $modalità, 'crew' => $crew, 'types' => $types], 'values' => $values, 'title' => t(ucfirst($modalità) . " service", false)]);
bdump($_SESSION['token'], "token");
}
?>

View File

@ -7,7 +7,8 @@ if($tools->validate_form("mod", "add")) {
if($tools->validate_form(['date', 'name', 'start_time', 'end_time', 'place', 'notes', 'token'])) {
if($_POST["token"] == $_SESSION['token']) {
bdump("adding training");
$crud->add_training($_POST["date"], $_POST["name"], $_POST["start_time"], $_POST["end_time"], $_POST["chief"][0], $tools->extract_unique($_POST["crew"]), $_POST["place"], $_POST["notes"], $tools->extract_unique([$_POST["chief"],$_POST["crew"]]), $user->name());
$place = $tools->checkPlaceParam($_POST["place"]);
$crud->add_training($_POST["date"], $_POST["name"], $_POST["start_time"], $_POST["end_time"], $_POST["chief"][0], $tools->extract_unique($_POST["crew"]), $place, $_POST["notes"], $tools->extract_unique([$_POST["chief"],$_POST["crew"]]), $user->name());
$tools->redirect("trainings.php");
} else {
debug(); //TODO: remove debug info
@ -20,7 +21,8 @@ if($tools->validate_form("mod", "add")) {
if($_POST["token"] == $_SESSION['token']) {
bdump($_POST);
bdump("editing training");
$crud->edit_training($_POST["id"], $_POST["date"], $_POST["name"], $_POST["start_time"], $_POST["end_time"], $_POST["chief"][0], $tools->extract_unique($_POST["crew"]), $_POST["place"], $_POST["notes"], $tools->extract_unique([$_POST["chief"],$_POST["crew"]]), $user->name());
$place = $tools->checkPlaceParam($_POST["place"]);
$crud->edit_training($_POST["id"], $_POST["date"], $_POST["name"], $_POST["start_time"], $_POST["end_time"], $_POST["chief"][0], $tools->extract_unique($_POST["crew"]), $place, $_POST["notes"], $tools->extract_unique([$_POST["chief"],$_POST["crew"]]), $user->name());
$tools->redirect("trainings.php");
} else {
debug();
@ -30,10 +32,10 @@ if($tools->validate_form("mod", "add")) {
}
} elseif($tools->validate_form("mod", "delete")) {
bdump("removing training");
if($tools->validate_form(['id', 'increment', 'token'])) {
if($tools->validate_form(['id', 'token'])) {
if($_POST["token"] == $_SESSION['token']) {
bdump("removing training");
$crud->remove_training($_POST["id"], $_POST["increment"]);
$crud->remove_training($_POST["id"]);
$tools->redirect("trainings.php");
} else {
debug();
@ -58,11 +60,6 @@ if($tools->validate_form("mod", "add")) {
} else {
$values = [];
}
if(isset($_GET["increment"])) {
$increment = $_GET["increment"];
} else {
$increment = "";
}
if($modalità=="edit" || $modalità=="delete") {
if(empty($id)) {
$tools->redirect("accessdenied.php");
@ -70,7 +67,7 @@ if($tools->validate_form("mod", "add")) {
//$tools->redirect("accessdenied.php");
}
}
loadtemplate('edit_training.html', ['training' => ['id' => $id, 'token' => $_SESSION['token'], 'modalità' => $modalità, 'crew' => $crew], 'values' => $values, 'increment' => $increment, 'title' => ucfirst($modalità) . ' '.ucfirst(t("training", false))]);
loadtemplate('edit_training.html', ['training' => ['id' => $id, 'token' => $_SESSION['token'], 'modalità' => $modalità, 'crew' => $crew], 'values' => $values, 'title' => t(ucfirst($modalità) . " training", false)]);
bdump($_SESSION['token'], "token");
}
?>

View File

@ -82,7 +82,7 @@ if($tools->validate_form("mod", "add")) {
$tools->redirect("accessdenied.php");
}
}
loadtemplate('edit_user.html', ['id' => $id, 'token' => $_SESSION["token"], 'modalità' => $modalità, 'values' => $values, 'title' => ucfirst($modalità) . ' '.ucfirst(t("user", false))]);
loadtemplate('edit_user.html', ['id' => $id, 'token' => $_SESSION["token"], 'modalità' => $modalità, 'values' => $values, 'title' => t(ucfirst($modalità) . " user", false)]);
bdump($_SESSION['token'], "token");
}
?>

View File

@ -62,8 +62,8 @@ function show_error_page($error=null, $error_message=null, $error_message_advanc
<div class="games_list" style="margin-left: 20px; text-align: left;">
While you are waiting, you can play some games:
<ul>
<li hidden><a href="javascript:play('pong')">Pong</a></li>
<li><a href="javascript:play('ld46')">What the firetruck</a></li>
<li hidden><a data-game="pong" class="playGame">Pong</a></li>
<li><a data-game="ld46" class="playGame">What the firetruck</a></li>
</ul>
</div>
<div class="credits" style="position:absolute;opacity: 0.5;bottom: 5px;right: 5px;">
@ -71,7 +71,6 @@ function show_error_page($error=null, $error_message=null, $error_message_advanc
</div>
<script src="<?php echo($main_script_url); ?>"></script>
<script src="<?php echo($game_script_url); ?>"></script>
<script>GAME_LOADING_ERROR_MSG="Game loading failed, please retry later.";</script>
<?php
}

View File

@ -32,7 +32,7 @@ function client_languages()
} else {
$client_languages = explode(",", $client_languages);
$tmp_languages = [];
foreach($client_languages as $key=>$language){
foreach($client_languages as $language){
if(strpos($language, ';') == false) {
$tmp_languages[$language] = 1;
} else {
@ -266,8 +266,8 @@ CREATE TABLE IF NOT EXISTS `".$prefix."_trainings` (
`chief` text NOT NULL,
`place` text NOT NULL,
`notes` text NOT NULL,
`increment` varchar(999) NOT NULL DEFAULT 'test',
`inserted_by` varchar(200) NOT NULL DEFAULT 'test',
`increment` varchar(999) NOT NULL,
`inserted_by` varchar(200) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `".$prefix."_services` (
@ -276,11 +276,11 @@ CREATE TABLE IF NOT EXISTS `".$prefix."_services` (
`code` text NOT NULL,
`beginning` time NOT NULL,
`end` time NOT NULL,
`chief` varchar(999) NOT NULL DEFAULT 'test',
`drivers` varchar(999) NOT NULL DEFAULT 'test',
`crew` varchar(999) NOT NULL DEFAULT 'test',
`place` varchar(999) NOT NULL DEFAULT 'test',
`notes` varchar(999) NOT NULL DEFAULT 'test',
`chief` varchar(999) NOT NULL,
`drivers` varchar(999) NOT NULL,
`crew` varchar(999) NOT NULL,
`place` varchar(999) NOT NULL,
`notes` varchar(999) NOT NULL,
`type` text NOT NULL,
`increment` varchar(999) NOT NULL,
`inserted_by` varchar(200) NOT NULL,
@ -487,10 +487,8 @@ function initOptions($name, $visible, $developer, $password, $report_email, $own
'use_custom_error_sound' => 0,
'use_custom_error_image' => 0,
'intrusion_save' => 1,
'intrusion_save_info' => 1,
'intrusion_save_info' => 0,
'log_save_ip' => 1,
'enable_technical_support' => 0,
'technical_support_key' => 0,
'cron_job_code' => ':cron_job_code',
'cron_job_enabled' => 1,
'cron_job_time' => ':cron_job_time',
@ -502,7 +500,8 @@ function initOptions($name, $visible, $developer, $password, $report_email, $own
'force_language' => 0,
'force_remember_cookie' => 0,
'holidays_provider' => 'USA',
'holidays_language' => 'en_US'
'holidays_language' => 'en_US',
'messages' => "{}"
];
$query = "";
foreach ($options as $key => $value) {
@ -662,7 +661,7 @@ function run_cli()
->setDescription(t("Destination path", false))
->setArgumentName('path')
->setValidation(
'is_writable', function ($operand, $value) {
'is_writable', function ($value) {
if(file_exists($value)) {
printf(t("%s is not writable. Directory permissions: %s"), $value, @fileperms($value));
exit(4);

View File

@ -232,7 +232,7 @@ function init_modal() {
$("#submit_schedules_change")
.unbind()
.click(submit_changes);
.on("click", submit_changes);
}
function extractSelections(){

View File

@ -6,11 +6,9 @@ $user->online_time_update();
$result = $database->exec("SELECT * FROM `%PREFIX%_profiles` ORDER BY available DESC, chief DESC, services ASC, availability_minutes ASC, name ASC;", true);
$hidden = $user->hidden();
$response = [];
foreach($result as $row){
if(!in_array($row['name'], $hidden) && ($row['hidden'] == 0 && $row['disabled'] == 0)){
if(!$user->hidden($row["id"])){
if($user->requireRole(Role::FULL_VIEWER)){
$name = $user->nameById($row["id"]);
$name_encoded = urlencode($user->name());

View File

@ -6,8 +6,6 @@ $user->online_time_update();
$result = $database->exec("SELECT * FROM `%PREFIX%_log` ORDER BY `timestamp` DESC", true);
$hidden = $user->hidden();
//https://stackoverflow.com/a/2524761
function isValidTimeStamp($timestamp)
{
@ -18,31 +16,29 @@ function isValidTimeStamp($timestamp)
$response = [];
foreach($result as $row){
if(!in_array($row['changed'], $hidden) OR in_array($user->name(), $hidden)){
if(isValidTimeStamp($row["timestamp"])){
$date = new DateTime();
$date->setTimestamp($row["timestamp"]);
$date = $date->format('Y-m-d H:i:s');
} else {
$date = $row["timestamp"];
}
if(!is_null($row["changed"])){
$changedName = $user->nameById($row["changed"]);
} else {
$changedName = "N/A";
}
if(!is_null($row["editor"])){
$editorName = $user->nameById($row["editor"]);
} else {
$editorName = "N/A";
}
$response[] = [
t($row["action"], false),
$changedName,
$editorName,
$date
];
if(isValidTimeStamp($row["timestamp"])){
$date = new DateTime();
$date->setTimestamp($row["timestamp"]);
$date = $date->format('Y-m-d H:i:s');
} else {
$date = $row["timestamp"];
}
if(!is_null($row["changed"])){
$changedName = $user->nameById($row["changed"]);
} else {
$changedName = "N/A";
}
if(!is_null($row["editor"])){
$editorName = $user->nameById($row["editor"]);
} else {
$editorName = "N/A";
}
$response[] = [
t($row["action"], false),
$changedName,
$editorName,
$date
];
}
$tools->ajax_page_response($response);
?>

View File

@ -33,7 +33,7 @@ foreach($result as $row){
s($row['notes'],false,true),
s($row['type'],false,true),
$database->get_option("service_edit") ? "<a class='pjax_disable' data-action='edit' href='edit_service.php?edit&id={$row['id']}'><i style='font-size: 40px' class='fa fa-edit'></i></a>" : null,
$database->get_option("service_remove") ? "<a class='pjax_disable' data-action='delete' href='edit_service.php?delete&id={$row['id']}&increment={$row['increment']}'><i style='font-size: 40px' class='fa fa-trash'></i></a>" : null
$database->get_option("service_remove") ? "<a class='pjax_disable' data-action='delete' href='edit_service.php?delete&id={$row['id']}'><i style='font-size: 40px' class='fa fa-trash'></i></a>" : null
];
}
$tools->ajax_page_response($response);

View File

@ -25,7 +25,7 @@ foreach($result as $row){
s($row['place'],false,true),
s($row['notes'],false,true),
$database->get_option("training_edit") ? "<a class='pjax_disable' data-action='edit' href='edit_training.php?edit&id={$row['id']}'><i style='font-size: 40px' class='fa fa-edit'></i></a>" : null,
$database->get_option("training_remove") ? "<a class='pjax_disable' data-action='delete' href='edit_training.php?delete&id={$row['id']}&increment={$row['increment']}'><i style='font-size: 40px' class='fa fa-trash'></i></a>" : null
$database->get_option("training_remove") ? "<a class='pjax_disable' data-action='delete' href='edit_training.php?delete&id={$row['id']}'><i style='font-size: 40px' class='fa fa-trash'></i></a>" : null
];
}
$tools->ajax_page_response($response);

View File

@ -1,8 +1,8 @@
{
"sentry_enabled": false,
"sentry_dsn": "",
"sentry_environment": "prod",
"sentry_auth_token": "",
"sentry_organization": "",
"sentry_project": ""
"sentryEnabled": false,
"sentryDsn": "",
"sentryEnvironment": "prod",
"sentryAuthToken": "",
"sentryOrganization": "",
"sentryProject": ""
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,24 +1,32 @@
var GAME_LOADING_ERROR_MSG = 'Game loading failed, please retry later.';
const GAME_LOADING_ERROR_MSG = "Game loading failed, please retry later.";
async function play(game){
async function play (game) {
console.log("Opening game " + game + "...");
try {
await import(`./games/${game}/game.js`)
.then(({default: Game}) => {
var game = new Game();
$("body").append('<div class="modal" id="modal_game" tabindex="-1" role="dialog" data-backdrop="static" style="display: none; min-width: 100%; margin: 0px;"><div class="modal-dialog" role="document" style="min-width: 100%; margin: 0;"><div class="modal-content" style="min-height: 100vh;" id="modal_game_content"></div></div></div>');
$("#modal_game_content").append(`<div class="modal-header"><h5 class="modal-title" style="color: black">${game.title}</h5><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button></div><div class="modal-body" id="modal_game_body"></div>`);
$("#modal_game_body").append(`<div id="game_content" style="text-align: center"></div><p style="text-align: right; color: black;">Game by <a style="color: blue" target="_blank" href="${game.author_url}">${game.author}</a></p>`);
$('#modal_game').modal('show');
game.initialize($("#game_content"));
});
$('#modal_game').on('hidden.bs.modal', function (e) {
.then(({ default: Game }) => {
const game = new Game();
$("body").append("<div class=\"modal\" id=\"modal_game\" tabindex=\"-1\" role=\"dialog\" data-backdrop=\"static\" style=\"display: none; min-width: 100%; margin: 0px;\"><div class=\"modal-dialog\" role=\"document\" style=\"min-width: 100%; margin: 0;\"><div class=\"modal-content\" style=\"min-height: 100vh;\" id=\"modal_game_content\"></div></div></div>");
$("#modal_game_content").append(`<div class="modal-header"><h5 class="modal-title" style="color: black">${game.title}</h5><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button></div><div class="modal-body" id="modal_game_body"></div>`);
$("#modal_game_body").append(`<div id="game_content" style="text-align: center"></div><p style="text-align: right; color: black;">Game by <a style="color: blue" target="_blank" href="${game.authorUrl}">${game.author}</a></p>`);
$("#modal_game").modal("show");
game.initialize($("#game_content"));
});
$("#modal_game").on("hidden.bs.modal", function (e) {
$("#modal_game").remove();
})
});
} catch (error) {
console.error(error);
toastr.error(GAME_LOADING_ERROR_MSG);
}
}
window.play = play;
window.GAME_LOADING_ERROR_MSG = GAME_LOADING_ERROR_MSG;
$(function() {
$(".playGame").each((num, elem) => {
console.log(num, elem);
let game = elem.getAttribute("data-game");
if(game !== null){
$(elem).on("click", function(){ play(game); });
}
});
});

View File

@ -2,7 +2,7 @@ export default class {
constructor(){
this.title = "Empty game";
this.author = "Prova";
this.author_url = "https://example.com/";
this.authorUrl = "https://example.com/";
}
initialize(container){

View File

@ -1,18 +1,18 @@
import {default as createUnityInstance} from './ld46.loader.js';
import {default as createUnityInstance} from "./ld46.loader.js";
import build_size_data from './ld46.data.gz';
import build_size_framework from './ld46.framework.js.gz';
import build_size_wasm from './ld46.wasm.gz';
import buildSizeData from "./ld46.data.gz";
import buildSizeFramework from "./ld46.framework.js.gz";
import buildSizeWasm from "./ld46.wasm.gz";
console.log("data "+build_size_data);
console.log("framework "+build_size_framework);
console.log("wasm "+build_size_wasm);
console.log("data "+buildSizeData);
console.log("framework "+buildSizeFramework);
console.log("wasm "+buildSizeWasm);
export default class {
constructor(){
this.title = "What the firetruck";
this.author = "dvdfu";
this.author_url = "https://github.com/dvdfu";
this.authorUrl = "https://github.com/dvdfu";
}
initialize(container){

View File

@ -1,237 +1,237 @@
body:not(table) {
max-width: 100%;
overflow-x: hidden;
max-width: 100%;
overflow-x: hidden;
}
@keyframes gradual_blur {
0% {-webkit-filter: blur(0px);}
50% {-webkit-filter: blur(2px);}
100% {-webkit-filter: blur(5px);}
0% { -webkit-filter: blur(0); }
50% { -webkit-filter: blur(2px); }
100% { -webkit-filter: blur(5px); }
}
.loading_blur {
animation: gradual_blur 1s;
animation-fill-mode: forwards;
cursor: wait;
animation: gradual_blur 1s;
animation-fill-mode: forwards;
cursor: wait;
}
.loading_no_blur {
animation: gradual_blur 1s;
animation-direction: reverse;
animation-fill-mode: forwards;
animation: gradual_blur 1s;
animation-direction: reverse;
animation-fill-mode: forwards;
}
.loading_overlay {
position: absolute;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
center {
text-align: center;
text-align: center;
}
#modulogin {
margin-top: 60px;
padding: 30px 0 30px 0;
width: 90%;
height: auto;
background: #fafafa;
border-radius: 15px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
margin-top: 60px;
padding: 30px 0 30px 0;
width: 90%;
height: auto;
background: #fafafa;
border-radius: 15px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
input::placeholder {
color: lightgray;
color: lightgray;
}
.modal-text {
margin-top: 15px;
line-height: 25px;
font-size: 1.0em;
font-family: calibri;
margin-top: 15px;
line-height: 25px;
/*
font-size: 1em;
font-family: calibri;
*/
}
/* Add a black background color to the top navigation */
.topnav {
background-color: red;
overflow: hidden;
background-color: red;
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
background-color: #ddd;
color: black;
}
/* Add an active class to highlight the current page */
.active {
background-color: #4CAF50;
color: white;
background-color: #4caf50;
color: white;
}
/* Hide the link that should open and close the topnav on small screens */
.topnav .icon {
display: none;
display: none;
}
/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
@media screen and (max-width: 600px) {
.topnav a:not(:first-child) {
display: none;
}
.topnav a:not(:first-child) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
.topnav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
@media screen and (max-width: 600px) {
.topnav.responsive {
position: relative;
}
.topnav.responsive {
position: relative;
}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
#bottom {
background-color: grey;
color: white;
background-color: grey;
color: white;
}
div.img {
border: 2px solid white;
float: left;
margin: 10px;
width: 100px;
height: 100px;
border: 2px solid white;
float: left;
margin: 10px;
width: 100px;
height: 100px;
}
#add {
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: bold 12px Arial, Helvetica, sans-serif;
color: #fff;
padding: 10px 20px;
border: solid 1px #0076a3;
background: #0095cd;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: bold 12px Arial, Helvetica, sans-serif;
color: #fff;
padding: 10px 20px;
border: solid 1px #0076a3;
background: #0095cd;
}
.form_input {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
background-color: #4caf50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
}
button:hover {
opacity: 0.8;
opacity: 0.8;
}
.container {
padding: 16px;
padding: 16px;
}
span.psw {
float: right;
padding-top: 16px;
float: right;
padding-top: 16px;
}
/* Change styles for span and cancel button on extra small screens */
@media screen and (max-width: 300px) {
span.psw {
display: block;
float: none;
}
span.psw {
display: block;
float: none;
}
.cancelbtn {
width: 100%;
}
.cancelbtn {
width: 100%;
}
}
textarea {
width: 100%;
height: 150px;
padding: 12px 20px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
resize: none;
width: 100%;
height: 150px;
padding: 12px 20px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
resize: none;
}
#href {
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: bold 12px Arial, Helvetica, sans-serif;
color: #fff;
padding: 10px 20px;
border: solid 1px #0076a3;
background: #0095cd;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: bold 12px Arial, Helvetica, sans-serif;
color: #fff;
padding: 10px 20px;
border: solid 1px #0076a3;
background: #0095cd;
}
table {
margin: auto;
max-width: 95%;
text-align:center;
overflow-x:auto;
margin: auto;
max-width: 95%;
text-align: center;
overflow-x: auto;
}
#table_wrapper{
margin-left:auto;
margin-right:auto;
width: 95%;
#table_wrapper {
margin-left: auto;
margin-right: auto;
width: 95%;
}
th, td {
text-align: center;
vertical-align: middle !important;
th,
td {
text-align: center;
vertical-align: middle !important;
}
.fa{
vertical-align: middle;
font-size: 20px;
}
.fa {
vertical-align: middle;
font-size: 20px;
}

View File

@ -1,49 +1,48 @@
jQuery = $;
window.$ = window.jQuery = $;
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import './main.css';
import './font-awesome.scss';
import 'bootstrap-datepicker';
import '../node_modules/bootstrap-toggle/css/bootstrap-toggle.css';
import '../node_modules/bootstrap-toggle/js/bootstrap-toggle.js';
import '../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css';
import 'time-input-polyfill/auto';
import 'jquery-pjax';
import toastr from 'toastr'
import 'toastr/build/toastr.css';
import "bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import "./main.css";
import "./font-awesome.scss";
import "bootstrap-datepicker";
import "../node_modules/bootstrap-toggle/css/bootstrap-toggle.css";
import "../node_modules/bootstrap-toggle/js/bootstrap-toggle.js";
import "../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css";
import "time-input-polyfill/auto";
import "jquery-pjax";
import toastr from "expose-loader?exposes=toastr!toastr";
import "toastr/build/toastr.css";
window.toastr = toastr;
toastr.options = {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-bottom-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
closeButton: false,
debug: false,
newestOnTop: false,
progressBar: true,
positionClass: "toast-bottom-right",
preventDuplicates: false,
onclick: null,
showDuration: "300",
hideDuration: "1000",
timeOut: "5000",
extendedTimeOut: "1000",
showEasing: "swing",
hideEasing: "linear",
showMethod: "fadeIn",
hideMethod: "fadeOut"
};
$.fn.loading = function(action="start", options) {
var opts = $.extend( {}, $.fn.loading.defaults, options );
$.fn.loading = function (action = "start", options) {
const opts = $.extend({}, $.fn.loading.defaults, options);
if(action == "show") {
this.addClass("loading_blur");
$( "body" ).append( "<div id='loading_div' class='loading_overlay'><p class=''><b>"+opts.message+"</b></p></div>" );
} else if(action == "hide") {
this.removeClass("loading_blur");
this.addClass("loading_no_blur");
setTimeout(() => {
this.removeClass("loading_no_blur");
}, 1000);
$( "#loading_div" ).remove();
if (action === "show") {
this.addClass("loading_blur");
$("body").append("<div id='loading_div' class='loading_overlay'><p class=''><b>" + opts.message + "</b></p></div>");
} else if (action === "hide") {
this.removeClass("loading_blur");
this.addClass("loading_no_blur");
setTimeout(() => {
this.removeClass("loading_no_blur");
}, 1000);
$("#loading_div").remove();
}
};
@ -51,74 +50,74 @@ $.fn.loading.defaults = {
message: "Loading..."
};
console.log("Commit: "+process.env.GIT_VERSION);
console.log("Date: "+process.env.GIT_AUTHOR_DATE);
console.log("Bundle mode: "+process.env.BUNDLE_MODE);
console.log("Bundle date: "+new Date(process.env.BUNDLE_DATE).toISOString());
console.log("Commit: " + process.env.GIT_VERSION);
console.log("Date: " + process.env.GIT_AUTHOR_DATE);
console.log("Bundle mode: " + process.env.BUNDLE_MODE);
console.log("Bundle date: " + new Date(process.env.BUNDLE_DATE).toISOString());
$(document).pjax('a:not(.pjax_disable)', '#content', {timeout: 100000});
$(document).on('pjax:start', function() {
if(document.getElementById("topNavBar") !== undefined){
$(document).pjax("a:not(.pjax_disable)", "#content", { timeout: 100000 });
$(document).on("pjax:start", function () {
if (document.getElementById("topNavBar") !== undefined) {
document.getElementById("topNavBar").className = "topnav";
}
old_data = "null";
oldData = "null";
fillTable = undefined;
table_engine = "datatables";
if(window.loadTable_interval !== undefined){
clearInterval(window.loadTable_interval);
window.loadTable_interval = undefined;
tableEngine = "datatables";
if (loadTableInterval !== undefined) {
clearInterval(loadTableInterval);
loadTableInterval = undefined;
}
})
});
// Cookie functions from w3schools
function setCookie(cname, cvalue, exdays) {
var d = new Date();
function setCookie (cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
const expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
function getCookie (cname) {
const name = cname + "=";
const decodedCookie = decodeURIComponent(document.cookie);
const ca = decodedCookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === " ") {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
$( document ).ajaxError(function(event, xhr, settings, error) {
console.error("Error requesting content: "+error+" - status code "+xhr.status);
console.log(event);
console.log(xhr);
console.log(settings);
$(document).ajaxError(function (event, xhr, settings, error) {
console.error("Error requesting content: " + error + " - status code " + xhr.status);
console.log(event);
console.log(xhr);
console.log(settings);
});
if (getCookie("authenticated")) {
var installServiceWorker = false;
if(window.skipServiceWorkerInstallation !== undefined){ //if you want to disable SW for example via GreasyFork userscript
if (window.skipServiceWorkerInstallation !== undefined) { // if you want to disable SW for example via GreasyFork userscript
installServiceWorker = false;
}
if(getCookie("disableServiceWorkerInstallation")){
if (getCookie("disableServiceWorkerInstallation")) {
console.log("Skipping ServiceWorker installation because cookie 'disableServiceWorkerInstallation' exists");
installServiceWorker = false;
}
if ('serviceWorker' in navigator) {
if ('connection' in navigator && navigator.connection.saveData && !getCookie("forceServiceWorkerInstallation")) {
if ("serviceWorker" in navigator) {
if ("connection" in navigator && navigator.connection.saveData && !getCookie("forceServiceWorkerInstallation")) {
console.log("Skipping ServiceWorker installation because saveData is enabled");
installServiceWorker = false;
}
if ('storage' in navigator && 'estimate' in navigator.storage && !getCookie("forceServiceWorkerInstallation")){
navigator.storage.estimate().then(quota => {
if ("storage" in navigator && "estimate" in navigator.storage && !getCookie("forceServiceWorkerInstallation")) {
navigator.storage.estimate().then((quota) => {
const requiredMemory = 3 * 1e+6;
if (quota < requiredMemory) {
console.log("Skipping ServiceWorker installation because memory is low. memory="+quota);
console.log("Skipping ServiceWorker installation because memory is low. memory=" + quota);
installServiceWorker = false;
}
});
@ -127,122 +126,121 @@ if (getCookie("authenticated")) {
installServiceWorker = false;
}
}
if(installServiceWorker){
window.addEventListener('load', () => {
navigator.serviceWorker.register('sw.js').then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
if (installServiceWorker) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("sw.js").then((registration) => {
console.log("SW registered: ", registration);
}).catch((registrationError) => {
console.log("SW registration failed: ", registrationError);
});
});
}
$( document ).ready(function() {
if($("#frontend_version") !== undefined){
$("#frontend_version").append(process.env.GIT_VERSION+" aggiornamento "+new Date(process.env.BUNDLE_DATE).toLocaleString());
$(function () {
if ($("#frontend_version") !== undefined) {
$("#frontend_version").append(process.env.GIT_VERSION + " aggiornamento " + new Date(process.env.BUNDLE_DATE).toLocaleString());
}
});
var offline = false;
var loadTable_interval = undefined;
var old_data = "null";
var table_engine = "datatables";
var loadTableInterval = undefined;
var oldData = "null";
var tableEngine = "datatables";
var fillTable = undefined;
var fillTableLoaded = undefined;
async function loadTable({table_page, set_interval=true, interval=10000, onlineReload=false, use_custom_table_engine=false, callback=false}){
if (typeof fillTable === "undefined"){
if(use_custom_table_engine !== false){
table_engine = use_custom_table_engine;
} else if ('connection' in navigator && navigator.connection.saveData) {
table_engine = "default";
window.addEventListener("securitypolicyviolation", console.error.bind(console));
$(function() {
$("#menuButton").on("click", function() {
const topNavBar = document.getElementById("topNavBar");
if (topNavBar.className === "topnav") {
topNavBar.className += " responsive";
} else {
topNavBar.className = "topnav";
}
fillTable = await import(`./table_engine_${table_engine}.js`)
.then(({default: _}) => {
return _;
});
});
});
export async function loadTable ({ tablePage, setTableRefreshInterval = true, interval = 10000, onlineReload = false, useCustomTableEngine = false, callback = false }) {
if(loadTableInterval !== undefined) {
clearInterval(loadTableInterval);
loadTableInterval = undefined;
}
if ('getBattery' in navigator) {
if (typeof fillTable === "undefined") {
if (useCustomTableEngine !== false) {
tableEngine = useCustomTableEngine;
} else if ("connection" in navigator && navigator.connection.saveData) {
tableEngine = "default";
}
fillTableLoaded = await import(`./table_engine_${tableEngine}.js`)
.then(({ default: _ }) => {
return _;
});
}
if ("getBattery" in navigator) {
navigator.getBattery().then((level, charging) => {
if (!charging && level < 0.2) {
return;
}
})
});
}
if ('deviceMemory' in navigator && navigator.deviceMemory < 0.2) {
if ("deviceMemory" in navigator && navigator.deviceMemory < 0.2) {
return;
}
let replaceLatLngWithMap = table_page == "services" || table_page == "trainings";
$.getJSON({ url: "resources/ajax/ajax_"+table_page+".php", data: { "old_data": old_data }, success: function( data, status, xhr ) {
old_data = xhr.getResponseHeader('data'); //TODO: refactoring and adding comments
console.log(data);
if(data.length > 0){
fillTable({data, replaceLatLngWithMap, callback});
var headers = new Headers();
headers.append('date', Date.now());
caches.open('tables-1').then((cache) => {
cache.put('/table_'+table_page+'.json', new Response(xhr.responseText, {headers: headers}))
});
}
if(window.offline){ // if xhr request successful, client is online
console.log(onlineReload);
if(onlineReload){
location.reload(); //for offline page
} else {
$("#offline_alert").hide(400);
window.offline = false;
const replaceLatLngWithMap = tablePage === "services" || tablePage === "trainings";
$.getJSON({
url: "resources/ajax/ajax_" + tablePage + ".php",
data: { oldData: oldData },
success: function (data, status, xhr) {
oldData = xhr.getResponseHeader("data"); // TODO: refactoring and adding comments
console.log(data);
if (data.length > 0) {
fillTableLoaded({ data, replaceLatLngWithMap, callback });
const headers = new Headers();
headers.append("date", Date.now());
caches.open("tables-1").then((cache) => {
cache.put("/table_" + tablePage + ".json", new Response(xhr.responseText, { headers: headers }));
});
}
if (offline) { // if xhr request successful, client is online
console.log(onlineReload);
if (onlineReload) {
location.reload(); // for offline page
} else {
$("#offline_alert").hide(400);
offline = false;
}
}
}
}}).fail(function(data, status) {
if(status == "parsererror"){
if($("#table_body").children().length == 0) { //this is a server-side authentication error on some cheap hosting providers
loadTable(table_page, set_interval, interval); //retry
}).fail(function (data, status) {
if (status === "parsererror") {
if ($("#table_body").children().length === 0) { // this is a server-side authentication error on some cheap hosting providers
loadTable(tablePage, setTableRefreshInterval, interval); // retry
} // else nothing
} else {
caches.open('tables-1').then(cache => {
cache.match("/table_"+table_page+".json").then(response => {
response.json().then(data => {
fillTable({data, replaceLatLngWithMap, callback});
caches.open("tables-1").then((cache) => {
cache.match("/table_" + tablePage + ".json").then((response) => {
response.json().then((data) => {
fillTableLoaded({ data, replaceLatLngWithMap, callback });
console.log("Table loaded from cache");
$("#offline_update").text(new Date(parseInt(response.headers.get("date"))).toLocaleString());
$("#offline_update").text(new Date(parseInt(response.headers.get("date"), 10)).toLocaleString());
});
});
});
if(!window.offline){ // if xhr request fails, client is offline
if (!offline) { // if xhr request fails, client is offline
$("#offline_alert").show(400);
window.offline = true;
offline = true;
}
}
});
if(set_interval){
if ('connection' in navigator && navigator.connection.saveData) {
if (setTableRefreshInterval) {
if ("connection" in navigator && navigator.connection.saveData) {
interval += 5000;
}
console.log("table_load interval "+interval);
window.loadTable_interval = setInterval(function() {
window.loadTable({table_page, set_interval: false, interval, onlineReload, use_custom_table_engine, callback: false});
console.log("table_load interval " + interval);
loadTableInterval = setInterval(function () {
loadTable({ tablePage, setTableRefreshInterval: false, interval, onlineReload, useCustomTableEngine, callback: false });
}, interval);
}
}
function chat() {
setCookie("chat", "true", 1);
location.reload();
}
window.addEventListener('securitypolicyviolation',console.error.bind(console));
function menu() {
var topNavBar = document.getElementById("topNavBar");
if (topNavBar.className === "topnav") {
topNavBar.className += " responsive";
} else {
topNavBar.className = "topnav";
}
}
window.loadTable_interval = loadTable_interval;
window.loadTable = loadTable;
window.setCookie = setCookie;
window.getCookie = getCookie;
window.chat = chat;
window.menu = menu;

View File

@ -1,32 +1,33 @@
div#map {
width: 100%;
height: 500px;
width: 100%;
height: 500px;
}
.map {
width: 100%;
height: 500px;
width: 100%;
height: 500px;
}
div#search {
background-color: rgba(255, 255, 255, 0.4);
bottom: 40px;
left: 40px;
width: auto;
height: auto;
padding: 10px;
background-color: rgba(255, 255, 255, 0.4);
bottom: 40px;
left: 40px;
width: auto;
height: auto;
padding: 10px;
}
div#results {
font-style: sans-serif;
color: black;
font-size: 75%;
font-style: sans-serif;
color: black;
font-size: 75%;
}
.fa.fa-map-marker-alt,.fa.fa-spinner.fa-spin {
line-height: inherit;
.fa.fa-map-marker-alt,
.fa.fa-spinner.fa-spin {
line-height: inherit;
}
.leaflet-pane.leaflet-shadow-pane {
display: none;
}
display: none;
}

View File

@ -1,210 +1,230 @@
import L from 'leaflet';
import 'leaflet.locatecontrol';
import '../node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.css'
import '../node_modules/leaflet/dist/leaflet.css';
import './maps.css';
import L from "leaflet";
import "leaflet.locatecontrol";
import "../node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.css";
import "../node_modules/leaflet/dist/leaflet.css";
import "./maps.css";
const iconRetinaUrl = 'resources/dist/marker-icon-2x.png';
const iconUrl = 'resources/dist/marker-icon.png';
const shadowUrl = 'resources/dist/marker-shadow.png';
const iconRetinaUrl = "resources/dist/marker-icon-2x.png";
const iconUrl = "resources/dist/marker-icon.png";
const shadowUrl = "resources/dist/marker-shadow.png";
const iconDefault = new L.Icon({
iconRetinaUrl,
iconUrl,
shadowUrl,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
iconRetinaUrl,
iconUrl,
shadowUrl,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
});
var marker;
var feature;
var map;
let marker;
let feature;
let map;
function set_marker(LatLng){
if(marker){
console.log("Marker exists");
//console.log(marker);
marker.remove();
}
function setMarker (LatLng) {
if (marker) {
console.log("Marker exists");
// console.log(marker);
marker.remove();
}
console.log(LatLng);
if($("input[name='place']").val() !== undefined){
if ($("input[name='place']").val() !== undefined) {
$("input[name='place']").val(LatLng.lat + ";" + LatLng.lng);
}
marker = L.marker(LatLng, {icon: iconDefault}).addTo(map);
marker = L.marker(LatLng, { icon: iconDefault }).addTo(map);
}
function load_map(lat=undefined, lng=undefined, selector_id=undefined, select=true) {
if(lat == undefined && lng == undefined){
lat = 45.5285; //TODO: replace hard-coded into cookie reading
lng = 10.2956;
}
if(selector_id == undefined){
selector_id = "map";
}
let zoom = select ? 10 : 17;
let latLng = new L.LatLng(lat, lng);
map = new L.Map(selector_id, {zoomControl: true});
var mapsList = [];
let osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttribution = 'Map data &copy; 2012 <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
osm = new L.TileLayer(osmUrl, {maxZoom: 20, attribution: osmAttribution});
export function loadMap (lat = undefined, lng = undefined, selectorId = undefined, select = true, removeMap = false) {
console.log("Loading map...", [lat, lng, selectorId, select]);
console.trace();
if (lat === undefined && lng === undefined) {
lat = 45.5285; // TODO: replace hard-coded into cookie reading
lng = 10.2956;
}
if (selectorId === undefined) {
selectorId = "map";
}
let container = L.DomUtil.get(selectorId);
if(container._leaflet_id){
console.log(mapsList);
if(removeMap){
mapsList[0].off();
mapsList[0].remove();
mapsList.splice(0, 1);
} else {
console.log("Skipping map loading because already loaded...");
return true;
}
}
const zoom = select ? 10 : 17;
const latLng = new L.LatLng(lat, lng);
L.Map.addInitHook(function () {
mapsList.push(this); // Use whatever global scope variable you like.
});
map = new L.Map(selectorId, { zoomControl: true });
map.setView(latLng, zoom).addLayer(osm);
const osmUrl = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
const osmAttribution = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
const osm = new L.TileLayer(osmUrl, { maxZoom: 20, attribution: osmAttribution });
if(select){
map.on('click', function(e) {
set_marker(e.latlng);
});
map.setView(latLng, zoom).addLayer(osm);
L.Control.CustomLocate = L.Control.Locate.extend({
_drawMarker: function() {
set_marker(this._event.latlng);
},
_onDrag: function(){},
_onZoom: function(){},
_onZoomEnd: function(){},
});
if (select) {
map.on("click", function (e) {
setMarker(e.latlng);
});
let lc = new L.Control.CustomLocate({
icon: "fa fa-map-marker",
cacheLocation: false, //disabled for privacy reasons
}).addTo(map);
L.Control.CustomLocate = L.Control.Locate.extend({
_drawMarker: function () {
setMarker(this._event.latlng);
},
_onDrag: function () {},
_onZoom: function () {},
_onZoomEnd: function () {}
});
if($("#addr").val() !== undefined){
document.getElementById("addr").addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
document.querySelector("#search > button").click();
}
});
}
const lc = new L.Control.CustomLocate({
icon: "fa fa-map-marker",
cacheLocation: false, // disabled for privacy reasons
initialZoomLevel: 16
}).addTo(map);
if(getCookie("experimental_read_clipboard")){
window.addEventListener("focus", function(event) {
if($("#addr").val() == ""){
console.log("Loading location from clipboard");
navigator.clipboard.readText().then(text => {
$("#addr").val(text);
if(!addr_search()){
$("#addr").val("");
}
}).catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
});
}
} else {
set_marker(latLng);
}
map.invalidateSize();
if ($("#addr").val() !== undefined) {
document.getElementById("addr").addEventListener("keydown", function (event) {
if (event.key === "Enter") {
event.preventDefault();
$("#search > button").trigger("click");
}
});
}
window.addEventListener("focus", function (event) {
if ($("#addr").val() === "") {
console.log("Loading location from clipboard");
try {
navigator.clipboard.readText().then((text) => {
$("#addr").val(text);
if (!addrSearch()) {
$("#addr").val("");
}
}).catch((err) => {
console.error("Failed to read clipboard contents: ", err);
});
} catch(error) {
console.error(error);
}
}
});
} else {
setMarker(latLng);
}
map.invalidateSize();
}
// from unknown source in the Internet
function chooseAddr(addr_lat, addr_lng, zoom=undefined, lat1=undefined, lng1=undefined, lat2=undefined, lng2=undefined, osm_type=undefined) {
addr_lat = addr_lat.replace(",", ".");
addr_lng = addr_lng.replace(",", ".");
if(lat1 !== undefined && lng1 !== undefined && lat2 !== undefined && lng2 !== undefined && osm_type !== undefined){
let loc1 = new L.LatLng(lat1, lng1);
let loc2 = new L.LatLng(lat2, lng2);
let bounds = new L.LatLngBounds(loc1, loc2);
console.log(lat1, lng1, lat2, lng2, osm_type);
set_marker(new L.LatLng(addr_lat, addr_lng));
if (feature) {
map.removeLayer(feature);
}
if (osm_type == "node") {
map.fitBounds(bounds);
map.setZoom(18);
} else {
let loc3 = new L.LatLng(lat1, lng2);
let loc4 = new L.LatLng(lat2, lng1);
feature = L.polyline( [loc1, loc4, loc2, loc3, loc1], {color: 'red'}).addTo(map);
map.fitBounds(bounds);
}
} else if (addr_lat !== undefined && addr_lng !== undefined){
let loc = new L.LatLng(addr_lat, addr_lng);
console.log(loc);
set_marker(loc);
if(zoom !== undefined){
map.setView(loc, zoom);
} else {
map.setView(loc);
}
}
export function chooseAddr (addrLat, addrLng, zoom = undefined, lat1 = undefined, lng1 = undefined, lat2 = undefined, lng2 = undefined, osmType = undefined) {
addrLat = addrLat.replace(",", ".");
addrLng = addrLng.replace(",", ".");
if (lat1 !== undefined && lng1 !== undefined && lat2 !== undefined && lng2 !== undefined && osmType !== undefined) {
const loc1 = new L.LatLng(lat1, lng1);
const loc2 = new L.LatLng(lat2, lng2);
const bounds = new L.LatLngBounds(loc1, loc2);
console.log(lat1, lng1, lat2, lng2, osmType);
setMarker(new L.LatLng(addrLat, addrLng));
if (feature) {
map.removeLayer(feature);
}
if (osmType === "node") {
map.fitBounds(bounds);
map.setZoom(16);
} else {
const loc3 = new L.LatLng(lat1, lng2);
const loc4 = new L.LatLng(lat2, lng1);
feature = L.polyline([loc1, loc4, loc2, loc3, loc1], { color: "red" }).addTo(map);
map.fitBounds(bounds);
}
} else if (addrLat !== undefined && addrLng !== undefined) {
const loc = new L.LatLng(addrLat, addrLng);
console.log(loc);
setMarker(loc);
if (zoom !== undefined) {
map.setView(loc, zoom);
} else {
map.setView(loc);
}
}
}
// started from https://derickrethans.nl/leaflet-and-nominatim.html
function addr_search(string_results_found=undefined, string_results_not_found=undefined) {
function searchError(error, checkClipboard){
if(!checkClipboard){
$('<p>', { html: string_results_not_found }).appendTo('#results');
console.error(error);
}
return false;
}
let inp = document.getElementById("addr").value;
//if translation strings are not defined, skip the nominatim step and don't log errors (no console.error)
let checkClipboard = string_results_found==undefined && string_results_not_found==undefined;
$('#results').empty();
export function addrSearch (stringResultsFound= undefined, stringResultsNotFound = undefined) {
function searchError (error, checkClipboard) {
if (!checkClipboard) {
$("#results").empty();
$("<p>", { html: stringResultsNotFound }).appendTo("#results");
console.error(error);
}
return false;
}
let inp = document.getElementById("addr").value;
// if translation strings are not defined, skip the nominatim step and don't log errors (no console.error)
const checkClipboard = stringResultsFound=== undefined && stringResultsNotFound === undefined;
$("#results").empty();
if(inp.match("\@(-?[\d\.]*)")){ //Google Maps
try {
inp = inp.split("@")[1].split(",");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.includes("#map=")) { //OpenStreetMap website
try {
inp = inp.split("#map=")[1].split("/");
chooseAddr(inp[1], inp[2], inp[0]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.match(/[0-9]+,\s[0-9]+/)) { //Bing
try {
inp = inp.split(", ");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.match(/[0-9]+;[0-9]+/)) { //DB dump
try {
inp = inp.split(";");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(!checkClipboard) {
$.getJSON('https://nominatim.openstreetmap.org/search?format=json&limit=5&q=' + inp, function(data) {
let items = [];
if (inp.match("\@(-?[\d\.]*)")) { // Google Maps
try {
inp = inp.split("@")[1].split(",");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if (inp.includes("#map=")) { // OpenStreetMap website
try {
inp = inp.split("#map=")[1].split("/");
chooseAddr(inp[1], inp[2], inp[0]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if (inp.match(/[0-9]+,\s[0-9]+/)) { // Bing
try {
inp = inp.split(", ");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if (inp.match(/[0-9]+;[0-9]+/)) { // DB dump
try {
inp = inp.split(";");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if (!checkClipboard) {
$.getJSON("https://nominatim.openstreetmap.org/search?format=json&limit=5&q=" + inp, function (data) {
const items = [];
$.each(data, function(key, val) {
items.push("<li><a href='' onclick='chooseAddr(\"" + val.lat + "\", \"" + val.lon + "\", undefined, " + val.boundingbox[0] + ", " + val.boundingbox[2] + ", " + val.boundingbox[1] + ", " + val.boundingbox[3] + ", \"" + val.osm_type + "\"); return false;'>" + val.display_name + '</a></li>');
});
$.each(data, function (key, val) {
items.push("<li><a href='' onclick='allertaJS.maps.chooseAddr(\"" + val.lat + "\", \"" + val.lon + "\", undefined, " + val.boundingbox[0] + ", " + val.boundingbox[2] + ", " + val.boundingbox[1] + ", " + val.boundingbox[3] + ", \"" + val.osm_type + "\"); return false;'>" + val.display_name + "</a></li>");
});
if (items.length != 0) {
$('<p>', { html: string_results_found+":" }).appendTo('#results');
$('<ul/>', {
'class': 'results-list',
html: items.join('')
}).appendTo('#results');
} else {
$('<p>', { html: string_results_not_found }).appendTo('#results');
}
});
} else {
return false;
}
if (items.length !== 0) {
$("#results").empty();
$("<p>", { html: stringResultsFound+ ":" }).appendTo("#results");
$("<ul/>", {
class: "results-list",
html: items.join("")
}).appendTo("#results");
} else {
$("#results").empty();
$("<p>", { html: stringResultsNotFound }).appendTo("#results");
}
});
} else {
return false;
}
}
window.load_map = load_map;
window.addr_search = addr_search;
window.chooseAddr = chooseAddr;

View File

@ -1 +1 @@
import {Howl, Howler} from 'howler';
import { Howl, Howler } from "howler";

View File

@ -1,16 +1,16 @@
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
if(process.env.config && process.env.config.sentry_enabled){
if('connection' in navigator && navigator.connection.saveData){
if (process.env.config && process.env.config.sentryEnabled) {
if ("connection" in navigator && navigator.connection.saveData) {
console.log("Skipping Sentry init because data save is enabled");
} else {
Sentry.init({
dsn: process.env.config.sentry_dsn,
dsn: process.env.config.sentryDsn,
integrations: [new Integrations.BrowserTracing()],
tracesSampleRate: 0.6,
release: "allerta-vvf-frontend@"+process.env.GIT_VERSION,
environment: process.env.config.sentry_environment
release: "allerta-vvf-frontend@" + process.env.GIT_VERSION,
environment: process.env.config.sentryEnvironment
});
}
}
}

View File

@ -1,18 +1,19 @@
const cacheVersion = process.env.BUNDLE_DATE;
const cacheName = "static-"+cacheVersion;
const expectedCaches = [cacheName, 'tables-1'];
const cacheName = "static-" + cacheVersion;
const expectedCaches = [cacheName, "tables-1"];
const urls = ['offline.php', 'manifest.webmanifest', 'resources/images/favicon.ico', 'resources/dist/marker-icon.png', 'resources/dist/layers.png', 'resources/dist/layers-2x.png', 'resources/images/android-chrome-192x192.png', 'resources/images/android-chrome-384x384.png', 'resources/images/black_helmet.png', 'resources/images/red_helmet.png', 'resources/images/wheel.png', 'resources/images/logo.png', 'resources/images/owner.png', 'resources/dist/fonts/fontawesome-webfont.woff2'];
const urls = ["offline.php", "manifest.webmanifest", "resources/images/favicon.ico", "resources/dist/marker-icon.png", "resources/dist/layers.png", "resources/dist/layers-2x.png", "resources/images/android-chrome-192x192.png", "resources/images/android-chrome-384x384.png", "resources/images/black_helmet.png", "resources/images/red_helmet.png", "resources/images/wheel.png", "resources/images/logo.png", "resources/images/owner.png", "resources/dist/fonts/fontawesome-webfont.woff2"];
function fetchHandler(event, content_type, not_found_message){
function fetchHandler (event, contentType, notFoundMessage) {
// TODO: refactoring
console.log(event);
// FROM https://googlechrome.github.io/samples/service-worker/custom-offline-page/
// We only want to call event.respondWith() if this is a navigation request
// for an HTML page.
if (event.request.mode === 'navigate') {
if (event.request.mode === "navigate") {
event.respondWith((async () => {
console.log("respond with");
try {
// First, try to use the navigation preload response if it's supported.
const preloadResponse = await event.preloadResponse;
@ -28,10 +29,10 @@ function fetchHandler(event, content_type, not_found_message){
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
console.log('Fetch failed; returning offline page instead.', error);
console.log("Fetch failed; returning offline page instead.", error);
const cache = await caches.open(cacheName);
if(event.request.headers.get('Accept').includes('text/html')){
if (event.request.headers.get("Accept").includes("text/html")) {
cacheFileName = "offline.php";
} else {
cacheFileName = event.request.url;
@ -49,57 +50,57 @@ function fetchHandler(event, content_type, not_found_message){
// were no service worker involvement.
}
self.addEventListener('fetch', function (event) {
var request = event.request;
self.addEventListener("fetch", function (event) {
const request = event.request;
// https://stackoverflow.com/a/49719964
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') return;
if (event.request.cache === "only-if-cached" && event.request.mode !== "same-origin") return;
if (request.headers.get('Accept').includes('text/html')) {
if (request.headers.get("Accept").includes("text/html")) {
fetchHandler(event, null, "offline.php");
} else if (request.destination == "script") {
fetchHandler(event, "application/javascript", "console.error('Script "+event.request.url+" not found');");
} else if (request.destination == "image") {
} else if (request.destination === "script") {
fetchHandler(event, "application/javascript", "console.error('Script " + event.request.url + " not found');");
} else if (request.destination === "image") {
fetchHandler(event, null, "resources/images/logo.png");
} else if (request.destination == "font") {
} else if (request.destination === "font") {
fetchHandler(event, null, null);
} else if (request.destination == "manifest" || request.url.includes("manifest")) {
} else if (request.destination === "manifest" || request.url.includes("manifest")) {
fetchHandler(event, null, "manifest.webmanifest");
} else {
event.respondWith(fetch(request));
}
});
self.addEventListener('install', event => {
self.addEventListener("install", (event) => {
self.skipWaiting();
event.waitUntil(
caches.open(cacheName).then(cache => {
caches.open(cacheName).then((cache) => {
cache.addAll(urls);
fetch('resources/dist/manifest.json')
.then(response => response.json())
.then(manifest => {
let scripts_required = ["main.js", "maps.js"];
scripts_required.map(script_name => {
fetch("resources/dist/manifest.json")
.then((response) => response.json())
.then((manifest) => {
const scriptsRequired = ["main.js", "maps.js"];
scriptsRequired.map((scriptName) => {
console.log(manifest);
console.log(script_name);
cache.add("resources/dist/"+manifest[script_name]);
console.log(scriptName);
cache.add("resources/dist/" + manifest[scriptName]);
});
});
})
);
})
});
self.addEventListener('activate', event => {
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then(keys => Promise.all(
keys.map(key => {
caches.keys().then((keys) => Promise.all(
keys.map((key) => {
if (!expectedCaches.includes(key)) {
console.log("Deleting cache "+key);
console.log("Deleting cache " + key);
return caches.delete(key);
}
})
)).then(() => {
console.log('Service worker now ready to handle fetches!');
console.log("Service worker now ready to handle fetches!");
})
);
});
});

View File

@ -1,39 +1,96 @@
import jsZip from 'jszip';
import jsZip from "jszip";
window.JSZip = jsZip;
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
import 'datatables.net-bs4/js/dataTables.bootstrap4.min.js';
import 'datatables.net-bs4/css/dataTables.bootstrap4.min.css';
import 'datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js';
import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css';
import 'datatables.net-buttons';
import 'datatables.net-buttons-bs4/js/buttons.bootstrap4.js';
import 'datatables.net-buttons-bs4/css/buttons.bootstrap4.css';
import 'datatables.net-buttons/js/buttons.html5.js';
import 'datatables.net-buttons/js/buttons.print.js';
import pdfFonts from "pdfmake/build/vfs_fonts";
import "datatables.net-bs4/js/dataTables.bootstrap4.min.js";
import "datatables.net-bs4/css/dataTables.bootstrap4.min.css";
import "datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js";
import "datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css";
import "datatables.net-buttons";
import "datatables.net-buttons-bs4/js/buttons.bootstrap4.js";
import "datatables.net-buttons-bs4/css/buttons.bootstrap4.css";
import "datatables.net-buttons/js/buttons.html5.js";
import "datatables.net-buttons/js/buttons.print.js";
export default async function fillTable({data, replaceLatLngWithMap=false, callback=false}){
export default async function fillTable ({ data, replaceLatLngWithMap = false, callback = false }) {
$("#table_body").empty();
$.each(data, function(row_num, item) {
let row = document.createElement("tr");
row.id = "row-"+row_num;
$.each(item, function(cell_num, i) {
if(i !== null){
if(replaceLatLngWithMap && i.match(/[+-]?\d+([.]\d+)?[;][+-]?\d+([.]\d+)?/gm)){ /* credits to @visoom https://github.com/visoom */
$.each(data, function (rowNum, item) {
const row = document.createElement("tr");
row.id = "row-" + rowNum;
$.each(item, function (cellNum, i) {
if (i !== null) {
if (replaceLatLngWithMap && i.match(/[+-]?\d+([.]\d+)?[;][+-]?\d+([.]\d+)?/gm)) { /* credits to @visoom https://github.com/visoom */
let lat = i.split(";")[0];
let lng = i.split(";")[1];
let mapDiv = document.createElement("div");
mapDiv.className = "map";
mapDiv.id = "map-"+row_num;
let mapScript = document.createElement("script");
mapScript.appendChild(document.createTextNode("load_map("+lat+", "+lng+", \"map-"+row_num+"\", false)"));
mapDiv.appendChild(mapScript);
let cell = document.createElement("td");
let mapImageID = undefined;
if(lng.includes("#")){
lng = lng.split("#")[0];
mapImageID = i.split("#")[1];
}
const mapDiv = document.createElement("div");
mapDiv.id = "map-" + rowNum;
const mapModal = document.createElement("div");
mapModal.id = "map-modal-" + rowNum;
mapModal.classList.add("modal");
mapModal.classList.add("map-modal");
mapModal.setAttribute("role", "dialog");
mapModal.setAttribute("tabindex", "-1");
mapModal.innerHTML = `<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Map</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="map-modal-${rowNum}-body">
<div id="map-container-${rowNum}" class="map"></div><br>
<p>Lat: <b id="map-${rowNum}-lat">${lat}</b></p>
<p>Lng: <b id="map-${rowNum}-lng">${lng}</b></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>`;
document.body.appendChild(mapModal);
if(mapImageID !== undefined){
const mapPreview = document.createElement("figure");
const mapPreviewImage = document.createElement("img");
console.log("Adding map image", [lat, lng, mapImageID, mapDiv.id]);
mapPreviewImage.src = "resources/images/map_cache/" + mapImageID + ".png";
mapPreview.appendChild(mapPreviewImage);
const mapPreviewCaption = document.createElement("figcaption");
const mapPreviewModalOpener = document.createElement("a");
mapPreviewCaption.style.cursor = "pointer";
mapPreviewModalOpener.id = "map-opener-" + rowNum;
mapPreviewModalOpener.classList.add("map-opener");
mapPreviewModalOpener.classList.add("pjax_disable");
mapPreviewModalOpener.innerText = "Premi qui per aprire la mappa interattiva";
mapPreviewCaption.appendChild(mapPreviewModalOpener);
mapPreview.appendChild(mapPreviewCaption);
mapDiv.appendChild(mapPreview);
} else {
const mapModalOpener = document.createElement("a");
mapModalOpener.id = "map-opener-" + rowNum;
mapModalOpener.href = "#";
mapModalOpener.classList.add("map-opener");
mapModalOpener.classList.add("pjax_disable");
mapModalOpener.innerText = "Premi qui per aprire la mappa interattiva";
mapDiv.appendChild(mapModalOpener);
}
const cell = document.createElement("td");
cell.appendChild(mapDiv);
row.appendChild(cell);
} else {
let cell = document.createElement("td");
const cell = document.createElement("td");
cell.innerHTML = i;
row.appendChild(cell);
}
@ -44,31 +101,61 @@ export default async function fillTable({data, replaceLatLngWithMap=false, callb
let loadedLanguage = {};
try {
let language = navigator.language || navigator.userLanguage;
language = language.toLowerCase().replace("_","-");
language = language.toLowerCase().replace("_", "-");
language = "it_it";
loadedLanguage = await import(`datatables.net-plugins/i18n/${language}.json`)
.then(({default: _}) => {
return _;
});
.then(({ default: _ }) => {
return _;
});
} catch (error) {
console.error("Error loading DataTables translation:");
console.log(error);
loadedLanguage = {};
}
if(! $.fn.DataTable.isDataTable( '#table' )){
var table_dt = $('#table').DataTable({
if (!$.fn.DataTable.isDataTable("#table")) {
var tableDt = $("#table").DataTable({
responsive: true,
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRowImmediate,
type: 'none',
target: ''
}
},
language: loadedLanguage,
buttons: [ 'excel', 'pdf', 'csv' ]
buttons: ["excel", "pdf", "csv"]
});
table_dt.buttons().container()
.appendTo( '#table_wrapper :nth-child(1):eq(0)' );
tableDt.buttons().container()
.appendTo("#table_wrapper :nth-child(1):eq(0)");
if(callback !== false){
callback(table_dt);
if (callback !== false) {
callback(tableDt);
}
} else {
table_dt.rows().invalidate();
tableDt.rows().invalidate();
}
window.table_dt = table_dt;
}
window.tableDt = tableDt;
}
$(function() {
document.querySelector("tbody").addEventListener('click', function(e) {
if(e.target.classList.contains("map-opener")) {
console.log(e);
let id = e.target.id.replace("map-opener-", "");
console.log(id);
$("#map-modal-"+id).modal('show');
}
});
$('body').on('shown.bs.modal', function (e) {
console.log(e);
if(e.target.classList.contains("map-modal")) {
let id = e.target.id.replace("map-modal-", "");
console.log(id);
let lat = $("#map-"+id+"-lat").text();
let lng = $("#map-"+id+"-lng").text();
console.log(lat);
console.log(lng);
allertaJS.maps.loadMap(lat, lng, "map-container-"+id, false, true);
}
});
});

View File

@ -1,32 +1,18 @@
export default async function fillTable({data, replaceLatLngWithMap=false, callback=false}){
export default async function fillTable ({ data, replaceLatLngWithMap = false, callback = false }) {
$("#table_body").empty();
$.each(data, function(row_num, item) {
let row = document.createElement("tr");
row.id = "row-"+row_num;
$.each(item, function(cell_num, i) {
if(i !== null){
if(replaceLatLngWithMap && i.match(/[+-]?\d+([.]\d+)?[;][+-]?\d+([.]\d+)?/gm)){ /* credits to @visoom https://github.com/visoom */
let lat = i.split(";")[0];
let lng = i.split(";")[1];
let mapDiv = document.createElement("div");
mapDiv.className = "map";
mapDiv.id = "map-"+row_num;
let mapScript = document.createElement("script");
mapScript.appendChild(document.createTextNode("load_map("+lat+", "+lng+", \"map-"+row_num+"\", false)"));
mapDiv.appendChild(mapScript);
let cell = document.createElement("td");
cell.appendChild(mapDiv);
row.appendChild(cell);
} else {
let cell = document.createElement("td");
cell.innerHTML = i;
row.appendChild(cell);
}
$.each(data, function (rowNum, item) {
const row = document.createElement("tr");
row.id = "row-" + rowNum;
$.each(item, function (cellNum, i) {
if (i !== null) {
const cell = document.createElement("td");
cell.innerHTML = i;
row.appendChild(cell);
}
});
document.getElementById("table_body").appendChild(row);
});
if(callback !== false){
if (callback !== false) {
callback();
}
}
}

View File

@ -1,56 +1,57 @@
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
var webpack = require('webpack');
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const WebpackAssetsManifest = require("webpack-assets-manifest");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
var webpack = require("webpack");
module.exports = {
entry: {
main: path.resolve(__dirname, './src/main.js'),
maps: path.resolve(__dirname, './src/maps.js'),
players: path.resolve(__dirname, './src/players.js'),
sw: path.resolve(__dirname, './src/sw.js'),
games: path.resolve(__dirname, './src/games.js'),
main: path.resolve(__dirname, "./src/main.js"),
maps: path.resolve(__dirname, "./src/maps.js"),
players: path.resolve(__dirname, "./src/players.js"),
sw: path.resolve(__dirname, "./src/sw.js"),
games: path.resolve(__dirname, "./src/games.js"),
},
output: {
filename: (pathData) => {
return pathData.chunk.name === 'sw' ? '../../sw.js': '[name].[contenthash].js';
return pathData.chunk.name === "sw" ? "../../sw.js": "[name].[contenthash].js";
},
path: path.resolve(__dirname, 'dist'),
publicPath: 'resources/dist/',
chunkFilename: '[name].bundle.js?h=[chunkhash]'
path: path.resolve(__dirname, "dist"),
publicPath: "resources/dist/",
chunkFilename: "[name].bundle.js?h=[chunkhash]",
library: ["allertaJS", "[name]"]
},
resolve: {
alias: {
// Force all modules to use the same jquery version.
'jquery': path.join(__dirname, 'node_modules/jquery/src/jquery')
"jquery": path.join(__dirname, "node_modules/jquery/src/jquery")
}
},
module: {
rules: [
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
use: ["style-loader", "css-loader"],
},
{
test: /\.s(a|c)ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(gif|png|jpg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
loader: "file-loader",
options: {
name: '[name].[ext]',
outputPath: './'
name: "[name].[ext]",
outputPath: "./"
}
}
]
@ -58,11 +59,11 @@ module.exports = {
{
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
use: [{
loader: 'file-loader',
loader: "file-loader",
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
publicPath: 'resources/dist/fonts'
name: "[name].[ext]",
outputPath: "fonts/",
publicPath: "resources/dist/fonts"
}
}]
},
@ -70,14 +71,14 @@ module.exports = {
test: /\.(gz|wasm|js_resource|data)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
loader: "file-loader",
options: {
name: '[name].[ext]',
outputPath: './'
name: "[name].[ext]",
outputPath: "./"
}
}
],
type: 'asset/resource'
type: "asset/resource"
}
],
},
@ -86,7 +87,7 @@ module.exports = {
new CleanWebpackPlugin(),
new CopyPlugin({
patterns: [
{ from: 'node_modules/leaflet/dist/images', to: '.', noErrorOnMissing: true }
{ from: "node_modules/leaflet/dist/images", to: ".", noErrorOnMissing: true }
],
}),
new WebpackAssetsManifest()

View File

@ -1,13 +1,13 @@
const { merge } = require('webpack-merge');
const prod = require('./webpack.prod.js');
const { merge } = require("webpack-merge");
const prod = require("./webpack.prod.js");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = smp.wrap(merge(prod, {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
analyzerMode: "static",
openAnalyzer: true,
generateStatsFile: true
})

View File

@ -1,19 +1,19 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
var webpack = require('webpack');
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
var webpack = require("webpack");
module.exports = merge(common, {
mode: 'development',
mode: "development",
devtool: false,
devServer: {
contentBase: './dist',
contentBase: "./dist",
},
plugins: [
new webpack.EnvironmentPlugin({
GIT_VERSION: null,
GIT_AUTHOR_DATE: null,
BUNDLE_DATE: Date.now(),
BUNDLE_MODE: 'development'
BUNDLE_MODE: "development"
})
]
});

View File

@ -1,18 +1,18 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const TerserPlugin = require("terser-webpack-plugin");
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
const AfterBuildPlugin = require('@fiverr/afterbuild-webpack-plugin');
const child_process = require('child_process');
const InjectPlugin = require('webpack-inject-plugin').default;
const colors = require('colors/safe');
const fs = require('fs');
const glob = require('glob');
const AfterBuildPlugin = require("@fiverr/afterbuild-webpack-plugin");
const childProcess = require("child_process");
const InjectPlugin = require("webpack-inject-plugin").default;
const colors = require("colors/safe");
const fs = require("fs");
const glob = require("glob");
function git(command) {
return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim();
return childProcess.execSync(`git ${command}`, { encoding: "utf8" }).trim();
}
var webpack = require('webpack');
var webpack = require("webpack");
if (!fs.existsSync("config.json")) {
fs.copyFileSync("config_sample.json", "config.json");
@ -27,7 +27,7 @@ const removeSourceMapUrlAfterBuild = () => {
//console.log(files);
files.forEach((key) => {
countMatchAssets += 1;
let asset = fs.readFileSync(key, 'utf8');
let asset = fs.readFileSync(key, "utf8");
let source = asset.split("//# sourceMappingURL=")[0].replace(/\n$/, "");
fs.writeFileSync(key, source);
});
@ -42,16 +42,16 @@ const removeSourceMapUrlAfterBuild = () => {
fs.unlinkSync(key);
});
});
}
};
var config_file = require('./config.json');
const sentry_enabled = config_file.sentry_enabled &&
config_file.sentry_auth_token &&
config_file.sentry_organization &&
config_file.sentry_project;
var configFile = require("./config.json");
const sentryEnabled = configFile.sentryEnabled &&
configFile.sentryAuthToken &&
configFile.sentryOrganization &&
configFile.sentryProject;
var prod_config = {
mode: 'production',
var prodConfig = {
mode: "production",
devtool: false,
module: {
rules: [
@ -59,10 +59,10 @@ var prod_config = {
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
loader: "babel-loader",
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-transform-runtime"]
}
}
}
@ -75,56 +75,61 @@ var prod_config = {
minimizer: [new TerserPlugin({
parallel: true,
extractComments: true,
sourceMap: sentry_enabled ? true : false
sourceMap: sentryEnabled ? true : false,
terserOptions: {
compress: {
drop_console: true
}
}
})]
}
};
module.exports = (env) => {
//run webpack build with '--env sentry_environment=custom-sentry-env' to replace Sentry environment
if(env.sentry_environment){
console.log(colors.green("INFO using custom sentry_environment "+env.sentry_environment));
config_file.sentry_environment = env.sentry_environment;
//run webpack build with "--env sentryEnvironment=custom-sentry-env" to replace Sentry environment
if(env.sentryEnvironment){
console.log(colors.green("INFO using custom sentryEnvironment "+env.sentryEnvironment));
configFile.sentryEnvironment = env.sentryEnvironment;
}
if(!config_file.sentry_environment){
config_file.sentry_environment = "prod";
if(!configFile.sentryEnvironment){
configFile.sentryEnvironment = "prod";
}
if(sentry_enabled){
prod_config.plugins.push(
if(sentryEnabled){
prodConfig.plugins.push(
new webpack.SourceMapDevToolPlugin({
filename: '[file].map'
filename: "[file].map"
}),
new SentryWebpackPlugin({
authToken: config_file.sentry_auth_token,
org: config_file.sentry_organization,
project: config_file.sentry_project,
urlPrefix: '~/dist',
include: './dist',
authToken: configFile.sentryAuthToken,
org: configFile.sentryOrganization,
project: configFile.sentryProject,
urlPrefix: "~/dist",
include: "./dist",
setCommits: {
auto: true
},
release: "allerta-vvf-frontend@"+git('describe --always')
release: "allerta-vvf-frontend@"+git("describe --always")
}),
new AfterBuildPlugin(removeSourceMapUrlAfterBuild),
new InjectPlugin(function() {
return "import './src/sentry.js';";
},{ entryName: 'main' })
},{ entryName: "main" })
);
console.log(colors.green("INFO Sentry Webpack plugins enabled"));
}
prod_config.plugins.push(
prodConfig.plugins.push(
new webpack.EnvironmentPlugin({
GIT_VERSION: git('describe --always'),
GIT_AUTHOR_DATE: git('log -1 --format=%aI'),
GIT_VERSION: git("describe --always"),
GIT_AUTHOR_DATE: git("log -1 --format=%aI"),
BUNDLE_DATE: Date.now(),
BUNDLE_MODE: 'production',
config: config_file
BUNDLE_MODE: "production",
config: configFile
})
);
return merge(common, prod_config);
}
return merge(common, prodConfig);
};

View File

@ -1,3 +1,4 @@
{% apply minimize %}
<!DOCTYPE html>
<html lang="it">
<head>
@ -48,45 +49,6 @@
{% endif %}
<script src="{{ urlsoftware }}/resources/dist/{{ resource('main.js') }}"></script>
<script>$.fn.loading.defaults.message = "{{ 'Loading...'|t }}";</script>
{% if enable_technical_support and technical_support_open %}
<!-- Smartsupp Live Chat script -->
<script type='text/javascript'>
var _smartsupp = _smartsupp || {};
_smartsupp.key = '{{ technical_support_key }}';
_smartsupp.ratingEnabled = true; // default value : false
_smartsupp.ratingComment = true; // default value : false
window.smartsupp || (function (d) {
var s, c, o = smartsupp = function () {
o._.push(arguments)
};
o._ = [];
s = d.getElementsByTagName('script')[0];
c = d.createElement('script');
c.type = 'text/javascript';
c.charset = 'utf-8';
c.async = true;
c.src = 'https://www.smartsuppchat.com/loader.js?';
s.parentNode.insertBefore(c, s);
})(document);
</script>
<script>
// basic info
smartsupp('email', '');
smartsupp('name', '{{ user.name }}');
smartsupp('recording:disable', false);
// extra info
smartsupp('variables', {
name: {
label: 'name user ',
value: '{{ user.name }}'
},
Admin: {
label: 'Admin',
value: '{{ user.full_viewer }}'
}
});
</script>
{% endif %}
{% endblock %}
{% if enable_debug_bar %}{{ debug_bar_head|raw }}{% endif %}
</head>
@ -100,11 +62,9 @@
<a href="{{ urlsoftware }}trainings.php">{{ 'Trainings'|t }}</a>
<a href="{{ urlsoftware }}log.php">{{ 'Logs'|t }}</a>
<a {# href="{{ urlsoftware }}graphics.php" #}>{{ 'Graphics'|t }}</a>
{% if enable_technical_support %}<a href="javascript:void(0);"
onclick="chat()">{{ 'Technical Support' }}</a>{% endif %}
<a style="float: right;" id="logout">{{ 'Hi, %s.'|t|format(user.name) }} <b
onclick="location.href='{{ urlsoftware }}logout.php';">{{ 'Logout'|t }}</b></a>
<a href="javascript:void(0);" class="icon" onclick="menu()"></a>
<a class="pjax_disable icon" id="menuButton"></a>
</div>
<!-- /Menu -->
{% endblock %}
@ -115,6 +75,11 @@
<!-- Content -->
<div id="content">
{% block pjax_content %}
{% if message %}
<div class="alert alert-info m-3" role="alert">
{{ message|raw }}
</div>
{% endif %}
{% if pjax_requested %}<title>{{ title }} - ALLERTA sistema gestionale {{ owner }}</title>{% endif %}
{% block content %}{% endblock %}
{% endblock %}
@ -132,4 +97,5 @@
{% endblock %}
{% endif %}
</body>
</html>
</html>
{% endapply %}

View File

@ -1,126 +1,135 @@
<!DOCTYPE html>
<html>
<head>
<link href="favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
<script src="{{ urlsoftware }}/resources/dist/{{ resource('main.js') }}"></script>
{% if enable_debug_bar %}{{ debug_bar_head|raw }}{% endif %}
</head>
<body>
{% extends "base.html" %}
{% block menu %}
{% endblock %}
{% block content %}
{% if service.modalità == "edit" or service.modalità == "add" %}
<form method="post">
<div class="container">
<label><b>{{ 'Service day'|t }}</b></label>
<div class="input-group">
<input aria-label="Date picker" placeholder="DD/MM/YYY" autocomplete="off" name="date" data-provide="datepicker"
<div class="form-group">
<label for="date-picker">{{ 'Service day'|t }}</label>
<input id="date-picker" aria-label="Date picker" placeholder="DD/MM/YYY" autocomplete="off" name="date" data-provide="datepicker"
value="{{ values.date }}" type="text" class="form-control">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<div class="form-group">
<label for="progressivo">{{ 'code'|t|capitalize }}</label>
<input id="progressivo" class="form-control" type="text" name="code" placeholder="1234/5" required value="{{ values.code }}">
</div>
<div class="form-group">
<label for="timePicker1">{{ 'Start time'|t }}</label>
<input id="timePicker1" class="form-control" type="time" name="beginning" required value="{{ values.beginning }}">
</div>
<div class="form-group">
<label for="timePicker2">{{ 'End time'|t }}</label>
<input id="timePicker2" class="form-control" type="time" name="end" required value="{{ values.end }}">
</div>
<div class="form-group">
<label>{{ 'Chief'|t }}</label>
<br>
{% for user in service.crew %}
{% if user.chief == 1 and not user.hidden %}
<div class="form-check">
<input aria-label="{{ username(user.id) }}" id="chief-{{ user.id }}" class="form-check-input chief chief-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='chief[]'
value='{{ user.id }}'>
<label class="form-check-label" for="chief-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
<br>
<br>
<label><b>{{ 'code'|t }}</b></label>
<input id="progressivo" type="text" name="code" placeholder="1234/5" required value="{{ values.code }}">
<br>
<br>
<label for="timePicker1"><b>{{ 'Start time'|t }}</b></label>
<input id="timePicker1" type="time" name="beginning" required value="{{ values.beginning }}">
<br>
<br>
<label for="timePicker2"><b>{{ 'End time'|t }}</b></label>
<input id="timePicker2" type="time" name="end" required value="{{ values.end }}">
<br>
<br>
<label><b>{{ 'Chief'|t }}</b></label>
<br>
{% for user in service.crew %}
<div {{ user.name == "test" ? "style='display: none'" : "" }} class="form-check">
<input aria-label="{{ username(user.id) }}" class="form-check-input chief chief-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='chief[]'
value='{{ user.id }}'>
<label class="form-check-label" for="chief-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endfor %}
<script>
$('.chief').on('change', function () {
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
});
</script>
<br>
<label><b>{{ 'Drivers'|t }}</b></label>
<br>
{% for user in service.crew %}
{% if user.driver == 1 %}
<div {{ user.name == "test" ? "style='display: none'" : "" }} class="form-check">
<input aria-label="{{ username(user.id) }}" class="form-check-input drivers drivers-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='drivers[]'
value='{{ user.id }}'>
<label class="form-check-label" for="drivers-{{ user.id }}">
{{ username(user.id) }}
</label>
<div class="form-group">
<label>{{ 'Drivers'|t }}</label>
<br>
{% for user in service.crew %}
{% if user.driver == 1 and not user.hidden %}
<div class="form-check">
<input aria-label="{{ username(user.id) }}"id="drivers-{{ user.id }}" class="form-check-input drivers drivers-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='drivers[]'
value='{{ user.id }}'>
<label class="form-check-label" for="drivers-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
<br>
<label><b>{{ 'Crew'|t }}</b></label>
<br>
{% for user in service.crew %}
<div {{ user.name == "test" ? "style='display: none'" : "" }} class="form-check">
<input aria-label="{{ username(user.id) }}" class="form-check-input crew crew-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='crew[]'
value='{{ user.id }}'>
<label class="form-check-label" for="crew-{{ user.id }}">
{{ username(user.id) }}
</label>
<div class="form-group">
<label>{{ 'Crew'|t }}</label>
<br>
{% for user in service.crew %}
{% if not user.hidden %}
<div class="form-check">
<input aria-label="{{ username(user.id) }}" id="crew-{{ user.id }}" class="form-check-input crew crew-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='crew[]'
value='{{ user.id }}'>
<label class="form-check-label" for="crew-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
<br>
{% if option('use_location_picker') %}
<label><b>{{ 'Service place'|t }}</b></label>
<label>{{ 'Service place'|t }}</label>
<div id="map"></div>
<div id="search">
<input type="text" name="addr" value="" id="addr" size="10" />
<button type="button" onclick="addr_search('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary">{{ 'Search'|t }}</button>
<div class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
<script src="{{ urlsoftware }}/resources/dist/{{ resource('maps.js') }}" onload="load_map();"></script>
<script src="{{ urlsoftware }}/resources/dist/{{ resource('maps.js') }}" onload="allertaJS.maps.loadMap();"></script>
{% else %}
<label><b>{{ 'Service place'|t }}</b></label>
<input type="text" name="place" required value="{{ values.place }}">
<div class="form-check">
<label>{{ 'Service place'|t }}</label>
<input type="text" name="place" class="form-control" required value="{{ values.place }}">
</div>
{% endif %}
<div class="form-check">
<label for="notes">{{ 'Others notes (ex. others infos)'|t }}</label><br>
<textarea class="form-control" id="notes" name='notes'></textarea>
</div>
<br>
<br>
<label><b>{{ 'Others notes (ex. others infos)'|t }}</b></label><br>
<textarea name='notes' id='notes'></textarea>
<br>
<br>
<label><b>{{ 'Service type'|t }}</b></label>
<br>
<select name='type' class="types">
{% for type in service.types %}
<option value='{{ type.name }}'>{{ type.name }}</option>
{% endfor %}
{% if service.types is empty %}
<option id="empty_option" value=''></option>
{% endif %}
<option value='add_new'>{{ 'Add type...'|t }}</option>
</select>
<div class="form-check">
<label>{{ 'Service type'|t }}</label>
<br>
<select id="types" class="form-control" name='type' class="types">
{% for type in service.types %}
<option value='{{ type.name }}'>{{ type.name }}</option>
{% endfor %}
{% if service.types is empty %}
<option id="empty_option" value=''></option>
{% endif %}
<option value='add_new'>{{ 'Add type...'|t }}</option>
</select>
</div>
<br>
<input id="modalità" type="hidden" value="{{ service.modalità }}" name="mod"></input>
<input id="token" type="hidden" value="{{ service.token }}" name="token"></input>
<input id="id" type="hidden" value="{{ service.id }}" name="id"></input>
<button type="submit">{{ 'Submit'|t }}</button>
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
</div>
</form>
<script>
$( ".types" ).change(function() {
$( "#types" ).change(function() {
$('#empty_option').remove();
var type = "";
$( ".types option:selected" ).each(function() {
$( "#types option:selected" ).each(function() {
type = $( this ).val();
});
console.log(type);
@ -134,7 +143,7 @@
type: new_type
},
success: function (data) {
$('option:last-of-type').before($('<option>').val(new_type).text(new_type));
$('option:last-of-type').before($('<option>').val(new_type).text(new_type));
$('option[value='+new_type+']').prop('selected', 'selected').change();
toastr.success(`{{ "Type '%s' added successfully."|t|format('${new_type}') }}`);
}
@ -151,12 +160,12 @@
$.each('{{ values.crew }}'.split(','), function (index, value) {
$('.crew-' + value).prop('checked', true);
});
$(".tipi").val('{{ values.type }}');
$("#types").val('{{ values.type }}');
$('#notes').val('{{ values.notes }}');
{% endif %}
$('form').submit(function () {
var type = "";
$( ".types option:selected" ).each(function() {
$( "#types option:selected" ).each(function() {
type = $( this ).val();
});
if(type == "add_new" || type == ""){
@ -181,7 +190,6 @@
<input id="modalità" type="hidden" value="delete" name="mod"></input>
<input id="token" type="hidden" value="{{ service.token }}" name="token"></input>
<input id="id" type="hidden" value="{{ service.id }}" name="id"></input>
<input id="increment" type="hidden" value="{{ increment }}" name="increment"></input>
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
</form>
<script>
@ -191,6 +199,8 @@
</script>
</div>
{% endif %}
{% if enable_debug_bar %}{{ debug_bar|raw }}{% endif %}
</body>
</html>
{% block footer %}
{% endblock %}
{% endblock %}

View File

@ -1,92 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<link href="favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
<script src="{{ urlsoftware }}/resources/dist/{{ resource('main.js') }}"></script>
{% if enable_debug_bar %}{{ debug_bar_head|raw }}{% endif %}
</head>
<body>
{% extends "base.html" %}
{% block menu %}
{% endblock %}
{% block content %}
{% if training.modalità == "edit" or training.modalità == "add" %}
<form method="post">
<div class="container">
<label><b>{{ 'Training day'|t }}</b></label>
<div class="input-group">
<input aria-label="Date picker" placeholder="DD/MM/YYY" autocomplete="off" name="date" data-provide="datepicker"
<div class="form-group">
<label for="date-picker">{{ 'Training day'|t }}</label>
<input id="date-picker" aria-label="Date picker" placeholder="DD/MM/YYY" autocomplete="off" name="date" data-provide="datepicker"
value="{{ values.date }}" type="text" class="form-control">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<div class="form-group">
<label for="name">{{ 'Name'|t }}</label>
<input id="name" class="form-control" type="text" name="name" placeholder="1° training" required value="{{ values.name }}">
</div>
<div class="form-group">
<label for="timePicker1">{{ 'Start time'|t }}</label>
<input id="timePicker1" class="form-control" type="time" name="start_time" required value="{{ values.beginning }}">
</div>
<div class="form-group">
<label for="timePicker2">{{ 'End time'|t }}</label>
<input id="timePicker2" class="form-control" type="time" name="end_time" required value="{{ values.end }}">
</div>
<div class="form-group">
<label>{{ 'Chief'|t }}</label>
<br>
{% for user in training.crew %}
{% if not user.hidden %}
<div class="form-check">
<input aria-label="{{ username(user.id) }}" id="chief-{{ user.id }}" class="form-check-input chief chief-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='chief[]'
value='{{ user.id }}'>
<label class="form-check-label" for="chief-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
<br>
<br>
<label><b>{{ 'Name'|t }}</b></label>
<input id="name" type="text" name="name" placeholder="1° training" required value="{{ values.name }}">
<br>
<br>
<label for="timePicker1"><b>{{ 'Start time'|t }}</b></label>
<input id="timePicker1" type="time" name="start_time" required value="{{ values.beginning }}">
<br>
<br>
<label for="timePicker2"><b>{{ 'End time'|t }}</b></label>
<input id="timePicker2" type="time" name="end_time" required value="{{ values.end }}">
<br>
<br>
<label><b>{{ 'Chief'|t }}</b></label>
<br>
{% for user in training.crew %}
<div {{ user.name == "test" ? "style='display: none'" : "" }} class="form-check">
<input aria-label="{{ username(user.id) }}" class="form-check-input chief chief-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='chief[]'
value='{{ user.id }}'>
<label class="form-check-label" for="chief-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endfor %}
<script>
$('.chief').on('change', function () {
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
});
</script>
<br>
<label><b>{{ 'Crew'|t }}</b></label>
<br>
{% for user in training.crew %}
<div {{ user.name == "test" ? "style='display: none'" : "" }} class="form-check">
<input aria-label="{{ username(user.id) }}" class="form-check-input crew crew-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='crew[]'
value='{{ user.id }}'>
<label class="form-check-label" for="crew-{{ user.id }}">
{{ username(user.id) }}
</label>
<div class="form-group">
<label>{{ 'Crew'|t }}</label>
<br>
{% for user in training.crew %}
{% if not user.hidden %}
<div class="form-check">
<input aria-label="{{ username(user.id) }}" id="crew-{{ user.id }}" class="form-check-input crew crew-{{ user.id }}"
style="transform: scale(1.4); -webkit-transform: scale(1.4);" type="checkbox" name='crew[]'
value='{{ user.id }}'>
<label class="form-check-label" for="crew-{{ user.id }}">
{{ username(user.id) }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
<br>
{% if option('use_location_picker') %}
<label><b>{{ 'Training place'|t }}</b></label>
<label>{{ 'Training place'|t }}</label>
<div id="map"></div>
<div id="search">
<input type="text" name="addr" value="" id="addr" size="10" />
<button type="button" onclick="addr_search('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary">{{ 'Search'|t }}</button>
<div class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
<script src="{{ urlsoftware }}/resources/dist/{{ resource('maps.js') }}" onload="load_map();"></script>
<script src="{{ urlsoftware }}/resources/dist/{{ resource('maps.js') }}" onload="allertaJS.maps.loadMap();"></script>
{% else %}
<label><b>{{ 'Training place'|t }}</b></label>
<input type="text" name="place" required value="{{ values.place }}">
<div class="form-check">
<label for="place">{{ 'Training place'|t }}</label>
<input id="place" type="text" class="form-control" name="place" required value="{{ values.place }}">
</div>
{% endif %}
<br>
<br>
<label><b>{{ 'Others notes (ex. others infos)'|t }}</b></label><br>
<textarea name='notes'></textarea>
<br>
<div class="form-check">
<label for="notes">{{ 'Others notes (ex. others infos)'|t }}</label><br>
<textarea class="form-control" id="notes" name='notes'></textarea>
</div>
<br>
<input id="modalità" type="hidden" value="{{ training.modalità }}" name="mod"></input>
<input id="id" type="hidden" value="{{ training.id }}" name="id"></input>
<input id="token" type="hidden" value="{{ training.token }}" name="token"></input>
<button type="submit">{{ 'Submit'|t }}</button>
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
</div>
</form>
<script>
@ -108,7 +114,6 @@
<input id="modalità" type="hidden" value="delete" name="mod"></input>
<input id="token" type="hidden" value="{{ training.token }}" name="token"></input>
<input id="id" type="hidden" value="{{ training.id }}" name="id"></input>
<input id="increment" type="hidden" value="{{ increment }}" name="increment"></input>
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
</form>
<script>
@ -118,6 +123,8 @@
</script>
</div>
{% endif %}
{% if enable_debug_bar %}{{ debug_bar|raw }}{% endif %}
</body>
</html>
{% block footer %}
{% endblock %}
{% endblock %}

View File

@ -1,68 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<link href="favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
<script src="{{ urlsoftware }}/resources/dist/{{ resource('main.js') }}"></script>
{% if enable_debug_bar %}{{ debug_bar_head|raw }}{% endif %}
</head>
<body>
{% extends "base.html" %}
{% block menu %}
{% endblock %}
{% block content %}
{% if modalità == "edit" or modalità == "add" %}
<form method="post">
<div class="container">
<label><b>{{ 'E-mail'|t }}</b></label>
<input id="mail" type="text" name="mail" placeholder="{{ 'user@provider-email-domain.com'|t }}" required>
<br>
<br>
<label><b>{{ 'Name'|t }}</b></label>
<input id="name" type="text" name="name" placeholder="{{ 'Name Surname'|t }}" required>
<br>
<br>
<label><b>{{ 'Username'|t }}</b></label>
<input id="username" type="text" name="username" placeholder="{{ 'name.surname'|t }}" required>
<br>
<br>
<label><b>{{ 'Password'|t }}</b></label>
<input id="password" type="text" name="password" required>
<br>
<br>
<label><b>{{ 'Phone number'|t }}</b></label>
<input id="phone_number" type="tel" name="phone_number" required>
<br>
<br>
<label><b>{{ 'Birthday'|t }}</b></label>
<div class="input-group">
<input placeholder="DD/MM/YYY" autocomplete="off" name="birthday" data-provide="datepicker"
value="{{ values.date }}" type="text" class="form-control">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<div class="form-group">
<label for="mail">{{ 'E-mail'|t }}</label>
<input id="mail" class="form-control" type="text" name="mail" placeholder="{{ 'user@provider-email-domain.com'|t }}" required>
</div>
<div class="form-group">
<label for="name">{{ 'Name'|t }}</label>
<input id="name" class="form-control" type="text" name="name" placeholder="{{ 'Name Surname'|t }}" required>
</div>
<div class="form-group">
<label for="username">{{ 'Username'|t }}</label>
<input id="username" class="form-control" type="text" name="username" placeholder="{{ 'name.surname'|t }}" required>
</div>
<div class="form-group">
<label>{{ 'Password'|t }}</label>
<input id="password" class="form-control" type="text" name="password" required>
</div>
<div class="form-group">
<label for="phone_number">{{ 'Phone number'|t }}</label>
<input id="phone_number" class="form-control" type="tel" name="phone_number" required>
</div>
<div class="form-group">
<label for="date-picker">{{ 'Birthday'|t }}</label>
<input id="date-picker" placeholder="DD/MM/YYY" autocomplete="off" name="birthday" data-provide="datepicker"
value="{{ values.date }}" type="text" class="form-control">
</div>
<br>
<br>
<style>
.toggle.workaround {
border: 1px solid black;
}
</style>
<label><b>{{ 'Chief'|t }}</b></label><br>
<input type="checkbox" name="chief" data-toggle="toggle" data-style="workaround">
<br>
<br>
<label><b>{{ 'Driver'|t }}</b></label><br>
<input type="checkbox" name="driver" data-toggle="toggle" data-style="workaround">
<br>
<br>
<label><b>{{ 'Visible'|t }}</b></label><br>
<input type="checkbox" name="visible" checked data-toggle="toggle" data-style="workaround">
<br>
<br>
<label><b>{{ 'Enabled'|t }}</b></label><br>
<input type="checkbox" name="enabled" checked data-toggle="toggle" data-style="workaround">
<br>
<div class="form-group">
<label for="chief">{{ 'Chief'|t }}</label><br>
<input id="chief" class="form-control" type="checkbox" name="chief" data-toggle="toggle" data-style="workaround">
</div>
<div class="form-group">
<label for="driver">{{ 'Driver'|t }}</label><br>
<input id="driver" class="form-control" type="checkbox" name="driver" data-toggle="toggle" data-style="workaround">
</div>
<div class="form-group">
<label for="visible">{{ 'Visible'|t }}</label><br>
<input id="visible" class="form-control" type="checkbox" name="visible" checked data-toggle="toggle" data-style="workaround">
</div>
<div class="form-group">
<label for="enabled">{{ 'Enabled'|t }}</label><br>
<input id="enabled" class="form-control" type="checkbox" name="enabled" checked data-toggle="toggle" data-style="workaround">
</div>
<br>
<input id="modalità" type="hidden" value="{{ modalità }}" name="mod"></input>
<input id="token" type="hidden" value="{{ token }}" name="token"></input>
<button type="submit">{{ 'Submit'|t }}</button>
<button type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
</div>
</form>
{% endif %}
@ -82,6 +76,8 @@
</script>
</div>
{% endif %}
{% if enable_debug_bar %}{{ debug_bar|raw }}{% endif %}
</body>
</html>
{% block footer %}
{% endblock %}
{% endblock %}

View File

@ -67,8 +67,7 @@
},
success: function (data) {
toastr.success(`{{ 'Thanks, %s, you have given %s in case of alert.'|t|format(user.name, '${generate_alert_string(id)}') }}`);
clearInterval(window.loadTable_interval); //stop reloading
loadTable({table_page: "list", use_custom_table_engine: "default"});
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
}
});
}
@ -84,8 +83,7 @@
},
success: function (data) {
toastr.success(`{{ 'Thanks, %s, you have removed %s in case of alert.'|t|format(user.name, '${generate_alert_string(id)}') }}`);
clearInterval(window.loadTable_interval); //stop reloading
loadTable({table_page: "list", use_custom_table_engine: "default"});
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
}
});
}
@ -114,7 +112,7 @@
</tbody>
</table>
<script>
loadTable({table_page: "list", use_custom_table_engine: "default"});
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
</script>
</div>

View File

@ -19,8 +19,8 @@
</tbody>
</table>
<script>
loadTable({table_page: "log", set_interval: false, callback: function(table_dt) {
table_dt
allertaJS.main.loadTable({tablePage: "log", setInterval: false, callback: function(tableDt) {
tableDt
.column( '3:visible' )
.order( 'desc' )
.draw();

View File

@ -26,7 +26,7 @@
</tbody>
</table>
<script>
loadTable("list", true, 20000, true);
allertaJS.main.loadTable("list", true, 20000, true);
</script>
</div>
<br>

View File

@ -36,7 +36,7 @@
</tbody>
</table>
<script>
loadTable({table_page: "services", interval: 120000});
allertaJS.main.loadTable({tablePage: "services", interval: 120000});
</script>
</div>
<br>

View File

@ -34,7 +34,7 @@
</tbody>
</table>
<script>
loadTable({table_page: "trainings", interval: 120000});
allertaJS.main.loadTable({tablePage: "trainings", interval: 120000});
</script>
</div>
<br>

View File

@ -33,6 +33,8 @@ return [
"Type" => "Type",
"The code has been detected as incorrect, do you want to add the service anyway?" => "The code has been detected as incorrect, do you want to add the service anyway?",
"Are you sure you want to delete the service?" => "Are you sure you want to delete the service?",
"Are you sure you want to delete the training?" => "Are you sure you want to delete the training?",
"Are you sure you want to delete the user?" => "Are you sure you want to delete the user?",
"The action cannot be canceled. Are you sure you want to continue?" => "The action cannot be canceled. Are you sure you want to continue?",
"Submit" => "Submit",
"Phone number" => "Phone number",
@ -42,7 +44,6 @@ return [
"Write" => "Write",
"Other" => "Other",
"Others infos" => "Others infos",
"Add user" => "Add user",
"Action" => "Action",
"Interested" => "Interested",
"Made by" => "Made by",
@ -74,6 +75,13 @@ return [
"Thanks, %s, you have removed %s in case of alert." => "Thanks, %s, you have removed %s in case of alert.",
"Add service" => "Add service",
"Add training" => "Add training",
"Add user" => "Add user",
"Edit service" => "Edit service",
"Edit training" => "Edit training",
"Edit user" => "Edit user",
"Delete service" => "Delete service",
"Delete training" => "Delete training",
"Delete user" => "Delete user",
"You are offline" => "You are offline",
"Last update" => "Last update",
"Search" => "Search",

View File

@ -33,6 +33,8 @@ return [
"Type" => "Tipo",
"The code has been detected as incorrect, do you want to add the service anyway?" => "Il codice è stato rilevato come non corretto, vuoi inserire l'intervento comunque?",
"Are you sure you want to delete the service?" => "Sei sicuro di voler rimuovere l'intervento?",
"Are you sure you want to delete the training?" => "Sei sicuro di voler rimuovere l'esercitazione?",
"Are you sure you want to delete the user?" => "Sei sicuro di voler rimuovere l'utente?",
"The action cannot be canceled. Are you sure you want to continue?" => "L'azione non potrà essere annullata. Sei sicuro di voler continuare?",
"Submit" => "Invia",
"Phone number" => "Numero di telefono",
@ -42,7 +44,6 @@ return [
"Write" => "Scrivi",
"Other" => "Altro",
"Others infos" => "Altri dettagli",
"Add user" => "Aggiungi utente",
"Action" => "Azione",
"Interested" => "Interessato",
"Made by" => "Fatto da",
@ -74,6 +75,13 @@ return [
"Thanks, %s, you have removed %s in case of alert." => "Grazie, %s, hai rimosso %s in caso di allerta.",
"Add service" => "Aggiungi intervento",
"Add training" => "Aggiungi esercitazione",
"Add user" => "Aggiungi utente",
"Edit service" => "Modifica intervento",
"Edit training" => "Modifica esercitazione",
"Edit user" => "Modifica utente",
"Delete service" => "Rimuovi intervento",
"Delete training" => "Rimuovi esercitazione",
"Delete user" => "Rimuovi utente",
"You are offline" => "Sei offline",
"Last update" => "Ultimo aggiornamento",
"Search" => "Cerca",

View File

@ -22,18 +22,20 @@ try {
} catch (Exception $e) {
$loader = new \Twig\Loader\FilesystemLoader('../templates');
}
$filter = new \Twig\TwigFilter(
't', function ($string) {
global $translations;
return $translations->translate($string);
}
);
$twig = new \Twig\Environment(
$loader, [
//'cache' => 'compilation'
]
);
$twig->addFilter($filter);
$filter_translate = new \Twig\TwigFilter(
't', function ($string) {
global $translations;
return $translations->translate($string);
}
);
$twig->addFilter($filter_translate);
$function_option = new \Twig\TwigFunction(
'option', function ($option) {
global $database;
@ -41,6 +43,7 @@ $function_option = new \Twig\TwigFunction(
}
);
$twig->addFunction($function_option);
$function_username = new \Twig\TwigFunction(
'username', function ($id) {
global $user;
@ -48,6 +51,7 @@ $function_username = new \Twig\TwigFunction(
}
);
$twig->addFunction($function_username);
$function_resource = new \Twig\TwigFunction(
'resource', function ($file) {
global $webpack_manifest;
@ -55,6 +59,20 @@ $function_resource = new \Twig\TwigFunction(
}
);
$twig->addFunction($function_resource);
$filter_minimize = new \Twig\TwigFilter(
'minimize', function ($content) {
if(isset($_REQUEST["skip_minify"])){
return $content;
} else {
return Minifier\TinyMinify::html($content, [
'collapse_whitespace' => true,
'disable_comments' => true,
]);
}
}, ['is_safe' => ['html']]
);
$twig->addFilter($filter_minimize);
p_stop();
$template = null;
@ -74,9 +92,6 @@ function loadtemplate($templatename, $data, $requirelogin=true)
$data['owner'] = $database->get_option("owner");
$data['urlsoftware'] = $database->get_option("web_url");
$data['user'] = $user->info();
$data['enable_technical_support'] = $database->get_option("enable_technical_support");
$data['technical_support_key'] = $database->get_option("technical_support_key");
$data['technical_support_open'] = isset($_COOKIE["chat"]);
$data['show_menu'] = !isset($_REQUEST["hide_menu"]);
$data['show_footer'] = !isset($_REQUEST["hide_footer"]);
if($database->get_option("use_custom_error_sound")) {
@ -89,6 +104,25 @@ function loadtemplate($templatename, $data, $requirelogin=true)
} else {
$data['error_image'] = "error.gif";
}
//TODO: replace this
if($messages = $database->get_option("messages")){
try {
$messages = json_decode($messages, true);
if(isset($messages[$templatename])){
$data["message"] = $messages[$templatename];
} else if(isset($messages["loggedIn"]) && $user->auth->isLoggedIn()) {
$data["message"] = $messages["loggedIn"];
} else if(isset($messages["global"])) {
$data["message"] = $messages["global"];
} else {
$data["message"] = false;
}
} catch (\Throwable $th) {
$data["message"] = false;
}
} else {
$data["message"] = false;
}
\header_remove('X-Frame-Options');
$template = $twig->load($templatename);
if(isset($_SERVER["HTTP_X_PJAX"]) || isset($_GET["X_PJAX"]) || isset($_GET["_PJAX"])) {