Compare commits

...

7 Commits

16 changed files with 121 additions and 95 deletions

View File

@@ -751,12 +751,38 @@ class API
$values[] = $from; $values[] = $from;
$values[] = $to; $values[] = $to;
} }
// ORDER BY
if (isset($builder['orderBy']) && is_array($builder['orderBy'])) {
if (count($builder['orderBy']) !== 2) {
continue;
}
$column = $builder['orderBy'][0];
$direction = strtoupper($builder['orderBy'][1]);
if (!in_array($column, $this->allowedGetColumns, true)) {
$this->apiOutput(400, ['error' => "The column $column is not allowed."]);
}
if (!in_array($direction, ['ASC', 'DESC'], true)) {
$this->apiOutput(400, ['error' => "Invalid order direction."]);
}
$orderByClauses[] = "$column $direction";
}
} }
if (!empty($whereClauses)) { if (!empty($whereClauses)) {
$this->baseQuery .= " WHERE " . implode(" AND ", $whereClauses); $this->baseQuery .= " WHERE " . implode(" AND ", $whereClauses);
} }
if (!empty($orderByClauses)) {
$this->baseQuery .= " ORDER BY " . implode(", ", $orderByClauses);
}
return [$this->baseQuery, $types, $values]; return [$this->baseQuery, $types, $values];
} }

View File

