|
@ -1,6 +1,12 @@
|
|||
<?php
|
||||
require_once 'utils.php';
|
||||
require_once 'cronRouter.php';
|
||||
|
||||
function apiRouter (FastRoute\RouteCollector $r) {
|
||||
$r->addGroup('/cron', function (FastRoute\RouteCollector $r) {
|
||||
cronRouter($r);
|
||||
});
|
||||
|
||||
$r->addRoute(
|
||||
'GET',
|
||||
'/healthcheck',
|
||||
|
@ -48,7 +54,11 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
global $db, $users;
|
||||
requireLogin() || accessDenied();
|
||||
$users->online_time_update();
|
||||
$response = $db->select("SELECT * FROM `".DB_PREFIX."_profiles` ORDER BY available DESC, chief DESC, services ASC, availability_minutes ASC, name ASC");
|
||||
if($users->hasRole(Role::FULL_VIEWER)) {
|
||||
$response = $db->select("SELECT * FROM `".DB_PREFIX."_profiles` ORDER BY available DESC, chief DESC, services ASC, availability_minutes ASC, name ASC");
|
||||
} else {
|
||||
$response = $db->select("SELECT `id`, `chief`, `online_time`, `available`, `name` FROM `".DB_PREFIX."_profiles` ORDER BY available DESC, chief DESC, services ASC, availability_minutes ASC, name ASC");
|
||||
}
|
||||
apiResponse(
|
||||
!is_null($response) ? $response : []
|
||||
);
|
||||
|
@ -126,6 +136,9 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
function ($vars) {
|
||||
global $users;
|
||||
requireLogin() || accessDenied();
|
||||
if(!$users->hasRole(Role::FULL_VIEWER) && $_POST["id"] !== $users->auth->getUserId()){
|
||||
exit;
|
||||
}
|
||||
apiResponse(["userId" => $users->add_user($_POST["email"], $_POST["name"], $_POST["username"], $_POST["password"], $_POST["phone_number"], $_POST["birthday"], $_POST["chief"], $_POST["driver"], $_POST["hidden"], $_POST["disabled"], "unknown")]);
|
||||
}
|
||||
);
|
||||
|
@ -135,6 +148,9 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
function ($vars) {
|
||||
global $users;
|
||||
requireLogin() || accessDenied();
|
||||
if(!$users->hasRole(Role::FULL_VIEWER) && $_POST["id"] !== $users->auth->getUserId()){
|
||||
exit;
|
||||
}
|
||||
apiResponse($users->get_user($vars["userId"]));
|
||||
}
|
||||
);
|
||||
|
@ -144,6 +160,9 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
function ($vars) {
|
||||
global $users;
|
||||
requireLogin() || accessDenied();
|
||||
if(!$users->hasRole(Role::FULL_VIEWER) && $_POST["id"] !== $users->auth->getUserId()){
|
||||
exit;
|
||||
}
|
||||
$users->remove_user($vars["userId"], "unknown");
|
||||
apiResponse(["status" => "success"]);
|
||||
}
|
||||
|
@ -171,12 +190,15 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
global $users, $db;
|
||||
requireLogin() || accessDenied();
|
||||
$users->online_time_update();
|
||||
logger("Disponibilità cambiata in ".($_POST["available"] ? '"disponibile"' : '"non disponibile"'), is_numeric($_POST["id"]) ? $_POST["id"] : $users->auth->getUserId());
|
||||
if(!$users->hasRole(Role::FULL_VIEWER) && $_POST["id"] !== $users->auth->getUserId()){
|
||||
exit;
|
||||
}
|
||||
logger("Disponibilità cambiata in ".($_POST["available"] ? '"disponibile"' : '"non disponibile"'), is_numeric($_POST["id"]) ? $_POST["id"] : $users->auth->getUserId(), $users->auth->getUserId());
|
||||
apiResponse([
|
||||
"response" => $db->update(
|
||||
DB_PREFIX.'_profiles',
|
||||
[
|
||||
'available' => $_POST['available'],
|
||||
'available' => $_POST['available'], 'availability_last_change' => 'manual'
|
||||
],
|
||||
[
|
||||
'id' => is_numeric($_POST["id"]) ? $_POST["id"] : $users->auth->getUserId()
|
||||
|
@ -186,6 +208,30 @@ function apiRouter (FastRoute\RouteCollector $r) {
|
|||
}
|
||||
);
|
||||
|
||||
$r->addRoute(
|
||||
['GET'],
|
||||
'/schedules',
|
||||
function ($vars) {
|
||||
global $users, $schedules;
|
||||
requireLogin() || accessDenied();
|
||||
$users->online_time_update();
|
||||
apiResponse($schedules->get());
|
||||
}
|
||||
);
|
||||
$r->addRoute(
|
||||
['POST'],
|
||||
'/schedules',
|
||||
function ($vars) {
|
||||
global $users, $schedules;
|
||||
requireLogin() || accessDenied();
|
||||
$users->online_time_update();
|
||||
$new_schedules = !is_string($_POST["schedules"]) ? json_encode($_POST["schedules"]) : $_POST["schedules"];
|
||||
apiResponse([
|
||||
"response" => $schedules->update($new_schedules)
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
$r->addRoute(
|
||||
['POST'],
|
||||
'/login',
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
"delight-im/auth": "dev-master",
|
||||
"ulrichsg/getopt-php": "4.0.0",
|
||||
"nikic/fast-route": "^2.0@dev",
|
||||
"spatie/array-to-xml": "2.16.0",
|
||||
"ezyang/htmlpurifier": "4.13.0",
|
||||
"spatie/array-to-xml": "3.1.0",
|
||||
"ezyang/htmlpurifier": "4.14.0",
|
||||
"brick/phonenumber": "0.4.0",
|
||||
"sentry/sdk": "3.1.1",
|
||||
"azuyalabs/yasumi": "2.4.0",
|
||||
"ministryofweb/php-osm-tiles": "2.0.0",
|
||||
"delight-im/db": "1.3.1",
|
||||
"phpfastcache/phpfastcache": "8.0.8",
|
||||
"phpfastcache/phpfastcache": "9.0.1",
|
||||
"skrtdev/novagram": "1.10",
|
||||
"league/mime-type-detection": "1.9.0"
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "122d9ea31cd8f0cdc173a0d102dc599e",
|
||||
"content-hash": "c24f492bcd977f01ae44c4ee0c7ae1e4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "azuyalabs/yasumi",
|
||||
|
@ -207,12 +207,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/allerta-vvf/PHP-Auth-JWT",
|
||||
"reference": "ddb3236ae79fcd0e706d108332dbad9dcdffc2c6"
|
||||
"reference": "3ea0aa3d7e74528c57932872bbda339e995a9d9a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/allerta-vvf/PHP-Auth-JWT/zipball/ddb3236ae79fcd0e706d108332dbad9dcdffc2c6",
|
||||
"reference": "ddb3236ae79fcd0e706d108332dbad9dcdffc2c6",
|
||||
"url": "https://api.github.com/repos/allerta-vvf/PHP-Auth-JWT/zipball/3ea0aa3d7e74528c57932872bbda339e995a9d9a",
|
||||
"reference": "3ea0aa3d7e74528c57932872bbda339e995a9d9a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -240,7 +240,7 @@
|
|||
"login",
|
||||
"security"
|
||||
],
|
||||
"time": "2021-12-24T14:07:13+00:00"
|
||||
"time": "2021-12-27T18:35:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "delight-im/base64",
|
||||
|
@ -334,24 +334,21 @@
|
|||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.13.0",
|
||||
"version": "v4.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
|
||||
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
|
||||
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
@ -382,9 +379,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
||||
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
|
||||
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0"
|
||||
},
|
||||
"time": "2020-06-29T00:56:53+00:00"
|
||||
"time": "2021-12-25T01:21:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "giggsey/libphonenumber-for-php",
|
||||
|
@ -1631,48 +1628,56 @@
|
|||
},
|
||||
{
|
||||
"name": "phpfastcache/phpfastcache",
|
||||
"version": "8.0.8",
|
||||
"version": "9.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPSocialNetwork/phpfastcache.git",
|
||||
"reference": "c413ffd8185564db3d670e20f9135497be9ebe85"
|
||||
"reference": "bcd068ff1a78cd1475a4d8c13ed371711465ef40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPSocialNetwork/phpfastcache/zipball/c413ffd8185564db3d670e20f9135497be9ebe85",
|
||||
"reference": "c413ffd8185564db3d670e20f9135497be9ebe85",
|
||||
"url": "https://api.github.com/repos/PHPSocialNetwork/phpfastcache/zipball/bcd068ff1a78cd1475a4d8c13ed371711465ef40",
|
||||
"reference": "bcd068ff1a78cd1475a4d8c13ed371711465ef40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=7.3",
|
||||
"psr/cache": "~1.0.0",
|
||||
"psr/simple-cache": "~1.0.0"
|
||||
"php": ">=8.0",
|
||||
"psr/cache": "^2.0||^3.0",
|
||||
"psr/simple-cache": "^2.0||^3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/couchdb": "*"
|
||||
"doctrine/couchdb": "<dev-master#9eeb9e5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-gettext": "*",
|
||||
"league/climate": "^3.5"
|
||||
"jetbrains/phpstorm-stubs": "dev-master",
|
||||
"league/climate": "^3.5",
|
||||
"phpmd/phpmd": "@stable",
|
||||
"phpstan/phpstan": "^0.12.98",
|
||||
"squizlabs/php_codesniffer": "~3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-apc": "*",
|
||||
"aws/aws-sdk-php": "~3.0",
|
||||
"doctrine/couchdb": "^dev-master#9eeb9e5",
|
||||
"ext-apcu": "*",
|
||||
"ext-couchbase": "*",
|
||||
"ext-couchbase_v3": "*",
|
||||
"ext-intl": "*",
|
||||
"ext-leveldb": "*",
|
||||
"ext-memcache": "*",
|
||||
"ext-memcached": "*",
|
||||
"ext-mongodb": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-sqlite": "*",
|
||||
"ext-wincache": "*",
|
||||
"ext-xcache": "*",
|
||||
"google/cloud-firestore": "^1.20",
|
||||
"mongodb/mongodb": "^1.9",
|
||||
"phpfastcache/couchdb": "~1.0.0",
|
||||
"phpfastcache/phpssdb": "~1.0.0",
|
||||
"predis/predis": "^1.1"
|
||||
"phpfastcache/phpssdb": "~1.1.0",
|
||||
"predis/predis": "^1.1",
|
||||
"triagens/arangodb": "^3.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -1693,15 +1698,14 @@
|
|||
"role": "Actual Project Manager/Developer"
|
||||
},
|
||||
{
|
||||
"name": "Khoa Bui",
|
||||
"email": "khoaofgod@gmail.com",
|
||||
"homepage": "https://www.phpfastcache.com",
|
||||
"role": "Former Project Developer/Original Creator"
|
||||
"name": "Contributors",
|
||||
"homepage": "https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "PHP Abstract Cache Class - Reduce your database call using cache system. PhpFastCache handles a lot of drivers such as Apc(u), Cassandra, CouchBase, Couchdb, Mongodb, Files, (P)redis, Leveldb, Memcache(d), Ssdb, Sqlite, Wincache, Xcache, Zend Data Cache.",
|
||||
"description": "PHP Abstract Cache Class - Reduce your database call using cache system. Phpfastcache handles a lot of drivers such as Apc(u), Cassandra, CouchBase, Couchdb, Mongodb, Files, (P)redis, Leveldb, Memcache(d), Ssdb, Sqlite, Wincache, Xcache, Zend Data Cache.",
|
||||
"homepage": "https://www.phpfastcache.com",
|
||||
"keywords": [
|
||||
"ArangoDb",
|
||||
"LevelDb",
|
||||
"abstract",
|
||||
"apc",
|
||||
|
@ -1713,6 +1717,7 @@
|
|||
"cookie",
|
||||
"couchbase",
|
||||
"couchdb",
|
||||
"dynamodb",
|
||||
"files cache",
|
||||
"memcache",
|
||||
"memcached",
|
||||
|
@ -1733,36 +1738,33 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPSocialNetwork/phpfastcache/issues",
|
||||
"source": "https://github.com/PHPSocialNetwork/phpfastcache/tree/8.0.8"
|
||||
"source": "https://github.com/PHPSocialNetwork/phpfastcache",
|
||||
"wiki": "https://github.com/PHPSocialNetwork/phpfastcache/wiki"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/geolim4",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/geolim4",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-18T01:26:03+00:00"
|
||||
"time": "2021-11-13T23:59:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "1.0.1",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -1782,7 +1784,7 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
|
@ -1792,9 +1794,9 @@
|
|||
"psr-6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/cache/tree/master"
|
||||
"source": "https://github.com/php-fig/cache/tree/3.0.0"
|
||||
},
|
||||
"time": "2016-08-06T20:24:11+00:00"
|
||||
"time": "2021-02-03T23:26:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
|
@ -2061,25 +2063,25 @@
|
|||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -2094,7 +2096,7 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
|
@ -2106,9 +2108,9 @@
|
|||
"simple-cache"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/master"
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
|
||||
},
|
||||
"time": "2017-10-23T01:57:42+00:00"
|
||||
"time": "2021-10-29T13:26:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
|
@ -2212,16 +2214,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
"version": "3.3.4",
|
||||
"version": "3.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/getsentry/sentry-php.git",
|
||||
"reference": "ecbd09ea5d053a202cf773cb24ab28af820831bd"
|
||||
"reference": "c186c44c32899ad0cf5b4e942d71035f01b87b64"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/ecbd09ea5d053a202cf773cb24ab28af820831bd",
|
||||
"reference": "ecbd09ea5d053a202cf773cb24ab28af820831bd",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/c186c44c32899ad0cf5b4e942d71035f01b87b64",
|
||||
"reference": "c186c44c32899ad0cf5b4e942d71035f01b87b64",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2229,7 +2231,7 @@
|
|||
"ext-mbstring": "*",
|
||||
"guzzlehttp/promises": "^1.4",
|
||||
"guzzlehttp/psr7": "^1.7|^2.0",
|
||||
"jean85/pretty-package-versions": "^1.5|^2.0.1",
|
||||
"jean85/pretty-package-versions": "^1.5|^2.0.4",
|
||||
"php": "^7.2|^8.0",
|
||||
"php-http/async-client-implementation": "^1.0",
|
||||
"php-http/client-common": "^1.5|^2.0",
|
||||
|
@ -2300,7 +2302,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/getsentry/sentry-php/issues",
|
||||
"source": "https://github.com/getsentry/sentry-php/tree/3.3.4"
|
||||
"source": "https://github.com/getsentry/sentry-php/tree/3.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2312,7 +2314,7 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-08T08:44:00+00:00"
|
||||
"time": "2021-12-27T12:31:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "skrtdev/async",
|
||||
|
@ -2421,25 +2423,25 @@
|
|||
},
|
||||
{
|
||||
"name": "spatie/array-to-xml",
|
||||
"version": "2.16.0",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/array-to-xml.git",
|
||||
"reference": "db39308c5236b69b89cadc3f44f191704814eae2"
|
||||
"reference": "3090918cb441ad707660dd8bccc6dc46beb34380"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/db39308c5236b69b89cadc3f44f191704814eae2",
|
||||
"reference": "db39308c5236b69b89cadc3f44f191704814eae2",
|
||||
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/3090918cb441ad707660dd8bccc6dc46beb34380",
|
||||
"reference": "3090918cb441ad707660dd8bccc6dc46beb34380",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"php": "^7.4|^8.0"
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.2"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -2469,7 +2471,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/array-to-xml/issues",
|
||||
"source": "https://github.com/spatie/array-to-xml/tree/2.16.0"
|
||||
"source": "https://github.com/spatie/array-to-xml/tree/3.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2481,7 +2483,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-18T22:03:17+00:00"
|
||||
"time": "2021-09-12T17:08:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
|
@ -3263,5 +3265,5 @@
|
|||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.2.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
require_once 'utils.php';
|
||||
|
||||
$executed_actions = [];
|
||||
|
||||
function job_reset_availability() {
|
||||
global $db, $executed_actions;
|
||||
$profiles = $db->select("SELECT * FROM `".DB_PREFIX."_profiles`");
|
||||
if(!is_null($profiles) && count($profiles) > 0) {
|
||||
$list = [];
|
||||
foreach($profiles as $profile){
|
||||
$list[] = [$profile["id"] => $profile["availability_minutes"]];
|
||||
}
|
||||
$db->insert(
|
||||
DB_PREFIX."_minutes",
|
||||
["month" => date("m"), "year" => date("Y"), "list"=> json_encode($list)]
|
||||
);
|
||||
$db->exec("UPDATE `".DB_PREFIX."_profiles` SET `availability_minutes` = 0");
|
||||
$output = $list;
|
||||
$output_status = "ok";
|
||||
} else {
|
||||
$output = ["profiles array empty"];
|
||||
$output_status = "error";
|
||||
}
|
||||
$executed_actions[] = [
|
||||
"title" => "Reset availability minutes",
|
||||
"description" => "Reset availability minutes for all profiles",
|
||||
"output" => $output,
|
||||
"output_status" => $output_status
|
||||
];
|
||||
}
|
||||
|
||||
function job_increment_availability() {
|
||||
global $db, $executed_actions;
|
||||
$profiles = $db->select("SELECT * FROM `".DB_PREFIX."_profiles` WHERE `available` = 1");
|
||||
if(!is_null($profiles) && count($profiles) > 0) {
|
||||
$output = [];
|
||||
$output[] = $profiles;
|
||||
$output_status = "ok";
|
||||
$queries = [];
|
||||
foreach ($profiles as $row) {
|
||||
$value = (int)$row["availability_minutes"]+5;
|
||||
$id = $row["id"];
|
||||
$increment[$id] = $value;
|
||||
$count = $db->update(
|
||||
DB_PREFIX."_profiles",
|
||||
["availability_minutes" => $value],
|
||||
["id" => $id]
|
||||
);
|
||||
$tmp = $id . " - " . $value . " ";
|
||||
$tmp .= $count == 1 ? "success" : "fail";
|
||||
$queries[] = $tmp;
|
||||
}
|
||||
$output[] = $queries;
|
||||
} else {
|
||||
$output = ["profiles array empty"];
|
||||
$output_status = "ok";
|
||||
}
|
||||
$executed_actions[] = [
|
||||
"title" => "Increment availability minutes",
|
||||
"description" => "Increment availability minutes for all available profiles",
|
||||
"output" => $output,
|
||||
"output_status" => $output_status
|
||||
];
|
||||
}
|
||||
|
||||
function job_schedule_availability() {
|
||||
global $db, $executed_actions;
|
||||
$result = $db->select("SELECT * FROM `".DB_PREFIX."_schedules`;");
|
||||
$schedules_check = [];
|
||||
$schedules_users = [];
|
||||
$schedules_check["schedules"] = [];
|
||||
$schedules_check["users"] = [];
|
||||
if(!empty($result)){
|
||||
foreach ($result as $key => $value) {
|
||||
$result[$key]["schedules"] = json_decode($result[$key]["schedules"], true);
|
||||
}
|
||||
$schedules_check["table"] = $result;
|
||||
foreach ($result as $row) {
|
||||
if(!is_null($row["last_exec"])){
|
||||
$last_exec = [
|
||||
"day" => (int) explode(";",$row["last_exec"])[0],
|
||||
"hour" => (int) explode(":",explode(";",$row["last_exec"])[1])[0],
|
||||
"minutes" => (int) explode(":",$row["last_exec"])[1]
|
||||
];
|
||||
} else {
|
||||
$last_exec = null;
|
||||
}
|
||||
|
||||
$id = $row["id"];
|
||||
$user_id = $row["user"];
|
||||
/*
|
||||
$selected_holidays = json_decode($row["holidays"]);
|
||||
$selected_holidays_dates = [];
|
||||
foreach ($selected_holidays as $holiday){
|
||||
$selected_holidays_dates[] = $user->holidays->getHoliday($holiday)->format('Y-m-d');
|
||||
}
|
||||
*/
|
||||
foreach ($row["schedules"] as $value) {
|
||||
$schedule = [
|
||||
"day" => (int) $value["day"]+1,
|
||||
"hour" => (int) explode(":",$value["hour"])[0],
|
||||
"minutes" => (int) explode(":",$value["hour"])[1]
|
||||
];
|
||||
$now = [
|
||||
"day" => (int) date("N"),
|
||||
"hour" => (int) date("H"),
|
||||
"minutes" => (int) date("i")
|
||||
];
|
||||
|
||||
if(
|
||||
$schedule["day"] == $now["day"] &&
|
||||
$schedule["hour"] == $now["hour"] &&
|
||||
$schedule["minutes"] <= $now["minutes"] &&
|
||||
$now["minutes"] - $schedule["minutes"] <= 30
|
||||
){
|
||||
if(!in_array($user_id,$schedules_users)) $schedules_users[] = $user_id;
|
||||
if(is_null($last_exec) || (is_array($last_exec) && $schedule["hour"] == $last_exec["hour"] ? $schedule["minutes"] !== $last_exec["minutes"] : true)/* && !in_array(date('Y-m-d'), $selected_holidays_dates)*/){
|
||||
$last_exec_new = $schedule["day"].";".sprintf("%02d", $schedule["hour"]).":".sprintf("%02d", $schedule["minutes"]);
|
||||
$db->update(
|
||||
DB_PREFIX."_schedules",
|
||||
["last_exec" => $last_exec_new],
|
||||
["id" => $id]
|
||||
);
|
||||
$db->update(
|
||||
DB_PREFIX."_profiles",
|
||||
["available" => '1', "availability_last_change" => "cron"],
|
||||
["id" => $user_id]
|
||||
);
|
||||
$schedules_check["schedules"][] = [
|
||||
"schedule" => $schedule,
|
||||
"now" => $now,
|
||||
"last_exec" => $last_exec,
|
||||
"last_exec_new" => $last_exec_new,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$schedules_check["users"] = $schedules_users;
|
||||
$profiles = $db->select("SELECT id FROM `".DB_PREFIX."_profiles`");
|
||||
foreach ($profiles as $profile) {
|
||||
if(!in_array($profile["id"],$schedules_users)){
|
||||
$db->update(
|
||||
DB_PREFIX."_profiles",
|
||||
["available" => 0],
|
||||
["availability_last_change" => "cron", "id" => $profile["id"]]
|
||||
);
|
||||
}
|
||||
}
|
||||
$output = $schedules_check;
|
||||
$output_status = "ok";
|
||||
} else {
|
||||
$output = ["schedules array empty"];
|
||||
$output_status = "ok";
|
||||
}
|
||||
$executed_actions[] = [
|
||||
"title" => "Schedule availability",
|
||||
"description" => "Update availability for all users based on schedules",
|
||||
"output" => $output,
|
||||
"output_status" => $output_status
|
||||
];
|
||||
}
|
||||
|
||||
function cronRouter (FastRoute\RouteCollector $r) {
|
||||
$r->addRoute(
|
||||
'GET',
|
||||
'/execute',
|
||||
function ($vars) {
|
||||
global $db, $executed_actions;
|
||||
$cron_job_allowed = true;
|
||||
|
||||
if(!$cron_job_allowed) {
|
||||
statusCode(403);
|
||||
exit();
|
||||
}
|
||||
|
||||
job_schedule_availability();
|
||||
//job_reset_availability();
|
||||
job_increment_availability();
|
||||
|
||||
apiResponse(["excuted_actions" => $executed_actions]);
|
||||
}
|
||||
);
|
||||
}
|
|
@ -155,21 +155,31 @@ class Users
|
|||
public function loginAndReturnToken($username, $password)
|
||||
{
|
||||
$this->auth->loginWithUsername($username, $password);
|
||||
$token = $this->auth->generateJWTtoken();
|
||||
$token = $this->auth->generateJWTtoken([
|
||||
"chief" => $this->auth->hasRole(Role::FULL_VIEWER),
|
||||
"name" => $this->getName(),
|
||||
]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function isHidden($id)
|
||||
public function isHidden($id=null)
|
||||
{
|
||||
if(is_null($id)) $id = $this->auth->getUserId();
|
||||
$user = $this->db->selectRow("SELECT * FROM `".DB_PREFIX."_profiles` WHERE `id` = ?", [$id]);
|
||||
return $user["hidden"];
|
||||
}
|
||||
|
||||
public function getName($id)
|
||||
public function getName($id=null)
|
||||
{
|
||||
if(is_null($id)) $id = $this->auth->getUserId();
|
||||
$user = $this->db->selectRow("SELECT * FROM `".DB_PREFIX."_profiles` WHERE `id` = ?", [$id]);
|
||||
return $user["name"];
|
||||
}
|
||||
|
||||
public function hasRole($role, $adminGranted=true)
|
||||
{
|
||||
return $this->auth->hasRole($role) || $adminGranted && $role !== Role::DEVELOPER && $this->auth->hasRole(Role::ADMIN) || $role !== Role::DEVELOPER && $this->auth->hasRole(Role::SUPER_ADMIN);
|
||||
}
|
||||
}
|
||||
|
||||
class Services {
|
||||
|
@ -222,5 +232,44 @@ class Services {
|
|||
}
|
||||
}
|
||||
|
||||
class Schedules {
|
||||
private $db = null;
|
||||
private $users = null;
|
||||
|
||||
public function __construct($db, $users)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
public function get($profile="default") {
|
||||
$response = $this->db->selectRow("SELECT * FROM `".DB_PREFIX."_schedules` WHERE `user` = ? AND `profile_name` = ?", [$this->users->auth->getUserId(), $profile]);
|
||||
if(!is_null($response)) {
|
||||
$response["schedules"] = json_decode($response["schedules"], true);
|
||||
return $response;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function update($schedules, $profile="default") {
|
||||
//TODO implement multiple profiles
|
||||
//TODO implement holidays
|
||||
logger("Aggiornata programmazione orari disponibilità");
|
||||
if(empty($this->get($profile))) {
|
||||
return $this->db->insert(
|
||||
DB_PREFIX."_schedules",
|
||||
["user" => $this->users->auth->getUserId(), "schedules" => $schedules, "profile_name" => $profile]
|
||||
);
|
||||
} else {
|
||||
return $this->db->update(
|
||||
DB_PREFIX."_schedules",
|
||||
["schedules" => $schedules, "last_update" => null],
|
||||
["user" => $this->users->auth->getUserId(), "profile_name" => $profile]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$users = new Users($db, $auth);
|
||||
$services = new Services($db);
|
||||
$services = new Services($db);
|
||||
$schedules = new Schedules($db, $users);
|
|
@ -20,9 +20,10 @@
|
|||
"@angular/router": "~13.0.0",
|
||||
"@angular/service-worker": "~13.0.0",
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "11.0.0",
|
||||
"bootstrap": "^5.1.3",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"ngx-bootstrap": "^7.1.2",
|
||||
"rxjs": "~7.4.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.11.4"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<div class="text-center">
|
||||
<p>Sei disponibile in caso di allerta?</p>
|
||||
<div id="availability-btn-group">
|
||||
<button (click)="changeAvailibility(1)" id="activate-btn" class="btn btn-lg btn-success me-1">Attiva</button>
|
||||
<button (click)="changeAvailibility(0)" id="deactivate-btn" class="btn btn-lg btn-danger">Disattiva</button>
|
||||
<button (click)="changeAvailibility(1)" type="button" [delay]="1000" tooltip="Cambia la tua disponibilità in 'attivo'" id="activate-btn" class="btn btn-lg btn-success me-1">Attiva</button>
|
||||
<button (click)="changeAvailibility(0)" type="button" [delay]="1000" tooltip="Cambia la tua disponibilità in 'non attivo'" id="deactivate-btn" class="btn btn-lg btn-danger">Disattiva</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-lg">
|
||||
<button type="button" class="btn btn-lg" (click)="openScheduleModal()">
|
||||
Modifica orari disponibilità
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { TableComponent } from '../table/table.component';
|
||||
import { ModalAvailabilityScheduleComponent } from '../modal-availability-schedule/modal-availability-schedule.component';
|
||||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
|
||||
|
||||
@Component({
|
||||
selector: 'app-list',
|
||||
|
@ -7,11 +10,10 @@ import { ApiClientService } from 'src/app/_services/api-client.service';
|
|||
styleUrls: ['./list.component.scss']
|
||||
})
|
||||
export class ListComponent implements OnInit {
|
||||
scheduleModalRef?: BsModalRef;
|
||||
@ViewChild('table') table!: TableComponent;
|
||||
|
||||
@ViewChild('table') table!: any;
|
||||
|
||||
constructor(private api: ApiClientService) {}
|
||||
|
||||
constructor(private api: ApiClientService, private modalService: BsModalService) {}
|
||||
|
||||
changeAvailibility(available: 0|1, id?: number|undefined) {
|
||||
this.api.post("availability", {
|
||||
|
@ -22,6 +24,10 @@ export class ListComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
openScheduleModal() {
|
||||
this.scheduleModalRef = this.modalService.show(ModalAvailabilityScheduleComponent, Object.assign({}, { class: 'modal-custom' }));
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<div class="modal-header">
|
||||
<h4 class="modal-title pull-left">Modifica orari disponibilità</h4>
|
||||
<button type="button" class="btn-close close pull-right" aria-label="Close" (click)="bsModalRef.hide()">
|
||||
<span aria-hidden="true" class="visually-hidden">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" style="overflow-x: auto">
|
||||
<table cellpadding="0" cellspacing="0" id="scheduler_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="background-color: white;"></td>
|
||||
<ng-container *ngIf="orientation === 'portrait'">
|
||||
<ng-container *ngFor="let day of days; let i = index">
|
||||
<td class="day" (click)="selectDay(i)">{{ day.short }}</td>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="orientation === 'landscape'">
|
||||
<ng-container *ngFor="let hour of hours">
|
||||
<td class="hour" (click)="selectHour(hour)">{{ hour }}</td>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="scheduler_body" *ngIf="orientation === 'portrait'">
|
||||
<ng-container *ngFor="let hour of hours">
|
||||
<tr>
|
||||
<td class="hour" (click)="selectHour(hour)">{{ hour }}</td>
|
||||
<ng-container *ngFor="let day of days; let i = index">
|
||||
<td class="hour-cell" [class.highlighted] = "isCellSelected(i, hour)" (mousedown)="mouseDownCell(i, hour)" (mouseup)="mouseUpCell()" (mouseover)="mouseOverCell(i, hour)"></td>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</tbody>
|
||||
<tbody id="scheduler_body" *ngIf="orientation === 'landscape'">
|
||||
<ng-container *ngFor="let day of days; let i = index">
|
||||
<tr>
|
||||
<td class="day" (click)="selectDay(i)">{{ day.short }}</td>
|
||||
<ng-container *ngFor="let hour of hours">
|
||||
<td class="hour-cell" [class.highlighted] = "isCellSelected(i, hour)" (mousedown)="mouseDownCell(i, hour)" (mouseup)="mouseUpCell()" (mouseover)="mouseOverCell(i, hour)"></td>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" (click)="saveChanges()">Salva le modifiche</button>
|
||||
<button type="button" class="btn btn-secondary" (click)="bsModalRef.hide()">Chiudi</button>
|
||||
</div>
|
|
@ -0,0 +1,21 @@
|
|||
.hour-cell {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: #ccc;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.hour-cell.highlighted {
|
||||
background-color: #999;
|
||||
}
|
||||
#scheduler_body td {
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.modal-custom {
|
||||
overflow-x: auto;
|
||||
max-width: 99%;
|
||||
margin-bottom: 5em;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
import { Component, OnInit, ViewEncapsulation, HostListener } from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
|
||||
@Component({
|
||||
selector: 'modal-availability-schedule',
|
||||
templateUrl: './modal-availability-schedule.component.html',
|
||||
styleUrls: ['./modal-availability-schedule.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ModalAvailabilityScheduleComponent implements OnInit {
|
||||
public orientation = "portrait";
|
||||
|
||||
public days = [
|
||||
{
|
||||
name: 'Lunedì',
|
||||
short: 'Lun'
|
||||
},
|
||||
{
|
||||
name: 'Martedì',
|
||||
short: 'Mar'
|
||||
},
|
||||
{
|
||||
name: 'Mercoledì',
|
||||
short: 'Mer'
|
||||
},
|
||||
{
|
||||
name: 'Giovedì',
|
||||
short: 'Gio'
|
||||
},
|
||||
{
|
||||
name: 'Venerdì',
|
||||
short: 'Ven'
|
||||
},
|
||||
{
|
||||
name: 'Sabato',
|
||||
short: 'Sab'
|
||||
},
|
||||
{
|
||||
name: 'Domenica',
|
||||
short: 'Dom'
|
||||
}
|
||||
];
|
||||
public hours = [
|
||||
"0:00", "0:30",
|
||||
"1:00", "1:30",
|
||||
"2:00", "2:30",
|
||||
"3:00", "3:30",
|
||||
"4:00", "4:30",
|
||||
"5:00", "5:30",
|
||||
"6:00", "6:30",
|
||||
"7:00", "7:30",
|
||||
"8:00", "8:30",
|
||||
"9:00", "9:30",
|
||||
"10:00", "10:30",
|
||||
"11:00", "11:30",
|
||||
"12:00", "12:30",
|
||||
"13:00", "13:30",
|
||||
"14:00", "14:30",
|
||||
"15:00", "15:30",
|
||||
"16:00", "16:30",
|
||||
"17:00", "17:30",
|
||||
"18:00", "18:30",
|
||||
"19:00", "19:30",
|
||||
"20:00", "20:30",
|
||||
"21:00", "21:30",
|
||||
"22:00", "22:30",
|
||||
"23:00", "23:30",
|
||||
];
|
||||
|
||||
public selectedCells: any = [];
|
||||
|
||||
//Used for "select all"
|
||||
public selectedHours: string[] = [];
|
||||
public selectedDays: number[] = [];
|
||||
|
||||
public isSelecting = false;
|
||||
|
||||
constructor(public bsModalRef: BsModalRef, private api: ApiClientService) { }
|
||||
|
||||
loadSchedules(schedules: any) {
|
||||
console.log("Loaded schedules", schedules);
|
||||
if(typeof schedules === "undefined") {
|
||||
schedules = [];
|
||||
}
|
||||
if(typeof schedules === "string") {
|
||||
schedules = JSON.parse(schedules);
|
||||
}
|
||||
this.selectedCells = schedules;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.orientation = window.innerHeight > window.innerWidth ? "portrait" : "landscape";
|
||||
if(localStorage.getItem('schedules') === null) {
|
||||
this.api.get("schedules").then((response: any) => {
|
||||
this.loadSchedules(response.schedules);
|
||||
});
|
||||
} else {
|
||||
this.loadSchedules(JSON.parse((localStorage.getItem('schedules') as string)));
|
||||
}
|
||||
}
|
||||
|
||||
saveChanges() {
|
||||
console.log("Selected cells", this.selectedCells);
|
||||
this.api.post("schedules", {
|
||||
schedules: this.selectedCells
|
||||
});
|
||||
localStorage.removeItem('schedules');
|
||||
this.bsModalRef.hide();
|
||||
}
|
||||
|
||||
saveChangesInLocal() {
|
||||
localStorage.setItem('schedules', JSON.stringify(this.selectedCells));
|
||||
}
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(event: Event) {
|
||||
this.orientation = window.innerHeight > window.innerWidth ? "portrait" : "landscape";
|
||||
}
|
||||
|
||||
isCellSelected(day: number, hour: string) {
|
||||
return this.selectedCells.find((cell: any) => cell.day === day && cell.hour === hour);
|
||||
}
|
||||
|
||||
toggleCell(day: number, hour: string) {
|
||||
if(!this.isCellSelected(day, hour)) {
|
||||
this.selectedCells.push({
|
||||
day, hour
|
||||
});
|
||||
} else {
|
||||
this.selectedCells = this.selectedCells.filter((cell: any) => cell.day !== day || cell.hour !== hour);
|
||||
}
|
||||
this.saveChangesInLocal();
|
||||
}
|
||||
|
||||
selectHour(hour: string) {
|
||||
console.log("Hour selected", hour);
|
||||
if(this.selectedHours.includes(hour)) {
|
||||
this.days.forEach((day: any, i: number) => {
|
||||
this.selectedCells = this.selectedCells.filter((cell: any) => cell.day !== i || cell.hour !== hour);
|
||||
});
|
||||
this.selectedHours = this.selectedHours.filter((h: string) => h !== hour);
|
||||
} else {
|
||||
this.days.forEach((day: any, i: number) => {
|
||||
if(!this.isCellSelected(i, hour)) {
|
||||
this.selectedCells.push({
|
||||
day: i, hour
|
||||
});
|
||||
}
|
||||
});
|
||||
this.selectedHours.push(hour);
|
||||
}
|
||||
this.saveChangesInLocal();
|
||||
}
|
||||
|
||||
selectDay(day: number) {
|
||||
console.log("Day selected", day);
|
||||
if(this.selectedDays.includes(day)) {
|
||||
this.hours.forEach((hour: string) => {
|
||||
this.selectedCells = this.selectedCells.filter((cell: any) => cell.day !== day || cell.hour !== hour);
|
||||
});
|
||||
this.selectedDays = this.selectedDays.filter((i: number) => i !== day);
|
||||
} else {
|
||||
this.hours.forEach((hour: string) => {
|
||||
if(!this.isCellSelected(day, hour)) {
|
||||
this.selectedCells.push({
|
||||
day, hour
|
||||
});
|
||||
}
|
||||
});
|
||||
this.selectedDays.push(day);
|
||||
}
|
||||
this.saveChangesInLocal();
|
||||
}
|
||||
|
||||
mouseDownCell(day: number, hour: string) {
|
||||
this.isSelecting = true;
|
||||
console.log("Mouse down");
|
||||
console.log("Hour cell selected", day, hour);
|
||||
this.toggleCell(day, hour);
|
||||
return false;
|
||||
}
|
||||
|
||||
mouseUpCell() {
|
||||
this.isSelecting = false;
|
||||
console.log("Mouse up");
|
||||
}
|
||||
|
||||
mouseOverCell(day: number, hour: string) {
|
||||
if (this.isSelecting) {
|
||||
console.log("Mouse over", day, hour);
|
||||
console.log("Hour cell selected", day, hour);
|
||||
this.toggleCell(day, hour);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -4,27 +4,30 @@
|
|||
<tr>
|
||||
<th>Nome</th>
|
||||
<th>Disponibile</th>
|
||||
<ng-container *ngIf="auth.profile.chief">
|
||||
<th>Autista</th>
|
||||
<th>Chiama</th>
|
||||
<th>Scrivi</th>
|
||||
<th>Interventi</th>
|
||||
<th>Minuti disponibilità</th>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table_body">
|
||||
<tr *ngFor="let row of data">
|
||||
<td>
|
||||
<img alt="red helmet" src="./assets/img/red_helmet.png" width="20px" *ngIf="row.chief">
|
||||
<img alt="red helmet" src="./assets/img/black_helmet.png" width="20px" *ngIf="!row.chief">
|
||||
<img alt="red helmet" src="./assets/icons/red_helmet.png" width="20px" *ngIf="row.chief">
|
||||
<img alt="red helmet" src="./assets/icons/black_helmet.png" width="20px" *ngIf="!row.chief">
|
||||
<ng-container *ngIf="(getTime() - row.online_time) < 30"><u>{{ row.name }}</u></ng-container>
|
||||
<ng-container *ngIf="(getTime() - row.online_time) > 30">{{ row.name }}</ng-container>
|
||||
</td>
|
||||
<td (click)="changeAvailability.emit({user: row.id, newState: row.available ? 0 : 1})">
|
||||
<td (click)="onChangeAvailability(row.id, row.available ? 0 : 1)">
|
||||
<i class="fa fa-check" style="color:green" *ngIf="row.available"></i>
|
||||
<i class="fa fa-times" style="color:red" *ngIf="!row.available"></i>
|
||||
</td>
|
||||
<ng-container *ngIf="auth.profile.chief">
|
||||
<td>
|
||||
<img alt="driver" src="./assets/img/wheel.png" width="20px" *ngIf="row.driver">
|
||||
<img alt="driver" src="./assets/icons/wheel.png" width="20px" *ngIf="row.driver">
|
||||
</td>
|
||||
<td>
|
||||
<a href="tel:{{row.phone_number}}"><i class="fa fa-phone"></i></a>
|
||||
|
@ -34,6 +37,7 @@
|
|||
</td>
|
||||
<td>{{ row.services }}</td>
|
||||
<td>{{ row.availability_minutes }}</td>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { TableType } from 'src/app/_models/TableType';
|
||||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
import { AuthService } from '../../_services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-table',
|
||||
|
@ -10,12 +11,15 @@ import { ApiClientService } from 'src/app/_services/api-client.service';
|
|||
export class TableComponent implements OnInit {
|
||||
|
||||
@Input() sourceType?: string;
|
||||
@Input() refreshInterval?: number;
|
||||
|
||||
@Output() changeAvailability: EventEmitter<{user: number, newState: 0|1}> = new EventEmitter<{user: number, newState: 0|1}>();
|
||||
|
||||
public data: any = [];
|
||||
|
||||
constructor(public apiClient: ApiClientService) {}
|
||||
public loadDataInterval: NodeJS.Timer | number = 0;
|
||||
|
||||
constructor(public apiClient: ApiClientService, public auth: AuthService) {}
|
||||
|
||||
getTime() {
|
||||
return Math.floor(Date.now() / 1000);
|
||||
|
@ -34,6 +38,15 @@ export class TableComponent implements OnInit {
|
|||
ngOnInit(): void {
|
||||
console.log(this.sourceType);
|
||||
this.loadTableData();
|
||||
this.loadDataInterval = setInterval(() => {
|
||||
console.log("Refreshing data...");
|
||||
this.loadTableData();
|
||||
}, this.refreshInterval || 10000);
|
||||
}
|
||||
|
||||
onChangeAvailability(user: number, newState: 0|1) {
|
||||
if(this.auth.profile.chief) {
|
||||
this.changeAvailability.emit({user, newState});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,10 @@ export class ApiClientService {
|
|||
}
|
||||
|
||||
public post(endpoint: string, data: any) {
|
||||
let params = new HttpParams({
|
||||
fromObject: data,
|
||||
});
|
||||
let params = Object.keys(data).reduce(function (params, key) {
|
||||
params.set(key, JSON.stringify(data[key]));
|
||||
return params;
|
||||
}, new URLSearchParams());
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.http.post(this.apiEndpoint(endpoint), params.toString(), this.requestOptions).subscribe((data: any) => {
|
||||
resolve(data);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/services">Interventi</a>
|
||||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/trainings">Esercitazioni</a>
|
||||
<a routerLinkActive="active" (click)="menuButtonClicked = false" routerLink="/logs">Logs</a>
|
||||
<a style="float: right;" id="logout">Ciao, {{ auth.profile.auth_username }}. <b id="logout-text" (click)="auth.logout()">Logout</b></a>
|
||||
<a style="float: right;" id="logout">Ciao, {{ auth.profile.name }}. <b id="logout-text" (click)="auth.logout()">Logout</b></a>
|
||||
<a class="icon" id="menuButton" (click)="menuButtonClicked = !menuButtonClicked">☰</a>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ import { NgModule } from '@angular/core';
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ModalModule } from 'ngx-bootstrap/modal';
|
||||
import { TooltipModule } from 'ngx-bootstrap/tooltip';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
|
@ -9,6 +11,7 @@ import { ServiceWorkerModule } from '@angular/service-worker';
|
|||
import { environment } from '../environments/environment';
|
||||
|
||||
import { TableComponent } from './_components/table/table.component';
|
||||
import { ModalAvailabilityScheduleComponent } from './_components/modal-availability-schedule/modal-availability-schedule.component';
|
||||
import { OwnerImageComponent } from './_components/owner-image/owner-image.component';
|
||||
|
||||
import { LoginComponent } from './_components/login/login.component';
|
||||
|
@ -23,6 +26,7 @@ import { TrainingsComponent } from './_components/trainings/trainings.component'
|
|||
AppComponent,
|
||||
//
|
||||
TableComponent,
|
||||
ModalAvailabilityScheduleComponent,
|
||||
OwnerImageComponent,
|
||||
//
|
||||
LoginComponent,
|
||||
|
@ -37,6 +41,8 @@ import { TrainingsComponent } from './_components/trainings/trainings.component'
|
|||
AppRoutingModule,
|
||||
HttpClientModule,
|
||||
FormsModule,
|
||||
ModalModule.forRoot(),
|
||||
TooltipModule.forRoot(),
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: false && environment.production,
|
||||
// Register the ServiceWorker as soon as the app is stable
|
||||
|
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 792 B |
Before Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 1.4 KiB |
|
@ -7,53 +7,15 @@
|
|||
"scope": "./",
|
||||
"start_url": "./",
|
||||
"icons": [
|
||||
{
|
||||
"src": "assets/icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"src/main.ts",
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
"name": "allerta-vvf/allerta-vvf",
|
||||
"description": "Un software di allertamento per i vvf",
|
||||
"type": "project",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"no-api": true,
|
||||
"url": "https://github.com/allerta-vvf/tiny-html-minifier"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"no-api": true,
|
||||
"url": "https://github.com/allerta-vvf/php-debugbar"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"twig/twig": "3.3.4",
|
||||
"delight-im/auth": "8.3.0",
|
||||
"ulrichsg/getopt-php": "4.0.0",
|
||||
"nikic/fast-route": "^2.0@dev",
|
||||
"spatie/array-to-xml": "2.16.0",
|
||||
"ezyang/htmlpurifier": "4.13.0",
|
||||
"brick/phonenumber": "0.4.0",
|
||||
"sentry/sdk": "3.1.1",
|
||||
"maximebf/debugbar": "dev-master",
|
||||
"azuyalabs/yasumi": "2.4.0",
|
||||
"ministryofweb/php-osm-tiles": "2.0.0",
|
||||
"jenstornell/tiny-html-minifier": "dev-master",
|
||||
"delight-im/db": "1.3.1",
|
||||
"webonyx/graphql-php": "14.11.3",
|
||||
"phpfastcache/phpfastcache": "8.0.8",
|
||||
"skrtdev/novagram": "1.10"
|
||||
},
|
||||
"license": "GPL-3.0-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matteo Gheza",
|
||||
"email": "matteo@matteogheza.it"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require-dev": {
|
||||
"pheromone/phpcs-security-audit": "2.0.1"
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
{
|
||||
"browserslist": [
|
||||
"ie 11"
|
||||
],
|
||||
"name": "allertavvf_webpack",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"prod": "webpack --config webpack.prod.js",
|
||||
"dev": "webpack --config webpack.dev.js",
|
||||
"dev_watch": "webpack --config webpack.dev.js --watch",
|
||||
"debug_bundle": "webpack --config webpack.debug_bundle.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "GPL3",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "6.12.0",
|
||||
"@sentry/tracing": "6.12.0",
|
||||
"bootstrap": "4.6.0",
|
||||
"bootstrap-datepicker": "1.9.0",
|
||||
"bootstrap-toggle": "2.2.2",
|
||||
"datatables.net-bs4": "1.11.1",
|
||||
"datatables.net-buttons-bs4": "1.7.1",
|
||||
"datatables.net-plugins": "1.10.24",
|
||||
"datatables.net-responsive-bs4": "2.2.9",
|
||||
"font-awesome": "4.7.0",
|
||||
"howler": "2.2.3",
|
||||
"jquery": "3.6.0",
|
||||
"jquery-pjax": "2.0.1",
|
||||
"jszip": "3.7.1",
|
||||
"leaflet": "1.7.1",
|
||||
"leaflet.locatecontrol": "0.74.0",
|
||||
"pdfmake": "0.2.2",
|
||||
"popper.js": "1.16.1",
|
||||
"promise-polyfill": "8.2.0",
|
||||
"time-input-polyfill": "1.0.10",
|
||||
"toastr": "2.1.4",
|
||||
"whatwg-fetch": "3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.15.5",
|
||||
"@babel/plugin-transform-runtime": "7.15.0",
|
||||
"@babel/preset-env": "7.15.4",
|
||||
"@fiverr/afterbuild-webpack-plugin": "1.0.0",
|
||||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@sentry/webpack-plugin": "1.17.1",
|
||||
"babel-loader": "8.2.2",
|
||||
"clean-webpack-plugin": "4.0.0",
|
||||
"colors": "1.4.0",
|
||||
"copy-webpack-plugin": "9.0.1",
|
||||
"core-js": "3.17.2",
|
||||
"css-loader": "6.2.0",
|
||||
"expose-loader": "3.0.0",
|
||||
"file-loader": "6.2.0",
|
||||
"glob": "7.1.7",
|
||||
"sass": "1.39.0",
|
||||
"sass-loader": "12.1.0",
|
||||
"speed-measure-webpack-plugin": "1.5.0",
|
||||
"style-loader": "3.2.1",
|
||||
"terser-webpack-plugin": "5.2.3",
|
||||
"webpack": "5.52.0",
|
||||
"webpack-assets-manifest": "5.0.6",
|
||||
"webpack-bundle-analyzer": "4.4.2",
|
||||
"webpack-cli": "4.8.0",
|
||||
"webpack-inject-plugin": "1.5.5",
|
||||
"webpack-merge": "5.8.0"
|
||||
}
|
||||
}
|