@@ -286,7 +286,7 @@ class API_inserve extends API
$sizes = array_column($disks, 'disk_space'); $sizes = array_column($disks, 'disk_space');
$server_disks_count = array_sum($sizes); $server_disks_count = array_sum($sizes);
} }
return $server_disks_count; return (int)ceil($server_disks_count);
} }
private function buildCountObject(string $serverUuid, string $key): array private function buildCountObject(string $serverUuid, string $key): array
@@ -294,11 +294,11 @@ class API_inserve extends API
return [ return [
'countSentri' => 0, 'countSentri' => 0,
'countInserve' => 0, 'countInserve' => 0,
'sentriCompanyId' => 0,
'SentriStatus' => 0, 'SentriStatus' => 0,
'subscriptionInserveExists' => false, 'subscriptionInserveExists' => false,
'subscriptionInserveId' => false, 'subscriptionInserveId' => false,
'subscriptionInserveCompanyId' => false, 'subscriptionSentriCompanyName' => false,
'subscriptionInserveCompanyName' => false,
'subscriptionInserveName' => false, 'subscriptionInserveName' => false,
'subscriptionInserveStatus' => 0, 'subscriptionInserveStatus' => 0,
'md5' => md5($serverUuid . ':' . $key), 'md5' => md5($serverUuid . ':' . $key),
@@ -338,11 +338,6 @@ class API_inserve extends API
public function syncServerLicencesToInserve() public function syncServerLicencesToInserve()
{ {
# Get all the linked companies
$this->getLinkedCompanies();
$allCompanies = json_decode($this->response, true);
$allCompaniesIds = array_column($allCompanies['matched'], 'id', 'company_id');
# first get the current subscriptions # first get the current subscriptions
$this->getCloudSubscriptions(); $this->getCloudSubscriptions();
$allInserveCloudSubscriptions = json_decode($this->response, true); $allInserveCloudSubscriptions = json_decode($this->response, true);
@@ -361,7 +356,7 @@ class API_inserve extends API
'id' => (int)$subscription['id'], 'id' => (int)$subscription['id'],
'quantity' => (int)$subscription['quantity'], 'quantity' => (int)$subscription['quantity'],
'status' => (int)$subscription['status'], 'status' => (int)$subscription['status'],
'cloud_distribution_company_id' => (int)$subscription['cloud_distribution_company_id'], 'company_name' => $subscription['company_name'],
'name' => $subscription['name'], 'name' => $subscription['name'],
]; ];
} }
@@ -421,19 +416,18 @@ class API_inserve extends API
if (isset($inserveLookup[$md5])) { # Subscription already exists in Inserve if (isset($inserveLookup[$md5])) { # Subscription already exists in Inserve
$item['SentriStatus'] = $sentriStatus; $item['SentriStatus'] = $sentriStatus;
$item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0;
$item['subscriptionInserveExists'] = true; $item['subscriptionInserveExists'] = true;
$item['subscriptionInserveId'] = $inserveLookup[$item['md5']]['id']; $item['subscriptionInserveId'] = $inserveLookup[$item['md5']]['id'];
$item['countInserve'] = $inserveLookup[$item['md5']]['quantity']; $item['countInserve'] = $inserveLookup[$item['md5']]['quantity'];
$item['subscriptionInserveCompanyId'] = $inserveLookup[$item['md5']]['cloud_distribution_company_id']; $item['subscriptionSentriCompanyName'] = $row['company_name'];
$item['subscriptionInserveCompanyName'] = $inserveLookup[$item['md5']]['company_name'];
$item['subscriptionInserveName'] = $inserveLookup[$item['md5']]['name']; $item['subscriptionInserveName'] = $inserveLookup[$item['md5']]['name'];
//$item['subscriptionInserveStatus'] = $inserveLookup[$item['md5']]['status']; $item['subscriptionInserveStatus'] = $inserveLookup[$item['md5']]['status'];
} else { # Subscription does not exist in Inserve } else { # Subscription does not exist in Inserve
$item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0; $item['subscriptionSentriCompanyName'] = $row['company_name'];
$item['subscriptionInserveExists'] = false; $item['subscriptionInserveExists'] = false;
$item['subscriptionInserveId'] = false; $item['subscriptionInserveId'] = false;
$item['countInserve'] = 0; $item['countInserve'] = 0;
$item['subscriptionInserveCompanyId'] = false;
} }
} }
unset($item); unset($item);
@@ -487,9 +481,9 @@ class API_inserve extends API
"cloud_distribution_id" => $item['md5'], #md5 hash based on the server_uuid from sentri and the subscription name (e.g. server_cpu_count) "cloud_distribution_id" => $item['md5'], #md5 hash based on the server_uuid from sentri and the subscription name (e.g. server_cpu_count)
"cloud_subscription_id" => "sentri-servers", # Mark all the sentri-servers subscriptions so we can filter the subscriptions better "cloud_subscription_id" => "sentri-servers", # Mark all the sentri-servers subscriptions so we can filter the subscriptions better
"name" => $item['subscriptionSentriName'], "name" => $item['subscriptionSentriName'],
"company_name" => $item['subscriptionSentriCompanyName'],
"quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'], "quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'],
"cloud_distributor" => $this->cloudDistributor, "cloud_distributor" => $this->cloudDistributor,
"cloud_distribution_company_id" => $item['sentriCompanyId'], # this is generated by inserve
"status" => $item['SentriStatus'], "status" => $item['SentriStatus'],
"period_type" => 0, # 0 = monthly, 1 = annual, 2 = one time cost "period_type" => 0, # 0 = monthly, 1 = annual, 2 = one time cost
"start_date" => date('Y-m-d') "start_date" => date('Y-m-d')
@@ -500,26 +494,55 @@ class API_inserve extends API
continue; continue;
} }
// update the subscription if the countInserve and countSentri don't match $countMismatch =
// Or when sentriCompanyId and subscriptionInserveCompanyId don't match (int)$item['subscriptionInserveStatus'] !== 5 && // Do not update the cound when license status is 5 (removed) in Inserve
if (( (int)$item['countInserve'] !== (int)$item['countSentri'];
(int)$item['countInserve'] !== (int)$item['countSentri'] || $statusMismatch = (int)$item['SentriStatus'] !== (int)$item['subscriptionInserveStatus'];
(int)$item['sentriCompanyId'] !== (int)$item['subscriptionInserveCompanyId'] || $nameMismatch = $item['subscriptionSentriName'] !== $item['subscriptionInserveName'];
(int)$item['SentriStatus'] !== (int)$item['subscriptionInserveStatus'] || $companyMismatch = $item['subscriptionSentriCompanyName'] !== $item['subscriptionInserveCompanyName'];
$item['subscriptionSentriName'] !== $item['subscriptionInserveName'] $subscriptionExists = $item['subscriptionInserveExists'] !== false;
)
&& $item['subscriptionInserveExists'] !== false if (
($countMismatch ||
$statusMismatch ||
$nameMismatch ||
$companyMismatch)
&& $subscriptionExists
) { ) {
$output = false;
if ($output) {
echo "<h3>Update triggered because:</h3>";
if ($countMismatch) {
echo "Count differs: Inserve={$item['countInserve']} Sentri={$item['countSentri']}<br>";
}
if ($statusMismatch) {
echo "Status differs: Inserve={$item['subscriptionInserveStatus']} Sentri={$item['SentriStatus']}<br>";
}
if ($nameMismatch) {
echo "Name differs: Inserve='{$item['subscriptionInserveName']}' Sentri='{$item['subscriptionSentriName']}'<br>";
}
if ($companyMismatch) {
echo "Company differs: Inserve='{$item['subscriptionInserveCompanyName']}' Sentri='{$item['subscriptionSentriCompanyName']}'<br>";
}
if (!$subscriptionExists) {
echo "Subscription does not exist.<br>";
}
}
$payload = [ $payload = [
"quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'], "quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'],
"cloud_distributor" => $this->cloudDistributor, "cloud_distributor" => $this->cloudDistributor,
"cloud_distribution_company_id" => (int)$item['sentriCompanyId'], "company_name" => $item['subscriptionSentriCompanyName'],
"name" => $item['subscriptionSentriName'], "name" => $item['subscriptionSentriName'],
"status" => $item['SentriStatus'] "status" => $item['SentriStatus']
]; ];
$this->updateCloudSubscription($item['subscriptionInserveId'], $payload); $this->updateCloudSubscription($item['subscriptionInserveId'], $payload);
} }
} }
} }

View File

@@ -59,20 +59,21 @@ class API_servers extends API
{ {
# if the server_state that is posted is 'deleted' check if the current server state is 'new' if so, delete it perm. # if the server_state that is posted is 'deleted' check if the current server state is 'new' if so, delete it perm.
if ($this->data['server_state'] == 'deleted') { if (isset($this->data['server_state'])) {
$stmt = $GLOBALS['pdo']->prepare("SELECT server_state FROM servers WHERE server_vm_id = ? AND server_state = 'new'"); if ($this->data['server_state'] == 'deleted') {
$stmt->execute([$this->data['server_vm_id']]); $stmt = $GLOBALS['pdo']->prepare("SELECT server_state FROM servers WHERE server_vm_id = ? AND server_state = 'new'");
$stmt->execute([$this->data['server_vm_id']]);
if ($stmt->fetch()) { if ($stmt->fetch()) {
$deleteStmt = $GLOBALS['pdo']->prepare("DELETE FROM servers WHERE server_vm_id = ? AND server_state = 'new'"); $deleteStmt = $GLOBALS['pdo']->prepare("DELETE FROM servers WHERE server_vm_id = ? AND server_state = 'new'");
$deleteStmt->execute([$this->data['server_vm_id']]); $deleteStmt->execute([$this->data['server_vm_id']]);
return; return;
}
} }
} if (isset($this->data['company_uuid'])) {
if (strlen($this->data['company_uuid']) == 0) {
if (isset($this->data['company_uuid'])) { $this->data['company_uuid'] = NULL;
if (strlen($this->data['company_uuid']) == 0) { }
$this->data['company_uuid'] = NULL;
} }
} }

View File

@@ -17,7 +17,17 @@ if (!$GLOBALS['modules_enabled']['office']) {
if ($API_office_travel_reimburse->request_method === 'GET') { if ($API_office_travel_reimburse->request_method === 'GET') {
$API_office_travel_reimburse->checkPermissions('office-travel-reimburse', 'RO'); $API_office_travel_reimburse->checkPermissions('office-travel-reimburse', 'RO');
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $_SESSION['user']['user_uuid']]]]; if (!isset($_GET['builder']) || !is_array($_GET['builder'])) {
$_GET['builder'] = [];
}
# Append user_uuid where builder to always search for the user_uuid that is requesting the travel entries
$_GET['builder'][] = [
'where' => [
0 => 'user_uuid',
1 => $_SESSION['user']['user_uuid']
]
];
$travel_reimbursements = $API_office_travel_reimburse->getTravelReimburse(); $travel_reimbursements = $API_office_travel_reimburse->getTravelReimburse();
$API_office_travel_reimburse->apiOutput($code = 200, $travel_reimbursements); $API_office_travel_reimburse->apiOutput($code = 200, $travel_reimbursements);

View File

@@ -20,8 +20,6 @@ if (!$GLOBALS['modules_enabled']['office']) {
} }
if ($API_office_travel_reimburse->request_method === 'POST') { if ($API_office_travel_reimburse->request_method === 'POST') {
ini_set('display_errors', 1);
$API_office_travel_reimburse->checkPermissions('office-travel-reimburse', 'RO'); $API_office_travel_reimburse->checkPermissions('office-travel-reimburse', 'RO');
$portal_settings = $GLOBALS['conn']->query("SELECT * FROM system_settings")->fetch_assoc(); $portal_settings = $GLOBALS['conn']->query("SELECT * FROM system_settings")->fetch_assoc();
$month = $_POST['calender_month']; $month = $_POST['calender_month'];
@@ -38,6 +36,10 @@ if ($API_office_travel_reimburse->request_method === 'POST') {
0 => 'travel_date', 0 => 'travel_date',
1 => $firstDay, 1 => $firstDay,
2 => $lastDay 2 => $lastDay
],
'orderBy' => [
0 => 'travel_date',
1 => 'ASC'
] ]
] ]
]; ];
@@ -199,7 +201,7 @@ if ($API_office_travel_reimburse->request_method === 'POST') {
$mail->mailText = 'Your travel reimbursement is attached.'; $mail->mailText = 'Your travel reimbursement is attached.';
try { try {
$mail->addAttachment($pdfFile, 'travel_reimbursement.pdf'); $mail->addAttachment($pdfFile, 'Travel reimbursement ' . $_SESSION['user']['user_full_name'] . ' - ' . $invoiceNumber . '.pdf');
} catch (\PHPMailer\PHPMailer\Exception $e) { } catch (\PHPMailer\PHPMailer\Exception $e) {
} }

View File

@@ -1,22 +0,0 @@
<?php
use api\classes\API_inserve;
session_start();
require_once "{$_SERVER['DOCUMENT_ROOT']}/api/classes/API_inserve.php";
$API_inserve = new API_inserve();
if ($API_inserve->request_method === 'GET' || $API_inserve->request_method === 'POST') {
# This syncs the company id's from Sentri to the Inserve cloudDistributor
# These are the same id's but it Inserve requires it to be synced to the cloudDistributor
$API_inserve->checkPermissions('servers', 'RW');
$API_inserve->setupConnection();
$API_inserve->syncCompaniesFromSentri();
$API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']);
}

View File

@@ -13,7 +13,6 @@ if ($API_inserve->request_method === 'GET' || $API_inserve->request_method === '
$API_inserve->checkPermissions('servers', 'RW'); $API_inserve->checkPermissions('servers', 'RW');
$API_inserve->setupConnection(); $API_inserve->setupConnection();
$API_inserve->syncCompaniesFromSentri();
$API_inserve->syncServerLicencesToInserve(); $API_inserve->syncServerLicencesToInserve();
$API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']); $API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']);

View File

@@ -13,7 +13,6 @@ if ($API_inserve->request_method === 'GET' || $API_inserve->request_method === '
$API_inserve->checkPermissions('servers', 'RW'); $API_inserve->checkPermissions('servers', 'RW');
$API_inserve->setupConnection(); $API_inserve->setupConnection();
$API_inserve->syncCompaniesFromSentri();
$API_inserve->syncServerSubscriptionsToInserve(); $API_inserve->syncServerSubscriptionsToInserve();
$API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']); $API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']);

View File

@@ -300,8 +300,6 @@ return [
'source_custom_data' => "Custom source data", 'source_custom_data' => "Custom source data",
'settings' => 'settings', 'settings' => 'settings',
'source_description' => 'Enter the necessary API details to set up and configure your connection to the Inserve API. This allows Sentri to communicate with Inserve and retrieve the data it needs. ', 'source_description' => 'Enter the necessary API details to set up and configure your connection to the Inserve API. This allows Sentri to communicate with Inserve and retrieve the data it needs. ',
'source_inserve_sync_cloud' => 'Sync cloud distributor companies',
'source_inserve_sync_cloud_desc' => 'This API call synchronizes active companies in Sentri with the corresponding cloud distributor companies in Inserve. These cloud distributor companies are required to associate Sentri server licenses with companies in Inserve.',
'source_inserve_sync_companies' => 'Sync companies from Inserve to Sentri', 'source_inserve_sync_companies' => 'Sync companies from Inserve to Sentri',
'source_inserve_sync_companies_desc' => 'This API call retrieves all companies from Inserve and creates or updates them in Sentri.', 'source_inserve_sync_companies_desc' => 'This API call retrieves all companies from Inserve and creates or updates them in Sentri.',
'source_inserve_sync_licenses' => 'Sync servers licenses', 'source_inserve_sync_licenses' => 'Sync servers licenses',

View File

@@ -300,8 +300,6 @@ return [
'source_custom_data' => "Custom bron data", 'source_custom_data' => "Custom bron data",
'settings' => 'insetellingen', 'settings' => 'insetellingen',
'source_description' => 'Voer de benodigde API-gegevens in om uw verbinding met de Inserve API in te stellen en te configureren. Dit stelt Sentri in staat om te communiceren met Inserve en de benodigde gegevens op te halen.', 'source_description' => 'Voer de benodigde API-gegevens in om uw verbinding met de Inserve API in te stellen en te configureren. Dit stelt Sentri in staat om te communiceren met Inserve en de benodigde gegevens op te halen.',
'source_inserve_sync_cloud' => 'Synchroniseer cloud-distributeurbedrijven',
'source_inserve_sync_cloud_desc' => 'Deze API-call synchroniseert actieve bedrijven in Sentri met de bijbehorende cloud-distributeurbedrijven in Inserve. Deze cloud-distributeurbedrijven zijn nodig om Sentri-serverlicenties te koppelen aan bedrijven in Inserve.',
'source_inserve_sync_companies' => 'Synchroniseer bedrijven van Inserve naar Sentri.', 'source_inserve_sync_companies' => 'Synchroniseer bedrijven van Inserve naar Sentri.',
'source_inserve_sync_companies_desc' => 'Deze API-call haalt alle bedrijven op uit Inserve en maakt ze aan of werkt ze bij in Sentri.', 'source_inserve_sync_companies_desc' => 'Deze API-call haalt alle bedrijven op uit Inserve en maakt ze aan of werkt ze bij in Sentri.',
'source_inserve_sync_licenses' => 'Synchroniseer serverlicenties.', 'source_inserve_sync_licenses' => 'Synchroniseer serverlicenties.',

View File

@@ -2,7 +2,7 @@
<div class="card-body py-0 border"> <div class="card-body py-0 border">
<h5> <h5>
Sentri<br> Made by: Sentri<br> Made by:
<a class="text-decoration-none" href="https://marcomooij.net" target="_blank">Marco Mooij</a><br> Version 1.3.0 <a class="text-decoration-none" href="https://marcomooij.net" target="_blank">Marco Mooij</a><br> Version 1.3.1
</h5> </h5>
</div> </div>
</div> </div>

View File

@@ -87,7 +87,7 @@ while ($module = $system_modules_data->fetch_assoc()) {
<div class="card"> <div class="card">
<form id="FormValidation" method="post" action="/api/v1/portal-management/configure/"> <form id="FormValidation" method="post" action="/api/v1/portal-management/configure/">
<input type="hidden" name="X-HTTP-Method-Override" value="PUT"> <input type="hidden" name="X-HTTP-Method-Override" value="PUT">
<input type="hidden" name="_return" value="/systemconfig/#global-settings"> <input type="hidden" name="_return" value="/portal-management/#global-settings">
<input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>"> <input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>">
<div class="card-body"> <div class="card-body">
<div class="form-group form-show-validation row"> <div class="form-group form-show-validation row">
@@ -176,7 +176,7 @@ while ($module = $system_modules_data->fetch_assoc()) {
<form id="FormValidation" method="post" action="/api/v1/portal-management/mail/configure/"> <form id="FormValidation" method="post" action="/api/v1/portal-management/mail/configure/">
<input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>"> <input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>">
<input type="hidden" name="X-HTTP-Method-Override" value="PUT"> <input type="hidden" name="X-HTTP-Method-Override" value="PUT">
<input type="hidden" name="_return" value="/systemconfig/#mail-settings"> <input type="hidden" name="_return" value="/portal-management/#mail-settings">
<div class="card-body"> <div class="card-body">
<div class="form-group form-show-validation row"> <div class="form-group form-show-validation row">
<label for="mail_from_name" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2"><?php echo __('mail_from_name') ?></label> <label for="mail_from_name" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2"><?php echo __('mail_from_name') ?></label>
@@ -276,7 +276,7 @@ while ($module = $system_modules_data->fetch_assoc()) {
<form id="FormValidation" method="post" action="/api/v1/portal-management/mail/test/"> <form id="FormValidation" method="post" action="/api/v1/portal-management/mail/test/">
<input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>"> <input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>">
<input type="hidden" name="X-HTTP-Method-Override" value="POST"> <input type="hidden" name="X-HTTP-Method-Override" value="POST">
<input type="hidden" name="_return" value="/systemconfig/#mail-settings"> <input type="hidden" name="_return" value="/portal-management/#mail-settings">
<div class="form-group form-show-validation row"> <div class="form-group form-show-validation row">
<label for="mail_to" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2"><?php echo __('mail_to') ?>:</label> <label for="mail_to" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2"><?php echo __('mail_to') ?>:</label>
<div class="col-lg-9 col-md-12 col-sm-10"> <div class="col-lg-9 col-md-12 col-sm-10">
@@ -313,7 +313,7 @@ while ($module = $system_modules_data->fetch_assoc()) {
<form id="FormValidation" method="post" action="/api/v1/modules/"> <form id="FormValidation" method="post" action="/api/v1/modules/">
<input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>"> <input type="hidden" name="portal_uuid" value="<?php echo $portal_settings['portal_uuid']; ?>">
<input type="hidden" name="X-HTTP-Method-Override" value="PUT"> <input type="hidden" name="X-HTTP-Method-Override" value="PUT">
<input type="hidden" name="_return" value="/systemconfig/#modules"> <input type="hidden" name="_return" value="/portal-management/#modules">
<table class="multi-filter-select display table table-striped table-hover" data-skip-columns="0,5"> <table class="multi-filter-select display table table-striped table-hover" data-skip-columns="0,5">
<thead> <thead>
<tr> <tr>

View File

@@ -129,25 +129,6 @@ $pageNavbar->outPutNavbar();
</div> </div>
<?php } ?> <?php } ?>
<?php if ($GLOBALS['modules_enabled']['servers'] && $API->checkPermissions('servers', 'RW', true)) { ?>
<div class="col d-flex">
<form method="post" action="/api/v1/sources/inserve/sync-cloud-distributor/" class="w-100">
<div class="card h-100 w-100">
<div class="card-body">
<h5 class="card-title"><?php echo __('source_inserve_sync_cloud') ?></h5>
<input type="hidden" name="_return" value="/portal-management/sources/inserve">
<p class="card-text"><?php echo __('source_inserve_sync_cloud_desc') ?></p>
</div>
<div class="card-footer mt-auto">
<button class="btn btn-primary">
<i class="fa-solid fa-arrow-rotate-right"></i> &nbsp;<?php echo __('sync') ?>
</button>
</div>
</div>
</form>
</div>
<?php } ?>
<?php if ($GLOBALS['modules_enabled']['servers'] && $API->checkPermissions('servers', 'RW', true)) { ?> <?php if ($GLOBALS['modules_enabled']['servers'] && $API->checkPermissions('servers', 'RW', true)) { ?>
<div class="col d-flex"> <div class="col d-flex">
<form method="post" action="/api/v1/sources/inserve/sync-server-licenses/" class="w-100"> <form method="post" action="/api/v1/sources/inserve/sync-server-licenses/" class="w-100">

View File

@@ -309,7 +309,7 @@ class pageBuilder
</nav> </nav>
<div class="copyright"> <div class="copyright">
<?php echo __('version') ?> <?php echo __('version') ?>
<a class="text-primary" href="/changelog/">1.3.0</a> <a class="text-primary" href="/changelog/">1.3.1</a>
</div> </div>
<div> <div>
<span class="navbar-text">Sentri</span> <span class="navbar-text">Sentri</span>

View File

@@ -1083,3 +1083,11 @@
rotate: 180deg rotate: 180deg
} }
.fc .fc-daygrid-day-frame {
padding: 2px;
}
.fc .fc-daygrid-day-number {
padding: 2px;
font-size: 0.85rem;
}

View File

@@ -97,6 +97,9 @@ document.addEventListener('DOMContentLoaded', async function () {
}) })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
if (!Array.isArray(data)) {
data = [];
}
let totalDistanceHomework = 0; let totalDistanceHomework = 0;
let totalDistanceBusiness = 0; let totalDistanceBusiness = 0;